1 /* code for low-level debugging/diagnostic output */
4 * This software is part of the SBCL system. See the README file for
7 * This software is derived from the CMU CL system, which was
8 * written at Carnegie Mellon University and released into the
9 * public domain. The software is in the public domain and is
10 * provided with absolutely no warranty. See the COPYING and CREDITS
11 * files for more information.
17 #include "genesis/sbcl.h"
22 #include "genesis/gc-tables.h"
29 struct dyndebug_config dyndebug_config
;
34 #define DYNDEBUG_NFLAGS (sizeof(struct dyndebug_config) / sizeof(int))
35 #define dyndebug_init1(lowercase, uppercase) \
37 int *ptr = &dyndebug_config.dyndebug_##lowercase; \
39 names[n] = #lowercase; \
40 char *val = getenv("SBCL_DYNDEBUG__" uppercase); \
41 *ptr = val && strlen(val); \
45 char *names
[DYNDEBUG_NFLAGS
];
46 int *ptrs
[DYNDEBUG_NFLAGS
];
48 dyndebug_init1(gencgc_verbose
, "GENCGC_VERBOSE");
49 dyndebug_init1(safepoints
, "SAFEPOINTS");
50 dyndebug_init1(seh
, "SEH");
51 dyndebug_init1(misc
, "MISC");
52 dyndebug_init1(pagefaults
, "PAGEFAULTS");
53 dyndebug_init1(io
, "IO");
54 dyndebug_init1(runtime_link
, "RUNTIME_LINK");
56 int n_output_flags
= n
;
57 dyndebug_init1(backtrace_when_lost
, "BACKTRACE_WHEN_LOST");
58 dyndebug_init1(sleep_when_lost
, "SLEEP_WHEN_LOST");
60 if (n
!= DYNDEBUG_NFLAGS
)
61 fprintf(stderr
, "Bug in dyndebug_init\n");
63 char *featurelist
= getenv("SBCL_DYNDEBUG");
66 featurelist
= strdup(featurelist
);
67 char *ptr
= featurelist
;
69 char *token
= strtok(ptr
, " ");
72 if (!strcmp(token
, "all"))
73 for (i
= 0; i
< n_output_flags
; i
++)
76 for (i
= 0; i
< (int)DYNDEBUG_NFLAGS
; i
++)
77 if (!strcmp(token
, names
[i
])) {
81 if (i
== DYNDEBUG_NFLAGS
) {
82 fprintf(stderr
, "No such dyndebug flag: `%s'\n", token
);
90 fprintf(stderr
, "Valid flags are:\n");
91 fprintf(stderr
, " all ;enables all of the following:\n");
93 for (i
= 0; i
< (int)DYNDEBUG_NFLAGS
; i
++) {
94 if (i
== n_output_flags
)
95 fprintf(stderr
, "Additional options:\n");
96 fprintf(stderr
, " %s\n", names
[i
]);
100 #if defined(LISP_FEATURE_GENERATIONAL)
101 if (dyndebug_config
.dyndebug_gencgc_verbose
) {
106 #undef dyndebug_init1
107 #undef DYNDEBUG_NFLAGS
112 #include "genesis/static-symbols.h"
113 #include "genesis/primitive-objects.h"
114 #include "genesis/static-symbols.h"
115 #include "genesis/tagnames.h"
117 static int max_lines
= 20, cur_lines
= 0;
118 static int max_depth
= 5, brief_depth
= 2, cur_depth
= 0;
119 static int max_length
= 5;
120 static bool dont_descend
= 0, skip_newline
= 0;
121 static int cur_clock
= 0;
123 static void print_obj(char *prefix
, lispobj obj
);
125 #define NEWLINE_OR_RETURN if (continue_p(1)) newline(NULL); else return;
127 static void indent(int in
)
129 static char *spaces
= " ";
132 fputs(spaces
, stdout
);
136 fputs(spaces
+ 64 - in
, stdout
);
139 static jmp_buf ldb_print_nlx
;
140 static bool continue_p(bool newline
)
144 if (cur_depth
>= max_depth
|| dont_descend
)
153 if (cur_lines
>= max_lines
) {
154 printf("More? [y] ");
157 if (fgets(buffer
, sizeof(buffer
), stdin
)) {
158 if (buffer
[0] == 'n' || buffer
[0] == 'N')
159 longjmp(ldb_print_nlx
, 1);
163 printf("\nUnable to read response, assuming y.\n");
172 static void newline(char *label
)
176 fputs(label
, stdout
);
178 indent(cur_depth
* 2);
182 static void print_unknown(lispobj obj
)
184 printf("unknown object: %p", (void *)obj
);
188 # define OBJ_FMTd PRIdPTR
190 # error "Your inttypes.h is lame"
193 static void brief_fixnum(lispobj obj
)
195 /* KLUDGE: Rather than update the tables in print_obj(), we
196 declare all fixnum-or-unknown tags to be fixnums and sort it
197 out here with a guard clause. */
198 if (!fixnump(obj
)) return print_unknown(obj
);
199 printf("%"OBJ_FMTd
, fixnum_value(obj
));
202 static void print_fixnum(lispobj obj
)
204 /* KLUDGE: Rather than update the tables in print_obj(), we
205 declare all fixnum-or-unknown tags to be fixnums and sort it
206 out here with a guard clause. */
207 if (!fixnump(obj
)) return print_unknown(obj
);
208 printf(": %"OBJ_FMTd
, fixnum_value(obj
));
211 static void brief_otherimm(lispobj obj
)
216 type
= header_widetag(obj
);
218 case CHARACTER_WIDETAG
:
219 c
= obj
>>8; // no mask. show whatever's there
222 case '\0': charname
= "Nul"; break;
223 case '\n': charname
= "Newline"; break;
224 case '\b': charname
= "Backspace"; break;
225 case '\177': charname
= "Delete"; break;
227 if (c
< 32) printf("^%c", c
+64);
228 else printf(c
< 128 ? "%c" : "U+%X", c
);
231 fputs(charname
, stdout
);
234 case UNBOUND_MARKER_WIDETAG
:
235 printf("<unbound marker>");
239 printf("%s", widetag_names
[type
>> 2]);
244 static void print_otherimm(lispobj obj
)
246 printf(", %s", widetag_names
[header_widetag(obj
) >> 2]);
248 switch (header_widetag(obj
)) {
249 case CHARACTER_WIDETAG
:
255 case UNBOUND_MARKER_WIDETAG
:
259 printf(": data=%"OBJ_FMTX
, (obj
>>8));
264 static void brief_list(lispobj obj
)
276 if (++length
>= max_length
) {
281 print_obj("", CONS(obj
)->car
);
282 obj
= CONS(obj
)->cdr
;
295 void print_list_car_ptrs(lispobj obj
, FILE* f
)
299 if (obj
== NIL
) { fprintf(f
, "NIL"); return; }
301 if (++len
> 20) { fprintf(f
, "...)"); return; }
302 fprintf(f
, "%c%p", sep
, (void*)CONS(obj
)->car
);
303 obj
= CONS(obj
)->cdr
;
305 } while (listp(obj
) && obj
!= NIL
);
306 if (obj
!= NIL
) fprintf(f
, " . %p", (void*)obj
);
311 static void print_list(lispobj obj
)
316 print_obj("car: ", CONS(obj
)->car
);
317 print_obj("cdr: ", CONS(obj
)->cdr
);
321 // takes native pointer as input
322 char * simple_base_stringize(struct vector
* string
)
324 if (widetag_of(&string
->header
) == SIMPLE_BASE_STRING_WIDETAG
)
325 return (char*)string
->data
;
326 int length
= vector_len(string
);
327 char * newstring
= malloc(length
+1);
328 uint32_t * data
= (uint32_t*)string
->data
;
330 for(i
=0;i
<length
;++i
)
331 newstring
[i
] = data
[i
] < 128 ? data
[i
] : '?';
332 newstring
[length
] = 0;
336 static void brief_struct(lispobj obj
)
338 struct instance
*instance
= INSTANCE(obj
);
339 extern struct vector
* instance_classoid_name(lispobj
*);
340 struct vector
* classoid_name
;
341 classoid_name
= instance_classoid_name((lispobj
*)instance
);
342 lispobj layout
= instance_layout((lispobj
*)instance
);
343 if ( classoid_name
) {
344 char * namestring
= simple_base_stringize(classoid_name
);
345 printf("#<ptr to %"OBJ_FMTX
" %s instance>", layout
, namestring
);
346 if ( namestring
!= (char*)classoid_name
->data
)
349 printf("#<ptr to %"OBJ_FMTX
" instance>", layout
);
353 #include "genesis/defstruct-description.h"
354 static bool tagged_slot_p(struct layout
*layout
, int slot_index
)
356 // Since we're doing this scan, we could return the name
357 // and exact raw type.
358 if (instancep(layout
->_info
)) {
359 struct defstruct_description
* dd
= (void*)(layout
->_info
-INSTANCE_POINTER_LOWTAG
);
360 lispobj slots
= dd
->slots
;
361 for ( ; slots
!= NIL
; slots
= CONS(slots
)->cdr
) {
362 struct defstruct_slot_description
* dsd
=
363 (void*)(CONS(slots
)->car
-INSTANCE_POINTER_LOWTAG
);
364 if ((fixnum_value(dsd
->bits
) >> DSD_INDEX_SHIFT
) == slot_index
)
365 return (fixnum_value(dsd
->bits
) & DSD_RAW_TYPE_MASK
) == 0;
368 /* Revision 2b783b49 said to prefer LAYOUT-INFO vs BITMAP because the bitmap
369 * can indicate a 0 bit ("raw") for any slot that _may_ be ignored by GC, such as
370 * slots constrained to FIXNUM. Unfortunately that misses that CONDITION instances
371 * have trailing variable-length tagged data. In practice an instance may have raw
372 * words only if it has a DD, which most CONDITION subtypes do not. Therefore this
373 * could almost always return 1. But layout-of-layout is an important use of trailing
374 * raw slots. Attempting to print random words as tagged could be disastrous.
375 * Therefore, test the bitmap if the above loop failed to find slot_index. */
376 return bitmap_logbitp(slot_index
, get_layout_bitmap(layout
));
379 static void print_struct(lispobj obj
)
381 struct instance
*instance
= INSTANCE(obj
);
384 lispobj layout
= instance_layout(native_pointer(obj
));
385 print_obj("type: ", layout
);
386 for (i
=INSTANCE_DATA_START
; i
<instance_length(instance
->header
); i
++) {
387 sprintf(buffer
, "slot %d: ", i
);
388 if (layout
&& tagged_slot_p(LAYOUT(layout
), i
)) {
389 print_obj(buffer
, instance
->slots
[i
]);
392 printf("\n\t %s0x%"OBJ_FMTX
" [raw]", buffer
, instance
->slots
[i
]);
397 void show_lstring(struct vector
* string
, int quotes
, FILE *s
)
400 int i
, len
= vector_len(string
);
402 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
403 if (widetag_of(&string
->header
) == SIMPLE_CHARACTER_STRING_WIDETAG
) {
406 putc('u', s
); /* an arbitrary notational convention */
409 if (quotes
) putc('"', s
);
410 for (i
=0 ; i
<len
; i
++) {
411 // hopefully the compiler will optimize out the ucs4_p test
412 // when the runtime is built without Unicode support
415 ch
= i
[(uint32_t*)string
->data
];
417 ch
= i
[(char*)string
->data
];
418 if (ch
>= 32 && ch
< 127) {
419 if (quotes
&& (ch
== '"' || ch
== '\\'))
423 fprintf(s
, ch
> 0xffff ? "\\U%08X" :
424 ch
> 0xff ? "\\u%04X" : "\\x%02X", ch
);
427 if (quotes
) putc('"', s
);
430 static void brief_fun_or_otherptr(lispobj obj
)
432 lispobj
*ptr
, header
;
434 struct symbol
*symbol
;
436 ptr
= native_pointer(obj
);
438 type
= header_widetag(header
);
441 symbol
= (struct symbol
*)ptr
;
442 lispobj package
= symbol_package(symbol
);
445 show_lstring(symbol_name(symbol
), 0, stdout
);
448 case SIMPLE_BASE_STRING_WIDETAG
:
449 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
450 case SIMPLE_CHARACTER_STRING_WIDETAG
:
452 show_lstring((struct vector
*)ptr
, 1, stdout
);
457 brief_otherimm(header
);
458 if (type
== FDEFN_WIDETAG
) { // Try to print name, if a symbol
459 // FIXME: more address validity checks perhaps?
460 lispobj name
= ((struct fdefn
*)ptr
)->name
;
461 if (lowtag_of(name
) == OTHER_POINTER_LOWTAG
462 && widetag_of(native_pointer(name
)) == SYMBOL_WIDETAG
) {
464 struct vector
* str
= symbol_name(SYMBOL(name
));
465 safely_show_lstring(str
, 0, stdout
);
472 static void print_slots(char **slots
, int count
, lispobj
*ptr
)
474 while (count
-- > 0) {
476 // kludge for encoded slots
478 char* slot_name
= *slots
;
479 if (N_WORD_BYTES
== 8 && !strcmp(slot_name
, "boxed_size: ")) word
= word
& 0xFFFFFFFF;
480 #ifdef LISP_FEATURE_COMPACT_SYMBOL
481 else if (!strcmp(slot_name
, "name: ")) word
= decode_symbol_name(word
);
483 print_obj(slot_name
, word
);
486 print_obj("???: ", *ptr
);
492 static void print_fun_or_otherptr(lispobj obj
)
497 lispobj
*ptr
= native_pointer(obj
);
499 printf(" (NULL Pointer)");
503 int count
= object_size(ptr
)-1;
504 uword_t header
= *ptr
++;
505 int type
= header_widetag(header
);
507 print_obj("header: ", header
);
508 if (!other_immediate_lowtag_p(header
)) {
510 printf("(invalid header object)");
522 #if N_WORD_BITS == 32
527 (unsigned long) *--ptr
, (count
?"_":""));
531 print_slots(ratio_slots
, count
, ptr
);
534 case COMPLEX_RATIONAL_WIDETAG
:
535 print_slots(complex_slots
, count
, ptr
);
539 // Only 1 byte of a symbol header conveys its size.
540 // The other bytes may be freely used by the backend.
541 print_slots(symbol_slots
, count
& 0xFF, ptr
);
542 struct symbol
* sym
= (void*)(ptr
- 1);
543 if (symbol_function(sym
) != NIL
) print_obj("fun: ", symbol_function(sym
));
544 #ifdef LISP_FEATURE_SB_THREAD
545 int tlsindex
= tls_index_of(sym
);
546 struct thread
*th
= get_sb_vm_thread();
547 if (th
!= 0 && tlsindex
!= 0) {
548 lispobj v
= *(lispobj
*)(tlsindex
+ (char*)th
);
549 print_obj("tlsval: ", v
);
552 #ifdef LISP_FEATURE_COMPACT_SYMBOL
553 // print_obj doesn't understand raw words, so make it a fixnum
554 int pkgid
= symbol_package_id(sym
) << N_FIXNUM_TAG_BITS
;
555 print_obj("pkgid: ", pkgid
);
559 #if N_WORD_BITS == 32
560 case SINGLE_FLOAT_WIDETAG
:
562 printf("%g", ((struct single_float
*)native_pointer(obj
))->value
);
565 case DOUBLE_FLOAT_WIDETAG
:
567 printf("%g", ((struct double_float
*)native_pointer(obj
))->value
);
570 #ifdef LONG_FLOAT_WIDETAG
571 case LONG_FLOAT_WIDETAG
:
573 printf("%Lg", ((struct long_float
*)native_pointer(obj
))->value
);
577 #ifdef COMPLEX_SINGLE_FLOAT_WIDETAG
578 case COMPLEX_SINGLE_FLOAT_WIDETAG
:
580 #ifdef LISP_FEATURE_64_BIT
581 printf("%g", ((struct complex_single_float
*)native_pointer(obj
))->data
.data
[0]);
583 printf("%g", ((struct complex_single_float
*)native_pointer(obj
))->real
);
586 #ifdef LISP_FEATURE_64_BIT
587 printf("%g", ((struct complex_single_float
*)native_pointer(obj
))->data
.data
[1]);
589 printf("%g", ((struct complex_single_float
*)native_pointer(obj
))->imag
);
594 #ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG
595 case COMPLEX_DOUBLE_FLOAT_WIDETAG
:
597 printf("%g", ((struct complex_double_float
*)native_pointer(obj
))->real
);
599 printf("%g", ((struct complex_double_float
*)native_pointer(obj
))->imag
);
603 #ifdef COMPLEX_LONG_FLOAT_WIDETAG
604 case COMPLEX_LONG_FLOAT_WIDETAG
:
606 printf("%Lg", ((struct complex_long_float
*)native_pointer(obj
))->real
);
608 printf("%Lg", ((struct complex_long_float
*)native_pointer(obj
))->imag
);
612 case SIMPLE_BASE_STRING_WIDETAG
:
613 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
614 case SIMPLE_CHARACTER_STRING_WIDETAG
:
617 show_lstring((struct vector
*)native_pointer(obj
), 1, stdout
);
620 case SIMPLE_VECTOR_WIDETAG
:
623 long length
= vector_len(VECTOR(obj
));
624 printf("length = %ld", length
);
627 while (length
-- > 0) {
628 sprintf(buffer
, "%d: ", index
++);
629 print_obj(buffer
, *ptr
++);
634 case SIMPLE_BIT_VECTOR_WIDETAG
:
637 long length
= vector_len(VECTOR(obj
));
638 printf("length = %ld : ", length
);
639 int bits_to_print
= (length
< N_WORD_BITS
) ? length
: N_WORD_BITS
;
640 uword_t word
= ptr
[1];
642 for(i
=0; i
<bits_to_print
; ++i
) {
643 putchar((word
& 1) ? '1' : '0');
644 if ((i
%8)==7) putchar('_');
647 if(bits_to_print
< length
) printf("...");
652 case CODE_HEADER_WIDETAG
:
653 // ptr was already bumped up
654 count
= code_header_words((struct code
*)(ptr
-1));
655 for_each_simple_fun(fun_index
, fun
, (struct code
*)(ptr
-1), 0, {
656 sprintf(buffer
, "f[%d]: ", fun_index
);
657 print_obj(buffer
, make_lispobj(fun
,FUN_POINTER_LOWTAG
));
659 print_slots(code_slots
, count
-1, ptr
);
662 case SIMPLE_FUN_WIDETAG
:
663 print_obj("code: ", fun_code_tagged(ptr
-1));
664 print_slots(simple_fun_slots
,
665 sizeof simple_fun_slots
/sizeof(char*)-1, ptr
);
668 #ifdef RETURN_PC_WIDETAG
669 case RETURN_PC_WIDETAG
:
670 print_obj("code: ", obj
- (count
* 4));
674 case CLOSURE_WIDETAG
:
675 print_slots(closure_slots
,
676 count
& SHORT_HEADER_MAX_WORDS
, ptr
);
679 case FUNCALLABLE_INSTANCE_WIDETAG
:
680 print_slots(funcallable_instance_slots
,
681 count
& SHORT_HEADER_MAX_WORDS
, ptr
);
684 case VALUE_CELL_WIDETAG
:
685 print_slots(value_cell_slots
, 1, ptr
);
690 printf("%p", (void*)*ptr
);
693 case WEAK_POINTER_WIDETAG
:
694 print_slots(weak_pointer_slots
, 1, ptr
);
697 case CHARACTER_WIDETAG
:
698 case UNBOUND_MARKER_WIDETAG
:
700 printf("pointer to an immediate?");
704 print_slots(fdefn_slots
, 2, ptr
);
705 print_obj("entry: ", decode_fdefn_rawfun((struct fdefn
*)(ptr
-1)));
708 // Make some vectors printable from C, for when all hell breaks lose
709 case SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG
:
712 long length
= vector_len(VECTOR(obj
));
713 uint32_t * data
= (uint32_t*)(ptr
+ 1);
716 for (i
=0; i
<length
; ++i
) {
717 printf("%s%d", i
>0?" ":"", data
[i
]);
718 if(i
==255 && length
>256) { printf(" ..."); break; }
725 if (specialized_vector_widetag_p(type
))
726 printf("length = %"OBJ_FMTd
, vector_len(VECTOR(obj
)));
728 printf("Unknown header object?");
733 static void print_obj(char *prefix
, lispobj obj
)
735 #include "genesis/print.inc"
736 int type
= lowtag_of(obj
);
737 struct var
*var
= lookup_by_obj(obj
);
739 bool verbose
= cur_depth
< brief_depth
;
741 if (!continue_p(verbose
))
744 if (var
!= NULL
&& var_clock(var
) == cur_clock
)
747 if (var
== NULL
&& is_lisp_pointer(obj
))
748 var
= define_var(NULL
, obj
, 0);
751 var_setclock(var
, cur_clock
);
753 void (**fns
)(lispobj
) = NULL
;
757 sprintf(buffer
, "$%s=", var_name(var
));
762 printf("%s0x%08lx: ", prefix
, (unsigned long) obj
);
763 if (cur_depth
< brief_depth
) {
764 fputs(lowtag_names
[type
], stdout
);
772 printf("$%s", var_name(var
));
775 printf("$%s=", var_name(var
));
781 else if (is_lisp_pointer(obj
) && !gc_managed_addr_p(obj
))
782 printf("(bad-address)");
796 void print(lispobj obj
)
803 if (!setjmp(ldb_print_nlx
))
809 void brief_print(lispobj obj
)
821 // The following accessors, which take a valid native pointer as input
822 // and return a Lisp string, are designed to be foolproof during GC,
823 // hence all the forwarding checks.
825 struct vector
* symbol_name(struct symbol
* sym
)
827 if (forwarding_pointer_p((lispobj
*)sym
))
828 sym
= (void*)native_pointer(forwarding_pointer_value((lispobj
*)sym
));
829 lispobj name
= sym
->name
;
830 if (lowtag_of(name
) != OTHER_POINTER_LOWTAG
) return NULL
;
831 lispobj string
= decode_symbol_name(name
);
832 return VECTOR(follow_fp(string
)); // can't have a nameless symbol
834 struct vector
* classoid_name(lispobj
* classoid
)
836 if (forwarding_pointer_p(classoid
))
837 classoid
= native_pointer(forwarding_pointer_value(classoid
));
838 // Classoids are named by symbols even though a CLASS name is arbitrary (theoretically)
839 lispobj sym
= ((struct classoid
*)classoid
)->name
;
840 return lowtag_of(sym
) != OTHER_POINTER_LOWTAG
? NULL
: symbol_name(SYMBOL(sym
));
842 struct vector
* layout_classoid_name(lispobj
* layout
)
844 if (forwarding_pointer_p(layout
))
845 layout
= native_pointer(forwarding_pointer_value(layout
));
846 lispobj classoid
= ((struct layout
*)layout
)->classoid
;
847 return instancep(classoid
) ? classoid_name(native_pointer(classoid
)) : NULL
;
849 struct vector
* instance_classoid_name(lispobj
* instance
)
851 if (forwarding_pointer_p(instance
))
852 instance
= native_pointer(forwarding_pointer_value(instance
));
853 lispobj layout
= instance_layout(instance
);
854 return instancep(layout
) ? layout_classoid_name(native_pointer(layout
)) : NULL
;
856 void safely_show_lstring(struct vector
* string
, int quotes
, FILE *s
)
858 extern void show_lstring(struct vector
*, int, FILE*);
859 if (forwarding_pointer_p((lispobj
*)string
))
860 string
= (struct vector
*)forwarding_pointer_value((lispobj
*)string
);
862 #ifdef SIMPLE_CHARACTER_STRING_WIDETAG
863 header_widetag(string
->header
) == SIMPLE_CHARACTER_STRING_WIDETAG
||
865 header_widetag(string
->header
) == SIMPLE_BASE_STRING_WIDETAG
)
866 show_lstring(string
, quotes
, s
);
868 fprintf(s
, "#<[widetag=%02X]>", header_widetag(string
->header
));