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 );
27 #elif defined(cygwin32_TARGET_OS)
28 static int ocVerifyImage_PEi386 ( ObjectCode* oc, int verb );
29 static int ocGetNames_PEi386 ( ObjectCode* oc, int verb );
30 static int ocResolve_PEi386 ( ObjectCode* oc, int verb );
33 static char* hackyAppend ( char* s1, char* s2 );
34 static int sortSymbols ( ObjectCode* oc );
37 /* --------------------------------------------------------------------------
38 * Arch-independent interface to the runtime linker
39 * ------------------------------------------------------------------------*/
41 ObjectCode* ocNew ( void (*errMsg)(char*),
42 void* (*clientLookup)(char*),
46 ObjectCode* oc = malloc(sizeof(ObjectCode));
48 errMsg("ocNew: can't allocate memory for object code record");
52 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
53 oc->formatName = "ELF";
54 # elif defined(cygwin32_TARGET_OS)
55 oc->formatName = "PEi386";
58 errMsg("ocNew: not implemented on this platform");
62 oc->status = OBJECT_NOTINUSE;
63 oc->objFileName = objFileName;
64 oc->objFileSize = objFileSize;
66 oc->clientLookup = clientLookup;
68 oc->oImage = malloc ( objFileSize );
71 errMsg("ocNew: can't allocate memory for object code");
77 oc->sectionTab = NULL;
78 oc->sizesectionTab = 0;
79 oc->usedsectionTab = 0;
86 int ocLoadImage ( ObjectCode* oc, int verb )
90 assert (oc && oc->status==OBJECT_NOTINUSE);
91 if (verb) fprintf(stderr, "ocLoadImage %s\n", oc->objFileName );
92 f = fopen(oc->objFileName, "rb");
94 (oc->errMsg(hackyAppend("ocLoadImage: can't read: ",
98 n = fread ( oc->oImage, 1, oc->objFileSize, f );
99 if (n != oc->objFileSize) {
101 oc->errMsg(hackyAppend("ocLoadImage: I/O error whilst reading: ",
105 oc->status = OBJECT_OIMAGE;
106 if (verb) fprintf(stderr, "ocLoadImage %s: read %d bytes\n",
107 oc->objFileName, oc->objFileSize );
112 /* returns 1 if ok, 0 if error */
113 int ocVerifyImage ( ObjectCode* oc, int verb )
116 assert (oc && oc->status==OBJECT_OIMAGE);
117 if (verb) fprintf(stderr, "ocVerifyImage: begin\n");
118 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
119 ret = ocVerifyImage_ELF ( oc, verb );
120 # elif defined(cygwin32_TARGET_OS)
121 ret = ocVerifyImage_PEi386 ( oc, verb );
123 oc->errMsg("ocVerifyImage: not implemented on this platform");
126 if (verb) fprintf(stderr, "ocVerifyImage: done, status = %d", ret);
128 if (ret) oc->status = OBJECT_VERIFIED;
133 /* returns 1 if ok, 0 if error */
134 int ocGetNames ( ObjectCode* oc, int verb )
137 assert (oc && oc->status==OBJECT_VERIFIED);
138 if (verb) fprintf(stderr, "ocGetNames: begin\n");
139 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
140 ret = ocGetNames_ELF ( oc, verb );
141 # elif defined(cygwin32_TARGET_OS)
142 ret = ocGetNames_PEi386 ( oc, verb );
144 oc->errMsg("ocGetNames: not implemented on this platform");
147 if (verb) fprintf(stderr, "ocGetNames: done, status = %d\n", ret);
148 if (ret) ret = sortSymbols(oc);
149 if (ret) oc->status = OBJECT_HAVENAMES;
154 /* returns 1 if ok, 0 if error */
155 int ocResolve ( ObjectCode* oc, int verb )
158 assert (oc && oc->status==OBJECT_HAVENAMES);
159 if (verb) fprintf(stderr, "ocResolve: begin\n");
160 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
161 ret = ocResolve_ELF ( oc, verb );
162 # elif defined(cygwin32_TARGET_OS)
163 ret = ocResolve_PEi386 ( oc, verb );
165 oc->errMsg("ocResolve: not implemented on this platform");
168 if (verb) fprintf(stderr, "ocResolve: done, status = %d\n", ret);
169 if (ret) oc->status = OBJECT_RESOLVED;
174 void ocFree ( ObjectCode* oc )
177 if (oc->oImage) free(oc->oImage);
178 if (oc->oTab) free(oc->oTab);
179 if (oc->sectionTab) free(oc->sectionTab);
185 /* --------------------------------------------------------------------------
186 * Simple, dynamically expandable association tables
187 * ------------------------------------------------------------------------*/
189 /* A bit tricky. Assumes that if tab==NULL, then
190 currUsed and *currSize must be zero.
191 Returns NULL if expansion failed.
193 static void* genericExpand ( void* tab,
194 int* currSize, int currUsed,
195 int initSize, int elemSize )
199 if (currUsed < *currSize) return tab;
200 size2 = (*currSize == 0) ? initSize : (2 * *currSize);
201 tab2 = malloc ( size2 * elemSize );
202 if (!tab2) return NULL;
204 memcpy ( tab2, tab, elemSize * *currSize );
206 if (tab) free ( tab );
211 /* returns 1 if success, 0 if error */
212 static int addSymbol ( ObjectCode* oc, char* nm, void* ad )
215 = genericExpand ( oc->oTab,
221 oc->errMsg("addSymbol: malloc failed whilst expanding table");
225 oc->oTab[ oc->usedoTab ].nm = nm;
226 oc->oTab[ oc->usedoTab ].ad = ad;
232 /* Reorder symbol table so that symbols are in alphabetical order.
233 Detects an error if, after sorting, any two symbols are the same,
234 since this would imply that the same symbol has been inserted more
235 than once. Returns 1 if success, 0 if error.
237 static int sortSymbols ( ObjectCode* oc )
240 = { 1, 4, 13, 40, 121, 364, 1093, 3280,
241 9841, 29524, 88573, 265720, 797161, 2391484 };
244 int hi = oc->usedoTab-1;
245 int i, j, h, bigN, hp;
248 bigN = hi - lo + 1; if (bigN < 2) return 1;
249 hp = 0; while (incs[hp] < bigN) hp++; hp--;
251 for (; hp >= 0; hp--) {
258 while (strcmp(oc->oTab[j-h].nm, v.nm) > 0) {
259 oc->oTab[j] = oc->oTab[j-h];
261 if (j <= (lo + h - 1)) break;
268 for (i = 1; i < oc->usedoTab; i++) {
269 j = strcmp(oc->oTab[i-1].nm, oc->oTab[i].nm);
271 oc->errMsg("sortSymbols: sorting failed");
275 oc->errMsg("sortSymbols: duplicate symbols in object file");
284 /* returns 1 if success, 0 if error */
285 static int addSection ( ObjectCode* oc, void* start, void* end, OSectionKind sect )
288 = genericExpand ( oc->sectionTab,
289 &(oc->sizesectionTab),
291 4, sizeof(OSection) );
293 oc->errMsg("addSection: malloc failed whilst expanding table");
296 oc->sectionTab = newTab;
297 oc->sectionTab[ oc->usedsectionTab ].start = start;
298 oc->sectionTab[ oc->usedsectionTab ].end = end;
299 oc->sectionTab[ oc->usedsectionTab ].kind = sect;
300 oc->usedsectionTab++;
305 void* ocLookupSym ( ObjectCode* oc, char* sym )
307 int lo, hi, mid, cmp;
310 if (oc->status != OBJECT_HAVENAMES
311 && oc->status != OBJECT_RESOLVED) {
312 oc->errMsg("ocLookupSym: no symbols available");
316 /* Originally used a sequential search; should still work
317 for (i = 0; i < oc->usedoTab; i++) {
320 "ocLookupSym: request %s, table has %s\n",
321 sym, oc->oTab[i].nm );
322 if (0==strcmp(sym,oc->oTab[i].nm))
323 return oc->oTab[i].ad;
330 /* Invariant: the unsearched area is oc->oTab[lo .. hi] inclusive. */
331 if (hi < lo) return NULL;
333 cmp = strcmp(sym, oc->oTab[mid].nm);
334 if (cmp == 0) return oc->oTab[mid].ad;
335 if (cmp < 0) hi = mid-1;
336 if (cmp > 0) lo = mid+1;
341 char* ocLookupAddr ( ObjectCode* oc, void* addr )
346 if (oc->status != OBJECT_HAVENAMES
347 && oc->status != OBJECT_RESOLVED) {
348 oc->errMsg("ocLookupAddr: no symbols available");
352 for (i = 0; i < oc->usedoTab; i++) {
353 if (addr == oc->oTab[i].ad)
354 return oc->oTab[i].nm;
360 OSectionKind ocLookupSection ( ObjectCode* oc, void* addr )
365 if (oc->status != OBJECT_HAVENAMES
366 && oc->status != OBJECT_RESOLVED) {
367 oc->errMsg("ocLookupSection: no symbols available");
368 return HUGS_SECTIONKIND_NOINFOAVAIL;
372 for (i = 0; i < oc->usedsectionTab; i++) {
373 if (oc->sectionTab[i].start <= addr
374 && addr <= oc->sectionTab[i].end)
375 return oc->sectionTab[i].kind;
378 return HUGS_SECTIONKIND_NOINFOAVAIL;
382 /* Ghastly append which leaks space. But we only use it for
383 error messages -- that's my excuse.
385 static char* hackyAppend ( char* s1, char* s2 )
387 char* res = malloc ( 4 + strlen(s1) + strlen(s2) );
389 fprintf ( stderr, "hugs: fatal: hackyAppend\n\t%s\n\t%s\n", s1, s2 );
397 /* --------------------------------------------------------------------------
398 * PEi386 specifics (cygwin32)
399 * ------------------------------------------------------------------------*/
401 /* The information for this linker comes from
402 Microsoft Portable Executable
403 and Common Object File Format Specification
404 revision 5.1 January 1998
405 which SimonM says comes from the MS Developer Network CDs.
409 #if defined(cygwin32_TARGET_OS)
415 typedef unsigned char UChar;
416 typedef unsigned short UInt16;
417 typedef unsigned int UInt32;
424 UInt16 NumberOfSections;
425 UInt32 TimeDateStamp;
426 UInt32 PointerToSymbolTable;
427 UInt32 NumberOfSymbols;
428 UInt16 SizeOfOptionalHeader;
429 UInt16 Characteristics;
433 #define sizeof_COFF_header 20
440 UInt32 VirtualAddress;
441 UInt32 SizeOfRawData;
442 UInt32 PointerToRawData;
443 UInt32 PointerToRelocations;
444 UInt32 PointerToLinenumbers;
445 UInt16 NumberOfRelocations;
446 UInt16 NumberOfLineNumbers;
447 UInt32 Characteristics;
451 #define sizeof_COFF_section 40
458 UInt16 SectionNumber;
461 UChar NumberOfAuxSymbols;
465 #define sizeof_COFF_symbol 18
470 UInt32 VirtualAddress;
471 UInt32 SymbolTableIndex;
476 #define sizeof_COFF_reloc 10
479 /* From PE spec doc, section 3.3.2 */
480 #define IMAGE_FILE_RELOCS_STRIPPED 0x0001
481 #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
482 #define IMAGE_FILE_DLL 0x2000
483 #define IMAGE_FILE_SYSTEM 0x1000
484 #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
485 #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
486 #define IMAGE_FILE_32BIT_MACHINE 0x0100
488 /* From PE spec doc, section 5.4.2 and 5.4.4 */
489 #define IMAGE_SYM_CLASS_EXTERNAL 2
490 #define IMAGE_SYM_UNDEFINED 0
492 /* From PE spec doc, section 4.1 */
493 #define IMAGE_SCN_CNT_CODE 0x00000020
494 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
497 /* We use myindex to calculate array addresses, rather than
498 simply doing the normal subscript thing. That's because
499 some of the above structs have sizes which are not
500 a whole number of words. GCC rounds their sizes up to a
501 whole number of words, which means that the address calcs
502 arising from using normal C indexing or pointer arithmetic
503 are just plain wrong. Sigh.
505 static UChar* myindex ( int scale, int index, void* base )
508 ((UChar*)base) + scale * index;
512 static void printName ( UChar* name, UChar* strtab )
514 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
515 UInt32 strtab_offset = * (UInt32*)(name+4);
516 fprintf ( stderr, "%s", strtab + strtab_offset );
519 for (i = 0; i < 8; i++) {
520 if (name[i] == 0) break;
521 fprintf ( stderr, "%c", name[i] );
527 static int ocVerifyImage_PEi386 ( ObjectCode* oc, int verb )
531 COFF_section* sectab;
535 hdr = (COFF_header*)(oc->oImage);
536 sectab = (COFF_section*) (
537 ((UChar*)(oc->oImage))
538 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
540 symtab = (COFF_symbol*) (
541 ((UChar*)(oc->oImage))
542 + hdr->PointerToSymbolTable
544 strtab = ((UChar*)(oc->oImage))
545 + hdr->PointerToSymbolTable
546 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
548 if (hdr->Machine != 0x14c) {
549 oc->errMsg("Not x86 PEi386");
552 if (hdr->SizeOfOptionalHeader != 0) {
553 oc->errMsg("PEi386 with nonempty optional header");
556 if ( (hdr->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) ||
557 (hdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) ||
558 (hdr->Characteristics & IMAGE_FILE_DLL) ||
559 (hdr->Characteristics & IMAGE_FILE_SYSTEM) ) {
560 oc->errMsg("Not a PEi386 object file");
563 if ( (hdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI) ||
564 !(hdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_LO) ||
565 !(hdr->Characteristics & IMAGE_FILE_32BIT_MACHINE) ) {
566 oc->errMsg("Invalid PEi386 word size or endiannness");
570 if (!verb) return TRUE;
571 /* No further verification after this point; only debug printing. */
574 "sectab offset = %d\n", ((UChar*)sectab) - ((UChar*)hdr) );
576 "symtab offset = %d\n", ((UChar*)symtab) - ((UChar*)hdr) );
578 "strtab offset = %d\n", ((UChar*)strtab) - ((UChar*)hdr) );
580 fprintf ( stderr, "\n" );
582 "Machine: 0x%x\n", (UInt32)(hdr->Machine) );
584 "# sections: %d\n", (UInt32)(hdr->NumberOfSections) );
586 "time/date: 0x%x\n", (UInt32)(hdr->TimeDateStamp) );
588 "symtab offset: %d\n", (UInt32)(hdr->PointerToSymbolTable) );
590 "# symbols: %d\n", (UInt32)(hdr->NumberOfSymbols) );
592 "sz of opt hdr: %d\n", (UInt32)(hdr->SizeOfOptionalHeader) );
594 "characteristics: 0x%x\n", (UInt32)(hdr->Characteristics) );
596 fprintf ( stderr, "\n" );
597 fprintf ( stderr, "string table has size 0x%x\n", * (UInt32*)strtab );
598 fprintf ( stderr, "---START of string table---\n");
599 for (i = 4; i < *(UInt32*)strtab; i++) {
601 fprintf ( stderr, "\n"); else
602 fprintf( stderr, "%c", strtab[i] );
604 fprintf ( stderr, "--- END of string table---\n");
606 fprintf ( stderr, "\n" );
607 for (i = 0; i < hdr->NumberOfSections; i++) {
609 COFF_section* sectab_i
611 myindex ( sizeof_COFF_section, i, sectab );
618 printName ( sectab_i->Name, strtab );
627 sectab_i->VirtualSize,
628 sectab_i->VirtualAddress,
629 sectab_i->SizeOfRawData,
630 sectab_i->PointerToRawData,
631 sectab_i->NumberOfRelocations,
632 sectab_i->PointerToRelocations
634 reltab = (COFF_reloc*) (
635 ((UChar*)(oc->oImage)) + sectab_i->PointerToRelocations
637 for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
639 COFF_reloc* rel = (COFF_reloc*)
640 myindex ( sizeof_COFF_reloc, j, reltab );
642 " type 0x%-4x vaddr 0x%-8x name `",
644 rel->VirtualAddress );
646 myindex ( sizeof_COFF_symbol, rel->SymbolTableIndex, symtab );
647 printName ( sym->Name, strtab );
648 fprintf ( stderr, "'\n" );
650 fprintf ( stderr, "\n" );
654 fprintf ( stderr, "\n" );
657 COFF_symbol* symtab_i;
658 if (i >= hdr->NumberOfSymbols) break;
659 symtab_i = (COFF_symbol*)
660 myindex ( sizeof_COFF_symbol, i, symtab );
666 printName ( symtab_i->Name, strtab );
675 (Int32)(symtab_i->SectionNumber) - 1,
676 (UInt32)symtab_i->Type,
677 (UInt32)symtab_i->StorageClass,
678 (UInt32)symtab_i->NumberOfAuxSymbols
680 i += symtab_i->NumberOfAuxSymbols;
684 fprintf ( stderr, "\n" );
690 static UChar* cstring_from_COFF_symbol_name ( UChar* name,
694 /* If the string is longer than 8 bytes, look in the
695 string table for it -- this will be correctly zero terminated.
697 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
698 UInt32 strtab_offset = * (UInt32*)(name+4);
699 return ((UChar*)strtab) + strtab_offset;
701 /* Otherwise, if shorter than 8 bytes, return the original,
702 which by defn is correctly terminated.
704 if (name[7]==0) return name;
705 /* The annoying case: 8 bytes. Copy into a temporary
706 (which is never freed ...)
710 strncpy(newstr,name,8);
717 static int ocGetNames_PEi386 ( ObjectCode* oc, int verb )
720 COFF_section* sectab;
728 hdr = (COFF_header*)(oc->oImage);
729 sectab = (COFF_section*) (
730 ((UChar*)(oc->oImage))
731 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
733 symtab = (COFF_symbol*) (
734 ((UChar*)(oc->oImage))
735 + hdr->PointerToSymbolTable
737 strtab = ((UChar*)(oc->oImage))
738 + hdr->PointerToSymbolTable
739 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
741 /* Copy exported symbols into the ObjectCode. */
744 COFF_symbol* symtab_i;
745 if (i >= hdr->NumberOfSymbols) break;
746 symtab_i = (COFF_symbol*)
747 myindex ( sizeof_COFF_symbol, i, symtab );
749 if (symtab_i->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
750 symtab_i->SectionNumber != IMAGE_SYM_UNDEFINED) {
752 /* This symbol is global and defined, viz, exported */
753 COFF_section* sectabent;
755 sname = cstring_from_COFF_symbol_name (
756 symtab_i->Name, strtab
759 oc->errMsg("Out of memory when copying PEi386 symbol");
763 /* for IMAGE_SYMCLASS_EXTERNAL
764 && !IMAGE_SYM_UNDEFINED,
765 the address of the symbol is:
766 address of relevant section + offset in section
768 sectabent = (COFF_section*)
769 myindex ( sizeof_COFF_section,
770 symtab_i->SectionNumber-1,
772 addr = ((UChar*)(oc->oImage))
773 + sectabent->PointerToRawData
776 if (!addSymbol(oc,sname,addr)) return FALSE;
778 i += symtab_i->NumberOfAuxSymbols;
782 /* Copy section information into the ObjectCode. */
783 for (i = 0; i < hdr->NumberOfSections; i++) {
788 = HUGS_SECTIONKIND_OTHER;
789 COFF_section* sectab_i
791 myindex ( sizeof_COFF_section, i, sectab );
793 if (sectab_i->Characteristics & IMAGE_SCN_CNT_CODE ||
794 sectab_i->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
795 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
797 start = ((UChar*)(oc->oImage))
798 + sectab_i->PointerToRawData;
800 + sectab_i->SizeOfRawData - 1;
801 addSection ( oc, start, end, kind );
808 static int ocResolve_PEi386 ( ObjectCode* oc, int verb )
813 #endif /* defined(cygwin32_TARGET_OS) */
816 /* --------------------------------------------------------------------------
817 * ELF specifics (Linux, Solaris)
818 * ------------------------------------------------------------------------*/
820 #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
827 static char* findElfSection ( void* objImage, Elf32_Word sh_type )
830 char* ehdrC = (char*)objImage;
831 Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
832 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
834 for (i = 0; i < ehdr->e_shnum; i++) {
835 if (shdr[i].sh_type == sh_type &&
836 i != ehdr->e_shstrndx) {
837 ptr = ehdrC + shdr[i].sh_offset;
845 static int ocVerifyImage_ELF ( ObjectCode* oc, int verb )
849 int i, j, nent, nstrtab, nsymtabs;
853 char* ehdrC = (char*)(oc->oImage);
854 Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
856 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
857 ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
858 ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
859 ehdr->e_ident[EI_MAG3] != ELFMAG3) {
860 oc->errMsg("Not an ELF header");
863 if (verb) fprintf ( stderr, "Is an ELF header\n" );
865 if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
866 oc->errMsg("Not 32 bit ELF" );
869 if (verb) fprintf ( stderr, "Is 32 bit ELF\n" );
871 if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
872 if (verb) fprintf ( stderr, "Is little-endian\n" );
874 if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
875 if (verb) fprintf ( stderr, "Is big-endian\n" );
877 oc->errMsg("Unknown endiannness");
881 if (ehdr->e_type != ET_REL) {
882 oc->errMsg("Not a relocatable object (.o) file");
885 if (verb) fprintf ( stderr, "Is a relocatable object (.o) file\n" );
887 if (verb) fprintf ( stderr, "Architecture is " );
888 switch (ehdr->e_machine) {
889 case EM_386: if (verb) fprintf ( stderr, "x86\n" ); break;
890 case EM_SPARC: if (verb) fprintf ( stderr, "sparc\n" ); break;
891 default: if (verb) fprintf ( stderr, "unknown\n" );
892 oc->errMsg("Unknown architecture");
898 "\nSection header table: start %d, n_entries %d, ent_size %d\n",
899 ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize );
901 assert (ehdr->e_shentsize == sizeof(Elf32_Shdr));
903 shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
905 if (ehdr->e_shstrndx == SHN_UNDEF) {
906 oc->errMsg("No section header string table");
909 if (verb) fprintf ( stderr,"Section header string table is section %d\n",
911 sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
914 for (i = 0; i < ehdr->e_shnum; i++) {
915 if (verb) fprintf ( stderr, "%2d: ", i );
916 if (verb) fprintf ( stderr, "type=%2d ", shdr[i].sh_type );
917 if (verb) fprintf ( stderr, "size=%4d ", shdr[i].sh_size );
918 if (verb) fprintf ( stderr, "offs=%4d ", shdr[i].sh_offset );
919 if (verb) fprintf ( stderr, " (%p .. %p) ",
920 ehdrC + shdr[i].sh_offset,
921 ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1);
923 if (shdr[i].sh_type == SHT_REL && verb) fprintf ( stderr, "Rel " ); else
924 if (shdr[i].sh_type == SHT_RELA && verb) fprintf ( stderr, "RelA " ); else
925 if (verb) fprintf ( stderr, " " );
926 if (sh_strtab && verb)
927 fprintf ( stderr, "sname=%s", sh_strtab + shdr[i].sh_name );
928 if (verb) fprintf ( stderr, "\n" );
931 if (verb) fprintf ( stderr, "\n\nString tables\n" );
934 for (i = 0; i < ehdr->e_shnum; i++) {
935 if (shdr[i].sh_type == SHT_STRTAB &&
936 i != ehdr->e_shstrndx) {
938 fprintf ( stderr, " section %d is a normal string table\n", i );
939 strtab = ehdrC + shdr[i].sh_offset;
944 oc->errMsg("WARNING: no string tables, or too many");
949 if (verb) fprintf ( stderr, "\n\nSymbol tables\n" );
950 for (i = 0; i < ehdr->e_shnum; i++) {
951 if (shdr[i].sh_type != SHT_SYMTAB) continue;
952 if (verb) fprintf ( stderr, "section %d is a symbol table\n", i );
954 stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
955 nent = shdr[i].sh_size / sizeof(Elf32_Sym);
956 if (verb) fprintf ( stderr, " number of entries is apparently %d (%d rem)\n",
958 shdr[i].sh_size % sizeof(Elf32_Sym)
960 if (0 != shdr[i].sh_size % sizeof(Elf32_Sym)) {
961 oc->errMsg("non-integral number of symbol table entries");
964 for (j = 0; j < nent; j++) {
965 if (verb) fprintf ( stderr, " %2d ", j );
966 if (verb) fprintf ( stderr, " sec=%-5d size=%-3d val=%-5p ",
967 (int)stab[j].st_shndx,
968 (int)stab[j].st_size,
969 (char*)stab[j].st_value );
971 if (verb) fprintf ( stderr, "type=" );
972 switch (ELF32_ST_TYPE(stab[j].st_info)) {
973 case STT_NOTYPE: if (verb) fprintf ( stderr, "notype " ); break;
974 case STT_OBJECT: if (verb) fprintf ( stderr, "object " ); break;
975 case STT_FUNC : if (verb) fprintf ( stderr, "func " ); break;
976 case STT_SECTION: if (verb) fprintf ( stderr, "section" ); break;
977 case STT_FILE: if (verb) fprintf ( stderr, "file " ); break;
978 default: if (verb) fprintf ( stderr, "? " ); break;
980 if (verb) fprintf ( stderr, " " );
982 if (verb) fprintf ( stderr, "bind=" );
983 switch (ELF32_ST_BIND(stab[j].st_info)) {
984 case STB_LOCAL : if (verb) fprintf ( stderr, "local " ); break;
985 case STB_GLOBAL: if (verb) fprintf ( stderr, "global" ); break;
986 case STB_WEAK : if (verb) fprintf ( stderr, "weak " ); break;
987 default: if (verb) fprintf ( stderr, "? " ); break;
989 if (verb) fprintf ( stderr, " " );
991 if (verb) fprintf ( stderr, "name=%s\n", strtab + stab[j].st_name );
996 oc->errMsg("Didn't find any symbol tables");
1004 static int ocGetNames_ELF ( ObjectCode* oc, int verb )
1009 char* ehdrC = (char*)(oc->oImage);
1010 Elf32_Ehdr* ehdr = (Elf32_Ehdr*)ehdrC;
1011 char* strtab = findElfSection ( ehdrC, SHT_STRTAB );
1012 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1013 char* sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1016 oc->errMsg("ELF: no strtab!");
1021 for (i = 0; i < ehdr->e_shnum; i++) {
1023 /* make a HugsDLSection entry for relevant sections */
1024 OSectionKind kind = HUGS_SECTIONKIND_OTHER;
1025 if (0==strcmp(".data",sh_strtab+shdr[i].sh_name) ||
1026 0==strcmp(".data1",sh_strtab+shdr[i].sh_name))
1027 kind = HUGS_SECTIONKIND_RWDATA;
1028 if (0==strcmp(".text",sh_strtab+shdr[i].sh_name) ||
1029 0==strcmp(".rodata",sh_strtab+shdr[i].sh_name) ||
1030 0==strcmp(".rodata1",sh_strtab+shdr[i].sh_name))
1031 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
1032 if (kind != HUGS_SECTIONKIND_OTHER)
1035 ehdrC + shdr[i].sh_offset,
1036 ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1,
1040 if (shdr[i].sh_type != SHT_SYMTAB) continue;
1042 /* copy stuff into this module's object symbol table */
1043 stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
1044 nent = shdr[i].sh_size / sizeof(Elf32_Sym);
1045 for (j = 0; j < nent; j++) {
1046 if ( ( ELF32_ST_BIND(stab[j].st_info)==STB_GLOBAL ||
1047 ELF32_ST_BIND(stab[j].st_info)==STB_LOCAL
1050 ( ELF32_ST_TYPE(stab[j].st_info)==STT_FUNC ||
1051 ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT)
1052 /* || ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE */
1054 char* nm = strtab + stab[j].st_name;
1056 + shdr[ stab[j].st_shndx ].sh_offset
1061 fprintf(stderr, "addOTabName: %10p %s %s\n",
1062 ad, oc->objFileName, nm );
1063 if (!addSymbol ( oc, nm, ad )) return FALSE;
1067 fprintf(stderr, "skipping `%s'\n", strtab + stab[j].st_name );
1075 static int ocResolve_ELF ( ObjectCode* oc, int verb )
1077 char symbol[1000]; // ToDo
1080 Elf32_Sym* stab = NULL;
1081 char* ehdrC = (char*)(oc->oImage);
1082 Elf32_Ehdr* ehdr = (Elf32_Ehdr*) ehdrC;
1083 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1086 /* first find "the" symbol table */
1087 stab = (Elf32_Sym*) findElfSection ( ehdrC, SHT_SYMTAB );
1089 /* also go find the string table */
1090 strtab = findElfSection ( ehdrC, SHT_STRTAB );
1092 if (!stab || !strtab) {
1093 oc->errMsg("can't find string or symbol table");
1097 for (i = 0; i < ehdr->e_shnum; i++) {
1098 if (shdr[i].sh_type == SHT_REL ) {
1099 Elf32_Rel* rtab = (Elf32_Rel*) (ehdrC + shdr[i].sh_offset);
1100 int nent = shdr[i].sh_size / sizeof(Elf32_Rel);
1101 int target_shndx = shdr[i].sh_info;
1102 int symtab_shndx = shdr[i].sh_link;
1103 stab = (Elf32_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
1104 targ = (Elf32_Word*)(ehdrC + shdr[ target_shndx ].sh_offset);
1107 "relocations for section %d using symtab %d\n",
1108 target_shndx, symtab_shndx );
1109 for (j = 0; j < nent; j++) {
1110 Elf32_Addr offset = rtab[j].r_offset;
1111 Elf32_Word info = rtab[j].r_info;
1113 Elf32_Addr P = ((Elf32_Addr)targ) + offset;
1114 Elf32_Word* pP = (Elf32_Word*)P;
1118 if (verb) fprintf ( stderr, "Rel entry %3d is raw(%6p %6p) ",
1119 j, (void*)offset, (void*)info );
1121 if (verb) fprintf ( stderr, " ZERO\n" );
1124 /* First see if it is a nameless local symbol. */
1125 if (stab[ ELF32_R_SYM(info)].st_name == 0) {
1126 if (verb) fprintf ( stderr, "(noname) ");
1127 S = (Elf32_Addr)(ehdrC
1128 + shdr[stab[ELF32_R_SYM(info)].st_shndx ].sh_offset
1129 + stab[ELF32_R_SYM(info)].st_value
1131 strcpy ( symbol, "(noname)");
1133 /* No? Perhaps it's a named symbol in this file. */
1134 strcpy ( symbol, strtab+stab[ ELF32_R_SYM(info)].st_name );
1135 if (verb) fprintf ( stderr, "`%s' ", symbol );
1136 S = (Elf32_Addr)ocLookupSym ( oc, symbol );
1138 /* No? Ok, too hard. Hand the problem to the client.
1139 And if that fails, we're outta options.
1141 S = (Elf32_Addr)(oc->clientLookup ( symbol ) );
1144 if (verb) fprintf ( stderr, "resolves to %p\n", (void*)S );
1147 strcpy(errtxt,oc->objFileName);
1148 strcat(errtxt,": unresolvable reference to: ");
1149 strcat(errtxt,symbol);
1154 /* fprintf ( stderr, "Reloc: P = %p S = %p A = %p\n\n",
1155 (void*)P, (void*)S, (void*)A );
1157 switch (ELF32_R_TYPE(info)) {
1158 case R_386_32: *pP = S + A; break;
1159 case R_386_PC32: *pP = S + A - P; break;
1160 default: fprintf(stderr,
1161 "unhandled ELF relocation type %d\n",
1162 ELF32_R_TYPE(info));
1163 oc->errMsg("unhandled ELF relocation type");
1170 if (shdr[i].sh_type == SHT_RELA) {
1171 oc->errMsg("RelA style reloc table -- not yet done");
1180 #endif /* defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) */
1184 /*-------------------------------------------------------------------------*/