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