1 \section[StgDebug]{Useful debugging routines for the STG machine}
3 Call these functions directly from a debugger to print Nodes,
4 registers, stacks, etc.
8 make EXTRA_HC_OPTS='-optl-u -optl_DEBUG_LoadSymbols' ghci
10 is usually required to get this code included in the object code.)
12 Nota Bene: in a registerised build, you have to save all the registers
13 in their appropriate SAVE locations before calling any code that needs
14 register contents. (This has to be repeated every time you emerge
17 On a sparc, this can be done by the following gdb script
21 set *(&MainRegTable+8) = $l1
22 set *(&MainRegTable+9) = $l2
23 set *(&MainRegTable+10) = $l3
24 set *(&MainRegTable+11) = $l4
25 set *(&MainRegTable+12) = $l5
26 set *(&MainRegTable+13) = $l6
27 set *(&MainRegTable+14) = $l7
28 set *(&MainRegTable+4) = $f2
29 set *(&MainRegTable+5) = $f3
30 set *(&MainRegTable+6) = $f4
31 set *(&MainRegTable+7) = $f5
33 set *((double *) &MainRegTable+0) = (double) $f6
34 set *((double *) &MainRegTable+2) = (double) $f8
35 set *(&MainRegTable+23) = $l0
36 set *(&MainRegTable+16) = $i0
37 set *(&MainRegTable+17) = $i1
38 set *(&MainRegTable+18) = $i2
39 set *(&MainRegTable+19) = $i3
40 set *(&StorageMgrInfo+0) = $i4
41 set *(&StorageMgrInfo+1) = $i5
46 New code (attempts to interpret heap/stack contents)
47 DEBUG_LoadSymbols( filename ) Load symbol table from object file
48 (not essential but useful initialisation)
49 DEBUG_PrintA( depth, size ) Print "depth" entries from A stack
50 DEBUG_PrintB( depth, size ) ditto
51 DEBUG_Where( depth, size ) Ambitious attempt to print stacks
52 symbolically. Result is a little inaccurate
53 but often good enough to do the job.
54 DEBUG_NODE( closure, size ) Print a closure on the heap
55 DEBUG_INFO_TABLE(closure) Print info-table of a closure
56 DEBUG_SPT( size ) Print the Stable Pointer Table
58 (Use variable DEBUG_details to set level of detail shown.)
60 Older code (less fancy ==> more reliable)
61 DEBUG_ASTACK(lines) Print "lines" lines of the A Stack
62 DEBUG_BSTACK(lines) Print "lines" lines of the B Stack
63 DEBUG_UPDATES(frames) Print "frames" update frames
64 DEBUG_REGS() Print register values
65 DEBUG_MP() Print the MallocPtr Lists
68 #if defined(RUNTIME_DEBUGGING)
73 \subsection[StgDebug_Symbol_Tables]{Loading Symbol Tables}
75 NB: this assumes a.out files - won't work on Alphas.
76 ToDo: At least add some #ifdefs
81 /* #include <nlist.h> */
85 #define FROM_START 0 /* for fseek */
87 /* Simple lookup table */
89 /* Current implementation is pretty dumb! */
97 static int table_uninitialised = 1;
98 static int max_table_size;
99 static int table_size;
100 static struct entry* table;
103 void reset_table( int size )
105 max_table_size = size;
107 table = (struct entry *) malloc( size * sizeof( struct entry ) );
113 /* Could sort it... */
117 void insert( unsigned value, int index, char *name )
119 if ( table_size >= max_table_size ) {
120 fprintf( stderr, "Symbol table overflow\n" );
123 table[table_size].value = value;
124 table[table_size].index = index;
125 table[table_size].name = name;
126 table_size = table_size + 1;
130 int lookup( unsigned value, int *result )
133 for( i = 0; i < table_size && table[i].value != value; ++i ) {
135 if (i < table_size) {
136 *result = table[i].index;
143 static int lookup_name( char *name, unsigned *result )
146 for( i = 0; i < table_size && strcmp(name,table[i].name) != 0; ++i ) {
148 if (i < table_size) {
149 *result = table[i].value;
158 "std"++xs -> "Zstd"++xs
172 char_to_c '\'' = "Zq"
175 char_to_c c = "Z" ++ show (ord c)
178 static char unZcode( char ch )
219 /* Precondition: out big enough to handle output (about twice length of in) */
220 static void enZcode( char *in, char *out )
226 for( i = 0; in[i] != '\0'; ++i ) {
302 static int lookupForName( P_ addr, char **result )
305 for( i = 0; i < table_size && table[i].value != (unsigned) addr; ++i ) {
307 if (i < table_size) {
308 *result = table[i].name;
315 static void printZcoded( char *raw )
319 /* start at 1 to skip the leading "_" */
320 for( j = 1; raw[j] != '\0'; /* explicit */) {
322 putchar(unZcode(raw[j+1]));
331 static void printName( P_ addr )
335 if (lookupForName( addr, &raw )) {
338 printf("0x%x", addr);
342 /* Fairly ad-hoc piece of code that seems to filter out a lot of
343 rubbish like the obj-splitting symbols */
346 int isReal( unsigned char type, char *name )
348 int external = type & N_EXT;
349 int tp = type & N_TYPE;
351 if (tp == N_TEXT || tp == N_DATA) {
352 return( name[0] == '_' && name[1] != '_' );
358 void DEBUG_LoadSymbols( char *name )
368 struct nlist *symbol_table;
371 long str_size; /* assumed 4 bytes.... */
376 binary = fopen( name, "r" );
377 if (binary == NULL) {
378 fprintf( stderr, "Can't open symbol table file \"%s\".\n", name );
382 if (fread( &header, sizeof( struct exec ), 1, binary ) != 1) {
383 fprintf( stderr, "Can't read symbol table header.\n" );
386 if ( N_BADMAG( header ) ) {
387 fprintf( stderr, "Bad magic number in symbol table header.\n" );
393 sym_offset = N_SYMOFF( header );
394 sym_size = header.a_syms;
395 num_syms = sym_size / sizeof( struct nlist );
396 fseek( binary, sym_offset, FROM_START );
398 symbol_table = (struct nlist *) malloc( sym_size );
399 if (symbol_table == NULL) {
400 fprintf( stderr, "Can't allocate symbol table of size %d\n", sym_size );
404 printf("Reading %d symbols\n", num_syms);
406 if (fread( symbol_table, sym_size, 1, binary ) != 1) {
407 fprintf( stderr, "Can't read symbol table\n");
413 str_offset = N_STROFF( header );
414 fseek( binary, str_offset, FROM_START );
416 if (fread( &str_size, 4, 1, binary ) != 1) {
417 fprintf( stderr, "Can't read string table size\n");
421 /* apparently the size of the string table includes the 4 bytes that
424 string_table = (char *) malloc( str_size );
425 if (string_table == NULL) {
426 fprintf( stderr, "Can't allocate string table of size %d\n", str_size );
430 if (fread( string_table+4, str_size-4, 1, binary ) != 1) {
431 fprintf( stderr, "Can't read string table\n");
436 for( i = 0; i != num_syms; ++i ) {
437 unsigned char type = symbol_table[i].n_type;
438 unsigned value = symbol_table[i].n_value;
439 char *str = &string_table[symbol_table[i].n_un.n_strx];
441 if ( isReal( type, str ) ) {
442 num_real_syms = num_real_syms + 1;
446 printf("Of which %d are real symbols\n", num_real_syms);
449 for( i = 0; i != num_syms; ++i ) {
450 unsigned char type = symbol_table[i].n_type;
451 unsigned value = symbol_table[i].n_value;
452 char *str = &string_table[symbol_table[i].n_un.n_strx];
454 if ( isReal(type, str) ) {
455 printf("Symbol %d. Extern? %c. Type: %c. Value: 0x%x. Name: %s\n",
457 (external ? 'y' : 'n'),
466 reset_table( num_real_syms );
468 for( i = 0; i != num_syms; ++i ) {
469 unsigned char type = symbol_table[i].n_type;
470 unsigned value = symbol_table[i].n_value;
471 char *str = &string_table[symbol_table[i].n_un.n_strx];
473 if ( isReal( type, str ) ) {
474 insert( value, i, str );
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 \subsection[StgDebug_PrettyPrinting]{Pretty printing internal structures}
487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490 #include "../storage/SMinternal.h"
493 #define HP_BOT appelInfo.oldbase
495 #define HP_BOT dualmodeInfo.modeinfo[dualmodeInfo.mode].base
497 #define HP_BOT semispaceInfo[semispace].base
499 #define HP_BOT compactingInfo.base
501 unknown garbage collector - help, help!
506 /* range: 0..NUM_LEVELS_OF_DETAIL-1. Level of machine-related detail shown */
507 #define NUM_LEVELS_OF_DETAIL 3
508 static int DEBUG_details = 2;
512 /* Determine the size and number of pointers for this kind of closure */
515 getClosureShape( P_ node, int *vhs, int *size, int *ptrs, char **type )
517 /* The result is used for printing out closure contents. If the
518 info-table is mince, we'd better conservatively guess there's
519 nothing in the closure to avoid chasing non-ptrs. */
523 *type = "*unknown info type*";
525 /* ToDo: if in garbage collector, consider subtracting some weird offset which some GCs add to infoptr */
527 /* The order here precisely reflects that in SMInfoTables.lh to make
528 it easier to check that this list is complete. */
529 switch(INFO_TYPE(INFO_PTR(node)))
531 case INFO_SPEC_U_TYPE:
532 *vhs = 0; /* by decree */
533 *size = SPEC_CLOSURE_SIZE(node);
534 *ptrs = SPEC_CLOSURE_NoPTRS(node);
537 case INFO_SPEC_N_TYPE:
538 *vhs = 0; /* by decree */
539 *size = SPEC_CLOSURE_SIZE(node);
540 *ptrs = SPEC_CLOSURE_NoPTRS(node);
544 case INFO_GEN_U_TYPE:
546 *size = GEN_CLOSURE_SIZE(node);
547 *ptrs = GEN_CLOSURE_NoPTRS(node);
550 case INFO_GEN_N_TYPE:
552 *size = GEN_CLOSURE_SIZE(node);
553 *ptrs = GEN_CLOSURE_NoPTRS(node);
559 *size = DYN_CLOSURE_SIZE(node);
560 *ptrs = DYN_CLOSURE_NoPTRS(node);
564 case INFO_TUPLE_TYPE:
566 *size = TUPLE_CLOSURE_SIZE(node);
567 *ptrs = TUPLE_CLOSURE_NoPTRS(node);
573 *size = DATA_CLOSURE_SIZE(node);
574 *ptrs = DATA_CLOSURE_NoPTRS(node);
578 case INFO_MUTUPLE_TYPE:
580 *size = MUTUPLE_CLOSURE_SIZE(node);
581 *ptrs = MUTUPLE_CLOSURE_NoPTRS(node);
585 case INFO_IMMUTUPLE_TYPE:
587 *size = MUTUPLE_CLOSURE_SIZE(node);
588 *ptrs = MUTUPLE_CLOSURE_NoPTRS(node);
592 case INFO_STATIC_TYPE:
594 *size = INFO_SIZE(INFO_PTR(node));
595 *ptrs = INFO_NoPTRS(INFO_PTR(node));
599 case INFO_CONST_TYPE:
606 case INFO_CHARLIKE_TYPE:
613 case INFO_INTLIKE_TYPE:
622 *size = INFO_SIZE(INFO_PTR(node));
627 /* most of the following are plausible guesses (particularily VHSs) ADR */
631 *size = BQ_CLOSURE_SIZE(node);
632 *ptrs = BQ_CLOSURE_NoPTRS(node);
635 printf("Panic: found BQ Infotable in non-threaded system.\n");
641 *size = IND_CLOSURE_SIZE(node);
642 *ptrs = IND_CLOSURE_NoPTRS(node);
647 *vhs = 0; /* ?? ADR */
648 *size = INFO_SIZE(INFO_PTR(node));
653 case INFO_FETCHME_TYPE:
656 *size = FETCHME_CLOSURE_SIZE(node);
657 *ptrs = FETCHME_CLOSURE_PTRS(node);
660 printf("Panic: found FETCHME Infotable in sequential system.\n");
667 *size = FMBQ_CLOSURE_SIZE(node);
668 *ptrs = FMBQ_CLOSURE_PTRS(node);
671 printf("Panic: found FMBQ Infotable in sequential system.\n");
680 *type = "BlockedFetch";
682 printf("Panic: found BlockedFetch Infotable in sequential system.\n");
687 /* Conservative underestimate: this will contain a regtable
688 which comes nowhere near fitting the standard "p ptrs; s-p
689 non-ptrs" format. ADR */
696 printf("Panic: found TSO Infotable in non-threaded system.\n");
701 /* Conservative underestimate: this will contain stuff
702 which comes nowhere near fitting the standard "p ptrs; s-p
703 non-ptrs" format. JSM */
710 printf("Panic: found STKO Infotable in non-threaded system.\n");
714 /* There are no others in SMInfoTables.lh 11/5/94 ADR*/
716 printf("Invalid/unknown info type %d\n", INFO_TYPE(INFO_PTR(node)));
725 printf("0x%08lx", word);
730 printAddress( P_ address )
733 PP_ SpA = STKO_SpA(SAVE_StkO);
734 PP_ SuA = STKO_SuA(SAVE_StkO);
735 P_ SpB = STKO_SpB(SAVE_StkO);
736 P_ SuB = STKO_SuB(SAVE_StkO);
745 PP_ botA = stackInfo.botA;
746 P_ botB = stackInfo.botB;
751 /* ToDo: check if it's in text or data segment. */
753 /* The @-1@s in stack comparisions are because we sometimes use the
754 address of just below the stack... */
756 if (lookupForName( address, &name )) {
759 if (DEBUG_details > 1) {
760 printWord( (W_) address );
763 if (HpBot <= address && address < Hp) {
764 printf("Hp[%d]", address - HpBot);
765 } else if (SUBTRACT_A_STK((PP_)address, botA) >= -1 && SUBTRACT_A_STK(SpA, (PP_)address) >= 0) {
766 printf("SpA[%d]", SUBTRACT_A_STK((PP_)address, botA));
767 } else if (SUBTRACT_B_STK(address, botB) >= -1 && SUBTRACT_B_STK(SpB, address) >= 0) {
768 /* ToDo: check if it's an update frame */
769 printf("SpB[%d]", SUBTRACT_B_STK(address, botB));
771 printWord( (W_) address );
778 printIndentation( int indentation )
781 for (i = 0; i < indentation; ++i) { printf(" "); }
784 /* The weight parameter is used to (eventually) break cycles */
787 printStandardShapeClosure(
790 P_ closure, int vhs, int size, int noPtrs
794 PP_ SpA = STKO_SpA(SAVE_StkO);
795 PP_ SuA = STKO_SuA(SAVE_StkO);
796 P_ SpB = STKO_SpB(SAVE_StkO);
797 P_ SuB = STKO_SuB(SAVE_StkO);
806 extern void printClosure PROTO( (P_, int, int) );
807 int numValues = size - vhs;
810 if (DEBUG_details > 1) {
811 printAddress( closure );
814 printName((P_)INFO_PTR(closure));
816 if ( numValues > 0 ) {
817 int newWeight = weight-1 ;
818 /* I've tried dividing the weight by size to share it out amongst
819 sub-closures - but that didn't work too well. */
824 while (i < numValues) {
825 P_ data = (P_) closure[_FHS + vhs + i];
827 printIndentation(indentation+1);
829 printClosure( data, indentation+1, newWeight);
831 printAddress( data );
834 if (i < numValues) printf(",\n");
840 for( i = 1; i < size; ++i ) {
848 /* Should be static but has to be extern to allow mutual recursion */
850 printClosure( P_ closure, int indentation, int weight )
855 /* I'd love to put a test here that this actually _is_ a closure -
856 but testing that it is in the heap is overly strong. */
858 getClosureShape(closure, &vhs, &size, &ptrs, &type);
860 /* The order here precisely reflects that in SMInfoTables.lh to make
861 it easier to check that this list is complete. */
862 switch(INFO_TYPE(INFO_PTR(closure))) {
863 case INFO_SPEC_U_TYPE:
864 case INFO_SPEC_N_TYPE:
865 case INFO_GEN_U_TYPE:
866 case INFO_GEN_N_TYPE:
868 case INFO_TUPLE_TYPE:
870 case INFO_MUTUPLE_TYPE:
871 case INFO_IMMUTUPLE_TYPE:
872 printStandardShapeClosure(indentation, weight, closure,
876 case INFO_STATIC_TYPE:
877 /* If the STATIC contains Floats or Doubles, we can't print it. */
878 /* And we can't always rely on the size/ptrs info either */
879 printAddress( closure );
883 case INFO_CONST_TYPE:
884 if (DEBUG_details > 1) {
885 printAddress( closure );
888 printName((P_)INFO_PTR(closure));
891 case INFO_CHARLIKE_TYPE:
892 /* ToDo: check for non-printable characters */
893 if (DEBUG_details > 1) printf("CHARLIKE ");
894 printf("\'%c\'", (unsigned char) CHARLIKE_VALUE(closure));
897 case INFO_INTLIKE_TYPE:
898 if (DEBUG_details > 1) printf("INTLIKE ");
899 printf("%d",INTLIKE_VALUE(closure));
903 /* Is there anything to say here> */
904 if (DEBUG_details > 1) {
905 printAddress( closure );
908 printName((P_)INFO_PTR(closure));
911 /* most of the following are just plausible guesses (particularily VHSs) ADR */
915 printStandardShapeClosure(indentation, weight, closure,
918 printf("Panic: found BQ Infotable in non-threaded system.\n");
923 if (DEBUG_details > 0) {
924 printAddress( closure );
927 printClosure( (P_) IND_CLOSURE_PTR(closure), indentation, weight );
931 if (DEBUG_details > 0) {
932 printAddress( closure );
935 printClosure( (P_) IND_CLOSURE_PTR(closure), indentation, weight );
938 case INFO_FETCHME_TYPE:
940 printStandardShapeClosure(indentation, weight, closure,
943 printf("Panic: found FETCHME Infotable in sequential system.\n");
949 printStandardShapeClosure(indentation, weight, closure,
952 printf("Panic: found FMBQ Infotable in sequential system.\n");
958 printStandardShapeClosure(indentation, weight, closure,
961 printf("Panic: found BlockedFetch Infotable in sequential system.\n");
967 /* A TSO contains a regtable... */
968 printAddress( closure );
971 printf("Panic: found TSO Infotable in non-threaded system.\n");
977 /* A STKO contains parts of the A and B stacks... */
978 printAddress( closure );
979 printf(" STKO: ...");
981 printf("Panic: found STKO Infotable in non-threaded system.\n");
985 /* There are no others in SMInfoTables.lh 11/5/94 ADR*/
987 printf("Invalid/unknown info type %d\n", INFO_TYPE(INFO_PTR(closure)));
993 DEBUG_NODE( P_ closure, int size )
995 printClosure( closure, 0, size );
1000 Now some stuff for printing stacks - almost certainly doesn't work
1001 under threads which keep the stack on the heap.
1007 minimum(int a, int b)
1016 void DEBUG_PrintA( int depth, int weight )
1025 I_ size = minimum(depth, SUBTRACT_A_STK(SpA, stackInfo.botA)+1);
1027 printf("Dump of the Address Stack (SpA = 0x%x, SuA = 0x%x)\n", SpA, SuA);
1029 for( i = 0; i < size; ++i ) {
1030 printIndentation(1);
1031 printf("SpA[%ld] (0x%08lx):", i, SpA + AREL(i));
1032 printClosure((P_)*(SpA + AREL(i)), 2, weight);
1037 void DEBUG_PrintB( int depth, int weight )
1046 I_ size = minimum(depth, SUBTRACT_B_STK(SpB, stackInfo.botB)+1);
1051 printf("Dump of the Value Stack (SpB = 0x%x, SuB = 0x%x)\n", SpB, SuB);
1053 updateFramePtr = SuB;
1057 if (updateFramePtr == SpB + BREL(i)) {
1059 printIndentation(1);
1060 printf("SpB[%ld] (0x%08lx): UpdateFrame[%d](",
1065 printName( (P_) *(SpB + BREL(i)) );
1066 printf(", UF[%d] (= SpB[%ld]), SpA[%ld], ",
1068 SUBTRACT_B_STK(SpB, GRAB_SuB(updateFramePtr)),
1069 SUBTRACT_A_STK(SpA, GRAB_SuA(updateFramePtr))
1071 printAddress( GRAB_UPDATEE(updateFramePtr) );
1074 printIndentation(2);
1075 printClosure( GRAB_UPDATEE(updateFramePtr), 3, weight );
1078 updateFramePtr = GRAB_SuB(updateFramePtr);
1079 update_count = update_count + 1;
1081 /* ToDo: GhcConstants.lh reveals that there are two other sizes possible */
1082 i = i + STD_UF_SIZE;
1084 printIndentation(1);
1085 printf("SpB[%ld] (0x%08lx): ", i, SpB + BREL(i) );
1086 printName((P_) *(SpB + BREL(i)) );
1092 #endif /* not CONCURRENT */
1097 All the following code incorrectly assumes that the only return
1098 addresses are those associated with update frames.
1100 To do a proper job of printing the environment we need to:
1102 1) Recognise vectored and non-vectored returns on the B stack.
1104 2) Know where the local variables are in the A and B stacks for
1105 each return situation.
1107 Until then, we'll just need to look suspiciously at the
1108 "environment" being printed out.
1113 /* How many real stacks are there on SpA and SpB? */
1118 PP_ SpA = STKO_SpA(SAVE_StkO);
1119 PP_ SuA = STKO_SuA(SAVE_StkO);
1120 P_ SpB = STKO_SpB(SAVE_StkO);
1121 P_ SuB = STKO_SuB(SAVE_StkO);
1130 int depth = 1; /* There's always at least one stack */
1132 while (SUBTRACT_B_STK(SuB, stackInfo.botB) >= 0) {
1133 SuB = GRAB_SuB( SuB );
1140 void printLocalAStack( int depth, int indentation, int weight, PP_ SpA, int size )
1144 ASSERT( size >= 0 );
1146 for( i = size-1; i >= 0; --i ) {
1147 printIndentation( indentation );
1148 printf("A[%ld][%ld]", depth, i);
1149 if (DEBUG_details > 1) printf(" (0x%08lx) ", SpA + AREL(i) );
1151 printClosure( *(SpA + AREL(i)), indentation+2, weight );
1157 void printLocalBStack( int depth, int indentation, int weight, P_ SpB, int size )
1161 ASSERT( size >= 0 );
1163 for( i = size-1; i >= 0; --i) {
1164 printIndentation( indentation );
1165 printf("B[%ld][%ld]", depth, i);
1166 if (DEBUG_details > 1) printf(" (0x%08lx) ", SpB + BREL(i) );
1168 printAddress( (P_) *(SpB + BREL(i)) );
1174 void printEnvironment( int depth, int indentation, int weight, PP_ SpA, PP_ SuA, P_ SpB, P_ SuB )
1176 int sizeA = SUBTRACT_A_STK(SpA, SuA);
1177 int sizeB = SUBTRACT_B_STK(SpB, SuB);
1179 if (sizeA + sizeB > 0) {
1180 printIndentation( indentation );
1183 printLocalAStack( depth, indentation+1, weight, SpA, sizeA );
1184 printLocalBStack( depth, indentation+1, weight, SpB, sizeB );
1186 printIndentation( indentation );
1192 Printing the current context is a little tricky.
1194 Ideally, we would work from the bottom of the stack up to the top
1195 recursively printing the stuff nearer the top.
1197 In practice, we have to work from the top down because the top
1198 contains info about how much data is below the current return address.
1200 The result is that we have two recursive passes over the stacks: the
1201 first one prints the "cases" and the second one prints the
1202 continuations (vector tables, etc.)
1204 Note that because we compress chains of update frames, the depth and
1205 indentation do not always change in step.
1209 * detecting non-updating cases too
1210 * printing continuations (from vector tables) properly
1211 * printing sensible names in environment.
1212 * fix bogus nature of lets
1216 static int maxDepth = 5;
1219 int printCases( int depth, int weight, PP_ SpA, PP_ SuA, P_ SpB, P_ SuB )
1223 if (depth < maxDepth && SUBTRACT_B_STK(SuB, stackInfo.botB) >= 0) {
1224 PP_ nextSpA, nextSuA;
1225 P_ nextSpB, nextSuB;
1227 /* ToDo: GhcConstants.lh reveals that there are two other sizes of
1228 update frame possible */
1229 /* ToDo: botB is probably wrong in THREAD system */
1231 nextSpB = SuB + BREL(STD_UF_SIZE);
1232 nextSuB = GRAB_SuB( SuB );
1234 nextSuA = GRAB_SuA( nextSuB );
1236 indentation = printCases( depth+1, weight, nextSpA, nextSuA, nextSpB, nextSuB );
1238 if (DEBUG_details > 1 || nextSpB != nextSuB) { /* show frame (even if adjacent to another) */
1239 printIndentation( indentation );
1241 indentation = indentation + 1;
1244 /* next thing on stack is a return vector - no need to show it here. */
1245 SpB = SpB + BREL(1);
1247 printEnvironment( depth, indentation, weight, SpA, SuA, SpB, SuB );
1256 /* ToDo: pay more attention to format of vector tables in SMupdate.lh */
1259 int isVTBLEntry( P_ entry )
1263 if (lookupForName( entry, &raw )) {
1264 if ( strncmp( "_ret", raw, 4 ) == 0 ) {
1266 } else if ( strncmp( "_djn", raw, 4 ) == 0) {
1277 void printVectorTable( int indentation, PP_ vtbl )
1279 if (isVTBLEntry( (P_) vtbl )) { /* Direct return */
1280 printName( (P_) vtbl );
1283 while( isVTBLEntry( vtbl[RVREL(i)] )) {
1284 printIndentation( indentation );
1285 printf( "%d -> ", i );
1286 printName( vtbl[RVREL(i)] );
1294 void printContinuations( int depth, int indentation, int weight, PP_ SpA, PP_ SuA, P_ SpB, P_ SuB )
1296 if (depth < maxDepth && SUBTRACT_B_STK(SuB, stackInfo.botB) >= 0) {
1297 PP_ nextSpA, nextSuA;
1298 P_ nextSpB, nextSuB;
1299 int nextIndent = indentation; /* Indentation to print next frame at */
1301 /* ToDo: GhcConstants.lh reveals that there are two other sizes of
1302 update frame possible */
1303 /* ToDo: botB is probably wrong in THREAD system */
1305 /* ToDo: ASSERT that SuA == nextSuA */
1307 nextSpB = SuB + BREL(STD_UF_SIZE);
1308 nextSuB = GRAB_SuB( SuB );
1310 nextSuA = GRAB_SuA( nextSuB );
1312 if (DEBUG_details > 0) { /* print update information */
1314 if (SpB != SuB) { /* start of chain of update frames */
1315 printIndentation( indentation );
1316 printf("of updatePtr ->\n");
1317 printIndentation( indentation+1 );
1320 printIndentation( indentation+2 );
1321 printClosure( (P_)*(SuB + BREL(UF_UPDATEE)), indentation+2, weight );
1323 printName( (P_) *(SuB + BREL(UF_RET)) );
1324 printf("(updatePtr)\n");
1326 if (nextSpB != nextSuB) { /* end of chain of update frames */
1327 nextIndent = nextIndent-1;
1328 printVectorTable( indentation+1, (PP_) *(nextSpB) );
1331 if (nextSpB != nextSuB) { /* end of chain of update frames */
1332 nextIndent = nextIndent-1;
1333 printVectorTable( indentation, (PP_) *(nextSpB) );
1336 printContinuations( depth+1, nextIndent, weight, nextSpA, nextSuA, nextSpB, nextSuB );
1344 void DEBUG_Where( int depth, int weight )
1347 PP_ SpA = STKO_SpA(SAVE_StkO);
1348 PP_ SuA = STKO_SuA(SAVE_StkO);
1349 P_ SpB = STKO_SpB(SAVE_StkO);
1350 P_ SuB = STKO_SuB(SAVE_StkO);
1358 StgRetAddr RetReg = SAVE_Ret;
1359 P_ Node = SAVE_R1.p;
1365 printf("WARNING: Non-updating cases may be incorrectly displayed\n");
1367 indentation = printCases( 1, weight, SpA, SuA, SpB, SuB );
1369 printIndentation( indentation );
1372 printIndentation( indentation+1 );
1375 printVectorTable( indentation+1, (PP_) RetReg );
1377 printContinuations( depth, indentation, weight, SpA, SuA, SpB, SuB );
1383 #if defined(RUNTIME_DEBUGGING)
1386 DEBUG_INFO_TABLE(node)
1389 int vhs, size, ptrs; /* not used */
1391 StgPtr info_ptr = (StgPtr) INFO_PTR(node);
1393 getClosureShape(node, &vhs, &size, &ptrs, &ip_type);
1396 "%s Info Ptr 0x%lx; Entry: 0x%lx; Update: 0x%lx\n",
1398 (W_) ENTRY_CODE(info_ptr), (W_) UPDATE_CODE(info_ptr));
1400 "Tag: %d; Type: %d; Size: %lu; Ptrs: %lu\n\n",
1401 INFO_TAG(info_ptr), INFO_TYPE(info_ptr),
1402 INFO_SIZE(info_ptr),INFO_NoPTRS(info_ptr));
1404 fprintf(stderr,"Enter Flush Entry: 0x%lx;\tExit Flush Entry: 0x%lx\n",INFO_FLUSHENT(info_ptr),INFO_FLUSH(info_ptr));
1407 #if defined(USE_COST_CENTRES)
1408 fprintf(stderr,"Cost Centre: 0x%lx\n",INFO_CAT(info_ptr));
1409 #endif /* USE_COST_CENTRES */
1411 #if defined(_INFO_COPYING)
1412 fprintf(stderr,"Evacuate Entry: 0x%lx;\tScavenge Entry: 0x%lx\n",
1413 INFO_EVAC_2S(info_ptr),INFO_SCAV_2S(info_ptr));
1414 #endif /* INFO_COPYING */
1416 #if defined(_INFO_COMPACTING)
1417 fprintf(stderr,"Scan Link: 0x%lx;\tScan Move: 0x%lx\n",
1418 (W_) INFO_SCAN_LINK_1S(info_ptr), (W_) INFO_SCAN_MOVE_1S(info_ptr));
1419 fprintf(stderr,"Mark: 0x%lx;\tMarked: 0x%lx;\n",
1420 (W_) INFO_MARK_1S(info_ptr), (W_) INFO_MARKED_1S(info_ptr));
1421 if(BASE_INFO_TYPE(info_ptr)==INFO_SPEC_TYPE)
1422 fprintf(stderr,"plus specialised code\n");
1424 fprintf(stderr,"Marking: 0x%lx\n",(W_) INFO_MARKING_1S(info_ptr));
1425 #endif /* INFO_COMPACTING */
1432 PP_ SpA = STKO_SpA(SAVE_StkO);
1433 PP_ SuA = STKO_SuA(SAVE_StkO);
1434 P_ SpB = STKO_SpB(SAVE_StkO);
1435 P_ SuB = STKO_SuB(SAVE_StkO);
1443 P_ HpLim= SAVE_HpLim;
1444 I_ TagReg= SAVE_Tag;
1445 StgRetAddr RetReg = SAVE_Ret;
1446 P_ Node = SAVE_R1.p;
1447 StgUnion R1 = SAVE_R1;
1448 StgUnion R2 = SAVE_R2;
1449 StgUnion R3 = SAVE_R3;
1450 StgUnion R4 = SAVE_R4;
1451 StgUnion R5 = SAVE_R5;
1452 StgUnion R6 = SAVE_R6;
1453 StgUnion R7 = SAVE_R7;
1454 StgUnion R8 = SAVE_R8;
1455 StgFloat FltReg1 = SAVE_Flt1;
1456 StgFloat FltReg2 = SAVE_Flt2;
1457 StgFloat FltReg3 = SAVE_Flt3;
1458 StgFloat FltReg4 = SAVE_Flt4;
1459 StgDouble DblReg1 = SAVE_Dbl1;
1460 StgDouble DblReg2 = SAVE_Dbl2;
1462 fprintf(stderr,"STG-Machine Register Values:\n\n");
1463 fprintf(stderr,"Node: %08lx; Hp: %08lx; HpLim: %08lx; Tag: %8lu\n",Node,(W_)Hp,(W_)HpLim,TagReg);
1464 fprintf(stderr,"SpA: %08lx; SpB: %08lx; SuA: %08lx; SuB: %08lx\n",(W_)SpA,(W_)SpB,(W_)SuA,(W_)SuB);
1465 fprintf(stderr,"RetReg: %08lx\n",RetReg);
1468 /* These bits need to have the FLUSH_REG_MAP, whereas the surrounding bits
1469 use the MAIN_REG_MAP */
1471 fprintf(stderr, "\n");
1472 fprintf(stderr,"LiveR: %08lx\n", LivenessReg);
1473 fprintf(stderr,"Flush: %08lx; FStk: %08lx; FStkB: %08lx; FTmp: %08lx\n",(W_)FlushP,(W_)FStack,(W_)FStackBase,(W_)Temp);
1476 fprintf(stderr, "\n");
1478 fprintf(stderr,"Gen: %8lu, %8lu, %8lu, %8lu\n",R1.i,R2.i,R3.i,R4.i);
1479 fprintf(stderr," %8lu, %8lu, %8lu, %8lu\n",R5.i,R6.i,R7.i,R8.i);
1480 fprintf(stderr,"Float: %8g, %8g, %8g, %8g\n",FltReg1,FltReg2,FltReg3,FltReg4);
1481 fprintf(stderr,"Dble: %8g, %8g\n",DblReg1,DblReg2);
1490 fprintf(stderr,"MallocPtrList\n\n");
1492 for(mp = StorageMgrInfo.MallocPtrList;
1494 mp = MallocPtr_CLOSURE_LINK(mp)) {
1496 fprintf(stderr, "MallocPtr(0x%lx) = 0x%lx\n", mp, MallocPtr_CLOSURE_DATA(mp));
1499 DEBUG_PRINT_NODE(mp);
1503 #if defined(GCap) || defined(GCgn)
1504 fprintf(stderr,"\nOldMallocPtr List\n\n");
1506 for(mp = StorageMgrInfo.OldMallocPtrList;
1508 mp = MallocPtr_CLOSURE_LINK(mp)) {
1510 fprintf(stderr, " MallocPtr(0x%lx) = 0x%lx\n", mp, MallocPtr_CLOSURE_DATA(mp));
1512 DEBUG_PRINT_NODE(mp);
1515 #endif /* GCap || GCgn */
1517 fprintf(stderr, "\n");
1522 DEBUG_SPT(int weight)
1524 StgPtr SPTable = StorageMgrInfo.StablePointerTable;
1525 StgInt size = SPT_SIZE(SPTable);
1526 StgInt ptrs = SPT_NoPTRS(SPTable);
1527 StgInt top = SPT_TOP(SPTable);
1532 DEBUG_PRINT_NODE(SPTable);
1535 fprintf(stderr,"SPTable@0x%lx:\n", SPTable);
1536 fprintf(stderr," InfoPtr = 0x%lx\n", INFO_PTR(SPTable));
1537 fprintf(stderr," size = %d, ptrs = %d, top = %d\n",
1540 for( i=0; i < ptrs; i++ ) {
1542 fprintf(stderr,"\n ");
1544 printClosure(SPT_SPTR(SPTable, i),1,weight);
1545 fprintf(stderr, "\n");
1547 fprintf(stderr, "\n");
1548 for( i=0; i < top; i++) {
1550 fprintf(stderr,"\n ");
1552 fprintf(stderr, " %3d", SPT_FREE(SPTable, i));
1555 fprintf(stderr, "\n\n");
1562 These routines crawl over the A and B stacks, printing
1563 a maximum "lines" lines at the top of the stack.
1567 #define STACK_VALUES_PER_LINE 5
1570 /* (stack stuff is really different on parallel machines) */
1584 fprintf(stderr,"Dump of the Address Stack, SpA: 0x%08lx, BOS: 0x%08lx\n",
1585 (W_) SpA, (W_) stackInfo.botA);
1587 for (stackptr = SpA;
1588 SUBTRACT_A_STK(stackptr, stackInfo.botA) >= 0;
1589 stackptr = stackptr + AREL(1))
1591 if( count++ % STACK_VALUES_PER_LINE == 0)
1593 if(count >= lines * STACK_VALUES_PER_LINE)
1595 fprintf(stderr,"\nSpA[%ld] (0x%08lx): ",count-1,stackptr);
1597 fprintf(stderr,"0x%08lx ",(W_) *stackptr);
1599 fprintf(stderr, "\n");
1615 fprintf(stderr,"Dump of the Value Stack, SpB: 0x%08lx, BOS: 0x%08lx\n",
1616 (W_) SpB, (W_) stackInfo.botB);
1618 for (stackptr = SpB;
1619 SUBTRACT_B_STK(stackptr, stackInfo.botB) > 0;
1620 stackptr = stackptr + BREL(1))
1622 if( count++ % STACK_VALUES_PER_LINE == 0)
1624 if(count >= lines * STACK_VALUES_PER_LINE)
1626 fprintf(stderr,"\nSpB[%ld] (0x%08lx): ",count-1,stackptr);
1628 fprintf(stderr,"0x%08lx ",(W_) *stackptr);
1630 fprintf(stderr, "\n");
1632 #endif /* not parallel */
1635 This should disentangle update frames from both stacks.
1640 DEBUG_UPDATES(limit)
1655 fprintf(stderr,"Update Frame Stack Dump:\n\n");
1658 SUBTRACT_B_STK(spb, stackInfo.botB) > 0 && count++ < limit;
1659 /* re-init given explicitly */)
1661 updatee = GRAB_UPDATEE(spb); /* Thing to be updated */
1662 retreg = (P_) GRAB_RET(spb); /* Return vector below */
1664 fprintf(stderr,"SuA: 0x%08lx, SuB: 0x%08lx, Updatee 0x%08lx, RetReg 0x%x\n",
1666 (W_) updatee, (W_) retreg);
1668 spa = GRAB_SuA(spb); /* Next SuA, SuB */
1669 spb = GRAB_SuB(spb);
1672 #endif /* not parallel */
1674 #endif /* RUNTIME_DEBUGGING */
1676 #endif /* PAR || RUNTIME_DEBUGGING */