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