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