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