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