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