Reduce efficiency notes for complex type checks.
[sbcl.git] / src / runtime / monitor.c
bloba8d22cfe3a1097fd727f6d28bb30e219f3e7f523
1 /*
2 * This software is part of the SBCL system. See the README file for
3 * more information.
5 * This software is derived from the CMU CL system, which was
6 * written at Carnegie Mellon University and released into the
7 * public domain. The software is in the public domain and is
8 * provided with absolutely no warranty. See the COPYING and CREDITS
9 * files for more information.
12 #include "genesis/sbcl.h"
13 #include "lispobj.h"
15 #include <stdio.h>
16 #include <sys/types.h>
17 #include <stdlib.h>
18 #include <sys/time.h>
19 #ifndef LISP_FEATURE_WIN32
20 #include <sys/resource.h>
21 #endif
22 #include <signal.h>
23 #include <unistd.h>
24 #include <fcntl.h>
26 #include "runtime.h"
27 #include "parse.h"
28 #include "vars.h"
30 #include "print.h"
31 #include "arch.h"
32 #include "interr.h"
33 #include "search.h"
34 #include "globals.h"
35 #include "lispregs.h"
36 #include "interrupt.h"
37 #include "thread.h"
38 #include "genesis/instance.h"
39 #include "genesis/static-symbols.h"
40 #include "genesis/primitive-objects.h"
41 #include "genesis/gc-tables.h"
42 #include "genesis/unwind-block.h"
43 #include "genesis/hash-table.h"
44 #include "gc.h"
45 #include "../../tlsf-bsd/tlsf/tlsf.h"
46 extern void* tlsf_control;
48 /* When we need to do command input, we use this stream, which is not
49 * in general stdin, so that things will "work" (as well as being
50 * thrown into ldb can be considered "working":-) even in a process
51 * where standard input has been redirected to a file or pipe.
53 * (We could set up output to go to a special ldb_out stream for the
54 * same reason, but there's been no pressure for that so far.)
56 * The enter-the-ldb-monitor function is responsible for setting up
57 * this stream. */
58 static FILE *ldb_in = 0;
59 static int ldb_in_fd = -1;
61 typedef int cmd(char **ptr);
63 struct crash_preamble {
64 uword_t signature;
65 uword_t static_start;
66 uword_t static_nbytes;
67 uword_t readonly_start;
68 uword_t readonly_nbytes;
69 uword_t permgen_start;
70 uword_t permgen_nbytes;
71 uword_t dynspace_start;
72 long dynspace_npages_total;
73 long dynspace_npages_used;
74 int card_size;
75 int card_table_nbits;
76 // fixedobj data dumped: pages, page table
77 uword_t fixedobj_start, fixedobj_size, fixedobj_free_pointer;
78 // text data dumped: pages, touched_bits, page table
79 uword_t text_start, text_size;
80 lispobj *tlsf_mem_start, *text_space_highwatermark;
81 lispobj sentinel_block[3];
82 void* tlsf_control_address;
83 int nthreads;
84 int tls_size;
85 lispobj lisp_package_vector;
86 int sizeof_context;
87 int tlsf_control_size;
88 char sprof_enabled;
89 char pin_dynspace_code;
91 struct crash_thread_preamble {
92 uword_t address;
93 uword_t has_context;
94 uword_t control_stack_nbytes;
95 uword_t binding_stack_nbytes;
98 // Prevent some mixups in case you add fields to the crash dump
99 const uword_t CRASH_PREAMBLE_SIGNATURE =
100 (sizeof (struct crash_preamble) << 16) | sizeof (struct crash_thread_preamble);
102 __attribute__((unused))
103 static void maybe_show_contents(__attribute__((unused)) char *legend,
104 __attribute__((unused)) void* buf,
105 __attribute__((unused)) long nbytes)
107 #if 0 // def LISP_FEATURE_64_BIT
108 int want = legend && (!strcmp(legend, "preamble") || legend[0] == ' ');
109 if (!want) return;
110 int nwords = nbytes>>WORD_SHIFT;
111 int i;
112 for (i=0;i<nwords;++i)
113 fprintf(stderr, "%s %16lx", (i%8)?"":(i?"\n ":" "), ((uword_t*)buf)[i]);
114 putc('\n', stderr);
115 #endif
118 #if defined LISP_FEATURE_X86 || defined LISP_FEATURE_X86_64 // un-tested elsewhere
119 #include <errno.h>
120 struct filewriter { long total; int fd; bool verbose; };
122 static void checked_write(char *section, struct filewriter* writer, void* buf, long nbytes)
124 char label[8];
125 // I don't know why strncpy() gets a warning here. Isn't truncation exactly the point?
126 // monitor.c:118:5: warning: ‘strncpy’ output truncated before terminating nul copying 8 bytes
127 // from a string of the same length [-Wstringop-truncation]
128 memset(label, 0, sizeof label);
129 memcpy(label, section, strlen(section)<sizeof label?strlen(section):sizeof label);
130 ssize_t wrote;
131 if (write(writer->fd, label, sizeof label) != sizeof label
132 || (wrote = write(writer->fd, buf, nbytes)) != nbytes)
133 lose("short write, errno=%d", errno);
134 if (writer->verbose) fprintf(stderr, "%s: %lx bytes\n", section, (long)(nbytes + sizeof label));
135 maybe_show_contents(section, buf, nbytes);
136 writer->total += nbytes + sizeof label;
139 #include "immobile-space.h"
140 void save_gc_crashdump(char *pathname,
141 lispobj* cur_thread_approx_stackptr,
142 bool verbose)
144 extern int pin_all_dynamic_space_code;
145 int fd = open(pathname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
146 struct thread* th;
147 int nthreads = 0;
148 for_each_thread(th) ++nthreads;
149 if (verbose) fprintf(stderr, "save: %d threads\n", nthreads);
150 struct crash_preamble preamble;
151 unsigned long nbytes_heap = next_free_page * GENCGC_PAGE_BYTES;
152 int nbytes_tls = SymbolValue(FREE_TLS_INDEX,0);
153 preamble.signature = CRASH_PREAMBLE_SIGNATURE;
154 preamble.static_start = STATIC_SPACE_START;
155 preamble.static_nbytes = (uword_t)static_space_free_pointer - STATIC_SPACE_START;
156 preamble.readonly_start = READ_ONLY_SPACE_START;
157 preamble.readonly_nbytes = (uword_t)read_only_space_free_pointer - READ_ONLY_SPACE_START;
158 preamble.permgen_start = PERMGEN_SPACE_START;
159 preamble.permgen_nbytes = (uword_t)permgen_space_free_pointer - PERMGEN_SPACE_START;
160 preamble.dynspace_start = DYNAMIC_SPACE_START;
161 preamble.dynspace_npages_total = dynamic_space_size / GENCGC_PAGE_BYTES;
162 preamble.dynspace_npages_used = next_free_page;
163 preamble.card_size = GENCGC_CARD_BYTES;
164 preamble.card_table_nbits = gc_card_table_nbits;
165 preamble.nthreads = nthreads;
166 preamble.tls_size = nbytes_tls;
167 preamble.lisp_package_vector = lisp_package_vector;
168 preamble.sprof_enabled = sb_sprof_enabled;
169 preamble.pin_dynspace_code = pin_all_dynamic_space_code;
170 preamble.sizeof_context = sizeof (os_context_t);
171 #ifdef LISP_FEATURE_IMMOBILE_SPACE
172 char *tlsf_memory_end = (char*)TEXT_SPACE_START + text_space_size;
173 preamble.fixedobj_start = FIXEDOBJ_SPACE_START;
174 preamble.fixedobj_size = FIXEDOBJ_SPACE_SIZE;
175 preamble.fixedobj_free_pointer = (uword_t)fixedobj_free_pointer;
176 preamble.text_start = TEXT_SPACE_START;
177 preamble.text_size = text_space_size;
178 preamble.text_space_highwatermark = text_space_highwatermark;
179 preamble.tlsf_mem_start = tlsf_mem_start;
180 preamble.tlsf_control_address = tlsf_control;
181 preamble.tlsf_control_size = tlsf_size();
182 memcpy(preamble.sentinel_block, tlsf_memory_end-3*N_WORD_BYTES, 3*N_WORD_BYTES);
183 #endif
184 struct filewriter writer = { .fd = fd, .total = 0, .verbose = verbose };
185 // write the preamble and static + readonly spaces
186 checked_write("preamble", &writer, &preamble, sizeof preamble);
187 checked_write("static", &writer, (char*)STATIC_SPACE_START, preamble.static_nbytes);
188 checked_write("R/O", &writer, (char*)READ_ONLY_SPACE_START, preamble.readonly_nbytes);
189 checked_write("perm", &writer, (char*)PERMGEN_SPACE_START, preamble.permgen_nbytes);
191 // write the dynamic-space, PTEs, card table
192 checked_write("dynamic", &writer, (char*)DYNAMIC_SPACE_START, nbytes_heap);
193 checked_write("PTE", &writer, page_table, sizeof (struct page) * next_free_page);
194 checked_write("cardmark", &writer, gc_card_mark, 1+gc_card_table_mask);
195 #ifdef LISP_FEATURE_MARK_REGION_GC
196 checked_write("allocated", &writer, allocation_bitmap, bitmap_size(next_free_page));
197 extern line_index_t line_count;
198 checked_write("linemap", &writer, line_bytemap, line_count);
199 #endif
200 #ifdef LISP_FEATURE_IMMOBILE_SPACE
201 int usage = (uword_t)fixedobj_free_pointer - FIXEDOBJ_SPACE_START;
202 checked_write("fixedobj", &writer, (char*)FIXEDOBJ_SPACE_START, usage);
203 int total_npages = FIXEDOBJ_SPACE_SIZE / IMMOBILE_CARD_BYTES;
204 checked_write("fixedobj_PTE", &writer, fixedobj_pages, total_npages * sizeof sizeof(struct fixedobj_page));
205 usage = (uword_t)text_space_highwatermark - TEXT_SPACE_START;
206 // write the block_header_t that is just beyond the high water mark
207 checked_write("text", &writer, (char*)TEXT_SPACE_START, usage+3*N_WORD_BYTES);
208 total_npages = text_space_size / IMMOBILE_CARD_BYTES;
209 int n_bitmap_elts = ALIGN_UP(total_npages, 32) / 32;
210 checked_write("text_gen", &writer, text_page_genmask, total_npages); // 1 byte per page
211 checked_write("text_WP", &writer, text_page_touched_bits, n_bitmap_elts * sizeof (int));
212 checked_write("TLSF_control", &writer, tlsf_control, preamble.tlsf_control_size);
213 int tlsf_memory_size = tlsf_memory_end - (char*)tlsf_mem_start;
214 int n_tlsf_pages = tlsf_memory_size / IMMOBILE_CARD_BYTES;
215 checked_write("TLSF_sso", &writer, tlsf_page_sso, n_tlsf_pages * sizeof (short));
216 #endif
217 struct crash_thread_preamble thread_preamble;
218 for_each_thread(th) {
219 int ici = fixnum_value(read_TLS(FREE_INTERRUPT_CONTEXT_INDEX,th));
220 os_context_t* threadcontext = nth_interrupt_context(0, th);
221 uword_t sp;
222 if (ici) {
223 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
224 sp = *os_context_register_addr(threadcontext, reg_SP);
225 #elif defined reg_CSP
226 sp = *os_context_register_addr(threadcontext, reg_CSP);
227 #endif
228 } else if (th->state_word.state == STATE_DEAD) {
229 gc_assert(th->binding_stack_pointer == th->binding_stack_start);
230 // FIXME: assumes stack grows down
231 sp = (uword_t)th->control_stack_end;
232 } else {
233 if (th != get_sb_vm_thread()) {
234 char msg[80];
235 int n = snprintf(msg, sizeof msg,
236 "thread %p state %d - No stackptr for crash dump\n",
237 th, th->state_word.state);
238 ignore_value(write(2, msg, n));
239 _exit(1);
241 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
242 sp = (uword_t)cur_thread_approx_stackptr;
243 #else
244 sp = access_control_stack_pointer(th);
245 #endif
247 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
248 int nbytes_control_stack =
249 (char*)th->control_stack_end - (char*)sp; // grows downward
250 int nbytes_binding_stack =
251 (char*)th->binding_stack_pointer - (char*)th->binding_stack_start; // grows upward
252 #else
253 int nbytes_control_stack = (char*)sp - (char*)th->control_stack_start; // grows upward
254 int nbytes_binding_stack =
255 (char*)get_binding_stack_pointer(th) - (char*)th->binding_stack_start;
256 #endif
257 thread_preamble.address = (uword_t)th;
258 thread_preamble.has_context = ici != 0; // boolean for have context or not
259 thread_preamble.control_stack_nbytes = nbytes_control_stack;
260 thread_preamble.binding_stack_nbytes = nbytes_binding_stack;
261 // write the preamble
262 checked_write("thread", &writer, &thread_preamble, sizeof thread_preamble);
263 // write 0 or 1 contexts, control-stack, binding-stack, TLS
264 if (ici) checked_write(" ctxt", &writer, threadcontext, preamble.sizeof_context);
265 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
266 checked_write(" stack", &writer, (char*)sp, nbytes_control_stack);
267 #else
268 checked_write(" stack", &writer, th->control_stack_start, nbytes_control_stack);
269 #endif
270 checked_write(" bindings", &writer, th->binding_stack_start, nbytes_binding_stack);
271 checked_write(" TLS", &writer, th, nbytes_tls);
273 checked_write("sig", &writer, "SB.Crash", 8); // trailing signature
274 close(fd);
275 if (verbose) fprintf(stderr, "Total: %ld bytes\n", writer.total);
277 #endif
279 static cmd call_cmd, dump_cmd, print_cmd, quit_cmd, help_cmd;
280 static cmd flush_cmd, regs_cmd, exit_cmd;
281 static cmd print_context_cmd, pte_cmd, search_cmd, hashtable_cmd;
282 static cmd backtrace_cmd, catchers_cmd;
283 static cmd threads_cmd, findpath_cmd, layouts_cmd;
285 extern void gc_stop_the_world(), gc_start_the_world();
286 static void suspend_other_threads() {
287 gc_stop_the_world();
288 // It might make sense for each thread's stop-for-gc handler to close its region
289 // versus doing this loop
290 struct thread *th;
291 for_each_thread(th) { gc_close_thread_regions(th, 0); }
292 gc_close_collector_regions(0);
294 static void unsuspend_other_threads() {
295 gc_start_the_world();
298 static int save_cmd(char **ptr) {
299 char *name = parse_token(ptr);
300 if (!name) {
301 fprintf(stderr, "Need filename\n");
302 return 0;
304 #if (defined LISP_FEATURE_X86 || defined LISP_FEATURE_X86_64) && defined LISP_FEATURE_SB_THREAD
305 suspend_other_threads();
306 save_gc_crashdump(name, (lispobj*)__builtin_frame_address(0), 1);
307 unsuspend_other_threads();
308 #else
309 fprintf(stderr, "Unimplemented\n");
310 #endif
311 return 0;
313 static int gc_and_save_cmd(char **ptr) {
314 /* The use-case for this is as follows: suppose you're testing a shiny new GC
315 * on a large Lisp application, but gc_and_save crashes 1 time in 10.
316 * How do you effectively debug that if merely getting to the point where you
317 * would run S-L-A-D takes significant time? Just inject save_gc_crashdump()
318 * into every save at the top of prepare_to_save() or thereabouts, and run
319 * until you collect at least one crash dump. Then iterate on editing the
320 * runtime including the GC, and restarting 'ldb' on the saved state from a
321 * crashed run to try to isolate what went wrong without having to build up
322 * the Lisp heap again from scratch */
323 char *name = parse_token(ptr);
324 if (!name) {
325 fprintf(stderr, "Need filename\n");
326 return 0;
328 #if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_WIN32)
329 current_thread = all_threads;
330 #endif
331 extern void gc_and_save(char*,bool,bool,bool,bool,int,int);
332 gc_and_save(name, 0, 0, 0, 0, 0, 0); // never returns
333 return 0;
335 void list_lisp_threads(int regions) {
336 struct thread* th;
337 fprintf(stderr, "(thread*,pthread,sb-vm:thread,name)\n");
338 void* pthread;
339 for_each_thread(th) {
340 memcpy(&pthread, &th->os_thread, N_WORD_BYTES);
341 struct thread_instance* i = (void*)(th->lisp_thread - INSTANCE_POINTER_LOWTAG);
342 lispobj name = instancep(th->lisp_thread) ? i->_name : 0;
343 char* cname = NULL;
344 // it's OK to call widetag_of on NIL but not NULL
345 if (name && simple_base_string_p(name)) cname = vector_sap(name);
346 fprintf(stderr, "%p %p %p \"%s\"\n", th, pthread, (void*)i, cname);
347 if (regions) {
348 #define show_tlab(label, r) fprintf(stderr, " %s @ %p: %p %p %p\n", label, \
349 &th->r, th->r.start_addr, th->r.end_addr, th->r.free_pointer)
350 show_tlab("usr cons ", cons_tlab);
351 show_tlab("usr mix ", mixed_tlab);
352 show_tlab("sys cons ", sys_cons_tlab);
353 show_tlab("sys mix ", sys_mixed_tlab);
354 #undef show_tlab
357 if (regions) {
358 #define show_tlab(label, r) fprintf(stderr, " %s @ %p: %p %p %p\n", label, \
359 r, r->start_addr, r->end_addr, r->free_pointer)
360 fprintf(stderr, "global regions:\n");
361 show_tlab("mixed ", mixed_region);
362 show_tlab("smallmix ", small_mixed_region);
363 show_tlab("unboxed ", unboxed_region);
364 show_tlab("code ", code_region);
365 show_tlab("boxed ", boxed_region);
366 show_tlab("cons ", cons_region);
367 #undef show_tlab
370 static int threads_cmd(char **ptr) {
371 list_lisp_threads(more_p(ptr) && !strncmp(*ptr, "-r", 2));
372 return 0;
374 extern int heap_trace_verbose;
375 extern int gc_pathfind_aux(lispobj*, lispobj, lispobj, lispobj, int);
377 static int findpath_cmd(char **ptr) {
378 // prevent the path finder from seeing the object that results from parsing the command
379 lispobj* stackptr = (lispobj*)&ptr;
380 // overaligned for 32-bit but doesn't matter
381 struct vector __attribute__ ((aligned (16))) result;
382 struct cons __attribute__ ((aligned (16))) list;
383 /* Despite capturing the stack pointer coming in to this function,
384 * it's very difficult to ensure that a locally allocated weak pointer
385 * is not above that (and hence its value slot seen).
386 * So it has to be malloc()ed. */
387 char* wp_mem = malloc(sizeof (struct weak_pointer) + N_WORD_BYTES);
388 struct weak_pointer* wp =
389 (void*)(wp_mem + (((uword_t)wp_mem & LOWTAG_MASK) ? N_WORD_BYTES : 0));
390 wp->header = ((WEAK_POINTER_SIZE-1)<<N_WIDETAG_BITS)|WEAK_POINTER_WIDETAG;
391 if (parse_lispobj(ptr, &wp->value)) {
392 list.car = make_lispobj(wp, OTHER_POINTER_LOWTAG);
393 list.cdr = NIL;
394 result.header = SIMPLE_VECTOR_WIDETAG;
395 result.length_ = make_fixnum(1);
396 result.data[0] = 0;
397 suspend_other_threads();
398 int save = heap_trace_verbose;
399 heap_trace_verbose = 4;
400 gc_pathfind_aux(stackptr,
401 make_lispobj(&list, LIST_POINTER_LOWTAG),
402 make_lispobj(&result, OTHER_POINTER_LOWTAG),
403 0, 2);
404 heap_trace_verbose = save;
405 unsuspend_other_threads();
406 lispobj path = result.data[0];
407 if (listp(path)) {
408 fprintf(stderr, "Answer:\n");
409 while (path != NIL) {
410 struct cons* pair = CONS(CONS(path)->car);
411 if (listp(pair->cdr)) {
412 // thread root - complicated to print
413 } else {
414 // otherwise, object and word index
415 fprintf(stderr, " %"OBJ_FMTX" word %d\n",
416 pair->car, (int)pair->cdr);
418 path = CONS(path)->cdr;
422 free(wp_mem);
423 return 0;
425 static int verify_cmd(char __attribute__((unused)) **ptr) {
426 gencgc_verbose = 1;
427 suspend_other_threads();
428 verify_heap(0, 0);
429 unsuspend_other_threads();
430 return 0;
432 static int gc_cmd(char **ptr) {
433 int last_gen = 0;
434 extern generation_index_t verify_gens;
435 if (more_p(ptr)) parse_number(ptr, &last_gen);
436 gencgc_verbose = 2;
437 pre_verify_gen_0 = 1;
438 verify_gens = 0;
439 suspend_other_threads();
440 collect_garbage(last_gen);
441 unsuspend_other_threads();
442 return 0;
445 #ifdef LISP_FEATURE_IMMOBILE_SPACE
446 static int tlsf_cmd(__attribute__((unused)) char **ptr) {
447 tlsf_dump_pool(tlsf_control, tlsf_mem_start, "/dev/tty");
448 #ifdef TLSF_CONFIG_DEBUG
449 tlsf_check(tlsf_control);
450 tlsf_check_pool(tlsf_mem_start);
451 #endif
452 return 0;
454 #endif
456 static struct cmd {
457 char *cmd, *help;
458 int (*fn)(char **ptr);
459 } supported_cmds[] = {
460 // Commands with no help string are all at-your-own-risk
461 {"help", "Display this help information.", help_cmd},
462 {"?", "(an alias for help)", help_cmd},
463 {"backtrace", "Backtrace up to N frames.", backtrace_cmd},
464 {"call", "Call FUNCTION with ARG1, ARG2, ...", call_cmd},
465 {"catchers", "Print a list of all the active catchers.", catchers_cmd},
466 {"context", "Print interrupt context number I.", print_context_cmd},
467 {"dump", "Dump memory starting at ADDRESS for COUNT words.", dump_cmd},
468 {"d", "(an alias for dump)", dump_cmd},
469 {"exit", "Exit this instance of the monitor.", exit_cmd},
470 {"findpath", "Find path to an object.", findpath_cmd},
471 {"flush", "Flush all temp variables.", flush_cmd},
472 {"hashtable", "Dump a hashtable in detail.", hashtable_cmd},
473 {"layouts", "Dump LAYOUT instances.", layouts_cmd},
474 {"print", "Print object at ADDRESS.", print_cmd},
475 {"p", "(an alias for print)", print_cmd},
476 {"pte", "Page table entry for address", pte_cmd},
477 {"quit", "Quit.", quit_cmd},
478 {"regs", "Display current Lisp registers.", regs_cmd},
479 {"search", "Search heap for object.", search_cmd},
480 {"save", 0, save_cmd}, // snapshot heap to file ("best effort" though)
481 {"gc_and_save", 0, gc_and_save_cmd},
482 {"threads", "List threads", threads_cmd},
483 #ifdef LISP_FEATURE_IMMOBILE_SPACE
484 {"tlsfdump", 0, tlsf_cmd}, // (unsafely) dump TLSF structures
485 #endif
486 {"verify", "Check heap invariants", verify_cmd},
487 {"gc", 0, gc_cmd}, // (this is not the right way to invoke GC)
488 {NULL, NULL, NULL}
491 static int
492 visible(unsigned char c)
494 if (c < ' ' || c > '~')
495 return ' ';
496 else
497 return c;
500 static bool valid_widetag_p(unsigned char widetag) {
501 // TODO: ensure that widetag is defined (not "unused") and is for a headered object
502 // (i.e. is not CHARACTER_WIDETAG and not some other things)
503 return other_immediate_lowtag_p(widetag);
505 static int NO_SANITIZE_MEMORY
506 dump_cmd(char **ptr)
508 static char *lastaddr = 0;
509 static int lastcount = 20;
511 char *addr = lastaddr;
512 int count = lastcount, displacement;
513 int force = 0, decode = 0;
515 if (more_p(ptr)) {
516 while (1) {
517 if (!strncmp(*ptr, "-f ", 3)) {
518 force = 1;
519 *ptr += 3;
520 } else if (!strncmp(*ptr, "-d ", 3)) {
521 decode = 1;
522 *ptr += 3;
523 } else break;
525 if (!parse_addr(ptr, !force, &addr)) return 0;
527 if (more_p(ptr) && !parse_number(ptr, &count)) return 0;
530 if (count == 0) {
531 printf("COUNT must be non-zero.\n");
532 return 0;
535 lastcount = count;
537 if (count > 0)
538 displacement = N_WORD_BYTES;
539 else {
540 displacement = -N_WORD_BYTES;
541 count = -count;
544 bool aligned = ((uword_t)addr & LOWTAG_MASK) == 0;
545 if (decode && (!aligned || displacement < 0)) {
546 printf("Sorry, can only decode if aligned and stepping forward\n");
547 decode = 0;
549 lispobj* next_object = decode ? (lispobj*)addr : 0;
551 while (count-- > 0) {
552 printf("%p: ", (os_vm_address_t) addr);
553 if (force || gc_managed_addr_p((lispobj)addr)) {
554 unsigned long *lptr = (unsigned long *)addr;
555 unsigned char *cptr = (unsigned char *)addr;
557 #if N_WORD_BYTES == 8
558 printf("0x%016lx | %c%c%c%c%c%c%c%c",
559 lptr[0],
560 visible(cptr[0]), visible(cptr[1]),
561 visible(cptr[2]), visible(cptr[3]),
562 visible(cptr[4]), visible(cptr[5]),
563 visible(cptr[6]), visible(cptr[7]));
564 #else
565 unsigned short *sptr = (unsigned short *)addr;
566 printf("0x%08lx 0x%04x 0x%04x "
567 "0x%02x 0x%02x 0x%02x 0x%02x "
568 "%c%c"
569 "%c%c",
570 lptr[0], sptr[0], sptr[1],
571 cptr[0], cptr[1], cptr[2], cptr[3],
572 visible(cptr[0]), visible(cptr[1]),
573 visible(cptr[2]), visible(cptr[3]));
574 #endif
575 #ifdef LISP_FEATURE_GENERATIONAL
576 if (aligned) {
577 lispobj ptr = *(lispobj*)addr;
578 int gen;
579 if (is_lisp_pointer(ptr) && gc_managed_heap_space_p(ptr)
580 && (gen = gc_gen_of(ptr, 99)) != 99) { // say that static is 99
581 if (gen != 99) printf(" | %d", gen);
582 } else {
583 printf(" "); // padding to make MR part line up
586 #endif
587 #ifdef LISP_FEATURE_MARK_REGION_GC
588 if (aligned && find_page_index(addr) != -1) {
589 extern bool allocation_bit_marked(void*);
590 printf(" %c", allocation_bit_marked(addr) ? '*' : ' ');
592 #endif
593 if (decode && addr == (char*)next_object) {
594 lispobj word = *(lispobj*)addr;
595 // ensure validity of widetag because crashing with
596 // "no size function" would be worse than doing nothing
597 if (word != 0 && !is_lisp_pointer(word)
598 && valid_widetag_p(header_widetag(word))) {
599 printf(" %s", widetag_names[header_widetag(word)>>2]);
600 next_object += headerobj_size2(next_object, word);
601 } else if (!is_header(word)) {
602 next_object += CONS_SIZE;
603 } else { // disable decoder if weirdness observed
604 decode = 0;
607 printf("\n");
609 else
610 printf("invalid Lisp-level address\n");
612 addr += displacement;
615 lastaddr = addr;
616 return 0;
619 static int
620 print_cmd(char **ptr)
622 lispobj obj;
623 if (parse_lispobj(ptr, &obj)) print(obj);
624 return 0;
627 int verify_lisp_hashtable(__attribute__((unused)) struct hash_table* ht,
628 __attribute__((unused)) FILE* file)
630 int errors = 0;
631 #if defined LISP_FEATURE_UNIX && defined LISP_FEATURE_64_BIT
632 char *kinds[4] = {"EQ","EQL","EQUAL","EQUALP"};
633 lispobj* data = VECTOR(ht->pairs)->data;
634 uint32_t* hvdata = ht->hash_vector != NIL ?
635 (uint32_t*)VECTOR(ht->hash_vector)->data : 0;
636 struct vector* iv = VECTOR(ht->index_vector);
637 uint32_t* ivdata = (void*)iv->data;
638 uint32_t* nvdata = (void*)VECTOR(ht->next_vector)->data;
639 unsigned ivmask = vector_len(iv) - 1;
640 int hwm = KV_PAIRS_HIGH_WATER_MARK(data);
641 if (file)
642 fprintf(file,
643 "Table %p Kind=%d=%s Weak=%d Count=%d HWM=%d rehash=%d\n",
644 ht, hashtable_kind(ht), kinds[hashtable_kind(ht)],
645 hashtable_weakp(ht)?1:0,
646 (int)fixnum_value(ht->_count), hwm, (int)data[1]);
647 int j;
648 for (j = 1; j <= hwm; j++) {
649 lispobj key = data[2*j];
650 lispobj val = data[2*j+1];
651 if (header_widetag(key) == UNBOUND_MARKER_WIDETAG ||
652 header_widetag(val) == UNBOUND_MARKER_WIDETAG) {
653 if (file) fprintf(file, "[%4d] %12lx %16lx\n", j, key, val);
654 continue;
656 uint32_t h;
657 if (hvdata && hvdata[j] != 0xFFFFFFFF) {
658 h = hvdata[j];
659 // print the as-stored hash
660 if (file)
661 fprintf(file, "[%4d] %12lx %16lx %08x %4x (",
662 j, key, val, h, h & ivmask);
663 } else {
664 // print the hash and then fuzzed hash;
665 lispobj h0 = funcall1(ht->hash_fun, key);
666 h = prefuzz_ht_hash(h0);
667 if (file)
668 fprintf(file, "[%4d] %12lx %16lx %016lx %08x %4x (", j,
669 key, val, fixnum_value(h0), h, h & ivmask);
671 // show the chain
672 unsigned cell = ivdata[h & ivmask];
673 while (cell) {
674 if (file) fprintf(file, "%d", cell);
675 lispobj matchp = funcall2(ht->test_fun, key, data[cell*2]);
676 if (matchp != NIL) { if (file) fprintf(file, "\u2713"); break; }
677 if ((cell = nvdata[cell]) != 0 && file) putc(' ', file);
679 if (!cell) ++errors;
680 if (file) fprintf(file, cell ? ")\n" : ") *\n");
682 #endif
683 return errors;
685 static int hashtable_cmd(char **ptr)
687 lispobj obj;
688 if (parse_lispobj(ptr, &obj)) {
689 int errors = verify_lisp_hashtable((void*)native_pointer(obj),
690 stdout);
691 if (errors) fprintf(stderr, "Errors: %d\n", errors);
693 return 0;
696 static int
697 pte_cmd(char **ptr)
699 extern void gc_show_pte(lispobj);
700 lispobj obj;
701 if (parse_lispobj(ptr, &obj)) gc_show_pte(obj);
702 return 0;
705 static int
706 regs_cmd(char __attribute__((unused)) **ptr)
708 struct thread __attribute__((unused)) *thread = get_sb_vm_thread();
710 printf("CSP\t=\t%p ", access_control_stack_pointer(thread));
711 #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
712 printf("CFP\t=\t%p ", access_control_frame_pointer(thread));
713 #endif
715 #ifdef reg_BSP
716 printf("BSP\t=\t%p\n", get_binding_stack_pointer(thread));
717 #else
718 /* printf("BSP\t=\t%p\n", (void*)SymbolValue(BINDING_STACK_POINTER)); */
719 printf("\n");
720 #endif
722 #ifdef LISP_FEATURE_GENERATIONAL
723 /* printf("DYNAMIC\t=\t%p\n", (void*)DYNAMIC_SPACE_START); */
724 #else
725 printf("STATIC\t=\t%p ", static_space_free_pointer);
726 printf("RDONLY\t=\t%p ", read_only_space_free_pointer);
727 printf("DYNAMIC\t=\t%p\n", (void*)current_dynamic_space);
728 #endif
729 return 0;
732 static int
733 call_cmd(char **ptr)
735 lispobj thing;
736 parse_lispobj(ptr, &thing);
737 lispobj function, args[3];
738 lispobj result = NIL;
740 int numargs;
742 if (lowtag_of(thing) == OTHER_POINTER_LOWTAG) {
743 lispobj *obj = native_pointer(thing);
744 switch (widetag_of(obj)) {
745 case SYMBOL_WIDETAG:
746 function = symbol_function((struct symbol*)obj);
747 if (function == NIL) {
748 printf("Symbol 0x%08lx is undefined.\n", (long unsigned)thing);
749 return 0;
751 break;
752 case FDEFN_WIDETAG:
753 function = FDEFN(thing)->fun;
754 if (function == NIL) {
755 printf("Fdefn 0x%08lx is undefined.\n", (long unsigned)thing);
756 return 0;
758 break;
759 default:
760 printf("0x%08lx is not a function pointer, symbol, "
761 "or fdefn object.\n",
762 (long unsigned)thing);
763 return 0;
766 else if (lowtag_of(thing) != FUN_POINTER_LOWTAG) {
767 printf("0x%08lx is not a function pointer, symbol, or fdefn object.\n",
768 (long unsigned)thing);
769 return 0;
771 else
772 function = thing;
774 numargs = 0;
775 while (more_p(ptr)) {
776 if (numargs >= 3) {
777 printf("too many arguments (no more than 3 supported)\n");
778 return 0;
780 parse_lispobj(ptr, &args[numargs++]);
783 switch (numargs) {
784 case 0:
785 result = funcall0(function);
786 break;
787 case 1:
788 result = funcall1(function, args[0]);
789 break;
790 case 2:
791 result = funcall2(function, args[0], args[1]);
792 break;
793 case 3:
794 result = funcall3(function, args[0], args[1], args[2]);
795 break;
796 default:
797 lose("unsupported arg count made it past validity check?!");
800 print(result);
801 return 0;
804 static int
805 flush_cmd(char __attribute__((unused)) **ptr)
807 flush_vars();
808 return 0;
811 static int
812 quit_cmd(char __attribute__((unused)) **ptr)
814 char buf[10];
816 printf("Really quit? [y] ");
817 fflush(stdout);
818 if (fgets(buf, sizeof(buf), ldb_in)) {
819 if (buf[0] == 'y' || buf[0] == 'Y' || buf[0] == '\n')
820 exit(1);
821 } else {
822 printf("\nUnable to read response, assuming y.\n");
823 exit(1);
825 return 0;
828 static int
829 help_cmd(char __attribute__((unused)) **ptr)
831 struct cmd *cmd;
833 for (cmd = supported_cmds; cmd->cmd != NULL; cmd++)
834 if (cmd->help != NULL)
835 printf("%s\t%s\n", cmd->cmd, cmd->help);
836 return 0;
839 static int
840 exit_cmd(char __attribute__((unused)) **ptr)
842 return 1; // 'done' flag
845 static void
846 print_context(os_context_t *context)
848 int i;
850 for (i = 0; i < NREGS; i++) {
851 printf("%s:\t", lisp_register_names[i]);
852 brief_print((lispobj)(*os_context_register_addr(context,i)));
855 #if defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_PPC)
856 printf("DAR:\t\t 0x%08lx\n", (unsigned long)(*os_context_register_addr(context, 41)));
857 printf("DSISR:\t\t 0x%08lx\n", (unsigned long)(*os_context_register_addr(context, 42)));
858 #endif
859 #ifndef REG_PC
860 printf("PC:\t\t 0x%08lx\n", (unsigned long)os_context_pc(context));
861 #endif
864 static int
865 print_context_cmd(char **ptr)
867 int free_ici;
868 struct thread *thread = get_sb_vm_thread();
870 free_ici = fixnum_value(read_TLS(FREE_INTERRUPT_CONTEXT_INDEX,thread));
872 if (more_p(ptr)) {
873 int index;
875 if (!parse_number(ptr, &index)) return 0;
877 if ((index >= 0) && (index < free_ici)) {
878 printf("There are %d interrupt contexts.\n", free_ici);
879 printf("printing context %d\n", index);
880 print_context(nth_interrupt_context(index, thread));
881 } else {
882 printf("There are %d interrupt contexts.\n", free_ici);
884 } else {
885 if (free_ici == 0)
886 printf("There are no interrupt contexts.\n");
887 else {
888 printf("There are %d interrupt contexts.\n", free_ici);
889 printf("printing context %d\n", free_ici - 1);
890 print_context(nth_interrupt_context(free_ici - 1, thread));
893 return 0;
896 static int
897 backtrace_cmd(char **ptr)
899 void lisp_backtrace(int frames);
900 int n;
902 if (more_p(ptr)) {
903 if (!parse_number(ptr, &n)) return 0;
904 } else
905 n = 100;
907 printf("Backtrace:\n");
908 lisp_backtrace(n);
909 return 0;
912 static int search_cmd(char **ptr)
914 char *addr;
915 if (!parse_addr(ptr, 1, &addr)) return 0;
916 lispobj *obj = search_all_gc_spaces((void*)addr);
917 if(obj)
918 printf("#x%"OBJ_FMTX"\n", compute_lispobj(obj));
919 else
920 printf("Not found\n");
921 return 0;
924 static int
925 catchers_cmd(char __attribute__((unused)) **ptr)
927 struct catch_block *catch = (struct catch_block *)
928 read_TLS(CURRENT_CATCH_BLOCK, get_sb_vm_thread());
930 if (catch == NULL)
931 printf("There are no active catchers!\n");
932 else {
933 while (catch != NULL) {
934 printf("%p:\n\tuwp : %p\n\tfp : %p\n\t"
935 "code : %p\n\tentry: %p\n\ttag: ",
936 catch,
937 catch->uwp,
938 catch->cfp,
939 #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64) || defined(LISP_FEATURE_ARM64)
940 component_ptr_from_pc((void*)catch->entry_pc),
941 #else
942 (void*)catch->code,
943 #endif
944 (void*)(catch->entry_pc));
945 brief_print((lispobj)catch->tag);
946 catch = catch->previous_catch;
949 return 0;
952 struct layout_collection {
953 struct cons* list;
954 int passno;
956 static int count_layout_occurs(lispobj x, struct cons* list)
958 int ct = 0;
959 for ( ; list ; list = (void*)list->cdr ) if (list->car == x) ++ct;
960 return ct;
963 static uword_t display_layouts(lispobj* where, lispobj* limit, uword_t arg)
965 extern struct vector * classoid_name(lispobj * classoid);
966 struct layout_collection *lc = (void*)arg;
967 where = next_object(where, 0, limit); /* find first marked object */
968 for ( ; where ; where = next_object(where, object_size(where), limit) ) {
969 if (widetag_of(where) == INSTANCE_WIDETAG &&
970 instance_layout(where) != 0 &&
971 layout_depth2_id(LAYOUT(instance_layout(where))) == LAYOUT_LAYOUT_ID) {
972 struct layout* l = (void*)where;
973 struct classoid* c = (void*)native_pointer(l->classoid);
974 if (lc->passno == 1) {
975 // on the first pass, just collect the classoids;
976 struct cons* cons = malloc(sizeof (struct cons));
977 cons->car = (lispobj)c;
978 cons->cdr = (lispobj)lc->list;
979 lc->list = cons;
980 } else {
981 // print some information preceded by a '*' if more than one
982 // layout points to the classoid of this layout
983 int count = count_layout_occurs((lispobj)c, lc->list);
984 struct vector* v = classoid_name((lispobj*)c);
985 char* name =
986 header_widetag(v->header)==SIMPLE_BASE_STRING_WIDETAG ? (char*)v->data : "?";
987 fprintf(stderr, "%c %p %16" OBJ_FMTX " %16" OBJ_FMTX " %p %" OBJ_FMTX " %s\n",
988 count>1 ? '*' : ' ', l, l->clos_hash, l->uw_id_word0,
989 c, l->invalid, name);
994 return 0;
997 static int layouts_cmd(char __attribute__((unused)) **ptr)
999 fprintf(stderr, "Dup, Layout, Hash, ID_Word, Classoid, Invalid, Name\n");
1000 struct layout_collection lc;
1001 lc.list = 0;
1002 for (lc.passno = 1; lc.passno <= 2; ++lc.passno) {
1003 walk_generation(display_layouts, -1, (uword_t)&lc);
1004 #ifdef LISP_FEATURE_IMMOBILE_SPACE
1005 display_layouts((lispobj*)FIXEDOBJ_SPACE_START, fixedobj_free_pointer,
1006 (uword_t)&lc);
1007 #endif
1009 struct cons* l = lc.list;
1010 while (l) {
1011 struct cons* next = (struct cons*)l->cdr;
1012 free(l);
1013 l = next;
1015 return 0;
1018 extern FILE *gc_activitylog_file;
1019 void
1020 ldb_monitor(void)
1022 struct cmd *cmd, *found;
1023 char buf[256];
1024 char *line, *ptr, *token;
1025 int ambig;
1027 printf("Welcome to LDB, a low-level debugger for the Lisp runtime environment.\n");
1028 if (gc_active_p) printf("(GC in progress, oldspace=%d, newspace=%d)\n",
1029 from_space, new_space);
1030 if (gc_activitylog_file) fflush(gc_activitylog_file);
1031 if (!ldb_in) {
1032 #ifndef LISP_FEATURE_WIN32
1033 ldb_in = fopen("/dev/tty","r+");
1034 if (ldb_in == NULL) {
1035 perror("Error opening /dev/tty");
1036 ldb_in = stdin;
1038 #else
1039 ldb_in = stdin;
1040 #endif
1041 ldb_in_fd = fileno(ldb_in);
1044 while (1) {
1045 printf("ldb> ");
1046 fflush(stdout);
1047 line = fgets(buf, sizeof(buf), ldb_in);
1048 if (line == NULL) {
1049 exit(1);
1051 ptr = line;
1052 if ((token = parse_token(&ptr)) == NULL)
1053 continue;
1054 ambig = 0;
1055 found = NULL;
1056 for (cmd = supported_cmds; cmd->cmd != NULL; cmd++) {
1057 if (strcmp(token, cmd->cmd) == 0) {
1058 found = cmd;
1059 ambig = 0;
1060 break;
1062 else if (strncmp(token, cmd->cmd, strlen(token)) == 0) {
1063 if (found)
1064 ambig = 1;
1065 else
1066 found = cmd;
1069 if (ambig)
1070 printf("``%s'' is ambiguous.\n", token);
1071 else if (found == NULL)
1072 printf("unknown command: ``%s''\n", token);
1073 else {
1074 reset_printer();
1075 int done = (*found->fn)(&ptr);
1076 if (done) return;
1081 #ifdef STANDALONE_LDB
1082 void gc_stop_the_world() { } // do nothing
1083 void gc_start_the_world() { } // do nothing
1084 #include <errno.h>
1085 #include <setjmp.h>
1086 #include "core.h"
1087 struct lisp_startup_options lisp_startup_options;
1089 static size_t checked_read(char *section, int fd, void* buf, size_t n)
1091 char label[8];
1092 if (read(fd, label, sizeof label) != 8 || strncmp(label, section, 8))
1093 lose("section messup: %.8s when expecting %s\n", label, section);
1094 if (n) {
1095 size_t result = read(fd, buf, n);
1096 if (result != n) { lose("read failed, errno=%d", errno); }
1097 fprintf(stderr, "%s: %zx bytes\n", section, n + sizeof label);
1098 maybe_show_contents(section, buf, n);
1100 return n + sizeof label;
1103 char *pagetypedesc(int type)
1105 static char what[4];
1106 switch (type) {
1107 case PAGE_TYPE_CODE: return "code";
1108 case PAGE_TYPE_BOXED: return "boxed";
1109 case PAGE_TYPE_UNBOXED: return "raw";
1110 case PAGE_TYPE_MIXED: return "mixed";
1111 default: snprintf(what, 4, "%d", type); return what;
1115 extern void gc_allocate_ptes();
1116 extern void recompute_gen_bytes_allocated();
1117 extern void print_generation_stats();
1118 extern struct thread *alloc_thread_struct(void*);
1120 int load_gc_crashdump(char* pathname)
1122 int fd;
1123 os_context_t *contexts[10], *context;
1124 struct thread* threads = 0;
1125 fd = open(pathname, O_RDONLY);
1126 if (fd < 0) {
1127 fprintf(stderr, "can't open %s\n", pathname);
1128 exit(1);
1130 struct crash_preamble preamble;
1131 struct crash_thread_preamble thread_preamble;
1132 checked_read("preamble", fd, &preamble, sizeof preamble);
1133 printf("static=%"OBJ_FMTX" nbytes=%x\n", preamble.static_start, (int)preamble.static_nbytes);
1134 printf("heap_start=%"OBJ_FMTX" npages=%d\n", preamble.dynspace_start,
1135 (int)preamble.dynspace_npages_used);
1136 // pin_dynspace_code is for display only. It gets recomputed as the
1137 // logical OR of all threads' values of *GC-PIN-CODE-PAGES*.
1138 printf("sprof_enabled=%d pin_dynspace_code=%d packages=%p\n",
1139 preamble.sprof_enabled, preamble.pin_dynspace_code,
1140 (void*)preamble.lisp_package_vector);
1141 lisp_package_vector = preamble.lisp_package_vector;
1142 sb_sprof_enabled = preamble.sprof_enabled;
1143 if (preamble.signature != CRASH_PREAMBLE_SIGNATURE)
1144 lose("Can't load crashdump: bad header (have %"OBJ_FMTX", expect %"OBJ_FMTX")",
1145 preamble.signature, (uword_t)CRASH_PREAMBLE_SIGNATURE);
1146 if (preamble.card_size != GENCGC_CARD_BYTES)
1147 lose("Can't load crashdump: memory parameters differ");
1148 gc_card_table_nbits = preamble.card_table_nbits;
1149 // static + readonly
1150 checked_read("static", fd, (char*)STATIC_SPACE_START, preamble.static_nbytes);
1151 static_space_free_pointer = (lispobj*)(STATIC_SPACE_START + preamble.static_nbytes);
1152 if (!preamble.readonly_nbytes) {
1153 checked_read("R/O", fd, 0, 0);
1154 } else {
1155 void* actual =
1156 os_alloc_gc_space(READ_ONLY_CORE_SPACE_ID, 0, (char*)preamble.readonly_start,
1157 ALIGN_UP(preamble.readonly_nbytes, 4096));
1158 if (actual != (void*)preamble.readonly_start)
1159 fprintf(stderr, "WARNING: wanted R/O space @ %p but got %p\n",
1160 (char*)preamble.readonly_start, actual);
1161 checked_read("R/O", fd, (char*)preamble.readonly_start, preamble.readonly_nbytes);
1162 #ifndef READ_ONLY_SPACE_START /* if non-constant */
1163 READ_ONLY_SPACE_START = preamble.readonly_start;
1164 READ_ONLY_SPACE_END = READ_ONLY_SPACE_START + preamble.readonly_nbytes;
1165 read_only_space_free_pointer = (lispobj*)READ_ONLY_SPACE_END;
1166 #endif
1168 if (!preamble.permgen_nbytes) {
1169 checked_read("perm", fd, 0, 0);
1170 } else {
1171 void* actual =
1172 os_alloc_gc_space(PERMGEN_CORE_SPACE_ID, 0, (char*)preamble.permgen_start,
1173 ALIGN_UP(preamble.permgen_nbytes, 4096));
1174 if (actual != (void*)preamble.permgen_start)
1175 lose("Couldn't map permgen as required (%p)", (char*)preamble.permgen_start);
1176 checked_read("perm", fd, (char*)preamble.permgen_start, preamble.permgen_nbytes);
1177 PERMGEN_SPACE_START = preamble.permgen_start;
1178 permgen_space_free_pointer = (lispobj*)(preamble.permgen_start + preamble.permgen_nbytes);
1181 gc_allocate_ptes();
1182 dynamic_space_size = preamble.dynspace_npages_total * GENCGC_PAGE_BYTES;
1183 next_free_page = preamble.dynspace_npages_used;
1184 DYNAMIC_SPACE_START = preamble.dynspace_start;
1185 long dynspace_nbytes = preamble.dynspace_npages_used * GENCGC_PAGE_BYTES;
1186 char* dynspace = os_alloc_gc_space(DYNAMIC_CORE_SPACE_ID, 0, (char*)preamble.dynspace_start,
1187 DEFAULT_DYNAMIC_SPACE_SIZE);
1188 if (dynspace != (char*)preamble.dynspace_start)
1189 lose("Didn't map dynamic space where expected: %p vs %p",
1190 dynspace, (char*)preamble.dynspace_start);
1191 checked_read("dynamic", fd, (char*)DYNAMIC_SPACE_START, dynspace_nbytes);
1192 fprintf(stderr, "snapshot: %"PAGE_INDEX_FMT" pages in use (%ld bytes)\n",
1193 next_free_page, dynspace_nbytes);
1194 checked_read("PTE", fd, page_table, sizeof (struct page) * next_free_page);
1195 checked_read("cardmark", fd, gc_card_mark, 1+gc_card_table_mask);
1196 // mrgc_init needs to know the dynamic space size so that's why this is delayed
1197 // until after reading the crash preamble.
1198 gc_init();
1199 #ifdef LISP_FEATURE_MARK_REGION_GC
1200 checked_read("allocated", fd, allocation_bitmap, bitmap_size(next_free_page));
1201 extern line_index_t line_count;
1202 checked_read("linemap", fd, line_bytemap, line_count);
1203 #endif
1204 recompute_gen_bytes_allocated();
1205 print_generation_stats();
1206 #ifdef LISP_FEATURE_IMMOBILE_SPACE
1207 extern void gc_init_immobile(),
1208 calc_immobile_space_bounds(),
1209 write_protect_immobile_space();
1210 gc_assert(preamble.fixedobj_size == FIXEDOBJ_SPACE_SIZE);
1211 gc_assert(preamble.text_size == text_space_size);
1212 FIXEDOBJ_SPACE_START = preamble.fixedobj_start;
1213 TEXT_SPACE_START = preamble.text_start;
1214 fixedobj_free_pointer = (lispobj*)preamble.fixedobj_free_pointer;
1215 text_space_highwatermark = (lispobj*)preamble.text_space_highwatermark;
1216 os_alloc_gc_space(IMMOBILE_FIXEDOBJ_CORE_SPACE_ID, 0, (char*)FIXEDOBJ_SPACE_START,
1217 FIXEDOBJ_SPACE_SIZE);
1218 os_alloc_gc_space(IMMOBILE_TEXT_CORE_SPACE_ID, 0, (char*)TEXT_SPACE_START,
1219 text_space_size);
1220 gc_init_immobile(); // allocate the page tables
1221 calc_immobile_space_bounds();
1222 // Read fixedobj space
1223 int usage = (uword_t)fixedobj_free_pointer - FIXEDOBJ_SPACE_START;
1224 checked_read("fixedobj", fd, (char*)FIXEDOBJ_SPACE_START, usage);
1225 // Always read the whole page table regardless of the current space usage
1226 int total_npages = FIXEDOBJ_SPACE_SIZE / IMMOBILE_CARD_BYTES;
1227 checked_read("fixedobj_PTE", fd, fixedobj_pages, total_npages * sizeof sizeof(struct fixedobj_page));
1228 // Read text space
1229 usage = (uword_t)text_space_highwatermark - TEXT_SPACE_START;
1230 char *tlsf_memory_end = (char*)TEXT_SPACE_START + text_space_size;
1231 tlsf_mem_start = preamble.tlsf_mem_start;
1232 fprintf(stderr, "tlsf_mem_start=%p\n", tlsf_mem_start);
1233 int tlsf_memory_size = tlsf_memory_end - (char*)tlsf_mem_start;
1234 checked_read("text", fd, (char*)TEXT_SPACE_START, usage+3*N_WORD_BYTES);
1235 memcpy(tlsf_memory_end-3*N_WORD_BYTES, preamble.sentinel_block, 3*N_WORD_BYTES);
1236 total_npages = text_space_size / IMMOBILE_CARD_BYTES;
1237 int n_bitmap_elts = ALIGN_UP(total_npages, 32) / 32;
1238 checked_read("text_gen", fd, text_page_genmask, total_npages); // 1 byte per page
1239 checked_read("text_WP", fd, text_page_touched_bits, n_bitmap_elts * sizeof (int));
1240 tlsf_control = preamble.tlsf_control_address; // already mapped at a fixed address
1241 // TLSF control was mapped in gc_init_immobile()
1242 checked_read("TLSF_control", fd, tlsf_control, preamble.tlsf_control_size);
1243 int n_tlsf_pages = tlsf_memory_size / IMMOBILE_CARD_BYTES;
1244 fprintf(stderr, "%d TLSF pages\n", n_tlsf_pages);
1245 tlsf_page_sso = malloc(n_tlsf_pages * sizeof (short));
1246 checked_read("TLSF_sso", fd, tlsf_page_sso, n_tlsf_pages * sizeof (short));
1247 write_protect_immobile_space();
1248 #endif
1249 fprintf(stderr, "%d threads:\n", (int)preamble.nthreads);
1250 int i;
1251 for(i=0; i<(int)preamble.nthreads; ++i) {
1252 struct thread* th = alloc_thread_struct(0);
1253 // Push it on the front
1254 th->prev = 0;
1255 th->next = threads;
1256 if (threads) threads->prev = th;
1257 threads = th;
1258 checked_read("thread", fd, &thread_preamble, sizeof thread_preamble);
1259 uword_t* stackptr = (uword_t*)((char*)th->control_stack_end - thread_preamble.control_stack_nbytes);
1260 context = contexts[i] = malloc(preamble.sizeof_context);
1261 nth_interrupt_context(0, th) = context;
1262 if (thread_preamble.has_context) {
1263 checked_read(" ctxt", fd, context, preamble.sizeof_context);
1265 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
1266 *os_context_sp_addr(context) = (uword_t)stackptr;
1267 #ifdef LISP_FEATURE_X86
1268 *os_context_register_addr(context,reg_SP) = (os_context_register_t)stackptr;
1269 #endif
1270 gc_assert(*os_context_register_addr(context,reg_SP) == (os_context_register_t)stackptr);
1271 #elif defined reg_CSP
1272 *os_context_register_addr(context, reg_CSP) = (uword_t)stackptr;
1273 #endif
1274 checked_read(" stack", fd, stackptr, thread_preamble.control_stack_nbytes);
1275 checked_read(" bindings", fd, th->binding_stack_start, thread_preamble.binding_stack_nbytes);
1277 // Capture the 'struct thread' portion of TLS so that things like
1278 // binding stack pointer, and prev,next links stay as they are,
1279 // after copying them back. This way the visual display of number of bytes
1280 // read comes out correctly
1281 struct thread preserve;
1282 memcpy(&preserve, th, sizeof *th);
1283 checked_read(" TLS", fd, th, preamble.tls_size);
1284 // Copy _into_ preserve the values of the allocation regions so that when
1285 // copied back into 'th' we have access to the regions as they were at dump.
1286 preserve.boxed_tlab = th->boxed_tlab;
1287 preserve.cons_tlab = th->cons_tlab;
1288 preserve.mixed_tlab = th->mixed_tlab;
1289 preserve.symbol_tlab = th->symbol_tlab; // not used yet
1290 preserve.sys_mixed_tlab = th->sys_mixed_tlab;
1291 preserve.sys_cons_tlab = th->sys_cons_tlab;
1292 memcpy(th, &preserve, sizeof *th - N_WORD_BYTES);
1294 write_TLS(FREE_INTERRUPT_CONTEXT_INDEX, make_fixnum(1), th);
1295 char* cname = "(no lisp thread)";
1296 if (th->lisp_thread) {
1297 struct thread_instance* instance = (void*)(th->lisp_thread - INSTANCE_POINTER_LOWTAG);
1298 lispobj name = instance->_name;
1299 cname = gc_managed_addr_p(name) && simple_base_string_p(name)
1300 ? vector_sap(name) : 0;
1302 fprintf(stderr, "thread @ %p originally %p, %d bind_stk words, %d val_stk words '%s'\n",
1303 th, (void*)thread_preamble.address,
1304 (int)(thread_preamble.binding_stack_nbytes>>WORD_SHIFT),
1305 (int)(thread_preamble.control_stack_nbytes>>WORD_SHIFT),
1306 cname);
1307 // Scan thread stack looking for words which could be valid pointers,
1308 // but don't find an object when the heap is scanned.
1309 // Realizing that failure to find isn't necessarily an error,
1310 // there's nothing that we can do except show some information.
1311 int nwords = thread_preamble.control_stack_nbytes>>WORD_SHIFT, wordindex;
1312 int n_definitely_valid = 0, n_dangling = 0;
1313 for (wordindex = 0; wordindex < nwords; ++wordindex) {
1314 lispobj word = stackptr[wordindex];
1315 if (DYNAMIC_SPACE_START <= word && word < DYNAMIC_SPACE_START + dynamic_space_size
1316 && (is_lisp_pointer(word) ||
1317 is_code(page_table[find_page_index((void*)word)].type))) {
1318 lispobj* found = search_dynamic_space((void*)word);
1319 if (found) {
1320 __attribute__((unused)) page_index_t ind = find_page_index(found);
1321 #if 0
1322 fprintf(stderr, " sp[%5d] = %"OBJ_FMTX" -> %p (g%d,%s)\n",
1323 wordindex, word, found,
1324 page_table[ind].gen, pagetypedesc(page_table[ind].type));
1325 #endif
1326 ++n_definitely_valid;
1327 } else {
1328 fprintf(stderr, " ! sp[%5d] = %"OBJ_FMTX" (not found)\n",
1329 wordindex, word);
1330 ++n_dangling;
1334 fprintf(stderr, "%d valid pointers", n_definitely_valid);
1335 if (n_dangling) fprintf(stderr, " (%d dangling)", n_dangling);
1336 putc('\n', stderr);
1338 char signature[8];
1339 checked_read("sig", fd, signature, 8);
1340 gc_assert(!strncmp(signature, "SB.Crash", 8));
1341 gc_assert(read(fd, signature, 1) == 0);
1342 close(fd);
1343 all_threads = threads;
1344 return 0;
1347 char *sbcl_runtime;
1348 jmp_buf ldb_toplevel;
1349 int main(int argc, char *argv[], char **envp)
1351 extern void calc_asm_routine_bounds();
1352 if (argc != 2) {
1353 fprintf(stderr, "Usage: ldb crashdump\n");
1354 return 1;
1356 bool have_hardwired_spaces = os_preinit(argv, envp);
1357 allocate_lisp_dynamic_space(have_hardwired_spaces);
1358 load_gc_crashdump(argv[1]);
1359 calc_asm_routine_bounds();
1360 gencgc_verbose = 1;
1361 if (setjmp(ldb_toplevel) != 0)
1362 fprintf(stderr, "Back in ldb, hope everything's Ok\n");
1363 ldb_monitor();
1365 #endif