[project @ 2000-12-12 12:19:57 by simonmar]
[ghc-hetmet.git] / ghc / rts / Linker.c
1 /* -----------------------------------------------------------------------------
2  * $Id: Linker.c,v 1.3 2000/12/12 12:19:57 simonmar Exp $
3  *
4  * (c) The GHC Team, 2000
5  *
6  * RTS Object Linker
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #include "Rts.h"
11 #include "RtsFlags.h"
12 #include "HsFFI.h"
13 #include "Hash.h"
14 #include "Linker.h"
15 #include "RtsUtils.h"
16
17 /* These two are POSIX headers */
18 #include <sys/types.h>
19 #include <sys/stat.h>
20
21 /* ToDo: configure this */
22 #include <dlfcn.h>
23
24 /* A bucket in the symbol hash-table.  Primarily, maps symbol names to
25  * absolute addresses.  All symbols from a given module are linked
26  * together, so they can be freed at the same time.  There's also a
27  * bucket link field for the hash table.
28  */
29 typedef struct _SymbolVal {
30     char   *lbl;
31     void   *addr;
32 } SymbolVal;
33
34 typedef enum { OBJECT_LOADED, OBJECT_RESOLVED } OStatus;
35
36 /* Indication of section kinds for loaded objects.  Needed by
37    the GC for deciding whether or not a pointer on the stack
38    is a code pointer.
39 */
40 typedef enum { SECTIONKIND_CODE_OR_RODATA,
41                SECTIONKIND_RWDATA,
42                SECTIONKIND_OTHER,
43                SECTIONKIND_NOINFOAVAIL } 
44    SectionKind;
45
46 typedef struct { void* start; void* end; SectionKind kind; } 
47    Section;
48
49 /* Top-level structure for an object module.  One of these is allocated
50  * for each object file in use.
51  */
52 typedef struct _ObjectCode {
53     OStatus   status;
54     char*     fileName;
55     int       fileSize;
56     char*     formatName;            /* eg "ELF32", "DLL", "COFF", etc. */
57
58     SymbolVal *symbols;
59     int       n_symbols;
60
61     /* ptr to malloc'd lump of memory holding the obj file */
62     void*     image;
63
64     /* The section-kind entries for this object module.  Dynamically expands. */
65     Section*  sections;
66     int       n_sections;
67     
68     /* Allow a chain of these things */
69     struct _ObjectCode * next;
70 } ObjectCode;
71
72
73 /* Hash table mapping symbol names to Symbol */
74 /*Str*/HashTable *symhash;
75
76 /* List of currently loaded objects */
77 ObjectCode *objects;
78
79 #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
80 static int ocVerifyImage_ELF    ( ObjectCode* oc );
81 static int ocGetNames_ELF       ( ObjectCode* oc );
82 static int ocResolve_ELF        ( ObjectCode* oc );
83 #elif defined(cygwin32_TARGET_OS)               
84 static int ocVerifyImage_PEi386 ( ObjectCode* oc );
85 static int ocGetNames_PEi386    ( ObjectCode* oc );
86 static int ocResolve_PEi386     ( ObjectCode* oc );
87 #endif
88
89 /* -----------------------------------------------------------------------------
90  * Built-in symbols from the RTS
91  */
92
93 #define RTS_SYMBOLS                             \
94       SymX(MainRegTable)                        \
95       Sym(stg_gc_enter_1)                       \
96       Sym(stg_gc_noregs)                        \
97       Sym(stg_gc_seq_1)                         \
98       Sym(stg_gc_d1)                            \
99       Sym(stg_gc_f1)                            \
100       Sym(stg_gc_ut_1_0)                        \
101       Sym(stg_gc_ut_0_1)                        \
102       Sym(stg_gc_unbx_r1)                       \
103       Sym(stg_chk_0)                            \
104       Sym(stg_chk_1)                            \
105       Sym(stg_gen_chk)                          \
106       SymX(stg_exit)                            \
107       SymX(stg_update_PAP)                      \
108       SymX(stg_ap_2_upd_info)                   \
109       SymX(stg_ap_3_upd_info)                   \
110       SymX(stg_ap_4_upd_info)                   \
111       SymX(stg_ap_5_upd_info)                   \
112       SymX(stg_ap_6_upd_info)                   \
113       SymX(stg_ap_7_upd_info)                   \
114       SymX(stg_ap_8_upd_info)                   \
115       SymX(stg_sel_0_upd_info)                  \
116       SymX(stg_sel_1_upd_info)                  \
117       SymX(stg_sel_2_upd_info)                  \
118       SymX(stg_sel_3_upd_info)                  \
119       SymX(stg_sel_4_upd_info)                  \
120       SymX(stg_sel_5_upd_info)                  \
121       SymX(stg_sel_6_upd_info)                  \
122       SymX(stg_sel_7_upd_info)                  \
123       SymX(stg_sel_8_upd_info)                  \
124       SymX(stg_sel_9_upd_info)                  \
125       SymX(stg_sel_10_upd_info)                 \
126       SymX(stg_sel_11_upd_info)                 \
127       SymX(stg_sel_12_upd_info)                 \
128       SymX(stg_upd_frame_info)                  \
129       SymX(stg_seq_frame_info)                  \
130       SymX(stg_CAF_BLACKHOLE_info)              \
131       SymX(stg_IND_STATIC_info)                 \
132       SymX(stg_EMPTY_MVAR_info)                 \
133       SymX(stg_MUT_ARR_PTRS_FROZEN_info)        \
134       SymX(stg_CHARLIKE_closure)                \
135       SymX(stg_INTLIKE_closure)                 \
136       SymX(stg_CAF_UNENTERED_entry)             \
137       SymX(newCAF)                              \
138       SymX(putMVarzh_fast)                      \
139       SymX(newMVarzh_fast)                      \
140       SymX(takeMVarzh_fast)                     \
141       SymX(tryTakeMVarzh_fast)                  \
142       SymX(catchzh_fast)                        \
143       SymX(raisezh_fast)                        \
144       SymX(delayzh_fast)                        \
145       SymX(yieldzh_fast)                        \
146       SymX(killThreadzh_fast)                   \
147       SymX(waitReadzh_fast)                     \
148       SymX(waitWritezh_fast)                    \
149       SymX(suspendThread)                       \
150       SymX(resumeThread)                        \
151       SymX(stackOverflow)                       \
152       SymX(int2Integerzh_fast)                  \
153       SymX(ErrorHdrHook)                        \
154       SymX(mkForeignObjzh_fast)                 \
155       SymX(__encodeDouble)                      \
156       SymX(decodeDoublezh_fast)                 \
157       SymX(isDoubleNaN)                         \
158       SymX(isDoubleInfinite)                    \
159       SymX(isDoubleDenormalized)                \
160       SymX(isDoubleNegativeZero)                \
161       SymX(__encodeFloat)                       \
162       SymX(decodeFloatzh_fast)                  \
163       SymX(isFloatNaN)                          \
164       SymX(isFloatInfinite)                     \
165       SymX(isFloatDenormalized)                 \
166       SymX(isFloatNegativeZero)                 \
167       SymX(__int_encodeFloat)                   \
168       SymX(__int_encodeDouble)                  \
169       SymX(__gmpz_cmp_si)                       \
170       SymX(__gmpz_cmp)                          \
171       SymX(__gmpn_gcd_1)                        \
172       SymX(gcdIntegerzh_fast)                   \
173       SymX(newArrayzh_fast)                     \
174       SymX(unsafeThawArrayzh_fast)              \
175       SymX(newByteArrayzh_fast)                 \
176       SymX(newMutVarzh_fast)                    \
177       SymX(quotRemIntegerzh_fast)               \
178       SymX(quotIntegerzh_fast)                  \
179       SymX(remIntegerzh_fast)                   \
180       SymX(divExactIntegerzh_fast)              \
181       SymX(divModIntegerzh_fast)                \
182       SymX(timesIntegerzh_fast)                 \
183       SymX(minusIntegerzh_fast)                 \
184       SymX(plusIntegerzh_fast)                  \
185       SymX(mkWeakzh_fast)                       \
186       SymX(prog_argv)                           \
187       SymX(prog_argc)                           \
188       SymX(resetNonBlockingFd)                  \
189       SymX(getStablePtr)                        \
190       SymX(stable_ptr_table)                    \
191       SymX(shutdownHaskellAndExit)              \
192       Sym(stg_enterStackTop)                    \
193       Sym(stg_yield_to_Hugs)                    \
194       Sym(StgReturn)                            \
195       Sym(init_stack)                           \
196       SymX(blockAsyncExceptionszh_fast)         \
197       SymX(unblockAsyncExceptionszh_fast)       \
198       Sym(__init_PrelGHC)
199
200 /* entirely bogus claims about types of these symbols */
201 #define Sym(vvv)  extern void (vvv);
202 #define SymX(vvv) /**/
203 RTS_SYMBOLS
204 #undef Sym
205 #undef SymX
206
207 #ifdef LEADING_UNDERSCORE
208 #define MAYBE_LEADING_UNDERSCORE_STR(s) ("_" s)
209 #else
210 #define MAYBE_LEADING_UNDERSCORE_STR(s) (s)
211 #endif
212
213 #define Sym(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
214                     (void*)(&(vvv)) },
215 #define SymX(vvv) Sym(vvv)
216
217 static SymbolVal rtsSyms[] = {
218       RTS_SYMBOLS
219       { 0, 0 } /* sentinel */
220 };
221
222 /* -----------------------------------------------------------------------------
223  * initialize the object linker
224  */
225 static void *dl_prog_handle;
226
227 void
228 initLinker( void )
229 {
230     SymbolVal *sym;
231
232     symhash = allocStrHashTable();
233
234     /* populate the symbol table with stuff from the RTS */
235     for (sym = rtsSyms; sym->lbl != NULL; sym++) {
236         insertStrHashTable(symhash, sym->lbl, sym);
237     }
238
239     dl_prog_handle = dlopen(NULL, RTLD_LAZY);
240 }
241
242 /* -----------------------------------------------------------------------------
243  * lookup a symbol in the hash table
244  */  
245 void *
246 lookupSymbol( char *lbl )
247 {
248     SymbolVal *val;
249     val = lookupStrHashTable(symhash, lbl);
250
251     if (val == NULL) {
252         return dlsym(dl_prog_handle, lbl);
253     } else {
254         return val->addr;
255     }
256 }
257
258 /* -----------------------------------------------------------------------------
259  * Load an obj (populate the global symbol table, but don't resolve yet)
260  *
261  * Returns: 1 if ok, 0 on error.
262  */
263 HsInt
264 loadObj( char *path )
265 {
266    ObjectCode* oc;
267    struct stat st;
268    int r, n;
269    FILE *f;
270
271 #ifdef DEBUG
272    /* assert that we haven't already loaded this object */
273    { 
274        ObjectCode *o;
275        for (o = objects; o; o = o->next)
276            ASSERT(strcmp(o->fileName, path));
277    }
278 #endif /* DEBUG */   
279
280    oc = stgMallocBytes(sizeof(ObjectCode), "loadObj(oc)");
281
282 #  if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
283    oc->formatName = "ELF";
284 #  elif defined(cygwin32_TARGET_OS)
285    oc->formatName = "PEi386";
286 #  else
287    free(oc);
288    barf("loadObj: not implemented on this platform");
289 #  endif
290
291    r = stat(path, &st);
292    if (r == -1) { return 0; }
293
294    oc->fileName          = path;
295    oc->fileSize          = st.st_size;
296    oc->image             = stgMallocBytes( st.st_size, "loadObj(image)" );
297    oc->symbols           = NULL;
298    oc->sections          = NULL;
299
300    /* chain it onto the list of objects */
301    oc->next              = objects;
302    objects               = oc;
303
304    /* load the image into memory */
305    f = fopen(path, "rb");
306    if (!f) {
307        barf("loadObj: can't read `%s'", path);
308    }
309    n = fread ( oc->image, 1, oc->fileSize, f );
310    if (n != oc->fileSize) {
311       fclose(f);
312       barf("loadObj: error whilst reading `%s'", path);
313    }
314
315    /* verify the in-memory image */
316 #  if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
317    r = ocVerifyImage_ELF ( oc );
318 #  elif defined(cygwin32_TARGET_OS)
319    r = ocVerifyImage_PEi386 ( oc );
320 #  else
321    barf("loadObj: no verify method");
322 #  endif
323    if (!r) { return r; }
324
325    /* build the symbol list for this image */
326 #  if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
327    r = ocGetNames_ELF ( oc );
328 #  elif defined(cygwin32_TARGET_OS)
329    r = ocGetNames_PEi386 ( oc );
330 #  else
331    barf("loadObj: no getNames method");
332 #  endif
333    if (!r) { return r; }
334
335    /* loaded, but not resolved yet */
336    oc->status = OBJECT_LOADED;
337
338    return 1;
339 }
340
341 /* -----------------------------------------------------------------------------
342  * resolve all the currently unlinked objects in memory
343  *
344  * Returns: 1 if ok, 0 on error.
345  */
346 HsInt 
347 resolveObjs( void )
348 {
349     ObjectCode *oc;
350     int r;
351
352     for (oc = objects; oc; oc = oc->next) {
353         if (oc->status != OBJECT_RESOLVED) {
354 #  if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
355             r = ocResolve_ELF ( oc );
356 #  elif defined(cygwin32_TARGET_OS)
357             r = ocResolve_PEi386 ( oc );
358 #  else
359             barf("link: not implemented on this platform");
360 #  endif
361             if (!r) { return r; }
362             oc->status = OBJECT_RESOLVED;
363         }
364     }
365     return 1;
366 }
367
368 /* -----------------------------------------------------------------------------
369  * delete an object from the pool
370  */
371 HsInt
372 unloadObj( char *path )
373 {
374     ObjectCode *oc;
375
376     for (oc = objects; oc; oc = oc->next) {
377         if (!strcmp(oc->fileName,path)) {
378
379             /* Remove all the mappings for the symbols within this
380              * object..
381              */
382             { 
383                 SymbolVal *s;
384                 for (s = oc->symbols; s < oc->symbols + oc->n_symbols; s++) {
385                     removeStrHashTable(symhash, s->lbl, NULL);
386                 }
387             }
388
389             /* We're going to leave this in place, in case there are
390                any pointers from the heap into it: */
391             /* free(oc->image); */
392             free(oc->symbols);
393             free(oc->sections);
394             free(oc);
395             return 1;
396         }
397     }
398     
399     belch("unloadObj: can't find `%s' to unload", path);
400     return 0;
401 }
402
403 /* --------------------------------------------------------------------------
404  * PEi386 specifics (cygwin32)
405  * ------------------------------------------------------------------------*/
406
407 /* The information for this linker comes from 
408       Microsoft Portable Executable 
409       and Common Object File Format Specification
410       revision 5.1 January 1998
411    which SimonM says comes from the MS Developer Network CDs.
412 */
413       
414
415 #if defined(cygwin32_TARGET_OS)
416
417
418
419 typedef unsigned char  UChar;
420 typedef unsigned short UInt16;
421 typedef unsigned int   UInt32;
422 typedef          int   Int32;
423
424
425 typedef 
426    struct {
427       UInt16 Machine;
428       UInt16 NumberOfSections;
429       UInt32 TimeDateStamp;
430       UInt32 PointerToSymbolTable;
431       UInt32 NumberOfSymbols;
432       UInt16 SizeOfOptionalHeader;
433       UInt16 Characteristics;
434    }
435    COFF_header;
436
437 #define sizeof_COFF_header 20
438
439
440 typedef 
441    struct {
442       UChar  Name[8];
443       UInt32 VirtualSize;
444       UInt32 VirtualAddress;
445       UInt32 SizeOfRawData;
446       UInt32 PointerToRawData;
447       UInt32 PointerToRelocations;
448       UInt32 PointerToLinenumbers;
449       UInt16 NumberOfRelocations;
450       UInt16 NumberOfLineNumbers;
451       UInt32 Characteristics; 
452    }
453    COFF_section;
454
455 #define sizeof_COFF_section 40
456
457
458 typedef
459    struct {
460       UChar  Name[8];
461       UInt32 Value;
462       UInt16 SectionNumber;
463       UInt16 Type;
464       UChar  StorageClass;
465       UChar  NumberOfAuxSymbols;
466    }
467    COFF_symbol;
468
469 #define sizeof_COFF_symbol 18
470
471
472 typedef
473    struct {
474       UInt32 VirtualAddress;
475       UInt32 SymbolTableIndex;
476       UInt16 Type;
477    }
478    COFF_reloc;
479
480 #define sizeof_COFF_reloc 10
481
482
483 /* From PE spec doc, section 3.3.2 */
484 #define IMAGE_FILE_RELOCS_STRIPPED     0x0001
485 #define IMAGE_FILE_EXECUTABLE_IMAGE    0x0002
486 #define IMAGE_FILE_DLL                 0x2000
487 #define IMAGE_FILE_SYSTEM              0x1000
488 #define IMAGE_FILE_BYTES_REVERSED_HI   0x8000
489 #define IMAGE_FILE_BYTES_REVERSED_LO   0x0080
490 #define IMAGE_FILE_32BIT_MACHINE       0x0100
491
492 /* From PE spec doc, section 5.4.2 and 5.4.4 */
493 #define IMAGE_SYM_CLASS_EXTERNAL       2
494 #define IMAGE_SYM_CLASS_STATIC         3
495 #define IMAGE_SYM_UNDEFINED            0
496
497 /* From PE spec doc, section 4.1 */
498 #define IMAGE_SCN_CNT_CODE             0x00000020
499 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
500
501 /* From PE spec doc, section 5.2.1 */
502 #define IMAGE_REL_I386_DIR32           0x0006
503 #define IMAGE_REL_I386_REL32           0x0014
504
505
506 /* We use myindex to calculate array addresses, rather than
507    simply doing the normal subscript thing.  That's because
508    some of the above structs have sizes which are not 
509    a whole number of words.  GCC rounds their sizes up to a
510    whole number of words, which means that the address calcs
511    arising from using normal C indexing or pointer arithmetic
512    are just plain wrong.  Sigh.
513 */
514 static UChar *
515 myindex ( int scale, int index, void* base )
516 {
517    return
518       ((UChar*)base) + scale * index;
519 }
520
521
522 static void
523 printName ( UChar* name, UChar* strtab )
524 {
525    if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
526       UInt32 strtab_offset = * (UInt32*)(name+4);
527       fprintf ( stderr, "%s", strtab + strtab_offset );
528    } else {
529       int i;
530       for (i = 0; i < 8; i++) {
531          if (name[i] == 0) break;
532          fprintf ( stderr, "%c", name[i] );
533       }
534    }
535 }
536
537
538 static void
539 copyName ( UChar* name, UChar* strtab, UChar* dst, int dstSize )
540 {
541    if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
542       UInt32 strtab_offset = * (UInt32*)(name+4);
543       strncpy ( dst, strtab+strtab_offset, dstSize );
544       dst[dstSize-1] = 0;
545    } else {
546       int i = 0;
547       while (1) {
548          if (i >= 8) break;
549          if (name[i] == 0) break;
550          dst[i] = name[i];
551          i++;
552       }
553       dst[i] = 0;
554    }
555 }
556
557
558 static UChar *
559 cstring_from_COFF_symbol_name ( UChar* name, UChar* strtab )
560 {
561    UChar* newstr;
562    /* If the string is longer than 8 bytes, look in the
563       string table for it -- this will be correctly zero terminated. 
564    */
565    if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
566       UInt32 strtab_offset = * (UInt32*)(name+4);
567       return ((UChar*)strtab) + strtab_offset;
568    }
569    /* Otherwise, if shorter than 8 bytes, return the original,
570       which by defn is correctly terminated.
571    */
572    if (name[7]==0) return name;
573    /* The annoying case: 8 bytes.  Copy into a temporary
574       (which is never freed ...)
575    */
576    newstr = malloc(9);
577    if (newstr) {
578       strncpy(newstr,name,8);
579       newstr[8] = 0;
580    }
581    return newstr;
582 }
583
584
585 /* Just compares the short names (first 8 chars) */
586 static COFF_section *
587 findPEi386SectionCalled ( ObjectCode* oc,  char* name )
588 {
589    int i;
590    COFF_header* hdr 
591       = (COFF_header*)(oc->image);
592    COFF_section* sectab 
593       = (COFF_section*) (
594            ((UChar*)(oc->image)) 
595            + sizeof_COFF_header + hdr->SizeOfOptionalHeader
596         );
597    for (i = 0; i < hdr->NumberOfSections; i++) {
598       UChar* n1;
599       UChar* n2;
600       COFF_section* section_i 
601          = (COFF_section*)
602            myindex ( sizeof_COFF_section, i, sectab );
603       n1 = (UChar*) &(section_i->Name);
604       n2 = name;
605       if (n1[0]==n2[0] && n1[1]==n2[1] && n1[2]==n2[2] && 
606           n1[3]==n2[3] && n1[4]==n2[4] && n1[5]==n2[5] && 
607           n1[6]==n2[6] && n1[7]==n2[7])
608          return section_i;
609    }
610
611    return NULL;
612 }
613
614
615 static void
616 zapTrailingAtSign ( UChar* sym )
617 {
618    int i, j;
619    if (sym[0] == 0) return;
620    i = 0; 
621    while (sym[i] != 0) i++;
622    i--;
623    j = i;
624    while (j > 0 && isdigit(sym[j])) j--;
625    if (j > 0 && sym[j] == '@' && j != i) sym[j] = 0;
626 }
627
628
629 static int
630 ocVerifyImage_PEi386 ( ObjectCode* oc )
631 {
632    int i, j;
633    COFF_header*  hdr;
634    COFF_section* sectab;
635    COFF_symbol*  symtab;
636    UChar*        strtab;
637
638    hdr = (COFF_header*)(oc->image);
639    sectab = (COFF_section*) (
640                ((UChar*)(oc->image)) 
641                + sizeof_COFF_header + hdr->SizeOfOptionalHeader
642             );
643    symtab = (COFF_symbol*) (
644                ((UChar*)(oc->image))
645                + hdr->PointerToSymbolTable 
646             );
647    strtab = ((UChar*)(oc->image))
648             + hdr->PointerToSymbolTable
649             + hdr->NumberOfSymbols * sizeof_COFF_symbol;
650
651    if (hdr->Machine != 0x14c) {
652       oc->errMsg("Not x86 PEi386");
653       return FALSE;
654    }
655    if (hdr->SizeOfOptionalHeader != 0) {
656       oc->errMsg("PEi386 with nonempty optional header");
657       return FALSE;
658    }
659    if ( /* (hdr->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) || */
660         (hdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) ||
661         (hdr->Characteristics & IMAGE_FILE_DLL) ||
662         (hdr->Characteristics & IMAGE_FILE_SYSTEM) ) {
663       oc->errMsg("Not a PEi386 object file");
664       return FALSE;
665    }
666    if ( (hdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI) ||
667         !(hdr->Characteristics & IMAGE_FILE_32BIT_MACHINE) ) {
668       oc->errMsg("Invalid PEi386 word size or endiannness");
669       return FALSE;
670    }
671
672    if (!verb) return TRUE;
673    /* No further verification after this point; only debug printing. */
674
675    fprintf ( stderr, 
676              "sectab offset = %d\n", ((UChar*)sectab) - ((UChar*)hdr) );
677    fprintf ( stderr, 
678              "symtab offset = %d\n", ((UChar*)symtab) - ((UChar*)hdr) );
679    fprintf ( stderr, 
680              "strtab offset = %d\n", ((UChar*)strtab) - ((UChar*)hdr) );
681
682    fprintf ( stderr, "\n" );
683    fprintf ( stderr, 
684              "Machine:           0x%x\n", (UInt32)(hdr->Machine) );
685    fprintf ( stderr, 
686              "# sections:        %d\n",   (UInt32)(hdr->NumberOfSections) );
687    fprintf ( stderr,
688              "time/date:         0x%x\n", (UInt32)(hdr->TimeDateStamp) );
689    fprintf ( stderr,
690              "symtab offset:     %d\n",   (UInt32)(hdr->PointerToSymbolTable) );
691    fprintf ( stderr, 
692              "# symbols:         %d\n",   (UInt32)(hdr->NumberOfSymbols) );
693    fprintf ( stderr, 
694              "sz of opt hdr:     %d\n",   (UInt32)(hdr->SizeOfOptionalHeader) );
695    fprintf ( stderr,
696              "characteristics:   0x%x\n", (UInt32)(hdr->Characteristics) );
697
698    fprintf ( stderr, "\n" );
699    fprintf ( stderr, "string table has size 0x%x\n", * (UInt32*)strtab );
700    fprintf ( stderr, "---START of string table---\n");
701    for (i = 4; i < *(UInt32*)strtab; i++) {
702       if (strtab[i] == 0) 
703          fprintf ( stderr, "\n"); else 
704          fprintf( stderr, "%c", strtab[i] );
705    }
706    fprintf ( stderr, "--- END  of string table---\n");
707
708    fprintf ( stderr, "\n" );
709    for (i = 0; i < hdr->NumberOfSections; i++) {
710       COFF_reloc* reltab;
711       COFF_section* sectab_i
712          = (COFF_section*)
713            myindex ( sizeof_COFF_section, i, sectab );
714       fprintf ( stderr, 
715                 "\n"
716                 "section %d\n"
717                 "     name `",
718                 i 
719               );
720       printName ( sectab_i->Name, strtab );
721       fprintf ( stderr, 
722                 "'\n"
723                 "    vsize %d\n"
724                 "    vaddr %d\n"
725                 "  data sz %d\n"
726                 " data off %d\n"
727                 "  num rel %d\n"
728                 "  off rel %d\n",
729                 sectab_i->VirtualSize,
730                 sectab_i->VirtualAddress,
731                 sectab_i->SizeOfRawData,
732                 sectab_i->PointerToRawData,
733                 sectab_i->NumberOfRelocations,
734                 sectab_i->PointerToRelocations
735               );
736       reltab = (COFF_reloc*) (
737                   ((UChar*)(oc->image)) + sectab_i->PointerToRelocations
738                );
739       for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
740          COFF_symbol* sym;
741          COFF_reloc* rel = (COFF_reloc*)
742                            myindex ( sizeof_COFF_reloc, j, reltab );
743          fprintf ( stderr, 
744                    "        type 0x%-4x   vaddr 0x%-8x   name `",
745                    (UInt32)rel->Type, 
746                    rel->VirtualAddress );
747          sym = (COFF_symbol*)
748                myindex ( sizeof_COFF_symbol, rel->SymbolTableIndex, symtab );
749          printName ( sym->Name, strtab );
750          fprintf ( stderr, "'\n" );
751       }
752       fprintf ( stderr, "\n" );
753    }
754
755
756    fprintf ( stderr, "\n" );
757    i = 0;
758    while (1) {
759       COFF_symbol* symtab_i;
760       if (i >= hdr->NumberOfSymbols) break;
761       symtab_i = (COFF_symbol*)
762                  myindex ( sizeof_COFF_symbol, i, symtab );
763       fprintf ( stderr, 
764                 "symbol %d\n"
765                 "     name `",
766                 i 
767               );
768       printName ( symtab_i->Name, strtab );
769       fprintf ( stderr, 
770                 "'\n"
771                 "    value 0x%x\n"
772                 "     sec# %d\n"
773                 "     type 0x%x\n"
774                 "   sclass 0x%x\n"
775                 "     nAux %d\n",
776                 symtab_i->Value,
777                 (Int32)(symtab_i->SectionNumber) - 1,
778                 (UInt32)symtab_i->Type,
779                 (UInt32)symtab_i->StorageClass,
780                 (UInt32)symtab_i->NumberOfAuxSymbols 
781               );
782       i += symtab_i->NumberOfAuxSymbols;
783       i++;
784    }
785
786    fprintf ( stderr, "\n" );
787
788    return TRUE;
789 }
790
791
792 static int
793 ocGetNames_PEi386 ( ObjectCode* oc )
794 {
795    COFF_header*  hdr;
796    COFF_section* sectab;
797    COFF_symbol*  symtab;
798    UChar*        strtab;
799
800    UChar* sname;
801    void*  addr;
802    int    i;
803    
804    hdr = (COFF_header*)(oc->image);
805    sectab = (COFF_section*) (
806                ((UChar*)(oc->image)) 
807                + sizeof_COFF_header + hdr->SizeOfOptionalHeader
808             );
809    symtab = (COFF_symbol*) (
810                ((UChar*)(oc->image))
811                + hdr->PointerToSymbolTable 
812             );
813    strtab = ((UChar*)(oc->image))
814             + hdr->PointerToSymbolTable
815             + hdr->NumberOfSymbols * sizeof_COFF_symbol;
816
817    /* Copy exported symbols into the ObjectCode. */
818    i = 0;
819    while (1) {
820       COFF_symbol* symtab_i;
821       if (i >= hdr->NumberOfSymbols) break;
822       symtab_i = (COFF_symbol*)
823                  myindex ( sizeof_COFF_symbol, i, symtab );
824
825       if (symtab_i->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
826           symtab_i->SectionNumber != IMAGE_SYM_UNDEFINED) {
827
828          /* This symbol is global and defined, viz, exported */
829          COFF_section* sectabent;
830
831          sname = cstring_from_COFF_symbol_name ( 
832                     symtab_i->Name, strtab 
833                  );
834          if (!sname) {
835             oc->errMsg("Out of memory when copying PEi386 symbol");
836             return FALSE;
837          }
838
839          /* for IMAGE_SYMCLASS_EXTERNAL 
840                 && !IMAGE_SYM_UNDEFINED,
841             the address of the symbol is: 
842                 address of relevant section + offset in section
843          */
844          sectabent = (COFF_section*)
845                      myindex ( sizeof_COFF_section, 
846                                symtab_i->SectionNumber-1,
847                                sectab );
848          addr = ((UChar*)(oc->image))
849                 + (sectabent->PointerToRawData
850                    + symtab_i->Value);
851          /* fprintf ( stderr, "addSymbol %p `%s'\n", addr,sname); */
852          if (!addSymbol(oc,sname,addr)) return FALSE;
853       }
854       i += symtab_i->NumberOfAuxSymbols;
855       i++;
856    }
857
858    oc->sections = stgMallocBytes( NumberOfSections * sizeof(Section), 
859                                     "ocGetNamesPEi386" );
860
861    /* Copy section information into the ObjectCode. */
862    for (i = 0; i < hdr->NumberOfSections; i++) {
863       UChar* start;
864       UChar* end;
865
866       SectionKind kind 
867          = SECTIONKIND_OTHER;
868       COFF_section* sectab_i
869          = (COFF_section*)
870            myindex ( sizeof_COFF_section, i, sectab );
871       /* fprintf ( stderr, "section name = %s\n", sectab_i->Name ); */
872
873 #if 0
874       /* I'm sure this is the Right Way to do it.  However, the 
875          alternative of testing the sectab_i->Name field seems to
876          work ok with Cygwin.
877       */
878       if (sectab_i->Characteristics & IMAGE_SCN_CNT_CODE || 
879           sectab_i->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
880          kind = SECTIONKIND_CODE_OR_RODATA;
881 #endif
882
883       if (0==strcmp(".text",sectab_i->Name))
884          kind = SECTIONKIND_CODE_OR_RODATA;
885       if (0==strcmp(".data",sectab_i->Name) ||
886           0==strcmp(".bss",sectab_i->Name))
887          kind = SECTIONKIND_RWDATA;
888
889       start = ((UChar*)(oc->image)) 
890               + sectab_i->PointerToRawData;
891       end   = start 
892               + sectab_i->SizeOfRawData - 1;
893
894       if (kind != SECTIONKIND_OTHER) {
895          addSection ( oc, start, end, kind );
896       } else {
897          fprintf ( stderr, "unknown section name = `%s'\n", 
898                    sectab_i->Name);
899          oc->errMsg("Unknown PEi386 section name");
900          return FALSE;
901       }
902    }
903
904    return TRUE;   
905 }
906
907
908 static int
909 ocResolve_PEi386 ( ObjectCode* oc, int verb )
910 {
911    COFF_header*  hdr;
912    COFF_section* sectab;
913    COFF_symbol*  symtab;
914    UChar*        strtab;
915
916    UInt32        A;
917    UInt32        S;
918    UInt32*       pP;
919
920    int i, j;
921    char symbol[1000]; // ToDo
922    
923    hdr = (COFF_header*)(oc->image);
924    sectab = (COFF_section*) (
925                ((UChar*)(oc->image)) 
926                + sizeof_COFF_header + hdr->SizeOfOptionalHeader
927             );
928    symtab = (COFF_symbol*) (
929                ((UChar*)(oc->image))
930                + hdr->PointerToSymbolTable 
931             );
932    strtab = ((UChar*)(oc->image))
933             + hdr->PointerToSymbolTable
934             + hdr->NumberOfSymbols * sizeof_COFF_symbol;
935
936    for (i = 0; i < hdr->NumberOfSections; i++) {
937       COFF_section* sectab_i
938          = (COFF_section*)
939            myindex ( sizeof_COFF_section, i, sectab );
940       COFF_reloc* reltab
941          = (COFF_reloc*) (
942               ((UChar*)(oc->image)) + sectab_i->PointerToRelocations
943            );
944       for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
945          COFF_symbol* sym;
946          COFF_reloc* reltab_j 
947             = (COFF_reloc*)
948               myindex ( sizeof_COFF_reloc, j, reltab );
949
950          /* the location to patch */
951          pP = (UInt32*)(
952                  ((UChar*)(oc->image)) 
953                  + (sectab_i->PointerToRawData 
954                     + reltab_j->VirtualAddress)
955               );
956          /* the existing contents of pP */
957          A = *pP;
958          /* the symbol to connect to */
959          sym = (COFF_symbol*)
960                myindex ( sizeof_COFF_symbol, 
961                          reltab_j->SymbolTableIndex, symtab );
962          if (verb) {
963             fprintf ( stderr, 
964                    "reloc sec %2d num %3d:  type 0x%-4x   "
965                    "vaddr 0x%-8x   name `",
966                    i, j,
967                    (UInt32)reltab_j->Type, 
968                    reltab_j->VirtualAddress );
969             printName ( sym->Name, strtab );
970             fprintf ( stderr, "'\n" );
971          }
972
973          if (sym->StorageClass == IMAGE_SYM_CLASS_STATIC) {
974             COFF_section* section_sym 
975                = findPEi386SectionCalled ( oc, sym->Name );
976             if (!section_sym) {
977                fprintf ( stderr, "bad section = `%s'\n", sym->Name );
978                oc->errMsg("Can't find abovementioned PEi386 section");
979                return FALSE;
980             }
981             S = ((UInt32)(oc->image))
982                 + (section_sym->PointerToRawData
983                    + sym->Value);
984          } else {
985          copyName ( sym->Name, strtab, symbol, 1000 );
986          zapTrailingAtSign ( symbol );
987          S = (UInt32) ocLookupSym ( oc, symbol );
988          if (S == 0) 
989             S = (UInt32)(oc->clientLookup ( symbol ));
990          if (S == 0) {
991              belch("%s: unresolvable reference to `%s'", oc->fileName, symbol);
992              return FALSE;
993          }
994          }
995
996          switch (reltab_j->Type) {
997             case IMAGE_REL_I386_DIR32: 
998                *pP = A + S; 
999                break;
1000             case IMAGE_REL_I386_REL32:
1001                /* Tricky.  We have to insert a displacement at
1002                   pP which, when added to the PC for the _next_
1003                   insn, gives the address of the target (S).
1004                   Problem is to know the address of the next insn
1005                   when we only know pP.  We assume that this
1006                   literal field is always the last in the insn,
1007                   so that the address of the next insn is pP+4
1008                   -- hence the constant 4.
1009                   Also I don't know if A should be added, but so
1010                   far it has always been zero.
1011                */
1012                ASSERT(A==0);
1013                *pP = S - ((UInt32)pP) - 4;
1014                break;
1015             default: 
1016                fprintf(stderr, 
1017                        "unhandled PEi386 relocation type %d\n",
1018                        reltab_j->Type);
1019                oc->errMsg("unhandled PEi386 relocation type");
1020                return FALSE;
1021          }
1022
1023       }
1024    }
1025    
1026    return TRUE;
1027 }
1028
1029 #endif /* defined(cygwin32_TARGET_OS) */
1030
1031
1032 /* --------------------------------------------------------------------------
1033  * ELF specifics (Linux, Solaris)
1034  * ------------------------------------------------------------------------*/
1035
1036 #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
1037
1038 #define FALSE 0
1039 #define TRUE  1
1040
1041 #include <elf.h>
1042
1043 static char *
1044 findElfSection ( void* objImage, Elf32_Word sh_type )
1045 {
1046    int i;
1047    char* ehdrC = (char*)objImage;
1048    Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
1049    Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1050    char* ptr = NULL;
1051    for (i = 0; i < ehdr->e_shnum; i++) {
1052       if (shdr[i].sh_type == sh_type &&
1053           i !=  ehdr->e_shstrndx) {
1054          ptr = ehdrC + shdr[i].sh_offset;
1055          break;
1056       }
1057    }
1058    return ptr;
1059 }
1060
1061
1062 static int
1063 ocVerifyImage_ELF ( ObjectCode* oc )
1064 {
1065    Elf32_Shdr* shdr;
1066    Elf32_Sym*  stab;
1067    int i, j, nent, nstrtab, nsymtabs;
1068    char* sh_strtab;
1069    char* strtab;
1070
1071    char*       ehdrC = (char*)(oc->image);
1072    Elf32_Ehdr* ehdr  = ( Elf32_Ehdr*)ehdrC;
1073
1074    if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
1075        ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
1076        ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
1077        ehdr->e_ident[EI_MAG3] != ELFMAG3) {
1078       belch("ocVerifyImage_ELF: not an ELF header");
1079       return 0;
1080    }
1081    IF_DEBUG(linker,belch( "Is an ELF header" ));
1082
1083    if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
1084       belch("ocVerifyImage_ELF: not 32 bit ELF" );
1085       return 0;
1086    }
1087
1088    IF_DEBUG(linker,belch( "Is 32 bit ELF" ));
1089
1090    if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
1091        IF_DEBUG(linker,belch( "Is little-endian" ));
1092    } else
1093    if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
1094        IF_DEBUG(linker,belch( "Is big-endian" ));
1095    } else {
1096        belch("ocVerifyImage_ELF: unknown endiannness");
1097        return 0;
1098    }
1099
1100    if (ehdr->e_type != ET_REL) {
1101       belch("ocVerifyImage_ELF: not a relocatable object (.o) file");
1102       return 0;
1103    }
1104    IF_DEBUG(linker, belch( "Is a relocatable object (.o) file" ));
1105
1106    IF_DEBUG(linker,belch( "Architecture is " ));
1107    switch (ehdr->e_machine) {
1108       case EM_386:   IF_DEBUG(linker,belch( "x86" )); break;
1109       case EM_SPARC: IF_DEBUG(linker,belch( "sparc" )); break;
1110       default:       IF_DEBUG(linker,belch( "unknown" )); 
1111                      belch("ocVerifyImage_ELF: unknown architecture");
1112                      return 0;
1113    }
1114
1115    IF_DEBUG(linker,belch(
1116              "\nSection header table: start %d, n_entries %d, ent_size %d", 
1117              ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize  ));
1118
1119    ASSERT (ehdr->e_shentsize == sizeof(Elf32_Shdr));
1120
1121    shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1122
1123    if (ehdr->e_shstrndx == SHN_UNDEF) {
1124       belch("ocVerifyImage_ELF: no section header string table");
1125       return 0;
1126    } else {
1127       IF_DEBUG(linker,belch( "Section header string table is section %d", 
1128                           ehdr->e_shstrndx));
1129       sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1130    }
1131
1132    for (i = 0; i < ehdr->e_shnum; i++) {
1133       IF_DEBUG(linker,fprintf(stderr, "%2d:  ", i ));
1134       IF_DEBUG(linker,fprintf(stderr, "type=%2d  ", shdr[i].sh_type ));
1135       IF_DEBUG(linker,fprintf(stderr, "size=%4d  ", shdr[i].sh_size ));
1136       IF_DEBUG(linker,fprintf(stderr, "offs=%4d  ", shdr[i].sh_offset ));
1137       IF_DEBUG(linker,fprintf(stderr, "  (%p .. %p)  ",
1138                ehdrC + shdr[i].sh_offset, 
1139                       ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1));
1140
1141       if (shdr[i].sh_type == SHT_REL) {
1142           IF_DEBUG(linker,fprintf(stderr, "Rel  " ));
1143       } else if (shdr[i].sh_type == SHT_RELA) {
1144           IF_DEBUG(linker,fprintf(stderr, "RelA " ));
1145       } else {
1146           IF_DEBUG(linker,fprintf(stderr,"     "));
1147       }
1148       if (sh_strtab) {
1149           IF_DEBUG(linker,fprintf(stderr, "sname=%s\n", sh_strtab + shdr[i].sh_name ));
1150       }
1151    }
1152
1153    IF_DEBUG(linker,belch( "\nString tables" ));
1154    strtab = NULL;
1155    nstrtab = 0;
1156    for (i = 0; i < ehdr->e_shnum; i++) {
1157       if (shdr[i].sh_type == SHT_STRTAB &&
1158           i !=  ehdr->e_shstrndx) {
1159           IF_DEBUG(linker,belch("   section %d is a normal string table", i ));
1160          strtab = ehdrC + shdr[i].sh_offset;
1161          nstrtab++;
1162       }
1163    }  
1164    if (nstrtab != 1) {
1165       belch("ocVerifyImage_ELF: no string tables, or too many");
1166       return 0;
1167    }
1168
1169    nsymtabs = 0;
1170    IF_DEBUG(linker,belch( "\nSymbol tables" )); 
1171    for (i = 0; i < ehdr->e_shnum; i++) {
1172       if (shdr[i].sh_type != SHT_SYMTAB) continue;
1173       IF_DEBUG(linker,belch( "section %d is a symbol table", i ));
1174       nsymtabs++;
1175       stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
1176       nent = shdr[i].sh_size / sizeof(Elf32_Sym);
1177       IF_DEBUG(linker,belch( "   number of entries is apparently %d (%d rem)",
1178                nent,
1179                shdr[i].sh_size % sizeof(Elf32_Sym)
1180              ));
1181       if (0 != shdr[i].sh_size % sizeof(Elf32_Sym)) {
1182          belch("ocVerifyImage_ELF: non-integral number of symbol table entries");
1183          return 0;
1184       }
1185       for (j = 0; j < nent; j++) {
1186          IF_DEBUG(linker,fprintf(stderr, "   %2d  ", j ));
1187          IF_DEBUG(linker,fprintf(stderr, "  sec=%-5d  size=%-3d  val=%5p  ", 
1188                              (int)stab[j].st_shndx,
1189                              (int)stab[j].st_size,
1190                              (char*)stab[j].st_value ));
1191
1192          IF_DEBUG(linker,fprintf(stderr, "type=" ));
1193          switch (ELF32_ST_TYPE(stab[j].st_info)) {
1194             case STT_NOTYPE:  IF_DEBUG(linker,fprintf(stderr, "notype " )); break;
1195             case STT_OBJECT:  IF_DEBUG(linker,fprintf(stderr, "object " )); break;
1196             case STT_FUNC  :  IF_DEBUG(linker,fprintf(stderr, "func   " )); break;
1197             case STT_SECTION: IF_DEBUG(linker,fprintf(stderr, "section" )); break;
1198             case STT_FILE:    IF_DEBUG(linker,fprintf(stderr, "file   " )); break;
1199             default:          IF_DEBUG(linker,fprintf(stderr, "?      " )); break;
1200          }
1201          IF_DEBUG(linker,fprintf(stderr, "  " ));
1202
1203          IF_DEBUG(linker,fprintf(stderr, "bind=" ));
1204          switch (ELF32_ST_BIND(stab[j].st_info)) {
1205             case STB_LOCAL :  IF_DEBUG(linker,fprintf(stderr, "local " )); break;
1206             case STB_GLOBAL:  IF_DEBUG(linker,fprintf(stderr, "global" )); break;
1207             case STB_WEAK  :  IF_DEBUG(linker,fprintf(stderr, "weak  " )); break;
1208             default:          IF_DEBUG(linker,fprintf(stderr, "?     " )); break;
1209          }
1210          IF_DEBUG(linker,fprintf(stderr, "  " ));
1211
1212          IF_DEBUG(linker,fprintf(stderr, "name=%s\n", strtab + stab[j].st_name ));
1213       }
1214    }
1215
1216    if (nsymtabs == 0) {
1217       belch("ocVerifyImage_ELF: didn't find any symbol tables");
1218       return 0;
1219    }
1220
1221    return 1;
1222 }
1223
1224
1225 static int
1226 ocGetNames_ELF ( ObjectCode* oc )
1227 {
1228    int i, j, k, nent;
1229    Elf32_Sym* stab;
1230
1231    char*       ehdrC      = (char*)(oc->image);
1232    Elf32_Ehdr* ehdr       = (Elf32_Ehdr*)ehdrC;
1233    char*       strtab     = findElfSection ( ehdrC, SHT_STRTAB );
1234    Elf32_Shdr* shdr       = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1235    char*       sh_strtab  = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1236
1237    if (!strtab) {
1238       belch("ocGetNames_ELF: no strtab");
1239       return 0;
1240    }
1241
1242    k = 0;
1243    oc->sections = stgMallocBytes( ehdr->e_shnum * sizeof(Section), 
1244                                     "ocGetNames_ELF" );
1245    oc->n_sections = ehdr->e_shnum;
1246
1247    for (i = 0; i < ehdr->e_shnum; i++) {
1248
1249       /* make a section entry for relevant sections */
1250       SectionKind kind = SECTIONKIND_OTHER;
1251       if (!strcmp(".data",sh_strtab+shdr[i].sh_name) ||
1252           !strcmp(".data1",sh_strtab+shdr[i].sh_name))
1253           kind = SECTIONKIND_RWDATA;
1254       if (!strcmp(".text",sh_strtab+shdr[i].sh_name) ||
1255           !strcmp(".rodata",sh_strtab+shdr[i].sh_name) ||
1256           !strcmp(".rodata1",sh_strtab+shdr[i].sh_name))
1257           kind = SECTIONKIND_CODE_OR_RODATA;
1258
1259       /* fill in the section info */
1260       oc->sections[i].start = ehdrC + shdr[i].sh_offset;
1261       oc->sections[i].end   = ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1;
1262       oc->sections[i].kind  = kind;
1263       
1264       if (shdr[i].sh_type != SHT_SYMTAB) continue;
1265
1266       /* copy stuff into this module's object symbol table */
1267       stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
1268       nent = shdr[i].sh_size / sizeof(Elf32_Sym);
1269       oc->symbols = malloc(nent * sizeof(SymbolVal));
1270       for (j = 0; j < nent; j++) {
1271          if ( ( ELF32_ST_BIND(stab[j].st_info)==STB_GLOBAL /* ||
1272                 ELF32_ST_BIND(stab[j].st_info)==STB_LOCAL */
1273               )
1274               /* and not an undefined symbol */
1275               && stab[j].st_shndx != SHN_UNDEF
1276               &&
1277               /* and it's a not a section or string table or anything silly */
1278               ( ELF32_ST_TYPE(stab[j].st_info)==STT_FUNC ||
1279                 ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT ||
1280                 ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE )
1281                 ) { 
1282             char* nm = strtab + stab[j].st_name;
1283             char* ad = ehdrC 
1284                        + shdr[ stab[j].st_shndx ].sh_offset
1285                        + stab[j].st_value;
1286             ASSERT(nm != NULL);
1287             ASSERT(ad != NULL);
1288             IF_DEBUG(linker,belch( "addOTabName: %10p  %s %s",
1289                        ad, oc->fileName, nm ));
1290             oc->symbols[j].lbl  = nm;
1291             oc->symbols[j].addr = ad;
1292             insertStrHashTable(symhash, nm, &(oc->symbols[j]));
1293          }
1294          else {
1295              IF_DEBUG(linker,belch( "skipping `%s'", strtab +
1296                              stab[j].st_name ));
1297              oc->symbols[j].lbl  = NULL;
1298              oc->symbols[j].addr = NULL;
1299          }
1300       }
1301    }
1302
1303    return 1;
1304 }
1305
1306
1307 static int
1308 ocResolve_ELF ( ObjectCode* oc )
1309 {
1310    char *strtab, *symbol;
1311    int   i, j;
1312    Elf32_Sym*  stab = NULL;
1313    char*       ehdrC = (char*)(oc->image);
1314    Elf32_Ehdr* ehdr = (Elf32_Ehdr*) ehdrC;
1315    Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1316    Elf32_Word* targ;
1317
1318    /* first find "the" symbol table */
1319    stab = (Elf32_Sym*) findElfSection ( ehdrC, SHT_SYMTAB );
1320
1321    /* also go find the string table */
1322    strtab = findElfSection ( ehdrC, SHT_STRTAB );
1323
1324    if (stab == NULL || strtab == NULL) {
1325       belch("ocResolve_ELF: can't find string or symbol table");
1326       return 0; 
1327    }
1328
1329    for (i = 0; i < ehdr->e_shnum; i++) {
1330       if (shdr[i].sh_type == SHT_REL ) {
1331          Elf32_Rel*  rtab = (Elf32_Rel*) (ehdrC + shdr[i].sh_offset);
1332          int         nent = shdr[i].sh_size / sizeof(Elf32_Rel);
1333          int target_shndx = shdr[i].sh_info;
1334          int symtab_shndx = shdr[i].sh_link;
1335          stab  = (Elf32_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
1336          targ  = (Elf32_Word*)(ehdrC + shdr[ target_shndx ].sh_offset);
1337          IF_DEBUG(linker,belch( "relocations for section %d using symtab %d",
1338                          target_shndx, symtab_shndx ));
1339          for (j = 0; j < nent; j++) {
1340             Elf32_Addr offset = rtab[j].r_offset;
1341             Elf32_Word info   = rtab[j].r_info;
1342
1343             Elf32_Addr  P = ((Elf32_Addr)targ) + offset;
1344             Elf32_Word* pP = (Elf32_Word*)P;
1345             Elf32_Addr  A = *pP;
1346             Elf32_Addr  S;
1347
1348             IF_DEBUG(linker,belch( "Rel entry %3d is raw(%6p %6p)   ", 
1349                                 j, (void*)offset, (void*)info ));
1350             if (!info) {
1351                IF_DEBUG(linker,belch( " ZERO" ));
1352                S = 0;
1353             } else {
1354                /* First see if it is a nameless local symbol. */
1355                if (stab[ ELF32_R_SYM(info)].st_name == 0) {
1356                    symbol = "(noname)";
1357                    S = (Elf32_Addr)(ehdrC
1358                                     + shdr[stab[ELF32_R_SYM(info)].st_shndx ].sh_offset
1359                                     + stab[ELF32_R_SYM(info)].st_value
1360                        );
1361                } else {
1362                    /* No?  Should be in the symbol table then. */
1363                    symbol = strtab+stab[ ELF32_R_SYM(info)].st_name;
1364                    (void *)S = lookupSymbol( symbol );
1365                }
1366                if (!S) {
1367                    barf("ocResolve_ELF: %s: unknown symbol `%s'",
1368                         oc->fileName, symbol);
1369                }
1370                IF_DEBUG(linker,belch( "`%s' resolves to %p", symbol, (void*)S ));
1371             }
1372             IF_DEBUG(linker,fprintf ( stderr, "Reloc: P = %p   S = %p   A = %p\n", (void*)P, (void*)S, (void*)A )); 
1373             switch (ELF32_R_TYPE(info)) {
1374                case R_386_32:   *pP = S + A;     break;
1375                case R_386_PC32: *pP = S + A - P; break;
1376                default: fprintf(stderr, 
1377                                 "unhandled ELF relocation type %d",
1378                                 ELF32_R_TYPE(info));
1379                         belch("ocResolve_ELF: unhandled ELF relocation type");
1380                         return 0;
1381             }
1382
1383          }
1384       }
1385       else
1386       if (shdr[i].sh_type == SHT_RELA) {
1387          belch("ocResolve_ELF: RelA style reloc table -- not yet done");
1388          return 0;
1389       }
1390    }
1391
1392    return 1;
1393 }
1394
1395
1396 #endif /* defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) */
1397
1398 /* -----------------------------------------------------------------------------
1399  * Look up an address to discover whether it is in text or data space.
1400  *
1401  * Used by the garbage collector when walking the stack.
1402  * -------------------------------------------------------------------------- */
1403
1404 SectionKind
1405 lookupSection ( void* addr )
1406 {
1407    int          i;
1408    ObjectCode*  oc;
1409    
1410    for ( oc = objects; oc; oc = oc->next ) {
1411        for (i = 0; i < oc->n_sections; i++) {
1412            if (oc->sections[i].start <= addr 
1413                && addr <= oc->sections[i].end)
1414                return oc->sections[i].kind;
1415        }
1416    }
1417    return SECTIONKIND_OTHER;
1418 }
1419
1420 int
1421 is_dynamically_loaded_code_or_rodata_ptr ( char* p )
1422 {
1423    SectionKind sk = lookupSection(p);
1424    assert (sk != SECTIONKIND_NOINFOAVAIL);
1425    return (sk == SECTIONKIND_CODE_OR_RODATA);
1426 }
1427
1428
1429 int
1430 is_dynamically_loaded_rwdata_ptr ( char* p )
1431 {
1432    SectionKind sk = lookupSection(p);
1433    assert (sk != SECTIONKIND_NOINFOAVAIL);
1434    return (sk == SECTIONKIND_RWDATA);
1435 }
1436
1437
1438 int
1439 is_not_dynamically_loaded_ptr ( char* p )
1440 {
1441    SectionKind sk = lookupSection(p);
1442    assert (sk != SECTIONKIND_NOINFOAVAIL);
1443    return (sk == SECTIONKIND_OTHER);
1444 }
1445