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*),
44 int (*clientWantsSymbol)(char*),
48 ObjectCode* oc = malloc(sizeof(ObjectCode));
50 errMsg("ocNew: can't allocate memory for object code record");
54 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
55 oc->formatName = "ELF";
56 # elif defined(cygwin32_TARGET_OS)
57 oc->formatName = "PEi386";
60 errMsg("ocNew: not implemented on this platform");
64 oc->status = OBJECT_NOTINUSE;
65 oc->objFileName = objFileName;
66 oc->objFileSize = objFileSize;
68 oc->clientLookup = clientLookup;
69 oc->clientWantsSymbol = clientWantsSymbol;
71 oc->oImage = malloc ( objFileSize );
74 errMsg("ocNew: can't allocate memory for object code");
80 oc->sectionTab = NULL;
81 oc->sizesectionTab = 0;
82 oc->usedsectionTab = 0;
89 int ocLoadImage ( ObjectCode* oc, int verb )
93 assert (oc && oc->status==OBJECT_NOTINUSE);
94 if (verb) fprintf(stderr, "ocLoadImage %s\n", oc->objFileName );
95 f = fopen(oc->objFileName, "rb");
97 (oc->errMsg(hackyAppend("ocLoadImage: can't read: ",
101 n = fread ( oc->oImage, 1, oc->objFileSize, f );
102 if (n != oc->objFileSize) {
104 oc->errMsg(hackyAppend("ocLoadImage: I/O error whilst reading: ",
108 oc->status = OBJECT_OIMAGE;
109 if (verb) fprintf(stderr, "ocLoadImage %s: read %d bytes\n",
110 oc->objFileName, oc->objFileSize );
115 /* returns 1 if ok, 0 if error */
116 int ocVerifyImage ( ObjectCode* oc, int verb )
119 assert (oc && oc->status==OBJECT_OIMAGE);
120 if (verb) fprintf(stderr, "ocVerifyImage: begin\n");
121 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
122 ret = ocVerifyImage_ELF ( oc, verb );
123 # elif defined(cygwin32_TARGET_OS)
124 ret = ocVerifyImage_PEi386 ( oc, verb );
126 oc->errMsg("ocVerifyImage: not implemented on this platform");
129 if (verb) fprintf(stderr, "ocVerifyImage: done, status = %d", ret);
131 if (ret) oc->status = OBJECT_VERIFIED;
136 /* returns 1 if ok, 0 if error */
137 int ocGetNames ( ObjectCode* oc, int verb )
140 assert (oc && oc->status==OBJECT_VERIFIED);
141 if (verb) fprintf(stderr, "ocGetNames: begin\n");
142 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
143 ret = ocGetNames_ELF ( oc, verb );
144 # elif defined(cygwin32_TARGET_OS)
145 ret = ocGetNames_PEi386 ( oc, verb );
147 oc->errMsg("ocGetNames: not implemented on this platform");
150 if (verb) fprintf(stderr, "ocGetNames: done, status = %d\n", ret);
151 if (ret) ret = sortSymbols(oc);
152 if (ret) oc->status = OBJECT_HAVENAMES;
157 /* returns 1 if ok, 0 if error */
158 int ocResolve ( ObjectCode* oc, int verb )
161 assert (oc && oc->status==OBJECT_HAVENAMES);
162 if (verb) fprintf(stderr, "ocResolve: begin\n");
163 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
164 ret = ocResolve_ELF ( oc, verb );
165 # elif defined(cygwin32_TARGET_OS)
166 ret = ocResolve_PEi386 ( oc, verb );
168 oc->errMsg("ocResolve: not implemented on this platform");
171 if (verb) fprintf(stderr, "ocResolve: done, status = %d\n", ret);
172 if (ret) oc->status = OBJECT_RESOLVED;
177 void ocFree ( ObjectCode* oc )
180 if (oc->oImage) free(oc->oImage);
181 if (oc->oTab) free(oc->oTab);
182 if (oc->sectionTab) free(oc->sectionTab);
188 /* --------------------------------------------------------------------------
189 * Simple, dynamically expandable association tables
190 * ------------------------------------------------------------------------*/
192 /* A bit tricky. Assumes that if tab==NULL, then
193 currUsed and *currSize must be zero.
194 Returns NULL if expansion failed.
196 static void* genericExpand ( void* tab,
197 int* currSize, int currUsed,
198 int initSize, int elemSize )
202 if (currUsed < *currSize) return tab;
203 size2 = (*currSize == 0) ? initSize : (2 * *currSize);
204 tab2 = malloc ( size2 * elemSize );
205 if (!tab2) return NULL;
207 memcpy ( tab2, tab, elemSize * *currSize );
209 if (tab) free ( tab );
214 /* returns 1 if success, 0 if error */
215 static int addSymbol ( ObjectCode* oc, char* nm, void* ad )
219 if (oc->clientWantsSymbol && !oc->clientWantsSymbol(nm))
223 = genericExpand ( oc->oTab,
229 oc->errMsg("addSymbol: malloc failed whilst expanding table");
233 oc->oTab[ oc->usedoTab ].nm = nm;
234 oc->oTab[ oc->usedoTab ].ad = ad;
240 /* Reorder symbol table so that symbols are in alphabetical order.
241 Detects an error if, after sorting, any two symbols are the same,
242 since this would imply that the same symbol has been inserted more
243 than once. Returns 1 if success, 0 if error.
245 static int sortSymbols ( ObjectCode* oc )
248 = { 1, 4, 13, 40, 121, 364, 1093, 3280,
249 9841, 29524, 88573, 265720, 797161, 2391484 };
252 int hi = oc->usedoTab-1;
253 int i, j, h, bigN, hp;
256 bigN = hi - lo + 1; if (bigN < 2) return 1;
257 hp = 0; while (incs[hp] < bigN) hp++; hp--;
259 for (; hp >= 0; hp--) {
266 while (strcmp(oc->oTab[j-h].nm, v.nm) > 0) {
267 oc->oTab[j] = oc->oTab[j-h];
269 if (j <= (lo + h - 1)) break;
276 for (i = 1; i < oc->usedoTab; i++) {
277 j = strcmp(oc->oTab[i-1].nm, oc->oTab[i].nm);
279 oc->errMsg("sortSymbols: sorting failed");
283 oc->errMsg("sortSymbols: duplicate symbols in object file:");
284 oc->errMsg(oc->oTab[i].nm);
293 /* returns 1 if success, 0 if error */
294 static int addSection ( ObjectCode* oc, void* start, void* end, OSectionKind sect )
297 = genericExpand ( oc->sectionTab,
298 &(oc->sizesectionTab),
300 4, sizeof(OSection) );
302 oc->errMsg("addSection: malloc failed whilst expanding table");
305 oc->sectionTab = newTab;
306 oc->sectionTab[ oc->usedsectionTab ].start = start;
307 oc->sectionTab[ oc->usedsectionTab ].end = end;
308 oc->sectionTab[ oc->usedsectionTab ].kind = sect;
309 oc->usedsectionTab++;
314 void* ocLookupSym ( ObjectCode* oc, char* sym )
316 int lo, hi, mid, cmp;
319 if (oc->status != OBJECT_HAVENAMES
320 && oc->status != OBJECT_RESOLVED) {
321 oc->errMsg("ocLookupSym: no symbols available");
325 /* Originally used a sequential search; should still work
326 for (i = 0; i < oc->usedoTab; i++) {
329 "ocLookupSym: request %s, table has %s\n",
330 sym, oc->oTab[i].nm );
331 if (0==strcmp(sym,oc->oTab[i].nm))
332 return oc->oTab[i].ad;
339 /* Invariant: the unsearched area is oc->oTab[lo .. hi] inclusive. */
340 if (hi < lo) return NULL;
342 cmp = strcmp(sym, oc->oTab[mid].nm);
343 if (cmp == 0) return oc->oTab[mid].ad;
344 if (cmp < 0) hi = mid-1;
345 if (cmp > 0) lo = mid+1;
350 char* ocLookupAddr ( ObjectCode* oc, void* addr )
355 if (oc->status != OBJECT_HAVENAMES
356 && oc->status != OBJECT_RESOLVED) {
357 oc->errMsg("ocLookupAddr: no symbols available");
361 for (i = 0; i < oc->usedoTab; i++) {
362 if (addr == oc->oTab[i].ad)
363 return oc->oTab[i].nm;
369 OSectionKind ocLookupSection ( ObjectCode* oc, void* addr )
374 if (oc->status != OBJECT_HAVENAMES
375 && oc->status != OBJECT_RESOLVED) {
376 oc->errMsg("ocLookupSection: no symbols available");
377 return HUGS_SECTIONKIND_NOINFOAVAIL;
381 for (i = 0; i < oc->usedsectionTab; i++) {
382 if (oc->sectionTab[i].start <= addr
383 && addr <= oc->sectionTab[i].end)
384 return oc->sectionTab[i].kind;
387 return HUGS_SECTIONKIND_NOINFOAVAIL;
391 /* Ghastly append which leaks space. But we only use it for
392 error messages -- that's my excuse.
394 static char* hackyAppend ( char* s1, char* s2 )
396 char* res = malloc ( 4 + strlen(s1) + strlen(s2) );
398 fprintf ( stderr, "hugs: fatal: hackyAppend\n\t%s\n\t%s\n", s1, s2 );
406 /* --------------------------------------------------------------------------
407 * PEi386 specifics (cygwin32)
408 * ------------------------------------------------------------------------*/
410 /* The information for this linker comes from
411 Microsoft Portable Executable
412 and Common Object File Format Specification
413 revision 5.1 January 1998
414 which SimonM says comes from the MS Developer Network CDs.
418 #if defined(cygwin32_TARGET_OS)
424 typedef unsigned char UChar;
425 typedef unsigned short UInt16;
426 typedef unsigned int UInt32;
433 UInt16 NumberOfSections;
434 UInt32 TimeDateStamp;
435 UInt32 PointerToSymbolTable;
436 UInt32 NumberOfSymbols;
437 UInt16 SizeOfOptionalHeader;
438 UInt16 Characteristics;
442 #define sizeof_COFF_header 20
449 UInt32 VirtualAddress;
450 UInt32 SizeOfRawData;
451 UInt32 PointerToRawData;
452 UInt32 PointerToRelocations;
453 UInt32 PointerToLinenumbers;
454 UInt16 NumberOfRelocations;
455 UInt16 NumberOfLineNumbers;
456 UInt32 Characteristics;
460 #define sizeof_COFF_section 40
467 UInt16 SectionNumber;
470 UChar NumberOfAuxSymbols;
474 #define sizeof_COFF_symbol 18
479 UInt32 VirtualAddress;
480 UInt32 SymbolTableIndex;
485 #define sizeof_COFF_reloc 10
488 /* From PE spec doc, section 3.3.2 */
489 #define IMAGE_FILE_RELOCS_STRIPPED 0x0001
490 #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
491 #define IMAGE_FILE_DLL 0x2000
492 #define IMAGE_FILE_SYSTEM 0x1000
493 #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
494 #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
495 #define IMAGE_FILE_32BIT_MACHINE 0x0100
497 /* From PE spec doc, section 5.4.2 and 5.4.4 */
498 #define IMAGE_SYM_CLASS_EXTERNAL 2
499 #define IMAGE_SYM_CLASS_STATIC 3
500 #define IMAGE_SYM_UNDEFINED 0
502 /* From PE spec doc, section 4.1 */
503 #define IMAGE_SCN_CNT_CODE 0x00000020
504 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
506 /* From PE spec doc, section 5.2.1 */
507 #define IMAGE_REL_I386_DIR32 0x0006
508 #define IMAGE_REL_I386_REL32 0x0014
511 /* We use myindex to calculate array addresses, rather than
512 simply doing the normal subscript thing. That's because
513 some of the above structs have sizes which are not
514 a whole number of words. GCC rounds their sizes up to a
515 whole number of words, which means that the address calcs
516 arising from using normal C indexing or pointer arithmetic
517 are just plain wrong. Sigh.
519 static UChar* myindex ( int scale, int index, void* base )
522 ((UChar*)base) + scale * index;
526 static void printName ( UChar* name, UChar* strtab )
528 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
529 UInt32 strtab_offset = * (UInt32*)(name+4);
530 fprintf ( stderr, "%s", strtab + strtab_offset );
533 for (i = 0; i < 8; i++) {
534 if (name[i] == 0) break;
535 fprintf ( stderr, "%c", name[i] );
541 static void copyName ( UChar* name, UChar* strtab,
542 UChar* dst, int dstSize )
544 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
545 UInt32 strtab_offset = * (UInt32*)(name+4);
546 strncpy ( dst, strtab+strtab_offset, dstSize );
552 if (name[i] == 0) break;
561 static UChar* cstring_from_COFF_symbol_name ( UChar* name,
565 /* If the string is longer than 8 bytes, look in the
566 string table for it -- this will be correctly zero terminated.
568 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
569 UInt32 strtab_offset = * (UInt32*)(name+4);
570 return ((UChar*)strtab) + strtab_offset;
572 /* Otherwise, if shorter than 8 bytes, return the original,
573 which by defn is correctly terminated.
575 if (name[7]==0) return name;
576 /* The annoying case: 8 bytes. Copy into a temporary
577 (which is never freed ...)
581 strncpy(newstr,name,8);
588 /* Just compares the short names (first 8 chars) */
589 static COFF_section* findPEi386SectionCalled ( ObjectCode* oc,
594 = (COFF_header*)(oc->oImage);
597 ((UChar*)(oc->oImage))
598 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
600 for (i = 0; i < hdr->NumberOfSections; i++) {
603 COFF_section* section_i
605 myindex ( sizeof_COFF_section, i, sectab );
606 n1 = (UChar*) &(section_i->Name);
608 if (n1[0]==n2[0] && n1[1]==n2[1] && n1[2]==n2[2] &&
609 n1[3]==n2[3] && n1[4]==n2[4] && n1[5]==n2[5] &&
610 n1[6]==n2[6] && n1[7]==n2[7])
618 static void zapTrailingAtSign ( UChar* sym )
621 if (sym[0] == 0) return;
623 while (sym[i] != 0) i++;
626 while (j > 0 && isdigit(sym[j])) j--;
627 if (j > 0 && sym[j] == '@' && j != i) sym[j] = 0;
631 static int ocVerifyImage_PEi386 ( ObjectCode* oc, int verb )
635 COFF_section* sectab;
639 hdr = (COFF_header*)(oc->oImage);
640 sectab = (COFF_section*) (
641 ((UChar*)(oc->oImage))
642 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
644 symtab = (COFF_symbol*) (
645 ((UChar*)(oc->oImage))
646 + hdr->PointerToSymbolTable
648 strtab = ((UChar*)(oc->oImage))
649 + hdr->PointerToSymbolTable
650 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
652 if (hdr->Machine != 0x14c) {
653 oc->errMsg("Not x86 PEi386");
656 if (hdr->SizeOfOptionalHeader != 0) {
657 oc->errMsg("PEi386 with nonempty optional header");
660 if ( /* (hdr->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) || */
661 (hdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) ||
662 (hdr->Characteristics & IMAGE_FILE_DLL) ||
663 (hdr->Characteristics & IMAGE_FILE_SYSTEM) ) {
664 oc->errMsg("Not a PEi386 object file");
667 if ( (hdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI) ||
668 !(hdr->Characteristics & IMAGE_FILE_32BIT_MACHINE) ) {
669 oc->errMsg("Invalid PEi386 word size or endiannness");
673 if (!verb) return TRUE;
674 /* No further verification after this point; only debug printing. */
677 "sectab offset = %d\n", ((UChar*)sectab) - ((UChar*)hdr) );
679 "symtab offset = %d\n", ((UChar*)symtab) - ((UChar*)hdr) );
681 "strtab offset = %d\n", ((UChar*)strtab) - ((UChar*)hdr) );
683 fprintf ( stderr, "\n" );
685 "Machine: 0x%x\n", (UInt32)(hdr->Machine) );
687 "# sections: %d\n", (UInt32)(hdr->NumberOfSections) );
689 "time/date: 0x%x\n", (UInt32)(hdr->TimeDateStamp) );
691 "symtab offset: %d\n", (UInt32)(hdr->PointerToSymbolTable) );
693 "# symbols: %d\n", (UInt32)(hdr->NumberOfSymbols) );
695 "sz of opt hdr: %d\n", (UInt32)(hdr->SizeOfOptionalHeader) );
697 "characteristics: 0x%x\n", (UInt32)(hdr->Characteristics) );
699 fprintf ( stderr, "\n" );
700 fprintf ( stderr, "string table has size 0x%x\n", * (UInt32*)strtab );
701 fprintf ( stderr, "---START of string table---\n");
702 for (i = 4; i < *(UInt32*)strtab; i++) {
704 fprintf ( stderr, "\n"); else
705 fprintf( stderr, "%c", strtab[i] );
707 fprintf ( stderr, "--- END of string table---\n");
709 fprintf ( stderr, "\n" );
710 for (i = 0; i < hdr->NumberOfSections; i++) {
712 COFF_section* sectab_i
714 myindex ( sizeof_COFF_section, i, sectab );
721 printName ( sectab_i->Name, strtab );
730 sectab_i->VirtualSize,
731 sectab_i->VirtualAddress,
732 sectab_i->SizeOfRawData,
733 sectab_i->PointerToRawData,
734 sectab_i->NumberOfRelocations,
735 sectab_i->PointerToRelocations
737 reltab = (COFF_reloc*) (
738 ((UChar*)(oc->oImage)) + sectab_i->PointerToRelocations
740 for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
742 COFF_reloc* rel = (COFF_reloc*)
743 myindex ( sizeof_COFF_reloc, j, reltab );
745 " type 0x%-4x vaddr 0x%-8x name `",
747 rel->VirtualAddress );
749 myindex ( sizeof_COFF_symbol, rel->SymbolTableIndex, symtab );
750 printName ( sym->Name, strtab );
751 fprintf ( stderr, "'\n" );
753 fprintf ( stderr, "\n" );
757 fprintf ( stderr, "\n" );
760 COFF_symbol* symtab_i;
761 if (i >= hdr->NumberOfSymbols) break;
762 symtab_i = (COFF_symbol*)
763 myindex ( sizeof_COFF_symbol, i, symtab );
769 printName ( symtab_i->Name, strtab );
778 (Int32)(symtab_i->SectionNumber) - 1,
779 (UInt32)symtab_i->Type,
780 (UInt32)symtab_i->StorageClass,
781 (UInt32)symtab_i->NumberOfAuxSymbols
783 i += symtab_i->NumberOfAuxSymbols;
787 fprintf ( stderr, "\n" );
793 static int ocGetNames_PEi386 ( ObjectCode* oc, int verb )
796 COFF_section* sectab;
804 hdr = (COFF_header*)(oc->oImage);
805 sectab = (COFF_section*) (
806 ((UChar*)(oc->oImage))
807 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
809 symtab = (COFF_symbol*) (
810 ((UChar*)(oc->oImage))
811 + hdr->PointerToSymbolTable
813 strtab = ((UChar*)(oc->oImage))
814 + hdr->PointerToSymbolTable
815 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
817 /* Copy exported symbols into the ObjectCode. */
820 COFF_symbol* symtab_i;
821 if (i >= hdr->NumberOfSymbols) break;
822 symtab_i = (COFF_symbol*)
823 myindex ( sizeof_COFF_symbol, i, symtab );
825 if (symtab_i->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
826 symtab_i->SectionNumber != IMAGE_SYM_UNDEFINED) {
828 /* This symbol is global and defined, viz, exported */
829 COFF_section* sectabent;
831 sname = cstring_from_COFF_symbol_name (
832 symtab_i->Name, strtab
835 oc->errMsg("Out of memory when copying PEi386 symbol");
839 /* for IMAGE_SYMCLASS_EXTERNAL
840 && !IMAGE_SYM_UNDEFINED,
841 the address of the symbol is:
842 address of relevant section + offset in section
844 sectabent = (COFF_section*)
845 myindex ( sizeof_COFF_section,
846 symtab_i->SectionNumber-1,
848 addr = ((UChar*)(oc->oImage))
849 + (sectabent->PointerToRawData
851 /* fprintf ( stderr, "addSymbol %p `%s'\n", addr,sname); */
852 if (!addSymbol(oc,sname,addr)) return FALSE;
854 i += symtab_i->NumberOfAuxSymbols;
858 /* Copy section information into the ObjectCode. */
859 for (i = 0; i < hdr->NumberOfSections; i++) {
864 = HUGS_SECTIONKIND_OTHER;
865 COFF_section* sectab_i
867 myindex ( sizeof_COFF_section, i, sectab );
868 /* fprintf ( stderr, "section name = %s\n", sectab_i->Name ); */
871 /* I'm sure this is the Right Way to do it. However, the
872 alternative of testing the sectab_i->Name field seems to
875 if (sectab_i->Characteristics & IMAGE_SCN_CNT_CODE ||
876 sectab_i->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
877 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
880 if (0==strcmp(".text",sectab_i->Name))
881 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
882 if (0==strcmp(".data",sectab_i->Name) ||
883 0==strcmp(".bss",sectab_i->Name))
884 kind = HUGS_SECTIONKIND_RWDATA;
886 start = ((UChar*)(oc->oImage))
887 + sectab_i->PointerToRawData;
889 + sectab_i->SizeOfRawData - 1;
891 if (kind != HUGS_SECTIONKIND_OTHER) {
892 addSection ( oc, start, end, kind );
894 fprintf ( stderr, "unknown section name = `%s'\n",
896 oc->errMsg("Unknown PEi386 section name");
905 static int ocResolve_PEi386 ( ObjectCode* oc, int verb )
908 COFF_section* sectab;
917 char symbol[1000]; // ToDo
919 hdr = (COFF_header*)(oc->oImage);
920 sectab = (COFF_section*) (
921 ((UChar*)(oc->oImage))
922 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
924 symtab = (COFF_symbol*) (
925 ((UChar*)(oc->oImage))
926 + hdr->PointerToSymbolTable
928 strtab = ((UChar*)(oc->oImage))
929 + hdr->PointerToSymbolTable
930 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
932 for (i = 0; i < hdr->NumberOfSections; i++) {
933 COFF_section* sectab_i
935 myindex ( sizeof_COFF_section, i, sectab );
938 ((UChar*)(oc->oImage)) + sectab_i->PointerToRelocations
940 for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
944 myindex ( sizeof_COFF_reloc, j, reltab );
946 /* the location to patch */
948 ((UChar*)(oc->oImage))
949 + (sectab_i->PointerToRawData
950 + reltab_j->VirtualAddress)
952 /* the existing contents of pP */
954 /* the symbol to connect to */
956 myindex ( sizeof_COFF_symbol,
957 reltab_j->SymbolTableIndex, symtab );
960 "reloc sec %2d num %3d: type 0x%-4x "
961 "vaddr 0x%-8x name `",
963 (UInt32)reltab_j->Type,
964 reltab_j->VirtualAddress );
965 printName ( sym->Name, strtab );
966 fprintf ( stderr, "'\n" );
969 if (sym->StorageClass == IMAGE_SYM_CLASS_STATIC) {
970 COFF_section* section_sym
971 = findPEi386SectionCalled ( oc, sym->Name );
973 fprintf ( stderr, "bad section = `%s'\n", sym->Name );
974 oc->errMsg("Can't find abovementioned PEi386 section");
977 S = ((UInt32)(oc->oImage))
978 + (section_sym->PointerToRawData
981 copyName ( sym->Name, strtab, symbol, 1000 );
982 zapTrailingAtSign ( symbol );
983 S = (UInt32) ocLookupSym ( oc, symbol );
985 S = (UInt32)(oc->clientLookup ( symbol ));
988 strcpy(errtxt,oc->objFileName);
989 strcat(errtxt,": unresolvable reference to: ");
990 strcat(errtxt,symbol);
996 switch (reltab_j->Type) {
997 case IMAGE_REL_I386_DIR32:
1000 case IMAGE_REL_I386_REL32:
1001 /* Tricky. We have to insert a displacement at
1002 pP which, when added to the PC for the _next_
1003 insn, gives the address of the target (S).
1004 Problem is to know the address of the next insn
1005 when we only know pP. We assume that this
1006 literal field is always the last in the insn,
1007 so that the address of the next insn is pP+4
1008 -- hence the constant 4.
1009 Also I don't know if A should be added, but so
1010 far it has always been zero.
1013 *pP = S - ((UInt32)pP) - 4;
1017 "unhandled PEi386 relocation type %d\n",
1019 oc->errMsg("unhandled PEi386 relocation type");
1029 #endif /* defined(cygwin32_TARGET_OS) */
1032 /* --------------------------------------------------------------------------
1033 * ELF specifics (Linux, Solaris)
1034 * ------------------------------------------------------------------------*/
1036 #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
1043 static char* findElfSection ( void* objImage, Elf32_Word sh_type )
1046 char* ehdrC = (char*)objImage;
1047 Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
1048 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1050 for (i = 0; i < ehdr->e_shnum; i++) {
1051 if (shdr[i].sh_type == sh_type &&
1052 i != ehdr->e_shstrndx) {
1053 ptr = ehdrC + shdr[i].sh_offset;
1061 static int ocVerifyImage_ELF ( ObjectCode* oc, int verb )
1065 int i, j, nent, nstrtab, nsymtabs;
1069 char* ehdrC = (char*)(oc->oImage);
1070 Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
1072 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
1073 ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
1074 ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
1075 ehdr->e_ident[EI_MAG3] != ELFMAG3) {
1076 oc->errMsg("Not an ELF header");
1079 if (verb) fprintf ( stderr, "Is an ELF header\n" );
1081 if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
1082 oc->errMsg("Not 32 bit ELF" );
1085 if (verb) fprintf ( stderr, "Is 32 bit ELF\n" );
1087 if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
1088 if (verb) fprintf ( stderr, "Is little-endian\n" );
1090 if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
1091 if (verb) fprintf ( stderr, "Is big-endian\n" );
1093 oc->errMsg("Unknown endiannness");
1097 if (ehdr->e_type != ET_REL) {
1098 oc->errMsg("Not a relocatable object (.o) file");
1101 if (verb) fprintf ( stderr, "Is a relocatable object (.o) file\n" );
1103 if (verb) fprintf ( stderr, "Architecture is " );
1104 switch (ehdr->e_machine) {
1105 case EM_386: if (verb) fprintf ( stderr, "x86\n" ); break;
1106 case EM_SPARC: if (verb) fprintf ( stderr, "sparc\n" ); break;
1107 default: if (verb) fprintf ( stderr, "unknown\n" );
1108 oc->errMsg("Unknown architecture");
1114 "\nSection header table: start %d, n_entries %d, ent_size %d\n",
1115 ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize );
1117 assert (ehdr->e_shentsize == sizeof(Elf32_Shdr));
1119 shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1121 if (ehdr->e_shstrndx == SHN_UNDEF) {
1122 oc->errMsg("No section header string table");
1125 if (verb) fprintf ( stderr,"Section header string table is section %d\n",
1127 sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1130 for (i = 0; i < ehdr->e_shnum; i++) {
1131 if (verb) fprintf ( stderr, "%2d: ", i );
1132 if (verb) fprintf ( stderr, "type=%2d ", shdr[i].sh_type );
1133 if (verb) fprintf ( stderr, "size=%4d ", shdr[i].sh_size );
1134 if (verb) fprintf ( stderr, "offs=%4d ", shdr[i].sh_offset );
1135 if (verb) fprintf ( stderr, " (%p .. %p) ",
1136 ehdrC + shdr[i].sh_offset,
1137 ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1);
1139 if (shdr[i].sh_type == SHT_REL && verb) fprintf ( stderr, "Rel " ); else
1140 if (shdr[i].sh_type == SHT_RELA && verb) fprintf ( stderr, "RelA " ); else
1141 if (verb) fprintf ( stderr, " " );
1142 if (sh_strtab && verb)
1143 fprintf ( stderr, "sname=%s", sh_strtab + shdr[i].sh_name );
1144 if (verb) fprintf ( stderr, "\n" );
1147 if (verb) fprintf ( stderr, "\n\nString tables\n" );
1150 for (i = 0; i < ehdr->e_shnum; i++) {
1151 if (shdr[i].sh_type == SHT_STRTAB &&
1152 i != ehdr->e_shstrndx) {
1154 fprintf ( stderr, " section %d is a normal string table\n", i );
1155 strtab = ehdrC + shdr[i].sh_offset;
1160 oc->errMsg("WARNING: no string tables, or too many");
1165 if (verb) fprintf ( stderr, "\n\nSymbol tables\n" );
1166 for (i = 0; i < ehdr->e_shnum; i++) {
1167 if (shdr[i].sh_type != SHT_SYMTAB) continue;
1168 if (verb) fprintf ( stderr, "section %d is a symbol table\n", i );
1170 stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
1171 nent = shdr[i].sh_size / sizeof(Elf32_Sym);
1172 if (verb) fprintf ( stderr, " number of entries is apparently %d (%d rem)\n",
1174 shdr[i].sh_size % sizeof(Elf32_Sym)
1176 if (0 != shdr[i].sh_size % sizeof(Elf32_Sym)) {
1177 oc->errMsg("non-integral number of symbol table entries");
1180 for (j = 0; j < nent; j++) {
1181 if (verb) fprintf ( stderr, " %2d ", j );
1182 if (verb) fprintf ( stderr, " sec=%-5d size=%-3d val=%-5p ",
1183 (int)stab[j].st_shndx,
1184 (int)stab[j].st_size,
1185 (char*)stab[j].st_value );
1187 if (verb) fprintf ( stderr, "type=" );
1188 switch (ELF32_ST_TYPE(stab[j].st_info)) {
1189 case STT_NOTYPE: if (verb) fprintf ( stderr, "notype " ); break;
1190 case STT_OBJECT: if (verb) fprintf ( stderr, "object " ); break;
1191 case STT_FUNC : if (verb) fprintf ( stderr, "func " ); break;
1192 case STT_SECTION: if (verb) fprintf ( stderr, "section" ); break;
1193 case STT_FILE: if (verb) fprintf ( stderr, "file " ); break;
1194 default: if (verb) fprintf ( stderr, "? " ); break;
1196 if (verb) fprintf ( stderr, " " );
1198 if (verb) fprintf ( stderr, "bind=" );
1199 switch (ELF32_ST_BIND(stab[j].st_info)) {
1200 case STB_LOCAL : if (verb) fprintf ( stderr, "local " ); break;
1201 case STB_GLOBAL: if (verb) fprintf ( stderr, "global" ); break;
1202 case STB_WEAK : if (verb) fprintf ( stderr, "weak " ); break;
1203 default: if (verb) fprintf ( stderr, "? " ); break;
1205 if (verb) fprintf ( stderr, " " );
1207 if (verb) fprintf ( stderr, "name=%s\n", strtab + stab[j].st_name );
1211 if (nsymtabs == 0) {
1212 oc->errMsg("Didn't find any symbol tables");
1220 static int ocGetNames_ELF ( ObjectCode* oc, int verb )
1225 char* ehdrC = (char*)(oc->oImage);
1226 Elf32_Ehdr* ehdr = (Elf32_Ehdr*)ehdrC;
1227 char* strtab = findElfSection ( ehdrC, SHT_STRTAB );
1228 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1229 char* sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1232 oc->errMsg("ELF: no strtab!");
1237 for (i = 0; i < ehdr->e_shnum; i++) {
1239 /* make a HugsDLSection entry for relevant sections */
1240 OSectionKind kind = HUGS_SECTIONKIND_OTHER;
1241 if (0==strcmp(".data",sh_strtab+shdr[i].sh_name) ||
1242 0==strcmp(".data1",sh_strtab+shdr[i].sh_name))
1243 kind = HUGS_SECTIONKIND_RWDATA;
1244 if (0==strcmp(".text",sh_strtab+shdr[i].sh_name) ||
1245 0==strcmp(".rodata",sh_strtab+shdr[i].sh_name) ||
1246 0==strcmp(".rodata1",sh_strtab+shdr[i].sh_name))
1247 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
1248 if (kind != HUGS_SECTIONKIND_OTHER)
1251 ehdrC + shdr[i].sh_offset,
1252 ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1,
1256 if (shdr[i].sh_type != SHT_SYMTAB) continue;
1258 /* copy stuff into this module's object symbol table */
1259 stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
1260 nent = shdr[i].sh_size / sizeof(Elf32_Sym);
1261 for (j = 0; j < nent; j++) {
1262 if ( ( ELF32_ST_BIND(stab[j].st_info)==STB_GLOBAL ||
1263 ELF32_ST_BIND(stab[j].st_info)==STB_LOCAL
1266 ( ELF32_ST_TYPE(stab[j].st_info)==STT_FUNC ||
1267 ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT)
1268 /* || ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE */
1270 char* nm = strtab + stab[j].st_name;
1272 + shdr[ stab[j].st_shndx ].sh_offset
1277 fprintf(stderr, "addOTabName: %10p %s %s\n",
1278 ad, oc->objFileName, nm );
1279 if (!addSymbol ( oc, nm, ad )) return FALSE;
1283 fprintf(stderr, "skipping `%s'\n", strtab + stab[j].st_name );
1291 static int ocResolve_ELF ( ObjectCode* oc, int verb )
1293 char symbol[1000]; // ToDo
1296 Elf32_Sym* stab = NULL;
1297 char* ehdrC = (char*)(oc->oImage);
1298 Elf32_Ehdr* ehdr = (Elf32_Ehdr*) ehdrC;
1299 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1302 /* first find "the" symbol table */
1303 stab = (Elf32_Sym*) findElfSection ( ehdrC, SHT_SYMTAB );
1305 /* also go find the string table */
1306 strtab = findElfSection ( ehdrC, SHT_STRTAB );
1308 if (!stab || !strtab) {
1309 oc->errMsg("can't find string or symbol table");
1313 for (i = 0; i < ehdr->e_shnum; i++) {
1314 if (shdr[i].sh_type == SHT_REL ) {
1315 Elf32_Rel* rtab = (Elf32_Rel*) (ehdrC + shdr[i].sh_offset);
1316 int nent = shdr[i].sh_size / sizeof(Elf32_Rel);
1317 int target_shndx = shdr[i].sh_info;
1318 int symtab_shndx = shdr[i].sh_link;
1319 stab = (Elf32_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
1320 targ = (Elf32_Word*)(ehdrC + shdr[ target_shndx ].sh_offset);
1323 "relocations for section %d using symtab %d\n",
1324 target_shndx, symtab_shndx );
1325 for (j = 0; j < nent; j++) {
1326 Elf32_Addr offset = rtab[j].r_offset;
1327 Elf32_Word info = rtab[j].r_info;
1329 Elf32_Addr P = ((Elf32_Addr)targ) + offset;
1330 Elf32_Word* pP = (Elf32_Word*)P;
1334 if (verb) fprintf ( stderr, "Rel entry %3d is raw(%6p %6p) ",
1335 j, (void*)offset, (void*)info );
1337 if (verb) fprintf ( stderr, " ZERO\n" );
1340 /* First see if it is a nameless local symbol. */
1341 if (stab[ ELF32_R_SYM(info)].st_name == 0) {
1342 if (verb) fprintf ( stderr, "(noname) ");
1343 S = (Elf32_Addr)(ehdrC
1344 + shdr[stab[ELF32_R_SYM(info)].st_shndx ].sh_offset
1345 + stab[ELF32_R_SYM(info)].st_value
1347 strcpy ( symbol, "(noname)");
1349 /* No? Perhaps it's a named symbol in this file. */
1350 strcpy ( symbol, strtab+stab[ ELF32_R_SYM(info)].st_name );
1351 if (verb) fprintf ( stderr, "`%s' ", symbol );
1352 S = (Elf32_Addr)ocLookupSym ( oc, symbol );
1354 /* No? Ok, too hard. Hand the problem to the client.
1355 And if that fails, we're outta options.
1357 S = (Elf32_Addr)(oc->clientLookup ( symbol ) );
1360 if (verb) fprintf ( stderr, "resolves to %p\n", (void*)S );
1363 strcpy(errtxt,oc->objFileName);
1364 strcat(errtxt,": unresolvable reference to: ");
1365 strcat(errtxt,symbol);
1370 /* fprintf ( stderr, "Reloc: P = %p S = %p A = %p\n\n",
1371 (void*)P, (void*)S, (void*)A );
1373 switch (ELF32_R_TYPE(info)) {
1374 case R_386_32: *pP = S + A; break;
1375 case R_386_PC32: *pP = S + A - P; break;
1376 default: fprintf(stderr,
1377 "unhandled ELF relocation type %d\n",
1378 ELF32_R_TYPE(info));
1379 oc->errMsg("unhandled ELF relocation type");
1386 if (shdr[i].sh_type == SHT_RELA) {
1387 oc->errMsg("RelA style reloc table -- not yet done");
1396 #endif /* defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) */
1400 /*-------------------------------------------------------------------------*/