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