2 * This software is part of the SBCL system. See the README file for
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"
16 #include <sys/types.h>
19 #ifndef LISP_FEATURE_WIN32
20 #include <sys/resource.h>
36 #include "interrupt.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"
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
58 static FILE *ldb_in
= 0;
59 static int ldb_in_fd
= -1;
61 typedef int cmd(char **ptr
);
63 struct crash_preamble
{
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
;
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
;
85 lispobj lisp_package_vector
;
87 int tlsf_control_size
;
89 char pin_dynspace_code
;
91 struct crash_thread_preamble
{
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] == ' ');
110 int nwords
= nbytes
>>WORD_SHIFT
;
112 for (i
=0;i
<nwords
;++i
)
113 fprintf(stderr
, "%s %16lx", (i
%8)?"":(i
?"\n ":" "), ((uword_t
*)buf
)[i
]);
118 #if defined LISP_FEATURE_X86 || defined LISP_FEATURE_X86_64 // un-tested elsewhere
120 struct filewriter
{ long total
; int fd
; bool verbose
; };
122 static void checked_write(char *section
, struct filewriter
* writer
, void* buf
, long nbytes
)
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
);
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
,
144 extern int pin_all_dynamic_space_code
;
145 int fd
= open(pathname
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
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
);
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
);
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));
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
);
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
);
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
;
233 if (th
!= get_sb_vm_thread()) {
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
));
241 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
242 sp
= (uword_t
)cur_thread_approx_stackptr
;
244 sp
= access_control_stack_pointer(th
);
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
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
;
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
);
268 checked_write(" stack", &writer
, th
->control_stack_start
, nbytes_control_stack
);
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
275 if (verbose
) fprintf(stderr
, "Total: %ld bytes\n", writer
.total
);
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() {
288 // It might make sense for each thread's stop-for-gc handler to close its region
289 // versus doing this loop
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
);
301 fprintf(stderr
, "Need filename\n");
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();
309 fprintf(stderr
, "Unimplemented\n");
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
);
325 fprintf(stderr
, "Need filename\n");
328 #if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_WIN32)
329 current_thread
= all_threads
;
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
335 void list_lisp_threads(int regions
) {
337 fprintf(stderr
, "(thread*,pthread,sb-vm:thread,name)\n");
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;
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
);
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
);
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
);
370 static int threads_cmd(char **ptr
) {
371 list_lisp_threads(more_p(ptr
) && !strncmp(*ptr
, "-r", 2));
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
);
394 result
.header
= SIMPLE_VECTOR_WIDETAG
;
395 result
.length_
= make_fixnum(1);
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
),
404 heap_trace_verbose
= save
;
405 unsuspend_other_threads();
406 lispobj path
= result
.data
[0];
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
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
;
425 static int verify_cmd(char __attribute__((unused
)) **ptr
) {
427 suspend_other_threads();
429 unsuspend_other_threads();
432 static int gc_cmd(char **ptr
) {
434 extern generation_index_t verify_gens
;
435 if (more_p(ptr
)) parse_number(ptr
, &last_gen
);
437 pre_verify_gen_0
= 1;
439 suspend_other_threads();
440 collect_garbage(last_gen
);
441 unsuspend_other_threads();
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
);
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
486 {"verify", "Check heap invariants", verify_cmd
},
487 {"gc", 0, gc_cmd
}, // (this is not the right way to invoke GC)
492 visible(unsigned char c
)
494 if (c
< ' ' || 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
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;
517 if (!strncmp(*ptr
, "-f ", 3)) {
520 } else if (!strncmp(*ptr
, "-d ", 3)) {
525 if (!parse_addr(ptr
, !force
, &addr
)) return 0;
527 if (more_p(ptr
) && !parse_number(ptr
, &count
)) return 0;
531 printf("COUNT must be non-zero.\n");
538 displacement
= N_WORD_BYTES
;
540 displacement
= -N_WORD_BYTES
;
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");
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",
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]));
565 unsigned short *sptr
= (unsigned short *)addr
;
566 printf("0x%08lx 0x%04x 0x%04x "
567 "0x%02x 0x%02x 0x%02x 0x%02x "
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]));
575 #ifdef LISP_FEATURE_GENERATIONAL
577 lispobj ptr
= *(lispobj
*)addr
;
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
);
583 printf(" "); // padding to make MR part line up
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
) ? '*' : ' ');
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
610 printf("invalid Lisp-level address\n");
612 addr
+= displacement
;
620 print_cmd(char **ptr
)
623 if (parse_lispobj(ptr
, &obj
)) print(obj
);
627 int verify_lisp_hashtable(__attribute__((unused
)) struct hash_table
* ht
,
628 __attribute__((unused
)) FILE* file
)
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
);
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]);
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
);
657 if (hvdata
&& hvdata
[j
] != 0xFFFFFFFF) {
659 // print the as-stored hash
661 fprintf(file
, "[%4d] %12lx %16lx %08x %4x (",
662 j
, key
, val
, h
, h
& ivmask
);
664 // print the hash and then fuzzed hash;
665 lispobj h0
= funcall1(ht
->hash_fun
, key
);
666 h
= prefuzz_ht_hash(h0
);
668 fprintf(file
, "[%4d] %12lx %16lx %016lx %08x %4x (", j
,
669 key
, val
, fixnum_value(h0
), h
, h
& ivmask
);
672 unsigned cell
= ivdata
[h
& ivmask
];
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
);
680 if (file
) fprintf(file
, cell
? ")\n" : ") *\n");
685 static int hashtable_cmd(char **ptr
)
688 if (parse_lispobj(ptr
, &obj
)) {
689 int errors
= verify_lisp_hashtable((void*)native_pointer(obj
),
691 if (errors
) fprintf(stderr
, "Errors: %d\n", errors
);
699 extern void gc_show_pte(lispobj
);
701 if (parse_lispobj(ptr
, &obj
)) gc_show_pte(obj
);
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
));
716 printf("BSP\t=\t%p\n", get_binding_stack_pointer(thread
));
718 /* printf("BSP\t=\t%p\n", (void*)SymbolValue(BINDING_STACK_POINTER)); */
722 #ifdef LISP_FEATURE_GENERATIONAL
723 /* printf("DYNAMIC\t=\t%p\n", (void*)DYNAMIC_SPACE_START); */
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
);
736 parse_lispobj(ptr
, &thing
);
737 lispobj function
, args
[3];
738 lispobj result
= NIL
;
742 if (lowtag_of(thing
) == OTHER_POINTER_LOWTAG
) {
743 lispobj
*obj
= native_pointer(thing
);
744 switch (widetag_of(obj
)) {
746 function
= symbol_function((struct symbol
*)obj
);
747 if (function
== NIL
) {
748 printf("Symbol 0x%08lx is undefined.\n", (long unsigned)thing
);
753 function
= FDEFN(thing
)->fun
;
754 if (function
== NIL
) {
755 printf("Fdefn 0x%08lx is undefined.\n", (long unsigned)thing
);
760 printf("0x%08lx is not a function pointer, symbol, "
761 "or fdefn object.\n",
762 (long unsigned)thing
);
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
);
775 while (more_p(ptr
)) {
777 printf("too many arguments (no more than 3 supported)\n");
780 parse_lispobj(ptr
, &args
[numargs
++]);
785 result
= funcall0(function
);
788 result
= funcall1(function
, args
[0]);
791 result
= funcall2(function
, args
[0], args
[1]);
794 result
= funcall3(function
, args
[0], args
[1], args
[2]);
797 lose("unsupported arg count made it past validity check?!");
805 flush_cmd(char __attribute__((unused
)) **ptr
)
812 quit_cmd(char __attribute__((unused
)) **ptr
)
816 printf("Really quit? [y] ");
818 if (fgets(buf
, sizeof(buf
), ldb_in
)) {
819 if (buf
[0] == 'y' || buf
[0] == 'Y' || buf
[0] == '\n')
822 printf("\nUnable to read response, assuming y.\n");
829 help_cmd(char __attribute__((unused
)) **ptr
)
833 for (cmd
= supported_cmds
; cmd
->cmd
!= NULL
; cmd
++)
834 if (cmd
->help
!= NULL
)
835 printf("%s\t%s\n", cmd
->cmd
, cmd
->help
);
840 exit_cmd(char __attribute__((unused
)) **ptr
)
842 return 1; // 'done' flag
846 print_context(os_context_t
*context
)
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)));
860 printf("PC:\t\t 0x%08lx\n", (unsigned long)os_context_pc(context
));
865 print_context_cmd(char **ptr
)
868 struct thread
*thread
= get_sb_vm_thread();
870 free_ici
= fixnum_value(read_TLS(FREE_INTERRUPT_CONTEXT_INDEX
,thread
));
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
));
882 printf("There are %d interrupt contexts.\n", free_ici
);
886 printf("There are no interrupt contexts.\n");
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
));
897 backtrace_cmd(char **ptr
)
899 void lisp_backtrace(int frames
);
903 if (!parse_number(ptr
, &n
)) return 0;
907 printf("Backtrace:\n");
912 static int search_cmd(char **ptr
)
915 if (!parse_addr(ptr
, 1, &addr
)) return 0;
916 lispobj
*obj
= search_all_gc_spaces((void*)addr
);
918 printf("#x%"OBJ_FMTX
"\n", compute_lispobj(obj
));
920 printf("Not found\n");
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());
931 printf("There are no active catchers!\n");
933 while (catch != NULL
) {
934 printf("%p:\n\tuwp : %p\n\tfp : %p\n\t"
935 "code : %p\n\tentry: %p\n\ttag: ",
939 #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64) || defined(LISP_FEATURE_ARM64)
940 component_ptr_from_pc((void*)catch->entry_pc
),
944 (void*)(catch->entry_pc
));
945 brief_print((lispobj
)catch->tag
);
946 catch = catch->previous_catch
;
952 struct layout_collection
{
956 static int count_layout_occurs(lispobj x
, struct cons
* list
)
959 for ( ; list
; list
= (void*)list
->cdr
) if (list
->car
== x
) ++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
;
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
);
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
);
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
;
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
,
1009 struct cons
* l
= lc
.list
;
1011 struct cons
* next
= (struct cons
*)l
->cdr
;
1018 extern FILE *gc_activitylog_file
;
1022 struct cmd
*cmd
, *found
;
1024 char *line
, *ptr
, *token
;
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
);
1032 #ifndef LISP_FEATURE_WIN32
1033 ldb_in
= fopen("/dev/tty","r+");
1034 if (ldb_in
== NULL
) {
1035 perror("Error opening /dev/tty");
1041 ldb_in_fd
= fileno(ldb_in
);
1047 line
= fgets(buf
, sizeof(buf
), ldb_in
);
1052 if ((token
= parse_token(&ptr
)) == NULL
)
1056 for (cmd
= supported_cmds
; cmd
->cmd
!= NULL
; cmd
++) {
1057 if (strcmp(token
, cmd
->cmd
) == 0) {
1062 else if (strncmp(token
, cmd
->cmd
, strlen(token
)) == 0) {
1070 printf("``%s'' is ambiguous.\n", token
);
1071 else if (found
== NULL
)
1072 printf("unknown command: ``%s''\n", token
);
1075 int done
= (*found
->fn
)(&ptr
);
1081 #ifdef STANDALONE_LDB
1082 void gc_stop_the_world() { } // do nothing
1083 void gc_start_the_world() { } // do nothing
1087 struct lisp_startup_options lisp_startup_options
;
1089 static size_t checked_read(char *section
, int fd
, void* buf
, size_t n
)
1092 if (read(fd
, label
, sizeof label
) != 8 || strncmp(label
, section
, 8))
1093 lose("section messup: %.8s when expecting %s\n", label
, section
);
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];
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
)
1123 os_context_t
*contexts
[10], *context
;
1124 struct thread
* threads
= 0;
1125 fd
= open(pathname
, O_RDONLY
);
1127 fprintf(stderr
, "can't open %s\n", pathname
);
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);
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
;
1168 if (!preamble
.permgen_nbytes
) {
1169 checked_read("perm", fd
, 0, 0);
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
);
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.
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
);
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
,
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
));
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();
1249 fprintf(stderr
, "%d threads:\n", (int)preamble
.nthreads
);
1251 for(i
=0; i
<(int)preamble
.nthreads
; ++i
) {
1252 struct thread
* th
= alloc_thread_struct(0);
1253 // Push it on the front
1256 if (threads
) threads
->prev
= 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
;
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
;
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
),
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
);
1320 __attribute__((unused
)) page_index_t ind
= find_page_index(found
);
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
));
1326 ++n_definitely_valid
;
1328 fprintf(stderr
, " ! sp[%5d] = %"OBJ_FMTX
" (not found)\n",
1334 fprintf(stderr
, "%d valid pointers", n_definitely_valid
);
1335 if (n_dangling
) fprintf(stderr
, " (%d dangling)", n_dangling
);
1339 checked_read("sig", fd
, signature
, 8);
1340 gc_assert(!strncmp(signature
, "SB.Crash", 8));
1341 gc_assert(read(fd
, signature
, 1) == 0);
1343 all_threads
= threads
;
1348 jmp_buf ldb_toplevel
;
1349 int main(int argc
, char *argv
[], char **envp
)
1351 extern void calc_asm_routine_bounds();
1353 fprintf(stderr
, "Usage: ldb crashdump\n");
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();
1361 if (setjmp(ldb_toplevel
) != 0)
1362 fprintf(stderr
, "Back in ldb, hope everything's Ok\n");