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.
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.
13 * ------------------------------------------------------------------------*/
19 #include "config.h" /* for linux_TARGET_OS etc */
23 #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
24 static int ocVerifyImage_ELF ( ObjectCode* oc, int verb );
25 static int ocGetNames_ELF ( ObjectCode* oc, int verb );
26 static int ocResolve_ELF ( ObjectCode* oc, int verb );
29 static char* hackyAppend ( char* s1, char* s2 );
30 static int sortSymbols ( ObjectCode* oc );
33 /* --------------------------------------------------------------------------
34 * Arch-independent interface to the runtime linker
35 * ------------------------------------------------------------------------*/
37 ObjectCode* ocNew ( void (*errMsg)(char*),
38 void* (*clientLookup)(char*),
42 ObjectCode* oc = malloc(sizeof(ObjectCode));
44 errMsg("ocNew: can't allocate memory for object code record");
48 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
49 oc->formatName = "ELF";
52 errMsg("ocNew: not implemented on this platform");
56 oc->status = OBJECT_NOTINUSE;
57 oc->objFileName = objFileName;
58 oc->objFileSize = objFileSize;
60 oc->clientLookup = clientLookup;
62 oc->oImage = malloc ( objFileSize );
65 errMsg("ocNew: can't allocate memory for object code");
71 oc->sectionTab = NULL;
72 oc->sizesectionTab = 0;
73 oc->usedsectionTab = 0;
80 int ocLoadImage ( ObjectCode* oc, int verb )
84 assert (oc && oc->status==OBJECT_NOTINUSE);
85 if (verb) fprintf(stderr, "ocLoadImage %s\n", oc->objFileName );
86 f = fopen(oc->objFileName, "rb");
88 (oc->errMsg(hackyAppend("ocLoadImage: can't read: ",
92 n = fread ( oc->oImage, 1, oc->objFileSize, f );
93 if (n != oc->objFileSize) {
95 oc->errMsg(hackyAppend("ocLoadImage: I/O error whilst reading: ",
99 oc->status = OBJECT_OIMAGE;
100 if (verb) fprintf(stderr, "ocLoadImage %s: read %d bytes\n",
101 oc->objFileName, oc->objFileSize );
106 /* returns 1 if ok, 0 if error */
107 int ocVerifyImage ( ObjectCode* oc, int verb )
110 assert (oc && oc->status==OBJECT_OIMAGE);
111 if (verb) fprintf(stderr, "ocVerifyImage: begin\n");
112 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
113 ret = ocVerifyImage_ELF ( oc, verb );
115 oc->errMsg("ocVerifyImage: not implemented on this platform");
118 if (verb) fprintf(stderr, "ocVerifyImage: done, status = %d", ret);
120 if (ret) oc->status = OBJECT_VERIFIED;
125 /* returns 1 if ok, 0 if error */
126 int ocGetNames ( ObjectCode* oc, int verb )
129 assert (oc && oc->status==OBJECT_VERIFIED);
130 if (verb) fprintf(stderr, "ocGetNames: begin\n");
131 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
132 ret = ocGetNames_ELF ( oc, verb );
134 oc->errMsg("ocGetNames: not implemented on this platform");
137 if (verb) fprintf(stderr, "ocGetNames: done, status = %d\n", ret);
138 if (ret) ret = sortSymbols(oc);
139 if (ret) oc->status = OBJECT_HAVENAMES;
144 /* returns 1 if ok, 0 if error */
145 int ocResolve ( ObjectCode* oc, int verb )
148 assert (oc && oc->status==OBJECT_HAVENAMES);
149 if (verb) fprintf(stderr, "ocResolve: begin\n");
150 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
151 ret = ocResolve_ELF ( oc, verb );
153 oc->errMsg("ocResolve: not implemented on this platform");
156 if (verb) fprintf(stderr, "ocResolve: done, status = %d\n", ret);
157 if (ret) oc->status = OBJECT_RESOLVED;
162 void ocFree ( ObjectCode* oc )
165 if (oc->oImage) free(oc->oImage);
166 if (oc->oTab) free(oc->oTab);
167 if (oc->sectionTab) free(oc->sectionTab);
173 /* --------------------------------------------------------------------------
174 * Simple, dynamically expandable association tables
175 * ------------------------------------------------------------------------*/
177 /* A bit tricky. Assumes that if tab==NULL, then
178 currUsed and *currSize must be zero.
179 Returns NULL if expansion failed.
181 static void* genericExpand ( void* tab,
182 int* currSize, int currUsed,
183 int initSize, int elemSize )
187 if (currUsed < *currSize) return tab;
188 size2 = (*currSize == 0) ? initSize : (2 * *currSize);
189 tab2 = malloc ( size2 * elemSize );
190 if (!tab2) return NULL;
192 memcpy ( tab2, tab, elemSize * *currSize );
194 if (tab) free ( tab );
199 /* returns 1 if success, 0 if error */
200 static int addSymbol ( ObjectCode* oc, char* nm, void* ad )
203 = genericExpand ( oc->oTab,
209 oc->errMsg("addSymbol: malloc failed whilst expanding table");
213 oc->oTab[ oc->usedoTab ].nm = nm;
214 oc->oTab[ oc->usedoTab ].ad = ad;
220 /* Reorder symbol table so that symbols are in alphabetical order.
221 Detects an error if, after sorting, any two symbols are the same,
222 since this would imply that the same symbol has been inserted more
223 than once. Returns 1 if success, 0 if error.
225 static int sortSymbols ( ObjectCode* oc )
228 = { 1, 4, 13, 40, 121, 364, 1093, 3280,
229 9841, 29524, 88573, 265720, 797161, 2391484 };
232 int hi = oc->usedoTab-1;
233 int i, j, h, bigN, hp;
236 bigN = hi - lo + 1; if (bigN < 2) return 1;
237 hp = 0; while (incs[hp] < bigN) hp++; hp--;
239 for (; hp >= 0; hp--) {
246 while (strcmp(oc->oTab[j-h].nm, v.nm) > 0) {
247 oc->oTab[j] = oc->oTab[j-h];
249 if (j <= (lo + h - 1)) break;
256 for (i = 1; i < oc->usedoTab; i++) {
257 j = strcmp(oc->oTab[i-1].nm, oc->oTab[i].nm);
259 oc->errMsg("sortSymbols: sorting failed");
263 oc->errMsg("sortSymbols: duplicate symbols in object file");
272 /* returns 1 if success, 0 if error */
273 static int addSection ( ObjectCode* oc, void* start, void* end, OSectionKind sect )
276 = genericExpand ( oc->sectionTab,
277 &(oc->sizesectionTab),
279 4, sizeof(OSection) );
281 oc->errMsg("addSection: malloc failed whilst expanding table");
284 oc->sectionTab = newTab;
285 oc->sectionTab[ oc->usedsectionTab ].start = start;
286 oc->sectionTab[ oc->usedsectionTab ].end = end;
287 oc->sectionTab[ oc->usedsectionTab ].kind = sect;
288 oc->usedsectionTab++;
293 void* ocLookupSym ( ObjectCode* oc, char* sym )
295 int lo, hi, mid, cmp;
298 if (oc->status != OBJECT_HAVENAMES
299 && oc->status != OBJECT_RESOLVED) {
300 oc->errMsg("ocLookupSym: no symbols available");
304 /* Originally used a sequential search; should still work
305 for (i = 0; i < oc->usedoTab; i++) {
308 "ocLookupSym: request %s, table has %s\n",
309 sym, oc->oTab[i].nm );
310 if (0==strcmp(sym,oc->oTab[i].nm))
311 return oc->oTab[i].ad;
318 /* Invariant: the unsearched area is oc->oTab[lo .. hi] inclusive. */
319 if (hi < lo) return NULL;
321 cmp = strcmp(sym, oc->oTab[mid].nm);
322 if (cmp == 0) return oc->oTab[mid].ad;
323 if (cmp < 0) hi = mid-1;
324 if (cmp > 0) lo = mid+1;
329 char* ocLookupAddr ( ObjectCode* oc, void* addr )
334 if (oc->status != OBJECT_HAVENAMES
335 && oc->status != OBJECT_RESOLVED) {
336 oc->errMsg("ocLookupAddr: no symbols available");
340 for (i = 0; i < oc->usedoTab; i++) {
341 if (addr == oc->oTab[i].ad)
342 return oc->oTab[i].nm;
348 OSectionKind ocLookupSection ( ObjectCode* oc, void* addr )
353 if (oc->status != OBJECT_HAVENAMES
354 && oc->status != OBJECT_RESOLVED) {
355 oc->errMsg("ocLookupSection: no symbols available");
356 return HUGS_SECTIONKIND_NOINFOAVAIL;
360 for (i = 0; i < oc->usedsectionTab; i++) {
361 if (oc->sectionTab[i].start <= addr
362 && addr <= oc->sectionTab[i].end)
363 return oc->sectionTab[i].kind;
366 return HUGS_SECTIONKIND_NOINFOAVAIL;
370 /* Ghastly append which leaks space. But we only use it for
371 error messages -- that's my excuse.
373 static char* hackyAppend ( char* s1, char* s2 )
375 char* res = malloc ( 4 + strlen(s1) + strlen(s2) );
377 fprintf ( stderr, "hugs: fatal: hackyAppend\n\t%s\n\t%s\n", s1, s2 );
385 /* --------------------------------------------------------------------------
387 * ------------------------------------------------------------------------*/
392 #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
396 static char* findElfSection ( void* objImage, Elf32_Word sh_type )
399 char* ehdrC = (char*)objImage;
400 Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
401 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
403 for (i = 0; i < ehdr->e_shnum; i++) {
404 if (shdr[i].sh_type == sh_type &&
405 i != ehdr->e_shstrndx) {
406 ptr = ehdrC + shdr[i].sh_offset;
414 static int ocVerifyImage_ELF ( ObjectCode* oc, int verb )
418 int i, j, nent, nstrtab, nsymtabs;
422 char* ehdrC = (char*)(oc->oImage);
423 Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
425 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
426 ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
427 ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
428 ehdr->e_ident[EI_MAG3] != ELFMAG3) {
429 oc->errMsg("Not an ELF header");
432 if (verb) fprintf ( stderr, "Is an ELF header\n" );
434 if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
435 oc->errMsg("Not 32 bit ELF" );
438 if (verb) fprintf ( stderr, "Is 32 bit ELF\n" );
440 if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
441 if (verb) fprintf ( stderr, "Is little-endian\n" );
443 if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
444 if (verb) fprintf ( stderr, "Is big-endian\n" );
446 oc->errMsg("Unknown endiannness");
450 if (ehdr->e_type != ET_REL) {
451 oc->errMsg("Not a relocatable object (.o) file");
454 if (verb) fprintf ( stderr, "Is a relocatable object (.o) file\n" );
456 if (verb) fprintf ( stderr, "Architecture is " );
457 switch (ehdr->e_machine) {
458 case EM_386: if (verb) fprintf ( stderr, "x86\n" ); break;
459 case EM_SPARC: if (verb) fprintf ( stderr, "sparc\n" ); break;
460 default: if (verb) fprintf ( stderr, "unknown\n" );
461 oc->errMsg("Unknown architecture");
467 "\nSection header table: start %d, n_entries %d, ent_size %d\n",
468 ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize );
470 assert (ehdr->e_shentsize == sizeof(Elf32_Shdr));
472 shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
474 if (ehdr->e_shstrndx == SHN_UNDEF) {
475 oc->errMsg("No section header string table");
478 if (verb) fprintf ( stderr,"Section header string table is section %d\n",
480 sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
483 for (i = 0; i < ehdr->e_shnum; i++) {
484 if (verb) fprintf ( stderr, "%2d: ", i );
485 if (verb) fprintf ( stderr, "type=%2d ", shdr[i].sh_type );
486 if (verb) fprintf ( stderr, "size=%4d ", shdr[i].sh_size );
487 if (verb) fprintf ( stderr, "offs=%4d ", shdr[i].sh_offset );
488 if (verb) fprintf ( stderr, " (%p .. %p) ",
489 ehdrC + shdr[i].sh_offset,
490 ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1);
492 if (shdr[i].sh_type == SHT_REL && verb) fprintf ( stderr, "Rel " ); else
493 if (shdr[i].sh_type == SHT_RELA && verb) fprintf ( stderr, "RelA " ); else
494 if (verb) fprintf ( stderr, " " );
495 if (sh_strtab && verb)
496 fprintf ( stderr, "sname=%s", sh_strtab + shdr[i].sh_name );
497 if (verb) fprintf ( stderr, "\n" );
500 if (verb) fprintf ( stderr, "\n\nString tables\n" );
503 for (i = 0; i < ehdr->e_shnum; i++) {
504 if (shdr[i].sh_type == SHT_STRTAB &&
505 i != ehdr->e_shstrndx) {
507 fprintf ( stderr, " section %d is a normal string table\n", i );
508 strtab = ehdrC + shdr[i].sh_offset;
513 oc->errMsg("WARNING: no string tables, or too many");
518 if (verb) fprintf ( stderr, "\n\nSymbol tables\n" );
519 for (i = 0; i < ehdr->e_shnum; i++) {
520 if (shdr[i].sh_type != SHT_SYMTAB) continue;
521 if (verb) fprintf ( stderr, "section %d is a symbol table\n", i );
523 stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
524 nent = shdr[i].sh_size / sizeof(Elf32_Sym);
525 if (verb) fprintf ( stderr, " number of entries is apparently %d (%d rem)\n",
527 shdr[i].sh_size % sizeof(Elf32_Sym)
529 if (0 != shdr[i].sh_size % sizeof(Elf32_Sym)) {
530 oc->errMsg("non-integral number of symbol table entries");
533 for (j = 0; j < nent; j++) {
534 if (verb) fprintf ( stderr, " %2d ", j );
535 if (verb) fprintf ( stderr, " sec=%-5d size=%-3d val=%-5p ",
536 (int)stab[j].st_shndx,
537 (int)stab[j].st_size,
538 (char*)stab[j].st_value );
540 if (verb) fprintf ( stderr, "type=" );
541 switch (ELF32_ST_TYPE(stab[j].st_info)) {
542 case STT_NOTYPE: if (verb) fprintf ( stderr, "notype " ); break;
543 case STT_OBJECT: if (verb) fprintf ( stderr, "object " ); break;
544 case STT_FUNC : if (verb) fprintf ( stderr, "func " ); break;
545 case STT_SECTION: if (verb) fprintf ( stderr, "section" ); break;
546 case STT_FILE: if (verb) fprintf ( stderr, "file " ); break;
547 default: if (verb) fprintf ( stderr, "? " ); break;
549 if (verb) fprintf ( stderr, " " );
551 if (verb) fprintf ( stderr, "bind=" );
552 switch (ELF32_ST_BIND(stab[j].st_info)) {
553 case STB_LOCAL : if (verb) fprintf ( stderr, "local " ); break;
554 case STB_GLOBAL: if (verb) fprintf ( stderr, "global" ); break;
555 case STB_WEAK : if (verb) fprintf ( stderr, "weak " ); break;
556 default: if (verb) fprintf ( stderr, "? " ); break;
558 if (verb) fprintf ( stderr, " " );
560 if (verb) fprintf ( stderr, "name=%s\n", strtab + stab[j].st_name );
565 oc->errMsg("Didn't find any symbol tables");
573 static int ocGetNames_ELF ( ObjectCode* oc, int verb )
578 char* ehdrC = (char*)(oc->oImage);
579 Elf32_Ehdr* ehdr = (Elf32_Ehdr*)ehdrC;
580 char* strtab = findElfSection ( ehdrC, SHT_STRTAB );
581 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
582 char* sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
585 oc->errMsg("no strtab!");
590 for (i = 0; i < ehdr->e_shnum; i++) {
592 /* make a HugsDLSection entry for relevant sections */
593 OSectionKind kind = HUGS_SECTIONKIND_OTHER;
594 if (0==strcmp(".data",sh_strtab+shdr[i].sh_name) ||
595 0==strcmp(".data1",sh_strtab+shdr[i].sh_name))
596 kind = HUGS_SECTIONKIND_RWDATA;
597 if (0==strcmp(".text",sh_strtab+shdr[i].sh_name) ||
598 0==strcmp(".rodata",sh_strtab+shdr[i].sh_name) ||
599 0==strcmp(".rodata1",sh_strtab+shdr[i].sh_name))
600 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
601 if (kind != HUGS_SECTIONKIND_OTHER)
604 ehdrC + shdr[i].sh_offset,
605 ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1,
609 if (shdr[i].sh_type != SHT_SYMTAB) continue;
611 /* copy stuff into this module's object symbol table */
612 stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
613 nent = shdr[i].sh_size / sizeof(Elf32_Sym);
614 for (j = 0; j < nent; j++) {
615 if ( ( ELF32_ST_BIND(stab[j].st_info)==STB_GLOBAL ||
616 ELF32_ST_BIND(stab[j].st_info)==STB_LOCAL
619 ( ELF32_ST_TYPE(stab[j].st_info)==STT_FUNC ||
620 ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT)
621 /* || ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE */
623 char* nm = strtab + stab[j].st_name;
625 + shdr[ stab[j].st_shndx ].sh_offset
630 fprintf(stderr, "addOTabName: %10p %s %s\n",
631 ad, oc->objFileName, nm );
632 if (!addSymbol ( oc, nm, ad )) return FALSE;
635 else fprintf(stderr, "skipping `%s'\n", strtab + stab[j].st_name );
644 static int ocResolve_ELF ( ObjectCode* oc, int verb )
646 char symbol[1000]; // ToDo
649 Elf32_Sym* stab = NULL;
650 char* ehdrC = (char*)(oc->oImage);
651 Elf32_Ehdr* ehdr = (Elf32_Ehdr*) ehdrC;
652 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
655 /* first find "the" symbol table */
656 stab = (Elf32_Sym*) findElfSection ( ehdrC, SHT_SYMTAB );
658 /* also go find the string table */
659 strtab = findElfSection ( ehdrC, SHT_STRTAB );
661 if (!stab || !strtab) {
662 oc->errMsg("can't find string or symbol table");
666 for (i = 0; i < ehdr->e_shnum; i++) {
667 if (shdr[i].sh_type == SHT_REL ) {
668 Elf32_Rel* rtab = (Elf32_Rel*) (ehdrC + shdr[i].sh_offset);
669 int nent = shdr[i].sh_size / sizeof(Elf32_Rel);
670 int target_shndx = shdr[i].sh_info;
671 int symtab_shndx = shdr[i].sh_link;
672 stab = (Elf32_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
673 targ = (Elf32_Word*)(ehdrC + shdr[ target_shndx ].sh_offset);
676 "relocations for section %d using symtab %d\n",
677 target_shndx, symtab_shndx );
678 for (j = 0; j < nent; j++) {
679 Elf32_Addr offset = rtab[j].r_offset;
680 Elf32_Word info = rtab[j].r_info;
682 Elf32_Addr P = ((Elf32_Addr)targ) + offset;
683 Elf32_Word* pP = (Elf32_Word*)P;
687 if (verb) fprintf ( stderr, "Rel entry %3d is raw(%6p %6p) ",
688 j, (void*)offset, (void*)info );
690 if (verb) fprintf ( stderr, " ZERO\n" );
693 /* First see if it is a nameless local symbol. */
694 if (stab[ ELF32_R_SYM(info)].st_name == 0) {
695 if (verb) fprintf ( stderr, "(noname) ");
696 S = (Elf32_Addr)(ehdrC
697 + shdr[stab[ELF32_R_SYM(info)].st_shndx ].sh_offset
698 + stab[ELF32_R_SYM(info)].st_value
700 strcpy ( symbol, "(noname)");
702 /* No? Perhaps it's a named symbol in this file. */
703 strcpy ( symbol, strtab+stab[ ELF32_R_SYM(info)].st_name );
704 if (verb) fprintf ( stderr, "`%s' ", symbol );
705 S = (Elf32_Addr)ocLookupSym ( oc, symbol );
707 /* No? Ok, too hard. Hand the problem to the client.
708 And if that fails, we're outta options.
710 S = (Elf32_Addr)(oc->clientLookup ( symbol ) );
713 if (verb) fprintf ( stderr, "resolves to %p\n", (void*)S );
716 strcpy(errtxt,oc->objFileName);
717 strcat(errtxt,": unresolvable reference to: ");
718 strcat(errtxt,symbol);
723 /* fprintf ( stderr, "Reloc: P = %p S = %p A = %p\n\n",
724 (void*)P, (void*)S, (void*)A );
726 switch (ELF32_R_TYPE(info)) {
727 case R_386_32: *pP = S + A; break;
728 case R_386_PC32: *pP = S + A - P; break;
729 default: fprintf(stderr,
730 "unhandled ELF relocation type %d\n",
732 oc->errMsg("unhandled ELF relocation type");
739 if (shdr[i].sh_type == SHT_RELA) {
740 oc->errMsg("RelA style reloc table -- not yet done");
749 #endif /* defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) */
753 /*-------------------------------------------------------------------------*/