From: Chris Hanson Date: Sun, 26 Jun 2005 04:35:35 +0000 (+0000) Subject: Rewrite the unix trap handler to simplify and clarify its logic. X-Git-Tag: 20090517-FFI~1269 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=14c14812ea3caadcb77f8373329283eed191d256;p=mit-scheme.git Rewrite the unix trap handler to simplify and clarify its logic. Change the __linux__ code to recognize that the third argument to the signal handler is a "ucontext_t *" and not a "struct sigcontext *" as previously assumed. (This will probably cause problems when used on older linux systems.) --- diff --git a/v7/src/microcode/configure.ac b/v7/src/microcode/configure.ac index 0b8666c3c..78c99acf7 100644 --- a/v7/src/microcode/configure.ac +++ b/v7/src/microcode/configure.ac @@ -1,7 +1,7 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT([MIT/GNU Scheme], [14.15], [bug-mit-scheme@gnu.org], [mit-scheme]) -AC_REVISION([$Id: configure.ac,v 1.4 2005/01/06 19:08:43 cph Exp $]) +AC_INIT([MIT/GNU Scheme], [14.16], [bug-mit-scheme@gnu.org], [mit-scheme]) +AC_REVISION([$Id: configure.ac,v 1.5 2005/06/26 04:35:35 cph Exp $]) AC_CONFIG_SRCDIR([boot.c]) AC_CONFIG_HEADERS([config.h]) AC_PROG_MAKE_SET diff --git a/v7/src/microcode/pruxenv.c b/v7/src/microcode/pruxenv.c index cd5eada6f..822b942f3 100644 --- a/v7/src/microcode/pruxenv.c +++ b/v7/src/microcode/pruxenv.c @@ -1,8 +1,9 @@ /* -*-C-*- -$Id: pruxenv.c,v 1.21 2003/02/14 18:28:23 cph Exp $ +$Id: pruxenv.c,v 1.22 2005/06/26 04:34:39 cph Exp $ -Copyright (c) 1990-2000 Massachusetts Institute of Technology +Copyright 1990,1991,1992l,1993,1995,1997 Massachusetts Institute of Technology +Copyright 2000,2005 Massachusetts Institute of Technology This file is part of MIT/GNU Scheme. @@ -28,6 +29,7 @@ USA. #include "scheme.h" #include "prims.h" #include "ux.h" +#include "uxtrap.h" #ifdef HAVE_SOCKETS # include "uxsock.h" @@ -215,19 +217,25 @@ DEFINE_PRIMITIVE ("HOSTNAME", Prim_hostname, 0, 0, } } - - - DEFINE_PRIMITIVE ("INSTRUCTION-ADDRESS->COMPILED-CODE-BLOCK", Prim_instruction_address_to_compiled_code_block, 1, 1, 0) { PRIMITIVE_HEADER (1); { - extern SCHEME_OBJECT find_ccblock(long); - long the_pc = (INTEGER_P (ARG_REF (1))) - ? (integer_to_long (ARG_REF (1))) - : ((long) OBJECT_ADDRESS (ARG_REF (1))); - PRIMITIVE_RETURN (find_ccblock (the_pc)); + SCHEME_OBJECT object = (ARG_REF (1)); + unsigned long pc; + if (INTEGER_P (object)) + { + if (! (integer_to_ulong_p (object))) + error_bad_range_arg (1); + pc = (integer_to_ulong (object)); + } + else + { + if (! (COMPILED_CODE_ADDRESS_P (object))) + error_bad_range_arg (1); + pc = ((unsigned long) (OBJECT_ADDRESS (object))); + } + PRIMITIVE_RETURN (find_ccblock (pc)); } } - diff --git a/v7/src/microcode/uxsig.c b/v7/src/microcode/uxsig.c index ded79a3df..3127eadeb 100644 --- a/v7/src/microcode/uxsig.c +++ b/v7/src/microcode/uxsig.c @@ -1,8 +1,9 @@ /* -*-C-*- -$Id: uxsig.c,v 1.39 2003/02/14 18:28:24 cph Exp $ +$Id: uxsig.c,v 1.40 2005/06/26 04:34:48 cph Exp $ -Copyright (c) 1990-2001 Massachusetts Institute of Technology +Copyright 1990,1991,1992,1993,1994,1996 Massachusetts Institute of Technology +Copyright 2000,2001,2005 Massachusetts Institute of Technology This file is part of MIT/GNU Scheme. @@ -391,8 +392,7 @@ DEFUN_STD_HANDLER (sighnd_control_b, tty_set_next_interrupt_char (CONTROL_B_INTERRUPT_CHAR); }) -static void EXFUN - (interactive_interrupt_handler, (struct FULL_SIGCONTEXT * scp)); +static void EXFUN (interactive_interrupt_handler, (FULL_SIGCONTEXT_T * scp)); static DEFUN_STD_HANDLER (sighnd_interactive, @@ -737,7 +737,7 @@ DEFUN (OS_tty_map_interrupt_char, (int_char), cc_t int_char) static void EXFUN (print_interactive_help, (void)); static void EXFUN (print_interrupt_chars, (void)); static void EXFUN (examine_memory, (void)); -static void EXFUN (reset_query, (struct FULL_SIGCONTEXT * scp)); +static void EXFUN (reset_query, (FULL_SIGCONTEXT_T * scp)); static void EXFUN (interactive_back_trace, (void)); #define INTERACTIVE_NEWLINE() \ @@ -750,7 +750,7 @@ static void EXFUN (interactive_back_trace, (void)); } static void -DEFUN (interactive_interrupt_handler, (scp), struct FULL_SIGCONTEXT * scp) +DEFUN (interactive_interrupt_handler, (scp), FULL_SIGCONTEXT_T * scp) { if (!option_emacs_subprocess) { @@ -1038,7 +1038,7 @@ DEFUN (invoke_soft_reset, (name), char * name) } static void -DEFUN (reset_query, (scp), struct FULL_SIGCONTEXT * scp) +DEFUN (reset_query, (scp), FULL_SIGCONTEXT_T * scp) { putc ('\n', stdout); fflush (stdout); diff --git a/v7/src/microcode/uxsig.h b/v7/src/microcode/uxsig.h index 4ba17c92c..b8b22ceb0 100644 --- a/v7/src/microcode/uxsig.h +++ b/v7/src/microcode/uxsig.h @@ -1,8 +1,8 @@ /* -*-C-*- -$Id: uxsig.h,v 1.8 2003/02/14 18:28:24 cph Exp $ +$Id: uxsig.h,v 1.9 2005/06/26 04:34:56 cph Exp $ -Copyright (c) 1993-2000 Massachusetts Institute of Technology +Copyright 1993,1994,2000,2005 Massachusetts Institute of Technology This file is part of MIT/GNU Scheme. @@ -53,7 +53,7 @@ Tsignal_handler_result \ DEFUN (name, (signo, info, pscp), \ int signo AND \ SIGINFO_T info AND \ - struct SIGCONTEXT * pscp) \ + SIGCONTEXT_T * pscp) \ { \ int STD_HANDLER_abortp; \ DECLARE_FULL_SIGCONTEXT (scp); \ @@ -79,7 +79,7 @@ Tsignal_handler_result \ DEFUN (name, (signo, info, pscp), \ int signo AND \ SIGINFO_T info AND \ - struct SIGCONTEXT * pscp) \ + SIGCONTEXT_T * pscp) \ { \ int STD_HANDLER_abortp; \ DECLARE_FULL_SIGCONTEXT (scp); \ diff --git a/v7/src/microcode/uxtrap.c b/v7/src/microcode/uxtrap.c index 02182ae72..4c84b98f0 100644 --- a/v7/src/microcode/uxtrap.c +++ b/v7/src/microcode/uxtrap.c @@ -1,9 +1,9 @@ /* -*-C-*- -$Id: uxtrap.c,v 1.39 2003/05/12 20:02:55 cph Exp $ +$Id: uxtrap.c,v 1.40 2005/06/26 04:35:03 cph Exp $ Copyright 1990,1991,1992,1993,1995,1997 Massachusetts Institute of Technology -Copyright 2000,2001,2002,2003 Massachusetts Institute of Technology +Copyright 2000,2001,2002,2003,2005 Massachusetts Institute of Technology This file is part of MIT/GNU Scheme. @@ -31,23 +31,98 @@ USA. #include "option.h" #include "ostop.h" +#ifdef HAS_COMPILER_SUPPORT +# include "gccode.h" +#endif + +#if defined(HAVE_STRUCT_SIGCONTEXT) && defined(HAS_COMPILER_SUPPORT) && !defined(USE_STACKLETS) +# define ENABLE_TRAP_RECOVERY 1 +#endif + extern CONST char * EXFUN (find_signal_name, (int signo)); extern void EXFUN (UX_dump_core, (void)); extern PTR initial_C_stack_pointer; +extern int EXFUN (pc_to_utility_index, (unsigned long)); +extern int EXFUN (pc_to_builtin_index, (unsigned long)); +extern SCHEME_OBJECT * EXFUN (find_constant_space_block, (SCHEME_OBJECT *)); +struct ux_sig_code_desc +{ + int signo; + unsigned long code_mask; + unsigned long code_value; + char * name; +}; + +static struct ux_sig_code_desc ux_signal_codes [64]; + +#define DECLARE_UX_SIGNAL_CODE(s, m, v, n) \ +{ \ + ((ux_signal_codes [i]) . signo) = (s); \ + ((ux_signal_codes [i]) . code_mask) = (m); \ + ((ux_signal_codes [i]) . code_value) = (v); \ + ((ux_signal_codes [i]) . name) = (n); \ + i += 1; \ +} + +enum pc_location +{ + pcl_heap, + pcl_constant, + pcl_builtin, + pcl_utility, + pcl_primitive, + pcl_unknown +}; + +#ifdef TC_POSITIVE_FIXNUM +# define FIXNUM_MARKER TC_POSITIVE_FIXNUM +#else +# define FIXNUM_MARKER TC_FIXNUM +#endif + +#ifndef SPECIAL_SIGNAL_CODE_NAMES +# define SPECIAL_SIGNAL_CODE_NAMES() +#endif + static enum trap_state trap_state; static enum trap_state user_trap_state; - static enum trap_state saved_trap_state; static int saved_signo; static SIGINFO_T saved_info; -static struct FULL_SIGCONTEXT * saved_scp; +static DECLARE_FULL_SIGCONTEXT (saved_scp); + +static void EXFUN + (continue_from_trap, (int, SIGINFO_T, FULL_SIGCONTEXT_T *)); + +static SCHEME_OBJECT * EXFUN (find_heap_address, (unsigned long)); +static SCHEME_OBJECT * EXFUN (find_constant_address, (unsigned long)); + +#ifdef ENABLE_TRAP_RECOVERY +static SCHEME_OBJECT * EXFUN + (find_block_address_in_area, (SCHEME_OBJECT *, SCHEME_OBJECT *)); +#endif -static void EXFUN (initialize_ux_signal_codes, (void)); static void EXFUN - (continue_from_trap, - (int signo, SIGINFO_T info, struct FULL_SIGCONTEXT * scp)); + (setup_trap_frame, (int, + SIGINFO_T, + FULL_SIGCONTEXT_T *, + struct trap_recovery_info *, + SCHEME_OBJECT *)); + +static void EXFUN (initialize_ux_signal_codes, (void)); + +static SCHEME_OBJECT EXFUN + (find_signal_code_name, (int, SIGINFO_T, FULL_SIGCONTEXT_T *)); +static enum pc_location EXFUN + (classify_pc, (unsigned long, SCHEME_OBJECT **, unsigned int *)); + +static void EXFUN (trap_normal_termination, (void)); +static void EXFUN (trap_immediate_termination, (void)); +static void EXFUN (trap_dump_core, (void)); +static void EXFUN (trap_recover, (void)); + void DEFUN_VOID (UX_initialize_trap_recovery) { @@ -65,44 +140,55 @@ DEFUN (OS_set_trap_state, (state), enum trap_state state) return (old_trap_state); } -static void -DEFUN_VOID (trap_normal_termination) -{ - trap_state = trap_state_exitting_soft; - termination_trap (); -} - -static void -DEFUN_VOID (trap_immediate_termination) +void +DEFUN (hard_reset, (scp), FULL_SIGCONTEXT_T * scp) { - trap_state = trap_state_exitting_hard; - OS_restore_external_state (); - exit (1); + /* 0 is an invalid signal, it means a user requested reset. */ + continue_from_trap (0, 0, scp); } -static void -DEFUN_VOID (trap_dump_core) +void +DEFUN_VOID (soft_reset) { - if (! (option_disable_core_dump)) - UX_dump_core (); + /* Called synchronously. */ + struct trap_recovery_info trinfo; + SCHEME_OBJECT * new_stack_pointer = + (((sp_register <= Stack_Top) && (sp_register > Stack_Guard)) + ? sp_register + : 0); + if ((Registers[REGBLOCK_PRIMITIVE]) != SHARP_F) + { + (trinfo . state) = STATE_PRIMITIVE; + (trinfo . pc_info_1) = (Registers[REGBLOCK_PRIMITIVE]); + (trinfo . pc_info_2) = + (LONG_TO_UNSIGNED_FIXNUM (Registers[REGBLOCK_LEXPR_ACTUALS])); + (trinfo . extra_trap_info) = SHARP_F; + } else { - fputs (">> Core dumps are disabled - Terminating normally.\n", stdout); - fflush (stdout); - termination_trap (); + (trinfo . state) = STATE_UNKNOWN; + (trinfo . pc_info_1) = SHARP_F; + (trinfo . pc_info_2) = SHARP_F; + (trinfo . extra_trap_info) = SHARP_F; } + if ((Free >= Heap_Top) || (Free < Heap_Bottom)) + /* Let's hope this works. */ + Free = MemTop; + setup_trap_frame (0, 0, 0, (&trinfo), new_stack_pointer); } -static void -DEFUN_VOID (trap_recover) +SCHEME_OBJECT +DEFUN (find_ccblock, (pc), unsigned long pc) { - if (WITHIN_CRITICAL_SECTION_P ()) - { - CLEAR_CRITICAL_SECTION_HOOK (); - EXIT_CRITICAL_SECTION ({}); - } - reset_interruptable_extent (); - continue_from_trap (saved_signo, saved_info, saved_scp); + SCHEME_OBJECT * block_addr; + int index; + + block_addr = 0; + classify_pc (pc, (&block_addr), (&index)); + return + ((block_addr != 0) + ? (MAKE_POINTER_OBJECT (TC_COMPILED_CODE_BLOCK, block_addr)) + : SHARP_F); } void @@ -110,7 +196,7 @@ DEFUN (trap_handler, (message, signo, info, scp), CONST char * message AND int signo AND SIGINFO_T info AND - struct FULL_SIGCONTEXT * scp) + FULL_SIGCONTEXT_T * scp) { int code = ((SIGINFO_VALID_P (info)) ? (SIGINFO_CODE (info)) : 0); Boolean stack_overflowed_p = (STACK_OVERFLOWED_P ()); @@ -118,74 +204,74 @@ DEFUN (trap_handler, (message, signo, info, scp), if (old_trap_state == trap_state_exitting_hard) _exit (1); - else if (old_trap_state == trap_state_exitting_soft) + if (old_trap_state == trap_state_exitting_soft) trap_immediate_termination (); trap_state = trap_state_trapped; + if (WITHIN_CRITICAL_SECTION_P ()) - { - fprintf (stdout, - "\n>> A %s has occurred within critical section \"%s\".\n", - message, (CRITICAL_SECTION_NAME ())); - fprintf (stdout, ">> [signal %d (%s), code %d]\n", - signo, (find_signal_name (signo)), code); - } + { + fprintf (stdout, + "\n>> A %s has occurred within critical section \"%s\".\n", + message, (CRITICAL_SECTION_NAME ())); + fprintf (stdout, ">> [signal %d (%s), code %d]\n", + signo, (find_signal_name (signo)), code); + } else if (stack_overflowed_p || (old_trap_state != trap_state_recover)) - { - fprintf (stdout, "\n>> A %s has occurred.\n", message); - fprintf (stdout, ">> [signal %d (%s), code %d]\n", - signo, (find_signal_name (signo)), code); - } + { + fprintf (stdout, "\n>> A %s has occurred.\n", message); + fprintf (stdout, ">> [signal %d (%s), code %d]\n", + signo, (find_signal_name (signo)), code); + } if (stack_overflowed_p) - { - fputs (">> The stack has overflowed overwriting adjacent memory.\n", - stdout); - fputs (">> This was probably caused by a runaway recursion.\n", stdout); - } + { + fputs (">> The stack has overflowed overwriting adjacent memory.\n", + stdout); + fputs (">> This was probably caused by a runaway recursion.\n", stdout); + } fflush (stdout); switch (old_trap_state) - { - case trap_state_trapped: - if ((saved_trap_state == trap_state_recover) || - (saved_trap_state == trap_state_query)) { - fputs (">> The trap occurred while processing an earlier trap.\n", - stdout); - fprintf (stdout, - ">> [The earlier trap raised signal %d (%s), code %d.]\n", - saved_signo, - (find_signal_name (saved_signo)), - ((SIGINFO_VALID_P (saved_info)) - ? (SIGINFO_CODE (saved_info)) - : 0)); - fputs (((WITHIN_CRITICAL_SECTION_P ()) - ? ">> Successful recovery is extremely unlikely.\n" - : ">> Successful recovery is unlikely.\n"), - stdout); + case trap_state_trapped: + if ((saved_trap_state == trap_state_recover) + || (saved_trap_state == trap_state_query)) + { + fprintf (stdout, + ">> The trap occurred while processing an earlier trap.\n"); + fprintf (stdout, + ">> [The earlier trap raised signal %d (%s), code %d.]\n", + saved_signo, + (find_signal_name (saved_signo)), + ((SIGINFO_VALID_P (saved_info)) + ? (SIGINFO_CODE (saved_info)) + : 0)); + fprintf (stdout, ">> Successful recovery is %sunlikely.\n", + ((WITHIN_CRITICAL_SECTION_P ()) ? "extremely " : "")); + } + else + trap_immediate_termination (); break; - } - else - trap_immediate_termination (); - case trap_state_recover: - if ((WITHIN_CRITICAL_SECTION_P ()) || stack_overflowed_p) - { - fputs (">> Successful recovery is unlikely.\n", stdout); + + case trap_state_recover: + if ((WITHIN_CRITICAL_SECTION_P ()) || stack_overflowed_p) + fprintf (stdout, ">> Successful recovery is unlikely.\n"); + else + { + saved_trap_state = old_trap_state; + saved_signo = signo; + saved_info = info; + saved_scp = scp; + trap_recover (); + } break; - } - else - { - saved_trap_state = old_trap_state; - saved_signo = signo; - saved_info = info; - saved_scp = scp; - trap_recover (); - } - case trap_state_exit: - termination_trap (); - default: - break; - } + case trap_state_exit: + termination_trap (); + break; + + default: + break; + } fflush (stdout); saved_trap_state = old_trap_state; @@ -194,213 +280,287 @@ DEFUN (trap_handler, (message, signo, info, scp), saved_scp = scp; while (1) - { - static CONST char * trap_query_choices[] = { - "D = dump core", - "I = terminate immediately", - "N = terminate normally", - "R = attempt recovery", - "Q = terminate normally", - 0 - }; - switch (userio_choose_option - ("Choose one of the following actions:", - "Action -> ", - trap_query_choices)) - { - case 'I': - trap_immediate_termination (); - case 'D': - trap_dump_core (); - case '\0': - /* Error in IO. Assume everything scrod. */ - case 'N': - case 'Q': - trap_normal_termination (); - case 'R': - trap_recover (); + static CONST char * trap_query_choices[] = + { + "D = dump core", + "I = terminate immediately", + "N = terminate normally", + "R = attempt recovery", + "Q = terminate normally", + 0 + }; + switch (userio_choose_option + ("Choose one of the following actions:", + "Action -> ", + trap_query_choices)) + { + case 'I': + trap_immediate_termination (); + break; + case 'D': + trap_dump_core (); + break; + case '\0': + /* Error in IO. Assume everything scrod. */ + case 'N': + case 'Q': + trap_normal_termination (); + break; + case 'R': + trap_recover (); + break; + } } - } } -struct ux_sig_code_desc -{ - int signo; - unsigned long code_mask; - unsigned long code_value; - char *name; -}; +#ifdef ENABLE_TRAP_RECOVERY -static struct ux_sig_code_desc ux_signal_codes [64]; +/* Heuristic recovery from Unix signals (traps). -#define DECLARE_UX_SIGNAL_CODE(s, m, v, n) \ + continue_from_trap attempts to: + + 1) validate the trap information (pc and sp); + 2) determine whether compiled code was executing, a primitive was + executing, or execution was in the interpreter; + 3) guess what C global state is still valid; and + 4) set up a recovery frame for the interpreter so that debuggers can + display more information. */ + +#define SCHEME_ALIGNMENT_MASK ((sizeof (SCHEME_OBJECT)) - 1) +#define FREE_PARANOIA_MARGIN 0x100 + +#define ALIGNED_P(addr) \ + ((((unsigned long) (addr)) & SCHEME_ALIGNMENT_MASK) == 0) + +#define PC_ALIGNED_P(pc) ((((unsigned long) (pc)) & PC_ALIGNMENT_MASK) == 0) + +#define SET_RECOVERY_INFO(s, arg1, arg2) do \ { \ - ((ux_signal_codes [i]) . signo) = (s); \ - ((ux_signal_codes [i]) . code_mask) = (m); \ - ((ux_signal_codes [i]) . code_value) = (v); \ - ((ux_signal_codes [i]) . name) = (n); \ - i += 1; \ -} + (recovery_info . state) = s; \ + (recovery_info . pc_info_1) = arg1; \ + (recovery_info . pc_info_2) = arg2; \ +} while (0) static void -DEFUN_VOID (initialize_ux_signal_codes) -{ - unsigned int i = 0; - INITIALIZE_UX_SIGNAL_CODES (); - DECLARE_UX_SIGNAL_CODE (0, 0, 0, ((char *) 0)); -} - -static SCHEME_OBJECT -DEFUN (find_signal_code_name, (signo, info, scp), +DEFUN (continue_from_trap, (signo, info, scp), int signo AND SIGINFO_T info AND - struct FULL_SIGCONTEXT * scp) + FULL_SIGCONTEXT_T * scp) { - unsigned long code = 0; - char * name = 0; - if (SIGINFO_VALID_P (info)) - { - code = (SIGINFO_CODE (info)); -#ifdef SPECIAL_SIGNAL_CODE_NAMES - SPECIAL_SIGNAL_CODE_NAMES (); - if (name == 0) + unsigned long pc = (FULL_SIGCONTEXT_PC (scp)); + SCHEME_OBJECT primitive = (Registers[REGBLOCK_PRIMITIVE]); + SCHEME_OBJECT * block_addr; + int index; + SCHEME_OBJECT * new_sp = 0; + struct trap_recovery_info recovery_info; + +#ifdef PC_VALUE_MASK + pc &= PC_VALUE_MASK; #endif + + /* Choose new SP and encode location data. */ + switch (classify_pc (pc, (&block_addr), (&index))) + { + case pcl_primitive: + new_sp = sp_register; + SET_RECOVERY_INFO + (STATE_PRIMITIVE, + primitive, + (LONG_TO_UNSIGNED_FIXNUM (Registers[REGBLOCK_LEXPR_ACTUALS]))); + break; + + case pcl_heap: + case pcl_constant: + new_sp = ((SCHEME_OBJECT *) (FULL_SIGCONTEXT_SCHSP (scp))); + Free = ((SCHEME_OBJECT *) (FULL_SIGCONTEXT_RFREE (scp))); + SET_RECOVERY_INFO + (STATE_COMPILED_CODE, + (MAKE_POINTER_OBJECT (TC_COMPILED_CODE_BLOCK, block_addr)), + (LONG_TO_UNSIGNED_FIXNUM (pc - ((unsigned long) block_addr)))); + break; + + case pcl_utility: + new_sp = sp_register; + SET_RECOVERY_INFO + (STATE_UTILITY, + (LONG_TO_UNSIGNED_FIXNUM (index)), + UNSPECIFIC); + break; + + case pcl_builtin: + new_sp = ((SCHEME_OBJECT *) (FULL_SIGCONTEXT_SCHSP (scp))); + Free = ((SCHEME_OBJECT *) (FULL_SIGCONTEXT_RFREE (scp))); + SET_RECOVERY_INFO + (STATE_BUILTIN, + (LONG_TO_UNSIGNED_FIXNUM (index)), + UNSPECIFIC); + break; + + case pcl_unknown: + new_sp = 0; + SET_RECOVERY_INFO + (STATE_UNKNOWN, + (LONG_TO_UNSIGNED_FIXNUM (pc)), + UNSPECIFIC); + break; + } + + /* Sanity-check the new SP. */ + if (! ((Stack_Bottom <= new_sp) + && (new_sp < Stack_Top) + && (ALIGNED_P (new_sp)))) + new_sp = 0; + + /* Sanity-check Free. */ + if ((new_sp != 0) + && (Heap_Bottom <= Free) + && (Free < Heap_Top) + && (ALIGNED_P (Free))) + { + if (Free < MemTop) { - struct ux_sig_code_desc * entry = (& (ux_signal_codes [0])); - while ((entry -> signo) != 0) - if (((entry -> signo) == signo) - && (((entry -> code_mask) & code) == (entry -> code_value))) - { - name = (entry -> name); - break; - } - else - entry += 1; + Free += FREE_PARANOIA_MARGIN; + if (Free > MemTop) + Free = MemTop; } } - return (cons ((long_to_integer ((long) code)), - ((name == 0) ? SHARP_F - : (char_pointer_to_string ((unsigned char *) name))))); + else + Free = MemTop; + + /* Encode the registers. */ + (recovery_info . extra_trap_info) = + (MAKE_POINTER_OBJECT (TC_NON_MARKED_VECTOR, Free)); + (*Free++) = + (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR, (2 + FULL_SIGCONTEXT_NREGS))); + (*Free++) = ((SCHEME_OBJECT) pc); + (*Free++) = ((SCHEME_OBJECT) (FULL_SIGCONTEXT_SP (scp))); + { + unsigned long * scan + = ((unsigned long *) (FULL_SIGCONTEXT_FIRST_REG (scp))); + unsigned long * end = (scan + FULL_SIGCONTEXT_NREGS); + while (scan < end) + (*Free++) = ((SCHEME_OBJECT) (*scan++)); + } + + setup_trap_frame (signo, info, scp, (&recovery_info), new_sp); } -static void -DEFUN (setup_trap_frame, (signo, info, scp, trinfo, new_stack_pointer), - int signo AND - SIGINFO_T info AND - struct FULL_SIGCONTEXT * scp AND - struct trap_recovery_info * trinfo AND - SCHEME_OBJECT * new_stack_pointer) +/* Find the compiled code block in area that contains `pc'. + This attempts to be more efficient than `find_block_address_in_area'. + If the pointer is in the heap, it can actually do twice as + much work, but it is expected to pay off on the average. */ + +#define MINIMUM_SCAN_RANGE 2048 + +static SCHEME_OBJECT * +DEFUN (find_heap_address, (pc), unsigned long pc) { - SCHEME_OBJECT handler = SHARP_F; - SCHEME_OBJECT signal_name, signal_code; - int stack_recovered_p = (new_stack_pointer != 0); - long saved_mask = (FETCH_INTERRUPT_MASK ()); - SET_INTERRUPT_MASK (0); /* To prevent GC for now. */ - if ((! (Valid_Fixed_Obj_Vector ())) || - ((handler = (Get_Fixed_Obj_Slot (Trap_Handler))) == SHARP_F)) + SCHEME_OBJECT * pcp = ((SCHEME_OBJECT *) (pc &~ SCHEME_ALIGNMENT_MASK)); + unsigned long maximum_distance = (pcp - Heap_Bottom); + unsigned long distance = maximum_distance; + + while ((distance / 2) > MINIMUM_SCAN_RANGE) + distance = (distance / 2); + while (1) { - fprintf (stderr, "There is no trap handler for recovery!\n"); - fflush (stderr); - termination_trap (); + SCHEME_OBJECT * block + = (find_block_address_in_area (pcp, (pcp - distance))); + distance *= 2; + if ((block != 0) || (distance >= maximum_distance)) + return (block); } - if (Free > MemTop) - { - Request_GC (0); - } - signal_name = - ((signo == 0) - ? SHARP_F - : (char_pointer_to_string - ((unsigned char *) (find_signal_name (signo))))); - signal_code = (find_signal_code_name (signo, info, scp)); - if (!stack_recovered_p) +} + +static SCHEME_OBJECT * +DEFUN (find_constant_address, (pc), unsigned long pc) +{ + SCHEME_OBJECT * pcp = ((SCHEME_OBJECT *) (pc &~ SCHEME_ALIGNMENT_MASK)); + SCHEME_OBJECT * constant_block = (find_constant_space_block (pcp)); + return + ((constant_block != 0) + ? (find_block_address_in_area (pcp, constant_block)) + : 0); +} + +/* Find the compiled code block in area that contains `pc_value', + by scanning sequentially the complete area. + For the time being, skip over manifest closures and linkage sections. */ + +static SCHEME_OBJECT * +DEFUN (find_block_address_in_area, (pcp, area_start), + SCHEME_OBJECT * pcp AND + SCHEME_OBJECT * area_start) +{ + SCHEME_OBJECT * first_valid = area_start; + SCHEME_OBJECT * area = area_start; + + while (area < pcp) { - INITIALIZE_STACK (); - Will_Push (CONTINUATION_SIZE); - Store_Return (RC_END_OF_COMPUTATION); - exp_register = SHARP_F; - Save_Cont (); - Pushed (); - } - else - sp_register = new_stack_pointer; - Will_Push (7 + CONTINUATION_SIZE); - STACK_PUSH (trinfo -> extra_trap_info); - STACK_PUSH (trinfo -> pc_info_2); - STACK_PUSH (trinfo -> pc_info_1); - STACK_PUSH (trinfo -> state); - STACK_PUSH (BOOLEAN_TO_OBJECT (stack_recovered_p)); - STACK_PUSH (signal_code); - STACK_PUSH (signal_name); - Store_Return (RC_HARDWARE_TRAP); - exp_register = (long_to_integer (signo)); - Save_Cont (); - Pushed (); - if (stack_recovered_p - /* This may want to do it in other cases, but this may be enough. */ - && (trinfo->state == STATE_COMPILED_CODE)) - { - Stop_History (); - } - history_register = (Make_Dummy_History ()); - Will_Push (STACK_ENV_EXTRA_SLOTS + 2); - STACK_PUSH (signal_name); - STACK_PUSH (handler); - STACK_PUSH (STACK_FRAME_HEADER + 1); - Pushed (); - SET_INTERRUPT_MASK (saved_mask); - abort_to_interpreter (PRIM_APPLY); -} - -/* 0 is an invalid signal, it means a user requested reset. */ + SCHEME_OBJECT object = (*area); + switch (OBJECT_TYPE (object)) + { + case TC_LINKAGE_SECTION: + { + switch (READ_LINKAGE_KIND (object)) + { + case GLOBAL_OPERATOR_LINKAGE_KIND: + case OPERATOR_LINKAGE_KIND: + { + unsigned long count = (READ_OPERATOR_LINKAGE_COUNT (object)); + area = ((END_OPERATOR_LINKAGE_AREA (area, count)) + 1); + } + break; -void -DEFUN (hard_reset, (scp), struct FULL_SIGCONTEXT * scp) -{ - continue_from_trap (0, 0, scp); -} + default: + area += ((READ_CACHE_LINKAGE_COUNT (object)) + 1); + break; + } + } + break; -/* Called synchronously. */ + case TC_MANIFEST_CLOSURE: + { + area += 1; + { + unsigned long count = (MANIFEST_CLOSURE_COUNT (area)); + area = (MANIFEST_CLOSURE_END (area, count)); + } + } + break; -void -DEFUN_VOID (soft_reset) -{ - struct trap_recovery_info trinfo; - SCHEME_OBJECT * new_stack_pointer = - (((sp_register <= Stack_Top) && (sp_register > Stack_Guard)) - ? sp_register - : 0); - if ((Registers[REGBLOCK_PRIMITIVE]) != SHARP_F) - { - (trinfo . state) = STATE_PRIMITIVE; - (trinfo . pc_info_1) = (Registers[REGBLOCK_PRIMITIVE]); - (trinfo . pc_info_2) = - (LONG_TO_UNSIGNED_FIXNUM (Registers[REGBLOCK_LEXPR_ACTUALS])); - (trinfo . extra_trap_info) = SHARP_F; - } - else - { - (trinfo . state) = STATE_UNKNOWN; - (trinfo . pc_info_1) = SHARP_F; - (trinfo . pc_info_2) = SHARP_F; - (trinfo . extra_trap_info) = SHARP_F; + case TC_MANIFEST_NM_VECTOR: + { + unsigned long count = (OBJECT_DATUM (object)); + if ((area + (count + 1)) < pcp) + { + area += (count + 1); + first_valid = area; + } + else + { + SCHEME_OBJECT * block = (area - 1); + return + (((area != first_valid) + && (((OBJECT_TYPE (*block)) == TC_MANIFEST_VECTOR) + || ((OBJECT_TYPE (*block)) == FIXNUM_MARKER)) + && ((OBJECT_DATUM (*block)) >= (count + 1)) + && (PLAUSIBLE_CC_BLOCK_P (block))) + ? block + : 0); + } + } + break; + + default: + area += 1; + break; + } } - if ((Free >= Heap_Top) || (Free < Heap_Bottom)) - /* Let's hope this works. */ - Free = MemTop; - setup_trap_frame (0, 0, 0, (&trinfo), new_stack_pointer); + return (0); } - -#ifdef HAS_COMPILER_SUPPORT -# include "gccode.h" -#endif - -#if defined(HAVE_STRUCT_SIGCONTEXT) && defined(HAS_COMPILER_SUPPORT) && !defined(USE_STACKLETS) -# define ENABLE_TRAP_RECOVERY 1 -#endif - -#ifndef ENABLE_TRAP_RECOVERY + +#else /* not ENABLE_TRAP_RECOVERY */ static struct trap_recovery_info dummy_recovery_info = { @@ -414,455 +574,228 @@ static void DEFUN (continue_from_trap, (signo, info, scp), int signo AND SIGINFO_T info AND - struct FULL_SIGCONTEXT * scp) + FULL_SIGCONTEXT_T * scp) { if (Free < MemTop) - { Free = MemTop; - } setup_trap_frame (signo, info, scp, (&dummy_recovery_info), 0); } -SCHEME_OBJECT * -DEFUN (find_block_address, (pc_value, area_start), - char * pc_value AND - SCHEME_OBJECT * area_start) +static SCHEME_OBJECT * +DEFUN (find_heap_address, (pc), unsigned long pc) { return (0); } -#else /* ENABLE_TRAP_RECOVERY */ - -/* Heuristic recovery from Unix signals (traps). - - continue_from_trap attempts to: - - 1) validate the trap information (pc and sp); - 2) determine whether compiled code was executing, a primitive was - executing, or execution was in the interpreter; - 3) guess what C global state is still valid; and - 4) set up a recovery frame for the interpreter so that debuggers can - display more information. */ - -#define SCHEME_ALIGNMENT_MASK ((sizeof (long)) - 1) -#define STACK_ALIGNMENT_MASK SCHEME_ALIGNMENT_MASK -#define FREE_PARANOIA_MARGIN 0x100 - -#define C_STACK_SIZE 0x01000000 +static SCHEME_OBJECT * +DEFUN (find_constant_address, (pc), unsigned long pc) +{ + return (0); +} +#endif /* not ENABLE_TRAP_RECOVERY */ + static void -DEFUN (continue_from_trap, (signo, info, scp), +DEFUN (setup_trap_frame, (signo, info, scp, trinfo, new_stack_pointer), int signo AND SIGINFO_T info AND - struct FULL_SIGCONTEXT * scp) + FULL_SIGCONTEXT_T * scp AND + struct trap_recovery_info * trinfo AND + SCHEME_OBJECT * new_stack_pointer) { - int pc_in_builtin; - int builtin_index; - int pc_in_C; - int pc_in_heap; - int pc_in_constant_space; - int pc_in_scheme; - int pc_in_hyper_space; - int pc_in_utility; - int utility_index; - int scheme_sp_valid; - long C_sp = (FULL_SIGCONTEXT_SP (scp)); - long scheme_sp = (FULL_SIGCONTEXT_SCHSP (scp)); - long the_pc = ((FULL_SIGCONTEXT_PC (scp)) & PC_VALUE_MASK); - SCHEME_OBJECT * new_stack_pointer; - SCHEME_OBJECT * xtra_info; - struct trap_recovery_info trinfo; - extern int EXFUN (pc_to_utility_index, (unsigned long)); - extern int EXFUN (pc_to_builtin_index, (unsigned long)); + unsigned long saved_mask = (FETCH_INTERRUPT_MASK ()); + SCHEME_OBJECT handler; + SCHEME_OBJECT signal_name; - if ((the_pc & PC_ALIGNMENT_MASK) != 0) - { - pc_in_builtin = 0; - pc_in_utility = 0; - pc_in_C = 0; - pc_in_heap = 0; - pc_in_constant_space = 0; - pc_in_scheme = 0; - pc_in_hyper_space = 1; - } - else - { - builtin_index = (pc_to_builtin_index (the_pc)); - pc_in_builtin = (builtin_index != -1); - utility_index = (pc_to_utility_index (the_pc)); - pc_in_utility = (utility_index != -1); - pc_in_C = ((the_pc <= ((long) (get_etext ()))) && (!pc_in_builtin)); - pc_in_heap = ADDRESS_HEAP_P ((SCHEME_OBJECT*) the_pc); - pc_in_constant_space = ADDRESS_CONSTANT_P ((SCHEME_OBJECT*) the_pc); - pc_in_scheme = (pc_in_heap || pc_in_constant_space || pc_in_builtin); - pc_in_hyper_space = ((!pc_in_C) && (!pc_in_scheme)); - } - - scheme_sp_valid = - (pc_in_scheme - && ((scheme_sp < ((long) Stack_Top)) && - (scheme_sp >= ((long) Stack_Bottom)) && - ((scheme_sp & STACK_ALIGNMENT_MASK) == 0))); - - new_stack_pointer = - (scheme_sp_valid - ? ((SCHEME_OBJECT *) scheme_sp) - : (pc_in_C && (sp_register < Stack_Top) - && (sp_register > Stack_Bottom)) - ? sp_register - : ((SCHEME_OBJECT *) 0)); + SET_INTERRUPT_MASK (0); /* To prevent GC for now. */ - if (pc_in_hyper_space || (pc_in_scheme && ALLOW_ONLY_C)) - { - /* In hyper space. */ - (trinfo . state) = STATE_UNKNOWN; - (trinfo . pc_info_1) = SHARP_F; - (trinfo . pc_info_2) = SHARP_F; - new_stack_pointer = 0; - if ((Free < MemTop) || - (Free >= Heap_Top) || - ((((unsigned long) Free) & SCHEME_ALIGNMENT_MASK) != 0)) - Free = MemTop; - } - else if (pc_in_scheme) - { - /* In compiled code. */ - SCHEME_OBJECT * block_addr; -#ifdef HAVE_FULL_SIGCONTEXT - SCHEME_OBJECT * maybe_free; -#endif - block_addr = - (pc_in_builtin - ? ((SCHEME_OBJECT *) NULL) - : (find_block_address (((PTR) the_pc), - (pc_in_heap ? Heap_Bottom : Constant_Space)))); - if (block_addr != ((SCHEME_OBJECT *) NULL)) - { - (trinfo . state) = STATE_COMPILED_CODE; - (trinfo . pc_info_1) = - (MAKE_POINTER_OBJECT (TC_COMPILED_CODE_BLOCK, block_addr)); - (trinfo . pc_info_2) = - (LONG_TO_UNSIGNED_FIXNUM (the_pc - ((long) block_addr))); - } - else if (pc_in_builtin) + handler = SHARP_F; + if (Valid_Fixed_Obj_Vector ()) + handler = (Get_Fixed_Obj_Slot (Trap_Handler)); + if (handler == SHARP_F) { - (trinfo . state) = STATE_BUILTIN; - (trinfo . pc_info_1) = (LONG_TO_UNSIGNED_FIXNUM (builtin_index)); - (trinfo . pc_info_2) = SHARP_T; - } - else - { - (trinfo . state) = STATE_PROBABLY_COMPILED; - (trinfo . pc_info_1) = (LONG_TO_UNSIGNED_FIXNUM (the_pc)); - (trinfo . pc_info_2) = SHARP_F; + fprintf (stderr, "There is no trap handler for recovery!\n"); + fflush (stderr); + termination_trap (); } - if ((block_addr == ((SCHEME_OBJECT *) NULL)) && (! pc_in_builtin)) - { - if ((Free < MemTop) || - (Free >= Heap_Top) || - ((((unsigned long) Free) & SCHEME_ALIGNMENT_MASK) != 0)) - Free = MemTop; - } - else - { -#ifdef HAVE_FULL_SIGCONTEXT - maybe_free = ((SCHEME_OBJECT *) (FULL_SIGCONTEXT_RFREE (scp))); - if (((((unsigned long) maybe_free) & SCHEME_ALIGNMENT_MASK) == 0) - && (maybe_free >= Heap_Bottom) && (maybe_free < Heap_Top)) - Free = (maybe_free + FREE_PARANOIA_MARGIN); - else -#endif - if ((Free < MemTop) || (Free >= Heap_Top) - || ((((unsigned long) Free) & SCHEME_ALIGNMENT_MASK) != 0)) - Free = MemTop; - } - } - else /* pc_in_C */ - { - /* In the interpreter, a primitive, or a compiled code utility. */ + signal_name = + ((signo != 0) + ? (char_pointer_to_string ((unsigned char *) (find_signal_name (signo)))) + : SHARP_F); - SCHEME_OBJECT primitive = (Registers[REGBLOCK_PRIMITIVE]); + if (Free > MemTop) + Request_GC (0); - if (pc_in_utility) - { - (trinfo . state) = STATE_UTILITY; - (trinfo . pc_info_1) = (LONG_TO_UNSIGNED_FIXNUM (utility_index)); - (trinfo . pc_info_2) = UNSPECIFIC; - } - else if ((OBJECT_TYPE (primitive)) != TC_PRIMITIVE) - { - (trinfo . state) = STATE_UNKNOWN; - (trinfo . pc_info_1) = SHARP_F; - (trinfo . pc_info_2) = SHARP_F; - new_stack_pointer = 0; - } - else + if (new_stack_pointer != 0) + sp_register = new_stack_pointer; + else { - (trinfo . state) = STATE_PRIMITIVE; - (trinfo . pc_info_1) = primitive; - (trinfo . pc_info_2) = - (LONG_TO_UNSIGNED_FIXNUM (Registers[REGBLOCK_LEXPR_ACTUALS])); + INITIALIZE_STACK (); + Will_Push (CONTINUATION_SIZE); + Store_Return (RC_END_OF_COMPUTATION); + exp_register = SHARP_F; + Save_Cont (); + Pushed (); } - if ((new_stack_pointer == 0) - || ((((unsigned long) Free) & SCHEME_ALIGNMENT_MASK) != 0) - || ((Free < Heap_Bottom) || (Free >= Heap_Top)) - || ((Free < MemTop) && ((Free + FREE_PARANOIA_MARGIN) >= MemTop))) - Free = MemTop; - else if ((Free + FREE_PARANOIA_MARGIN) < MemTop) - Free += FREE_PARANOIA_MARGIN; - } - xtra_info = Free; - Free += (1 + 2 + PROCESSOR_NREGS); - (trinfo . extra_trap_info) = - (MAKE_POINTER_OBJECT (TC_NON_MARKED_VECTOR, xtra_info)); - (*xtra_info++) = - (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR, (2 + PROCESSOR_NREGS))); - (*xtra_info++) = ((SCHEME_OBJECT) the_pc); - (*xtra_info++) = ((SCHEME_OBJECT) C_sp); - { - int counter = FULL_SIGCONTEXT_NREGS; - long * regs = ((long *) (FULL_SIGCONTEXT_FIRST_REG (scp))); - while ((counter--) > 0) - (*xtra_info++) = ((SCHEME_OBJECT) (*regs++)); - } - /* We assume that regs,sp,pc is the order in the processor. - Scheme can always fix this. */ - if ((PROCESSOR_NREGS - FULL_SIGCONTEXT_NREGS) > 0) - (*xtra_info++) = ((SCHEME_OBJECT) C_sp); - if ((PROCESSOR_NREGS - FULL_SIGCONTEXT_NREGS) > 1) - (*xtra_info++) = ((SCHEME_OBJECT) the_pc); - setup_trap_frame (signo, info, scp, (&trinfo), new_stack_pointer); -} -/* Find the compiled code block in area which contains `pc_value'. - This attempts to be more efficient than `find_block_address_in_area'. - If the pointer is in the heap, it can actually do twice as - much work, but it is expected to pay off on the average. */ + Will_Push (7 + CONTINUATION_SIZE); + STACK_PUSH (trinfo -> extra_trap_info); + STACK_PUSH (trinfo -> pc_info_2); + STACK_PUSH (trinfo -> pc_info_1); + STACK_PUSH (trinfo -> state); + STACK_PUSH (BOOLEAN_TO_OBJECT (new_stack_pointer != 0)); + STACK_PUSH (find_signal_code_name (signo, info, scp)); + STACK_PUSH (signal_name); + Store_Return (RC_HARDWARE_TRAP); + exp_register = (long_to_integer (signo)); + Save_Cont (); + Pushed (); -static SCHEME_OBJECT * EXFUN - (find_block_address_in_area, (char * pc_value, SCHEME_OBJECT * area_start)); + if ((new_stack_pointer != 0) + /* This may want to do it in other cases, but this may be enough. */ + && ((trinfo -> state) == STATE_COMPILED_CODE)) + Stop_History (); + history_register = (Make_Dummy_History ()); -#define MINIMUM_SCAN_RANGE 2048 + Will_Push (STACK_ENV_EXTRA_SLOTS + 2); + STACK_PUSH (signal_name); + STACK_PUSH (handler); + STACK_PUSH (STACK_FRAME_HEADER + 1); + Pushed (); -SCHEME_OBJECT * -DEFUN (find_block_address, (pc_value, area_start), - char * pc_value AND - SCHEME_OBJECT * area_start) + SET_INTERRUPT_MASK (saved_mask); + abort_to_interpreter (PRIM_APPLY); +} + +static void +DEFUN_VOID (initialize_ux_signal_codes) { - if (area_start == Constant_Space) - { - extern SCHEME_OBJECT * EXFUN - (find_constant_space_block, (SCHEME_OBJECT *)); - SCHEME_OBJECT * constant_block = - (find_constant_space_block - ((SCHEME_OBJECT *) - (((unsigned long) pc_value) &~ SCHEME_ALIGNMENT_MASK))); - return - ((constant_block == 0) - ? 0 - : (find_block_address_in_area (pc_value, constant_block))); - } - { - SCHEME_OBJECT * nearest_word = - ((SCHEME_OBJECT *) - (((unsigned long) pc_value) &~ SCHEME_ALIGNMENT_MASK)); - long maximum_distance = (nearest_word - area_start); - long distance = maximum_distance; - while ((distance / 2) > MINIMUM_SCAN_RANGE) - distance = (distance / 2); - while ((distance * 2) < maximum_distance) - { - SCHEME_OBJECT * block = - (find_block_address_in_area (pc_value, (nearest_word - distance))); - if (block != 0) - return (block); - distance *= 2; - } - } - return (find_block_address_in_area (pc_value, area_start)); + unsigned int i = 0; + INITIALIZE_UX_SIGNAL_CODES (); + DECLARE_UX_SIGNAL_CODE (0, 0, 0, ((char *) 0)); } -/* - Find the compiled code block in area which contains `pc_value', - by scanning sequentially the complete area. - For the time being, skip over manifest closures and linkage sections. */ - -static SCHEME_OBJECT * -DEFUN (find_block_address_in_area, (pc_value, area_start), - char * pc_value AND - SCHEME_OBJECT * area_start) +static SCHEME_OBJECT +DEFUN (find_signal_code_name, (signo, info, scp), + int signo AND + SIGINFO_T info AND + FULL_SIGCONTEXT_T * scp) { - SCHEME_OBJECT * first_valid = area_start; - SCHEME_OBJECT * area = area_start; - while (((char *) area) < pc_value) + unsigned long code = 0; + char * name = 0; + if (SIGINFO_VALID_P (info)) { - SCHEME_OBJECT object = (*area); - switch (OBJECT_TYPE (object)) + code = (SIGINFO_CODE (info)); + SPECIAL_SIGNAL_CODE_NAMES (); + if (name == 0) { - case TC_LINKAGE_SECTION: - { - switch (READ_LINKAGE_KIND (object)) - { - case GLOBAL_OPERATOR_LINKAGE_KIND: - case OPERATOR_LINKAGE_KIND: + struct ux_sig_code_desc * entry = (& (ux_signal_codes[0])); + while ((entry -> signo) != 0) + if (((entry -> signo) == signo) + && (((entry -> code_mask) & code) == (entry -> code_value))) { - long count = (READ_OPERATOR_LINKAGE_COUNT (object)); - area = ((END_OPERATOR_LINKAGE_AREA (area, count)) + 1); + name = (entry -> name); break; } - - default: -#if FALSE - { - gc_death (TERM_EXIT, - "find_block_address: Unknown compiler linkage kind.", - area, NULL); - /*NOTREACHED*/ - } -#else - /* Fall through, no reason to crash here. */ -#endif - case ASSIGNMENT_LINKAGE_KIND: - case CLOSURE_PATTERN_LINKAGE_KIND: - case REFERENCE_LINKAGE_KIND: - area += ((READ_CACHE_LINKAGE_COUNT (object)) + 1); - break; - + else + entry += 1; + } + } + return + (cons ((ulong_to_integer (code)), + ((name == 0) + ? SHARP_F + : (char_pointer_to_string ((unsigned char *) name))))); +} + +static enum pc_location +DEFUN (classify_pc, (pc, r_block_addr, r_index), + unsigned long pc AND + SCHEME_OBJECT ** r_block_addr AND + unsigned int * r_index) +{ + if (PC_ALIGNED_P (pc)) + { + if (ADDRESS_HEAP_P ((SCHEME_OBJECT *) pc)) + { + SCHEME_OBJECT * block_addr = (find_heap_address (pc)); + if (block_addr != 0) + { + if (r_block_addr != 0) + (*r_block_addr) = block_addr; + return (pcl_heap); } - break; - } - case TC_MANIFEST_CLOSURE: - { - area += 1; + } + else if (ADDRESS_CONSTANT_P ((SCHEME_OBJECT *) pc)) + { + SCHEME_OBJECT * block_addr = (find_constant_address (pc)); + if (block_addr != 0) { - long count = (MANIFEST_CLOSURE_COUNT (area)); - area = (MANIFEST_CLOSURE_END (area, count)); + if (r_block_addr != 0) + (*r_block_addr) = block_addr; + return (pcl_constant); } - break; - } - case TC_MANIFEST_NM_VECTOR: - { - long count = (OBJECT_DATUM (object)); - if (((char *) (area + (count + 1))) < pc_value) - { - area += (count + 1); - first_valid = area; - break; - } + } + else if (ADDRESS_UCODE_P (pc)) + { + int index = (pc_to_builtin_index (pc)); + if (index >= 0) { - SCHEME_OBJECT * block = (area - 1); - return - (((area == first_valid) || - (((OBJECT_TYPE (*block)) != TC_MANIFEST_VECTOR) - && ((OBJECT_TYPE (*block)) != -#ifdef TC_POSITIVE_FIXNUM - TC_POSITIVE_FIXNUM -#else - TC_FIXNUM -#endif - )) - || - ((OBJECT_DATUM (*block)) < (count + 1)) || - (! (PLAUSIBLE_CC_BLOCK_P (block)))) - ? 0 - : block); + if (r_index != 0) + (*r_index) = index; + return (pcl_builtin); } - } - default: - { - area += 1; - break; - } + index = (pc_to_utility_index (pc)); + if (index >= 0) + { + if (r_index != 0) + (*r_index) = index; + return (pcl_utility); + } + if ((OBJECT_TYPE (Registers[REGBLOCK_PRIMITIVE])) == TC_PRIMITIVE) + return (pcl_primitive); } } - return (0); + return (pcl_unknown); } - -#endif /* ENABLE_TRAP_RECOVERY */ -SCHEME_OBJECT -DEFUN (find_ccblock, (the_pc), - long the_pc) +static void +DEFUN_VOID (trap_normal_termination) { - int pc_in_builtin; - int builtin_index; - int pc_in_C; - int pc_in_heap; - int pc_in_constant_space; - int pc_in_scheme; - int pc_in_hyper_space; - int pc_in_utility; - int utility_index; - extern int EXFUN (pc_to_utility_index, (unsigned long)); - extern int EXFUN (pc_to_builtin_index, (unsigned long)); - - if ((the_pc & PC_ALIGNMENT_MASK) != 0) - { - pc_in_builtin = 0; - pc_in_utility = 0; - pc_in_C = 0; - pc_in_heap = 0; - pc_in_constant_space = 0; - pc_in_scheme = 0; - pc_in_hyper_space = 1; - } - else - { - builtin_index = (pc_to_builtin_index (the_pc)); - pc_in_builtin = (builtin_index != -1); - utility_index = (pc_to_utility_index (the_pc)); - pc_in_utility = (utility_index != -1); - pc_in_C = ((the_pc <= ((long) (get_etext ()))) && (!pc_in_builtin)); - pc_in_heap = ADDRESS_HEAP_P ((SCHEME_OBJECT*) the_pc); - pc_in_constant_space = ADDRESS_CONSTANT_P ((SCHEME_OBJECT*) the_pc); - pc_in_scheme = (pc_in_heap || pc_in_constant_space || pc_in_builtin); - pc_in_hyper_space = ((!pc_in_C) && (!pc_in_scheme)); - } - - if (pc_in_hyper_space || (pc_in_scheme && ALLOW_ONLY_C)) - { - return SHARP_F; - } - else if (pc_in_scheme) - { - /* In compiled code. */ - SCHEME_OBJECT * block_addr; - block_addr = - (pc_in_builtin - ? ((SCHEME_OBJECT *) NULL) - : (find_block_address (((PTR) the_pc), - (pc_in_heap ? Heap_Bottom : Constant_Space)))); - if (block_addr != ((SCHEME_OBJECT *) NULL)) - { - return MAKE_POINTER_OBJECT (TC_COMPILED_CODE_BLOCK, block_addr); - } - else if (pc_in_builtin) - { - return SHARP_F; - } - else - { - return SHARP_F; - } - } - else /* pc_in_C */ - { - /* In the interpreter, a primitive, or a compiled code utility. */ + trap_state = trap_state_exitting_soft; + termination_trap (); +} - SCHEME_OBJECT primitive = (Registers[REGBLOCK_PRIMITIVE]); +static void +DEFUN_VOID (trap_immediate_termination) +{ + trap_state = trap_state_exitting_hard; + OS_restore_external_state (); + exit (1); +} - if (pc_in_utility) - { - return SHARP_F; - } - else if ((OBJECT_TYPE (primitive)) != TC_PRIMITIVE) +static void +DEFUN_VOID (trap_dump_core) +{ + if (! (option_disable_core_dump)) + UX_dump_core (); + else { - return SHARP_F; + fputs (">> Core dumps are disabled - Terminating normally.\n", stdout); + fflush (stdout); + termination_trap (); } - else +} + +static void +DEFUN_VOID (trap_recover) +{ + if (WITHIN_CRITICAL_SECTION_P ()) { - return SHARP_F; + CLEAR_CRITICAL_SECTION_HOOK (); + EXIT_CRITICAL_SECTION ({}); } - } + reset_interruptable_extent (); + continue_from_trap (saved_signo, saved_info, saved_scp); } diff --git a/v7/src/microcode/uxtrap.h b/v7/src/microcode/uxtrap.h index 89b569810..29c6cbd16 100644 --- a/v7/src/microcode/uxtrap.h +++ b/v7/src/microcode/uxtrap.h @@ -1,9 +1,9 @@ /* -*-C-*- -$Id: uxtrap.h,v 1.33 2004/12/15 02:34:46 cph Exp $ +$Id: uxtrap.h,v 1.34 2005/06/26 04:35:11 cph Exp $ Copyright 1990,1991,1992,1993,1996,1998 Massachusetts Institute of Technology -Copyright 2000,2001,2004 Massachusetts Institute of Technology +Copyright 2000,2001,2004,2005 Massachusetts Institute of Technology This file is part of MIT/GNU Scheme. @@ -37,12 +37,10 @@ USA. #include #include -#define HAVE_FULL_SIGCONTEXT -#define PROCESSOR_NREGS 16 #define FULL_SIGCONTEXT_NREGS GPR_REGS /* Missing sp */ #define RFREE AR5 -#define SIGCONTEXT full_sigcontext +#define SIGCONTEXT_T struct full_sigcontext #define SIGCONTEXT_SP(scp) ((scp)->fs_context.sc_sp) #define SIGCONTEXT_PC(scp) ((scp)->fs_context.sc_pc) #define FULL_SIGCONTEXT_RFREE(scp) ((scp)->fs_regs[RFREE]) @@ -113,8 +111,6 @@ both, we use the no-siginfo way */ /* See included by */ -# define HAVE_FULL_SIGCONTEXT - # ifndef sc_pc # define sc_pc sc_pcoq_head # endif /* sc_pc */ @@ -127,7 +123,6 @@ both, we use the no-siginfo way */ # define FULL_SIGCONTEXT_SCHSP(scp) ((scp)->sc_sl.sl_ss.ss_schsp) # define FULL_SIGCONTEXT_FIRST_REG(scp) (&((scp)->sc_sl.sl_ss.ss_gr0)) # define FULL_SIGCONTEXT_NREGS 32 -# define PROCESSOR_NREGS 32 # define INITIALIZE_UX_SIGNAL_CODES() \ { \ @@ -196,8 +191,6 @@ both, we use the no-siginfo way */ #ifdef sun3 -#define HAVE_FULL_SIGCONTEXT -#define PROCESSOR_NREGS 16 #define FULL_SIGCONTEXT_NREGS 15 /* missing sp */ struct full_sigcontext @@ -207,14 +200,13 @@ struct full_sigcontext }; #define RFREE (8 + 5) /* A5 */ -#define FULL_SIGCONTEXT full_sigcontext +#define FULL_SIGCONTEXT_T struct full_sigcontext #define FULL_SIGCONTEXT_SP(scp) (scp->fs_original->sc_sp) #define FULL_SIGCONTEXT_PC(scp) (scp->fs_original->sc_pc) #define FULL_SIGCONTEXT_RFREE(scp) (scp->fs_regs[RFREE]) #define FULL_SIGCONTEXT_FIRST_REG(scp) (&((scp)->fs_regs[0])) -#define DECLARE_FULL_SIGCONTEXT(name) \ - struct FULL_SIGCONTEXT name [1] +#define DECLARE_FULL_SIGCONTEXT(name) FULL_SIGCONTEXT_T name [1] #define INITIALIZE_FULL_SIGCONTEXT(partial, full) \ { \ @@ -227,8 +219,6 @@ struct full_sigcontext #ifdef vax -#define HAVE_FULL_SIGCONTEXT -#define PROCESSOR_NREGS 16 #define FULL_SIGCONTEXT_NREGS 16 struct full_sigcontext @@ -238,14 +228,13 @@ struct full_sigcontext }; #define RFREE 12 /* fp */ -#define FULL_SIGCONTEXT full_sigcontext +#define FULL_SIGCONTEXT_T struct full_sigcontext #define FULL_SIGCONTEXT_SP(scp) ((scp)->fs_original->sc_sp) #define FULL_SIGCONTEXT_PC(scp) ((scp)->fs_original->sc_pc) #define FULL_SIGCONTEXT_RFREE(scp) ((scp)->fs_regs[RFREE]) #define FULL_SIGCONTEXT_FIRST_REG(scp) (&((scp)->fs_regs[0])) -#define DECLARE_FULL_SIGCONTEXT(name) \ - struct FULL_SIGCONTEXT name [1] +#define DECLARE_FULL_SIGCONTEXT(name) FULL_SIGCONTEXT_T name [1] /* r0 has to be kludged. */ @@ -277,12 +266,10 @@ struct full_sigcontext #define sc_rfree sc_regs[9] #define sc_schsp sc_regs[3] -#define HAVE_FULL_SIGCONTEXT #define FULL_SIGCONTEXT_RFREE(scp) ((scp)->sc_rfree) #define FULL_SIGCONTEXT_SCHSP(scp) ((scp)->sc_schsp) #define FULL_SIGCONTEXT_FIRST_REG(scp) (&((scp)->sc_regs[0])) #define FULL_SIGCONTEXT_NREGS 32 -#define PROCESSOR_NREGS 32 #define INITIALIZE_UX_SIGNAL_CODES() \ { \ @@ -314,12 +301,10 @@ struct full_sigcontext #define sc_rfree sc_regs[9] #define sc_schsp sc_regs[3] -#define HAVE_FULL_SIGCONTEXT #define FULL_SIGCONTEXT_RFREE(scp) ((scp)->sc_rfree) #define FULL_SIGCONTEXT_SCHSP(scp) ((scp)->sc_schsp) #define FULL_SIGCONTEXT_FIRST_REG(scp) (&((scp)->sc_regs[0])) #define FULL_SIGCONTEXT_NREGS 32 -#define PROCESSOR_NREGS 32 #define INITIALIZE_UX_SIGNAL_CODES() \ { \ @@ -367,16 +352,14 @@ struct full_sigcontext #define SIGINFO_VALID_P(info) ((info) != 0) #define SIGINFO_CODE(info) ((info) -> si_code) -#define SIGCONTEXT ucontext +#define SIGCONTEXT_T ucontext_t #define SIGCONTEXT_SP(scp) ((((scp) -> uc_mcontext) . gregs) [CXT_SP]) #define SIGCONTEXT_PC(scp) ((((scp) -> uc_mcontext) . gregs) [CXT_EPC]) -#define HAVE_FULL_SIGCONTEXT #define FULL_SIGCONTEXT_RFREE(scp) ((((scp) -> uc_mcontext) . gregs) [CXT_T1]) #define FULL_SIGCONTEXT_SCHSP(scp) ((((scp) -> uc_mcontext) . gregs) [CXT_V1]) #define FULL_SIGCONTEXT_FIRST_REG(scp) (((scp) -> uc_mcontext) . gregs) #define FULL_SIGCONTEXT_NREGS NGREG -#define PROCESSOR_NREGS NGREG #define INITIALIZE_UX_SIGNAL_CODES() \ { \ @@ -426,16 +409,17 @@ struct full_sigcontext #define SIGINFO_VALID_P(info) ((info) != 0) #define SIGINFO_CODE(info) ((info) -> si_code) -#define SIGCONTEXT sigcontext -#define SIGCONTEXT_SP(scp) ((scp) -> esp) -#define SIGCONTEXT_PC(scp) ((scp) -> eip) +#define SIGCONTEXT_T ucontext_t +#define __SIGCONTEXT_REG(scp, ir) \ + ((unsigned long) ((((scp) -> uc_mcontext) . gregs) [(ir)])) + +#define SIGCONTEXT_SP(scp) (__SIGCONTEXT_REG (scp, REG_ESP)) +#define SIGCONTEXT_PC(scp) (__SIGCONTEXT_REG (scp, REG_EIP)) -#define HAVE_FULL_SIGCONTEXT /* Grab them all. Nobody looks at them, but grab them anyway. */ -#define PROCESSOR_NREGS 19 -#define FULL_SIGCONTEXT_NREGS 19 -#define FULL_SIGCONTEXT_FIRST_REG(scp) (scp) -#define FULL_SIGCONTEXT_RFREE(scp) ((scp) -> edi) +#define FULL_SIGCONTEXT_NREGS NGREG +#define FULL_SIGCONTEXT_FIRST_REG(scp) (((scp) -> uc_mcontext) . gregs) +#define FULL_SIGCONTEXT_RFREE(scp) (__SIGCONTEXT_REG (scp, REG_EDI)) #define INITIALIZE_UX_SIGNAL_CODES() \ { \ @@ -473,65 +457,15 @@ struct full_sigcontext (SIGILL, (~ 0L), ILL_BADSTK, "bad stack trap"); \ } -#if 0 -/* In versions of Linux prior to 2.2 (?), signal handlers are called - with one argument -- the `signo'. There's an alleged "iBCS signal - stack" register dump just above it. Thus, the fictitious `info' - argument to the handler is actually the first member of this - register dump (described by struct linux_sigcontext, below). - Unfortunately, kludging SIGINFO_CODE to access the sc_trapno will - fail later on when looking at the saved_info. */ -#define SIGINFO_T long -#define SIGINFO_VALID_P(info) (0) -#define SIGINFO_CODE(info) (0) - -/* Here's the "iBCS signal stack", whatever that means. */ -struct linux_sigcontext { - long sc_gs, sc_fs, sc_es, sc_ds, sc_edi, sc_esi, sc_ebp, sc_esp, sc_ebx; - long sc_edx, sc_ecx, sc_eax, sc_trapno, sc_err, sc_eip, sc_cs, sc_eflags; - long sc_esp_again, sc_ss; -}; - -/* INITIALIZE_FULL_SIGCONTEXT gives us a chance to generate a pointer to - the register dump, since it is used at the beginning of STD_HANDLER's. - In terms of the expected arguments to the STD_ signal HANDLER's, the - register dump is right above `signo', at `info', one long below `pscp', - which is what INITIALIZE_FULL_SIGCONTEXT is getting for `partial'. - Thus, our pointer to a `full'_SIGCONTEXT is initialized to the address - of `partial' minus 1 long. */ -#define HAVE_FULL_SIGCONTEXT -#define DECLARE_FULL_SIGCONTEXT(name) \ - struct FULL_SIGCONTEXT * name -#define INITIALIZE_FULL_SIGCONTEXT(partial, full) \ - ((full) = ((struct FULL_SIGCONTEXT *) (((long *)&(partial))-1))) - -/* Grab them all. Nobody looks at them, but grab them anyway. */ -#define PROCESSOR_NREGS 19 -#define FULL_SIGCONTEXT_NREGS 19 -#define FULL_SIGCONTEXT_FIRST_REG(scp) (scp) - -#define SIGCONTEXT linux_sigcontext -#define SIGCONTEXT_SP(scp) ((scp)->sc_esp) -#define SIGCONTEXT_PC(scp) ((scp)->sc_eip) - -#define FULL_SIGCONTEXT SIGCONTEXT -#define FULL_SIGCONTEXT_SP SIGCONTEXT_SP -#define FULL_SIGCONTEXT_PC SIGCONTEXT_PC -#define FULL_SIGCONTEXT_RFREE(scp) ((scp)->sc_edi) - -#endif /* 0 */ - #endif /* __linux__ */ #ifdef _MACH_UNIX /* The following are true for Mach (BSD 4.3 compatible). I don't know about SCO or other versions. */ -#define HAVE_FULL_SIGCONTEXT -#define PROCESSOR_NREGS 8 #define FULL_SIGCONTEXT_NREGS 8 -#define SIGCONTEXT sigcontext +#define SIGCONTEXT_T struct sigcontext #define SIGCONTEXT_SP(scp) ((scp)->sc_esp) #define SIGCONTEXT_PC(scp) ((scp)->sc_eip) #define FULL_SIGCONTEXT_RFREE(scp) ((scp)->sc_edi) @@ -549,14 +483,11 @@ struct linux_sigcontext { #define sc_rfree sc_regs[4] #define sc_schsp sc_regs[2] -#define HAVE_FULL_SIGCONTEXT #define FULL_SIGCONTEXT_RFREE(scp) ((scp)->sc_rfree) #define FULL_SIGCONTEXT_SCHSP(scp) ((scp)->sc_schsp) #define FULL_SIGCONTEXT_FIRST_REG(scp) (&((scp)->sc_regs[0])) #define FULL_SIGCONTEXT_NREGS 32 -#define PROCESSOR_NREGS 32 - #ifdef FPE_COMPLETE_FAULT #define STUPID_FIRST_SIGNAL() \ DECLARE_UX_SIGNAL_CODE \ @@ -588,7 +519,7 @@ struct linux_sigcontext { #ifdef _AIX /* For now */ -# define SIGCONTEXT sigcontext +# define SIGCONTEXT_T struct sigcontext # define SIGCONTEXT_SP(scp) 0 # define SIGCONTEXT_PC(scp) 0 #endif /* _AIX */ @@ -603,19 +534,19 @@ struct linux_sigcontext { struct sigcontext { long sc_sp; long sc_pc; }; #endif -#ifndef SIGCONTEXT -# define SIGCONTEXT sigcontext +#ifndef SIGCONTEXT_T +# define SIGCONTEXT_T struct sigcontext # define SIGCONTEXT_SP(scp) ((scp) -> sc_sp) # define SIGCONTEXT_PC(scp) ((scp) -> sc_pc) #endif -#ifndef FULL_SIGCONTEXT -# define FULL_SIGCONTEXT SIGCONTEXT +#ifndef FULL_SIGCONTEXT_T +# define FULL_SIGCONTEXT_T SIGCONTEXT_T # define FULL_SIGCONTEXT_SP SIGCONTEXT_SP # define FULL_SIGCONTEXT_PC SIGCONTEXT_PC -# define DECLARE_FULL_SIGCONTEXT(name) struct FULL_SIGCONTEXT * name +# define DECLARE_FULL_SIGCONTEXT(name) FULL_SIGCONTEXT_T * name # define INITIALIZE_FULL_SIGCONTEXT(partial, full) \ - ((full) = ((struct FULL_SIGCONTEXT *) (partial))) + ((full) = ((FULL_SIGCONTEXT_T *) (partial))) #endif #ifndef FULL_SIGCONTEXT_NREGS @@ -623,8 +554,8 @@ struct linux_sigcontext { # define FULL_SIGCONTEXT_FIRST_REG(scp) ((int *) 0) #endif -#ifndef PROCESSOR_NREGS -# define PROCESSOR_NREGS 0 +#ifndef FULL_SIGCONTEXT_RFREE +# define FULL_SIGCONTEXT_RFREE ((unsigned long) MemTop) #endif #ifndef FULL_SIGCONTEXT_SCHSP @@ -639,37 +570,28 @@ struct linux_sigcontext { #define PC_ALIGNMENT_MASK ((1 << PC_ZERO_BITS) - 1) -/* But they may have bits that can be masked by this. */ - -#ifndef PC_VALUE_MASK -#define PC_VALUE_MASK (~0) -#endif - -#ifdef HAS_COMPILER_SUPPORT -# define ALLOW_ONLY_C 0 -#else -# define ALLOW_ONLY_C 1 -# define PLAUSIBLE_CC_BLOCK_P(block) 0 +#ifndef HAS_COMPILER_SUPPORT +# define PLAUSIBLE_CC_BLOCK_P(block) 0 #endif #ifdef _AIX extern int _etext; -# define get_etext() (&_etext) #endif #ifdef __linux__ + extern unsigned int _init; extern unsigned int etext; -# define get_etext() (&etext) +# define ADDRESS_UCODE_P(addr) \ + ((((unsigned int *) (addr)) >= (&_init)) \ + && (((unsigned int *) (addr)) <= (&etext))) #endif #ifdef __CYGWIN__ extern unsigned int end; -# define get_etext() (&end) #endif -#ifndef get_etext - extern int etext; -# define get_etext() (&etext) +#ifndef ADDRESS_UCODE_P +# define ADDRESS_UCODE_P(addr) 0 #endif /* Machine/OS-independent section */ @@ -685,16 +607,13 @@ enum trap_state trap_state_exitting_hard }; -extern void EXFUN (initialize_trap_recovery, (char * C_sp)); +extern void EXFUN (UX_initialize_trap_recovery, (void)); extern enum trap_state EXFUN (OS_set_trap_state, (enum trap_state state)); -extern void EXFUN - (trap_handler, - (CONST char * message, - int signo, - SIGINFO_T info, - struct FULL_SIGCONTEXT * scp)); -extern void EXFUN (hard_reset, (struct FULL_SIGCONTEXT * scp)); +extern void EXFUN (hard_reset, (FULL_SIGCONTEXT_T * scp)); extern void EXFUN (soft_reset, (void)); +extern void EXFUN + (trap_handler, (CONST char *, int, SIGINFO_T, FULL_SIGCONTEXT_T *)); +extern SCHEME_OBJECT find_ccblock (unsigned long); #define STATE_UNKNOWN (LONG_TO_UNSIGNED_FIXNUM (0)) #define STATE_PRIMITIVE (LONG_TO_UNSIGNED_FIXNUM (1)) @@ -711,7 +630,4 @@ struct trap_recovery_info SCHEME_OBJECT extra_trap_info; }; -extern SCHEME_OBJECT * EXFUN - (find_block_address, (char * pc_value, SCHEME_OBJECT * area_start)); - #endif /* SCM_UXTRAP_H */