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