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_NoPTRS(node);
655 printf("Panic: found FETCHME Infotable in sequential system.\n");
662 *size = FMBQ_CLOSURE_SIZE(node);
663 *ptrs = FMBQ_CLOSURE_NoPTRS(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);
730 PP_ botA = 0; /* junk */
732 # define CAN_SEE_STK_BOTTOMS 0
738 PP_ botA = stackInfo.botA;
739 P_ botB = stackInfo.botB;
740 # define CAN_SEE_STK_BOTTOMS 1
748 /* ToDo: check if it's in text or data segment. */
750 /* The @-1@s in stack comparisons are because we sometimes use the
751 address of just below the stack... */
754 if (lookupForName( address, &name )) {
760 if (DEBUG_details > 1) {
761 printWord( (W_) address );
764 if (HpBot <= address && address < Hp) {
765 printf("Hp[%d]", address - HpBot);
766 } else if ( CAN_SEE_STK_BOTTOMS
767 && SUBTRACT_A_STK((PP_)address, botA) >= -1
768 && SUBTRACT_A_STK(SpA, (PP_)address) >= 0) {
769 printf("SpA[%d]", SUBTRACT_A_STK((PP_)address, botA));
771 } else if ( CAN_SEE_STK_BOTTOMS
772 && SUBTRACT_B_STK(address, botB) >= -1
773 && SUBTRACT_B_STK(SpB, address) >= 0) {
774 /* ToDo: check if it's an update frame */
775 printf("SpB[%d]", SUBTRACT_B_STK(address, botB));
778 printWord( (W_) address );
784 printIndentation( int indentation )
787 for (i = 0; i < indentation; ++i) { printf(" "); }
790 /* The weight parameter is used to (eventually) break cycles */
792 printStandardShapeClosure(
795 P_ closure, int vhs, int size, int noPtrs
799 PP_ SpA = STKO_SpA(SAVE_StkO);
800 PP_ SuA = STKO_SuA(SAVE_StkO);
801 P_ SpB = STKO_SpB(SAVE_StkO);
802 P_ SuB = STKO_SuB(SAVE_StkO);
811 extern void printClosure PROTO( (P_, int, int) );
812 int numValues = size - vhs;
815 if (DEBUG_details > 1) {
816 printAddress( closure );
819 printName((P_)INFO_PTR(closure));
821 if ( numValues > 0 ) {
822 int newWeight = weight-1 ;
823 /* I've tried dividing the weight by size to share it out amongst
824 sub-closures - but that didn't work too well. */
829 while (i < numValues) {
830 P_ data = (P_) closure[_FHS + vhs + i];
832 printIndentation(indentation+1);
834 printClosure( data, indentation+1, newWeight);
836 printAddress( data );
839 if (i < numValues) printf(",\n");
845 for( i = 1; i < size; ++i ) {
853 /* Should be static but has to be extern to allow mutual recursion */
855 printClosure( P_ closure, int indentation, int weight )
860 /* I'd love to put a test here that this actually _is_ a closure -
861 but testing that it is in the heap is overly strong. */
863 getClosureShape(closure, &vhs, &size, &ptrs, &type);
865 /* The order here precisely reflects that in SMInfoTables.lh to make
866 it easier to check that this list is complete. */
867 switch(INFO_TYPE(INFO_PTR(closure))) {
868 case INFO_SPEC_U_TYPE:
869 case INFO_SPEC_N_TYPE:
870 case INFO_GEN_U_TYPE:
871 case INFO_GEN_N_TYPE:
873 case INFO_TUPLE_TYPE:
875 case INFO_MUTUPLE_TYPE:
876 case INFO_IMMUTUPLE_TYPE:
877 printStandardShapeClosure(indentation, weight, closure,
881 case INFO_STATIC_TYPE:
882 /* If the STATIC contains Floats or Doubles, we can't print it. */
883 /* And we can't always rely on the size/ptrs info either */
884 printAddress( closure );
888 case INFO_CONST_TYPE:
889 if (DEBUG_details > 1) {
890 printAddress( closure );
893 printName((P_)INFO_PTR(closure));
896 case INFO_CHARLIKE_TYPE:
897 /* ToDo: check for non-printable characters */
898 if (DEBUG_details > 1) printf("CHARLIKE ");
899 printf("\'%c\'", (unsigned char) CHARLIKE_VALUE(closure));
902 case INFO_INTLIKE_TYPE:
903 if (DEBUG_details > 1) printf("INTLIKE ");
904 printf("%d",INTLIKE_VALUE(closure));
908 /* Is there anything to say here> */
909 if (DEBUG_details > 1) {
910 printAddress( closure );
913 printName((P_)INFO_PTR(closure));
916 /* most of the following are just plausible guesses (particularily VHSs) ADR */
920 printStandardShapeClosure(indentation, weight, closure,
923 printf("Panic: found BQ Infotable in non-threaded system.\n");
928 if (DEBUG_details > 0) {
929 printAddress( closure );
932 printClosure( (P_) IND_CLOSURE_PTR(closure), indentation, weight );
936 if (DEBUG_details > 0) {
937 printAddress( closure );
940 printClosure( (P_) IND_CLOSURE_PTR(closure), indentation, weight );
943 case INFO_FETCHME_TYPE:
945 printStandardShapeClosure(indentation, weight, closure,
948 printf("Panic: found FETCHME Infotable in sequential system.\n");
954 printStandardShapeClosure(indentation, weight, closure,
957 printf("Panic: found FMBQ Infotable in sequential system.\n");
963 printStandardShapeClosure(indentation, weight, closure,
966 printf("Panic: found BlockedFetch Infotable in sequential system.\n");
972 /* A TSO contains a regtable... */
973 printAddress( closure );
976 printf("Panic: found TSO Infotable in non-threaded system.\n");
982 /* A STKO contains parts of the A and B stacks... */
983 printAddress( closure );
984 printf(" STKO: ...");
986 printf("Panic: found STKO Infotable in non-threaded system.\n");
990 /* There are no others in SMInfoTables.lh 11/5/94 ADR*/
992 printf("Invalid/unknown info type %d\n", INFO_TYPE(INFO_PTR(closure)));
998 DEBUG_NODE( P_ closure, int size )
1000 printClosure( closure, 0, size );
1005 Now some stuff for printing stacks - almost certainly doesn't work
1006 under threads which keep the stack on the heap.
1012 minimum(int a, int b)
1022 DEBUG_PrintA( int depth, int weight )
1031 I_ size = minimum(depth, SUBTRACT_A_STK(SpA, stackInfo.botA)+1);
1033 printf("Dump of the Address Stack (SpA = 0x%x, SuA = 0x%x)\n", SpA, SuA);
1035 for( i = 0; i < size; ++i ) {
1036 printIndentation(1);
1037 printf("SpA[%ld] (0x%08lx):", i, SpA + AREL(i));
1038 printClosure((P_)*(SpA + AREL(i)), 2, weight);
1044 DEBUG_PrintB( int depth, int weight )
1053 I_ size = minimum(depth, SUBTRACT_B_STK(SpB, stackInfo.botB)+1);
1058 printf("Dump of the Value Stack (SpB = 0x%x, SuB = 0x%x)\n", SpB, SuB);
1060 updateFramePtr = SuB;
1064 if (updateFramePtr == SpB + BREL(i)) {
1066 printIndentation(1);
1067 printf("SpB[%ld] (0x%08lx): UpdateFrame[%d](",
1072 printName( (P_) *(SpB + BREL(i)) );
1073 printf(", UF[%d] (= SpB[%ld]), SpA[%ld], ",
1075 SUBTRACT_B_STK(SpB, GRAB_SuB(updateFramePtr)),
1076 SUBTRACT_A_STK(SpA, GRAB_SuA(updateFramePtr))
1078 printAddress( GRAB_UPDATEE(updateFramePtr) );
1081 printIndentation(2);
1082 printClosure( GRAB_UPDATEE(updateFramePtr), 3, weight );
1085 updateFramePtr = GRAB_SuB(updateFramePtr);
1086 update_count = update_count + 1;
1088 /* ToDo: GhcConstants.lh reveals that there are two other sizes possible */
1089 i = i + STD_UF_SIZE;
1091 printIndentation(1);
1092 printf("SpB[%ld] (0x%08lx): ", i, SpB + BREL(i) );
1093 printName((P_) *(SpB + BREL(i)) );
1099 #endif /* not CONCURRENT */
1104 All the following code incorrectly assumes that the only return
1105 addresses are those associated with update frames.
1107 To do a proper job of printing the environment we need to:
1109 1) Recognise vectored and non-vectored returns on the B stack.
1111 2) Know where the local variables are in the A and B stacks for
1112 each return situation.
1114 Until then, we'll just need to look suspiciously at the
1115 "environment" being printed out.
1120 /* How many real stacks are there on SpA and SpB? */
1121 /* Say what?? (Will and Phil, 96/01) */
1127 PP_ SpA = STKO_SpA(SAVE_StkO);
1128 PP_ SuA = STKO_SuA(SAVE_StkO);
1129 P_ SpB = STKO_SpB(SAVE_StkO);
1130 P_ SuB = STKO_SuB(SAVE_StkO);
1139 int depth = 1; /* There's always at least one stack */
1141 while (SUBTRACT_B_STK(SuB, stackInfo.botB) >= 0) {
1142 SuB = GRAB_SuB( SuB );
1147 #endif /* !CONCURRENT */
1150 printLocalAStack( int depth, int indentation, int weight, PP_ SpA, int size )
1154 ASSERT( size >= 0 );
1156 for( i = size-1; i >= 0; --i ) {
1157 printIndentation( indentation );
1158 printf("A[%ld][%ld]", depth, i);
1159 if (DEBUG_details > 1) printf(" (0x%08lx) ", SpA + AREL(i) );
1161 printClosure( *(SpA + AREL(i)), indentation+2, weight );
1167 printLocalBStack( int depth, int indentation, int weight, P_ SpB, int size )
1171 ASSERT( size >= 0 );
1173 for( i = size-1; i >= 0; --i) {
1174 printIndentation( indentation );
1175 printf("B[%ld][%ld]", depth, i);
1176 if (DEBUG_details > 1) printf(" (0x%08lx) ", SpB + BREL(i) );
1178 printAddress( (P_) *(SpB + BREL(i)) );
1184 printEnvironment( int depth, int indentation, int weight, PP_ SpA, PP_ SuA, P_ SpB, P_ SuB )
1186 int sizeA = SUBTRACT_A_STK(SpA, SuA);
1187 int sizeB = SUBTRACT_B_STK(SpB, SuB);
1189 if (sizeA + sizeB > 0) {
1190 printIndentation( indentation );
1193 printLocalAStack( depth, indentation+1, weight, SpA, sizeA );
1194 printLocalBStack( depth, indentation+1, weight, SpB, sizeB );
1196 printIndentation( indentation );
1202 Printing the current context is a little tricky.
1204 Ideally, we would work from the bottom of the stack up to the top
1205 recursively printing the stuff nearer the top.
1207 In practice, we have to work from the top down because the top
1208 contains info about how much data is below the current return address.
1210 The result is that we have two recursive passes over the stacks: the
1211 first one prints the "cases" and the second one prints the
1212 continuations (vector tables, etc.)
1214 Note that because we compress chains of update frames, the depth and
1215 indentation do not always change in step.
1219 * detecting non-updating cases too
1220 * printing continuations (from vector tables) properly
1221 * printing sensible names in environment.
1222 * fix bogus nature of lets
1226 static int maxDepth = 5;
1229 printCases( int depth, int weight, PP_ SpA, PP_ SuA, P_ SpB, P_ SuB )
1232 printf("no printCases for CONCURRENT\n");
1236 if (depth < maxDepth && SUBTRACT_B_STK(SuB, stackInfo.botB) >= 0) {
1237 PP_ nextSpA, nextSuA;
1238 P_ nextSpB, nextSuB;
1240 /* ToDo: GhcConstants.lh reveals that there are two other sizes of
1241 update frame possible */
1242 /* ToDo: botB is probably wrong in THREAD system */
1244 nextSpB = SuB + BREL(STD_UF_SIZE);
1245 nextSuB = GRAB_SuB( SuB );
1247 nextSuA = GRAB_SuA( nextSuB );
1249 indentation = printCases( depth+1, weight, nextSpA, nextSuA, nextSpB, nextSuB );
1251 if (DEBUG_details > 1 || nextSpB != nextSuB) { /* show frame (even if adjacent to another) */
1252 printIndentation( indentation );
1254 indentation = indentation + 1;
1257 /* next thing on stack is a return vector - no need to show it here. */
1258 SpB = SpB + BREL(1);
1260 printEnvironment( depth, indentation, weight, SpA, SuA, SpB, SuB );
1268 #endif /* CONCURRENT */
1271 /* ToDo: pay more attention to format of vector tables in SMupdate.lh */
1274 isVTBLEntry( P_ entry )
1278 if (lookupForName( entry, &raw )) {
1279 if ( strncmp( "_ret", raw, 4 ) == 0 ) {
1281 } else if ( strncmp( "_djn", raw, 4 ) == 0) {
1292 printVectorTable( int indentation, PP_ vtbl )
1294 if (isVTBLEntry( (P_) vtbl )) { /* Direct return */
1295 printName( (P_) vtbl );
1298 while( isVTBLEntry( vtbl[RVREL(i)] )) {
1299 printIndentation( indentation );
1300 printf( "%d -> ", i );
1301 printName( vtbl[RVREL(i)] );
1309 printContinuations( int depth, int indentation, int weight, PP_ SpA, PP_ SuA, P_ SpB, P_ SuB )
1312 printf("no printContinuations for CONCURRENT\n");
1314 if (depth < maxDepth && SUBTRACT_B_STK(SuB, stackInfo.botB) >= 0) {
1315 PP_ nextSpA, nextSuA;
1316 P_ nextSpB, nextSuB;
1317 int nextIndent = indentation; /* Indentation to print next frame at */
1319 /* ToDo: GhcConstants.lh reveals that there are two other sizes of
1320 update frame possible */
1321 /* ToDo: botB is probably wrong in THREAD system */
1323 /* ToDo: ASSERT that SuA == nextSuA */
1325 nextSpB = SuB + BREL(STD_UF_SIZE);
1326 nextSuB = GRAB_SuB( SuB );
1328 nextSuA = GRAB_SuA( nextSuB );
1330 if (DEBUG_details > 0) { /* print update information */
1332 if (SpB != SuB) { /* start of chain of update frames */
1333 printIndentation( indentation );
1334 printf("of updatePtr ->\n");
1335 printIndentation( indentation+1 );
1338 printIndentation( indentation+2 );
1339 printClosure( (P_)*(SuB + BREL(UF_UPDATEE)), indentation+2, weight );
1341 printName( (P_) *(SuB + BREL(UF_RET)) );
1342 printf("(updatePtr)\n");
1344 if (nextSpB != nextSuB) { /* end of chain of update frames */
1345 nextIndent = nextIndent-1;
1346 printVectorTable( indentation+1, (PP_) *(nextSpB) );
1349 if (nextSpB != nextSuB) { /* end of chain of update frames */
1350 nextIndent = nextIndent-1;
1351 printVectorTable( indentation, (PP_) *(nextSpB) );
1354 printContinuations( depth+1, nextIndent, weight, nextSpA, nextSuA, nextSpB, nextSuB );
1359 #endif /* CONCURRENT */
1363 DEBUG_Where( int depth, int weight )
1366 PP_ SpA = STKO_SpA(SAVE_StkO);
1367 PP_ SuA = STKO_SuA(SAVE_StkO);
1368 P_ SpB = STKO_SpB(SAVE_StkO);
1369 P_ SuB = STKO_SuB(SAVE_StkO);
1377 StgRetAddr RetReg = SAVE_Ret;
1378 P_ Node = SAVE_R1.p;
1384 printf("WARNING: Non-updating cases may be incorrectly displayed\n");
1386 indentation = printCases( 1, weight, SpA, SuA, SpB, SuB );
1388 printIndentation( indentation );
1391 printIndentation( indentation+1 );
1394 printVectorTable( indentation+1, (PP_) RetReg );
1396 printContinuations( depth, indentation, weight, SpA, SuA, SpB, SuB );
1403 DEBUG_INFO_TABLE(node)
1406 int vhs, size, ptrs; /* not used */
1408 StgPtr info_ptr = (StgPtr) INFO_PTR(node);
1410 getClosureShape(node, &vhs, &size, &ptrs, &ip_type);
1413 "%s Info Ptr 0x%lx; Entry: 0x%lx; Update: 0x%lx\n",
1415 (W_) ENTRY_CODE(info_ptr), (W_) UPDATE_CODE(info_ptr));
1417 "Tag: %d; Type: %d; Size: %lu; Ptrs: %lu\n\n",
1418 INFO_TAG(info_ptr), INFO_TYPE(info_ptr),
1419 INFO_SIZE(info_ptr),INFO_NoPTRS(info_ptr));
1421 /* flushing is GRIP only */
1422 fprintf(stderr,"Enter Flush Entry: 0x%lx;\tExit Flush Entry: 0x%lx\n",INFO_FLUSHENT(info_ptr),INFO_FLUSH(info_ptr));
1425 #if defined(PROFILING)
1426 fprintf(stderr,"Cost Centre: 0x%lx\n",INFO_CAT(info_ptr));
1427 #endif /* PROFILING */
1429 #if defined(_INFO_COPYING)
1430 fprintf(stderr,"Evacuate Entry: 0x%lx;\tScavenge Entry: 0x%lx\n",
1431 INFO_EVAC_2S(info_ptr),INFO_SCAV_2S(info_ptr));
1432 #endif /* INFO_COPYING */
1434 #if defined(_INFO_COMPACTING)
1435 fprintf(stderr,"Scan Link: 0x%lx;\tScan Move: 0x%lx\n",
1436 (W_) INFO_SCAN_LINK_1S(info_ptr), (W_) INFO_SCAN_MOVE_1S(info_ptr));
1437 fprintf(stderr,"Mark: 0x%lx;\tMarked: 0x%lx;\n",
1438 (W_) INFO_MARK_1S(info_ptr), (W_) INFO_MARKED_1S(info_ptr));
1439 if(BASE_INFO_TYPE(info_ptr)==INFO_SPEC_TYPE)
1440 fprintf(stderr,"plus specialised code\n");
1442 fprintf(stderr,"Marking: 0x%lx\n",(W_) INFO_MARKING_1S(info_ptr));
1443 #endif /* INFO_COMPACTING */
1450 PP_ SpA = STKO_SpA(SAVE_StkO);
1451 PP_ SuA = STKO_SuA(SAVE_StkO);
1452 P_ SpB = STKO_SpB(SAVE_StkO);
1453 P_ SuB = STKO_SuB(SAVE_StkO);
1461 P_ HpLim= SAVE_HpLim;
1462 I_ TagReg= SAVE_Tag;
1463 StgRetAddr RetReg = SAVE_Ret;
1464 P_ Node = SAVE_R1.p;
1465 StgUnion R1 = SAVE_R1;
1466 StgUnion R2 = SAVE_R2;
1467 StgUnion R3 = SAVE_R3;
1468 StgUnion R4 = SAVE_R4;
1469 StgUnion R5 = SAVE_R5;
1470 StgUnion R6 = SAVE_R6;
1471 StgUnion R7 = SAVE_R7;
1472 StgUnion R8 = SAVE_R8;
1473 StgFloat FltReg1 = SAVE_Flt1;
1474 StgFloat FltReg2 = SAVE_Flt2;
1475 StgFloat FltReg3 = SAVE_Flt3;
1476 StgFloat FltReg4 = SAVE_Flt4;
1477 StgDouble DblReg1 = SAVE_Dbl1;
1478 StgDouble DblReg2 = SAVE_Dbl2;
1480 fprintf(stderr,"STG-Machine Register Values:\n\n");
1481 fprintf(stderr,"Node: %08lx; Hp: %08lx; HpLim: %08lx; Tag: %8lu\n",Node,(W_)Hp,(W_)HpLim,TagReg);
1482 fprintf(stderr,"SpA: %08lx; SpB: %08lx; SuA: %08lx; SuB: %08lx\n",(W_)SpA,(W_)SpB,(W_)SuA,(W_)SuB);
1483 fprintf(stderr,"RetReg: %08lx\n",RetReg);
1486 /* These bits need to have the FLUSH_REG_MAP, whereas the surrounding bits
1487 use the MAIN_REG_MAP */
1489 fprintf(stderr, "\n");
1490 fprintf(stderr,"LiveR: %08lx\n", LivenessReg);
1491 fprintf(stderr,"Flush: %08lx; FStk: %08lx; FStkB: %08lx; FTmp: %08lx\n",(W_)FlushP,(W_)FStack,(W_)FStackBase,(W_)Temp);
1494 fprintf(stderr, "\n");
1496 fprintf(stderr,"Gen: %8lu, %8lu, %8lu, %8lu\n",R1.i,R2.i,R3.i,R4.i);
1497 fprintf(stderr," %8lu, %8lu, %8lu, %8lu\n",R5.i,R6.i,R7.i,R8.i);
1498 fprintf(stderr,"Float: %8g, %8g, %8g, %8g\n",FltReg1,FltReg2,FltReg3,FltReg4);
1499 fprintf(stderr,"Dble: %8g, %8g\n",DblReg1,DblReg2);
1510 fprintf(stderr,"MallocPtrList\n\n");
1512 for(mp = StorageMgrInfo.MallocPtrList;
1514 mp = MallocPtr_CLOSURE_LINK(mp)) {
1516 fprintf(stderr, "MallocPtr(0x%lx) = 0x%lx\n", mp, MallocPtr_CLOSURE_DATA(mp));
1519 DEBUG_PRINT_NODE(mp);
1523 # if defined(GCap) || defined(GCgn)
1524 fprintf(stderr,"\nOldMallocPtr List\n\n");
1526 for(mp = StorageMgrInfo.OldMallocPtrList;
1528 mp = MallocPtr_CLOSURE_LINK(mp)) {
1530 fprintf(stderr, " MallocPtr(0x%lx) = 0x%lx\n", mp, MallocPtr_CLOSURE_DATA(mp));
1532 DEBUG_PRINT_NODE(mp);
1535 # endif /* GCap || GCgn */
1537 fprintf(stderr, "\n");
1541 DEBUG_SPT(int weight)
1543 StgPtr SPTable = StorageMgrInfo.StablePointerTable;
1544 StgInt size = SPT_SIZE(SPTable);
1545 StgInt ptrs = SPT_NoPTRS(SPTable);
1546 StgInt top = SPT_TOP(SPTable);
1551 DEBUG_PRINT_NODE(SPTable);
1554 fprintf(stderr,"SPTable@0x%lx:\n", SPTable);
1555 fprintf(stderr," InfoPtr = 0x%lx\n", INFO_PTR(SPTable));
1556 fprintf(stderr," size = %d, ptrs = %d, top = %d\n",
1559 for( i=0; i < ptrs; i++ ) {
1561 fprintf(stderr,"\n ");
1563 printClosure(SPT_SPTR(SPTable, i),1,weight);
1564 fprintf(stderr, "\n");
1566 fprintf(stderr, "\n");
1567 for( i=0; i < top; i++) {
1569 fprintf(stderr,"\n ");
1571 fprintf(stderr, " %3d", SPT_FREE(SPTable, i));
1574 fprintf(stderr, "\n\n");
1577 #endif /* !CONCURRENT */
1580 These routines crawl over the A and B stacks, printing
1581 a maximum "lines" lines at the top of the stack.
1584 #define STACK_VALUES_PER_LINE 5
1587 /* (stack stuff is really different on parallel machines) */
1601 fprintf(stderr,"Dump of the Address Stack, SpA: 0x%08lx, BOS: 0x%08lx\n",
1602 (W_) SpA, (W_) stackInfo.botA);
1604 for (stackptr = SpA;
1605 SUBTRACT_A_STK(stackptr, stackInfo.botA) >= 0;
1606 stackptr = stackptr + AREL(1))
1608 if( count++ % STACK_VALUES_PER_LINE == 0)
1610 if(count >= lines * STACK_VALUES_PER_LINE)
1612 fprintf(stderr,"\nSpA[%ld] (0x%08lx): ",count-1,stackptr);
1614 fprintf(stderr,"0x%08lx ",(W_) *stackptr);
1616 fprintf(stderr, "\n");
1631 fprintf(stderr,"Dump of the Value Stack, SpB: 0x%08lx, BOS: 0x%08lx\n",
1632 (W_) SpB, (W_) stackInfo.botB);
1634 for (stackptr = SpB;
1635 SUBTRACT_B_STK(stackptr, stackInfo.botB) > 0;
1636 stackptr = stackptr + BREL(1))
1638 if( count++ % STACK_VALUES_PER_LINE == 0)
1640 if(count >= lines * STACK_VALUES_PER_LINE)
1642 fprintf(stderr,"\nSpB[%ld] (0x%08lx): ",count-1,stackptr);
1644 fprintf(stderr,"0x%08lx ",(W_) *stackptr);
1646 fprintf(stderr, "\n");
1648 #endif /* not concurrent */
1651 This should disentangle update frames from both stacks.
1656 DEBUG_UPDATES(limit)
1669 fprintf(stderr,"Update Frame Stack Dump:\n\n");
1671 for(spa = SuA, spb = SuB;
1672 SUBTRACT_B_STK(spb, stackInfo.botB) > 0 && count++ < limit;
1673 spa = GRAB_SuA(spb), spb = GRAB_SuB(spb) ) {
1675 updatee = GRAB_UPDATEE(spb); /* Thing to be updated */
1676 retreg = (P_) GRAB_RET(spb); /* Return vector below */
1678 fprintf(stderr,"SuA: 0x%08lx, SuB: 0x%08lx, Updatee 0x%08lx (Info 0x%08lx), RetReg 0x%x\n",
1680 (W_) updatee, (W_) INFO_PTR(updatee), (W_) retreg);
1684 #endif /* not concurrent */
1693 STGRegisterTable *r = TSO_INTERNAL_PTR(tso);
1694 W_ liveness = r->rLiveness;
1697 fprintf(stderr,"TSO:\ntso=%lx, regs=%lx, liveness=%lx\nlink=%lx,name=%lx,id=%lx,type=%lx,pc1=%lx,arg1=%lx,switch=%lx\n"
1710 for (i = 0; liveness != 0; liveness >>= 1, i++) {
1712 fprintf(stderr, "live reg %d (%lx)\n",i, r->rR[i].p);
1714 fprintf(stderr, "reg %d (%lx) not live\n", i, r->rR[i].p);
1719 #endif /* concurrent */