|
|
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.