2 * stuff to handle internal errors
6 * This software is part of the SBCL system. See the README file for
9 * This software is derived from the CMU CL system, which was
10 * written at Carnegie Mellon University and released into the
11 * public domain. The software is in the public domain and is
12 * provided with absolutely no warranty. See the COPYING and CREDITS
13 * files for more information.
28 #include "genesis/static-symbols.h"
29 #include "genesis/vector.h"
30 #include "genesis/code.h"
33 #include "breakpoint.h"
35 #include "sc-offset.h"
37 /* the way that we shut down the system on a fatal error */
40 default_lossage_handler(void)
44 static void (*lossage_handler
)(void) = default_lossage_handler
;
48 configurable_lossage_handler()
50 void lisp_backtrace(int frames
);
52 if (dyndebug_config
.dyndebug_backtrace_when_lost
) {
53 fprintf(stderr
, "lose: backtrace follows as requested\n");
57 if (dyndebug_config
.dyndebug_sleep_when_lost
) {
59 "The system is too badly corrupted or confused to continue at the Lisp.\n"
60 "level. The monitor was enabled, but you requested `sleep_when_lost'\n"
61 "behaviour though dyndebug. To help with your debugging effort, this\n"
62 "thread will not enter the monitor, and instead proceed immediately to an\n"
63 "infinite sleep call, maximizing your chances that the thread's current\n"
64 "state can be preserved until you attach an external debugger. Good luck!\n");
66 # ifdef LISP_FEATURE_WIN32
73 monitor_or_something();
77 void enable_lossage_handler(void)
80 lossage_handler
= configurable_lossage_handler
;
82 lossage_handler
= monitor_or_something
;
85 void disable_lossage_handler(void)
87 lossage_handler
= default_lossage_handler
;
91 void print_message(char *fmt
, va_list ap
)
93 fprintf(stderr
, " in SBCL pid %d",getpid());
94 #if defined(LISP_FEATURE_SB_THREAD)
95 fprintf(stderr
, "(tid %p)", (void*)thread_self());
98 fprintf(stderr
, ":\n");
99 vfprintf(stderr
, fmt
, ap
);
101 fprintf(stderr
, "\n");
105 call_lossage_handler() never_returns
;
108 call_lossage_handler()
111 fprintf(stderr
, "Argh! lossage_handler() returned, total confusion..\n");
119 /* Block signals to prevent other threads, timers and such from
120 * interfering. If only all threads could be stopped somehow. */
121 block_blockable_signals(0);
122 fprintf(stderr
, "fatal error encountered");
124 print_message(fmt
, ap
);
126 fprintf(stderr
, "\n");
128 call_lossage_handler();
131 boolean lose_on_corruption_p
= 0;
134 corruption_warning_and_maybe_lose(char *fmt
, ...)
137 #ifndef LISP_FEATURE_WIN32
139 block_blockable_signals(&oldset
);
141 fprintf(stderr
, "CORRUPTION WARNING");
143 print_message(fmt
, ap
);
145 fprintf(stderr
, "The integrity of this image is possibly compromised.\n");
146 if (lose_on_corruption_p
)
147 fprintf(stderr
, "Exiting.\n");
149 fprintf(stderr
, "Continuing with fingers crossed.\n");
151 if (lose_on_corruption_p
)
152 call_lossage_handler();
153 #ifndef LISP_FEATURE_WIN32
155 thread_sigmask(SIG_SETMASK
,&oldset
,0);
159 void print_constant(os_context_t
*context
, int offset
) {
160 lispobj code
= find_code(context
);
162 struct code
*codeptr
= (struct code
*)native_pointer(code
);
163 int length
= code_header_words(codeptr
->header
);
165 if (offset
>= length
) {
166 printf("Constant offset %d out of bounds for the code object of length %d.\n",
169 brief_print(codeptr
->constants
[offset
-
170 (offsetof(struct code
, constants
) >> WORD_SHIFT
)]);
175 char *internal_error_descriptions
[] = {INTERNAL_ERROR_NAMES
};
176 char internal_error_nargs
[] = INTERNAL_ERROR_NARGS
;
177 /* internal error handler for when the Lisp error system doesn't exist
179 * FIXME: Shouldn't error output go to stderr instead of stdout? (Alas,
180 * this'd require changes in a number of things like brief_print(..),
181 * or I'd have changed it immediately.) */
183 describe_internal_error(os_context_t
*context
)
185 unsigned char *ptr
= arch_internal_error_arguments(context
);
187 int position
, sc_offset
, sc_number
, offset
, ch
;
188 void * pc
= (void*)*os_context_pc_addr(context
);
190 #ifdef LISP_FEATURE_ARM64
191 u32 trap_instruction
= *(u32
*)ptr
;
192 unsigned char code
= trap_instruction
>> 13 & 0xFF;
195 unsigned char code
= *ptr
;
199 if (code
> sizeof(internal_error_nargs
)) {
200 printf("Unknown error code %d at %p\n", code
, pc
);
202 printf("Internal error #%d \"%s\" at %p\n", code
, internal_error_descriptions
[code
], pc
);
204 for (count
= internal_error_nargs
[code
], position
= 0;
207 sc_offset
= read_var_integer(ptr
, &position
);
208 sc_number
= sc_offset_sc_number(sc_offset
);
209 offset
= sc_offset_offset(sc_offset
);
211 printf(" SC: %d, Offset: %d", sc_number
, offset
);
214 case sc_DescriptorReg
:
216 brief_print(*os_context_register_addr(context
, offset
));
219 case sc_CharacterReg
:
220 ch
= *os_context_register_addr(context
, offset
);
221 #ifdef LISP_FEATURE_X86
227 case '\n': printf("\t'\\n'\n"); break;
228 case '\b': printf("\t'\\b'\n"); break;
229 case '\t': printf("\t'\\t'\n"); break;
230 case '\r': printf("\t'\\r'\n"); break;
232 if (ch
< 32 || ch
> 127)
233 printf("\\%03o", ch
);
235 printf("\t'%c'\n", ch
);
240 #ifdef sc_WordPointerReg
241 case sc_WordPointerReg
:
243 printf("\t0x%08lx\n", (unsigned long) *os_context_register_addr(context
, offset
));
246 printf("\t%ld\n", (long) *os_context_register_addr(context
, offset
));
249 printf("\t%lu\n", (unsigned long) *os_context_register_addr(context
, offset
));
251 #ifdef sc_SingleFloatReg
252 case sc_SingleFloatReg
:
253 printf("\t%g\n", *(float *)&context
->sc_fpregs
[offset
]);
256 #ifdef sc_DoubleFloatReg
257 case sc_DoubleFloatReg
:
258 printf("\t%g\n", *(double *)&context
->sc_fpregs
[offset
]);
262 print_constant(context
, offset
);
271 /* utility routines used by miscellaneous pieces of code */
273 lispobj
debug_print(lispobj string
)
275 /* This is a kludge. It's not actually safe - in general - to use
276 %primitive print on the alpha, because it skips half of the
277 number stack setup that should usually be done on a function
278 call, so the called routine (i.e. this one) ends up being able
279 to overwrite local variables in the caller. Rather than fix
280 this everywhere that %primitive print is used (it's only a
281 debugging aid anyway) we just guarantee our safety by putting
282 an unused buffer on the stack before doing anything else
285 fprintf(stderr
, "%s\n",
286 (char *)(((struct vector
*)native_pointer(string
))->data
));
287 /* shut GCC up about not using this, because that's the point.. */