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