[project @ 1999-12-20 10:12:50 by simonpj]
[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 <assert.h>
19 #include "object.h"
20
21
22 #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
23 static int ocVerifyImage_ELF ( ObjectCode* oc, int verb );
24 static int ocGetNames_ELF    ( ObjectCode* oc, int verb );
25 static int ocResolve_ELF     ( ObjectCode* oc, int verb );
26 #endif
27
28 static char* hackyAppend ( char* s1, char* s2 );
29
30
31 /* --------------------------------------------------------------------------
32  * Arch-independent interface to the runtime linker
33  * ------------------------------------------------------------------------*/
34
35 ObjectCode*  ocNew ( void  (*errMsg)(char*),
36                      void* (*clientLookup)(char*),
37                      char*  objFileName,
38                      int    objFileSize )
39 {
40    ObjectCode* oc     = malloc(sizeof(ObjectCode));
41    if (!oc) {
42       errMsg("ocNew: can't allocate memory for object code record");
43       return NULL;
44    }
45
46 #  if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
47    oc->formatName = "ELF";
48 #  else
49    free(oc);
50    errMsg("ocNew: not implemented on this platform");
51    return NULL;
52 #  endif
53
54    oc->status         = OBJECT_NOTINUSE;
55    oc->objFileName    = objFileName;
56    oc->objFileSize    = objFileSize;
57    oc->errMsg         = errMsg;
58    oc->clientLookup   = clientLookup;
59
60    oc->oImage         = malloc ( objFileSize );
61    if (!oc->oImage) {
62       free(oc);
63       errMsg("ocNew: can't allocate memory for object code");
64       return NULL;
65    }
66    oc->oTab           = NULL;
67    oc->sizeoTab       = 0;
68    oc->usedoTab       = 0;
69    oc->sectionTab     = NULL;
70    oc->sizesectionTab = 0;
71    oc->usedsectionTab = 0;
72    oc->next           = NULL;
73
74    return oc;
75 }
76                             
77
78 int ocLoadImage ( ObjectCode* oc, int verb )
79 {
80    int   n;
81    FILE* f;
82    assert (oc && oc->status==OBJECT_NOTINUSE);
83    if (verb) fprintf(stderr, "ocLoadImage %s\n", oc->objFileName );
84    f = fopen(oc->objFileName, "rb");
85    if (!f) {
86        (oc->errMsg(hackyAppend("ocLoadImage: can't read: ",
87                                oc->objFileName)));
88        return 0;
89    }
90    n = fread ( oc->oImage, 1, oc->objFileSize, f );
91    if (n != oc->objFileSize) {
92       fclose(f);
93       oc->errMsg(hackyAppend("ocLoadImage: I/O error whilst reading: ",
94                              oc->objFileName));
95       return 0;
96    }
97    oc->status = OBJECT_OIMAGE;
98    if (verb) fprintf(stderr, "ocLoadImage %s: read %d bytes\n", 
99                      oc->objFileName, oc->objFileSize );
100    return 1;
101 }
102
103
104 /* returns 1 if ok, 0 if error */
105 int ocVerifyImage ( ObjectCode* oc, int verb )
106 {
107    int ret;
108    assert (oc && oc->status==OBJECT_OIMAGE);
109    if (verb) fprintf(stderr, "ocVerifyImage: begin\n");
110 #  if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
111    ret = ocVerifyImage_ELF ( oc, verb );
112 #  else
113    oc->errMsg("ocVerifyImage: not implemented on this platform");
114    return 0;
115 #  endif
116    if (verb) fprintf(stderr, "ocVerifyImage: done, status = %d", ret);
117
118    if (ret) oc->status==OBJECT_VERIFIED;
119    return ret;
120 }
121
122
123 /* returns 1 if ok, 0 if error */
124 int ocGetNames ( ObjectCode* oc, int verb )
125 {
126    int ret;
127    assert (oc && oc->status==OBJECT_VERIFIED);
128    if (verb) fprintf(stderr, "ocGetNames: begin\n");
129 #  if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
130    ret = ocGetNames_ELF ( oc, verb );
131 #  else
132    oc->errMsg("ocGetNames: not implemented on this platform");
133    return 0;
134 #  endif
135    if (verb) fprintf(stderr, "ocGetNames: done, status = %d\n", ret);
136    if (ret) oc->status==OBJECT_HAVENAMES;
137    return ret;
138 }
139
140
141 /* returns 1 if ok, 0 if error */
142 int ocResolve ( ObjectCode* oc, int verb )
143 {
144    int ret;
145    assert (oc && oc->status==OBJECT_HAVENAMES);
146    if (verb) fprintf(stderr, "ocResolve: begin\n");
147 #  if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
148    ret = ocResolve_ELF ( oc, verb );
149 #  else
150    oc->errMsg("ocResolve: not implemented on this platform");
151    return 0;
152 #  endif
153    if (verb) fprintf(stderr, "ocResolve: done, status = %d\n", ret);
154    if (ret) oc->status==OBJECT_RESOLVED;
155    return ret;
156 }
157
158
159 void ocFree ( ObjectCode* oc )
160 {
161    if (oc) {
162       if (oc->oImage)     free(oc->oImage);
163       if (oc->oTab)       free(oc->oTab);
164       if (oc->sectionTab) free(oc->sectionTab);
165       free(oc);
166    }
167 }
168
169
170 /* --------------------------------------------------------------------------
171  * Simple, dynamically expandable association tables
172  * ------------------------------------------------------------------------*/
173
174 /* A bit tricky.  Assumes that if tab==NULL, then 
175    currUsed and *currSize must be zero.
176    Returns NULL if expansion failed.
177 */
178 static void* genericExpand ( void* tab, 
179                              int*  currSize, int  currUsed,
180                              int   initSize, int  elemSize )
181 {
182    int   size2;
183    void* tab2;
184    if (currUsed < *currSize) return tab;
185    size2 = (*currSize == 0) ? initSize : (2 * *currSize);
186    tab2 = malloc ( size2 * elemSize );
187    if (!tab2) return NULL;
188    if (*currSize > 0)
189       memcpy ( tab2, tab, elemSize * *currSize );
190    *currSize = size2;
191    if (tab) free ( tab );
192    return tab2;
193 }
194
195
196 /* returns 1 if success, 0 if error */
197 static int addSymbol ( ObjectCode* oc, char* nm, void* ad )
198 {
199    OSym* newTab
200       = genericExpand ( oc->oTab, 
201                         &(oc->sizeoTab),
202                         oc->usedoTab,
203                         8, sizeof(OSym) );
204
205    if (!newTab) {
206       oc->errMsg("addSymbol: malloc failed whilst expanding table");
207       return 0;
208    }
209    oc->oTab = newTab;
210    oc->oTab[ oc->usedoTab ].nm = nm;
211    oc->oTab[ oc->usedoTab ].ad = ad;
212    oc->usedoTab++;
213    return 1;
214 }
215
216
217 /* returns 1 if success, 0 if error */
218 static int addSection ( ObjectCode* oc, void* start, void* end, OSectionKind sect )
219 {
220    OSection* newTab
221       = genericExpand ( oc->sectionTab,
222                         &(oc->sizesectionTab),
223                         oc->usedsectionTab,
224                         4, sizeof(OSection) );
225    if (!newTab) {
226       oc->errMsg("addSection: malloc failed whilst expanding table");
227       return 0;
228    }
229    oc->sectionTab = newTab;
230    oc->sectionTab[ oc->usedsectionTab ].start = start;
231    oc->sectionTab[ oc->usedsectionTab ].end   = end;
232    oc->sectionTab[ oc->usedsectionTab ].kind  = sect;
233    oc->usedsectionTab++;
234    return 1;
235 }
236
237
238 void* ocLookupSym ( ObjectCode* oc, char* sym )
239 {
240    int i;
241
242    assert(oc);
243    if (oc->status != OBJECT_HAVENAMES 
244        && oc->status != OBJECT_RESOLVED) {
245       oc->errMsg("ocLookupSym: no symbols available");
246       return NULL;
247    }
248
249    for (i = 0; i < oc->usedoTab; i++) {
250       if (0)
251          fprintf ( stderr, 
252                    "ocLookupSym: request %s, table has %s\n",
253                    sym, oc->oTab[i].nm );
254       if (0==strcmp(sym,oc->oTab[i].nm))
255          return oc->oTab[i].ad;
256    }
257    return NULL;
258 }
259
260
261 char* ocLookupAddr ( ObjectCode* oc, void* addr )
262 {
263    int i;
264
265    assert(oc);
266    if (oc->status != OBJECT_HAVENAMES 
267        && oc->status != OBJECT_RESOLVED) {
268       oc->errMsg("ocLookupAddr: no symbols available");
269       return NULL;
270    }
271
272    for (i = 0; i < oc->usedoTab; i++) {
273       if (addr == oc->oTab[i].ad)
274          return oc->oTab[i].nm;
275    }
276    return NULL;
277 }
278
279
280 OSectionKind ocLookupSection ( ObjectCode* oc, void* addr )
281 {
282    int i;
283
284    assert(oc);
285    if (oc->status != OBJECT_HAVENAMES 
286        && oc->status != OBJECT_RESOLVED) {
287       oc->errMsg("ocLookupSection: no symbols available");
288       return HUGS_SECTIONKIND_NOINFOAVAIL;
289    }
290
291
292    for (i = 0; i < oc->usedsectionTab; i++) {
293       if (oc->sectionTab[i].start <= addr 
294           && addr <= oc->sectionTab[i].end)
295          return oc->sectionTab[i].kind;
296    }
297
298    return HUGS_SECTIONKIND_NOINFOAVAIL;
299 }
300
301
302 /* Ghastly append which leaks space.  But we only use it for
303    error messages -- that's my excuse.
304 */
305 static char* hackyAppend ( char* s1, char* s2 )
306 {
307    char* res = malloc ( 4 + strlen(s1) + strlen(s2) );
308    if (!res) {
309       fprintf ( stderr, "hugs: fatal: hackyAppend\n\t%s\n\t%s\n", s1, s2 );
310       assert(res);
311    }
312    strcpy(res,s1);
313    strcat(res,s2);
314    return res;
315 }
316
317 /* --------------------------------------------------------------------------
318  * ELF specifics
319  * ------------------------------------------------------------------------*/
320
321 #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
322
323 #include <elf.h>
324
325 static char* findElfSection ( void* objImage, Elf32_Word sh_type )
326 {
327    Int i;
328    char* ehdrC = (char*)objImage;
329    Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
330    Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
331    char* ptr = NULL;
332    for (i = 0; i < ehdr->e_shnum; i++) {
333       if (shdr[i].sh_type == sh_type &&
334           i !=  ehdr->e_shstrndx) {
335          ptr = ehdrC + shdr[i].sh_offset;
336          break;
337       }
338    }
339    return ptr;
340 }
341
342
343 static int ocVerifyImage_ELF ( ObjectCode* oc, int verb )
344 {
345    Elf32_Shdr* shdr;
346    Elf32_Sym*  stab;
347    int i, j, nent, nstrtab, nsymtabs;
348    char* sh_strtab;
349    char* strtab;
350
351    char*       ehdrC = (char*)(oc->oImage);
352    Elf32_Ehdr* ehdr  = ( Elf32_Ehdr*)ehdrC;
353
354    if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
355        ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
356        ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
357        ehdr->e_ident[EI_MAG3] != ELFMAG3) {
358       oc->errMsg("Not an ELF header");
359       return FALSE;
360    }
361    if (verb) fprintf ( stderr, "Is an ELF header\n" );
362
363    if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
364       oc->errMsg("Not 32 bit ELF" );
365       return FALSE;
366    }
367    if (verb) fprintf ( stderr, "Is 32 bit ELF\n" );
368
369    if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
370       if (verb) fprintf ( stderr, "Is little-endian\n" );
371    } else
372    if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
373       if (verb) fprintf ( stderr, "Is big-endian\n" );
374    } else {
375       oc->errMsg("Unknown endiannness");
376       return FALSE;
377    }
378
379    if (ehdr->e_type != ET_REL) {
380       oc->errMsg("Not a relocatable object (.o) file");
381       return FALSE;
382    }
383    if (verb) fprintf ( stderr, "Is a relocatable object (.o) file\n" );
384
385    if (verb) fprintf ( stderr, "Architecture is " );
386    switch (ehdr->e_machine) {
387       case EM_386:   if (verb) fprintf ( stderr, "x86\n" ); break;
388       case EM_SPARC: if (verb) fprintf ( stderr, "sparc\n" ); break;
389       default:       if (verb) fprintf ( stderr, "unknown\n" ); 
390                      oc->errMsg("Unknown architecture");
391                      return FALSE;
392    }
393
394    if (verb) 
395    fprintf ( stderr,
396              "\nSection header table: start %d, n_entries %d, ent_size %d\n", 
397              ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize  );
398
399    assert (ehdr->e_shentsize == sizeof(Elf32_Shdr));
400
401    shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
402
403    if (ehdr->e_shstrndx == SHN_UNDEF) {
404       oc->errMsg("No section header string table");
405       return FALSE;
406    } else {
407       if (verb) fprintf (  stderr,"Section header string table is section %d\n", 
408                           ehdr->e_shstrndx);
409       sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
410    }
411
412    for (i = 0; i < ehdr->e_shnum; i++) {
413       if (verb) fprintf ( stderr, "%2d:  ", i );
414       if (verb) fprintf ( stderr, "type=%2d  ", shdr[i].sh_type );
415       if (verb) fprintf ( stderr, "size=%4d  ", shdr[i].sh_size );
416       if (verb) fprintf ( stderr, "offs=%4d  ", shdr[i].sh_offset );
417       if (verb) fprintf ( stderr, "  (%p .. %p)  ",
418                ehdrC + shdr[i].sh_offset, 
419                ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1);
420
421       if (shdr[i].sh_type == SHT_REL  && verb) fprintf ( stderr, "Rel  " ); else
422       if (shdr[i].sh_type == SHT_RELA && verb) fprintf ( stderr, "RelA " ); else
423       if (verb)                                fprintf ( stderr, "     " );
424       if (sh_strtab && verb) 
425          fprintf ( stderr, "sname=%s", sh_strtab + shdr[i].sh_name );
426       if (verb) fprintf ( stderr, "\n" );
427    }
428
429    if (verb) fprintf ( stderr, "\n\nString tables\n" );
430    strtab = NULL;
431    nstrtab = 0;
432    for (i = 0; i < ehdr->e_shnum; i++) {
433       if (shdr[i].sh_type == SHT_STRTAB &&
434           i !=  ehdr->e_shstrndx) {
435          if (verb) 
436             fprintf ( stderr, "   section %d is a normal string table\n", i );
437          strtab = ehdrC + shdr[i].sh_offset;
438          nstrtab++;
439       }
440    }  
441    if (nstrtab != 1) {
442       oc->errMsg("WARNING: no string tables, or too many");
443       return FALSE;
444    }
445
446    nsymtabs = 0;
447    if (verb) fprintf ( stderr, "\n\nSymbol tables\n" ); 
448    for (i = 0; i < ehdr->e_shnum; i++) {
449       if (shdr[i].sh_type != SHT_SYMTAB) continue;
450       if (verb) fprintf ( stderr, "section %d is a symbol table\n", i );
451       nsymtabs++;
452       stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
453       nent = shdr[i].sh_size / sizeof(Elf32_Sym);
454       if (verb) fprintf ( stderr, "   number of entries is apparently %d (%d rem)\n",
455                nent,
456                shdr[i].sh_size % sizeof(Elf32_Sym)
457              );
458       if (0 != shdr[i].sh_size % sizeof(Elf32_Sym)) {
459          oc->errMsg("non-integral number of symbol table entries");
460          return FALSE;
461       }
462       for (j = 0; j < nent; j++) {
463          if (verb) fprintf ( stderr, "   %2d  ", j );
464          if (verb) fprintf ( stderr, "  sec=%-5d  size=%-3d  val=%-5p  ", 
465                              (int)stab[j].st_shndx,
466                              (int)stab[j].st_size,
467                              (char*)stab[j].st_value );
468
469          if (verb) fprintf ( stderr, "type=" );
470          switch (ELF32_ST_TYPE(stab[j].st_info)) {
471             case STT_NOTYPE:  if (verb) fprintf ( stderr, "notype " ); break;
472             case STT_OBJECT:  if (verb) fprintf ( stderr, "object " ); break;
473             case STT_FUNC  :  if (verb) fprintf ( stderr, "func   " ); break;
474             case STT_SECTION: if (verb) fprintf ( stderr, "section" ); break;
475             case STT_FILE:    if (verb) fprintf ( stderr, "file   " ); break;
476             default:          if (verb) fprintf ( stderr, "?      " ); break;
477          }
478          if (verb) fprintf ( stderr, "  " );
479
480          if (verb) fprintf ( stderr, "bind=" );
481          switch (ELF32_ST_BIND(stab[j].st_info)) {
482             case STB_LOCAL :  if (verb) fprintf ( stderr, "local " ); break;
483             case STB_GLOBAL:  if (verb) fprintf ( stderr, "global" ); break;
484             case STB_WEAK  :  if (verb) fprintf ( stderr, "weak  " ); break;
485             default:          if (verb) fprintf ( stderr, "?     " ); break;
486          }
487          if (verb) fprintf ( stderr, "  " );
488
489          if (verb) fprintf ( stderr, "name=%s\n", strtab + stab[j].st_name );
490       }
491    }
492
493    if (nsymtabs == 0) {
494       oc->errMsg("Didn't find any symbol tables");
495       return FALSE;
496    }
497
498    return TRUE;
499 }
500
501
502 static int ocGetNames_ELF ( ObjectCode* oc, int verb )
503 {
504    int i, j, k, nent;
505    Elf32_Sym* stab;
506
507    char*       ehdrC      = (char*)(oc->oImage);
508    Elf32_Ehdr* ehdr       = (Elf32_Ehdr*)ehdrC;
509    char*       strtab     = findElfSection ( ehdrC, SHT_STRTAB );
510    Elf32_Shdr* shdr       = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
511    char*       sh_strtab  = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
512
513    if (!strtab) {
514       oc->errMsg("no strtab!");
515       return FALSE;
516    }
517
518    k = 0;
519    for (i = 0; i < ehdr->e_shnum; i++) {
520
521       /* make a HugsDLSection entry for relevant sections */
522       DLSect kind = HUGS_DL_SECTION_OTHER;
523       if (0==strcmp(".data",sh_strtab+shdr[i].sh_name) ||
524           0==strcmp(".data1",sh_strtab+shdr[i].sh_name))
525          kind = HUGS_DL_SECTION_RWDATA;
526       if (0==strcmp(".text",sh_strtab+shdr[i].sh_name) ||
527           0==strcmp(".rodata",sh_strtab+shdr[i].sh_name) ||
528           0==strcmp(".rodata1",sh_strtab+shdr[i].sh_name))
529          kind = HUGS_DL_SECTION_CODE_OR_RODATA;
530       if (kind != HUGS_DL_SECTION_OTHER)
531          addDLSect (
532             m,
533             ehdrC + shdr[i].sh_offset, 
534             ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1,
535             kind
536          );
537
538       if (shdr[i].sh_type != SHT_SYMTAB) continue;
539
540       /* copy stuff into this module's object symbol table */
541       stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
542       nent = shdr[i].sh_size / sizeof(Elf32_Sym);
543       for (j = 0; j < nent; j++) {
544          if ( ( ELF32_ST_BIND(stab[j].st_info)==STB_GLOBAL ||
545                 ELF32_ST_BIND(stab[j].st_info)==STB_LOCAL
546               )
547               &&
548               ( ELF32_ST_TYPE(stab[j].st_info)==STT_FUNC ||
549                 ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT ||
550                 ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE)
551               ) {
552             char* nm = strtab + stab[j].st_name;
553             char* ad = ehdrC 
554                        + shdr[ stab[j].st_shndx ].sh_offset
555                        + stab[j].st_value;
556             assert(nm);
557             assert(ad);
558             if (verb)
559                fprintf(stderr, "addOTabName: %10p  %s %s\n",
560                        ad, textToStr(module(m).text), nm );
561             addSymbol ( oc, nm, ad );
562          }
563          //else fprintf(stderr, "skipping `%s'\n", strtab + stab[j].st_name );
564       }
565
566    }
567 }
568
569
570 static int ocResolve_ELF ( ObjectCode* oc, int verb )
571 {
572    char symbol[1000]; // ToDo
573    char* strtab;
574    int   i, j;
575    Elf32_Sym*  stab = NULL;
576    char*       ehdrC = (char*)(oc->oImage);
577    Elf32_Ehdr* ehdr = (Elf32_Ehdr*) ehdrC;
578    Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
579    Elf32_Word* targ;
580
581    /* first find "the" symbol table */
582    stab = (Elf32_Sym*) findElfSection ( ehdrC, SHT_SYMTAB );
583
584    /* also go find the string table */
585    strtab = findElfSection ( ehdrC, SHT_STRTAB );
586
587    if (!stab || !strtab) {
588       oc->errMsg("can't find string or symbol table");
589       return FALSE; 
590    }
591
592    for (i = 0; i < ehdr->e_shnum; i++) {
593       if (shdr[i].sh_type == SHT_REL ) {
594          Elf32_Rel*  rtab = (Elf32_Rel*) (ehdrC + shdr[i].sh_offset);
595          Int         nent = shdr[i].sh_size / sizeof(Elf32_Rel);
596          Int target_shndx = shdr[i].sh_info;
597          Int symtab_shndx = shdr[i].sh_link;
598          stab  = (Elf32_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
599          targ  = (Elf32_Word*)(ehdrC + shdr[ target_shndx ].sh_offset);
600          if (verb)
601          fprintf ( stderr,
602                   "relocations for section %d using symtab %d\n",
603                   target_shndx, symtab_shndx );
604          for (j = 0; j < nent; j++) {
605             Elf32_Addr offset = rtab[j].r_offset;
606             Elf32_Word info   = rtab[j].r_info;
607
608             Elf32_Addr  P = ((Elf32_Addr)targ) + offset;
609             Elf32_Word* pP = (Elf32_Word*)P;
610             Elf32_Addr  A = *pP;
611             Elf32_Addr  S;
612
613             if (verb) fprintf ( stderr, "Rel entry %3d is raw(%6p %6p)   ", 
614                                 j, (void*)offset, (void*)info );
615             if (!info) {
616                if (verb) fprintf ( stderr, " ZERO\n" );
617                S = 0;
618             } else {
619                /* First see if it is a nameless local symbol. */
620                if (stab[ ELF32_R_SYM(info)].st_name == 0) {
621                   if (verb) fprintf ( stderr, "(noname)  ");
622                   S = (Elf32_Addr)(ehdrC
623                                    + shdr[stab[ELF32_R_SYM(info)].st_shndx ].sh_offset
624                                    + stab[ELF32_R_SYM(info)].st_value
625                                   );
626                   strcpy ( symbol, "(noname)");
627                } else {
628                   /* No?  Perhaps it's a named symbol in this file. */
629                   strcpy ( symbol, strtab+stab[ ELF32_R_SYM(info)].st_name );
630                   if (verb) fprintf ( stderr, "`%s'  ", symbol );
631                   S = (Elf32_Addr)lookupSymbol ( oc, symbol );
632                   if (!S) {
633                      /* No?  Ok, too hard.  Hand the problem to the client. 
634                         And if that fails, we're outta options.
635                      */
636                      S = (Elf32_Addr)(oc->clientLookup ( symbol ) );
637                   }
638                }
639                if (verb) fprintf ( stderr, "resolves to %p\n", (void*)S );
640                if (!S) {
641                   char errtxt[2000];
642                   strcpy(errtxt,oc->objFileName);
643                   strcat(errtxt,": unresolvable reference to: ");
644                   strcat(errtxt,symbol);
645                   oc->errMsg(errtxt);
646                   return FALSE;
647                }
648             }
649             /* fprintf ( stderr, "Reloc: P = %p   S = %p   A = %p\n\n",
650                          (void*)P, (void*)S, (void*)A ); 
651             */
652             switch (ELF32_R_TYPE(info)) {
653                case R_386_32:   *pP = S + A;     break;
654                case R_386_PC32: *pP = S + A - P; break;
655                default: fprintf(stderr, 
656                                 "unhandled ELF relocation type %d\n",
657                                 ELF32_R_TYPE(info));
658                         oc->errMsg("unhandled ELF relocation type");
659                         return FALSE;
660             }
661
662          }
663       }
664       else
665       if (shdr[i].sh_type == SHT_RELA) {
666          oc->errMsg("RelA style reloc table -- not yet done");
667          return FALSE;
668       }
669    }
670
671    return TRUE;
672 }
673
674
675 #endif /* defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) */
676
677
678
679 /*-------------------------------------------------------------------------*/