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
66 DEBUG_TSO(tso) (CONCURRENT) Print a Thread State Object
69 DEBUG_STKO(stko) (CONCURRENT) Print a STacK Object
75 \subsection[StgDebug_Symbol_Tables]{Loading Symbol Tables}
77 NB: this assumes a.out files - won't work on Alphas.
78 ToDo: At least add some #ifdefs
81 /* #include <a.out.h> */
82 /* #include <stab.h> */
83 /* #include <nlist.h> */
87 #define FROM_START 0 /* for fseek */
89 /* Simple lookup table */
91 /* Current implementation is pretty dumb! */
99 static int table_uninitialised = 1;
100 static int max_table_size;
101 static int table_size;
102 static struct entry* table;
105 reset_table( int size )
107 max_table_size = size;
109 table = (struct entry *) stgMallocBytes(size * sizeof(struct entry), "reset_table");
115 /* Could sort it... */
119 insert( unsigned value, int index, char *name )
121 if ( table_size >= max_table_size ) {
122 fprintf( stderr, "Symbol table overflow\n" );
125 table[table_size].value = value;
126 table[table_size].index = index;
127 table[table_size].name = name;
128 table_size = table_size + 1;
132 lookup( unsigned value, int *result )
135 for( i = 0; i < table_size && table[i].value != value; ++i ) {
137 if (i < table_size) {
138 *result = table[i].index;
146 lookup_name( char *name, unsigned *result )
149 for( i = 0; i < table_size && strcmp(name,table[i].name) != 0; ++i ) {
151 if (i < table_size) {
152 *result = table[i].value;
161 "std"++xs -> "Zstd"++xs
175 char_to_c '\'' = "Zq"
178 char_to_c c = "Z" ++ show (ord c)
181 static char unZcode( char ch )
222 /* Precondition: out big enough to handle output (about twice length of in) */
223 static void enZcode( char *in, char *out )
229 for( i = 0; in[i] != '\0'; ++i ) {
305 static int lookupForName( P_ addr, char **result )
308 for( i = 0; i < table_size && table[i].value != (unsigned) addr; ++i ) {
310 if (i < table_size) {
311 *result = table[i].name;
318 static void printZcoded( char *raw )
322 /* start at 1 to skip the leading "_" */
323 for( j = 1; raw[j] != '\0'; /* explicit */) {
325 putchar(unZcode(raw[j+1]));
334 static void printName( P_ addr )
338 if (lookupForName( addr, &raw )) {
341 printf("0x%x", addr);
345 #if 0 /* OMIT load-symbol stuff cos it doesn't work on Alphas */
347 /* Fairly ad-hoc piece of code that seems to filter out a lot of
348 rubbish like the obj-splitting symbols */
351 isReal( unsigned char type, char *name )
353 int external = type & N_EXT;
354 int tp = type & N_TYPE;
356 if (tp == N_TEXT || tp == N_DATA) {
357 return( name[0] == '_' && name[1] != '_' );
364 DEBUG_LoadSymbols( char *name )
374 struct nlist *symbol_table;
377 long str_size; /* assumed 4 bytes.... */
382 binary = fopen( name, "r" );
383 if (binary == NULL) {
384 fprintf( stderr, "Can't open symbol table file \"%s\".\n", name );
388 if (fread( &header, sizeof( struct exec ), 1, binary ) != 1) {
389 fprintf( stderr, "Can't read symbol table header.\n" );
392 if ( N_BADMAG( header ) ) {
393 fprintf( stderr, "Bad magic number in symbol table header.\n" );
399 sym_offset = N_SYMOFF( header );
400 sym_size = header.a_syms;
401 num_syms = sym_size / sizeof( struct nlist );
402 fseek( binary, sym_offset, FROM_START );
404 symbol_table = (struct nlist *) stgMallocBytes(sym_size, "symbol table (DEBUG_LoadSymbols)");
405 printf("Reading %d symbols\n", num_syms);
407 if (fread( symbol_table, sym_size, 1, binary ) != 1) {
408 fprintf( stderr, "Can't read symbol table\n");
412 str_offset = N_STROFF( header );
413 fseek( binary, str_offset, FROM_START );
415 if (fread( &str_size, 4, 1, binary ) != 1) {
416 fprintf( stderr, "Can't read string table size\n");
420 /* apparently the size of the string table includes the 4 bytes that
423 string_table = (char *) stgMallocBytes(str_size, "string table (DEBUG_LoadSymbols)");
425 if (fread( string_table+4, str_size-4, 1, binary ) != 1) {
426 fprintf( stderr, "Can't read string table\n");
431 for( i = 0; i != num_syms; ++i ) {
432 unsigned char type = symbol_table[i].n_type;
433 unsigned value = symbol_table[i].n_value;
434 char *str = &string_table[symbol_table[i].n_un.n_strx];
436 if ( isReal( type, str ) ) {
437 num_real_syms = num_real_syms + 1;
441 printf("Of which %d are real symbols\n", num_real_syms);
444 for( i = 0; i != num_syms; ++i ) {
445 unsigned char type = symbol_table[i].n_type;
446 unsigned value = symbol_table[i].n_value;
447 char *str = &string_table[symbol_table[i].n_un.n_strx];
449 if ( isReal(type, str) ) {
450 printf("Symbol %d. Extern? %c. Type: %c. Value: 0x%x. Name: %s\n",
452 (external ? 'y' : 'n'),
461 reset_table( num_real_syms );
463 for( i = 0; i != num_syms; ++i ) {
464 unsigned char type = symbol_table[i].n_type;
465 unsigned value = symbol_table[i].n_value;
466 char *str = &string_table[symbol_table[i].n_un.n_strx];
468 if ( isReal( type, str ) ) {
469 insert( value, i, str );
479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 \subsection[StgDebug_PrettyPrinting]{Pretty printing internal structures}
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486 #include "../storage/SMinternal.h"
489 #define HP_BOT appelInfo.oldbase
491 #define HP_BOT dualmodeInfo.modeinfo[dualmodeInfo.mode].base
493 #define HP_BOT semispaceInfo[semispace].base
495 #define HP_BOT compactingInfo.base
497 unknown garbage collector - help, help!
502 /* range: 0..NUM_LEVELS_OF_DETAIL-1. Level of machine-related detail shown */
503 #define NUM_LEVELS_OF_DETAIL 3
504 static int DEBUG_details = 2;
508 /* Determine the size and number of pointers for this kind of closure */
510 getClosureShape( P_ node, int *vhs, int *size, int *ptrs, char **type )
512 /* The result is used for printing out closure contents. If the
513 info-table is mince, we'd better conservatively guess there's
514 nothing in the closure to avoid chasing non-ptrs. */
518 *type = "*unknown info type*";
520 /* ToDo: if in garbage collector, consider subtracting some weird offset which some GCs add to infoptr */
522 /* The order here precisely reflects that in SMInfoTables.lh to make
523 it easier to check that this list is complete. */
524 switch(INFO_TYPE(INFO_PTR(node)))
526 case INFO_SPEC_U_TYPE:
527 *vhs = 0; /* by decree */
528 *size = SPEC_CLOSURE_SIZE(node);
529 *ptrs = SPEC_CLOSURE_NoPTRS(node);
532 case INFO_SPEC_N_TYPE:
533 *vhs = 0; /* by decree */
534 *size = SPEC_CLOSURE_SIZE(node);
535 *ptrs = SPEC_CLOSURE_NoPTRS(node);
539 case INFO_GEN_U_TYPE:
541 *size = GEN_CLOSURE_SIZE(node);
542 *ptrs = GEN_CLOSURE_NoPTRS(node);
545 case INFO_GEN_N_TYPE:
547 *size = GEN_CLOSURE_SIZE(node);
548 *ptrs = GEN_CLOSURE_NoPTRS(node);
554 *size = DYN_CLOSURE_SIZE(node);
555 *ptrs = DYN_CLOSURE_NoPTRS(node);
559 case INFO_TUPLE_TYPE:
561 *size = TUPLE_CLOSURE_SIZE(node);
562 *ptrs = TUPLE_CLOSURE_NoPTRS(node);
568 *size = DATA_CLOSURE_SIZE(node);
569 *ptrs = DATA_CLOSURE_NoPTRS(node);
573 case INFO_MUTUPLE_TYPE:
575 *size = MUTUPLE_CLOSURE_SIZE(node);
576 *ptrs = MUTUPLE_CLOSURE_NoPTRS(node);
580 case INFO_IMMUTUPLE_TYPE:
582 *size = MUTUPLE_CLOSURE_SIZE(node);
583 *ptrs = MUTUPLE_CLOSURE_NoPTRS(node);
587 case INFO_STATIC_TYPE:
589 *size = INFO_SIZE(INFO_PTR(node));
590 *ptrs = INFO_NoPTRS(INFO_PTR(node));
594 case INFO_CONST_TYPE:
601 case INFO_CHARLIKE_TYPE:
608 case INFO_INTLIKE_TYPE:
617 *size = INFO_SIZE(INFO_PTR(node));
622 /* most of the following are plausible guesses (particularily VHSs) ADR */
626 *size = BQ_CLOSURE_SIZE(node);
627 *ptrs = BQ_CLOSURE_NoPTRS(node);
630 printf("Panic: found BQ Infotable in non-threaded system.\n");
636 *size = IND_CLOSURE_SIZE(node);
637 *ptrs = IND_CLOSURE_NoPTRS(node);
642 *vhs = 0; /* ?? ADR */
643 *size = INFO_SIZE(INFO_PTR(node));
648 case INFO_FETCHME_TYPE:
651 *size = FETCHME_CLOSURE_SIZE(node);
652 *ptrs = FETCHME_CLOSURE_PTRS(node);
655 printf("Panic: found FETCHME Infotable in sequential system.\n");
662 *size = FMBQ_CLOSURE_SIZE(node);
663 *ptrs = FMBQ_CLOSURE_PTRS(node);
666 printf("Panic: found FMBQ Infotable in sequential system.\n");
675 *type = "BlockedFetch";
677 printf("Panic: found BlockedFetch Infotable in sequential system.\n");
682 /* Conservative underestimate: this will contain a regtable
683 which comes nowhere near fitting the standard "p ptrs; s-p
684 non-ptrs" format. ADR */
691 printf("Panic: found TSO Infotable in non-threaded system.\n");
696 /* Conservative underestimate: this will contain stuff
697 which comes nowhere near fitting the standard "p ptrs; s-p
698 non-ptrs" format. JSM */
705 printf("Panic: found STKO Infotable in non-threaded system.\n");
709 /* There are no others in SMInfoTables.lh 11/5/94 ADR*/
711 printf("Invalid/unknown info type %d\n", INFO_TYPE(INFO_PTR(node)));
719 printf("0x%08lx", word);
723 printAddress( P_ address )
726 PP_ SpA = STKO_SpA(SAVE_StkO);
727 PP_ SuA = STKO_SuA(SAVE_StkO);
728 P_ SpB = STKO_SpB(SAVE_StkO);
729 P_ SuB = STKO_SuB(SAVE_StkO);
738 PP_ botA = stackInfo.botA;
739 P_ botB = stackInfo.botB;
744 /* ToDo: check if it's in text or data segment. */
746 /* The @-1@s in stack comparisions are because we sometimes use the
747 address of just below the stack... */
750 if (lookupForName( address, &name )) {
756 if (DEBUG_details > 1) {
757 printWord( (W_) address );
760 if (HpBot <= address && address < Hp) {
761 printf("Hp[%d]", address - HpBot);
762 } else if (SUBTRACT_A_STK((PP_)address, botA) >= -1 && SUBTRACT_A_STK(SpA, (PP_)address) >= 0) {
763 printf("SpA[%d]", SUBTRACT_A_STK((PP_)address, botA));
764 } else if (SUBTRACT_B_STK(address, botB) >= -1 && SUBTRACT_B_STK(SpB, address) >= 0) {
765 /* ToDo: check if it's an update frame */
766 printf("SpB[%d]", SUBTRACT_B_STK(address, botB));
768 printWord( (W_) address );
774 printIndentation( int indentation )
777 for (i = 0; i < indentation; ++i) { printf(" "); }
780 /* The weight parameter is used to (eventually) break cycles */
782 printStandardShapeClosure(
785 P_ closure, int vhs, int size, int noPtrs
789 PP_ SpA = STKO_SpA(SAVE_StkO);
790 PP_ SuA = STKO_SuA(SAVE_StkO);
791 P_ SpB = STKO_SpB(SAVE_StkO);
792 P_ SuB = STKO_SuB(SAVE_StkO);
801 extern void printClosure PROTO( (P_, int, int) );
802 int numValues = size - vhs;
805 if (DEBUG_details > 1) {
806 printAddress( closure );
809 printName((P_)INFO_PTR(closure));
811 if ( numValues > 0 ) {
812 int newWeight = weight-1 ;
813 /* I've tried dividing the weight by size to share it out amongst
814 sub-closures - but that didn't work too well. */
819 while (i < numValues) {
820 P_ data = (P_) closure[_FHS + vhs + i];
822 printIndentation(indentation+1);
824 printClosure( data, indentation+1, newWeight);
826 printAddress( data );
829 if (i < numValues) printf(",\n");
835 for( i = 1; i < size; ++i ) {
843 /* Should be static but has to be extern to allow mutual recursion */
845 printClosure( P_ closure, int indentation, int weight )
850 /* I'd love to put a test here that this actually _is_ a closure -
851 but testing that it is in the heap is overly strong. */
853 getClosureShape(closure, &vhs, &size, &ptrs, &type);
855 /* The order here precisely reflects that in SMInfoTables.lh to make
856 it easier to check that this list is complete. */
857 switch(INFO_TYPE(INFO_PTR(closure))) {
858 case INFO_SPEC_U_TYPE:
859 case INFO_SPEC_N_TYPE:
860 case INFO_GEN_U_TYPE:
861 case INFO_GEN_N_TYPE:
863 case INFO_TUPLE_TYPE:
865 case INFO_MUTUPLE_TYPE:
866 case INFO_IMMUTUPLE_TYPE:
867 printStandardShapeClosure(indentation, weight, closure,
871 case INFO_STATIC_TYPE:
872 /* If the STATIC contains Floats or Doubles, we can't print it. */
873 /* And we can't always rely on the size/ptrs info either */
874 printAddress( closure );
878 case INFO_CONST_TYPE:
879 if (DEBUG_details > 1) {
880 printAddress( closure );
883 printName((P_)INFO_PTR(closure));
886 case INFO_CHARLIKE_TYPE:
887 /* ToDo: check for non-printable characters */
888 if (DEBUG_details > 1) printf("CHARLIKE ");
889 printf("\'%c\'", (unsigned char) CHARLIKE_VALUE(closure));
892 case INFO_INTLIKE_TYPE:
893 if (DEBUG_details > 1) printf("INTLIKE ");
894 printf("%d",INTLIKE_VALUE(closure));
898 /* Is there anything to say here> */
899 if (DEBUG_details > 1) {
900 printAddress( closure );
903 printName((P_)INFO_PTR(closure));
906 /* most of the following are just plausible guesses (particularily VHSs) ADR */
910 printStandardShapeClosure(indentation, weight, closure,
913 printf("Panic: found BQ Infotable in non-threaded system.\n");
918 if (DEBUG_details > 0) {
919 printAddress( closure );
922 printClosure( (P_) IND_CLOSURE_PTR(closure), indentation, weight );
926 if (DEBUG_details > 0) {
927 printAddress( closure );
930 printClosure( (P_) IND_CLOSURE_PTR(closure), indentation, weight );
933 case INFO_FETCHME_TYPE:
935 printStandardShapeClosure(indentation, weight, closure,
938 printf("Panic: found FETCHME Infotable in sequential system.\n");
944 printStandardShapeClosure(indentation, weight, closure,
947 printf("Panic: found FMBQ Infotable in sequential system.\n");
953 printStandardShapeClosure(indentation, weight, closure,
956 printf("Panic: found BlockedFetch Infotable in sequential system.\n");
962 /* A TSO contains a regtable... */
963 printAddress( closure );
966 printf("Panic: found TSO Infotable in non-threaded system.\n");
972 /* A STKO contains parts of the A and B stacks... */
973 printAddress( closure );
974 printf(" STKO: ...");
976 printf("Panic: found STKO Infotable in non-threaded system.\n");
980 /* There are no others in SMInfoTables.lh 11/5/94 ADR*/
982 printf("Invalid/unknown info type %d\n", INFO_TYPE(INFO_PTR(closure)));
988 DEBUG_NODE( P_ closure, int size )
990 printClosure( closure, 0, size );
995 Now some stuff for printing stacks - almost certainly doesn't work
996 under threads which keep the stack on the heap.
1002 minimum(int a, int b)
1012 DEBUG_PrintA( int depth, int weight )
1021 I_ size = minimum(depth, SUBTRACT_A_STK(SpA, stackInfo.botA)+1);
1023 printf("Dump of the Address Stack (SpA = 0x%x, SuA = 0x%x)\n", SpA, SuA);
1025 for( i = 0; i < size; ++i ) {
1026 printIndentation(1);
1027 printf("SpA[%ld] (0x%08lx):", i, SpA + AREL(i));
1028 printClosure((P_)*(SpA + AREL(i)), 2, weight);
1034 DEBUG_PrintB( int depth, int weight )
1043 I_ size = minimum(depth, SUBTRACT_B_STK(SpB, stackInfo.botB)+1);
1048 printf("Dump of the Value Stack (SpB = 0x%x, SuB = 0x%x)\n", SpB, SuB);
1050 updateFramePtr = SuB;
1054 if (updateFramePtr == SpB + BREL(i)) {
1056 printIndentation(1);
1057 printf("SpB[%ld] (0x%08lx): UpdateFrame[%d](",
1062 printName( (P_) *(SpB + BREL(i)) );
1063 printf(", UF[%d] (= SpB[%ld]), SpA[%ld], ",
1065 SUBTRACT_B_STK(SpB, GRAB_SuB(updateFramePtr)),
1066 SUBTRACT_A_STK(SpA, GRAB_SuA(updateFramePtr))
1068 printAddress( GRAB_UPDATEE(updateFramePtr) );
1071 printIndentation(2);
1072 printClosure( GRAB_UPDATEE(updateFramePtr), 3, weight );
1075 updateFramePtr = GRAB_SuB(updateFramePtr);
1076 update_count = update_count + 1;
1078 /* ToDo: GhcConstants.lh reveals that there are two other sizes possible */
1079 i = i + STD_UF_SIZE;
1081 printIndentation(1);
1082 printf("SpB[%ld] (0x%08lx): ", i, SpB + BREL(i) );
1083 printName((P_) *(SpB + BREL(i)) );
1089 #endif /* not CONCURRENT */
1094 All the following code incorrectly assumes that the only return
1095 addresses are those associated with update frames.
1097 To do a proper job of printing the environment we need to:
1099 1) Recognise vectored and non-vectored returns on the B stack.
1101 2) Know where the local variables are in the A and B stacks for
1102 each return situation.
1104 Until then, we'll just need to look suspiciously at the
1105 "environment" being printed out.
1110 /* How many real stacks are there on SpA and SpB? */
1115 PP_ SpA = STKO_SpA(SAVE_StkO);
1116 PP_ SuA = STKO_SuA(SAVE_StkO);
1117 P_ SpB = STKO_SpB(SAVE_StkO);
1118 P_ SuB = STKO_SuB(SAVE_StkO);
1127 int depth = 1; /* There's always at least one stack */
1129 while (SUBTRACT_B_STK(SuB, stackInfo.botB) >= 0) {
1130 SuB = GRAB_SuB( SuB );
1137 printLocalAStack( int depth, int indentation, int weight, PP_ SpA, int size )
1141 ASSERT( size >= 0 );
1143 for( i = size-1; i >= 0; --i ) {
1144 printIndentation( indentation );
1145 printf("A[%ld][%ld]", depth, i);
1146 if (DEBUG_details > 1) printf(" (0x%08lx) ", SpA + AREL(i) );
1148 printClosure( *(SpA + AREL(i)), indentation+2, weight );
1154 printLocalBStack( int depth, int indentation, int weight, P_ SpB, int size )
1158 ASSERT( size >= 0 );
1160 for( i = size-1; i >= 0; --i) {
1161 printIndentation( indentation );
1162 printf("B[%ld][%ld]", depth, i);
1163 if (DEBUG_details > 1) printf(" (0x%08lx) ", SpB + BREL(i) );
1165 printAddress( (P_) *(SpB + BREL(i)) );
1171 printEnvironment( int depth, int indentation, int weight, PP_ SpA, PP_ SuA, P_ SpB, P_ SuB )
1173 int sizeA = SUBTRACT_A_STK(SpA, SuA);
1174 int sizeB = SUBTRACT_B_STK(SpB, SuB);
1176 if (sizeA + sizeB > 0) {
1177 printIndentation( indentation );
1180 printLocalAStack( depth, indentation+1, weight, SpA, sizeA );
1181 printLocalBStack( depth, indentation+1, weight, SpB, sizeB );
1183 printIndentation( indentation );
1189 Printing the current context is a little tricky.
1191 Ideally, we would work from the bottom of the stack up to the top
1192 recursively printing the stuff nearer the top.
1194 In practice, we have to work from the top down because the top
1195 contains info about how much data is below the current return address.
1197 The result is that we have two recursive passes over the stacks: the
1198 first one prints the "cases" and the second one prints the
1199 continuations (vector tables, etc.)
1201 Note that because we compress chains of update frames, the depth and
1202 indentation do not always change in step.
1206 * detecting non-updating cases too
1207 * printing continuations (from vector tables) properly
1208 * printing sensible names in environment.
1209 * fix bogus nature of lets
1213 static int maxDepth = 5;
1216 printCases( int depth, int weight, PP_ SpA, PP_ SuA, P_ SpB, P_ SuB )
1220 if (depth < maxDepth && SUBTRACT_B_STK(SuB, stackInfo.botB) >= 0) {
1221 PP_ nextSpA, nextSuA;
1222 P_ nextSpB, nextSuB;
1224 /* ToDo: GhcConstants.lh reveals that there are two other sizes of
1225 update frame possible */
1226 /* ToDo: botB is probably wrong in THREAD system */
1228 nextSpB = SuB + BREL(STD_UF_SIZE);
1229 nextSuB = GRAB_SuB( SuB );
1231 nextSuA = GRAB_SuA( nextSuB );
1233 indentation = printCases( depth+1, weight, nextSpA, nextSuA, nextSpB, nextSuB );
1235 if (DEBUG_details > 1 || nextSpB != nextSuB) { /* show frame (even if adjacent to another) */
1236 printIndentation( indentation );
1238 indentation = indentation + 1;
1241 /* next thing on stack is a return vector - no need to show it here. */
1242 SpB = SpB + BREL(1);
1244 printEnvironment( depth, indentation, weight, SpA, SuA, SpB, SuB );
1253 /* ToDo: pay more attention to format of vector tables in SMupdate.lh */
1256 isVTBLEntry( P_ entry )
1260 if (lookupForName( entry, &raw )) {
1261 if ( strncmp( "_ret", raw, 4 ) == 0 ) {
1263 } else if ( strncmp( "_djn", raw, 4 ) == 0) {
1274 printVectorTable( int indentation, PP_ vtbl )
1276 if (isVTBLEntry( (P_) vtbl )) { /* Direct return */
1277 printName( (P_) vtbl );
1280 while( isVTBLEntry( vtbl[RVREL(i)] )) {
1281 printIndentation( indentation );
1282 printf( "%d -> ", i );
1283 printName( vtbl[RVREL(i)] );
1291 printContinuations( int depth, int indentation, int weight, PP_ SpA, PP_ SuA, P_ SpB, P_ SuB )
1293 if (depth < maxDepth && SUBTRACT_B_STK(SuB, stackInfo.botB) >= 0) {
1294 PP_ nextSpA, nextSuA;
1295 P_ nextSpB, nextSuB;
1296 int nextIndent = indentation; /* Indentation to print next frame at */
1298 /* ToDo: GhcConstants.lh reveals that there are two other sizes of
1299 update frame possible */
1300 /* ToDo: botB is probably wrong in THREAD system */
1302 /* ToDo: ASSERT that SuA == nextSuA */
1304 nextSpB = SuB + BREL(STD_UF_SIZE);
1305 nextSuB = GRAB_SuB( SuB );
1307 nextSuA = GRAB_SuA( nextSuB );
1309 if (DEBUG_details > 0) { /* print update information */
1311 if (SpB != SuB) { /* start of chain of update frames */
1312 printIndentation( indentation );
1313 printf("of updatePtr ->\n");
1314 printIndentation( indentation+1 );
1317 printIndentation( indentation+2 );
1318 printClosure( (P_)*(SuB + BREL(UF_UPDATEE)), indentation+2, weight );
1320 printName( (P_) *(SuB + BREL(UF_RET)) );
1321 printf("(updatePtr)\n");
1323 if (nextSpB != nextSuB) { /* end of chain of update frames */
1324 nextIndent = nextIndent-1;
1325 printVectorTable( indentation+1, (PP_) *(nextSpB) );
1328 if (nextSpB != nextSuB) { /* end of chain of update frames */
1329 nextIndent = nextIndent-1;
1330 printVectorTable( indentation, (PP_) *(nextSpB) );
1333 printContinuations( depth+1, nextIndent, weight, nextSpA, nextSuA, nextSpB, nextSuB );
1341 DEBUG_Where( int depth, int weight )
1344 PP_ SpA = STKO_SpA(SAVE_StkO);
1345 PP_ SuA = STKO_SuA(SAVE_StkO);
1346 P_ SpB = STKO_SpB(SAVE_StkO);
1347 P_ SuB = STKO_SuB(SAVE_StkO);
1355 StgRetAddr RetReg = SAVE_Ret;
1356 P_ Node = SAVE_R1.p;
1362 printf("WARNING: Non-updating cases may be incorrectly displayed\n");
1364 indentation = printCases( 1, weight, SpA, SuA, SpB, SuB );
1366 printIndentation( indentation );
1369 printIndentation( indentation+1 );
1372 printVectorTable( indentation+1, (PP_) RetReg );
1374 printContinuations( depth, indentation, weight, SpA, SuA, SpB, SuB );
1381 DEBUG_INFO_TABLE(node)
1384 int vhs, size, ptrs; /* not used */
1386 StgPtr info_ptr = (StgPtr) INFO_PTR(node);
1388 getClosureShape(node, &vhs, &size, &ptrs, &ip_type);
1391 "%s Info Ptr 0x%lx; Entry: 0x%lx; Update: 0x%lx\n",
1393 (W_) ENTRY_CODE(info_ptr), (W_) UPDATE_CODE(info_ptr));
1395 "Tag: %d; Type: %d; Size: %lu; Ptrs: %lu\n\n",
1396 INFO_TAG(info_ptr), INFO_TYPE(info_ptr),
1397 INFO_SIZE(info_ptr),INFO_NoPTRS(info_ptr));
1399 fprintf(stderr,"Enter Flush Entry: 0x%lx;\tExit Flush Entry: 0x%lx\n",INFO_FLUSHENT(info_ptr),INFO_FLUSH(info_ptr));
1402 #if defined(PROFILING)
1403 fprintf(stderr,"Cost Centre: 0x%lx\n",INFO_CAT(info_ptr));
1404 #endif /* PROFILING */
1406 #if defined(_INFO_COPYING)
1407 fprintf(stderr,"Evacuate Entry: 0x%lx;\tScavenge Entry: 0x%lx\n",
1408 INFO_EVAC_2S(info_ptr),INFO_SCAV_2S(info_ptr));
1409 #endif /* INFO_COPYING */
1411 #if defined(_INFO_COMPACTING)
1412 fprintf(stderr,"Scan Link: 0x%lx;\tScan Move: 0x%lx\n",
1413 (W_) INFO_SCAN_LINK_1S(info_ptr), (W_) INFO_SCAN_MOVE_1S(info_ptr));
1414 fprintf(stderr,"Mark: 0x%lx;\tMarked: 0x%lx;\n",
1415 (W_) INFO_MARK_1S(info_ptr), (W_) INFO_MARKED_1S(info_ptr));
1416 if(BASE_INFO_TYPE(info_ptr)==INFO_SPEC_TYPE)
1417 fprintf(stderr,"plus specialised code\n");
1419 fprintf(stderr,"Marking: 0x%lx\n",(W_) INFO_MARKING_1S(info_ptr));
1420 #endif /* INFO_COMPACTING */
1427 PP_ SpA = STKO_SpA(SAVE_StkO);
1428 PP_ SuA = STKO_SuA(SAVE_StkO);
1429 P_ SpB = STKO_SpB(SAVE_StkO);
1430 P_ SuB = STKO_SuB(SAVE_StkO);
1438 P_ HpLim= SAVE_HpLim;
1439 I_ TagReg= SAVE_Tag;
1440 StgRetAddr RetReg = SAVE_Ret;
1441 P_ Node = SAVE_R1.p;
1442 StgUnion R1 = SAVE_R1;
1443 StgUnion R2 = SAVE_R2;
1444 StgUnion R3 = SAVE_R3;
1445 StgUnion R4 = SAVE_R4;
1446 StgUnion R5 = SAVE_R5;
1447 StgUnion R6 = SAVE_R6;
1448 StgUnion R7 = SAVE_R7;
1449 StgUnion R8 = SAVE_R8;
1450 StgFloat FltReg1 = SAVE_Flt1;
1451 StgFloat FltReg2 = SAVE_Flt2;
1452 StgFloat FltReg3 = SAVE_Flt3;
1453 StgFloat FltReg4 = SAVE_Flt4;
1454 StgDouble DblReg1 = SAVE_Dbl1;
1455 StgDouble DblReg2 = SAVE_Dbl2;
1457 fprintf(stderr,"STG-Machine Register Values:\n\n");
1458 fprintf(stderr,"Node: %08lx; Hp: %08lx; HpLim: %08lx; Tag: %8lu\n",Node,(W_)Hp,(W_)HpLim,TagReg);
1459 fprintf(stderr,"SpA: %08lx; SpB: %08lx; SuA: %08lx; SuB: %08lx\n",(W_)SpA,(W_)SpB,(W_)SuA,(W_)SuB);
1460 fprintf(stderr,"RetReg: %08lx\n",RetReg);
1463 /* These bits need to have the FLUSH_REG_MAP, whereas the surrounding bits
1464 use the MAIN_REG_MAP */
1466 fprintf(stderr, "\n");
1467 fprintf(stderr,"LiveR: %08lx\n", LivenessReg);
1468 fprintf(stderr,"Flush: %08lx; FStk: %08lx; FStkB: %08lx; FTmp: %08lx\n",(W_)FlushP,(W_)FStack,(W_)FStackBase,(W_)Temp);
1471 fprintf(stderr, "\n");
1473 fprintf(stderr,"Gen: %8lu, %8lu, %8lu, %8lu\n",R1.i,R2.i,R3.i,R4.i);
1474 fprintf(stderr," %8lu, %8lu, %8lu, %8lu\n",R5.i,R6.i,R7.i,R8.i);
1475 fprintf(stderr,"Float: %8g, %8g, %8g, %8g\n",FltReg1,FltReg2,FltReg3,FltReg4);
1476 fprintf(stderr,"Dble: %8g, %8g\n",DblReg1,DblReg2);
1487 fprintf(stderr,"MallocPtrList\n\n");
1489 for(mp = StorageMgrInfo.MallocPtrList;
1491 mp = MallocPtr_CLOSURE_LINK(mp)) {
1493 fprintf(stderr, "MallocPtr(0x%lx) = 0x%lx\n", mp, MallocPtr_CLOSURE_DATA(mp));
1496 DEBUG_PRINT_NODE(mp);
1500 # if defined(GCap) || defined(GCgn)
1501 fprintf(stderr,"\nOldMallocPtr List\n\n");
1503 for(mp = StorageMgrInfo.OldMallocPtrList;
1505 mp = MallocPtr_CLOSURE_LINK(mp)) {
1507 fprintf(stderr, " MallocPtr(0x%lx) = 0x%lx\n", mp, MallocPtr_CLOSURE_DATA(mp));
1509 DEBUG_PRINT_NODE(mp);
1512 # endif /* GCap || GCgn */
1514 fprintf(stderr, "\n");
1518 DEBUG_SPT(int weight)
1520 StgPtr SPTable = StorageMgrInfo.StablePointerTable;
1521 StgInt size = SPT_SIZE(SPTable);
1522 StgInt ptrs = SPT_NoPTRS(SPTable);
1523 StgInt top = SPT_TOP(SPTable);
1528 DEBUG_PRINT_NODE(SPTable);
1531 fprintf(stderr,"SPTable@0x%lx:\n", SPTable);
1532 fprintf(stderr," InfoPtr = 0x%lx\n", INFO_PTR(SPTable));
1533 fprintf(stderr," size = %d, ptrs = %d, top = %d\n",
1536 for( i=0; i < ptrs; i++ ) {
1538 fprintf(stderr,"\n ");
1540 printClosure(SPT_SPTR(SPTable, i),1,weight);
1541 fprintf(stderr, "\n");
1543 fprintf(stderr, "\n");
1544 for( i=0; i < top; i++) {
1546 fprintf(stderr,"\n ");
1548 fprintf(stderr, " %3d", SPT_FREE(SPTable, i));
1551 fprintf(stderr, "\n\n");
1554 #endif /* !CONCURRENT */
1557 These routines crawl over the A and B stacks, printing
1558 a maximum "lines" lines at the top of the stack.
1561 #define STACK_VALUES_PER_LINE 5
1564 /* (stack stuff is really different on parallel machines) */
1578 fprintf(stderr,"Dump of the Address Stack, SpA: 0x%08lx, BOS: 0x%08lx\n",
1579 (W_) SpA, (W_) stackInfo.botA);
1581 for (stackptr = SpA;
1582 SUBTRACT_A_STK(stackptr, stackInfo.botA) >= 0;
1583 stackptr = stackptr + AREL(1))
1585 if( count++ % STACK_VALUES_PER_LINE == 0)
1587 if(count >= lines * STACK_VALUES_PER_LINE)
1589 fprintf(stderr,"\nSpA[%ld] (0x%08lx): ",count-1,stackptr);
1591 fprintf(stderr,"0x%08lx ",(W_) *stackptr);
1593 fprintf(stderr, "\n");
1608 fprintf(stderr,"Dump of the Value Stack, SpB: 0x%08lx, BOS: 0x%08lx\n",
1609 (W_) SpB, (W_) stackInfo.botB);
1611 for (stackptr = SpB;
1612 SUBTRACT_B_STK(stackptr, stackInfo.botB) > 0;
1613 stackptr = stackptr + BREL(1))
1615 if( count++ % STACK_VALUES_PER_LINE == 0)
1617 if(count >= lines * STACK_VALUES_PER_LINE)
1619 fprintf(stderr,"\nSpB[%ld] (0x%08lx): ",count-1,stackptr);
1621 fprintf(stderr,"0x%08lx ",(W_) *stackptr);
1623 fprintf(stderr, "\n");
1625 #endif /* not concurrent */
1628 This should disentangle update frames from both stacks.
1633 DEBUG_UPDATES(limit)
1646 fprintf(stderr,"Update Frame Stack Dump:\n\n");
1648 for(spa = SuA, spb = SuB;
1649 SUBTRACT_B_STK(spb, stackInfo.botB) > 0 && count++ < limit;
1650 spa = GRAB_SuA(spb), spb = GRAB_SuB(spb) ) {
1652 updatee = GRAB_UPDATEE(spb); /* Thing to be updated */
1653 retreg = (P_) GRAB_RET(spb); /* Return vector below */
1655 fprintf(stderr,"SuA: 0x%08lx, SuB: 0x%08lx, Updatee 0x%08lx (Info 0x%08lx), RetReg 0x%x\n",
1657 (W_) updatee, (W_) INFO_PTR(updatee), (W_) retreg);
1661 #endif /* not concurrent */
1670 STGRegisterTable *r = TSO_INTERNAL_PTR(tso);
1671 W_ liveness = r->rLiveness;
1674 fprintf(stderr,"TSO:\ntso=%lx, regs=%lx, liveness=%lx\nlink=%lx,name=%lx,id=%lx,type=%lx,pc1=%lx,arg1=%lx,switch=%lx\n"
1687 for (i = 0; liveness != 0; liveness >>= 1, i++) {
1689 fprintf(stderr, "live reg %d (%lx)\n",i, r->rR[i].p);
1691 fprintf(stderr, "reg %d (%lx) not live\n", i, r->rR[i].p);
1696 #endif /* concurrent */