[project @ 2004-02-12 02:04:59 by mthomas]
[ghc-hetmet.git] / ghc / rts / Printer.c
1 /* -----------------------------------------------------------------------------
2  * $Id: Printer.c,v 1.62 2003/11/12 17:49:08 sof 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 = FIXED_HS, 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)->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_ret_R1p_info) {
462            fprintf(stderr, "\t\t\tstg_ctoi_ret_R1p_info\n" );
463         } else
464         if (c == (StgClosure*)&stg_ctoi_ret_R1n_info) {
465            fprintf(stderr, "\t\t\tstg_ctoi_ret_R1n_info\n" );
466         } else
467         if (c == (StgClosure*)&stg_ctoi_ret_F1_info) {
468            fprintf(stderr, "\t\t\tstg_ctoi_ret_F1_info\n" );
469         } else
470         if (c == (StgClosure*)&stg_ctoi_ret_D1_info) {
471            fprintf(stderr, "\t\t\tstg_ctoi_ret_D1_info\n" );
472         } else
473         if (c == (StgClosure*)&stg_ctoi_ret_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                              GET_LIVENESS(r->liveness), RET_DYN_BITMAP_SIZE);
563             p += RET_DYN_BITMAP_SIZE + RET_DYN_NONPTR_REGS_SIZE;
564
565             for (size = GET_NONPTRS(dyn); size > 0; size--) {
566                 fprintf(stderr,"   stk[%ld] (%p) = ", (long)(spBottom-p), p);
567                 fprintf(stderr,"Word# %ld\n", (long)*p);
568                 p++;
569             }
570         
571             for (size = GET_PTRS(dyn); size > 0; size--) {
572                 fprintf(stderr,"   stk[%ld] (%p) = ", (long)(spBottom-p), p);
573                 printPtr(p);
574                 p++;
575             }
576             continue;
577         }
578
579         case RET_SMALL:
580         case RET_VEC_SMALL:
581             fprintf(stderr, "RET_SMALL (%p)\n", sp);
582             bitmap = info->layout.bitmap;
583             printSmallBitmap(spBottom, sp+1, 
584                              BITMAP_BITS(bitmap), BITMAP_SIZE(bitmap));
585             continue;
586
587         case RET_BCO: {
588             StgBCO *bco;
589             
590             bco = ((StgBCO *)sp[1]);
591
592             fprintf(stderr, "RET_BCO (%p)\n", sp);
593             printLargeBitmap(spBottom, sp+2,
594                              BCO_BITMAP(bco), BCO_BITMAP_SIZE(bco));
595             continue;
596         }
597
598         case RET_BIG:
599         case RET_VEC_BIG:
600             barf("todo");
601
602         case RET_FUN:
603         {
604             StgFunInfoTable *fun_info;
605             StgRetFun *ret_fun;
606             nat size;
607
608             ret_fun = (StgRetFun *)sp;
609             fun_info = get_fun_itbl(ret_fun->fun);
610             size = ret_fun->size;
611             fprintf(stderr,"RET_FUN (%p) (type=%d)\n", ret_fun, fun_info->fun_type);
612             switch (fun_info->fun_type) {
613             case ARG_GEN:
614                 printSmallBitmap(spBottom, sp+1,
615                                  BITMAP_BITS(fun_info->bitmap),
616                                  BITMAP_SIZE(fun_info->bitmap));
617                 break;
618             case ARG_GEN_BIG:
619                 printLargeBitmap(spBottom, sp+2,
620                                  (StgLargeBitmap *)fun_info->bitmap,
621                                  BITMAP_SIZE(fun_info->bitmap));
622                 break;
623             default:
624                 printSmallBitmap(spBottom, sp+1,
625                                  BITMAP_BITS(stg_arg_bitmaps[fun_info->fun_type]),
626                                  BITMAP_SIZE(stg_arg_bitmaps[fun_info->fun_type]));
627                 break;
628             }
629             continue;
630         }
631            
632         default:
633             fprintf(stderr, "unknown object %d\n", info->type);
634             barf("printStackChunk");
635         }
636     }
637 }
638
639 void printTSO( StgTSO *tso )
640 {
641     printStackChunk( tso->sp, tso->stack+tso->stack_size);
642 }
643
644 /* -----------------------------------------------------------------------------
645    Closure types
646    
647    NOTE: must be kept in sync with the closure types in includes/ClosureTypes.h
648    -------------------------------------------------------------------------- */
649
650 static char *closure_type_names[] = {
651     "INVALID_OBJECT",
652     "CONSTR",
653     "CONSTR_1",
654     "CONSTR_0",
655     "CONSTR_2",
656     "CONSTR_1",
657     "CONSTR_0",
658     "CONSTR_INTLIKE",
659     "CONSTR_CHARLIKE",
660     "CONSTR_STATIC",
661     "CONSTR_NOCAF_STATIC",
662     "FUN",
663     "FUN_1_0",
664     "FUN_0_1",
665     "FUN_2_0",
666     "FUN_1_1",
667     "FUN_0",
668     "FUN_STATIC",
669     "THUNK",
670     "THUNK_1_0",
671     "THUNK_0_1",
672     "THUNK_2_0",
673     "THUNK_1_1",
674     "THUNK_0",
675     "THUNK_STATIC",
676     "THUNK_SELECTOR",
677     "BCO",
678     "AP_UPD",
679     "PAP",
680     "AP_STACK",
681     "IND",
682     "IND_OLDGEN",
683     "IND_PERM",
684     "IND_OLDGEN_PERM",
685     "IND_STATIC",
686     "RET_BCO",
687     "RET_SMALL",
688     "RET_VEC_SMALL",
689     "RET_BIG",
690     "RET_VEC_BIG",
691     "RET_DYN",
692     "RET_FUN",
693     "UPDATE_FRAME",
694     "CATCH_FRAME",
695     "STOP_FRAME",
696     "CAF_BLACKHOLE",
697     "BLACKHOLE",
698     "BLACKHOLE_BQ",
699     "SE_BLACKHOLE",
700     "SE_CAF_BLACKHOLE",
701     "MVAR",
702     "ARR_WORDS",
703     "MUT_ARR_PTRS",
704     "MUT_ARR_PTRS_FROZEN",
705     "MUT_VAR",
706     "MUT_CONS",
707     "WEAK",
708     "FOREIGN",
709     "STABLE_NAME",
710     "TSO",
711     "BLOCKED_FETCH",
712     "FETCH_ME",
713     "FETCH_ME_BQ",
714     "RBH",
715     "EVACUATED",
716     "REMOTE_REF"
717 };
718
719
720 char *
721 info_type(StgClosure *closure){ 
722   return closure_type_names[get_itbl(closure)->type];
723 }
724
725 char *
726 info_type_by_ip(StgInfoTable *ip){ 
727   return closure_type_names[ip->type];
728 }
729
730 void
731 info_hdr_type(StgClosure *closure, char *res){ 
732   strcpy(res,closure_type_names[get_itbl(closure)->type]);
733 }
734
735 /* --------------------------------------------------------------------------
736  * Address printing code
737  *
738  * Uses symbol table in (unstripped executable)
739  * ------------------------------------------------------------------------*/
740
741 /* --------------------------------------------------------------------------
742  * Simple lookup table
743  *
744  * Current implementation is pretty dumb!
745  * ------------------------------------------------------------------------*/
746
747 struct entry {
748     nat value;
749     const char *name;
750 };
751
752 static nat table_size;
753 static struct entry* table;
754
755 #ifdef USING_LIBBFD
756 static nat max_table_size;
757
758 static void reset_table( int size )
759 {
760     max_table_size = size;
761     table_size = 0;
762     table = (struct entry *)stgMallocBytes(size * sizeof(struct entry), "Printer.c:reset_table()");
763 }
764
765 static void prepare_table( void )
766 {
767     /* Could sort it...  */
768 }
769
770 static void insert( unsigned value, const char *name )
771 {
772     if ( table_size >= max_table_size ) {
773         barf( "Symbol table overflow\n" );
774     }
775     table[table_size].value = value;
776     table[table_size].name = name;
777     table_size = table_size + 1;
778 }
779 #endif
780
781 #if 0
782 static rtsBool lookup_name( char *name, unsigned *result )
783 {
784     int i;
785     for( i = 0; i < table_size && strcmp(name,table[i].name) != 0; ++i ) {
786     }
787     if (i < table_size) {
788         *result = table[i].value;
789         return rtsTrue;
790     } else {
791         return rtsFalse;
792     }
793 }
794 #endif
795
796 /* Code from somewhere inside GHC (circa 1994)
797  * * Z-escapes:
798  *     "std"++xs -> "Zstd"++xs
799  *     char_to_c 'Z'  = "ZZ"
800  *     char_to_c '&'  = "Za"
801  *     char_to_c '|'  = "Zb"
802  *     char_to_c ':'  = "Zc"
803  *     char_to_c '/'  = "Zd"
804  *     char_to_c '='  = "Ze"
805  *     char_to_c '>'  = "Zg"
806  *     char_to_c '#'  = "Zh"
807  *     char_to_c '<'  = "Zl"
808  *     char_to_c '-'  = "Zm"
809  *     char_to_c '!'  = "Zn"
810  *     char_to_c '.'  = "Zo"
811  *     char_to_c '+'  = "Zp"
812  *     char_to_c '\'' = "Zq"
813  *     char_to_c '*'  = "Zt"
814  *     char_to_c '_'  = "Zu"
815  *     char_to_c c    = "Z" ++ show (ord c)
816  */
817 static char unZcode( char ch )
818 {
819     switch (ch) {
820     case 'a'  : return ('&');
821     case 'b'  : return ('|');
822     case 'c'  : return (':');
823     case 'd'  : return ('/');
824     case 'e'  : return ('=');
825     case 'g'  : return ('>');
826     case 'h'  : return ('#');
827     case 'l'  : return ('<');
828     case 'm'  : return ('-');
829     case 'n'  : return ('!');
830     case 'o'  : return ('.');
831     case 'p'  : return ('+');
832     case 'q'  : return ('\'');
833     case 't'  : return ('*');
834     case 'u'  : return ('_');
835     case 'Z'  :
836     case '\0' : return ('Z');
837     default   : return (ch);
838     }
839 }
840
841 #if 0
842 /* Precondition: out big enough to handle output (about twice length of in) */
843 static void enZcode( char *in, char *out )
844 {
845     int i, j;
846
847     j = 0;
848     out[ j++ ] = '_';
849     for( i = 0; in[i] != '\0'; ++i ) {
850         switch (in[i]) {
851         case 'Z'  : 
852                 out[j++] = 'Z';
853                 out[j++] = 'Z';
854                 break;
855         case '&'  : 
856                 out[j++] = 'Z';
857                 out[j++] = 'a';
858                 break;
859         case '|'  : 
860                 out[j++] = 'Z';
861                 out[j++] = 'b';
862                 break;
863         case ':'  : 
864                 out[j++] = 'Z';
865                 out[j++] = 'c';
866                 break;
867         case '/'  : 
868                 out[j++] = 'Z';
869                 out[j++] = 'd';
870                 break;
871         case '='  : 
872                 out[j++] = 'Z';
873                 out[j++] = 'e';
874                 break;
875         case '>'  : 
876                 out[j++] = 'Z';
877                 out[j++] = 'g';
878                 break;
879         case '#'  : 
880                 out[j++] = 'Z';
881                 out[j++] = 'h';
882                 break;
883         case '<'  : 
884                 out[j++] = 'Z';
885                 out[j++] = 'l';
886                 break;
887         case '-'  : 
888                 out[j++] = 'Z';
889                 out[j++] = 'm';
890                 break;
891         case '!'  : 
892                 out[j++] = 'Z';
893                 out[j++] = 'n';
894                 break;
895         case '.'  : 
896                 out[j++] = 'Z';
897                 out[j++] = 'o';
898                 break;
899         case '+'  : 
900                 out[j++] = 'Z';
901                 out[j++] = 'p';
902                 break;
903         case '\'' : 
904                 out[j++] = 'Z';
905                 out[j++] = 'q';
906                 break;
907         case '*'  : 
908                 out[j++] = 'Z';
909                 out[j++] = 't';
910                 break;
911         case '_'  : 
912                 out[j++] = 'Z';
913                 out[j++] = 'u';
914                 break;
915         default :
916                 out[j++] = in[i];
917                 break;
918         }
919     }
920     out[j] = '\0';
921 }
922 #endif
923
924 const char *lookupGHCName( void *addr )
925 {
926     nat i;
927     for( i = 0; i < table_size && table[i].value != (unsigned) addr; ++i ) {
928     }
929     if (i < table_size) {
930         return table[i].name;
931     } else {
932         return NULL;
933     }
934 }
935
936 static void printZcoded( const char *raw )
937 {
938     nat j = 0;
939     
940     while ( raw[j] != '\0' ) {
941         if (raw[j] == 'Z') {
942             fputc(unZcode(raw[j+1]),stderr);
943             j = j + 2;
944         } else {
945             fputc(raw[j],stderr);
946             j = j + 1;
947         }
948     }
949 }
950
951 /* --------------------------------------------------------------------------
952  * Symbol table loading
953  * ------------------------------------------------------------------------*/
954
955 /* Causing linking trouble on Win32 plats, so I'm
956    disabling this for now. 
957 */
958 #ifdef USING_LIBBFD
959
960 #include <bfd.h>
961
962 /* Fairly ad-hoc piece of code that seems to filter out a lot of
963  * rubbish like the obj-splitting symbols
964  */
965
966 static rtsBool isReal( flagword flags STG_UNUSED, const char *name )
967 {
968 #if 0
969     /* ToDo: make this work on BFD */
970     int tp = type & N_TYPE;    
971     if (tp == N_TEXT || tp == N_DATA) {
972         return (name[0] == '_' && name[1] != '_');
973     } else {
974         return rtsFalse;
975     }
976 #else
977     if (*name == '\0'  || 
978         (name[0] == 'g' && name[1] == 'c' && name[2] == 'c') ||
979         (name[0] == 'c' && name[1] == 'c' && name[2] == '.')) {
980         return rtsFalse;
981     }
982     return rtsTrue;
983 #endif
984 }
985
986 extern void DEBUG_LoadSymbols( char *name )
987 {
988     bfd* abfd;
989     char **matching;
990
991     bfd_init();
992     abfd = bfd_openr(name, "default");
993     if (abfd == NULL) {
994         barf("can't open executable %s to get symbol table", name);
995     }
996     if (!bfd_check_format_matches (abfd, bfd_object, &matching)) {
997         barf("mismatch");
998     }
999
1000     {
1001         long storage_needed;
1002         asymbol **symbol_table;
1003         long number_of_symbols;
1004         long num_real_syms = 0;
1005         long i;
1006      
1007         storage_needed = bfd_get_symtab_upper_bound (abfd);
1008      
1009         if (storage_needed < 0) {
1010             barf("can't read symbol table");
1011         }     
1012 #if 0
1013         if (storage_needed == 0) {
1014             belch("no storage needed");
1015         }
1016 #endif
1017         symbol_table = (asymbol **) stgMallocBytes(storage_needed,"DEBUG_LoadSymbols");
1018
1019         number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
1020      
1021         if (number_of_symbols < 0) {
1022             barf("can't canonicalise symbol table");
1023         }
1024
1025         for( i = 0; i != number_of_symbols; ++i ) {
1026             symbol_info info;
1027             bfd_get_symbol_info(abfd,symbol_table[i],&info);
1028             /*fprintf(stderr,"\t%c\t0x%x      \t%s\n",info.type,(nat)info.value,info.name); */
1029             if (isReal(info.type, info.name)) {
1030                 num_real_syms += 1;
1031             }
1032         }
1033     
1034         IF_DEBUG(interpreter,
1035                  fprintf(stderr,"Loaded %ld symbols. Of which %ld are real symbols\n", 
1036                          number_of_symbols, num_real_syms)
1037                  );
1038
1039         reset_table( num_real_syms );
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             if (isReal(info.type, info.name)) {
1045                 insert( info.value, info.name );
1046             }
1047         }
1048
1049         stgFree(symbol_table);
1050     }
1051     prepare_table();
1052 }
1053
1054 #else /* HAVE_BFD_H */
1055
1056 extern void DEBUG_LoadSymbols( char *name STG_UNUSED )
1057 {
1058   /* nothing, yet */
1059 }
1060
1061 #endif /* HAVE_BFD_H */
1062
1063 #include "StoragePriv.h"
1064
1065 void findPtr(P_ p, int);                /* keep gcc -Wall happy */
1066
1067 void
1068 findPtr(P_ p, int follow)
1069 {
1070   nat s, g;
1071   P_ q, r;
1072   bdescr *bd;
1073 #if defined(__GNUC__)
1074   const int arr_size = 1024;
1075 #else
1076 #define arr_size 1024
1077 #endif
1078   StgPtr arr[arr_size];
1079   int i = 0;
1080
1081   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
1082       for (s = 0; s < generations[g].n_steps; s++) {
1083           if (RtsFlags.GcFlags.generations == 1) {
1084               bd = generations[g].steps[s].to_blocks;
1085           } else {
1086               bd = generations[g].steps[s].blocks;
1087           }
1088           for (; bd; bd = bd->link) {
1089               for (q = bd->start; q < bd->free; q++) {
1090                   if (*q == (W_)p) {
1091                       if (i < arr_size) {
1092                           r = q;
1093                           while (!LOOKS_LIKE_INFO_PTR(*r) || (P_)*r == NULL) {
1094                               r--;
1095                           }
1096                           fprintf(stderr, "%p = ", r);
1097                           printClosure((StgClosure *)r);
1098                           arr[i++] = r;
1099                       } else {
1100                           return;
1101                       }
1102                   }
1103               }
1104           }
1105       }
1106   }
1107   if (follow && i == 1) {
1108       fprintf(stderr, "-->\n");
1109       findPtr(arr[0], 1);
1110   }
1111 }
1112
1113 #else /* DEBUG */
1114 void printPtr( StgPtr p )
1115 {
1116     fprintf(stderr, "ptr 0x%p (enable -DDEBUG for more info) " , p );
1117 }
1118   
1119 void printObj( StgClosure *obj )
1120 {
1121     fprintf(stderr, "obj 0x%p (enable -DDEBUG for more info) " , obj );
1122 }
1123 #endif /* DEBUG */