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