STM invariants
[ghc-hetmet.git] / rts / Printer.c
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1994-2000.
4  *
5  * Heap printer
6  * 
7  * ---------------------------------------------------------------------------*/
8
9 #include "PosixSource.h"
10 #include "Rts.h"
11 #include "Printer.h"
12 #include "RtsUtils.h"
13
14 #ifdef DEBUG
15
16 #include "RtsFlags.h"
17 #include "MBlock.h"
18 #include "Storage.h"
19 #include "Bytecodes.h"  /* for InstrPtr */
20 #include "Disassembler.h"
21 #include "Apply.h"
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #if defined(GRAN) || defined(PAR)
27 // HWL: explicit fixed header size to make debugging easier
28 int fixed_hs = sizeof(StgHeader), itbl_sz = sizeofW(StgInfoTable), 
29     uf_sz=sizeofW(StgUpdateFrame); 
30 #endif
31
32 /* --------------------------------------------------------------------------
33  * local function decls
34  * ------------------------------------------------------------------------*/
35
36 static void    printStdObjPayload( StgClosure *obj );
37 #ifdef USING_LIBBFD
38 static void    reset_table   ( int size );
39 static void    prepare_table ( void );
40 static void    insert        ( StgWord value, const char *name );
41 #endif
42 #if 0 /* unused but might be useful sometime */
43 static rtsBool lookup_name   ( char *name, StgWord *result );
44 static void    enZcode       ( char *in, char *out );
45 #endif
46 static char    unZcode       ( char ch );
47 const char *   lookupGHCName ( void *addr );
48 static void    printZcoded   ( const char *raw );
49
50 /* --------------------------------------------------------------------------
51  * Printer
52  * ------------------------------------------------------------------------*/
53
54 void printPtr( StgPtr p )
55 {
56     const char *raw;
57     raw = lookupGHCName(p);
58     if (raw != NULL) {
59         printZcoded(raw);
60     } else {
61         debugBelch("%p", p);
62     }
63 }
64   
65 void printObj( StgClosure *obj )
66 {
67     debugBelch("Object "); printPtr((StgPtr)obj); debugBelch(" = ");
68     printClosure(obj);
69 }
70
71 STATIC_INLINE void
72 printStdObjHdr( StgClosure *obj, char* tag )
73 {
74     debugBelch("%s(",tag);
75     printPtr((StgPtr)obj->header.info);
76 #ifdef PROFILING
77     debugBelch(", %s", obj->header.prof.ccs->cc->label);
78 #endif
79 }
80
81 static void
82 printStdObjPayload( StgClosure *obj )
83 {
84     StgWord i, j;
85     const StgInfoTable* info;
86
87     info = get_itbl(obj);
88     for (i = 0; i < info->layout.payload.ptrs; ++i) {
89         debugBelch(", ");
90         printPtr((StgPtr)obj->payload[i]);
91     }
92     for (j = 0; j < info->layout.payload.nptrs; ++j) {
93         debugBelch(", %pd#",obj->payload[i+j]);
94     }
95     debugBelch(")\n");
96 }
97
98 static void
99 printThunkPayload( StgThunk *obj )
100 {
101     StgWord i, j;
102     const StgInfoTable* info;
103
104     info = get_itbl(obj);
105     for (i = 0; i < info->layout.payload.ptrs; ++i) {
106         debugBelch(", ");
107         printPtr((StgPtr)obj->payload[i]);
108     }
109     for (j = 0; j < info->layout.payload.nptrs; ++j) {
110         debugBelch(", %pd#",obj->payload[i+j]);
111     }
112     debugBelch(")\n");
113 }
114
115 static void
116 printThunkObject( StgThunk *obj, char* tag )
117 {
118     printStdObjHdr( (StgClosure *)obj, tag );
119     printThunkPayload( obj );
120 }
121
122 void
123 printClosure( StgClosure *obj )
124 {
125     StgInfoTable *info;
126     
127     info = get_itbl(obj);
128
129     switch ( info->type ) {
130     case INVALID_OBJECT:
131             barf("Invalid object");
132
133     case CONSTR:
134     case CONSTR_1_0: case CONSTR_0_1:
135     case CONSTR_1_1: case CONSTR_0_2: case CONSTR_2_0:
136     case CONSTR_STATIC:
137     case CONSTR_NOCAF_STATIC:
138         {
139             StgWord i, j;
140 #ifdef PROFILING
141             debugBelch("%s(", info->prof.closure_desc);
142             debugBelch("%s", obj->header.prof.ccs->cc->label);
143 #else
144             debugBelch("CONSTR(");
145             printPtr((StgPtr)obj->header.info);
146             debugBelch("(tag=%d)",info->srt_bitmap);
147 #endif
148             for (i = 0; i < info->layout.payload.ptrs; ++i) {
149                 debugBelch(", ");
150                 printPtr((StgPtr)obj->payload[i]);
151             }
152             for (j = 0; j < info->layout.payload.nptrs; ++j) {
153                 debugBelch(", %p#", obj->payload[i+j]);
154             }
155             debugBelch(")\n");
156             break;
157         }
158
159     case FUN:
160     case FUN_1_0: case FUN_0_1: 
161     case FUN_1_1: case FUN_0_2: case FUN_2_0:
162     case FUN_STATIC:
163         debugBelch("FUN/%d(",itbl_to_fun_itbl(info)->f.arity);
164         printPtr((StgPtr)obj->header.info);
165 #ifdef PROFILING
166         debugBelch(", %s", obj->header.prof.ccs->cc->label);
167 #endif
168         printStdObjPayload(obj);
169         break;
170
171     case THUNK:
172     case THUNK_1_0: case THUNK_0_1:
173     case THUNK_1_1: case THUNK_0_2: case THUNK_2_0:
174     case THUNK_STATIC:
175             /* ToDo: will this work for THUNK_STATIC too? */
176 #ifdef PROFILING
177             printThunkObject((StgThunk *)obj,info->prof.closure_desc);
178 #else
179             printThunkObject((StgThunk *)obj,"THUNK");
180 #endif
181             break;
182
183     case THUNK_SELECTOR:
184         printStdObjHdr(obj, "THUNK_SELECTOR");
185         debugBelch(", %p)\n", ((StgSelector *)obj)->selectee);
186         break;
187
188     case BCO:
189             disassemble( (StgBCO*)obj );
190             break;
191
192     case AP:
193         {
194             StgAP* ap = stgCast(StgAP*,obj);
195             StgWord i;
196             debugBelch("AP("); printPtr((StgPtr)ap->fun);
197             for (i = 0; i < ap->n_args; ++i) {
198                 debugBelch(", ");
199                 printPtr((P_)ap->payload[i]);
200             }
201             debugBelch(")\n");
202             break;
203         }
204
205     case PAP:
206         {
207             StgPAP* pap = stgCast(StgPAP*,obj);
208             StgWord i;
209             debugBelch("PAP/%d(",pap->arity); 
210             printPtr((StgPtr)pap->fun);
211             for (i = 0; i < pap->n_args; ++i) {
212                 debugBelch(", ");
213                 printPtr((StgPtr)pap->payload[i]);
214             }
215             debugBelch(")\n");
216             break;
217         }
218
219     case AP_STACK:
220         {
221             StgAP_STACK* ap = stgCast(StgAP_STACK*,obj);
222             StgWord i;
223             debugBelch("AP_STACK("); printPtr((StgPtr)ap->fun);
224             for (i = 0; i < ap->size; ++i) {
225                 debugBelch(", ");
226                 printPtr((P_)ap->payload[i]);
227             }
228             debugBelch(")\n");
229             break;
230         }
231
232     case IND:
233             debugBelch("IND("); 
234             printPtr((StgPtr)stgCast(StgInd*,obj)->indirectee);
235             debugBelch(")\n"); 
236             break;
237
238     case IND_OLDGEN:
239             debugBelch("IND_OLDGEN("); 
240             printPtr((StgPtr)stgCast(StgInd*,obj)->indirectee);
241             debugBelch(")\n"); 
242             break;
243
244     case IND_PERM:
245             debugBelch("IND("); 
246             printPtr((StgPtr)stgCast(StgInd*,obj)->indirectee);
247             debugBelch(")\n"); 
248             break;
249
250     case IND_OLDGEN_PERM:
251             debugBelch("IND_OLDGEN_PERM("); 
252             printPtr((StgPtr)stgCast(StgInd*,obj)->indirectee);
253             debugBelch(")\n"); 
254             break;
255
256     case IND_STATIC:
257             debugBelch("IND_STATIC("); 
258             printPtr((StgPtr)stgCast(StgInd*,obj)->indirectee);
259             debugBelch(")\n"); 
260             break;
261
262     /* Cannot happen -- use default case.
263     case RET_BCO:
264     case RET_SMALL:
265     case RET_VEC_SMALL:
266     case RET_BIG:
267     case RET_VEC_BIG:
268     case RET_DYN:
269     case RET_FUN:
270     */
271
272     case UPDATE_FRAME:
273         {
274             StgUpdateFrame* u = stgCast(StgUpdateFrame*,obj);
275             debugBelch("UPDATE_FRAME(");
276             printPtr((StgPtr)GET_INFO(u));
277             debugBelch(",");
278             printPtr((StgPtr)u->updatee);
279             debugBelch(")\n"); 
280             break;
281         }
282
283     case CATCH_FRAME:
284         {
285             StgCatchFrame* u = stgCast(StgCatchFrame*,obj);
286             debugBelch("CATCH_FRAME(");
287             printPtr((StgPtr)GET_INFO(u));
288             debugBelch(",");
289             printPtr((StgPtr)u->handler);
290             debugBelch(")\n"); 
291             break;
292         }
293
294     case STOP_FRAME:
295         {
296             StgStopFrame* u = stgCast(StgStopFrame*,obj);
297             debugBelch("STOP_FRAME(");
298             printPtr((StgPtr)GET_INFO(u));
299             debugBelch(")\n"); 
300             break;
301         }
302
303     case CAF_BLACKHOLE:
304             debugBelch("CAF_BH"); 
305             break;
306
307     case BLACKHOLE:
308             debugBelch("BH\n"); 
309             break;
310
311     case SE_BLACKHOLE:
312             debugBelch("SE_BH\n"); 
313             break;
314
315     case SE_CAF_BLACKHOLE:
316             debugBelch("SE_CAF_BH\n"); 
317             break;
318
319     case ARR_WORDS:
320         {
321             StgWord i;
322             debugBelch("ARR_WORDS(\"");
323             /* ToDo: we can't safely assume that this is a string! 
324             for (i = 0; arrWordsGetChar(obj,i); ++i) {
325                 putchar(arrWordsGetChar(obj,i));
326                 } */
327             for (i=0; i<((StgArrWords *)obj)->words; i++)
328               debugBelch("%lu", (lnat)((StgArrWords *)obj)->payload[i]);
329             debugBelch("\")\n");
330             break;
331         }
332
333     case MUT_ARR_PTRS_CLEAN:
334         debugBelch("MUT_ARR_PTRS_CLEAN(size=%lu)\n", (lnat)((StgMutArrPtrs *)obj)->ptrs);
335         break;
336
337     case MUT_ARR_PTRS_DIRTY:
338         debugBelch("MUT_ARR_PTRS_DIRTY(size=%lu)\n", (lnat)((StgMutArrPtrs *)obj)->ptrs);
339         break;
340
341     case MUT_ARR_PTRS_FROZEN:
342         debugBelch("MUT_ARR_PTRS_FROZEN(size=%lu)\n", (lnat)((StgMutArrPtrs *)obj)->ptrs);
343         break;
344
345     case MVAR:
346         {
347           StgMVar* mv = (StgMVar*)obj;
348           debugBelch("MVAR(head=%p, tail=%p, value=%p)\n", mv->head, mv->tail, mv->value);
349           break;
350         }
351
352     case MUT_VAR_CLEAN:
353         {
354           StgMutVar* mv = (StgMutVar*)obj;
355           debugBelch("MUT_VAR_CLEAN(var=%p)\n", mv->var);
356           break;
357         }
358
359     case MUT_VAR_DIRTY:
360         {
361           StgMutVar* mv = (StgMutVar*)obj;
362           debugBelch("MUT_VAR_DIRTY(var=%p)\n", mv->var);
363           break;
364         }
365
366     case WEAK:
367             debugBelch("WEAK("); 
368             debugBelch(" key=%p value=%p finalizer=%p", 
369                     (StgPtr)(((StgWeak*)obj)->key),
370                     (StgPtr)(((StgWeak*)obj)->value),
371                     (StgPtr)(((StgWeak*)obj)->finalizer));
372             debugBelch(")\n"); 
373             /* ToDo: chase 'link' ? */
374             break;
375
376     case STABLE_NAME:
377             debugBelch("STABLE_NAME(%lu)\n", (lnat)((StgStableName*)obj)->sn); 
378             break;
379
380     case TSO:
381       debugBelch("TSO("); 
382       debugBelch("%lu (%p)",(unsigned long)(((StgTSO*)obj)->id), (StgTSO*)obj);
383       debugBelch(")\n"); 
384       break;
385
386 #if defined(PAR)
387     case BLOCKED_FETCH:
388       debugBelch("BLOCKED_FETCH("); 
389       printGA(&(stgCast(StgBlockedFetch*,obj)->ga));
390       printPtr((StgPtr)(stgCast(StgBlockedFetch*,obj)->node));
391       debugBelch(")\n"); 
392       break;
393
394     case FETCH_ME:
395       debugBelch("FETCH_ME("); 
396       printGA((globalAddr *)stgCast(StgFetchMe*,obj)->ga);
397       debugBelch(")\n"); 
398       break;
399
400     case FETCH_ME_BQ:
401       debugBelch("FETCH_ME_BQ("); 
402       // printGA((globalAddr *)stgCast(StgFetchMe*,obj)->ga);
403       printPtr((StgPtr)stgCast(StgFetchMeBlockingQueue*,obj)->blocking_queue);
404       debugBelch(")\n"); 
405       break;
406 #endif
407
408 #if defined(GRAN) || defined(PAR)
409     case RBH:
410       debugBelch("RBH("); 
411       printPtr((StgPtr)stgCast(StgRBH*,obj)->blocking_queue);
412       debugBelch(")\n"); 
413       break;
414
415 #endif
416
417 #if 0
418       /* Symptomatic of a problem elsewhere, have it fall-through & fail */
419     case EVACUATED:
420       debugBelch("EVACUATED("); 
421       printClosure((StgEvacuated*)obj->evacuee);
422       debugBelch(")\n"); 
423       break;
424 #endif
425
426 #if defined(PAR) && defined(DIST)
427     case REMOTE_REF:
428       debugBelch("REMOTE_REF("); 
429       printGA((globalAddr *)stgCast(StgFetchMe*,obj)->ga);
430       debugBelch(")\n"); 
431       break;
432 #endif
433
434     default:
435             //barf("printClosure %d",get_itbl(obj)->type);
436             debugBelch("*** printClosure: unknown type %d ****\n",
437                     get_itbl(obj)->type );
438             barf("printClosure %d",get_itbl(obj)->type);
439             return;
440     }
441 }
442
443 /*
444 void printGraph( StgClosure *obj )
445 {
446  printClosure(obj);
447 }
448 */
449
450 StgPtr
451 printStackObj( StgPtr sp )
452 {
453     /*debugBelch("Stack[%d] = ", &stgStack[STACK_SIZE] - sp); */
454
455         StgClosure* c = (StgClosure*)(*sp);
456         printPtr((StgPtr)*sp);
457         if (c == (StgClosure*)&stg_ctoi_R1p_info) {
458            debugBelch("\t\t\tstg_ctoi_ret_R1p_info\n" );
459         } else
460         if (c == (StgClosure*)&stg_ctoi_R1n_info) {
461            debugBelch("\t\t\tstg_ctoi_ret_R1n_info\n" );
462         } else
463         if (c == (StgClosure*)&stg_ctoi_F1_info) {
464            debugBelch("\t\t\tstg_ctoi_ret_F1_info\n" );
465         } else
466         if (c == (StgClosure*)&stg_ctoi_D1_info) {
467            debugBelch("\t\t\tstg_ctoi_ret_D1_info\n" );
468         } else
469         if (c == (StgClosure*)&stg_ctoi_V_info) {
470            debugBelch("\t\t\tstg_ctoi_ret_V_info\n" );
471         } else
472         if (get_itbl(c)->type == BCO) {
473            debugBelch("\t\t\t");
474            debugBelch("BCO(...)\n"); 
475         }
476         else {
477            debugBelch("\t\t\t");
478            printClosure ( (StgClosure*)(*sp));
479         }
480         sp += 1;
481
482     return sp;
483     
484 }
485
486 static void
487 printSmallBitmap( StgPtr spBottom, StgPtr payload, StgWord bitmap, nat size )
488 {
489     StgPtr p;
490     nat i;
491
492     p = payload;
493     for(i = 0; i < size; i++, bitmap >>= 1 ) {
494         debugBelch("   stk[%ld] (%p) = ", (long)(spBottom-(payload+i)), payload+i);
495         if ((bitmap & 1) == 0) {
496             printPtr((P_)payload[i]);
497             debugBelch("\n");
498         } else {
499             debugBelch("Word# %lu\n", (lnat)payload[i]);
500         }
501     }
502 }
503
504 static void
505 printLargeBitmap( StgPtr spBottom, StgPtr payload, StgLargeBitmap* large_bitmap, nat size )
506 {
507     StgWord bmp;
508     nat i, j;
509
510     i = 0;
511     for (bmp=0; i < size; bmp++) {
512         StgWord bitmap = large_bitmap->bitmap[bmp];
513         j = 0;
514         for(; i < size && j < BITS_IN(W_); j++, i++, bitmap >>= 1 ) {
515             debugBelch("   stk[%lu] (%p) = ", (lnat)(spBottom-(payload+i)), payload+i);
516             if ((bitmap & 1) == 0) {
517                 printPtr((P_)payload[i]);
518                 debugBelch("\n");
519             } else {
520                 debugBelch("Word# %lu\n", (lnat)payload[i]);
521             }
522         }
523     }
524 }
525
526 void
527 printStackChunk( StgPtr sp, StgPtr spBottom )
528 {
529     StgWord bitmap;
530     const StgInfoTable *info;
531
532     ASSERT(sp <= spBottom);
533     for (; sp < spBottom; sp += stack_frame_sizeW((StgClosure *)sp)) {
534
535         info = get_itbl((StgClosure *)sp);
536
537         switch (info->type) {
538             
539         case UPDATE_FRAME:
540         case CATCH_FRAME:
541             printObj((StgClosure*)sp);
542             continue;
543
544         case STOP_FRAME:
545             printObj((StgClosure*)sp);
546             return;
547
548         case RET_DYN:
549         { 
550             StgRetDyn* r;
551             StgPtr p;
552             StgWord dyn;
553             nat size;
554
555             r = (StgRetDyn *)sp;
556             dyn = r->liveness;
557             debugBelch("RET_DYN (%p)\n", r);
558
559             p = (P_)(r->payload);
560             printSmallBitmap(spBottom, sp,
561                              RET_DYN_LIVENESS(r->liveness), 
562                              RET_DYN_BITMAP_SIZE);
563             p += RET_DYN_BITMAP_SIZE + RET_DYN_NONPTR_REGS_SIZE;
564
565             for (size = RET_DYN_NONPTRS(dyn); size > 0; size--) {
566                 debugBelch("   stk[%ld] (%p) = ", (long)(spBottom-p), p);
567                 debugBelch("Word# %ld\n", (long)*p);
568                 p++;
569             }
570         
571             for (size = RET_DYN_PTRS(dyn); size > 0; size--) {
572                 debugBelch("   stk[%ld] (%p) = ", (long)(spBottom-p), p);
573                 printPtr(p);
574                 p++;
575             }
576             continue;
577         }
578
579         case RET_SMALL:
580         case RET_VEC_SMALL:
581             debugBelch("RET_SMALL (%p)\n", info);
582             bitmap = info->layout.bitmap;
583             printSmallBitmap(spBottom, sp+1, 
584                              BITMAP_BITS(bitmap), BITMAP_SIZE(bitmap));
585             continue;
586
587         case RET_BCO: {
588             StgBCO *bco;
589             
590             bco = ((StgBCO *)sp[1]);
591
592             debugBelch("RET_BCO (%p)\n", sp);
593             printLargeBitmap(spBottom, sp+2,
594                              BCO_BITMAP(bco), BCO_BITMAP_SIZE(bco));
595             continue;
596         }
597
598         case RET_BIG:
599         case RET_VEC_BIG:
600             barf("todo");
601
602         case RET_FUN:
603         {
604             StgFunInfoTable *fun_info;
605             StgRetFun *ret_fun;
606             nat size;
607
608             ret_fun = (StgRetFun *)sp;
609             fun_info = get_fun_itbl(ret_fun->fun);
610             size = ret_fun->size;
611             debugBelch("RET_FUN (%p) (type=%d)\n", ret_fun->fun, fun_info->f.fun_type);
612             switch (fun_info->f.fun_type) {
613             case ARG_GEN:
614                 printSmallBitmap(spBottom, sp+2,
615                                  BITMAP_BITS(fun_info->f.b.bitmap),
616                                  BITMAP_SIZE(fun_info->f.b.bitmap));
617                 break;
618             case ARG_GEN_BIG:
619                 printLargeBitmap(spBottom, sp+2,
620                                  GET_FUN_LARGE_BITMAP(fun_info),
621                                  GET_FUN_LARGE_BITMAP(fun_info)->size);
622                 break;
623             default:
624                 printSmallBitmap(spBottom, sp+2,
625                                  BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]),
626                                  BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]));
627                 break;
628             }
629             continue;
630         }
631            
632         default:
633             debugBelch("unknown object %d\n", info->type);
634             barf("printStackChunk");
635         }
636     }
637 }
638
639 void printTSO( StgTSO *tso )
640 {
641     printStackChunk( tso->sp, tso->stack+tso->stack_size);
642 }
643
644 /* -----------------------------------------------------------------------------
645    Closure types
646    
647    NOTE: must be kept in sync with the closure types in includes/ClosureTypes.h
648    -------------------------------------------------------------------------- */
649
650 static char *closure_type_names[] = {
651     "INVALID_OBJECT",
652     "CONSTR",
653     "CONSTR_1",
654     "CONSTR_0",
655     "CONSTR_2",
656     "CONSTR_1",
657     "CONSTR_0",
658     "CONSTR_STATIC",
659     "CONSTR_NOCAF_STATIC",
660     "FUN",
661     "FUN_1_0",
662     "FUN_0_1",
663     "FUN_2_0",
664     "FUN_1_1",
665     "FUN_0",
666     "FUN_STATIC",
667     "THUNK",
668     "THUNK_1_0",
669     "THUNK_0_1",
670     "THUNK_2_0",
671     "THUNK_1_1",
672     "THUNK_0",
673     "THUNK_STATIC",
674     "THUNK_SELECTOR",
675     "BCO",
676     "AP_UPD",
677     "PAP",
678     "AP_STACK",
679     "IND",
680     "IND_OLDGEN",
681     "IND_PERM",
682     "IND_OLDGEN_PERM",
683     "IND_STATIC",
684     "RET_BCO",
685     "RET_SMALL",
686     "RET_VEC_SMALL",
687     "RET_BIG",
688     "RET_VEC_BIG",
689     "RET_DYN",
690     "RET_FUN",
691     "UPDATE_FRAME",
692     "CATCH_FRAME",
693     "STOP_FRAME",
694     "CAF_BLACKHOLE",
695     "BLACKHOLE",
696     "BLACKHOLE_BQ",
697     "SE_BLACKHOLE",
698     "SE_CAF_BLACKHOLE",
699     "MVAR",
700     "ARR_WORDS",
701     "MUT_ARR_PTRS_CLEAN",
702     "MUT_ARR_PTRS_DIRTY",
703     "MUT_ARR_PTRS_FROZEN",
704     "MUT_VAR_CLEAN",
705     "MUT_VAR_DIRTY",
706     "MUT_CONS",
707     "WEAK",
708     "FOREIGN",
709     "STABLE_NAME",
710     "TSO",
711     "BLOCKED_FETCH",
712     "FETCH_ME",
713     "FETCH_ME_BQ",
714     "RBH",
715     "EVACUATED",
716     "REMOTE_REF",
717     "TVAR_WATCH_QUEUE",
718     "INVARIANT_CHECK_QUEUE",
719     "ATOMIC_INVARIANT",
720     "TVAR",
721     "TREC_CHUNK",
722     "TREC_HEADER",
723     "ATOMICALLY_FRAME",
724     "CATCH_RETRY_FRAME"
725 };
726
727
728 char *
729 info_type(StgClosure *closure){ 
730   return closure_type_names[get_itbl(closure)->type];
731 }
732
733 char *
734 info_type_by_ip(StgInfoTable *ip){ 
735   return closure_type_names[ip->type];
736 }
737
738 void
739 info_hdr_type(StgClosure *closure, char *res){ 
740   strcpy(res,closure_type_names[get_itbl(closure)->type]);
741 }
742
743 /* --------------------------------------------------------------------------
744  * Address printing code
745  *
746  * Uses symbol table in (unstripped executable)
747  * ------------------------------------------------------------------------*/
748
749 /* --------------------------------------------------------------------------
750  * Simple lookup table
751  *
752  * Current implementation is pretty dumb!
753  * ------------------------------------------------------------------------*/
754
755 struct entry {
756     StgWord value;
757     const char *name;
758 };
759
760 static nat table_size;
761 static struct entry* table;
762
763 #ifdef USING_LIBBFD
764 static nat max_table_size;
765
766 static void reset_table( int size )
767 {
768     max_table_size = size;
769     table_size = 0;
770     table = (struct entry *)stgMallocBytes(size * sizeof(struct entry), "Printer.c:reset_table()");
771 }
772
773 static void prepare_table( void )
774 {
775     /* Could sort it...  */
776 }
777
778 static void insert( StgWord value, const char *name )
779 {
780     if ( table_size >= max_table_size ) {
781         barf( "Symbol table overflow\n" );
782     }
783     table[table_size].value = value;
784     table[table_size].name = name;
785     table_size = table_size + 1;
786 }
787 #endif
788
789 #if 0
790 static rtsBool lookup_name( char *name, StgWord *result )
791 {
792     nat i;
793     for( i = 0; i < table_size && strcmp(name,table[i].name) != 0; ++i ) {
794     }
795     if (i < table_size) {
796         *result = table[i].value;
797         return rtsTrue;
798     } else {
799         return rtsFalse;
800     }
801 }
802 #endif
803
804 /* Code from somewhere inside GHC (circa 1994)
805  * * Z-escapes:
806  *     "std"++xs -> "Zstd"++xs
807  *     char_to_c 'Z'  = "ZZ"
808  *     char_to_c '&'  = "Za"
809  *     char_to_c '|'  = "Zb"
810  *     char_to_c ':'  = "Zc"
811  *     char_to_c '/'  = "Zd"
812  *     char_to_c '='  = "Ze"
813  *     char_to_c '>'  = "Zg"
814  *     char_to_c '#'  = "Zh"
815  *     char_to_c '<'  = "Zl"
816  *     char_to_c '-'  = "Zm"
817  *     char_to_c '!'  = "Zn"
818  *     char_to_c '.'  = "Zo"
819  *     char_to_c '+'  = "Zp"
820  *     char_to_c '\'' = "Zq"
821  *     char_to_c '*'  = "Zt"
822  *     char_to_c '_'  = "Zu"
823  *     char_to_c c    = "Z" ++ show (ord c)
824  */
825 static char unZcode( char ch )
826 {
827     switch (ch) {
828     case 'a'  : return ('&');
829     case 'b'  : return ('|');
830     case 'c'  : return (':');
831     case 'd'  : return ('/');
832     case 'e'  : return ('=');
833     case 'g'  : return ('>');
834     case 'h'  : return ('#');
835     case 'l'  : return ('<');
836     case 'm'  : return ('-');
837     case 'n'  : return ('!');
838     case 'o'  : return ('.');
839     case 'p'  : return ('+');
840     case 'q'  : return ('\'');
841     case 't'  : return ('*');
842     case 'u'  : return ('_');
843     case 'Z'  :
844     case '\0' : return ('Z');
845     default   : return (ch);
846     }
847 }
848
849 #if 0
850 /* Precondition: out big enough to handle output (about twice length of in) */
851 static void enZcode( char *in, char *out )
852 {
853     int i, j;
854
855     j = 0;
856     out[ j++ ] = '_';
857     for( i = 0; in[i] != '\0'; ++i ) {
858         switch (in[i]) {
859         case 'Z'  : 
860                 out[j++] = 'Z';
861                 out[j++] = 'Z';
862                 break;
863         case '&'  : 
864                 out[j++] = 'Z';
865                 out[j++] = 'a';
866                 break;
867         case '|'  : 
868                 out[j++] = 'Z';
869                 out[j++] = 'b';
870                 break;
871         case ':'  : 
872                 out[j++] = 'Z';
873                 out[j++] = 'c';
874                 break;
875         case '/'  : 
876                 out[j++] = 'Z';
877                 out[j++] = 'd';
878                 break;
879         case '='  : 
880                 out[j++] = 'Z';
881                 out[j++] = 'e';
882                 break;
883         case '>'  : 
884                 out[j++] = 'Z';
885                 out[j++] = 'g';
886                 break;
887         case '#'  : 
888                 out[j++] = 'Z';
889                 out[j++] = 'h';
890                 break;
891         case '<'  : 
892                 out[j++] = 'Z';
893                 out[j++] = 'l';
894                 break;
895         case '-'  : 
896                 out[j++] = 'Z';
897                 out[j++] = 'm';
898                 break;
899         case '!'  : 
900                 out[j++] = 'Z';
901                 out[j++] = 'n';
902                 break;
903         case '.'  : 
904                 out[j++] = 'Z';
905                 out[j++] = 'o';
906                 break;
907         case '+'  : 
908                 out[j++] = 'Z';
909                 out[j++] = 'p';
910                 break;
911         case '\'' : 
912                 out[j++] = 'Z';
913                 out[j++] = 'q';
914                 break;
915         case '*'  : 
916                 out[j++] = 'Z';
917                 out[j++] = 't';
918                 break;
919         case '_'  : 
920                 out[j++] = 'Z';
921                 out[j++] = 'u';
922                 break;
923         default :
924                 out[j++] = in[i];
925                 break;
926         }
927     }
928     out[j] = '\0';
929 }
930 #endif
931
932 const char *lookupGHCName( void *addr )
933 {
934     nat i;
935     for( i = 0; i < table_size && table[i].value != (StgWord) addr; ++i ) {
936     }
937     if (i < table_size) {
938         return table[i].name;
939     } else {
940         return NULL;
941     }
942 }
943
944 static void printZcoded( const char *raw )
945 {
946     nat j = 0;
947     
948     while ( raw[j] != '\0' ) {
949         if (raw[j] == 'Z') {
950             debugBelch("%c", unZcode(raw[j+1]));
951             j = j + 2;
952         } else {
953             debugBelch("%c", unZcode(raw[j+1]));
954             j = j + 1;
955         }
956     }
957 }
958
959 /* --------------------------------------------------------------------------
960  * Symbol table loading
961  * ------------------------------------------------------------------------*/
962
963 /* Causing linking trouble on Win32 plats, so I'm
964    disabling this for now. 
965 */
966 #ifdef USING_LIBBFD
967
968 #include <bfd.h>
969
970 /* Fairly ad-hoc piece of code that seems to filter out a lot of
971  * rubbish like the obj-splitting symbols
972  */
973
974 static rtsBool isReal( flagword flags STG_UNUSED, const char *name )
975 {
976 #if 0
977     /* ToDo: make this work on BFD */
978     int tp = type & N_TYPE;    
979     if (tp == N_TEXT || tp == N_DATA) {
980         return (name[0] == '_' && name[1] != '_');
981     } else {
982         return rtsFalse;
983     }
984 #else
985     if (*name == '\0'  || 
986         (name[0] == 'g' && name[1] == 'c' && name[2] == 'c') ||
987         (name[0] == 'c' && name[1] == 'c' && name[2] == '.')) {
988         return rtsFalse;
989     }
990     return rtsTrue;
991 #endif
992 }
993
994 extern void DEBUG_LoadSymbols( char *name )
995 {
996     bfd* abfd;
997     char **matching;
998
999     bfd_init();
1000     abfd = bfd_openr(name, "default");
1001     if (abfd == NULL) {
1002         barf("can't open executable %s to get symbol table", name);
1003     }
1004     if (!bfd_check_format_matches (abfd, bfd_object, &matching)) {
1005         barf("mismatch");
1006     }
1007
1008     {
1009         long storage_needed;
1010         asymbol **symbol_table;
1011         long number_of_symbols;
1012         long num_real_syms = 0;
1013         long i;
1014      
1015         storage_needed = bfd_get_symtab_upper_bound (abfd);
1016      
1017         if (storage_needed < 0) {
1018             barf("can't read symbol table");
1019         }     
1020 #if 0
1021         if (storage_needed == 0) {
1022             debugBelch("no storage needed");
1023         }
1024 #endif
1025         symbol_table = (asymbol **) stgMallocBytes(storage_needed,"DEBUG_LoadSymbols");
1026
1027         number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
1028      
1029         if (number_of_symbols < 0) {
1030             barf("can't canonicalise symbol table");
1031         }
1032
1033         for( i = 0; i != number_of_symbols; ++i ) {
1034             symbol_info info;
1035             bfd_get_symbol_info(abfd,symbol_table[i],&info);
1036             /*debugBelch("\t%c\t0x%x      \t%s\n",info.type,(nat)info.value,info.name); */
1037             if (isReal(info.type, info.name)) {
1038                 num_real_syms += 1;
1039             }
1040         }
1041     
1042         IF_DEBUG(interpreter,
1043                  debugBelch("Loaded %ld symbols. Of which %ld are real symbols\n", 
1044                          number_of_symbols, num_real_syms)
1045                  );
1046
1047         reset_table( num_real_syms );
1048     
1049         for( i = 0; i != number_of_symbols; ++i ) {
1050             symbol_info info;
1051             bfd_get_symbol_info(abfd,symbol_table[i],&info);
1052             if (isReal(info.type, info.name)) {
1053                 insert( info.value, info.name );
1054             }
1055         }
1056
1057         stgFree(symbol_table);
1058     }
1059     prepare_table();
1060 }
1061
1062 #else /* HAVE_BFD_H */
1063
1064 extern void DEBUG_LoadSymbols( char *name STG_UNUSED )
1065 {
1066   /* nothing, yet */
1067 }
1068
1069 #endif /* HAVE_BFD_H */
1070
1071 void findPtr(P_ p, int);                /* keep gcc -Wall happy */
1072
1073 void
1074 findPtr(P_ p, int follow)
1075 {
1076   nat s, g;
1077   P_ q, r;
1078   bdescr *bd;
1079 #if defined(__GNUC__)
1080   const int arr_size = 1024;
1081 #else
1082 #define arr_size 1024
1083 #endif
1084   StgPtr arr[arr_size];
1085   int i = 0;
1086
1087   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1088       for (s = 0; s < generations[g].n_steps; s++) {
1089           bd = generations[g].steps[s].blocks;
1090           for (; bd; bd = bd->link) {
1091               for (q = bd->start; q < bd->free; q++) {
1092                   if (*q == (W_)p) {
1093                       if (i < arr_size) {
1094                           r = q;
1095                           while (!LOOKS_LIKE_INFO_PTR(*r) || (P_)*r == NULL) {
1096                               r--;
1097                           }
1098                           debugBelch("%p = ", r);
1099                           printClosure((StgClosure *)r);
1100                           arr[i++] = r;
1101                       } else {
1102                           return;
1103                       }
1104                   }
1105               }
1106           }
1107       }
1108   }
1109   if (follow && i == 1) {
1110       debugBelch("-->\n");
1111       findPtr(arr[0], 1);
1112   }
1113 }
1114
1115 #else /* DEBUG */
1116 void printPtr( StgPtr p )
1117 {
1118     debugBelch("ptr 0x%p (enable -DDEBUG for more info) " , p );
1119 }
1120   
1121 void printObj( StgClosure *obj )
1122 {
1123     debugBelch("obj 0x%p (enable -DDEBUG for more info) " , obj );
1124 }
1125 #endif /* DEBUG */