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