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