|
|
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: ! 27: #include <common/_limits.h> ! 28: #include <common/_wait.h> ! 29: #include <common/_gregset.h> ! 30: #include <kernel/sigproc.h> ! 31: ! 32: #include <sys/coherent.h> ! 33: #include <sys/errno.h> ! 34: #include <sys/ino.h> ! 35: #include <sys/inode.h> ! 36: #include <sys/io.h> ! 37: #include <sys/proc.h> ! 38: #include <sys/ptrace.h> ! 39: #include <sys/sched.h> ! 40: #include <sys/seg.h> ! 41: #include <sys/file.h> ! 42: #include <sys/core.h> ! 43: ! 44: ! 45: /* ! 46: * ---------------------------------------------------------------------- ! 47: * Definitions. ! 48: * Constants. ! 49: * Macros with argument lists. ! 50: * Typedefs. ! 51: * Enums. ! 52: */ ! 53: ! 54: /* ! 55: * ---------------------------------------------------------------------- ! 56: * Functions. ! 57: * Import Functions. ! 58: * Export Functions. ! 59: * Local Functions. ! 60: */ ! 61: void curr_check_signals(); ! 62: int ptset(); ! 63: void sendsig(); ! 64: int sigdump(); ! 65: __sigfunc_t usigsys(); ! 66: ! 67: static struct _fpstate * empack(); ! 68: static int ptret(); ! 69: ! 70: /* ! 71: * ---------------------------------------------------------------------- ! 72: * Global Data. ! 73: * Import Variables. ! 74: * Export Variables. ! 75: * Local Variables. ! 76: */ ! 77: /* ! 78: * Patchable variables. ! 79: * ! 80: * Patch DUMP_TEXT nonzero to make text segment show up in core files. ! 81: * Patch DUMP_LIM set the upper limit in bytes of how much of a ! 82: * segment is written to a core file. ! 83: * ! 84: * CATCH_SEGV can be patched to allow signal () to be used to catch the ! 85: * SIGSEGV signal (). This is off by default because: ! 86: * i) Experience has shown that kernel printf () messages being on by ! 87: * default is very useful for catching bugs. ! 88: * ii) Certain extremely ill-behaved applications apparently catch SIGSEGV ! 89: * blindly as part of some catch-all behaviour, and when such faults ! 90: * happen have been known to loop generating kernel printf () output ! 91: * which bogs down the system unacceptably. ! 92: * iii) Turning the signal off to avoid ii) causes less actual disruption than ! 93: * leaving it on. ! 94: * This only applies to the signal () interface; we assume that apps which are ! 95: * smart enough to use sigset () or sigaction () also know what to do with ! 96: * SIGSEGV. ! 97: */ ! 98: ! 99: int DUMP_TEXT = 0; ! 100: int DUMP_LIM=512*1024; ! 101: int CATCH_SEGV = 0; ! 102: ! 103: /* ! 104: * ---------------------------------------------------------------------- ! 105: * Code. ! 106: */ ! 107: ! 108: /* ! 109: * Or an entire signal mask into the "hold" mask. ! 110: */ ! 111: ! 112: static void ! 113: sigMask (mask) ! 114: __sigset_t * mask; ! 115: { ! 116: int i; ! 117: __sigmask_t * loop = mask->_sigbits; ! 118: __sigset_t signal_mask; ! 119: ! 120: curr_signal_mask (NULL, & signal_mask); ! 121: ! 122: for (i = 0 ; i < __ARRAY_LENGTH (mask->_sigbits) ; i ++) ! 123: signal_mask._sigbits [i] |= * loop ++; ! 124: ! 125: curr_signal_mask (& signal_mask, NULL); ! 126: } ! 127: ! 128: ! 129: /* ! 130: * Set up the action to be taken on a signal. ! 131: */ ! 132: ! 133: __sigfunc_t ! 134: usigsys (signal, func, regsetp) ! 135: unsigned signal; ! 136: __sigfunc_t func; ! 137: gregset_t * regsetp; ! 138: { ! 139: int sigtype; ! 140: __sigmask_t mask; ! 141: __sigset_t signal_mask; ! 142: __sigaction_t signal_action; ! 143: ! 144: sigtype = signal & ~ 0xFF; ! 145: signal &= 0xFF; ! 146: ! 147: #if 0 ! 148: T_HAL(8, printf("[%d]sig(%d, %x) ", SELF->p_pid, signal, func)); ! 149: #endif ! 150: ! 151: /* ! 152: * Check the passed signal number. SIGKILL and SIGSTOP are not allowed ! 153: * to be caught. ! 154: */ ! 155: ! 156: /* Range check on 1-based signal number. */ ! 157: if (signal <= 0 || signal > NSIG || signal == SIGSTOP || ! 158: signal == SIGKILL) { ! 159: u.u_error = EINVAL; ! 160: return; ! 161: } ! 162: ! 163: signal_action.sa_handler = func; ! 164: signal_action.sa_flags = 0; ! 165: __SIGSET_EMPTY (signal_action.sa_mask); ! 166: func = 0; ! 167: ! 168: curr_signal_mask (NULL, & signal_mask); ! 169: ! 170: mask = __SIGSET_MASK (signal); ! 171: ! 172: switch (sigtype) { ! 173: case SIGHOLD: ! 174: __SIGSET_ADDMASK (signal_mask, signal, mask); ! 175: break; ! 176: ! 177: case SIGRELSE: ! 178: __SIGSET_CLRMASK (signal_mask, signal, mask); ! 179: break; ! 180: ! 181: case SIGIGNORE: ! 182: __SIGSET_CLRMASK (signal_mask, signal, mask); ! 183: signal_action.sa_handler = SIG_IGN; ! 184: curr_signal_action (signal, & signal_action, NULL); ! 185: break; ! 186: ! 187: case 0: /* signal () */ ! 188: if (signal == SIGSEGV && CATCH_SEGV == 0) { ! 189: u.u_error = EINVAL; ! 190: return 0; ! 191: } ! 192: u.u_sigreturn = (__sigfunc_t) regsetp->_i386._edx; ! 193: ! 194: if (signal == SIGCHLD) { ! 195: /* ! 196: * With signal (), the argument implicitly mangles the ! 197: * SA_NOCLDWAIT flag. I have no idea whether the ! 198: * SA_NOCLDSTOP flag is also implicitly affected, but ! 199: * for now we leave it alone. ! 200: */ ! 201: ! 202: curr_signal_misc (__SF_NOCLDWAIT, ! 203: signal_action.sa_handler == ! 204: SIG_IGN ? __SF_NOCLDWAIT : 0); ! 205: } ! 206: signal_action.sa_flags |= __SA_RESETHAND; ! 207: curr_signal_action (signal, & signal_action, & signal_action); ! 208: ! 209: /* ! 210: * Using the signal () interface automatically causes a ! 211: * pending signal to be discarded. ! 212: */ ! 213: ! 214: proc_unkill (SELF, signal); ! 215: return signal_action.sa_handler; ! 216: ! 217: case SIGSET: ! 218: u.u_sigreturn = (__sigfunc_t) regsetp->_i386._edx; ! 219: ! 220: if (__SIGSET_TSTMASK (signal_mask, signal, mask)) ! 221: func = SIG_HOLD; ! 222: ! 223: if (signal_action.sa_handler == SIG_HOLD) { ! 224: ! 225: __SIGSET_ADDMASK (signal_mask, signal, mask); ! 226: ! 227: if (func != SIG_HOLD) { ! 228: curr_signal_action (signal, NULL, ! 229: & signal_action); ! 230: func = signal_action.sa_handler; ! 231: } ! 232: break; ! 233: } ! 234: ! 235: if (signal == SIGCHLD) { ! 236: /* ! 237: * With sigset (), the argument implicitly mangles the ! 238: * SA_NOCLDWAIT flag. I have no idea whether the ! 239: * SA_NOCLDSTOP flag is also implicitly affected, but ! 240: * for now we leave it alone. ! 241: */ ! 242: ! 243: curr_signal_misc (__SF_NOCLDWAIT, ! 244: signal_action.sa_handler == ! 245: SIG_IGN ? __SF_NOCLDWAIT : 0); ! 246: } ! 247: __SIGSET_CLRMASK (signal_mask, signal, mask); ! 248: __SIGSET_ADDMASK (signal_action.sa_mask, signal, mask); ! 249: curr_signal_action (signal, & signal_action, & signal_action); ! 250: ! 251: if (func != SIG_HOLD) ! 252: func = signal_action.sa_handler; ! 253: break; ! 254: ! 255: case SIGPAUSE: ! 256: /* ! 257: * Like upause(), do a sleep on an event which never gets a ! 258: * wakeup. The sleep returns immediately if a signal was ! 259: * already holding. ! 260: */ ! 261: ! 262: __SIGSET_CLRMASK (signal_mask, signal, mask); ! 263: curr_signal_mask (& signal_mask, NULL); ! 264: (void) x_sleep ((char *) & u, prilo, slpriSigCatch, ! 265: "sigpause"); ! 266: return 0; ! 267: ! 268: default: ! 269: u.u_error = SIGSYS; ! 270: return 0; ! 271: } ! 272: ! 273: curr_signal_mask (& signal_mask, NULL); ! 274: return func; ! 275: } ! 276: ! 277: /* ! 278: * Send a signal to the process `pp'. This function is only valid for use with ! 279: * signals generated from user level with kill (), sigsend () or ! 280: * sigsendset (). ! 281: */ ! 282: ! 283: void ! 284: sendsig(sig, pp) ! 285: register unsigned sig; ! 286: register PROC *pp; ! 287: { ! 288: __siginfo_t siginfo; ! 289: ! 290: #if 0 ! 291: T_HAL(8, if (sig == SIGINT) printf("[%d]gets int ", pp->p_pid)); ! 292: #else ! 293: T_HAL(8, printf ("[%d] sig=%d ", pp->p_pid, sig)); ! 294: #endif ! 295: ! 296: siginfo.__si_signo = sig; ! 297: siginfo.__si_code = 0; ! 298: siginfo.__si_errno = 0; ! 299: siginfo.__si_pid = SELF->p_pid; ! 300: siginfo.__si_uid = SELF->p_uid; ! 301: ! 302: proc_send_signal (pp, & siginfo); ! 303: } ! 304: ! 305: ! 306: /* ! 307: * Return signal number if we have a non ignored or delayed signal, else zero. ! 308: */ ! 309: ! 310: int ! 311: nondsig() ! 312: { ! 313: return curr_signal_pending (); ! 314: } ! 315: ! 316: ! 317: /* ! 318: * If we have a signal that isn't ignored, activate it. The register set is ! 319: * not "const" because the low-level trap code that uses it wants to modify ! 320: * it. ! 321: */ ! 322: ! 323: #if __USE_PROTO__ ! 324: void curr_check_signals (gregset_t * regsetp) ! 325: #else ! 326: void ! 327: curr_check_signals (regsetp) ! 328: gregset_t * regsetp; ! 329: #endif ! 330: { ! 331: register int signum; ! 332: int ptval; ! 333: ! 334: /* ! 335: * Fetch an unprocessed signal. ! 336: * Return if there are none. ! 337: * The while() structure is only for traced processes. ! 338: */ ! 339: while ((signum = curr_signal_pending ()) != 0) { ! 340: __sigaction_t signal_action; ! 341: ! 342: /* ! 343: * Reset the signal to indicate that it has been processed, ! 344: * and fetch the signal disposition. ! 345: */ ! 346: ! 347: got_signal: ! 348: proc_unkill (SELF, signum); ! 349: curr_signal_action (signum, NULL, & signal_action); ! 350: ! 351: /* ! 352: * Store the signal number in the u area. ! 353: * This is how a core dump records the death signal. ! 354: */ ! 355: u.u_signo = signum; ! 356: ! 357: /* ! 358: * If the signal is not defaulted, go run the requested ! 359: * function. ! 360: */ ! 361: ! 362: if (signal_action.sa_handler != SIG_DFL) { ! 363: if (__xmode_286 (regsetp)) ! 364: oldsigstart (signum, signal_action.sa_handler, ! 365: regsetp); ! 366: else ! 367: msigstart (signum, signal_action.sa_handler, ! 368: regsetp); ! 369: ! 370: /* ! 371: * If the signal needs to be reset after delivery, do so. Note that ! 372: * all signal-related activity goes though the defined function ! 373: * interface; many subtle things may need to happen, so we let the ! 374: * layering take care of it. ! 375: */ ! 376: ! 377: if ((signal_action.sa_flags & __SA_RESETHAND) != 0) { ! 378: signal_action.sa_handler = SIG_DFL; ! 379: curr_signal_action (signum, & signal_action, ! 380: NULL); ! 381: } else ! 382: sigMask (& signal_action.sa_mask); ! 383: ! 384: return; ! 385: } ! 386: ! 387: /* ! 388: * msysgen() is a nop for COHERENT 4.0. The comment in the ! 389: * assembly code is "Nothing useful to save". ! 390: */ ! 391: ! 392: msysgen (u.u_sysgen); ! 393: ! 394: /* ! 395: * When a traced process is signaled, it may need to exchange ! 396: * data with its parent (via ptret). ! 397: */ ! 398: ! 399: if ((SELF->p_flags & PFTRAC) != 0) { ! 400: SELF->p_flags |= PFWAIT; ! 401: ptval = ptret (regsetp); ! 402: ! 403: T_HAL(0x10000, printf("ptret()=%x ", ptval)); ! 404: ! 405: SELF->p_flags &= ~ (PFWAIT | PFSTOP); ! 406: ! 407: while ((signum = curr_signal_pending ()) != 0) ! 408: proc_unkill (SELF, signum); ! 409: ! 410: if (ptval == 0) ! 411: /* see if another signal came in */ ! 412: continue; ! 413: ! 414: if ((signum = ptval) != SIGKILL) ! 415: goto got_signal; ! 416: } ! 417: ! 418: /* ! 419: * Some signals cause a core file to be written. ! 420: */ ! 421: switch (signum) { ! 422: case SIGQUIT: ! 423: case SIGILL: ! 424: case SIGTRAP: ! 425: case SIGABRT: ! 426: case SIGFPE: ! 427: case SIGSEGV: ! 428: case SIGSYS: ! 429: if (sigdump ()) ! 430: signum |= __WCOREFLG; ! 431: break; ! 432: } ! 433: pexit (signum); ! 434: } ! 435: } ! 436: ! 437: /* ! 438: * Create a dump of ourselves onto the file `core'. ! 439: */ ! 440: ! 441: int ! 442: sigdump () ! 443: { ! 444: register INODE *ip; ! 445: register SR *srp; ! 446: register SEG * sp; ! 447: register int n; ! 448: register paddr_t ssize; ! 449: extern int DUMP_LIM; ! 450: struct ch_info chInfo; ! 451: IO io; ! 452: struct direct dir; ! 453: ! 454: if (SELF->p_flags & PFNDMP) ! 455: return 0; ! 456: ! 457: /* Make the core with the real owners */ ! 458: schizo (); ! 459: ! 460: io.io_seg = IOSYS; ! 461: io.io_flag = 0; ! 462: if (ftoi ("core", 'c', & io, & dir)) { ! 463: schizo (); ! 464: return 0; ! 465: } ! 466: ! 467: if ((ip = u.u_cdiri) == NULL) { ! 468: if ((ip = imake (IFREG | 0644, 0, & io, & dir)) == NULL) { ! 469: schizo (); ! 470: return 0; ! 471: } ! 472: } else { ! 473: if ((ip->i_mode & IFMT) != IFREG || iaccess (ip, IPW) == 0 || ! 474: getment (ip->i_dev, 1) == NULL) { ! 475: idetach (ip); ! 476: schizo (); ! 477: return 0; ! 478: } ! 479: iclear (ip); ! 480: } ! 481: schizo (); ! 482: u.u_error = 0; ! 483: ! 484: /* Write core file header */ ! 485: chInfo.ch_magic = CORE_MAGIC; ! 486: chInfo.ch_info_len = sizeof (chInfo); ! 487: chInfo.ch_uproc_offset = U_OFFSET; ! 488: ! 489: io.io_seek = 0; ! 490: io.io_seg = IOSYS; ! 491: io.io.vbase = & chInfo; ! 492: io.io_ioc = sizeof (chInfo); ! 493: io.io_flag = 0; ! 494: ! 495: iwrite (ip, & io); ! 496: ! 497: /* ! 498: * Added to aid in kernel debugging - if DUMP_TEXT is nonzero, ! 499: * dump the text segment (to see if it was corrupted) and set ! 500: * the dump flag so that postmortem utilities will know that ! 501: * text is present in the core file. ! 502: */ ! 503: ! 504: if (DUMP_TEXT) ! 505: u.u_segl [SISTEXT].sr_flag |= SRFDUMP; ! 506: ! 507: for (srp = u.u_segl + 1 ; u.u_error == 0 && srp < u.u_segl + NUSEG ; ! 508: srp ++) { ! 509: ! 510: if ((srp->sr_flag & SRFDUMP) == 0) ! 511: continue; ! 512: ! 513: /* Don't try to dump empty segments. */ ! 514: if ((sp = srp->sr_segp) == NULL) { ! 515: srp->sr_flag &= ~SRFDUMP; ! 516: continue; ! 517: } ! 518: ! 519: /* Don't dump segments too big to dump. */ ! 520: if (sp->s_size > DUMP_LIM) ! 521: srp->sr_flag &= ~SRFDUMP; ! 522: } ! 523: ! 524: /* Always dump the U segment. */ ! 525: u.u_segl [SIUSERP].sr_flag |= SRFDUMP; ! 526: ! 527: for (srp = u.u_segl ; u.u_error == 0 && srp < u.u_segl + NUSEG ; ! 528: srp ++) { ! 529: ! 530: /* Only dump segments flagged for dumping. */ ! 531: if ((srp->sr_flag & SRFDUMP) == 0) ! 532: continue; ! 533: ! 534: sp = srp->sr_segp; ! 535: ! 536: ssize = sp->s_size; ! 537: io.io_seg = IOPHY; ! 538: io.io.pbase = MAPIO (sp->s_vmem, 0); ! 539: io.io_flag = 0; ! 540: sp->s_lrefc ++; ! 541: while (u.u_error == 0 && ssize != 0) { ! 542: n = ssize > SCHUNK ? SCHUNK : ssize; ! 543: io.io_ioc = n; ! 544: iwrite (ip, & io); ! 545: io.io.pbase += n; ! 546: ssize -= (paddr_t) n; ! 547: } ! 548: sp->s_lrefc --; ! 549: } ! 550: idetach (ip); ! 551: return u.u_error == 0; ! 552: } ! 553: ! 554: /* ! 555: * Send a ptrace command to the child. ! 556: * ! 557: * "pid" is child pid. ! 558: */ ! 559: ! 560: int ! 561: ptset(req, pid, addr, data) ! 562: unsigned req; ! 563: int *addr; ! 564: { ! 565: register PROC *pp; ! 566: ! 567: lock (pnxgate); ! 568: for (pp = procq.p_nforw ; pp != & procq ; pp = pp->p_nforw) ! 569: if (pp->p_pid == pid) ! 570: break; ! 571: unlock (pnxgate); ! 572: if (pp == & procq || (pp->p_flags & PFSTOP) == 0 || ! 573: pp->p_ppid != SELF->p_pid) { ! 574: u.u_error = ESRCH; ! 575: return; ! 576: } ! 577: ! 578: lock (pts.pt_gate); ! 579: pts.pt_req = req; ! 580: pts.pt_pid = pid; ! 581: pts.pt_addr = addr; ! 582: pts.pt_data = data; ! 583: pts.pt_errs = 0; ! 584: pts.pt_rval = 0; ! 585: pts.pt_busy = 1; ! 586: ! 587: wakeup ((char *) & pts.pt_req); ! 588: ! 589: while (pts.pt_busy) { ! 590: x_sleep ((char *) & pts.pt_busy, primed, slpriSigCatch, ! 591: "ptrace"); ! 592: /* Send a ptrace command to the child. */ ! 593: } ! 594: ! 595: u.u_error = pts.pt_errs; ! 596: unlock (pts.pt_gate); ! 597: return pts.pt_rval; ! 598: } ! 599: ! 600: /* ! 601: * This routine is called when a child that is being traced receives a signal ! 602: * that is not caught or ignored. It follows up on any requests by the parent ! 603: * and returns when done. ! 604: * ! 605: * After ptrace handling done in this routine, a real or simulated signal ! 606: * may need to be sent to the traced process. ! 607: * Return a signal number to be sent to the child process, or 0 if none. ! 608: */ ! 609: ! 610: static int ! 611: ptret (regsetp) ! 612: gregset_t * regsetp; ! 613: { ! 614: extern void (*ndpKfrstor)(); ! 615: register PROC *pp; ! 616: register PROC *pp1; ! 617: register int sign; ! 618: unsigned off; ! 619: int doEmUnpack = 0; ! 620: struct _fpstate * fstp = empack (); ! 621: ! 622: pp = SELF; ! 623: next: ! 624: u.u_error = 0; ! 625: if (pp->p_ppid == 1) ! 626: return SIGKILL; ! 627: sign = -1; ! 628: ! 629: /* wake up parent if it is sleeping */ ! 630: lock (pnxgate); ! 631: pp1 = & procq; ! 632: for (;;) { ! 633: if ((pp1 = pp1->p_nforw) == & procq) { ! 634: sign = SIGKILL; ! 635: break; ! 636: } ! 637: if (pp1->p_pid != pp->p_ppid) ! 638: continue; ! 639: if (ASLEEP (pp1)) ! 640: wakeup ((char *) pp1); ! 641: break; ! 642: } ! 643: unlock (pnxgate); ! 644: ! 645: while (sign < 0) { ! 646: /* If no pending ptrace transaction for this process, sleep. */ ! 647: if (pts.pt_busy == 0 || pp->p_pid != pts.pt_pid) { ! 648: /* ! 649: * If a signal bit is set now, just exit - let ! 650: * actvsig() handle it next time through. ! 651: * Doing sleep and goto next will stick us in a loop ! 652: */ ! 653: ! 654: if (nondsig ()) ! 655: return 0; ! 656: x_sleep ((char *) & pts.pt_req, primed, ! 657: slpriSigCatch, "ptret"); ! 658: goto next; ! 659: } ! 660: ! 661: switch (pts.pt_req) { ! 662: case PTRACE_RD_TXT: ! 663: if (__xmode_286 (regsetp)) { ! 664: pts.pt_rval = getuwd (NBPS + pts.pt_addr); ! 665: break; ! 666: } ! 667: /* Fall through for 386 mode processes. */ ! 668: ! 669: case PTRACE_RD_DAT: ! 670: pts.pt_rval = getuwd (pts.pt_addr); ! 671: break; ! 672: ! 673: case PTRACE_RD_USR: ! 674: /* See ptrace.h for valid offsets. */ ! 675: off = (unsigned) pts.pt_addr; ! 676: if (off & 3) ! 677: u.u_error = EINVAL; ! 678: else if (off < PTRACE_FP_CW) { ! 679: /* Reading CPU general register state */ ! 680: if (off == PTRACE_SIG) ! 681: pts.pt_rval = u.u_signo; ! 682: else ! 683: pts.pt_rval = ! 684: ((int *) regsetp) [off >> 2]; ! 685: } else if (off < PTRACE_DR0) { ! 686: /* ! 687: * Reading NDP state. ! 688: * If NDP state not already saved, save it. ! 689: * Fetch desired info. ! 690: * Restore NDP state in case we will resume. ! 691: */ ! 692: if (rdNdpUser ()) { ! 693: /* if using coprocessor */ ! 694: if (! rdNdpSaved ()) { ! 695: ndpSave (& u.u_ndpCon); ! 696: wrNdpSaved (1); ! 697: } ! 698: pts.pt_rval = ((int *) & u.u_ndpCon) [(off - PTRACE_FP_CW) >> 2]; ! 699: ndpRestore (& u.u_ndpCon); ! 700: wrNdpSaved (0); ! 701: } else if (fstp) { ! 702: pts.pt_rval = getuwd(((int *) fstp) + ((off - PTRACE_FP_CW) >> 2)); ! 703: /* if emulating */ ! 704: } else { /* no ndp state to display */ ! 705: pts.pt_rval = 0; ! 706: u.u_error = EFAULT; ! 707: } ! 708: } else /* Bad pseudo offset. */ ! 709: u.u_error = EINVAL; ! 710: break; ! 711: ! 712: case PTRACE_WR_TXT: ! 713: if (__xmode_286 (regsetp)) { ! 714: putuwd (NBPS + pts.pt_addr, pts.pt_data); ! 715: break; ! 716: } ! 717: /* Fall through for 386 mode processes. */ ! 718: ! 719: case PTRACE_WR_DAT: ! 720: putuwd (pts.pt_addr, pts.pt_data); ! 721: break; ! 722: ! 723: case PTRACE_WR_USR: ! 724: /* See ptrace.h for valid offsets. */ ! 725: off = (unsigned) pts.pt_addr; ! 726: ! 727: if (off & 3) ! 728: u.u_error = EINVAL; ! 729: else if (off < PTRACE_FP_CW) { ! 730: /* Writing CPU general register state */ ! 731: if (off == PTRACE_SIG) ! 732: u.u_error = EINVAL; ! 733: else ! 734: ((int *) regsetp) [off >> 2] = ! 735: pts.pt_data; ! 736: } else if (off < PTRACE_DR0) { ! 737: if (rdNdpUser ()) { ! 738: /* ! 739: * Writing NDP state. ! 740: * If NDP state not already saved, save it. ! 741: * Store desired info. ! 742: * Restore NDP state in case we will resume. ! 743: */ ! 744: if (! rdNdpSaved ()) { ! 745: ndpSave (& u.u_ndpCon); ! 746: wrNdpSaved (1); ! 747: } ! 748: ((int *)&u.u_ndpCon)[(off - PTRACE_FP_CW)>>2] = pts.pt_data; ! 749: ndpRestore (& u.u_ndpCon); ! 750: wrNdpSaved (0); ! 751: } else if (fstp && ndpKfrstor) { ! 752: putuwd(((int *)fstp) + ((off - PTRACE_FP_CW)>>2), pts.pt_data); ! 753: doEmUnpack = 1; ! 754: } else { /* No NDP state to modify. */ ! 755: u.u_error = EFAULT; ! 756: } ! 757: } else /* Bad pseudo offset. */ ! 758: u.u_error = EINVAL; ! 759: break; ! 760: ! 761: case PTRACE_RESUME: ! 762: regsetp->_i386._eflags &= ~ MFTTB; ! 763: goto sig; ! 764: ! 765: case PTRACE_TERM: ! 766: sign = SIGKILL; ! 767: break; ! 768: ! 769: case PTRACE_SSTEP: ! 770: regsetp->_i386._eflags |= MFTTB; ! 771: sig: ! 772: if (pts.pt_data < 0 || pts.pt_data > NSIG) { ! 773: u.u_error = EINVAL; ! 774: break; ! 775: } ! 776: sign = pts.pt_data; ! 777: break; ! 778: ! 779: default: ! 780: u.u_error = EINVAL; ! 781: } ! 782: ! 783: if ((pts.pt_errs = u.u_error) == EFAULT) ! 784: pts.pt_errs = EINVAL; ! 785: ! 786: pts.pt_busy = 0; ! 787: wakeup((char *) & pts.pt_busy); ! 788: } ! 789: if (doEmUnpack) ! 790: (* ndpKfrstor) (fstp, & u.u_ndpCon); ! 791: return sign; ! 792: } ! 793: ! 794: /* ! 795: * If using floating point emulator, make room on user stack and save ! 796: * floating point context there. Code elsewhere takes care of floating ! 797: * point context if there is a coprocessor. ! 798: * ! 799: * Return the virtual address in user space of the context area, or ! 800: * return NULL if not using FP emulation. ! 801: */ ! 802: ! 803: static struct _fpstate * ! 804: empack (regsetp) ! 805: gregset_t * regsetp; ! 806: { ! 807: int sphi; ! 808: struct _fpstate * ret; ! 809: SEG * segp = u.u_segl [SISTACK].sr_segp; ! 810: extern void (*ndpKfsave)(); ! 811: unsigned long sw_old; ! 812: ! 813: /* If not emulating, do nothing */ ! 814: if (rdNdpUser () || ! rdEmTrapped () || ! ndpKfsave) ! 815: return NULL; ! 816: ! 817: /* ! 818: * Will copy at least u_sigreturn, _fpstackframe, and ndpFlags. ! 819: * If using ndp, need room for an _fpstate. ! 820: * If emulating, need room for an _fpemstate. ! 821: */ ! 822: ! 823: ret = (struct _fpstate *) ! 824: (__xmode_286 (regsetp) ? regsetp->_i286._usp : ! 825: regsetp->_i386._uesp) - 1; ! 826: ! 827: /* Add to user stack if necessary. */ ! 828: sphi = __xmode_286 (regsetp) ? ISP_286 : ISP_386; ! 829: ! 830: if (sphi - segp->s_size > (__ptr_arith_t) ret) { ! 831: cseg_t * pp; ! 832: ! 833: pp = c_extend (segp->s_vmem, btoc (segp->s_size)); ! 834: if (pp == 0) { ! 835: printf ("Empack failed. cmd=%s c_extend(%x,%x)=0 ", ! 836: u.u_comm, segp->s_vmem, btoc (segp->s_size)); ! 837: return NULL; ! 838: } ! 839: ! 840: segp->s_vmem = pp; ! 841: segp->s_size += NBPC; ! 842: if (sproto (0) == 0) { ! 843: printf ("Empack failed. cmd=%s sproto(0)=0 ", ! 844: u.u_comm); ! 845: return NULL; ! 846: } ! 847: ! 848: segload (); ! 849: } ! 850: ! 851: (* ndpKfsave) (& u.u_ndpCon, ret); ! 852: sw_old = getuwd (& ret->sw); ! 853: putuwd (& ret->status, sw_old); ! 854: putuwd (& ret->sw, sw_old & 0x7f00); ! 855: ! 856: return ret; ! 857: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.