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