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 * ------------------------------------------------------------------------*/
20 #include "config.h" /* for linux_TARGET_OS etc */
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 );
34 static char* hackyAppend ( char* s1, char* s2 );
35 static int sortSymbols ( ObjectCode* oc );
38 /* --------------------------------------------------------------------------
39 * Arch-independent interface to the runtime linker
40 * ------------------------------------------------------------------------*/
42 ObjectCode* ocNew ( void (*errMsg)(char*),
43 void* (*clientLookup)(char*),
47 ObjectCode* oc = malloc(sizeof(ObjectCode));
49 errMsg("ocNew: can't allocate memory for object code record");
53 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
54 oc->formatName = "ELF";
55 # elif defined(cygwin32_TARGET_OS)
56 oc->formatName = "PEi386";
59 errMsg("ocNew: not implemented on this platform");
63 oc->status = OBJECT_NOTINUSE;
64 oc->objFileName = objFileName;
65 oc->objFileSize = objFileSize;
67 oc->clientLookup = clientLookup;
69 oc->oImage = malloc ( objFileSize );
72 errMsg("ocNew: can't allocate memory for object code");
78 oc->sectionTab = NULL;
79 oc->sizesectionTab = 0;
80 oc->usedsectionTab = 0;
87 int ocLoadImage ( ObjectCode* oc, int verb )
91 assert (oc && oc->status==OBJECT_NOTINUSE);
92 if (verb) fprintf(stderr, "ocLoadImage %s\n", oc->objFileName );
93 f = fopen(oc->objFileName, "rb");
95 (oc->errMsg(hackyAppend("ocLoadImage: can't read: ",
99 n = fread ( oc->oImage, 1, oc->objFileSize, f );
100 if (n != oc->objFileSize) {
102 oc->errMsg(hackyAppend("ocLoadImage: I/O error whilst reading: ",
106 oc->status = OBJECT_OIMAGE;
107 if (verb) fprintf(stderr, "ocLoadImage %s: read %d bytes\n",
108 oc->objFileName, oc->objFileSize );
113 /* returns 1 if ok, 0 if error */
114 int ocVerifyImage ( ObjectCode* oc, int verb )
117 assert (oc && oc->status==OBJECT_OIMAGE);
118 if (verb) fprintf(stderr, "ocVerifyImage: begin\n");
119 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
120 ret = ocVerifyImage_ELF ( oc, verb );
121 # elif defined(cygwin32_TARGET_OS)
122 ret = ocVerifyImage_PEi386 ( oc, verb );
124 oc->errMsg("ocVerifyImage: not implemented on this platform");
127 if (verb) fprintf(stderr, "ocVerifyImage: done, status = %d", ret);
129 if (ret) oc->status = OBJECT_VERIFIED;
134 /* returns 1 if ok, 0 if error */
135 int ocGetNames ( ObjectCode* oc, int verb )
138 assert (oc && oc->status==OBJECT_VERIFIED);
139 if (verb) fprintf(stderr, "ocGetNames: begin\n");
140 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
141 ret = ocGetNames_ELF ( oc, verb );
142 # elif defined(cygwin32_TARGET_OS)
143 ret = ocGetNames_PEi386 ( oc, verb );
145 oc->errMsg("ocGetNames: not implemented on this platform");
148 if (verb) fprintf(stderr, "ocGetNames: done, status = %d\n", ret);
149 if (ret) ret = sortSymbols(oc);
150 if (ret) oc->status = OBJECT_HAVENAMES;
155 /* returns 1 if ok, 0 if error */
156 int ocResolve ( ObjectCode* oc, int verb )
159 assert (oc && oc->status==OBJECT_HAVENAMES);
160 if (verb) fprintf(stderr, "ocResolve: begin\n");
161 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
162 ret = ocResolve_ELF ( oc, verb );
163 # elif defined(cygwin32_TARGET_OS)
164 ret = ocResolve_PEi386 ( oc, verb );
166 oc->errMsg("ocResolve: not implemented on this platform");
169 if (verb) fprintf(stderr, "ocResolve: done, status = %d\n", ret);
170 if (ret) oc->status = OBJECT_RESOLVED;
175 void ocFree ( ObjectCode* oc )
178 if (oc->oImage) free(oc->oImage);
179 if (oc->oTab) free(oc->oTab);
180 if (oc->sectionTab) free(oc->sectionTab);
186 /* --------------------------------------------------------------------------
187 * Simple, dynamically expandable association tables
188 * ------------------------------------------------------------------------*/
190 /* A bit tricky. Assumes that if tab==NULL, then
191 currUsed and *currSize must be zero.
192 Returns NULL if expansion failed.
194 static void* genericExpand ( void* tab,
195 int* currSize, int currUsed,
196 int initSize, int elemSize )
200 if (currUsed < *currSize) return tab;
201 size2 = (*currSize == 0) ? initSize : (2 * *currSize);
202 tab2 = malloc ( size2 * elemSize );
203 if (!tab2) return NULL;
205 memcpy ( tab2, tab, elemSize * *currSize );
207 if (tab) free ( tab );
212 /* returns 1 if success, 0 if error */
213 static int addSymbol ( ObjectCode* oc, char* nm, void* ad )
216 = genericExpand ( oc->oTab,
222 oc->errMsg("addSymbol: malloc failed whilst expanding table");
226 oc->oTab[ oc->usedoTab ].nm = nm;
227 oc->oTab[ oc->usedoTab ].ad = ad;
233 /* Reorder symbol table so that symbols are in alphabetical order.
234 Detects an error if, after sorting, any two symbols are the same,
235 since this would imply that the same symbol has been inserted more
236 than once. Returns 1 if success, 0 if error.
238 static int sortSymbols ( ObjectCode* oc )
241 = { 1, 4, 13, 40, 121, 364, 1093, 3280,
242 9841, 29524, 88573, 265720, 797161, 2391484 };
245 int hi = oc->usedoTab-1;
246 int i, j, h, bigN, hp;
249 bigN = hi - lo + 1; if (bigN < 2) return 1;
250 hp = 0; while (incs[hp] < bigN) hp++; hp--;
252 for (; hp >= 0; hp--) {
259 while (strcmp(oc->oTab[j-h].nm, v.nm) > 0) {
260 oc->oTab[j] = oc->oTab[j-h];
262 if (j <= (lo + h - 1)) break;
269 for (i = 1; i < oc->usedoTab; i++) {
270 j = strcmp(oc->oTab[i-1].nm, oc->oTab[i].nm);
272 oc->errMsg("sortSymbols: sorting failed");
276 oc->errMsg("sortSymbols: duplicate symbols in object file");
285 /* returns 1 if success, 0 if error */
286 static int addSection ( ObjectCode* oc, void* start, void* end, OSectionKind sect )
289 = genericExpand ( oc->sectionTab,
290 &(oc->sizesectionTab),
292 4, sizeof(OSection) );
294 oc->errMsg("addSection: malloc failed whilst expanding table");
297 oc->sectionTab = newTab;
298 oc->sectionTab[ oc->usedsectionTab ].start = start;
299 oc->sectionTab[ oc->usedsectionTab ].end = end;
300 oc->sectionTab[ oc->usedsectionTab ].kind = sect;
301 oc->usedsectionTab++;
306 void* ocLookupSym ( ObjectCode* oc, char* sym )
308 int lo, hi, mid, cmp;
311 if (oc->status != OBJECT_HAVENAMES
312 && oc->status != OBJECT_RESOLVED) {
313 oc->errMsg("ocLookupSym: no symbols available");
317 /* Originally used a sequential search; should still work
318 for (i = 0; i < oc->usedoTab; i++) {
321 "ocLookupSym: request %s, table has %s\n",
322 sym, oc->oTab[i].nm );
323 if (0==strcmp(sym,oc->oTab[i].nm))
324 return oc->oTab[i].ad;
331 /* Invariant: the unsearched area is oc->oTab[lo .. hi] inclusive. */
332 if (hi < lo) return NULL;
334 cmp = strcmp(sym, oc->oTab[mid].nm);
335 if (cmp == 0) return oc->oTab[mid].ad;
336 if (cmp < 0) hi = mid-1;
337 if (cmp > 0) lo = mid+1;
342 char* ocLookupAddr ( ObjectCode* oc, void* addr )
347 if (oc->status != OBJECT_HAVENAMES
348 && oc->status != OBJECT_RESOLVED) {
349 oc->errMsg("ocLookupAddr: no symbols available");
353 for (i = 0; i < oc->usedoTab; i++) {
354 if (addr == oc->oTab[i].ad)
355 return oc->oTab[i].nm;
361 OSectionKind ocLookupSection ( ObjectCode* oc, void* addr )
366 if (oc->status != OBJECT_HAVENAMES
367 && oc->status != OBJECT_RESOLVED) {
368 oc->errMsg("ocLookupSection: no symbols available");
369 return HUGS_SECTIONKIND_NOINFOAVAIL;
373 for (i = 0; i < oc->usedsectionTab; i++) {
374 if (oc->sectionTab[i].start <= addr
375 && addr <= oc->sectionTab[i].end)
376 return oc->sectionTab[i].kind;
379 return HUGS_SECTIONKIND_NOINFOAVAIL;
383 /* Ghastly append which leaks space. But we only use it for
384 error messages -- that's my excuse.
386 static char* hackyAppend ( char* s1, char* s2 )
388 char* res = malloc ( 4 + strlen(s1) + strlen(s2) );
390 fprintf ( stderr, "hugs: fatal: hackyAppend\n\t%s\n\t%s\n", s1, s2 );
398 /* --------------------------------------------------------------------------
399 * PEi386 specifics (cygwin32)
400 * ------------------------------------------------------------------------*/
402 /* The information for this linker comes from
403 Microsoft Portable Executable
404 and Common Object File Format Specification
405 revision 5.1 January 1998
406 which SimonM says comes from the MS Developer Network CDs.
410 #if defined(cygwin32_TARGET_OS)
416 typedef unsigned char UChar;
417 typedef unsigned short UInt16;
418 typedef unsigned int UInt32;
425 UInt16 NumberOfSections;
426 UInt32 TimeDateStamp;
427 UInt32 PointerToSymbolTable;
428 UInt32 NumberOfSymbols;
429 UInt16 SizeOfOptionalHeader;
430 UInt16 Characteristics;
434 #define sizeof_COFF_header 20
441 UInt32 VirtualAddress;
442 UInt32 SizeOfRawData;
443 UInt32 PointerToRawData;
444 UInt32 PointerToRelocations;
445 UInt32 PointerToLinenumbers;
446 UInt16 NumberOfRelocations;
447 UInt16 NumberOfLineNumbers;
448 UInt32 Characteristics;
452 #define sizeof_COFF_section 40
459 UInt16 SectionNumber;
462 UChar NumberOfAuxSymbols;
466 #define sizeof_COFF_symbol 18
471 UInt32 VirtualAddress;
472 UInt32 SymbolTableIndex;
477 #define sizeof_COFF_reloc 10
480 /* From PE spec doc, section 3.3.2 */
481 #define IMAGE_FILE_RELOCS_STRIPPED 0x0001
482 #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
483 #define IMAGE_FILE_DLL 0x2000
484 #define IMAGE_FILE_SYSTEM 0x1000
485 #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
486 #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
487 #define IMAGE_FILE_32BIT_MACHINE 0x0100
489 /* From PE spec doc, section 5.4.2 and 5.4.4 */
490 #define IMAGE_SYM_CLASS_EXTERNAL 2
491 #define IMAGE_SYM_CLASS_STATIC 3
492 #define IMAGE_SYM_UNDEFINED 0
494 /* From PE spec doc, section 4.1 */
495 #define IMAGE_SCN_CNT_CODE 0x00000020
496 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
498 /* From PE spec doc, section 5.2.1 */
499 #define IMAGE_REL_I386_DIR32 0x0006
500 #define IMAGE_REL_I386_REL32 0x0014
503 /* We use myindex to calculate array addresses, rather than
504 simply doing the normal subscript thing. That's because
505 some of the above structs have sizes which are not
506 a whole number of words. GCC rounds their sizes up to a
507 whole number of words, which means that the address calcs
508 arising from using normal C indexing or pointer arithmetic
509 are just plain wrong. Sigh.
511 static UChar* myindex ( int scale, int index, void* base )
514 ((UChar*)base) + scale * index;
518 static void printName ( UChar* name, UChar* strtab )
520 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
521 UInt32 strtab_offset = * (UInt32*)(name+4);
522 fprintf ( stderr, "%s", strtab + strtab_offset );
525 for (i = 0; i < 8; i++) {
526 if (name[i] == 0) break;
527 fprintf ( stderr, "%c", name[i] );
533 static void copyName ( UChar* name, UChar* strtab,
534 UChar* dst, int dstSize )
536 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
537 UInt32 strtab_offset = * (UInt32*)(name+4);
538 strncpy ( dst, strtab+strtab_offset, dstSize );
544 if (name[i] == 0) break;
553 static UChar* cstring_from_COFF_symbol_name ( UChar* name,
557 /* If the string is longer than 8 bytes, look in the
558 string table for it -- this will be correctly zero terminated.
560 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
561 UInt32 strtab_offset = * (UInt32*)(name+4);
562 return ((UChar*)strtab) + strtab_offset;
564 /* Otherwise, if shorter than 8 bytes, return the original,
565 which by defn is correctly terminated.
567 if (name[7]==0) return name;
568 /* The annoying case: 8 bytes. Copy into a temporary
569 (which is never freed ...)
573 strncpy(newstr,name,8);
580 /* Just compares the short names (first 8 chars) */
581 static COFF_section* findPEi386SectionCalled ( ObjectCode* oc,
586 = (COFF_header*)(oc->oImage);
589 ((UChar*)(oc->oImage))
590 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
592 for (i = 0; i < hdr->NumberOfSections; i++) {
595 COFF_section* section_i
597 myindex ( sizeof_COFF_section, i, sectab );
598 n1 = (UChar*) &(section_i->Name);
600 if (n1[0]==n2[0] && n1[1]==n2[1] && n1[2]==n2[2] &&
601 n1[3]==n2[3] && n1[4]==n2[4] && n1[5]==n2[5] &&
602 n1[6]==n2[6] && n1[7]==n2[7])
610 static void zapTrailingAtSign ( UChar* sym )
613 if (sym[0] == 0) return;
615 while (sym[i] != 0) i++;
618 while (j > 0 && isdigit(sym[j])) j--;
619 if (j > 0 && sym[j] == '@' && j != i) sym[j] = 0;
623 static int ocVerifyImage_PEi386 ( ObjectCode* oc, int verb )
627 COFF_section* sectab;
631 hdr = (COFF_header*)(oc->oImage);
632 sectab = (COFF_section*) (
633 ((UChar*)(oc->oImage))
634 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
636 symtab = (COFF_symbol*) (
637 ((UChar*)(oc->oImage))
638 + hdr->PointerToSymbolTable
640 strtab = ((UChar*)(oc->oImage))
641 + hdr->PointerToSymbolTable
642 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
644 if (hdr->Machine != 0x14c) {
645 oc->errMsg("Not x86 PEi386");
648 if (hdr->SizeOfOptionalHeader != 0) {
649 oc->errMsg("PEi386 with nonempty optional header");
652 if ( /* (hdr->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) || */
653 (hdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) ||
654 (hdr->Characteristics & IMAGE_FILE_DLL) ||
655 (hdr->Characteristics & IMAGE_FILE_SYSTEM) ) {
656 oc->errMsg("Not a PEi386 object file");
659 if ( (hdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI) ||
660 !(hdr->Characteristics & IMAGE_FILE_32BIT_MACHINE) ) {
661 oc->errMsg("Invalid PEi386 word size or endiannness");
665 if (!verb) return TRUE;
666 /* No further verification after this point; only debug printing. */
669 "sectab offset = %d\n", ((UChar*)sectab) - ((UChar*)hdr) );
671 "symtab offset = %d\n", ((UChar*)symtab) - ((UChar*)hdr) );
673 "strtab offset = %d\n", ((UChar*)strtab) - ((UChar*)hdr) );
675 fprintf ( stderr, "\n" );
677 "Machine: 0x%x\n", (UInt32)(hdr->Machine) );
679 "# sections: %d\n", (UInt32)(hdr->NumberOfSections) );
681 "time/date: 0x%x\n", (UInt32)(hdr->TimeDateStamp) );
683 "symtab offset: %d\n", (UInt32)(hdr->PointerToSymbolTable) );
685 "# symbols: %d\n", (UInt32)(hdr->NumberOfSymbols) );
687 "sz of opt hdr: %d\n", (UInt32)(hdr->SizeOfOptionalHeader) );
689 "characteristics: 0x%x\n", (UInt32)(hdr->Characteristics) );
691 fprintf ( stderr, "\n" );
692 fprintf ( stderr, "string table has size 0x%x\n", * (UInt32*)strtab );
693 fprintf ( stderr, "---START of string table---\n");
694 for (i = 4; i < *(UInt32*)strtab; i++) {
696 fprintf ( stderr, "\n"); else
697 fprintf( stderr, "%c", strtab[i] );
699 fprintf ( stderr, "--- END of string table---\n");
701 fprintf ( stderr, "\n" );
702 for (i = 0; i < hdr->NumberOfSections; i++) {
704 COFF_section* sectab_i
706 myindex ( sizeof_COFF_section, i, sectab );
713 printName ( sectab_i->Name, strtab );
722 sectab_i->VirtualSize,
723 sectab_i->VirtualAddress,
724 sectab_i->SizeOfRawData,
725 sectab_i->PointerToRawData,
726 sectab_i->NumberOfRelocations,
727 sectab_i->PointerToRelocations
729 reltab = (COFF_reloc*) (
730 ((UChar*)(oc->oImage)) + sectab_i->PointerToRelocations
732 for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
734 COFF_reloc* rel = (COFF_reloc*)
735 myindex ( sizeof_COFF_reloc, j, reltab );
737 " type 0x%-4x vaddr 0x%-8x name `",
739 rel->VirtualAddress );
741 myindex ( sizeof_COFF_symbol, rel->SymbolTableIndex, symtab );
742 printName ( sym->Name, strtab );
743 fprintf ( stderr, "'\n" );
745 fprintf ( stderr, "\n" );
749 fprintf ( stderr, "\n" );
752 COFF_symbol* symtab_i;
753 if (i >= hdr->NumberOfSymbols) break;
754 symtab_i = (COFF_symbol*)
755 myindex ( sizeof_COFF_symbol, i, symtab );
761 printName ( symtab_i->Name, strtab );
770 (Int32)(symtab_i->SectionNumber) - 1,
771 (UInt32)symtab_i->Type,
772 (UInt32)symtab_i->StorageClass,
773 (UInt32)symtab_i->NumberOfAuxSymbols
775 i += symtab_i->NumberOfAuxSymbols;
779 fprintf ( stderr, "\n" );
785 static int ocGetNames_PEi386 ( ObjectCode* oc, int verb )
788 COFF_section* sectab;
796 hdr = (COFF_header*)(oc->oImage);
797 sectab = (COFF_section*) (
798 ((UChar*)(oc->oImage))
799 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
801 symtab = (COFF_symbol*) (
802 ((UChar*)(oc->oImage))
803 + hdr->PointerToSymbolTable
805 strtab = ((UChar*)(oc->oImage))
806 + hdr->PointerToSymbolTable
807 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
809 /* Copy exported symbols into the ObjectCode. */
812 COFF_symbol* symtab_i;
813 if (i >= hdr->NumberOfSymbols) break;
814 symtab_i = (COFF_symbol*)
815 myindex ( sizeof_COFF_symbol, i, symtab );
817 if (symtab_i->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
818 symtab_i->SectionNumber != IMAGE_SYM_UNDEFINED) {
820 /* This symbol is global and defined, viz, exported */
821 COFF_section* sectabent;
823 sname = cstring_from_COFF_symbol_name (
824 symtab_i->Name, strtab
827 oc->errMsg("Out of memory when copying PEi386 symbol");
831 /* for IMAGE_SYMCLASS_EXTERNAL
832 && !IMAGE_SYM_UNDEFINED,
833 the address of the symbol is:
834 address of relevant section + offset in section
836 sectabent = (COFF_section*)
837 myindex ( sizeof_COFF_section,
838 symtab_i->SectionNumber-1,
840 addr = ((UChar*)(oc->oImage))
841 + (sectabent->PointerToRawData
843 /* fprintf ( stderr, "addSymbol %p `%s'\n", addr,sname); */
844 if (!addSymbol(oc,sname,addr)) return FALSE;
846 i += symtab_i->NumberOfAuxSymbols;
850 /* Copy section information into the ObjectCode. */
851 for (i = 0; i < hdr->NumberOfSections; i++) {
856 = HUGS_SECTIONKIND_OTHER;
857 COFF_section* sectab_i
859 myindex ( sizeof_COFF_section, i, sectab );
860 /* fprintf ( stderr, "section name = %s\n", sectab_i->Name ); */
863 /* I'm sure this is the Right Way to do it. However, the
864 alternative of testing the sectab_i->Name field seems to
867 if (sectab_i->Characteristics & IMAGE_SCN_CNT_CODE ||
868 sectab_i->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
869 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
872 if (0==strcmp(".text",sectab_i->Name))
873 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
874 if (0==strcmp(".data",sectab_i->Name) ||
875 0==strcmp(".bss",sectab_i->Name))
876 kind = HUGS_SECTIONKIND_RWDATA;
878 start = ((UChar*)(oc->oImage))
879 + sectab_i->PointerToRawData;
881 + sectab_i->SizeOfRawData - 1;
883 if (kind != HUGS_SECTIONKIND_OTHER) {
884 addSection ( oc, start, end, kind );
886 fprintf ( stderr, "unknown section name = `%s'\n",
888 oc->errMsg("Unknown PEi386 section name");
897 static int ocResolve_PEi386 ( ObjectCode* oc, int verb )
900 COFF_section* sectab;
909 char symbol[1000]; // ToDo
911 hdr = (COFF_header*)(oc->oImage);
912 sectab = (COFF_section*) (
913 ((UChar*)(oc->oImage))
914 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
916 symtab = (COFF_symbol*) (
917 ((UChar*)(oc->oImage))
918 + hdr->PointerToSymbolTable
920 strtab = ((UChar*)(oc->oImage))
921 + hdr->PointerToSymbolTable
922 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
924 for (i = 0; i < hdr->NumberOfSections; i++) {
925 COFF_section* sectab_i
927 myindex ( sizeof_COFF_section, i, sectab );
930 ((UChar*)(oc->oImage)) + sectab_i->PointerToRelocations
932 for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
936 myindex ( sizeof_COFF_reloc, j, reltab );
938 /* the location to patch */
940 ((UChar*)(oc->oImage))
941 + (sectab_i->PointerToRawData
942 + reltab_j->VirtualAddress)
944 /* the existing contents of pP */
946 /* the symbol to connect to */
948 myindex ( sizeof_COFF_symbol,
949 reltab_j->SymbolTableIndex, symtab );
952 "reloc sec %2d num %3d: type 0x%-4x "
953 "vaddr 0x%-8x name `",
955 (UInt32)reltab_j->Type,
956 reltab_j->VirtualAddress );
957 printName ( sym->Name, strtab );
958 fprintf ( stderr, "'\n" );
961 if (sym->StorageClass == IMAGE_SYM_CLASS_STATIC) {
962 COFF_section* section_sym
963 = findPEi386SectionCalled ( oc, sym->Name );
965 fprintf ( stderr, "bad section = `%s'\n", sym->Name );
966 oc->errMsg("Can't find abovementioned PEi386 section");
969 S = ((UInt32)(oc->oImage))
970 + (section_sym->PointerToRawData
973 copyName ( sym->Name, strtab, symbol, 1000 );
974 zapTrailingAtSign ( symbol );
975 S = (UInt32) ocLookupSym ( oc, symbol );
977 S = (UInt32)(oc->clientLookup ( symbol ));
980 strcpy(errtxt,oc->objFileName);
981 strcat(errtxt,": unresolvable reference to: ");
982 strcat(errtxt,symbol);
988 switch (reltab_j->Type) {
989 case IMAGE_REL_I386_DIR32:
992 case IMAGE_REL_I386_REL32:
993 /* Tricky. We have to insert a displacement at
994 pP which, when added to the PC for the _next_
995 insn, gives the address of the target (S).
996 Problem is to know the address of the next insn
997 when we only know pP. We assume that this
998 literal field is always the last in the insn,
999 so that the address of the next insn is pP+4
1000 -- hence the constant 4.
1001 Also I don't know if A should be added, but so
1002 far it has always been zero.
1005 *pP = S - ((UInt32)pP) - 4;
1009 "unhandled PEi386 relocation type %d\n",
1011 oc->errMsg("unhandled PEi386 relocation type");
1021 #endif /* defined(cygwin32_TARGET_OS) */
1024 /* --------------------------------------------------------------------------
1025 * ELF specifics (Linux, Solaris)
1026 * ------------------------------------------------------------------------*/
1028 #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
1035 static char* findElfSection ( void* objImage, Elf32_Word sh_type )
1038 char* ehdrC = (char*)objImage;
1039 Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
1040 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1042 for (i = 0; i < ehdr->e_shnum; i++) {
1043 if (shdr[i].sh_type == sh_type &&
1044 i != ehdr->e_shstrndx) {
1045 ptr = ehdrC + shdr[i].sh_offset;
1053 static int ocVerifyImage_ELF ( ObjectCode* oc, int verb )
1057 int i, j, nent, nstrtab, nsymtabs;
1061 char* ehdrC = (char*)(oc->oImage);
1062 Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
1064 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
1065 ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
1066 ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
1067 ehdr->e_ident[EI_MAG3] != ELFMAG3) {
1068 oc->errMsg("Not an ELF header");
1071 if (verb) fprintf ( stderr, "Is an ELF header\n" );
1073 if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
1074 oc->errMsg("Not 32 bit ELF" );
1077 if (verb) fprintf ( stderr, "Is 32 bit ELF\n" );
1079 if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
1080 if (verb) fprintf ( stderr, "Is little-endian\n" );
1082 if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
1083 if (verb) fprintf ( stderr, "Is big-endian\n" );
1085 oc->errMsg("Unknown endiannness");
1089 if (ehdr->e_type != ET_REL) {
1090 oc->errMsg("Not a relocatable object (.o) file");
1093 if (verb) fprintf ( stderr, "Is a relocatable object (.o) file\n" );
1095 if (verb) fprintf ( stderr, "Architecture is " );
1096 switch (ehdr->e_machine) {
1097 case EM_386: if (verb) fprintf ( stderr, "x86\n" ); break;
1098 case EM_SPARC: if (verb) fprintf ( stderr, "sparc\n" ); break;
1099 default: if (verb) fprintf ( stderr, "unknown\n" );
1100 oc->errMsg("Unknown architecture");
1106 "\nSection header table: start %d, n_entries %d, ent_size %d\n",
1107 ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize );
1109 assert (ehdr->e_shentsize == sizeof(Elf32_Shdr));
1111 shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1113 if (ehdr->e_shstrndx == SHN_UNDEF) {
1114 oc->errMsg("No section header string table");
1117 if (verb) fprintf ( stderr,"Section header string table is section %d\n",
1119 sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1122 for (i = 0; i < ehdr->e_shnum; i++) {
1123 if (verb) fprintf ( stderr, "%2d: ", i );
1124 if (verb) fprintf ( stderr, "type=%2d ", shdr[i].sh_type );
1125 if (verb) fprintf ( stderr, "size=%4d ", shdr[i].sh_size );
1126 if (verb) fprintf ( stderr, "offs=%4d ", shdr[i].sh_offset );
1127 if (verb) fprintf ( stderr, " (%p .. %p) ",
1128 ehdrC + shdr[i].sh_offset,
1129 ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1);
1131 if (shdr[i].sh_type == SHT_REL && verb) fprintf ( stderr, "Rel " ); else
1132 if (shdr[i].sh_type == SHT_RELA && verb) fprintf ( stderr, "RelA " ); else
1133 if (verb) fprintf ( stderr, " " );
1134 if (sh_strtab && verb)
1135 fprintf ( stderr, "sname=%s", sh_strtab + shdr[i].sh_name );
1136 if (verb) fprintf ( stderr, "\n" );
1139 if (verb) fprintf ( stderr, "\n\nString tables\n" );
1142 for (i = 0; i < ehdr->e_shnum; i++) {
1143 if (shdr[i].sh_type == SHT_STRTAB &&
1144 i != ehdr->e_shstrndx) {
1146 fprintf ( stderr, " section %d is a normal string table\n", i );
1147 strtab = ehdrC + shdr[i].sh_offset;
1152 oc->errMsg("WARNING: no string tables, or too many");
1157 if (verb) fprintf ( stderr, "\n\nSymbol tables\n" );
1158 for (i = 0; i < ehdr->e_shnum; i++) {
1159 if (shdr[i].sh_type != SHT_SYMTAB) continue;
1160 if (verb) fprintf ( stderr, "section %d is a symbol table\n", i );
1162 stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
1163 nent = shdr[i].sh_size / sizeof(Elf32_Sym);
1164 if (verb) fprintf ( stderr, " number of entries is apparently %d (%d rem)\n",
1166 shdr[i].sh_size % sizeof(Elf32_Sym)
1168 if (0 != shdr[i].sh_size % sizeof(Elf32_Sym)) {
1169 oc->errMsg("non-integral number of symbol table entries");
1172 for (j = 0; j < nent; j++) {
1173 if (verb) fprintf ( stderr, " %2d ", j );
1174 if (verb) fprintf ( stderr, " sec=%-5d size=%-3d val=%-5p ",
1175 (int)stab[j].st_shndx,
1176 (int)stab[j].st_size,
1177 (char*)stab[j].st_value );
1179 if (verb) fprintf ( stderr, "type=" );
1180 switch (ELF32_ST_TYPE(stab[j].st_info)) {
1181 case STT_NOTYPE: if (verb) fprintf ( stderr, "notype " ); break;
1182 case STT_OBJECT: if (verb) fprintf ( stderr, "object " ); break;
1183 case STT_FUNC : if (verb) fprintf ( stderr, "func " ); break;
1184 case STT_SECTION: if (verb) fprintf ( stderr, "section" ); break;
1185 case STT_FILE: if (verb) fprintf ( stderr, "file " ); break;
1186 default: if (verb) fprintf ( stderr, "? " ); break;
1188 if (verb) fprintf ( stderr, " " );
1190 if (verb) fprintf ( stderr, "bind=" );
1191 switch (ELF32_ST_BIND(stab[j].st_info)) {
1192 case STB_LOCAL : if (verb) fprintf ( stderr, "local " ); break;
1193 case STB_GLOBAL: if (verb) fprintf ( stderr, "global" ); break;
1194 case STB_WEAK : if (verb) fprintf ( stderr, "weak " ); break;
1195 default: if (verb) fprintf ( stderr, "? " ); break;
1197 if (verb) fprintf ( stderr, " " );
1199 if (verb) fprintf ( stderr, "name=%s\n", strtab + stab[j].st_name );
1203 if (nsymtabs == 0) {
1204 oc->errMsg("Didn't find any symbol tables");
1212 static int ocGetNames_ELF ( ObjectCode* oc, int verb )
1217 char* ehdrC = (char*)(oc->oImage);
1218 Elf32_Ehdr* ehdr = (Elf32_Ehdr*)ehdrC;
1219 char* strtab = findElfSection ( ehdrC, SHT_STRTAB );
1220 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1221 char* sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1224 oc->errMsg("ELF: no strtab!");
1229 for (i = 0; i < ehdr->e_shnum; i++) {
1231 /* make a HugsDLSection entry for relevant sections */
1232 OSectionKind kind = HUGS_SECTIONKIND_OTHER;
1233 if (0==strcmp(".data",sh_strtab+shdr[i].sh_name) ||
1234 0==strcmp(".data1",sh_strtab+shdr[i].sh_name))
1235 kind = HUGS_SECTIONKIND_RWDATA;
1236 if (0==strcmp(".text",sh_strtab+shdr[i].sh_name) ||
1237 0==strcmp(".rodata",sh_strtab+shdr[i].sh_name) ||
1238 0==strcmp(".rodata1",sh_strtab+shdr[i].sh_name))
1239 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
1240 if (kind != HUGS_SECTIONKIND_OTHER)
1243 ehdrC + shdr[i].sh_offset,
1244 ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1,
1248 if (shdr[i].sh_type != SHT_SYMTAB) continue;
1250 /* copy stuff into this module's object symbol table */
1251 stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
1252 nent = shdr[i].sh_size / sizeof(Elf32_Sym);
1253 for (j = 0; j < nent; j++) {
1254 if ( ( ELF32_ST_BIND(stab[j].st_info)==STB_GLOBAL ||
1255 ELF32_ST_BIND(stab[j].st_info)==STB_LOCAL
1258 ( ELF32_ST_TYPE(stab[j].st_info)==STT_FUNC ||
1259 ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT)
1260 /* || ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE */
1262 char* nm = strtab + stab[j].st_name;
1264 + shdr[ stab[j].st_shndx ].sh_offset
1269 fprintf(stderr, "addOTabName: %10p %s %s\n",
1270 ad, oc->objFileName, nm );
1271 if (!addSymbol ( oc, nm, ad )) return FALSE;
1275 fprintf(stderr, "skipping `%s'\n", strtab + stab[j].st_name );
1283 static int ocResolve_ELF ( ObjectCode* oc, int verb )
1285 char symbol[1000]; // ToDo
1288 Elf32_Sym* stab = NULL;
1289 char* ehdrC = (char*)(oc->oImage);
1290 Elf32_Ehdr* ehdr = (Elf32_Ehdr*) ehdrC;
1291 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1294 /* first find "the" symbol table */
1295 stab = (Elf32_Sym*) findElfSection ( ehdrC, SHT_SYMTAB );
1297 /* also go find the string table */
1298 strtab = findElfSection ( ehdrC, SHT_STRTAB );
1300 if (!stab || !strtab) {
1301 oc->errMsg("can't find string or symbol table");
1305 for (i = 0; i < ehdr->e_shnum; i++) {
1306 if (shdr[i].sh_type == SHT_REL ) {
1307 Elf32_Rel* rtab = (Elf32_Rel*) (ehdrC + shdr[i].sh_offset);
1308 int nent = shdr[i].sh_size / sizeof(Elf32_Rel);
1309 int target_shndx = shdr[i].sh_info;
1310 int symtab_shndx = shdr[i].sh_link;
1311 stab = (Elf32_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
1312 targ = (Elf32_Word*)(ehdrC + shdr[ target_shndx ].sh_offset);
1315 "relocations for section %d using symtab %d\n",
1316 target_shndx, symtab_shndx );
1317 for (j = 0; j < nent; j++) {
1318 Elf32_Addr offset = rtab[j].r_offset;
1319 Elf32_Word info = rtab[j].r_info;
1321 Elf32_Addr P = ((Elf32_Addr)targ) + offset;
1322 Elf32_Word* pP = (Elf32_Word*)P;
1326 if (verb) fprintf ( stderr, "Rel entry %3d is raw(%6p %6p) ",
1327 j, (void*)offset, (void*)info );
1329 if (verb) fprintf ( stderr, " ZERO\n" );
1332 /* First see if it is a nameless local symbol. */
1333 if (stab[ ELF32_R_SYM(info)].st_name == 0) {
1334 if (verb) fprintf ( stderr, "(noname) ");
1335 S = (Elf32_Addr)(ehdrC
1336 + shdr[stab[ELF32_R_SYM(info)].st_shndx ].sh_offset
1337 + stab[ELF32_R_SYM(info)].st_value
1339 strcpy ( symbol, "(noname)");
1341 /* No? Perhaps it's a named symbol in this file. */
1342 strcpy ( symbol, strtab+stab[ ELF32_R_SYM(info)].st_name );
1343 if (verb) fprintf ( stderr, "`%s' ", symbol );
1344 S = (Elf32_Addr)ocLookupSym ( oc, symbol );
1346 /* No? Ok, too hard. Hand the problem to the client.
1347 And if that fails, we're outta options.
1349 S = (Elf32_Addr)(oc->clientLookup ( symbol ) );
1352 if (verb) fprintf ( stderr, "resolves to %p\n", (void*)S );
1355 strcpy(errtxt,oc->objFileName);
1356 strcat(errtxt,": unresolvable reference to: ");
1357 strcat(errtxt,symbol);
1362 /* fprintf ( stderr, "Reloc: P = %p S = %p A = %p\n\n",
1363 (void*)P, (void*)S, (void*)A );
1365 switch (ELF32_R_TYPE(info)) {
1366 case R_386_32: *pP = S + A; break;
1367 case R_386_PC32: *pP = S + A - P; break;
1368 default: fprintf(stderr,
1369 "unhandled ELF relocation type %d\n",
1370 ELF32_R_TYPE(info));
1371 oc->errMsg("unhandled ELF relocation type");
1378 if (shdr[i].sh_type == SHT_RELA) {
1379 oc->errMsg("RelA style reloc table -- not yet done");
1388 #endif /* defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) */
1392 /*-------------------------------------------------------------------------*/