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