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;
88 int ocLoadImage ( ObjectCode* oc, int verb )
92 assert (oc && oc->status==OBJECT_NOTINUSE);
93 if (verb) fprintf(stderr, "ocLoadImage %s\n", oc->objFileName );
94 f = fopen(oc->objFileName, "rb");
96 (oc->errMsg(hackyAppend("ocLoadImage: can't read: ",
100 n = fread ( oc->oImage, 1, oc->objFileSize, f );
101 if (n != oc->objFileSize) {
103 oc->errMsg(hackyAppend("ocLoadImage: I/O error whilst reading: ",
107 oc->status = OBJECT_OIMAGE;
108 if (verb) fprintf(stderr, "ocLoadImage %s: read %d bytes\n",
109 oc->objFileName, oc->objFileSize );
114 /* returns 1 if ok, 0 if error */
115 int ocVerifyImage ( ObjectCode* oc, int verb )
118 assert (oc && oc->status==OBJECT_OIMAGE);
119 if (verb) fprintf(stderr, "ocVerifyImage: begin\n");
120 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
121 ret = ocVerifyImage_ELF ( oc, verb );
122 # elif defined(cygwin32_TARGET_OS)
123 ret = ocVerifyImage_PEi386 ( oc, verb );
125 oc->errMsg("ocVerifyImage: not implemented on this platform");
128 if (verb) fprintf(stderr, "ocVerifyImage: done, status = %d", ret);
130 if (ret) oc->status = OBJECT_VERIFIED;
135 /* returns 1 if ok, 0 if error */
136 int ocGetNames ( ObjectCode* oc, int verb )
139 assert (oc && oc->status==OBJECT_VERIFIED);
140 if (verb) fprintf(stderr, "ocGetNames: begin\n");
141 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
142 ret = ocGetNames_ELF ( oc, verb );
143 # elif defined(cygwin32_TARGET_OS)
144 ret = ocGetNames_PEi386 ( oc, verb );
146 oc->errMsg("ocGetNames: not implemented on this platform");
149 if (verb) fprintf(stderr, "ocGetNames: done, status = %d\n", ret);
150 if (ret) ret = sortSymbols(oc);
151 if (ret) oc->status = OBJECT_HAVENAMES;
156 /* returns 1 if ok, 0 if error */
157 int ocResolve ( ObjectCode* oc, int verb )
160 assert (oc && oc->status==OBJECT_HAVENAMES);
161 if (verb) fprintf(stderr, "ocResolve: begin\n");
162 # if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
163 ret = ocResolve_ELF ( oc, verb );
164 # elif defined(cygwin32_TARGET_OS)
165 ret = ocResolve_PEi386 ( oc, verb );
167 oc->errMsg("ocResolve: not implemented on this platform");
170 if (verb) fprintf(stderr, "ocResolve: done, status = %d\n", ret);
171 if (ret) oc->status = OBJECT_RESOLVED;
176 void ocFree ( ObjectCode* oc )
179 if (oc->oImage) free(oc->oImage);
180 if (oc->oTab) free(oc->oTab);
181 if (oc->sectionTab) free(oc->sectionTab);
187 /* --------------------------------------------------------------------------
188 * Simple, dynamically expandable association tables
189 * ------------------------------------------------------------------------*/
191 /* A bit tricky. Assumes that if tab==NULL, then
192 currUsed and *currSize must be zero.
193 Returns NULL if expansion failed.
195 static void* genericExpand ( void* tab,
196 int* currSize, int currUsed,
197 int initSize, int elemSize )
201 if (currUsed < *currSize) return tab;
202 size2 = (*currSize == 0) ? initSize : (2 * *currSize);
203 tab2 = malloc ( size2 * elemSize );
204 if (!tab2) return NULL;
206 memcpy ( tab2, tab, elemSize * *currSize );
208 if (tab) free ( tab );
213 /* returns 1 if success, 0 if error */
214 static int addSymbol ( ObjectCode* oc, char* nm, void* ad )
218 if (oc->clientWantsSymbol && !oc->clientWantsSymbol(nm))
222 = genericExpand ( oc->oTab,
228 oc->errMsg("addSymbol: malloc failed whilst expanding table");
232 oc->oTab[ oc->usedoTab ].nm = nm;
233 oc->oTab[ oc->usedoTab ].ad = ad;
239 /* Reorder symbol table so that symbols are in alphabetical order.
240 Detects an error if, after sorting, any two symbols are the same,
241 since this would imply that the same symbol has been inserted more
242 than once. Returns 1 if success, 0 if error.
244 static int sortSymbols ( ObjectCode* oc )
247 = { 1, 4, 13, 40, 121, 364, 1093, 3280,
248 9841, 29524, 88573, 265720, 797161, 2391484 };
251 int hi = oc->usedoTab-1;
252 int i, j, h, bigN, hp;
255 bigN = hi - lo + 1; if (bigN < 2) return 1;
256 hp = 0; while (incs[hp] < bigN) hp++; hp--;
258 for (; hp >= 0; hp--) {
265 while (strcmp(oc->oTab[j-h].nm, v.nm) > 0) {
266 oc->oTab[j] = oc->oTab[j-h];
268 if (j <= (lo + h - 1)) break;
275 for (i = 1; i < oc->usedoTab; i++) {
276 j = strcmp(oc->oTab[i-1].nm, oc->oTab[i].nm);
278 oc->errMsg("sortSymbols: sorting failed");
282 oc->errMsg("sortSymbols: duplicate symbols in object file:");
283 oc->errMsg(oc->oTab[i].nm);
292 /* returns 1 if success, 0 if error */
293 static int addSection ( ObjectCode* oc, void* start, void* end, OSectionKind sect )
296 = genericExpand ( oc->sectionTab,
297 &(oc->sizesectionTab),
299 4, sizeof(OSection) );
301 oc->errMsg("addSection: malloc failed whilst expanding table");
304 oc->sectionTab = newTab;
305 oc->sectionTab[ oc->usedsectionTab ].start = start;
306 oc->sectionTab[ oc->usedsectionTab ].end = end;
307 oc->sectionTab[ oc->usedsectionTab ].kind = sect;
308 oc->usedsectionTab++;
313 void* ocLookupSym ( ObjectCode* oc, char* sym )
315 int lo, hi, mid, cmp;
318 if (oc->status != OBJECT_HAVENAMES
319 && oc->status != OBJECT_RESOLVED) {
320 oc->errMsg("ocLookupSym: no symbols available");
324 /* Originally used a sequential search; should still work
325 for (i = 0; i < oc->usedoTab; i++) {
328 "ocLookupSym: request %s, table has %s\n",
329 sym, oc->oTab[i].nm );
330 if (0==strcmp(sym,oc->oTab[i].nm))
331 return oc->oTab[i].ad;
338 /* Invariant: the unsearched area is oc->oTab[lo .. hi] inclusive. */
339 if (hi < lo) return NULL;
341 cmp = strcmp(sym, oc->oTab[mid].nm);
342 if (cmp == 0) return oc->oTab[mid].ad;
343 if (cmp < 0) hi = mid-1;
344 if (cmp > 0) lo = mid+1;
349 char* ocLookupAddr ( ObjectCode* oc, void* addr )
354 if (oc->status != OBJECT_HAVENAMES
355 && oc->status != OBJECT_RESOLVED) {
356 oc->errMsg("ocLookupAddr: no symbols available");
360 for (i = 0; i < oc->usedoTab; i++) {
361 if (addr == oc->oTab[i].ad)
362 return oc->oTab[i].nm;
368 OSectionKind ocLookupSection ( ObjectCode* oc, void* addr )
373 if (oc->status != OBJECT_HAVENAMES
374 && oc->status != OBJECT_RESOLVED) {
375 oc->errMsg("ocLookupSection: no symbols available");
376 return HUGS_SECTIONKIND_NOINFOAVAIL;
380 for (i = 0; i < oc->usedsectionTab; i++) {
381 if (oc->sectionTab[i].start <= addr
382 && addr <= oc->sectionTab[i].end)
383 return oc->sectionTab[i].kind;
386 return HUGS_SECTIONKIND_NOINFOAVAIL;
390 /* Ghastly append which leaks space. But we only use it for
391 error messages -- that's my excuse.
393 static char* hackyAppend ( char* s1, char* s2 )
395 char* res = malloc ( 4 + strlen(s1) + strlen(s2) );
397 fprintf ( stderr, "hugs: fatal: hackyAppend\n\t%s\n\t%s\n", s1, s2 );
405 /* --------------------------------------------------------------------------
406 * PEi386 specifics (cygwin32)
407 * ------------------------------------------------------------------------*/
409 /* The information for this linker comes from
410 Microsoft Portable Executable
411 and Common Object File Format Specification
412 revision 5.1 January 1998
413 which SimonM says comes from the MS Developer Network CDs.
417 #if defined(cygwin32_TARGET_OS)
423 typedef unsigned char UChar;
424 typedef unsigned short UInt16;
425 typedef unsigned int UInt32;
432 UInt16 NumberOfSections;
433 UInt32 TimeDateStamp;
434 UInt32 PointerToSymbolTable;
435 UInt32 NumberOfSymbols;
436 UInt16 SizeOfOptionalHeader;
437 UInt16 Characteristics;
441 #define sizeof_COFF_header 20
448 UInt32 VirtualAddress;
449 UInt32 SizeOfRawData;
450 UInt32 PointerToRawData;
451 UInt32 PointerToRelocations;
452 UInt32 PointerToLinenumbers;
453 UInt16 NumberOfRelocations;
454 UInt16 NumberOfLineNumbers;
455 UInt32 Characteristics;
459 #define sizeof_COFF_section 40
466 UInt16 SectionNumber;
469 UChar NumberOfAuxSymbols;
473 #define sizeof_COFF_symbol 18
478 UInt32 VirtualAddress;
479 UInt32 SymbolTableIndex;
484 #define sizeof_COFF_reloc 10
487 /* From PE spec doc, section 3.3.2 */
488 #define IMAGE_FILE_RELOCS_STRIPPED 0x0001
489 #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
490 #define IMAGE_FILE_DLL 0x2000
491 #define IMAGE_FILE_SYSTEM 0x1000
492 #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
493 #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
494 #define IMAGE_FILE_32BIT_MACHINE 0x0100
496 /* From PE spec doc, section 5.4.2 and 5.4.4 */
497 #define IMAGE_SYM_CLASS_EXTERNAL 2
498 #define IMAGE_SYM_CLASS_STATIC 3
499 #define IMAGE_SYM_UNDEFINED 0
501 /* From PE spec doc, section 4.1 */
502 #define IMAGE_SCN_CNT_CODE 0x00000020
503 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
505 /* From PE spec doc, section 5.2.1 */
506 #define IMAGE_REL_I386_DIR32 0x0006
507 #define IMAGE_REL_I386_REL32 0x0014
510 /* We use myindex to calculate array addresses, rather than
511 simply doing the normal subscript thing. That's because
512 some of the above structs have sizes which are not
513 a whole number of words. GCC rounds their sizes up to a
514 whole number of words, which means that the address calcs
515 arising from using normal C indexing or pointer arithmetic
516 are just plain wrong. Sigh.
518 static UChar* myindex ( int scale, int index, void* base )
521 ((UChar*)base) + scale * index;
525 static void printName ( UChar* name, UChar* strtab )
527 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
528 UInt32 strtab_offset = * (UInt32*)(name+4);
529 fprintf ( stderr, "%s", strtab + strtab_offset );
532 for (i = 0; i < 8; i++) {
533 if (name[i] == 0) break;
534 fprintf ( stderr, "%c", name[i] );
540 static void copyName ( UChar* name, UChar* strtab,
541 UChar* dst, int dstSize )
543 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
544 UInt32 strtab_offset = * (UInt32*)(name+4);
545 strncpy ( dst, strtab+strtab_offset, dstSize );
551 if (name[i] == 0) break;
560 static UChar* cstring_from_COFF_symbol_name ( UChar* name,
564 /* If the string is longer than 8 bytes, look in the
565 string table for it -- this will be correctly zero terminated.
567 if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
568 UInt32 strtab_offset = * (UInt32*)(name+4);
569 return ((UChar*)strtab) + strtab_offset;
571 /* Otherwise, if shorter than 8 bytes, return the original,
572 which by defn is correctly terminated.
574 if (name[7]==0) return name;
575 /* The annoying case: 8 bytes. Copy into a temporary
576 (which is never freed ...)
580 strncpy(newstr,name,8);
587 /* Just compares the short names (first 8 chars) */
588 static COFF_section* findPEi386SectionCalled ( ObjectCode* oc,
593 = (COFF_header*)(oc->oImage);
596 ((UChar*)(oc->oImage))
597 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
599 for (i = 0; i < hdr->NumberOfSections; i++) {
602 COFF_section* section_i
604 myindex ( sizeof_COFF_section, i, sectab );
605 n1 = (UChar*) &(section_i->Name);
607 if (n1[0]==n2[0] && n1[1]==n2[1] && n1[2]==n2[2] &&
608 n1[3]==n2[3] && n1[4]==n2[4] && n1[5]==n2[5] &&
609 n1[6]==n2[6] && n1[7]==n2[7])
617 static void zapTrailingAtSign ( UChar* sym )
620 if (sym[0] == 0) return;
622 while (sym[i] != 0) i++;
625 while (j > 0 && isdigit(sym[j])) j--;
626 if (j > 0 && sym[j] == '@' && j != i) sym[j] = 0;
630 static int ocVerifyImage_PEi386 ( ObjectCode* oc, int verb )
634 COFF_section* sectab;
638 hdr = (COFF_header*)(oc->oImage);
639 sectab = (COFF_section*) (
640 ((UChar*)(oc->oImage))
641 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
643 symtab = (COFF_symbol*) (
644 ((UChar*)(oc->oImage))
645 + hdr->PointerToSymbolTable
647 strtab = ((UChar*)(oc->oImage))
648 + hdr->PointerToSymbolTable
649 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
651 if (hdr->Machine != 0x14c) {
652 oc->errMsg("Not x86 PEi386");
655 if (hdr->SizeOfOptionalHeader != 0) {
656 oc->errMsg("PEi386 with nonempty optional header");
659 if ( /* (hdr->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) || */
660 (hdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) ||
661 (hdr->Characteristics & IMAGE_FILE_DLL) ||
662 (hdr->Characteristics & IMAGE_FILE_SYSTEM) ) {
663 oc->errMsg("Not a PEi386 object file");
666 if ( (hdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI) ||
667 !(hdr->Characteristics & IMAGE_FILE_32BIT_MACHINE) ) {
668 oc->errMsg("Invalid PEi386 word size or endiannness");
672 if (!verb) return TRUE;
673 /* No further verification after this point; only debug printing. */
676 "sectab offset = %d\n", ((UChar*)sectab) - ((UChar*)hdr) );
678 "symtab offset = %d\n", ((UChar*)symtab) - ((UChar*)hdr) );
680 "strtab offset = %d\n", ((UChar*)strtab) - ((UChar*)hdr) );
682 fprintf ( stderr, "\n" );
684 "Machine: 0x%x\n", (UInt32)(hdr->Machine) );
686 "# sections: %d\n", (UInt32)(hdr->NumberOfSections) );
688 "time/date: 0x%x\n", (UInt32)(hdr->TimeDateStamp) );
690 "symtab offset: %d\n", (UInt32)(hdr->PointerToSymbolTable) );
692 "# symbols: %d\n", (UInt32)(hdr->NumberOfSymbols) );
694 "sz of opt hdr: %d\n", (UInt32)(hdr->SizeOfOptionalHeader) );
696 "characteristics: 0x%x\n", (UInt32)(hdr->Characteristics) );
698 fprintf ( stderr, "\n" );
699 fprintf ( stderr, "string table has size 0x%x\n", * (UInt32*)strtab );
700 fprintf ( stderr, "---START of string table---\n");
701 for (i = 4; i < *(UInt32*)strtab; i++) {
703 fprintf ( stderr, "\n"); else
704 fprintf( stderr, "%c", strtab[i] );
706 fprintf ( stderr, "--- END of string table---\n");
708 fprintf ( stderr, "\n" );
709 for (i = 0; i < hdr->NumberOfSections; i++) {
711 COFF_section* sectab_i
713 myindex ( sizeof_COFF_section, i, sectab );
720 printName ( sectab_i->Name, strtab );
729 sectab_i->VirtualSize,
730 sectab_i->VirtualAddress,
731 sectab_i->SizeOfRawData,
732 sectab_i->PointerToRawData,
733 sectab_i->NumberOfRelocations,
734 sectab_i->PointerToRelocations
736 reltab = (COFF_reloc*) (
737 ((UChar*)(oc->oImage)) + sectab_i->PointerToRelocations
739 for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
741 COFF_reloc* rel = (COFF_reloc*)
742 myindex ( sizeof_COFF_reloc, j, reltab );
744 " type 0x%-4x vaddr 0x%-8x name `",
746 rel->VirtualAddress );
748 myindex ( sizeof_COFF_symbol, rel->SymbolTableIndex, symtab );
749 printName ( sym->Name, strtab );
750 fprintf ( stderr, "'\n" );
752 fprintf ( stderr, "\n" );
756 fprintf ( stderr, "\n" );
759 COFF_symbol* symtab_i;
760 if (i >= hdr->NumberOfSymbols) break;
761 symtab_i = (COFF_symbol*)
762 myindex ( sizeof_COFF_symbol, i, symtab );
768 printName ( symtab_i->Name, strtab );
777 (Int32)(symtab_i->SectionNumber) - 1,
778 (UInt32)symtab_i->Type,
779 (UInt32)symtab_i->StorageClass,
780 (UInt32)symtab_i->NumberOfAuxSymbols
782 i += symtab_i->NumberOfAuxSymbols;
786 fprintf ( stderr, "\n" );
792 static int ocGetNames_PEi386 ( ObjectCode* oc, int verb )
795 COFF_section* sectab;
803 hdr = (COFF_header*)(oc->oImage);
804 sectab = (COFF_section*) (
805 ((UChar*)(oc->oImage))
806 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
808 symtab = (COFF_symbol*) (
809 ((UChar*)(oc->oImage))
810 + hdr->PointerToSymbolTable
812 strtab = ((UChar*)(oc->oImage))
813 + hdr->PointerToSymbolTable
814 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
816 /* Copy exported symbols into the ObjectCode. */
819 COFF_symbol* symtab_i;
820 if (i >= hdr->NumberOfSymbols) break;
821 symtab_i = (COFF_symbol*)
822 myindex ( sizeof_COFF_symbol, i, symtab );
824 if (symtab_i->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
825 symtab_i->SectionNumber != IMAGE_SYM_UNDEFINED) {
827 /* This symbol is global and defined, viz, exported */
828 COFF_section* sectabent;
830 sname = cstring_from_COFF_symbol_name (
831 symtab_i->Name, strtab
834 oc->errMsg("Out of memory when copying PEi386 symbol");
838 /* for IMAGE_SYMCLASS_EXTERNAL
839 && !IMAGE_SYM_UNDEFINED,
840 the address of the symbol is:
841 address of relevant section + offset in section
843 sectabent = (COFF_section*)
844 myindex ( sizeof_COFF_section,
845 symtab_i->SectionNumber-1,
847 addr = ((UChar*)(oc->oImage))
848 + (sectabent->PointerToRawData
850 /* fprintf ( stderr, "addSymbol %p `%s'\n", addr,sname); */
851 if (!addSymbol(oc,sname,addr)) return FALSE;
853 i += symtab_i->NumberOfAuxSymbols;
857 /* Copy section information into the ObjectCode. */
858 for (i = 0; i < hdr->NumberOfSections; i++) {
863 = HUGS_SECTIONKIND_OTHER;
864 COFF_section* sectab_i
866 myindex ( sizeof_COFF_section, i, sectab );
867 /* fprintf ( stderr, "section name = %s\n", sectab_i->Name ); */
870 /* I'm sure this is the Right Way to do it. However, the
871 alternative of testing the sectab_i->Name field seems to
874 if (sectab_i->Characteristics & IMAGE_SCN_CNT_CODE ||
875 sectab_i->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
876 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
879 if (0==strcmp(".text",sectab_i->Name))
880 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
881 if (0==strcmp(".data",sectab_i->Name) ||
882 0==strcmp(".bss",sectab_i->Name))
883 kind = HUGS_SECTIONKIND_RWDATA;
885 start = ((UChar*)(oc->oImage))
886 + sectab_i->PointerToRawData;
888 + sectab_i->SizeOfRawData - 1;
890 if (kind != HUGS_SECTIONKIND_OTHER) {
891 addSection ( oc, start, end, kind );
893 fprintf ( stderr, "unknown section name = `%s'\n",
895 oc->errMsg("Unknown PEi386 section name");
904 static int ocResolve_PEi386 ( ObjectCode* oc, int verb )
907 COFF_section* sectab;
916 char symbol[1000]; // ToDo
918 hdr = (COFF_header*)(oc->oImage);
919 sectab = (COFF_section*) (
920 ((UChar*)(oc->oImage))
921 + sizeof_COFF_header + hdr->SizeOfOptionalHeader
923 symtab = (COFF_symbol*) (
924 ((UChar*)(oc->oImage))
925 + hdr->PointerToSymbolTable
927 strtab = ((UChar*)(oc->oImage))
928 + hdr->PointerToSymbolTable
929 + hdr->NumberOfSymbols * sizeof_COFF_symbol;
931 for (i = 0; i < hdr->NumberOfSections; i++) {
932 COFF_section* sectab_i
934 myindex ( sizeof_COFF_section, i, sectab );
937 ((UChar*)(oc->oImage)) + sectab_i->PointerToRelocations
939 for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
943 myindex ( sizeof_COFF_reloc, j, reltab );
945 /* the location to patch */
947 ((UChar*)(oc->oImage))
948 + (sectab_i->PointerToRawData
949 + reltab_j->VirtualAddress)
951 /* the existing contents of pP */
953 /* the symbol to connect to */
955 myindex ( sizeof_COFF_symbol,
956 reltab_j->SymbolTableIndex, symtab );
959 "reloc sec %2d num %3d: type 0x%-4x "
960 "vaddr 0x%-8x name `",
962 (UInt32)reltab_j->Type,
963 reltab_j->VirtualAddress );
964 printName ( sym->Name, strtab );
965 fprintf ( stderr, "'\n" );
968 if (sym->StorageClass == IMAGE_SYM_CLASS_STATIC) {
969 COFF_section* section_sym
970 = findPEi386SectionCalled ( oc, sym->Name );
972 fprintf ( stderr, "bad section = `%s'\n", sym->Name );
973 oc->errMsg("Can't find abovementioned PEi386 section");
976 S = ((UInt32)(oc->oImage))
977 + (section_sym->PointerToRawData
980 copyName ( sym->Name, strtab, symbol, 1000 );
981 zapTrailingAtSign ( symbol );
982 S = (UInt32) ocLookupSym ( oc, symbol );
984 S = (UInt32)(oc->clientLookup ( symbol ));
987 strcpy(errtxt,oc->objFileName);
988 strcat(errtxt,": unresolvable reference to: ");
989 strcat(errtxt,symbol);
995 switch (reltab_j->Type) {
996 case IMAGE_REL_I386_DIR32:
999 case IMAGE_REL_I386_REL32:
1000 /* Tricky. We have to insert a displacement at
1001 pP which, when added to the PC for the _next_
1002 insn, gives the address of the target (S).
1003 Problem is to know the address of the next insn
1004 when we only know pP. We assume that this
1005 literal field is always the last in the insn,
1006 so that the address of the next insn is pP+4
1007 -- hence the constant 4.
1008 Also I don't know if A should be added, but so
1009 far it has always been zero.
1012 *pP = S - ((UInt32)pP) - 4;
1016 "unhandled PEi386 relocation type %d\n",
1018 oc->errMsg("unhandled PEi386 relocation type");
1028 #endif /* defined(cygwin32_TARGET_OS) */
1031 /* --------------------------------------------------------------------------
1032 * ELF specifics (Linux, Solaris)
1033 * ------------------------------------------------------------------------*/
1035 #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS)
1042 static char* findElfSection ( void* objImage, Elf32_Word sh_type )
1045 char* ehdrC = (char*)objImage;
1046 Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
1047 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1049 for (i = 0; i < ehdr->e_shnum; i++) {
1050 if (shdr[i].sh_type == sh_type &&
1051 i != ehdr->e_shstrndx) {
1052 ptr = ehdrC + shdr[i].sh_offset;
1060 static int ocVerifyImage_ELF ( ObjectCode* oc, int verb )
1064 int i, j, nent, nstrtab, nsymtabs;
1068 char* ehdrC = (char*)(oc->oImage);
1069 Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC;
1071 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
1072 ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
1073 ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
1074 ehdr->e_ident[EI_MAG3] != ELFMAG3) {
1075 oc->errMsg("Not an ELF header");
1078 if (verb) fprintf ( stderr, "Is an ELF header\n" );
1080 if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
1081 oc->errMsg("Not 32 bit ELF" );
1084 if (verb) fprintf ( stderr, "Is 32 bit ELF\n" );
1086 if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
1087 if (verb) fprintf ( stderr, "Is little-endian\n" );
1089 if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
1090 if (verb) fprintf ( stderr, "Is big-endian\n" );
1092 oc->errMsg("Unknown endiannness");
1096 if (ehdr->e_type != ET_REL) {
1097 oc->errMsg("Not a relocatable object (.o) file");
1100 if (verb) fprintf ( stderr, "Is a relocatable object (.o) file\n" );
1102 if (verb) fprintf ( stderr, "Architecture is " );
1103 switch (ehdr->e_machine) {
1104 case EM_386: if (verb) fprintf ( stderr, "x86\n" ); break;
1105 case EM_SPARC: if (verb) fprintf ( stderr, "sparc\n" ); break;
1106 default: if (verb) fprintf ( stderr, "unknown\n" );
1107 oc->errMsg("Unknown architecture");
1113 "\nSection header table: start %d, n_entries %d, ent_size %d\n",
1114 ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize );
1116 assert (ehdr->e_shentsize == sizeof(Elf32_Shdr));
1118 shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1120 if (ehdr->e_shstrndx == SHN_UNDEF) {
1121 oc->errMsg("No section header string table");
1124 if (verb) fprintf ( stderr,"Section header string table is section %d\n",
1126 sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1129 for (i = 0; i < ehdr->e_shnum; i++) {
1130 if (verb) fprintf ( stderr, "%2d: ", i );
1131 if (verb) fprintf ( stderr, "type=%2d ", shdr[i].sh_type );
1132 if (verb) fprintf ( stderr, "size=%4d ", shdr[i].sh_size );
1133 if (verb) fprintf ( stderr, "offs=%4d ", shdr[i].sh_offset );
1134 if (verb) fprintf ( stderr, " (%p .. %p) ",
1135 ehdrC + shdr[i].sh_offset,
1136 ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1);
1138 if (shdr[i].sh_type == SHT_REL && verb) fprintf ( stderr, "Rel " ); else
1139 if (shdr[i].sh_type == SHT_RELA && verb) fprintf ( stderr, "RelA " ); else
1140 if (verb) fprintf ( stderr, " " );
1141 if (sh_strtab && verb)
1142 fprintf ( stderr, "sname=%s", sh_strtab + shdr[i].sh_name );
1143 if (verb) fprintf ( stderr, "\n" );
1146 if (verb) fprintf ( stderr, "\n\nString tables\n" );
1149 for (i = 0; i < ehdr->e_shnum; i++) {
1150 if (shdr[i].sh_type == SHT_STRTAB &&
1151 i != ehdr->e_shstrndx) {
1153 fprintf ( stderr, " section %d is a normal string table\n", i );
1154 strtab = ehdrC + shdr[i].sh_offset;
1159 oc->errMsg("WARNING: no string tables, or too many");
1164 if (verb) fprintf ( stderr, "\n\nSymbol tables\n" );
1165 for (i = 0; i < ehdr->e_shnum; i++) {
1166 if (shdr[i].sh_type != SHT_SYMTAB) continue;
1167 if (verb) fprintf ( stderr, "section %d is a symbol table\n", i );
1169 stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
1170 nent = shdr[i].sh_size / sizeof(Elf32_Sym);
1171 if (verb) fprintf ( stderr, " number of entries is apparently %d (%d rem)\n",
1173 shdr[i].sh_size % sizeof(Elf32_Sym)
1175 if (0 != shdr[i].sh_size % sizeof(Elf32_Sym)) {
1176 oc->errMsg("non-integral number of symbol table entries");
1179 for (j = 0; j < nent; j++) {
1180 if (verb) fprintf ( stderr, " %2d ", j );
1181 if (verb) fprintf ( stderr, " sec=%-5d size=%-3d val=%-5p ",
1182 (int)stab[j].st_shndx,
1183 (int)stab[j].st_size,
1184 (char*)stab[j].st_value );
1186 if (verb) fprintf ( stderr, "type=" );
1187 switch (ELF32_ST_TYPE(stab[j].st_info)) {
1188 case STT_NOTYPE: if (verb) fprintf ( stderr, "notype " ); break;
1189 case STT_OBJECT: if (verb) fprintf ( stderr, "object " ); break;
1190 case STT_FUNC : if (verb) fprintf ( stderr, "func " ); break;
1191 case STT_SECTION: if (verb) fprintf ( stderr, "section" ); break;
1192 case STT_FILE: if (verb) fprintf ( stderr, "file " ); break;
1193 default: if (verb) fprintf ( stderr, "? " ); break;
1195 if (verb) fprintf ( stderr, " " );
1197 if (verb) fprintf ( stderr, "bind=" );
1198 switch (ELF32_ST_BIND(stab[j].st_info)) {
1199 case STB_LOCAL : if (verb) fprintf ( stderr, "local " ); break;
1200 case STB_GLOBAL: if (verb) fprintf ( stderr, "global" ); break;
1201 case STB_WEAK : if (verb) fprintf ( stderr, "weak " ); break;
1202 default: if (verb) fprintf ( stderr, "? " ); break;
1204 if (verb) fprintf ( stderr, " " );
1206 if (verb) fprintf ( stderr, "name=%s\n", strtab + stab[j].st_name );
1210 if (nsymtabs == 0) {
1211 oc->errMsg("Didn't find any symbol tables");
1219 static int ocGetNames_ELF ( ObjectCode* oc, int verb )
1224 char* ehdrC = (char*)(oc->oImage);
1225 Elf32_Ehdr* ehdr = (Elf32_Ehdr*)ehdrC;
1226 char* strtab = findElfSection ( ehdrC, SHT_STRTAB );
1227 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1228 char* sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
1231 oc->errMsg("ELF: no strtab!");
1236 for (i = 0; i < ehdr->e_shnum; i++) {
1238 /* make a HugsDLSection entry for relevant sections */
1239 OSectionKind kind = HUGS_SECTIONKIND_OTHER;
1240 if (0==strcmp(".data",sh_strtab+shdr[i].sh_name) ||
1241 0==strcmp(".data1",sh_strtab+shdr[i].sh_name))
1242 kind = HUGS_SECTIONKIND_RWDATA;
1243 if (0==strcmp(".text",sh_strtab+shdr[i].sh_name) ||
1244 0==strcmp(".rodata",sh_strtab+shdr[i].sh_name) ||
1245 0==strcmp(".rodata1",sh_strtab+shdr[i].sh_name))
1246 kind = HUGS_SECTIONKIND_CODE_OR_RODATA;
1247 if (kind != HUGS_SECTIONKIND_OTHER)
1250 ehdrC + shdr[i].sh_offset,
1251 ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1,
1255 if (shdr[i].sh_type != SHT_SYMTAB) continue;
1257 /* copy stuff into this module's object symbol table */
1258 stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset);
1259 nent = shdr[i].sh_size / sizeof(Elf32_Sym);
1260 for (j = 0; j < nent; j++) {
1261 if ( ( ELF32_ST_BIND(stab[j].st_info)==STB_GLOBAL ||
1262 ELF32_ST_BIND(stab[j].st_info)==STB_LOCAL
1265 ( ELF32_ST_TYPE(stab[j].st_info)==STT_FUNC ||
1266 ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT)
1267 /* || ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE */
1269 char* nm = strtab + stab[j].st_name;
1271 + shdr[ stab[j].st_shndx ].sh_offset
1276 fprintf(stderr, "addOTabName: %10p %s %s\n",
1277 ad, oc->objFileName, nm );
1278 if (!addSymbol ( oc, nm, ad )) return FALSE;
1282 fprintf(stderr, "skipping `%s'\n", strtab + stab[j].st_name );
1290 static int ocResolve_ELF ( ObjectCode* oc, int verb )
1292 char symbol[1000]; // ToDo
1295 Elf32_Sym* stab = NULL;
1296 char* ehdrC = (char*)(oc->oImage);
1297 Elf32_Ehdr* ehdr = (Elf32_Ehdr*) ehdrC;
1298 Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
1301 /* first find "the" symbol table */
1302 stab = (Elf32_Sym*) findElfSection ( ehdrC, SHT_SYMTAB );
1304 /* also go find the string table */
1305 strtab = findElfSection ( ehdrC, SHT_STRTAB );
1307 if (!stab || !strtab) {
1308 oc->errMsg("can't find string or symbol table");
1312 for (i = 0; i < ehdr->e_shnum; i++) {
1313 if (shdr[i].sh_type == SHT_REL ) {
1314 Elf32_Rel* rtab = (Elf32_Rel*) (ehdrC + shdr[i].sh_offset);
1315 int nent = shdr[i].sh_size / sizeof(Elf32_Rel);
1316 int target_shndx = shdr[i].sh_info;
1317 int symtab_shndx = shdr[i].sh_link;
1318 stab = (Elf32_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
1319 targ = (Elf32_Word*)(ehdrC + shdr[ target_shndx ].sh_offset);
1322 "relocations for section %d using symtab %d\n",
1323 target_shndx, symtab_shndx );
1324 for (j = 0; j < nent; j++) {
1325 Elf32_Addr offset = rtab[j].r_offset;
1326 Elf32_Word info = rtab[j].r_info;
1328 Elf32_Addr P = ((Elf32_Addr)targ) + offset;
1329 Elf32_Word* pP = (Elf32_Word*)P;
1333 if (verb) fprintf ( stderr, "Rel entry %3d is raw(%6p %6p) ",
1334 j, (void*)offset, (void*)info );
1336 if (verb) fprintf ( stderr, " ZERO\n" );
1339 /* First see if it is a nameless local symbol. */
1340 if (stab[ ELF32_R_SYM(info)].st_name == 0) {
1341 if (verb) fprintf ( stderr, "(noname) ");
1342 S = (Elf32_Addr)(ehdrC
1343 + shdr[stab[ELF32_R_SYM(info)].st_shndx ].sh_offset
1344 + stab[ELF32_R_SYM(info)].st_value
1346 strcpy ( symbol, "(noname)");
1348 /* No? Perhaps it's a named symbol in this file. */
1349 strcpy ( symbol, strtab+stab[ ELF32_R_SYM(info)].st_name );
1350 if (verb) fprintf ( stderr, "`%s' ", symbol );
1351 S = (Elf32_Addr)ocLookupSym ( oc, symbol );
1353 /* No? Ok, too hard. Hand the problem to the client.
1354 And if that fails, we're outta options.
1356 S = (Elf32_Addr)(oc->clientLookup ( symbol ) );
1359 if (verb) fprintf ( stderr, "resolves to %p\n", (void*)S );
1362 strcpy(errtxt,oc->objFileName);
1363 strcat(errtxt,": unresolvable reference to: ");
1364 strcat(errtxt,symbol);
1369 /* fprintf ( stderr, "Reloc: P = %p S = %p A = %p\n\n",
1370 (void*)P, (void*)S, (void*)A );
1372 switch (ELF32_R_TYPE(info)) {
1373 # if defined(linux_TARGET_OS)
1374 case R_386_32: *pP = S + A; break;
1375 case R_386_PC32: *pP = S + A - P; break;
1377 default: fprintf(stderr,
1378 "unhandled ELF relocation type %d\n",
1379 ELF32_R_TYPE(info));
1380 oc->errMsg("unhandled ELF relocation type");
1387 if (shdr[i].sh_type == SHT_RELA) {
1388 oc->errMsg("RelA style reloc table -- not yet done");
1397 #endif /* defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) */
1401 /*-------------------------------------------------------------------------*/