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