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