|
|
1.1 ! root 1: /* (lgl- ! 2: * The information contained herein is a trade secret of Mark Williams ! 3: * Company, and is confidential information. It is provided under a ! 4: * license agreement, and may be copied or disclosed only under the ! 5: * terms of that agreement. Any reproduction or disclosure of this ! 6: * material without the express written authorization of Mark Williams ! 7: * Company or persuant to the license agreement is unlawful. ! 8: * ! 9: * COHERENT Version 5.0 ! 10: * Copyright (c) 1982, 1993. ! 11: * An unpublished work by Mark Williams Company, Chicago. ! 12: * All rights reserved. ! 13: -lgl) */ ! 14: /* ! 15: * File: coh.386/sig.c ! 16: * ! 17: * Purpose: signal handling ! 18: * ! 19: * Revised: Tue May 4 11:59:15 1993 CDT ! 20: */ ! 21: ! 22: /* ! 23: * ---------------------------------------------------------------------- ! 24: * Includes. ! 25: */ ! 26: #include <sys/coherent.h> ! 27: #include <errno.h> ! 28: #include <sys/ino.h> ! 29: #include <sys/inode.h> ! 30: #include <sys/io.h> ! 31: #include <sys/proc.h> ! 32: #include <sys/ptrace.h> ! 33: #include <sys/sched.h> ! 34: #include <sys/seg.h> ! 35: #include <signal.h> ! 36: #include <sys/core.h> ! 37: ! 38: /* ! 39: * ---------------------------------------------------------------------- ! 40: * Definitions. ! 41: * Constants. ! 42: * Macros with argument lists. ! 43: * Typedefs. ! 44: * Enums. ! 45: */ ! 46: typedef void (*VFPTR)(); /* pointer to void function */ ! 47: ! 48: /* ! 49: * ---------------------------------------------------------------------- ! 50: * Functions. ! 51: * Import Functions. ! 52: * Export Functions. ! 53: * Local Functions. ! 54: */ ! 55: int actvsig(); ! 56: int nondsig(); ! 57: int ptret(); ! 58: int ptset(); ! 59: void sendsig(); ! 60: void sigDefault(); ! 61: void sigHold(); ! 62: void sigIgnore(); ! 63: void sigPause(); ! 64: void sigRelease(); ! 65: int sigSet(); ! 66: int sigdump(); ! 67: int usigsys(); ! 68: ! 69: static struct _fpstate * empack(); ! 70: ! 71: /* ! 72: * ---------------------------------------------------------------------- ! 73: * Global Data. ! 74: * Import Variables. ! 75: * Export Variables. ! 76: * Local Variables. ! 77: */ ! 78: /* ! 79: * Patchable variables. ! 80: * ! 81: * Patch DUMP_TEXT nonzero to make text segment show up in core files. ! 82: * Patch DUMP_LIM set the upper limit in bytes of how much of a ! 83: * segment is written to a core file. ! 84: * ! 85: * Patch CATCH_SEGV nonzero if you are trying to run software that was ! 86: * written in blatant defiance of the SVID 2 caution that handling SIGSEGV ! 87: * is nonportable and should not be assumed valid on all systems. ! 88: */ ! 89: int DUMP_TEXT = 0; ! 90: int DUMP_LIM=512*1024; ! 91: int CATCH_SEGV = 0; ! 92: ! 93: /* ! 94: * ---------------------------------------------------------------------- ! 95: * Code. ! 96: */ ! 97: ! 98: /* ! 99: * Given 1-based signal number, ask whether a signal handler was ! 100: * attached to the current process using sigset(). This allows ! 101: * the kernel to process sigset() differently from signal(), as ! 102: * required. ! 103: * ! 104: * return 1 if sigset(), 0 if not. ! 105: */ ! 106: int ! 107: sigSet(signal) ! 108: int signal; ! 109: { ! 110: return (SELF->p_dsig & SIG_BIT(signal)) ? 1 : 0; ! 111: } ! 112: ! 113: /* ! 114: * Given 1-based signal number, ignore that signal in the current process. ! 115: */ ! 116: void ! 117: sigIgnore(signal) ! 118: int signal; ! 119: { ! 120: int sigbit = SIG_BIT(signal); ! 121: ! 122: SELF->p_dfsig &= ~sigbit; /* No longer defaulted. */ ! 123: SELF->p_isig |= sigbit; /* Mark signal as ignored. */ ! 124: u.u_sfunc[signal - 1] = SIG_IGN; ! 125: } ! 126: ! 127: /* ! 128: * Given 1-based signal number, restore default handling for the current ! 129: * process. ! 130: * ! 131: * There is some duplication of work done in sigAttach(), but sigDefault() ! 132: * is also called from msig.c ! 133: */ ! 134: void ! 135: sigDefault(signal) ! 136: int signal; ! 137: { ! 138: int sigbit = SIG_BIT(signal); ! 139: ! 140: SELF->p_dfsig |= sigbit; ! 141: SELF->p_isig &= ~sigbit; ! 142: u.u_sfunc[signal - 1] = SIG_DFL; ! 143: } ! 144: ! 145: /* ! 146: * Given 1-based signal number, hold that signal for the current process. ! 147: */ ! 148: void ! 149: sigHold(signal) ! 150: int signal; ! 151: { ! 152: SELF->p_hsig |= SIG_BIT(signal); ! 153: } ! 154: ! 155: /* ! 156: * Given 1-based signal number, pause for that signal for the current process. ! 157: */ ! 158: void ! 159: sigPause(signal) ! 160: int signal; ! 161: { ! 162: SELF->p_hsig &= ~SIG_BIT(signal); ! 163: ! 164: /* ! 165: * Like upause(), do a sleep on an event which never gets a wakeup. ! 166: * The sleep returns immediately if a signal was already holding. ! 167: */ ! 168: x_sleep((char *)&u, prilo, slpriSigCatch, "sigpause"); ! 169: actvsig(); ! 170: } ! 171: ! 172: /* ! 173: * Given 1-based signal number, release that signal for the current process. ! 174: */ ! 175: void ! 176: sigRelease(signal) ! 177: int signal; ! 178: { ! 179: SELF->p_hsig &= ~SIG_BIT(signal); ! 180: if (nondsig()) { ! 181: actvsig(); ! 182: } ! 183: } ! 184: ! 185: /* ! 186: * Given 1-based signal number, a pointer to a signal-handling function, ! 187: * and a flag, attach the signal handler to the current process. ! 188: * ! 189: * Function pointer "func" may take on special values SIG_DFL, SIG_IGN, ! 190: * and, if "how" is SIGSET, SIG_HOLD. ! 191: * ! 192: * The flag "how" is 0 if attachment is via signal(), SIGSET if attachment ! 193: * is via sigset(). ! 194: * ! 195: * Return the previously attached signal handler, or SIG_HOLD if signals ! 196: * were previously held. ! 197: */ ! 198: VFPTR ! 199: sigAttach(signal, func, how) ! 200: int signal; ! 201: VFPTR func; ! 202: int how; ! 203: { ! 204: VFPTR retval; ! 205: int sigbit = SIG_BIT(signal); ! 206: ! 207: /* ! 208: * Set up the return value, which says what was previously ! 209: * done with the given signal. ! 210: */ ! 211: if (SELF->p_isig & sigbit) ! 212: retval = (VFPTR)SIG_IGN; ! 213: else if (SELF->p_hsig & sigbit) ! 214: retval = (VFPTR)SIG_HOLD; ! 215: else ! 216: retval = u.u_sfunc[signal - 1]; ! 217: ! 218: u.u_sigreturn = (VFPTR)(u.u_regl[EDX]); ! 219: u.u_sfunc[signal - 1] = func; ! 220: ! 221: /* ! 222: * Remove previous default, ignore, or hold status. ! 223: */ ! 224: SELF->p_dfsig &= ~sigbit; ! 225: SELF->p_isig &= ~sigbit; ! 226: SELF->p_hsig &= ~sigbit; ! 227: ! 228: /* ! 229: * Any pending signal is lost. ! 230: */ ! 231: SELF->p_ssig &= ~sigbit; ! 232: ! 233: /* ! 234: * Special cases for handler. ! 235: */ ! 236: switch ((int)func) { ! 237: case (int)SIG_DFL: ! 238: sigDefault(signal); ! 239: break; ! 240: case (int)SIG_IGN: ! 241: sigIgnore(signal); ! 242: break; ! 243: case (int)SIG_HOLD: ! 244: sigHold(signal); ! 245: break; ! 246: } ! 247: ! 248: /* ! 249: * Remember whether handler was attached with sigset() vs signal(). ! 250: */ ! 251: if (how == SIGSET) ! 252: SELF->p_dsig |= sigbit; ! 253: else ! 254: SELF->p_dsig &= ~sigbit; ! 255: ! 256: return retval; ! 257: } ! 258: ! 259: /* ! 260: * Set up the action to be taken on a signal. ! 261: */ ! 262: int ! 263: usigsys(signal, func) ! 264: int signal; ! 265: VFPTR func; ! 266: { ! 267: int sigtype; ! 268: int retval = 0; ! 269: ! 270: sigtype = signal & ~0xFF; ! 271: signal &= 0xFF; ! 272: ! 273: T_HAL(8, if (signal == SIGINT) ! 274: printf("[%d]sigint(%x, %x) ", SELF->p_pid, sigtype, func)); ! 275: ! 276: /* Range check on 1-based signal number. */ ! 277: if (signal <= 0 || signal > NSIG) { ! 278: u.u_error = EINVAL; ! 279: return; ! 280: } ! 281: ! 282: /* ! 283: * Don't allow setting/holding/releasing some signals. ! 284: * ! 285: * NOTICE: Ignoring SIGSEGV causes runaway user faults. ! 286: * SVID Issue 2 says *don't* do signal(SIGSEGV,...)!!! ! 287: */ ! 288: if (signal == SIGKILL) { ! 289: u.u_error = EINVAL; ! 290: return; ! 291: } ! 292: ! 293: if (signal == SIGSEGV && CATCH_SEGV == 0) { ! 294: u.u_error = EINVAL; ! 295: return; ! 296: } ! 297: ! 298: switch (sigtype) { ! 299: case SIGHOLD: ! 300: sigHold(signal); ! 301: break; ! 302: case SIGRELSE: ! 303: sigRelease(signal); ! 304: break; ! 305: case SIGIGNORE: ! 306: sigIgnore(signal); ! 307: break; ! 308: case 0: /* old system entry */ ! 309: retval = (int)sigAttach(signal, func, 0); ! 310: break; ! 311: case SIGSET: /* new system entry */ ! 312: retval = (int)sigAttach(signal, func, SIGSET); ! 313: break; ! 314: case SIGPAUSE: ! 315: sigPause(signal); ! 316: break; ! 317: default: ! 318: u.u_error = SIGSYS; ! 319: break; ! 320: } ! 321: return retval; ! 322: } ! 323: ! 324: /* ! 325: * Send a signal to the process `pp'. ! 326: * Return 1 if signal was sent. ! 327: * Return 0 if signal was ignored. ! 328: * The return value is of use to the trap handler. ! 329: */ ! 330: void ! 331: sendsig(sig, pp) ! 332: register unsigned sig; ! 333: register PROC *pp; ! 334: { ! 335: register sig_t f; ! 336: register int s; ! 337: ! 338: T_HAL(8, if (sig == SIGINT) printf("[%d]gets int ", pp->p_pid)); ! 339: ! 340: /* ! 341: * Convert the signal to a bit position. ! 342: */ ! 343: f = SIG_BIT(sig); ! 344: ! 345: /* ! 346: * If the signal is ignored, and is not SIGCLD, do nothing. ! 347: */ ! 348: if ((pp->p_isig & f) && sig != SIGCLD) { ! 349: goto sendSigDone; ! 350: } ! 351: ! 352: /* ! 353: * No further processing for delayed or held signals. ! 354: */ ! 355: if ((pp->p_ssig & f) && (pp->p_hsig|pp->p_dsig) & f) ! 356: goto sendSigDone; ! 357: ! 358: /* ! 359: * Actually send the signal by flagging the needed bit. ! 360: */ ! 361: pp->p_ssig |= f; ! 362: ! 363: /* ! 364: * If the process is sleeping, wake it up so that ! 365: * it can process this signal. ! 366: */ ! 367: if (pp->p_state == PSSLSIG) { ! 368: s = sphi(); ! 369: pp->p_lback->p_lforw = pp->p_lforw; ! 370: pp->p_lforw->p_lback = pp->p_lback; ! 371: #ifndef _I386 ! 372: addu(pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK); ! 373: #endif ! 374: setrun(pp); ! 375: spl(s); ! 376: } ! 377: sendSigDone: ! 378: return; ! 379: } ! 380: ! 381: /* ! 382: * Return signal number if we have a non ignored or delayed signal, else zero. ! 383: */ ! 384: int ! 385: nondsig() ! 386: { ! 387: register PROC *pp; ! 388: register sig_t mask; ! 389: register int signo; ! 390: ! 391: pp = SELF; ! 392: signo = 0; ! 393: ! 394: /* ! 395: * Turn off all ignored signals except SIGCLD. ! 396: */ ! 397: pp->p_ssig &= ~(pp->p_isig & ~SIG_BIT(SIGCLD)); ! 398: ! 399: /* ! 400: * If any signals have arrived, but which are not held, ! 401: * figure out what they are. ! 402: */ ! 403: if (pp->p_ssig&~pp->p_hsig) { ! 404: /* ! 405: * There is at least one signal. Extract its number ! 406: * from the signal bits. ! 407: */ ! 408: mask = (sig_t) 1; ! 409: signo += 1; ! 410: while (((pp->p_ssig&~pp->p_hsig) & mask) == 0) { ! 411: mask <<= 1; ! 412: signo += 1; ! 413: } ! 414: } ! 415: return signo; ! 416: } ! 417: ! 418: /* ! 419: * If we have a signal that isn't ignored, activate it. ! 420: */ ! 421: int ! 422: actvsig() ! 423: { ! 424: register int signum; ! 425: register PROC *pp; ! 426: register int (*func)(); ! 427: int ptval; ! 428: ! 429: /* ! 430: * Fetch an unprocessed signal. ! 431: * Return if there are none. ! 432: * The while() structure is only for traced processes. ! 433: */ ! 434: while (signum = nondsig()) { ! 435: ! 436: pp = SELF; ! 437: ! 438: /* ! 439: * Reset the signal to indicate that it has been processed. ! 440: * Bit table p_ssig uses 0-based signals, while signal.h ! 441: * lists 1-based signals. ! 442: */ ! 443: pp->p_ssig &= ~SIG_BIT(signum); ! 444: ! 445: /* ! 446: * Fetch the user function that goes with this signal. ! 447: * Function table u_sfunc uses 0-based signals, while signal.h ! 448: * lists 1-based signals. ! 449: */ ! 450: func = u.u_sfunc[signum-1]; ! 451: ! 452: /* ! 453: * SIGCLD causes no work here if defaulted or ignored. ! 454: */ ! 455: if (signum == SIGCLD && (func == SIG_DFL || func == SIG_IGN)) ! 456: return; ! 457: ! 458: /* ! 459: * Store the (1-based) signal number in the u area. ! 460: * This is how a core dump records the death signal. ! 461: */ ! 462: u.u_signo = signum; ! 463: ! 464: /* ! 465: * If the signal is not defaulted, go run the requested ! 466: * function. ! 467: */ ! 468: if (func != SIG_DFL) { ! 469: if (XMODE_286) ! 470: oldsigstart(signum, func); ! 471: else { ! 472: msigstart(signum, func); ! 473: } ! 474: return; ! 475: } ! 476: ! 477: /* ! 478: * ASSERTION: the signal being processed is SIG_DFL'd. ! 479: */ ! 480: ! 481: /* ! 482: * msysgen() is a nop for COHERENT 4.0. The comment in the ! 483: * assembly code is "Nothing useful to save". ! 484: */ ! 485: msysgen(u.u_sysgen); ! 486: ! 487: /* ! 488: * When a traced process is signaled, it may need to exchange ! 489: * data with its parent (via ptret). ! 490: */ ! 491: if (pp->p_flags&PFTRAC) { ! 492: pp->p_flags |= PFWAIT; ! 493: ptval = ptret(); ! 494: T_HAL(0x10000, printf("ptret()=%x ", ptval)); ! 495: pp->p_flags &= ~(PFWAIT|PFSTOP); ! 496: if (ptval == 0) ! 497: /* see if another signal came in */ ! 498: continue; ! 499: else ! 500: signum = ptval; ! 501: } ! 502: ! 503: /* ! 504: * Some signals cause a core file to be written. ! 505: */ ! 506: switch(signum) { ! 507: case SIGQUIT: ! 508: case SIGILL: ! 509: case SIGTRAP: ! 510: case SIGABRT: ! 511: case SIGFPE: ! 512: case SIGSEGV: ! 513: case SIGSYS: ! 514: if (sigdump()) ! 515: signum |= 0x80; ! 516: break; ! 517: } ! 518: pexit(signum); ! 519: } ! 520: } ! 521: ! 522: /* ! 523: * Create a dump of ourselves onto the file `core'. ! 524: */ ! 525: int ! 526: sigdump() ! 527: { ! 528: register INODE *ip; ! 529: register SR *srp; ! 530: register SEG * sp; ! 531: register int n; ! 532: register paddr_t ssize; ! 533: extern int DUMP_LIM; ! 534: struct ch_info chInfo; ! 535: ! 536: if (SELF->p_flags&PFNDMP) ! 537: return (0); ! 538: u.u_io.io_seg = IOSYS; ! 539: u.u_io.io_flag = 0; ! 540: /* Make the core with the real owners */ ! 541: schizo(); ! 542: if (ftoi("core", 'c')) { ! 543: schizo(); ! 544: return (0); ! 545: } ! 546: if ((ip=u.u_cdiri) == NULL) { ! 547: if ((ip=imake(IFREG|0644, 0)) == NULL) { ! 548: schizo(); ! 549: return (0); ! 550: } ! 551: } else { ! 552: if ((ip->i_mode&IFMT)!=IFREG ! 553: || iaccess(ip, IPW)==0 ! 554: || getment(ip->i_dev, 1)==NULL) { ! 555: idetach(ip); ! 556: schizo(); ! 557: return (0); ! 558: } ! 559: iclear(ip); ! 560: } ! 561: schizo(); ! 562: u.u_error = 0; ! 563: u.u_io.io_seek = 0; ! 564: ! 565: /* Write core file header */ ! 566: chInfo.ch_magic = CORE_MAGIC; ! 567: chInfo.ch_info_len = sizeof(chInfo); ! 568: chInfo.ch_uproc_offset = U_OFFSET; ! 569: ! 570: u.u_io.io_seg = IOSYS; ! 571: u.u_io.io.vbase = &chInfo; ! 572: u.u_io.io_ioc = sizeof(chInfo); ! 573: u.u_io.io_flag = 0; ! 574: ! 575: sp->s_lrefc++; ! 576: iwrite(ip, &u.u_io); ! 577: sp->s_lrefc--; ! 578: ! 579: /* ! 580: * Added to aid in kernel debugging - if DUMP_TEXT is nonzero, ! 581: * dump the text segment (to see if it was corrupted) and set ! 582: * the dump flag so that postmortem utilities will know that ! 583: * text is present in the core file. ! 584: */ ! 585: if (DUMP_TEXT) ! 586: u.u_segl[SISTEXT].sr_flag |= SRFDUMP; ! 587: ! 588: for (srp=u.u_segl; u.u_error==0 && srp<&u.u_segl[NUSEG]; srp++) { ! 589: ! 590: if ((srp->sr_flag & SRFDUMP)==0) ! 591: continue; ! 592: ! 593: /* Don't try to dump empty segments. */ ! 594: if ((sp = srp->sr_segp)==NULL) { ! 595: srp->sr_flag &= ~SRFDUMP; ! 596: continue; ! 597: } ! 598: ! 599: /* Don't dump segments too big to dump. */ ! 600: if (sp->s_size > DUMP_LIM) ! 601: srp->sr_flag &= ~SRFDUMP; ! 602: } ! 603: ! 604: for (srp=u.u_segl; u.u_error==0 && srp<&u.u_segl[NUSEG]; srp++) { ! 605: ! 606: /* Only dump segments flagged for dumping. */ ! 607: if ((srp->sr_flag & SRFDUMP)==0) ! 608: continue; ! 609: ! 610: ssize = sp->s_size; ! 611: u.u_io.io_seg = IOPHY; ! 612: u.u_io.io.pbase = MAPIO(sp->s_vmem, 0); ! 613: u.u_io.io_flag = 0; ! 614: sp->s_lrefc++; ! 615: while (u.u_error == 0 && ssize != 0) { ! 616: n = ssize > SCHUNK ? SCHUNK : ssize; ! 617: u.u_io.io_ioc = n; ! 618: iwrite(ip, &u.u_io); ! 619: u.u_io.io.pbase += n; ! 620: ssize -= (paddr_t)n; ! 621: } ! 622: sp->s_lrefc--; ! 623: } ! 624: idetach(ip); ! 625: return (u.u_error==0); ! 626: } ! 627: ! 628: /* ! 629: * Send a ptrace command to the child. ! 630: * ! 631: * "pid" is child pid. ! 632: */ ! 633: int ! 634: ptset(req, pid, addr, data) ! 635: unsigned req; ! 636: int *addr; ! 637: { ! 638: register PROC *pp; ! 639: ! 640: lock(pnxgate); ! 641: for (pp=procq.p_nforw; pp!=&procq; pp=pp->p_nforw) ! 642: if (pp->p_pid == pid) ! 643: break; ! 644: unlock(pnxgate); ! 645: if (pp==&procq || (pp->p_flags&PFSTOP)==0 || pp->p_ppid!=SELF->p_pid){ ! 646: u.u_error = ESRCH; ! 647: return; ! 648: } ! 649: lock(pts.pt_gate); ! 650: pts.pt_req = req; ! 651: pts.pt_pid = pid; ! 652: pts.pt_addr = addr; ! 653: pts.pt_data = data; ! 654: pts.pt_errs = 0; ! 655: pts.pt_rval = 0; ! 656: pts.pt_busy = 1; ! 657: wakeup((char *)&pts.pt_req); ! 658: while (pts.pt_busy) { ! 659: x_sleep((char *)&pts.pt_busy, primed, slpriSigCatch, "ptrace"); ! 660: /* Send a ptrace command to the child. */ ! 661: } ! 662: u.u_error = pts.pt_errs; ! 663: unlock(pts.pt_gate); ! 664: return (pts.pt_rval); ! 665: } ! 666: ! 667: /* ! 668: * This routine is called when a child that is being traced receives a signal ! 669: * that is not caught or ignored. It follows up on any requests by the parent ! 670: * and returns when done. ! 671: * ! 672: * After ptrace handling done in this routine, a real or simulated signal ! 673: * may need to be sent to the traced process. ! 674: * Return a signal number to be sent to the child process, or 0 if none. ! 675: */ ! 676: int ! 677: ptret() ! 678: { ! 679: extern void (*ndpKfrstor)(); ! 680: register PROC *pp; ! 681: register PROC *pp1; ! 682: register int sign; ! 683: unsigned off; ! 684: int doEmUnpack = 0; ! 685: ! 686: struct _fpstate * fstp = empack(); ! 687: ! 688: pp = SELF; ! 689: next: ! 690: u.u_error = 0; ! 691: if (pp->p_ppid == 1) ! 692: return (SIGKILL); ! 693: sign = -1; ! 694: ! 695: /* wake up parent if it is sleeping */ ! 696: lock(pnxgate); ! 697: pp1 = &procq; ! 698: for (;;) { ! 699: if ((pp1=pp1->p_nforw) == &procq) { ! 700: sign = SIGKILL; ! 701: break; ! 702: } ! 703: if (pp1->p_pid != pp->p_ppid) ! 704: continue; ! 705: if (ASLEEP(pp1)) ! 706: wakeup((char *)pp1); ! 707: break; ! 708: } ! 709: unlock(pnxgate); ! 710: ! 711: while (sign < 0) { ! 712: /* If no pending ptrace transaction for this process, sleep. */ ! 713: if (pts.pt_busy==0 || pp->p_pid!=pts.pt_pid) { ! 714: /* If a signal bit is set now, just exit - let ! 715: * actvsig() handle it next time through. ! 716: * Doing sleep and goto next will stick us in a loop */ ! 717: if (nondsig()) ! 718: return 0; ! 719: x_sleep((char *)&pts.pt_req, ! 720: primed, slpriSigCatch, "ptret"); ! 721: goto next; ! 722: } ! 723: switch (pts.pt_req) { ! 724: case PTRACE_RD_TXT: ! 725: if (XMODE_286) { ! 726: pts.pt_rval = getuwd(NBPS+pts.pt_addr); ! 727: break; ! 728: } ! 729: /* Fall through for 386 mode processes. */ ! 730: case PTRACE_RD_DAT: ! 731: pts.pt_rval = getuwd(pts.pt_addr); ! 732: break; ! 733: case PTRACE_RD_USR: ! 734: /* See ptrace.h for valid offsets. */ ! 735: off = (unsigned)pts.pt_addr; ! 736: if (off & 3) ! 737: u.u_error = EINVAL; ! 738: else if (off < PTRACE_FP_CW) { ! 739: /* Reading CPU general register state */ ! 740: if (off == PTRACE_SIG) ! 741: pts.pt_rval = u.u_signo; ! 742: else ! 743: pts.pt_rval = u.u_regl[off>>2]; ! 744: } else if (off < PTRACE_DR0) { ! 745: /* ! 746: * Reading NDP state. ! 747: * If NDP state not already saved, save it. ! 748: * Fetch desired info. ! 749: * Restore NDP state in case we will resume. ! 750: */ ! 751: if (rdNdpUser()) { ! 752: /* if using coprocessor */ ! 753: if (!rdNdpSaved()) { ! 754: ndpSave(&u.u_ndpCon); ! 755: wrNdpSaved(1); ! 756: } ! 757: pts.pt_rval = ((int *)&u.u_ndpCon)[(off - PTRACE_FP_CW)>>2]; ! 758: ndpRestore(&u.u_ndpCon); ! 759: wrNdpSaved(0); ! 760: } else if (fstp) { ! 761: pts.pt_rval = getuwd(((int *)fstp) + ((off - PTRACE_FP_CW)>>2)); ! 762: /* if emulating */ ! 763: } else /* no ndp state to display */ ! 764: pts.pt_rval = 0; ! 765: } else ! 766: u.u_error = EINVAL; ! 767: break; ! 768: case PTRACE_WR_TXT: ! 769: if (XMODE_286) { ! 770: putuwd(NBPS+pts.pt_addr, pts.pt_data); ! 771: break; ! 772: } ! 773: /* Fall through for 386 mode processes. */ ! 774: case PTRACE_WR_DAT: ! 775: putuwd(pts.pt_addr, pts.pt_data); ! 776: break; ! 777: case PTRACE_WR_USR: ! 778: /* See ptrace.h for valid offsets. */ ! 779: off = (unsigned)pts.pt_addr; ! 780: ! 781: if (off & 3) ! 782: u.u_error = EINVAL; ! 783: else if (off < PTRACE_FP_CW) { ! 784: /* Writing CPU general register state */ ! 785: if (off == PTRACE_SIG) ! 786: u.u_error = EINVAL; ! 787: else ! 788: u.u_regl[off>>2] = pts.pt_data; ! 789: } else if (off < PTRACE_DR0) { ! 790: if (rdNdpUser()) { ! 791: /* ! 792: * Writing NDP state. ! 793: * If NDP state not already saved, save it. ! 794: * Store desired info. ! 795: * Restore NDP state in case we will resume. ! 796: */ ! 797: if (!rdNdpSaved()) { ! 798: ndpSave(&u.u_ndpCon); ! 799: wrNdpSaved(1); ! 800: } ! 801: ((int *)&u.u_ndpCon)[(off - PTRACE_FP_CW)>>2] = pts.pt_data; ! 802: ndpRestore(&u.u_ndpCon); ! 803: wrNdpSaved(0); ! 804: } else if (fstp && ndpKfrstor) { ! 805: putuwd(((int *)fstp) + ((off - PTRACE_FP_CW)>>2), pts.pt_data); ! 806: doEmUnpack = 1; ! 807: } ! 808: } else ! 809: u.u_error = EINVAL; ! 810: break; ! 811: case PTRACE_RESUME: ! 812: u.u_regl[EFL] &= ~MFTTB; ! 813: goto sig; ! 814: case PTRACE_TERM: ! 815: sign = SIGKILL; ! 816: break; ! 817: case PTRACE_SSTEP: ! 818: u.u_regl[EFL] |= MFTTB; ! 819: sig: ! 820: if (pts.pt_data<0 || pts.pt_data>NSIG) { ! 821: u.u_error = EINVAL; ! 822: break; ! 823: } ! 824: sign = pts.pt_data; ! 825: if (pts.pt_addr != SIG_IGN) { ! 826: u.u_regl[EIP] = (int)pts.pt_addr; ! 827: } ! 828: break; ! 829: default: ! 830: u.u_error = EINVAL; ! 831: } ! 832: if ((pts.pt_errs=u.u_error) == EFAULT) ! 833: pts.pt_errs = EINVAL; ! 834: pts.pt_busy = 0; ! 835: wakeup((char *)&pts.pt_busy); ! 836: } ! 837: if (doEmUnpack) ! 838: (*ndpKfrstor)(fstp, &u.u_ndpCon); ! 839: return (sign); ! 840: } ! 841: ! 842: /* ! 843: * If using floating point emulator, make room on user stack and save ! 844: * floating point context there. Code elsewhere takes care of floating ! 845: * point context if there is a coprocessor. ! 846: * ! 847: * Return the virtual address in user space of the context area, or ! 848: * return NULL if not using FP emulation. ! 849: */ ! 850: static struct _fpstate * ! 851: empack() ! 852: { ! 853: int uesp; ! 854: int sphi, splo; ! 855: SEG * segp; ! 856: cseg_t * pp; ! 857: struct _fpstate * ret = NULL; ! 858: extern void (*ndpKfsave)(); ! 859: unsigned long sw_old; ! 860: ! 861: /* If not emulating, do nothing */ ! 862: if (rdNdpUser() || !rdEmTrapped() || !ndpKfsave) ! 863: return NULL; ! 864: ! 865: /* ! 866: * Will copy at least u_sigreturn, _fpstackframe, and ndpFlags. ! 867: * If using ndp, need room for an _fpstate. ! 868: * If emulating, need room for an _fpemstate. ! 869: */ ! 870: uesp = u.u_regl[UESP] - sizeof(struct _fpstate); ! 871: ! 872: /* Add to user stack if necessary. */ ! 873: segp = u.u_segl[SISTACK].sr_segp; ! 874: sphi = (XMODE_286) ? ISP_286 : ISP_386; ! 875: splo = sphi - segp->s_size; ! 876: ! 877: if (splo > uesp) { ! 878: pp = c_extend(segp->s_vmem, btoc(segp->s_size)); ! 879: if (pp==0) { ! 880: printf("Empack failed. cmd=%s c_extend(%x,%x)=0 ", ! 881: u.u_comm, segp->s_vmem, btoc(segp->s_size)); ! 882: return NULL; ! 883: } ! 884: ! 885: segp->s_vmem = pp; ! 886: segp->s_size += NBPC; ! 887: if (sproto(0)==0) { ! 888: printf("Empack failed. cmd=%s sproto(0)=0 ", ! 889: u.u_comm); ! 890: return NULL; ! 891: } ! 892: ! 893: segload(); ! 894: } ! 895: ! 896: ret = (struct _fpstate *)uesp; ! 897: (*ndpKfsave)(&u.u_ndpCon, uesp); ! 898: sw_old = getuwd(&ret->sw); ! 899: putuwd(&ret->status, sw_old); ! 900: putuwd(&ret->sw, sw_old & 0x7f00); ! 901: ! 902: return ret; ! 903: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.