summaryrefslogtreecommitdiff
path: root/rts/linker
diff options
context:
space:
mode:
authorTamar Christina <tamar@zhox.com>2017-07-08 09:57:55 +0100
committerTamar Christina <tamar@zhox.com>2017-07-08 17:00:27 +0100
commit81377e9e4bd52256946114d9c1dd966d5e3e7692 (patch)
tree7a5af5dc8d215978e797bdfe190fe9980e51651c /rts/linker
parente1146ed5d822e79b121b057c49ac13b61bcca93a (diff)
downloadhaskell-81377e9e4bd52256946114d9c1dd966d5e3e7692.tar.gz
Big-obj support for the Windows runtime linker
Summary: The normal object file on Windows has a limit of `2^16` sections that can be in an object-file. The `big-obj` format raises this to `2^32` sections. The implementation is made difficult because we now need to support two header formats and two section formats that differ only by a single element size within each. The element that's different is in the middle of the structs and since the structs are used to map regions of memory directly, it means we need to know which struct it is when we do the mapping or pointer arithmetics. This is the final Object-Code format which Windows compilers can generate which we do not support yet in GHCI. All other major compilers on the platforms can produce it and all linkers consume it (bfd and lld). See http://tinyurl.com/bigobj This patch abstracts away retrieving the fields to functions which all take an struct which describes which object format is currently being parsed. These functions are always in-lined as they're small but would looks messy being copy-pasted everywhere. Test Plan: ./validate and new test `big-obj` ``` Tamar@Rage MINGW64 /r $ gcc -c -Wa,-mbig-obj foo.c -o foo.o Tamar@Rage MINGW64 /r $ objdump -h foo.o foo.o: file format pe-bigobj-x86-64 Sections: Idx Name Size VMA LMA File off Algn 0 .text 00000010 0000000000000000 0000000000000000 00000128 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 00000000 0000000000000000 0000000000000000 00000000 2**4 ALLOC, LOAD, DATA 2 .bss 00000000 0000000000000000 0000000000000000 00000000 2**4 ALLOC 3 .xdata 00000008 0000000000000000 0000000000000000 00000138 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .pdata 0000000c 0000000000000000 0000000000000000 00000140 2**2 CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA 5 .rdata$zzz 00000030 0000000000000000 0000000000000000 0000014c 2**4 CONTENTS, ALLOC, LOAD, READONLY, DATA Tamar@Rage MINGW64 /r $ echo main | ~/ghc/inplace/bin/ghc-stage2.exe --interactive bar.hs foo.o GHCi, version 8.3.20170430: http://www.haskell.org/ghc/ :? for help [1 of 1] Compiling Main ( bar.hs, interpreted ) Ok, modules loaded: Main. *Main> 17 *Main> Leaving GHCi. ``` Reviewers: austin, bgamari, erikd, simonmar Subscribers: awson, rwbarton, thomie, #ghc_windows_task_force GHC Trac Issues: #13815 Differential Revision: https://phabricator.haskell.org/D3523
Diffstat (limited to 'rts/linker')
-rw-r--r--rts/linker/PEi386.c624
-rw-r--r--rts/linker/PEi386.h52
2 files changed, 524 insertions, 152 deletions
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index 5301eb1964..22258fe970 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -42,6 +42,21 @@
The current code is based on version 0.99.6 - October 2013
+ The current GHCi linker supports the following four object file formats:
+
+ * PE/PE+ obj - The normal COFF_ANON_OBJ format which is generated by default
+ from Windows compilers
+
+ * PE/PE+ big-obj - The big object format COFF_ANON_BIG_OBJ which extends the
+ number of sections to 2^31 and the number of symbols in each section. This
+ requires a flag but all Windows compilers can produce it.
+
+ * PE Import format - The import library format defined in the PE standard
+ COFF_IMPORT_LIB and commonly has the file extension .lib
+
+ * GNU BFD import format - The import library format defined and used by GNU
+ tools. See note below.
+
Note [BFD import library]
On Windows, compilers don't link directly to dynamic libraries.
@@ -151,8 +166,9 @@ static void addDLLHandle(
HINSTANCE instance);
static bool verifyCOFFHeader(
- COFF_header *hdr,
- pathchar *filename);
+ uint16_t machine,
+ IMAGE_FILE_HEADER *hdr,
+ pathchar *fileName);
static bool checkIfDllLoaded(
HINSTANCE instance);
@@ -275,9 +291,204 @@ void freePreloadObjectFile_PEi386(ObjectCode *oc)
indirects = NULL;
}
-/* Loads the DLL specified by DLL_NAME, and if successful
- adds the DLL to the internal linker map and returns the instance handle
- of the loaded dll in LOADED if LOADED is not NULL. */
+/*************
+ * This function determines what kind of COFF image we are dealing with.
+ * This is needed in order to correctly load and verify objects and their
+ * sections.
+ *************/
+COFF_OBJ_TYPE getObjectType ( char* image, pathchar* fileName )
+{
+ /* {D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8} */
+ static const char header_bigobj_classid[16] =
+ {
+ 0xC7, 0xA1, 0xBA, 0xD1,
+ 0xEE, 0xBA,
+ 0xa9, 0x4b,
+ 0xAF, 0x20,
+ 0xFA, 0xF6, 0x6A, 0xA4, 0xDC, 0xB8
+ };
+
+ WORD machine;
+ COFF_OBJ_TYPE ret = COFF_UNKNOWN;
+ /* First check if we have an ANON_OBJECT_HEADER signature. */
+ ANON_OBJECT_HEADER* anon = (ANON_OBJECT_HEADER*)image;
+ if ( anon->Sig1 == IMAGE_FILE_MACHINE_UNKNOWN
+ && anon->Sig2 == IMPORT_OBJECT_HDR_SIG2)
+ {
+ machine = anon->Machine;
+ if (verifyCOFFHeader (machine, NULL, fileName))
+ {
+ switch (anon->Version)
+ {
+ case 0:
+ ret = COFF_IMPORT_LIB;
+ break;
+ case 1:
+ ret = COFF_ANON_OBJ;
+ break;
+ case 2:
+ if (memcmp (&anon->ClassID, header_bigobj_classid, 16) == 0)
+ ret = COFF_ANON_BIG_OBJ;
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ /* If it's not an ANON_OBJECT then try an image file. */
+ IMAGE_FILE_HEADER* img = (IMAGE_FILE_HEADER*)image;
+ machine = img->Machine;
+ if (verifyCOFFHeader (machine, img, fileName))
+ ret = COFF_IMAGE;
+ }
+ return ret;
+}
+
+/*************
+ * Retrieve common header information
+ *************/
+COFF_HEADER_INFO* getHeaderInfo ( ObjectCode* oc )
+{
+ COFF_OBJ_TYPE coff_type = getObjectType (oc->image, oc->fileName);
+
+ COFF_HEADER_INFO* info
+ = stgMallocBytes (sizeof(COFF_HEADER_INFO), "getHeaderInfo");
+ memset (info, 0, sizeof(COFF_HEADER_INFO));
+ info->type = coff_type;
+ switch (coff_type)
+ {
+ case COFF_IMAGE:
+ {
+ IMAGE_FILE_HEADER* hdr = (IMAGE_FILE_HEADER*)oc->image;
+ info->sizeOfHeader = sizeof(IMAGE_FILE_HEADER);
+ info->sizeOfOptionalHeader = hdr->SizeOfOptionalHeader;
+ info->pointerToSymbolTable = hdr->PointerToSymbolTable;
+ info->numberOfSymbols = hdr->NumberOfSymbols;
+ info->numberOfSections = hdr->NumberOfSections;
+ }
+ break;
+ case COFF_ANON_BIG_OBJ:
+ {
+ ANON_OBJECT_HEADER_BIGOBJ* hdr = (ANON_OBJECT_HEADER_BIGOBJ*)oc->image;
+ info->sizeOfHeader = sizeof(ANON_OBJECT_HEADER_BIGOBJ);
+ info->sizeOfOptionalHeader = 0;
+ info->pointerToSymbolTable = hdr->PointerToSymbolTable;
+ info->numberOfSymbols = hdr->NumberOfSymbols;
+ info->numberOfSections = hdr->NumberOfSections;
+ }
+ break;
+ default:
+ {
+ stgFree (info);
+ info = NULL;
+ errorBelch ("Unknown COFF %d type in getHeaderInfo.", coff_type);
+ }
+ break;
+ }
+
+ return info;
+}
+
+/*************
+ * Symbol utility functions
+ *************/
+__attribute__ ((always_inline)) inline
+size_t getSymbolSize ( COFF_HEADER_INFO *info )
+{
+ ASSERT (info);
+ switch (info->type)
+ {
+ case COFF_ANON_BIG_OBJ:
+ return sizeof_COFF_symbol_ex;
+ default:
+ return sizeof_COFF_symbol_og;
+ }
+}
+
+__attribute__ ((always_inline)) inline
+int32_t getSymSectionNumber ( COFF_HEADER_INFO *info, COFF_symbol* sym )
+{
+ ASSERT (info);
+ ASSERT (sym);
+ switch (info->type)
+ {
+ case COFF_ANON_BIG_OBJ:
+ return sym->ex.SectionNumber;
+ default:
+ return sym->og.SectionNumber;
+ }
+}
+
+__attribute__ ((always_inline)) inline
+uint32_t getSymValue ( COFF_HEADER_INFO *info, COFF_symbol* sym )
+{
+ ASSERT (info);
+ ASSERT (sym);
+ switch (info->type)
+ {
+ case COFF_ANON_BIG_OBJ:
+ return sym->ex.Value;
+ default:
+ return sym->og.Value;
+ }
+}
+
+__attribute__ ((always_inline)) inline
+uint8_t getSymStorageClass ( COFF_HEADER_INFO *info, COFF_symbol* sym )
+{
+ ASSERT (info);
+ ASSERT (sym);
+ switch (info->type)
+ {
+ case COFF_ANON_BIG_OBJ:
+ return sym->ex.StorageClass;
+ default:
+ return sym->og.StorageClass;
+ }
+}
+
+__attribute__ ((always_inline)) inline
+uint8_t getSymNumberOfAuxSymbols ( COFF_HEADER_INFO *info, COFF_symbol* sym )
+{
+ ASSERT (info);
+ ASSERT (sym);
+ switch (info->type)
+ {
+ case COFF_ANON_BIG_OBJ:
+ return sym->ex.NumberOfAuxSymbols;
+ default:
+ return sym->og.NumberOfAuxSymbols;
+ }
+}
+
+__attribute__ ((always_inline)) inline
+uint16_t getSymType ( COFF_HEADER_INFO *info, COFF_symbol* sym )
+{
+ ASSERT (info);
+ ASSERT (sym);
+ switch (info->type)
+ {
+ case COFF_ANON_BIG_OBJ:
+ return sym->ex.Type;
+ default:
+ return sym->og.Type;
+ }
+}
+
+__attribute__ ((always_inline)) inline
+uint8_t* getSymShortName ( COFF_HEADER_INFO *info, COFF_symbol* sym )
+{
+ ASSERT (info);
+ ASSERT (sym);
+ switch (info->type)
+ {
+ case COFF_ANON_BIG_OBJ:
+ return sym->ex.N.ShortName;
+ default:
+ return sym->og.N.ShortName;
+ }
+}
+
const char *
addDLL_PEi386( pathchar *dll_name, HINSTANCE *loaded )
{
@@ -488,19 +699,76 @@ allocateImageAndTrampolines (
{
/* PeCoff contains number of symbols right in it's header, so
we can reserve the room for symbolExtras right here. */
- COFF_header hdr;
size_t n;
-
- n = fread(&hdr, 1, sizeof_COFF_header, f);
- if (n != sizeof_COFF_header) {
- errorBelch("getNumberOfSymbols: error whilst reading `%s' header in `%" PATH_FMT "'",
- member_name, arch_name);
+ /* Minimum header size to read. */
+ const size_t MIN_HEADER_SIZE = sizeof(ANON_OBJECT_HEADER);
+ char* tmp = stgMallocBytes (MIN_HEADER_SIZE, "allocateImageAndTrampolines");
+ n = fread (tmp, 1, MIN_HEADER_SIZE, f);
+ if (n != MIN_HEADER_SIZE) {
+ stgFree (tmp);
+ errorBelch ("getNumberOfSymbols: error whilst reading `%s' header "
+ "in `%" PATH_FMT "'",
+ member_name, arch_name);
return NULL;
}
- fseek(f, -(long int)sizeof_COFF_header, SEEK_CUR);
-
- if (!verifyCOFFHeader(&hdr, arch_name)) {
- return 0;
+ fseek(f, -(long int)MIN_HEADER_SIZE, SEEK_CUR);
+
+ COFF_OBJ_TYPE objType = getObjectType (tmp, arch_name);
+ stgFree (tmp);
+ uint32_t numberOfSymbols = 0;
+ switch (objType)
+ {
+ case COFF_IMAGE:
+ {
+ IMAGE_FILE_HEADER hdr;
+ n = fread (&hdr, 1, sizeof(IMAGE_FILE_HEADER), f);
+ if (n != sizeof(IMAGE_FILE_HEADER))
+ {
+ errorBelch ("getNumberOfSymbols: error whilst reading `%s' "
+ "image header in `%" PATH_FMT "'",
+ member_name, arch_name);
+ return NULL;
+ }
+ fseek (f, -(long int)sizeof(IMAGE_FILE_HEADER), SEEK_CUR);
+ if (!verifyCOFFHeader (hdr.Machine, &hdr, arch_name)) {
+ return NULL;
+ }
+ numberOfSymbols = hdr.NumberOfSymbols;
+ }
+ break;
+ case COFF_ANON_BIG_OBJ:
+ {
+ ANON_OBJECT_HEADER_BIGOBJ hdr;
+ n = fread (&hdr, 1, sizeof(ANON_OBJECT_HEADER_BIGOBJ), f);
+ if (n != sizeof(ANON_OBJECT_HEADER_BIGOBJ))
+ {
+ errorBelch ("getNumberOfSymbols: error whilst reading `%s' "
+ "big obj header in `%" PATH_FMT "'",
+ member_name, arch_name);
+ return NULL;
+ }
+ fseek (f, -(long int)sizeof(ANON_OBJECT_HEADER_BIGOBJ), SEEK_CUR);
+ if (!verifyCOFFHeader (hdr.Machine, NULL, arch_name)) {
+ return NULL;
+ }
+ numberOfSymbols = hdr.NumberOfSymbols;
+ }
+ break;
+ case COFF_ANON_OBJ:
+ barf ("COFF_ANON_OBJ should not be allocated with "
+ "allocateImageAndTrampolines. It is not specific enough.\n");
+ case COFF_IMPORT_LIB:
+ barf ("COFF_IMPORT_LIB should not be allocated with "
+ "allocateImageAndTrampolines. It is read-only.\n");
+ case COFF_UNKNOWN:
+ default:
+ {
+ errorBelch (
+ "getNumberOfSymbols: error whilst reading `%s' header "
+ "in `%" PATH_FMT "': Unknown COFF_OBJ_TYPE.",
+ member_name, arch_name);
+ return NULL;
+ }
}
/* We get back 8-byte aligned memory (is that guaranteed?), but
@@ -513,7 +781,7 @@ allocateImageAndTrampolines (
/* We allocate trampolines area for all symbols right behind
image data, aligned on 8. */
size = ((PEi386_IMAGE_OFFSET + size + 0x7) & ~0x7)
- + hdr.NumberOfSymbols * sizeof(SymbolExtra);
+ + numberOfSymbols * sizeof(SymbolExtra);
}
#endif
image = VirtualAlloc(NULL, size,
@@ -529,6 +797,14 @@ allocateImageAndTrampolines (
return image + PEi386_IMAGE_OFFSET;
}
+/* -----------------------
+ * This loads import libraries following Microsoft's official standard in the PE
+ * documentation. This is a smaller more efficient format which is just a list
+ * of symbol name => dll.
+ *
+ * This function must fail gracefully and if it does, the filestream needs to
+ * be reset to what it was when the function was called.
+ */
bool checkAndLoadImportLibrary( pathchar* arch_name, char* member_name, FILE* f )
{
char* image;
@@ -542,13 +818,17 @@ bool checkAndLoadImportLibrary( pathchar* arch_name, char* member_name, FILE* f
size_t n;
n = fread(&hdr, 1, sizeof_COFF_import_Header, f);
- if (n != sizeof(COFF_header)) {
- errorBelch("getNumberOfSymbols: error whilst reading `%s' header in `%" PATH_FMT "'\n",
- member_name, arch_name);
+ if (n != sizeof_COFF_import_Header) {
+ errorBelch("loadImportLibrary: error whilst reading `%s' header "
+ "in `%" PATH_FMT "'\n",
+ member_name, arch_name);
+ fseek(f, -(long int)sizeof_COFF_import_Header, SEEK_CUR);
return false;
}
- if (hdr.Sig1 != 0x0 || hdr.Sig2 != IMPORT_OBJECT_HDR_SIG2) {
+ if ( hdr.Sig1 != IMAGE_FILE_MACHINE_UNKNOWN
+ || hdr.Sig2 != IMPORT_OBJECT_HDR_SIG2
+ || getObjectType ((char*)&hdr, arch_name) != COFF_IMPORT_LIB) {
fseek(f, -(long int)sizeof_COFF_import_Header, SEEK_CUR);
IF_DEBUG(linker, debugBelch("loadArchive: Object `%s` is not an import lib. Skipping...\n", member_name));
return false;
@@ -561,6 +841,8 @@ bool checkAndLoadImportLibrary( pathchar* arch_name, char* member_name, FILE* f
if (n != hdr.SizeOfData) {
errorBelch("loadArchive: error whilst reading `%s' header in `%" PATH_FMT "'. Did not read enough bytes.\n",
member_name, arch_name);
+ fseek(f, -(n + sizeof_COFF_import_Header), SEEK_CUR);
+ return false;
}
char* symbol = strtok(image, "\0");
@@ -744,37 +1026,39 @@ lookupSymbolInDLLs ( uint8_t *lbl )
}
static bool
-verifyCOFFHeader ( COFF_header *hdr, pathchar *fileName )
+verifyCOFFHeader ( uint16_t machine, IMAGE_FILE_HEADER *hdr,
+ pathchar *fileName )
{
#if defined(i386_HOST_ARCH)
- if (hdr->Machine != IMAGE_FILE_MACHINE_I386) {
- errorBelch("%" PATH_FMT ": Not x86 PEi386", fileName);
+ if (machine != IMAGE_FILE_MACHINE_I386) {
+ errorBelch("%" PATH_FMT ": Not a x86 PE file.", fileName);
return false;
}
#elif defined(x86_64_HOST_ARCH)
- if (hdr->Machine != IMAGE_FILE_MACHINE_AMD64) {
- errorBelch("%" PATH_FMT ": Not x86_64 PEi386", fileName);
+ if (machine != IMAGE_FILE_MACHINE_AMD64) {
+ errorBelch("%" PATH_FMT ": Not a x86_64 PE+ file.", fileName);
return false;
}
#else
- errorBelch("PEi386 not supported on this arch");
+ errorBelch("PE/PE+ not supported on this arch.");
#endif
+ if (!hdr)
+ return true;
+
if (hdr->SizeOfOptionalHeader != 0) {
- errorBelch("%" PATH_FMT ": PEi386 with nonempty optional header",
+ errorBelch("%" PATH_FMT ": PE/PE+ with nonempty optional header",
fileName);
return 0;
}
- if ( /* (hdr->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) || */
- (hdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) ||
+ if ( (hdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) ||
(hdr->Characteristics & IMAGE_FILE_DLL ) ||
(hdr->Characteristics & IMAGE_FILE_SYSTEM ) ) {
- errorBelch("%" PATH_FMT ": Not a PEi386 object file", fileName);
+ errorBelch("%" PATH_FMT ": Not a PE/PE+ object file", fileName);
return false;
}
- if ( (hdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI)
- /* || !(hdr->Characteristics & IMAGE_FILE_32BIT_MACHINE) */ ) {
- errorBelch("%" PATH_FMT ": Invalid PEi386 word size or endiannness: %d",
+ if ( (hdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI)) {
+ errorBelch("%" PATH_FMT ": Invalid PE/PE+ word size or endiannness: %d",
fileName,
(int)(hdr->Characteristics));
return false;
@@ -785,28 +1069,24 @@ verifyCOFFHeader ( COFF_header *hdr, pathchar *fileName )
bool
ocVerifyImage_PEi386 ( ObjectCode* oc )
{
- int i;
+ unsigned int i;
uint32_t j, noRelocs;
- COFF_header* hdr;
COFF_section* sectab;
COFF_symbol* symtab;
- uint8_t* strtab;
- /* debugBelch("\nLOADING %s\n", oc->fileName); */
- hdr = (COFF_header*)(oc->image);
+ uint8_t* strtab;
+
+ COFF_HEADER_INFO *info = getHeaderInfo (oc);
+
sectab = (COFF_section*) (
((uint8_t*)(oc->image))
- + sizeof_COFF_header + hdr->SizeOfOptionalHeader
+ + info->sizeOfHeader + info->sizeOfOptionalHeader
);
symtab = (COFF_symbol*) (
((uint8_t*)(oc->image))
- + hdr->PointerToSymbolTable
+ + info->pointerToSymbolTable
);
strtab = ((uint8_t*)symtab)
- + hdr->NumberOfSymbols * sizeof_COFF_symbol;
-
- if (!verifyCOFFHeader(hdr, oc->fileName)) {
- return false;
- }
+ + info->numberOfSymbols * getSymbolSize (info);
/* If the string table size is way crazy, this might indicate that
there are more than 64k relocations, despite claims to the
@@ -827,13 +1107,13 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
Section *sections;
sections = (Section*)stgCallocBytes(
sizeof(Section),
- hdr->NumberOfSections + 1, /* +1 for the global BSS section see ocGetNames_PEi386 */
+ info->numberOfSections + 1, /* +1 for the global BSS section see ocGetNames_PEi386 */
"ocVerifyImage_PEi386(sections)");
oc->sections = sections;
- oc->n_sections = hdr->NumberOfSections + 1;
+ oc->n_sections = info->numberOfSections + 1;
/* Initialize the Sections */
- for (i = 0; i < hdr->NumberOfSections; i++) {
+ for (i = 0; i < info->numberOfSections; i++) {
COFF_section* sectab_i
= (COFF_section*)
myindex(sizeof_COFF_section, sectab, i);
@@ -845,27 +1125,64 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
/* No further verification after this point; only debug printing. */
i = 0;
IF_DEBUG(linker, i=1);
- if (i == 0) return true;
+ if (i == 0)
+ {
+ stgFree (info);
+ return true;
+ }
debugBelch("sectab offset = %" FMT_SizeT "\n",
- ((uint8_t*)sectab) - ((uint8_t*)hdr) );
+ ((uint8_t*)sectab) - ((uint8_t*)oc->image) );
debugBelch("symtab offset = %" FMT_SizeT "\n",
- ((uint8_t*)symtab) - ((uint8_t*)hdr) );
+ ((uint8_t*)symtab) - ((uint8_t*)oc->image) );
debugBelch("strtab offset = %" FMT_SizeT "\n",
- ((uint8_t*)strtab) - ((uint8_t*)hdr) );
+ ((uint8_t*)strtab) - ((uint8_t*)oc->image) );
debugBelch("\n" );
- debugBelch( "Machine: 0x%x\n", (uint32_t)(hdr->Machine) );
- debugBelch( "# sections: %d\n", (uint32_t)(hdr->NumberOfSections) );
- debugBelch( "time/date: 0x%x\n", (uint32_t)(hdr->TimeDateStamp) );
- debugBelch( "symtab offset: %d\n", (uint32_t)(hdr->PointerToSymbolTable) );
- debugBelch( "# symbols: %d\n", (uint32_t)(hdr->NumberOfSymbols) );
- debugBelch( "sz of opt hdr: %d\n", (uint32_t)(hdr->SizeOfOptionalHeader) );
- debugBelch( "characteristics: 0x%x\n", (uint32_t)(hdr->Characteristics) );
+ if (info->type == COFF_IMAGE)
+ {
+ IMAGE_FILE_HEADER* hdr = (IMAGE_FILE_HEADER*)oc->image;
+ debugBelch( "COFF Type: IMAGE_FILE_HEADER\n");
+ debugBelch( "Machine: 0x%x\n",
+ (uint32_t)(hdr->Machine) );
+ debugBelch( "# sections: %d\n",
+ (uint32_t)(hdr->NumberOfSections) );
+ debugBelch( "time/date: 0x%x\n",
+ (uint32_t)(hdr->TimeDateStamp) );
+ debugBelch( "symtab offset: %d\n",
+ (uint32_t)(hdr->PointerToSymbolTable) );
+ debugBelch( "# symbols: %d\n",
+ (uint32_t)(hdr->NumberOfSymbols) );
+ debugBelch( "sz of opt hdr: %d\n",
+ (uint32_t)(hdr->SizeOfOptionalHeader) );
+ debugBelch( "characteristics: 0x%x\n",
+ (uint32_t)(hdr->Characteristics) );
+ }
+ else if (info->type == COFF_ANON_BIG_OBJ)
+ {
+ ANON_OBJECT_HEADER_BIGOBJ* hdr = (ANON_OBJECT_HEADER_BIGOBJ*)oc->image;
+ debugBelch( "COFF Type: ANON_OBJECT_HEADER_BIGOBJ\n");
+ debugBelch( "Machine: 0x%x\n",
+ (uint32_t)(hdr->Machine) );
+ debugBelch( "# sections: %d\n",
+ (uint32_t)(hdr->NumberOfSections) );
+ debugBelch( "time/date: 0x%x\n",
+ (uint32_t)(hdr->TimeDateStamp) );
+ debugBelch( "symtab offset: %d\n",
+ (uint32_t)(hdr->PointerToSymbolTable) );
+ debugBelch( "# symbols: %d\n",
+ (uint32_t)(hdr->NumberOfSymbols) );
+ }
+ else
+ {
+ debugBelch( "COFF Type: UNKNOWN\n");
+ stgFree (info);
+ return false;
+ }
/* Print the section table. */
debugBelch("\n" );
- for (i = 0; i < hdr->NumberOfSections; i++) {
+ for (i = 0; i < info->numberOfSections; i++) {
COFF_reloc* reltab;
COFF_section* sectab_i
= (COFF_section*)
@@ -923,8 +1240,8 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
(uint32_t)rel->Type,
rel->VirtualAddress );
sym = (COFF_symbol*)
- myindex ( sizeof_COFF_symbol, symtab, rel->SymbolTableIndex );
- printName ( sym->N.ShortName, strtab );
+ myindex ( getSymbolSize (info), symtab, rel->SymbolTableIndex );
+ printName ( getSymShortName (info, sym), strtab );
debugBelch("'\n" );
}
@@ -933,7 +1250,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
debugBelch("\n" );
debugBelch("string table has size 0x%x\n", * (uint32_t*)strtab );
debugBelch("---START of string table---\n");
- for (i = 4; i < *(int32_t*)strtab; i++) {
+ for (i = 4; i < *(uint32_t*)strtab; i++) {
if (strtab[i] == 0)
debugBelch("\n"); else
debugBelch("%c", strtab[i] );
@@ -944,40 +1261,40 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
i = 0;
while (1) {
COFF_symbol* symtab_i;
- if (i >= (int32_t)(hdr->NumberOfSymbols)) break;
+ if (i >= info->numberOfSymbols) break;
symtab_i = (COFF_symbol*)
- myindex ( sizeof_COFF_symbol, symtab, i );
+ myindex ( getSymbolSize (info), symtab, i );
debugBelch(
"symbol %d\n"
" name `",
i
);
- printName ( symtab_i->N.ShortName, strtab );
+ printName ( getSymShortName (info, symtab_i), strtab );
debugBelch(
"'\n"
- " value 0x%lx\n"
+ " value 0x%x\n"
" 1+sec# %d\n"
" type 0x%x\n"
" sclass 0x%x\n"
" nAux %d\n",
- symtab_i->Value,
- (int32_t)(symtab_i->SectionNumber),
- (uint32_t)symtab_i->Type,
- (uint32_t)symtab_i->StorageClass,
- (uint32_t)symtab_i->NumberOfAuxSymbols
+ getSymValue (info, symtab_i),
+ getSymSectionNumber (info, symtab_i),
+ getSymType (info, symtab_i),
+ getSymStorageClass (info, symtab_i),
+ getSymNumberOfAuxSymbols (info, symtab_i)
);
- i += symtab_i->NumberOfAuxSymbols;
+ i += getSymNumberOfAuxSymbols (info, symtab_i);
i++;
}
debugBelch("\n" );
+ stgFree (info);
return true;
}
bool
ocGetNames_PEi386 ( ObjectCode* oc )
{
- COFF_header* hdr;
COFF_section* sectab;
COFF_symbol* symtab;
uint8_t* strtab;
@@ -985,24 +1302,25 @@ ocGetNames_PEi386 ( ObjectCode* oc )
uint8_t* sname;
SymbolAddr* addr;
- int i;
+ unsigned int i;
+
+ COFF_HEADER_INFO *info = getHeaderInfo (oc);
- hdr = (COFF_header*)(oc->image);
sectab = (COFF_section*) (
((uint8_t*)(oc->image))
- + sizeof_COFF_header + hdr->SizeOfOptionalHeader
+ + info->sizeOfHeader + info->sizeOfOptionalHeader
);
symtab = (COFF_symbol*) (
((uint8_t*)(oc->image))
- + hdr->PointerToSymbolTable
+ + info->pointerToSymbolTable
);
strtab = ((uint8_t*)(oc->image))
- + hdr->PointerToSymbolTable
- + hdr->NumberOfSymbols * sizeof_COFF_symbol;
+ + info->pointerToSymbolTable
+ + info->numberOfSymbols * getSymbolSize (info);
/* Allocate space for any (local, anonymous) .bss sections. */
- for (i = 0; i < hdr->NumberOfSections; i++) {
+ for (i = 0; i < info->numberOfSections; i++) {
uint32_t bss_sz;
uint8_t* zspace;
COFF_section* sectab_i
@@ -1047,7 +1365,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
/* Copy section information into the ObjectCode. */
- for (i = 0; i < hdr->NumberOfSections; i++) {
+ for (i = 0; i < info->numberOfSections; i++) {
uint8_t* start;
uint8_t* end;
uint32_t sz;
@@ -1099,9 +1417,10 @@ ocGetNames_PEi386 ( ObjectCode* oc )
of DLLs. */
sname = ((uint8_t*)section.start)+2;
COFF_symbol* symtab_i = (COFF_symbol*)
- myindex ( sizeof_COFF_symbol, symtab, hdr->NumberOfSymbols-1 );
- addr = (char*)cstring_from_COFF_symbol_name(symtab_i->N.ShortName,
- strtab);
+ myindex ( getSymbolSize(info), symtab, info->numberOfSymbols-1 );
+ addr = (char*)cstring_from_COFF_symbol_name(
+ getSymShortName (info, symtab_i),
+ strtab);
IF_DEBUG(linker,
debugBelch("addImportSymbol `%s' => `%s'\n",
@@ -1134,24 +1453,26 @@ ocGetNames_PEi386 ( ObjectCode* oc )
/* Copy exported symbols into the ObjectCode. */
- oc->n_symbols = hdr->NumberOfSymbols;
+ oc->n_symbols = info->numberOfSymbols;
oc->symbols = stgCallocBytes(sizeof(SymbolName*), oc->n_symbols,
"ocGetNames_PEi386(oc->symbols)");
/* Work out the size of the global BSS section */
StgWord globalBssSize = 0;
- for (i=0; i < (int)hdr->NumberOfSymbols; i++) {
+ for (i=0; i < info->numberOfSymbols; i++) {
COFF_symbol* symtab_i;
symtab_i = (COFF_symbol*)
- myindex ( sizeof_COFF_symbol, symtab, i );
- if (symtab_i->SectionNumber == IMAGE_SYM_UNDEFINED
- && symtab_i->Value > 0
- && symtab_i->StorageClass != IMAGE_SYM_CLASS_SECTION) {
- globalBssSize += symtab_i->Value;
+ myindex ( getSymbolSize (info), symtab, i );
+ if (getSymSectionNumber (info, symtab_i) == IMAGE_SYM_UNDEFINED
+ && getSymValue (info, symtab_i) > 0
+ && getSymStorageClass (info, symtab_i) != IMAGE_SYM_CLASS_SECTION) {
+ globalBssSize += getSymValue (info, symtab_i);
}
- i += symtab_i->NumberOfAuxSymbols;
+ i += getSymNumberOfAuxSymbols (info, symtab_i);
}
+ stgFree (info);
+
/* Allocate BSS space */
SymbolAddr* bss = NULL;
if (globalBssSize > 0) {
@@ -1167,20 +1488,24 @@ ocGetNames_PEi386 ( ObjectCode* oc )
SECTIONKIND_OTHER, SECTION_NOMEM, NULL, 0, 0, 0, 0);
}
- for (i = 0; i < oc->n_symbols; i++) {
+ for (i = 0; i < (uint32_t)oc->n_symbols; i++) {
COFF_symbol* symtab_i;
symtab_i = (COFF_symbol*)
- myindex ( sizeof_COFF_symbol, symtab, i );
+ myindex ( getSymbolSize (info), symtab, i );
+
+ int32_t secNumber = getSymSectionNumber (info, symtab_i);
+ uint32_t symValue = getSymValue (info, symtab_i);
+ uint8_t symStorageClass = getSymStorageClass (info, symtab_i);
addr = NULL;
bool isWeak = false;
- Section *section = symtab_i->SectionNumber > 0
- ? &oc->sections[symtab_i->SectionNumber-1]
+ Section *section = secNumber > 0
+ ? &oc->sections[secNumber-1]
: NULL;
- sname = cstring_from_COFF_symbol_name(symtab_i->N.ShortName, strtab);
+ sname = cstring_from_COFF_symbol_name(getSymShortName (info, symtab_i), strtab);
- if ( symtab_i->SectionNumber != IMAGE_SYM_UNDEFINED
- && symtab_i->SectionNumber > 0
+ if ( secNumber != IMAGE_SYM_UNDEFINED
+ && secNumber > 0
&& section
&& section->kind != SECTIONKIND_IMPORT_LIBRARY) {
/* This symbol is global and defined, viz, exported */
@@ -1191,32 +1516,30 @@ ocGetNames_PEi386 ( ObjectCode* oc )
*/
COFF_section* sectabent
= (COFF_section*) myindex ( sizeof_COFF_section,
- sectab,
- symtab_i->SectionNumber-1 );
- if (symtab_i->StorageClass == IMAGE_SYM_CLASS_EXTERNAL
- || ( symtab_i->StorageClass == IMAGE_SYM_CLASS_STATIC
+ sectab, secNumber-1 );
+ if (symStorageClass == IMAGE_SYM_CLASS_EXTERNAL
+ || ( symStorageClass == IMAGE_SYM_CLASS_STATIC
&& sectabent->Characteristics & IMAGE_SCN_LNK_COMDAT
&& section)
) {
addr = (void*)((size_t)section->start
- + symtab_i->Value);
+ + symValue);
if (sectabent->Characteristics & IMAGE_SCN_LNK_COMDAT) {
isWeak = true;
}
}
}
- else if (symtab_i->StorageClass == IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
+ else if (symStorageClass == IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
isWeak = true;
}
- else if ( symtab_i->SectionNumber == IMAGE_SYM_UNDEFINED
- && symtab_i->Value > 0) {
+ else if ( secNumber == IMAGE_SYM_UNDEFINED && symValue > 0) {
/* This symbol isn't in any section at all, ie, global bss.
Allocate zeroed space for it from the BSS section */
addr = bss;
- bss = (SymbolAddr*)((StgWord)bss + (StgWord)symtab_i->Value);
- IF_DEBUG(linker, debugBelch("bss symbol @ %p %lu\n", addr, symtab_i->Value));
+ bss = (SymbolAddr*)((StgWord)bss + (StgWord)symValue);
+ IF_DEBUG(linker, debugBelch("bss symbol @ %p %u\n", addr, symValue));
}
- else if (symtab_i->SectionNumber > 0
+ else if (secNumber > 0
&& section
&& section->kind == SECTIONKIND_IMPORT_LIBRARY) {
/* This is an import section. We should load the dll and lookup
@@ -1231,8 +1554,8 @@ ocGetNames_PEi386 ( ObjectCode* oc )
stgFree(dirName);
symtab_i = (COFF_symbol*)
- myindex ( sizeof_COFF_symbol, symtab, oc->n_symbols-1 );
- sname = cstring_from_COFF_symbol_name(symtab_i->N.ShortName, strtab);
+ myindex ( getSymbolSize (info), symtab, oc->n_symbols-1 );
+ sname = cstring_from_COFF_symbol_name(getSymShortName (info, symtab_i), strtab);
IF_DEBUG(linker,
debugBelch("loading symbol `%s' from dll: '%ls' => `%s'\n",
@@ -1285,7 +1608,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
&& (!section || (section && section->kind != SECTIONKIND_IMPORT))) {
/* debugBelch("addSymbol %p `%s' Weak:%lld \n", addr, sname, isWeak); */
IF_DEBUG(linker, debugBelch("addSymbol %p `%s'\n", addr,sname));
- ASSERT(i >= 0 && i < oc->n_symbols);
+ ASSERT(i < (uint32_t)oc->n_symbols);
/* cstring_from_COFF_symbol_name always succeeds. */
oc->symbols[i] = (SymbolName*)sname;
if (isWeak) {
@@ -1307,7 +1630,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
" name `",
i
);
- printName ( symtab_i->N.ShortName, strtab );
+ printName ( getSymShortName (info, symtab_i), strtab );
debugBelch(
"'\n"
" value 0x%x\n"
@@ -1315,16 +1638,16 @@ ocGetNames_PEi386 ( ObjectCode* oc )
" type 0x%x\n"
" sclass 0x%x\n"
" nAux %d\n",
- symtab_i->Value,
- (int32_t)(symtab_i->SectionNumber),
- (uint32_t)symtab_i->Type,
- (uint32_t)symtab_i->StorageClass,
- (uint32_t)symtab_i->NumberOfAuxSymbols
+ symValue,
+ getSymSectionNumber (info, symtab_i),
+ getSymType (info, symtab_i),
+ getSymStorageClass (info, symtab_i),
+ getSymNumberOfAuxSymbols (info, symtab_i)
);
# endif
}
- i += symtab_i->NumberOfAuxSymbols;
+ i += getSymNumberOfAuxSymbols (info, symtab_i);
}
return true;
@@ -1341,7 +1664,9 @@ ocAllocateSymbolExtras_PEi386 ( ObjectCode* oc )
oc->symbol_extras = (SymbolExtra*)(oc->image - PEi386_IMAGE_OFFSET
+ ((PEi386_IMAGE_OFFSET + oc->fileSize + 0x7) & ~0x7));
oc->first_symbol_extra = 0;
- oc->n_symbol_extras = ((COFF_header*)oc->image)->NumberOfSymbols;
+ COFF_HEADER_INFO *info = getHeaderInfo (oc);
+ oc->n_symbol_extras = info->numberOfSymbols;
+ stgFree (info);
return true;
}
@@ -1375,7 +1700,6 @@ makeSymbolExtra_PEi386( ObjectCode* oc, uint64_t index, size_t s, char* symbol )
bool
ocResolve_PEi386 ( ObjectCode* oc )
{
- COFF_header* hdr;
COFF_section* sectab;
COFF_symbol* symtab;
uint8_t* strtab;
@@ -1384,7 +1708,7 @@ ocResolve_PEi386 ( ObjectCode* oc )
size_t S;
SymbolAddr* pP;
- int i;
+ unsigned int i;
uint32_t j, noRelocs;
/* ToDo: should be variable-sized? But is at least safe in the
@@ -1392,20 +1716,23 @@ ocResolve_PEi386 ( ObjectCode* oc )
uint8_t symbol[1000];
/* debugBelch("resolving for %s\n", oc->fileName); */
- hdr = (COFF_header*)(oc->image);
+ COFF_HEADER_INFO *info = getHeaderInfo (oc);
+
sectab = (COFF_section*) (
((uint8_t*)(oc->image))
- + sizeof_COFF_header + hdr->SizeOfOptionalHeader
+ + info->sizeOfHeader + info->sizeOfOptionalHeader
);
symtab = (COFF_symbol*) (
((uint8_t*)(oc->image))
- + hdr->PointerToSymbolTable
+ + info->pointerToSymbolTable
);
strtab = ((uint8_t*)(oc->image))
- + hdr->PointerToSymbolTable
- + hdr->NumberOfSymbols * sizeof_COFF_symbol;
+ + info->pointerToSymbolTable
+ + info->numberOfSymbols * getSymbolSize (info);
+
+ uint32_t numberOfSections = info->numberOfSections;
- for (i = 0; i < hdr->NumberOfSections; i++) {
+ for (i = 0; i < numberOfSections; i++) {
COFF_section* sectab_i
= (COFF_section*)
myindex ( sizeof_COFF_section, sectab, i );
@@ -1474,12 +1801,12 @@ ocResolve_PEi386 ( ObjectCode* oc )
A = *(uint32_t*)pP;
/* the symbol to connect to */
sym = (COFF_symbol*)
- myindex ( sizeof_COFF_symbol,
+ myindex ( getSymbolSize (info),
symtab, reltab_j->SymbolTableIndex );
#if defined(x86_64_HOST_ARCH)
- uint64_t symIndex = ((uint64_t)myindex(sizeof_COFF_symbol, symtab,
+ uint64_t symIndex = ((uint64_t)myindex(getSymbolSize (info), symtab,
reltab_j->SymbolTableIndex)
- - (uint64_t)symtab) / sizeof_COFF_symbol;
+ - (uint64_t)symtab) / getSymbolSize (info);
#endif
IF_DEBUG(linker,
@@ -1489,18 +1816,19 @@ ocResolve_PEi386 ( ObjectCode* oc )
i, j,
(uint32_t)reltab_j->Type,
reltab_j->VirtualAddress );
- printName ( sym->N.ShortName, strtab );
+ printName ( getSymShortName (info, sym), strtab );
debugBelch("'\n" ));
- if (sym->StorageClass == IMAGE_SYM_CLASS_STATIC) {
- Section section = oc->sections[sym->SectionNumber-1];
+ if (getSymStorageClass (info, sym) == IMAGE_SYM_CLASS_STATIC) {
+ Section section = oc->sections[getSymSectionNumber (info, sym)-1];
S = ((size_t)(section.start))
- + ((size_t)(sym->Value));
+ + ((size_t)(getSymValue (info, sym)));
} else {
- copyName ( sym->N.ShortName, strtab, symbol, 1000-1 );
+ copyName ( getSymShortName (info, sym), strtab, symbol, 1000-1 );
S = (size_t) lookupSymbol_( (char*)symbol );
if ((void*)S == NULL) {
errorBelch(" | %" PATH_FMT ": unknown symbol `%s'", oc->fileName, symbol);
+ stgFree (info);
return false;
}
}
@@ -1556,7 +1884,7 @@ ocResolve_PEi386 ( ObjectCode* oc )
size_t v;
v = S + ((size_t)A);
if (v >> 32) {
- copyName ( sym->N.ShortName, strtab, symbol, 1000-1 );
+ copyName ( getSymShortName (info, sym), strtab, symbol, 1000-1 );
S = makeSymbolExtra_PEi386(oc, symIndex, S, (char *)symbol);
/* And retry */
v = S + ((size_t)A);
@@ -1574,7 +1902,7 @@ ocResolve_PEi386 ( ObjectCode* oc )
v = ((intptr_t)S) + ((intptr_t)(int32_t)A) - ((intptr_t)pP) - 4;
if ((v >> 32) && ((-v) >> 32)) {
/* Make the trampoline then */
- copyName ( sym->N.ShortName, strtab, symbol, 1000-1 );
+ copyName ( getSymShortName (info, sym), strtab, symbol, 1000-1 );
S = makeSymbolExtra_PEi386(oc, symIndex, S, (char *)symbol);
/* And retry */
v = ((intptr_t)S) + ((intptr_t)(int32_t)A) - ((intptr_t)pP) - 4;
@@ -1590,12 +1918,14 @@ ocResolve_PEi386 ( ObjectCode* oc )
default:
debugBelch("%" PATH_FMT ": unhandled PEi386 relocation type %d\n",
oc->fileName, reltab_j->Type);
+ stgFree (info);
return false;
}
}
}
+ stgFree (info);
IF_DEBUG(linker, debugBelch("completed %" PATH_FMT "\n", oc->fileName));
return true;
}
@@ -1618,19 +1948,18 @@ ocResolve_PEi386 ( ObjectCode* oc )
bool
ocRunInit_PEi386 ( ObjectCode *oc )
{
- COFF_header* hdr;
COFF_section* sectab;
uint8_t* strtab;
- int i;
+ unsigned int i;
- hdr = (COFF_header*)(oc->image);
+ COFF_HEADER_INFO *info = getHeaderInfo (oc);
sectab = (COFF_section*) (
((uint8_t*)(oc->image))
- + sizeof_COFF_header + hdr->SizeOfOptionalHeader
+ + info->sizeOfHeader + info->sizeOfOptionalHeader
);
strtab = ((uint8_t*)(oc->image))
- + hdr->PointerToSymbolTable
- + hdr->NumberOfSymbols * sizeof_COFF_symbol;
+ + info->pointerToSymbolTable
+ + info->numberOfSymbols * getSymbolSize (info);
int argc, envc;
char **argv, **envv;
@@ -1644,7 +1973,7 @@ ocRunInit_PEi386 ( ObjectCode *oc )
This can be done by saving the index of the .ctor section in the ObjectCode
from ocGetNames. Then this loop isn't needed. */
- for (i = 0; i < hdr->NumberOfSections; i++) {
+ for (i = 0; i < info->numberOfSections; i++) {
COFF_section* sectab_i
= (COFF_section*)
myindex ( sizeof_COFF_section, sectab, i );
@@ -1661,6 +1990,7 @@ ocRunInit_PEi386 ( ObjectCode *oc )
}
}
}
+ stgFree (info);
freeProgEnvv(envc, envv);
return true;
}
diff --git a/rts/linker/PEi386.h b/rts/linker/PEi386.h
index 44f280fdb3..e84e05232a 100644
--- a/rts/linker/PEi386.h
+++ b/rts/linker/PEi386.h
@@ -14,6 +14,31 @@
#define PEi386_IMAGE_OFFSET 0
#endif
+/********************************************
+ * COFF/PE types
+ ********************************************/
+
+typedef enum _COFF_OBJ_TYPE {
+ COFF_IMAGE,
+ COFF_ANON_OBJ,
+ COFF_IMPORT_LIB,
+ COFF_ANON_BIG_OBJ,
+ COFF_UNKNOWN
+} COFF_OBJ_TYPE;
+
+typedef struct _COFF_HEADER_INFO {
+ COFF_OBJ_TYPE type;
+ uint16_t sizeOfOptionalHeader;
+ uint16_t sizeOfHeader;
+ uint32_t pointerToSymbolTable;
+ uint32_t numberOfSymbols;
+ uint32_t numberOfSections;
+} COFF_HEADER_INFO;
+
+/********************************************
+ * COFF/PE prototypes
+ ********************************************/
+
void initLinker_PEi386( void );
const char * addDLL_PEi386( pathchar *dll_name, HINSTANCE *instance );
void freePreloadObjectFile_PEi386( ObjectCode *oc );
@@ -43,9 +68,6 @@ allocateImageAndTrampolines (
/********************************************
* COFF/PE headers
********************************************/
-typedef IMAGE_FILE_HEADER COFF_header;
-#define sizeof_COFF_header sizeof(COFF_header)
-
/* Section 7.1 PE Specification */
typedef IMPORT_OBJECT_HEADER COFF_import_header;
#define sizeof_COFF_import_Header sizeof(COFF_import_header)
@@ -54,9 +76,11 @@ typedef IMAGE_SECTION_HEADER COFF_section;
#define sizeof_COFF_section sizeof(COFF_section)
-typedef IMAGE_SYMBOL COFF_symbol;
-#define sizeof_COFF_symbol sizeof(COFF_symbol)
+typedef IMAGE_SYMBOL COFF_symbol_og;
+#define sizeof_COFF_symbol_og sizeof(COFF_symbol_og)
+typedef IMAGE_SYMBOL_EX COFF_symbol_ex;
+#define sizeof_COFF_symbol_ex sizeof(COFF_symbol_ex)
typedef IMAGE_RELOCATION COFF_reloc;
#define sizeof_COFF_reloc sizeof(COFF_reloc)
@@ -65,6 +89,13 @@ typedef IMAGE_RELOCATION COFF_reloc;
typedef DLL_DIRECTORY_COOKIE(WINAPI *LPAddDLLDirectory)(PCWSTR NewDirectory);
typedef WINBOOL(WINAPI *LPRemoveDLLDirectory)(DLL_DIRECTORY_COOKIE Cookie);
+/* Combine union of possible symbol types. */
+typedef
+union _COFF_symbol {
+ COFF_symbol_og og;
+ COFF_symbol_ex ex;
+} COFF_symbol;
+
/* A record for storing handles into DLLs. */
typedef
struct _OpenedDLL {
@@ -80,6 +111,17 @@ struct _IndirectAddr {
struct _IndirectAddr* next;
} IndirectAddr;
+/* Util symbol handling functions. */
+COFF_OBJ_TYPE getObjectType ( char* image, pathchar* fileName );
+COFF_HEADER_INFO* getHeaderInfo ( ObjectCode* oc );
+size_t getSymbolSize ( COFF_HEADER_INFO *info );
+int32_t getSymSectionNumber ( COFF_HEADER_INFO *info, COFF_symbol* sym );
+uint32_t getSymValue ( COFF_HEADER_INFO *info, COFF_symbol* sym );
+uint8_t getSymStorageClass ( COFF_HEADER_INFO *info, COFF_symbol* sym );
+uint8_t getSymNumberOfAuxSymbols ( COFF_HEADER_INFO *info, COFF_symbol* sym );
+uint16_t getSymType ( COFF_HEADER_INFO *info, COFF_symbol* sym );
+uint8_t* getSymShortName ( COFF_HEADER_INFO *info, COFF_symbol* sym );
+
/* See Note [mingw-w64 name decoration scheme] */
#if !defined(x86_64_HOST_ARCH)
#define STRIP_LEADING_UNDERSCORE 1