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