Andreas Klebinger pushed to branch wip/andreask/linker_fix at Glasgow Haskell Compiler / GHC
Commits:
e3e1bec3 by Andreas Klebinger at 2026-04-03T11:32:27+00:00
rts: LoadArchive/LoadObj - refactor object verification.
Fixes #26231.
We now consistently call `verifyAndInitOc` to check for valid object code.
Allowing us to replace the somewhat adhoc magic number checking in
loadArchive with the platform specific verification logic.
On windows this adds loadArchive support for
AArch64/32bit COFF bigobj files.
- - - - -
ac470315 by Andreas Klebinger at 2026-04-03T11:32:36+00:00
RTS Linker: Refactor import lib detection on windows.
- - - - -
2c44763e by Andreas Klebinger at 2026-04-03T11:32:36+00:00
Add debug tracing things.
- - - - -
0d51a744 by Andreas Klebinger at 2026-04-03T11:32:36+00:00
Recognize all common mac section names.
Invalid machO entries are failure condition now.
- - - - -
583b53e2 by Andreas Klebinger at 2026-04-03T11:34:25+00:00
Rip out old macOS misalignment code.
Best I can tell it is no longer needed as we now *always* align individual sections.
The handling was already very inconsistent with very few code paths actually doing this alignment.
So I'm letting it go and will see if anything falls over.
- - - - -
a34b3fa5 by Andreas Klebinger at 2026-04-03T12:33:16+00:00
Cleanup logs/build warnings.
- - - - -
8 changed files:
- rts/Linker.c
- rts/LinkerInternals.h
- rts/linker/LoadArchive.c
- rts/linker/LoadNativeObjPosix.c
- rts/linker/MachO.c
- rts/linker/MachO.h
- rts/linker/PEi386.c
- rts/linker/SymbolExtras.c
Changes:
=====================================
rts/Linker.c
=====================================
@@ -1240,7 +1240,7 @@ void freeObjectCode (ObjectCode *oc)
ObjectCode*
mkOc( ObjectType type, pathchar *path, char *image, int imageSize,
- bool mapped, pathchar *archiveMemberName, int misalignment ) {
+ bool mapped, pathchar *archiveMemberName ) {
ObjectCode* oc;
@@ -1294,7 +1294,6 @@ mkOc( ObjectType type, pathchar *path, char *image, int imageSize,
oc->bssEnd = NULL;
oc->imageMapped = mapped;
- oc->misalignment = misalignment;
oc->cxa_finalize = NULL;
oc->extraInfos = NULL;
@@ -1352,7 +1351,6 @@ preloadObjectFile (pathchar *path)
int r;
void *image;
ObjectCode *oc;
- int misalignment = 0;
r = pathstat(path, &st);
if (r == -1) {
@@ -1410,27 +1408,8 @@ preloadObjectFile (pathchar *path)
return NULL;
}
-# if defined(darwin_HOST_OS)
-
- // In a Mach-O .o file, all sections can and will be misaligned
- // if the total size of the headers is not a multiple of the
- // desired alignment. This is fine for .o files that only serve
- // as input for the static linker, but it's not fine for us,
- // as SSE (used by gcc for floating point) and Altivec require
- // 16-byte alignment.
- // We calculate the correct alignment from the header before
- // reading the file, and then we misalign image on purpose so
- // that the actual sections end up aligned again.
- misalignment = machoGetMisalignment(f);
- image = stgMallocBytes(fileSize + misalignment, "loadObj(image)");
- image += misalignment;
-
-# else /* !defined(darwin_HOST_OS) */
-
image = stgMallocBytes(fileSize, "loadObj(image)");
-#endif /* !defined(darwin_HOST_OS) */
-
int n;
n = fread ( image, 1, fileSize, f );
fclose(f);
@@ -1445,16 +1424,13 @@ preloadObjectFile (pathchar *path)
IF_DEBUG(linker, debugBelch("loadObj: preloaded image at %p\n", (void *) image));
/* FIXME (AP): =mapped= parameter unconditionally set to true */
- oc = mkOc(STATIC_OBJECT, path, image, fileSize, true, NULL, misalignment);
+ oc = mkOc(STATIC_OBJECT, path, image, fileSize, true, NULL);
-#if defined(OBJFORMAT_MACHO)
- if (ocVerifyImage_MachO( oc ))
- ocInit_MachO( oc );
-#endif
-#if defined(OBJFORMAT_ELF)
- if(ocVerifyImage_ELF( oc ))
- ocInit_ELF( oc );
-#endif
+ if (!verifyAndInitOc(oc)) {
+ ocDebugBelch(oc, "loadObj: Failed to verify oc.\n");
+ freeObjectCode(oc);
+ return NULL;
+ }
return oc;
}
@@ -1511,27 +1487,42 @@ HsInt loadObj (pathchar *path)
return r;
}
+// Call the relevant VerifyImage_* and ocInit_* functions.
+// Return 1 on success.
+HsInt verifyAndInitOc (ObjectCode* oc)
+{
+ int r;
+
+ /* verify the in-memory image */
+#if defined(OBJFORMAT_ELF)
+ r = ocVerifyImage_ELF ( oc );
+ if(r) {
+ ocInit_ELF( oc );
+ }
+#elif defined(OBJFORMAT_PEi386)
+ r = ocVerifyImage_PEi386 ( oc );
+#elif defined(OBJFORMAT_MACHO)
+ r = ocVerifyImage_MachO ( oc );
+ if(r) {
+ ocInit_MachO( oc );
+ }
+#else
+ barf("loadObj: no verify method");
+#endif
+ if (!r) {
+ IF_DEBUG(linker, ocDebugBelch(oc, "ocVerifyImage_* failed\n"));
+ return r;
+ }
+ return 1;
+}
+
+// Precondition: oc already verified.
HsInt loadOc (ObjectCode* oc)
{
int r;
IF_DEBUG(linker, ocDebugBelch(oc, "start\n"));
- /* verify the in-memory image */
-# if defined(OBJFORMAT_ELF)
- r = ocVerifyImage_ELF ( oc );
-# elif defined(OBJFORMAT_PEi386)
- r = ocVerifyImage_PEi386 ( oc );
-# elif defined(OBJFORMAT_MACHO)
- r = ocVerifyImage_MachO ( oc );
-# else
- barf("loadObj: no verify method");
-# endif
- if (!r) {
- IF_DEBUG(linker, ocDebugBelch(oc, "ocVerifyImage_* failed\n"));
- return r;
- }
-
/* Note [loadOc orderings]
~~~~~~~~~~~~~~~~~~~~~~~
The order of `ocAllocateExtras` and `ocGetNames` matters. For MachO
@@ -1593,7 +1584,7 @@ HsInt loadOc (ObjectCode* oc)
oc->status = OBJECT_LOADED;
}
}
- IF_DEBUG(linker, ocDebugBelch(oc, "done\n"));
+ IF_DEBUG(linker, ocDebugBelch(oc, "loadOc:done\n"));
return 1;
}
=====================================
rts/LinkerInternals.h
=====================================
@@ -264,10 +264,6 @@ struct _ObjectCode {
/* non-zero if the object file was mmap'd, otherwise malloc'd */
int imageMapped;
- /* record by how much image has been deliberately misaligned
- after allocation, so that we can use realloc */
- int misalignment;
-
/* The address of __cxa_finalize; set when at least one finalizer was
* register and therefore we must call __cxa_finalize before unloading.
* See Note [Resolving __dso_handle]. */
@@ -390,6 +386,11 @@ extern Elf_Word shndx_table_uninit_label;
OC_INFORMATIVE_FILENAME(oc), \
##__VA_ARGS__)
+#define ocBelch(oc, s, ...) \
+ errorBelch("%s(%" PATH_FMT ": " s, \
+ __func__, \
+ OC_INFORMATIVE_FILENAME(oc), \
+ ##__VA_ARGS__)
#if defined(THREADED_RTS)
extern Mutex linker_mutex;
@@ -487,12 +488,17 @@ HsInt loadArchive_ (pathchar *path);
HsInt isAlreadyLoaded( pathchar *path );
OStatus getObjectLoadStatus_ (pathchar *path);
ObjectCode *lookupObjectByPath(pathchar *path);
+
+/* Verify an objects is an a format that can be loaded and initialize the oc struct if required. */
+HsInt verifyAndInitOc( ObjectCode *oc );
+
+//Expects the oc to be verified already.
HsInt loadOc( ObjectCode* oc );
ObjectCode* mkOc( ObjectType type, pathchar *path, char *image, int imageSize,
- bool mapped, pathchar *archiveMemberName,
- int misalignment
+ bool mapped, pathchar *archiveMemberName
);
+
void initSegment(Segment *s, void *start, size_t size, SegmentProt prot, int n_sections);
void freeSegments(ObjectCode *oc);
=====================================
rts/linker/LoadArchive.c
=====================================
@@ -24,7 +24,9 @@
#include
#include
#include
+#include
#include
+#include
#define FAIL(...) do {\
errorBelch("loadArchive: "__VA_ARGS__); \
@@ -33,7 +35,6 @@
#define DEBUG_LOG(...) IF_DEBUG(linker, debugBelch("loadArchive: " __VA_ARGS__))
-
#if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
/* Read 4 bytes and convert to host byte order */
static uint32_t read4Bytes(const char buf[static 4])
@@ -110,56 +111,8 @@ static bool loadFatArchive(char input[static 20], FILE* f, pathchar* path)
}
#endif
-enum ObjectFileFormat {
- NotObject,
- COFFAmd64,
- COFFI386,
- COFFAArch64,
- ELF,
- MachO32,
- MachO64,
-};
-
-static enum ObjectFileFormat identifyObjectFile_(char* buf, size_t sz)
-{
- if (sz > 2 && ((uint16_t*)buf)[0] == 0x8664) {
- return COFFAmd64;
- }
- if (sz > 2 && ((uint16_t*)buf)[0] == 0x014c) {
- return COFFI386;
- }
- if (sz > 2 && ((uint16_t*)buf)[0] == 0xaa64) {
- return COFFAArch64;
- }
- if (sz > 4 && memcmp(buf, "\x7f" "ELF", 4) == 0) {
- return ELF;
- }
- if (sz > 4 && ((uint32_t*)buf)[0] == 0xfeedface) {
- return MachO32;
- }
- if (sz > 4 && ((uint32_t*)buf)[0] == 0xfeedfacf) {
- return MachO64;
- }
- // BigObj COFF files ...
- if (sz > 8 && ((uint64_t*)buf)[0] == 0x86640002ffff0000) {
- return COFFAmd64;
- }
- return NotObject;
-}
-
-static enum ObjectFileFormat identifyObjectFile(FILE *f)
+static pathchar* thinArchiveMemberPath(pathchar* path, char* fileName)
{
- char buf[32];
- ssize_t sz = fread(buf, 1, 32, f);
- CHECK(fseek(f, -sz, SEEK_CUR) == 0);
- return identifyObjectFile_(buf, sz);
-}
-
-static bool readThinArchiveMember(int n, int memberSize, pathchar* path,
- char* fileName, char* image)
-{
- bool has_succeeded = false;
- FILE* member = NULL;
pathchar *pathCopy, *dirName, *memberPath, *objFileName;
memberPath = NULL;
/* Allocate and setup the dirname of the archive. We'll need
@@ -173,15 +126,29 @@ static bool readThinArchiveMember(int n, int memberSize, pathchar* path,
objFileName = mkPath(fileName);
pathprintf(memberPath, memberLen, WSTR("%" PATH_FMT "%" PATH_FMT), dirName,
objFileName);
- stgFree(objFileName);
+
+ stgFree(pathCopy);
stgFree(dirName);
+ stgFree(objFileName);
+ return memberPath;
+}
+
+static bool readThinArchiveMember(int memberSize, pathchar* path,
+ char* fileName, char* image)
+{
+ bool has_succeeded = false;
+ FILE* member = NULL;
+ pathchar *memberPath;
+ //Fully resolved path.
+ memberPath = thinArchiveMemberPath(path, fileName);
+
member = pathopen(memberPath, WSTR("rb"));
if (!member) {
errorBelch("loadObj: can't read thin archive `%" PATH_FMT "'",
memberPath);
goto inner_fail;
}
- n = fread(image, 1, memberSize, member);
+ int n = fread(image, 1, memberSize, member);
if (n != memberSize) {
errorBelch("loadArchive: error whilst reading `%s'",
fileName);
@@ -192,7 +159,6 @@ static bool readThinArchiveMember(int n, int memberSize, pathchar* path,
inner_fail:
fclose(member);
stgFree(memberPath);
- stgFree(pathCopy);
return has_succeeded;
}
@@ -379,7 +345,6 @@ HsInt loadArchive_ (pathchar *path)
int memberIdx = 0;
FILE *f = NULL;
size_t thisFileNameSize = (size_t) -1; /* shut up bogus GCC warning */
- int misalignment = 0;
DEBUG_LOG("start\n");
DEBUG_LOG("Loading archive `%" PATH_FMT "'\n", path);
@@ -387,8 +352,7 @@ HsInt loadArchive_ (pathchar *path)
/* Check that we haven't already loaded this archive.
Ignore requests to load multiple times */
if (isAlreadyLoaded(path)) {
- IF_DEBUG(linker,
- debugBelch("ignoring repeated load of %" PATH_FMT "\n", path));
+ DEBUG_LOG("ignoring repeated load of %" PATH_FMT "\n", path);
return 1; /* success */
}
@@ -407,6 +371,9 @@ HsInt loadArchive_ (pathchar *path)
FAIL("failed to identify archive format of %" PATH_FMT ".", path);
}
bool isThin = archive_fmt == ThinArchive;
+ if(isThin) {
+ DEBUG_LOG("Found thin archive.\n");
+ }
DEBUG_LOG("loading archive contents\n");
@@ -547,9 +514,25 @@ HsInt loadArchive_ (pathchar *path)
}
DEBUG_LOG("Found member file `%s'\n", fileName);
-
bool is_symbol_table = strcmp("", fileName) == 0;
- enum ObjectFileFormat object_fmt = is_symbol_table ? NotObject : identifyObjectFile(f);
+#if defined(OBJFORMAT_MACHO)
+ if (!is_symbol_table) {
+ /* Darwin ranlib symbol tables are named __.SYMDEF*
+ * There is no good documentation for this. Your best bets are
+ * probably the LLVM and Apple cctools sources.
+ */
+ if (strncmp(fileName, "__.SYMDEF", sizeof("__.SYMDEF")) == 0 ||
+ strncmp(fileName, "__.SYMDEF SORTED", sizeof("__.SYMDEF SORTED")) == 0 ||
+ strncmp(fileName, "__.SYMDEF_64", sizeof("__.SYMDEF_64")) == 0 ||
+ strncmp(fileName, "__.SYMDEF_64 SORTED", sizeof("__.SYMDEF_64 SORTED")) == 0) {
+ is_symbol_table = true;
+ }
+ }
+#endif
+
+/////////////////////////////////////////////////
+// We found the member file. Load it into memory.
+/////////////////////////////////////////////////
#if defined(OBJFORMAT_PEi386)
/*
@@ -562,39 +545,70 @@ HsInt loadArchive_ (pathchar *path)
* for sections. So on windows, just try to load it all.
*
* Linker members (e.g. filename / are skipped since they are not needed)
+ *
+ * AK: The gist of it is really that we need to:
+ * + Load .dll members as objects if they are *not* an import lib.
+ * + Load .dll members as import libs if they are ... import libs.
+ *
+ * There seems to be no good place to make this decision so i've put the
+ * ugly import lib detection code here, keeping the rest of the verification/loading
+ * logic relatively tidy. We basically read parts of the member file to get
+ * the header and then reuse the PE linkers type detection logic.
+ *
+ * We read at least sizeof(ANON_OBJECT_HEADER) bytes, but at most
+ * sizeof(ANON_OBJECT_HEADER_BIGOBJ). Members might be megabytes in size
+ * and we really only need at most the size of the largest header to determine
+ * the type.
*/
- bool isImportLib = thisFileNameSize >= 4 && strncmp(fileName + thisFileNameSize - 4, ".dll", 4) == 0;
-#else
- bool isImportLib = false;
-#endif // windows
+ bool mb_peImportLib = thisFileNameSize >= 4 && strncmp(fileName + thisFileNameSize - 4, ".dll", 4) == 0;
+ bool importLib = false;
+ if (mb_peImportLib) {
+
+ char buf[sizeof(ANON_OBJECT_HEADER_BIGOBJ)];
+ // Too small to be a import lib
+ if(memberSize < sizeof(ANON_OBJECT_HEADER)) { importLib = false;}
+ // Read & Check the header
+ else {
+ if (isThin)
+ { if (!readThinArchiveMember(
+ stg_min(sizeof(ANON_OBJECT_HEADER_BIGOBJ), memberSize),
+ path, fileName, buf))
+ { goto fail; }
+ }
+ else {
+ ssize_t sz = fread(buf, 1, sizeof(ANON_OBJECT_HEADER_BIGOBJ), f);
+ CHECK(fseek(f, -sz, SEEK_CUR) == 0);
+ }
+ importLib = getObjectType(buf, path) == COFF_IMPORT_LIB;
+ }
+ IF_DEBUG(linker, if(importLib) { DEBUG_LOG("\tfound import lib.\n") })
+ }
+#endif // windows
DEBUG_LOG("\tthisFileNameSize = %d\n", (int)thisFileNameSize);
- DEBUG_LOG("\tisObject = %d\n", object_fmt);
-
- if ((!is_symbol_table && isThin) || object_fmt != NotObject) {
- DEBUG_LOG("Member is an object file...loading...\n");
+ if (!is_symbol_table
+#if defined(OBJFORMAT_PEi386)
+ && !importLib
+#endif
+ )
+ {
+ ASSERT(!isGnuIndex);
+ DEBUG_LOG("Member might be an object file...loading...\n");
#if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
- if (RTS_LINKER_USE_MMAP)
- image = mmapAnonForLinker(memberSize);
- else {
- /* See loadObj() */
- misalignment = machoGetMisalignment(f);
- image = stgMallocBytes(memberSize + misalignment,
- "loadArchive(image)");
- image += misalignment;
- }
+#if defined(RTS_LINKER_USE_MMAP)
+ image = mmapAnonForLinker(memberSize);
+#else
+#error "Only MMAP based loading supported on Apple platforms"
+#endif // defined(RTS_LINKER_USE_MMAP)
#else // not darwin
image = stgMallocBytes(memberSize, "loadArchive(image)");
#endif
if (isThin) {
- if (!readThinArchiveMember(n, memberSize, path, fileName, image)) {
- goto fail;
+ if (!readThinArchiveMember(memberSize, path, fileName, image)) {
+ FAIL("Failed to read thin member %" PATH_FMT"\n", path);
}
- // Unlike for regular archives for thin archives we can only identify the object format
- // after having read the file pointed to.
- object_fmt = identifyObjectFile_(image, memberSize);
}
else
{
@@ -613,21 +627,26 @@ HsInt loadArchive_ (pathchar *path)
pathprintf(archiveMemberName, size+1, WSTR("%" PATH_FMT "(#%d:%.*s)"),
path, memberIdx, (int)thisFileNameSize, fileName);
- ObjectCode *oc = mkOc(STATIC_OBJECT, path, image, memberSize, false, archiveMemberName,
- misalignment);
-#if defined(OBJFORMAT_MACHO)
- ASSERT(object_fmt == MachO32 || object_fmt == MachO64);
- ocInit_MachO( oc );
-#endif
-#if defined(OBJFORMAT_ELF)
- ASSERT(object_fmt == ELF);
- ocInit_ELF( oc );
-#endif
+///////////////////////////////////////////////////////////////
+// Verfiy the object file is valid, and load it if appropriate.
+///////////////////////////////////////////////////////////////
+ // Prepare headers, doesn't load any data yet.
+ ObjectCode *oc = mkOc(STATIC_OBJECT, path, image, memberSize, false, archiveMemberName);
stgFree(archiveMemberName);
+ if(!verifyAndInitOc( oc ))
+ {
+ errorBelch("Failed to verify %" PATH_FMT " , aborting.\n", path);
+ freeObjectCode( oc );
+ continue;
+ }
+
+
if (0 == loadOc(oc)) {
+ ocBelch(oc, "Failed to load OC %" PATH_FMT " , aborting.\n", path);
stgFree(fileName);
+ freeObjectCode( oc );
fclose(f);
return 0;
} else {
@@ -654,8 +673,8 @@ while reading filename from `%" PATH_FMT "'", path);
gnuFileIndex[memberSize] = '/';
gnuFileIndexSize = memberSize;
}
- else if (isImportLib) {
#if defined(OBJFORMAT_PEi386)
+ else if (importLib) {
if (checkAndLoadImportLibrary(path, fileName, f)) {
DEBUG_LOG("Member is an import file section... "
"Corresponding DLL has been loaded...\n");
@@ -668,8 +687,8 @@ while reading filename from `%" PATH_FMT "'", path);
FAIL("error whilst seeking by %zd in `%" PATH_FMT "'",
memberSize, path);
}
-#endif
}
+#endif
else {
DEBUG_LOG("`%s' does not appear to be an object file\n",
fileName);
@@ -698,7 +717,7 @@ while reading filename from `%" PATH_FMT "'", path);
}
memberIdx ++;
DEBUG_LOG("reached end of archive loading while loop\n");
- }
+ } // while(1)
retcode = 1;
fail:
if (f != NULL)
@@ -742,4 +761,3 @@ bool isArchive (pathchar *path)
}
return strncmp(ARCHIVE_HEADER, buffer, sizeof(ARCHIVE_HEADER)-1) == 0;
}
-
=====================================
rts/linker/LoadNativeObjPosix.c
=====================================
@@ -134,7 +134,7 @@ void * loadNativeObj_POSIX (pathchar *path, char **errmsg)
goto dlopen_fail;
}
- nc = mkOc(DYNAMIC_OBJECT, path, NULL, 0, false, NULL, 0);
+ nc = mkOc(DYNAMIC_OBJECT, path, NULL, 0, false, NULL);
// If we HAVE_DLINFO, we use RTLD_NOW rather than RTLD_LAZY because we want
// to learn eagerly about all external functions. Otherwise, there is no
=====================================
rts/linker/MachO.c
=====================================
@@ -1,4 +1,5 @@
#include "Rts.h"
+#include "rts/Linker.h"
#if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
@@ -199,11 +200,14 @@ ocAllocateExtras_MachO(ObjectCode* oc)
int
ocVerifyImage_MachO(ObjectCode * oc)
{
+ IF_DEBUG(linker, debugBelch("ocVerifyImage_MachO: start\n"));
char *image = (char*) oc->image;
+ if (oc->fileSize < (int) sizeof(MachOHeader)) {
+ IF_DEBUG(linker, errorBelch("Tried loading machO smaller than header size.\n"));
+ return 0;
+ }
MachOHeader *header = (MachOHeader*) image;
- IF_DEBUG(linker, debugBelch("ocVerifyImage_MachO: start\n"));
-
if(header->magic != MH_MAGIC_64) {
errorBelch("Could not load image %s: bad magic!\n"
" Expected %08x (64bit), got %08x%s\n",
@@ -1774,34 +1778,4 @@ ocRunFini_MachO ( ObjectCode *oc )
return 1;
}
-/*
- * Figure out by how much to shift the entire Mach-O file in memory
- * when loading so that its single segment ends up 16-byte-aligned
- */
-int
-machoGetMisalignment( FILE * f )
-{
- MachOHeader header;
- int misalignment;
-
- {
- size_t n = fread(&header, sizeof(header), 1, f);
- if (n != 1) {
- barf("machoGetMisalignment: can't read the Mach-O header");
- }
- }
- fseek(f, -sizeof(header), SEEK_CUR);
-
- if(header.magic != MH_MAGIC_64) {
- barf("Bad magic. Expected: %08x, got: %08x.",
- MH_MAGIC_64, header.magic);
- }
-
- misalignment = (header.sizeofcmds + sizeof(header))
- & 0xF;
-
- IF_DEBUG(linker, debugBelch("mach-o misalignment %d\n", misalignment));
- return misalignment ? (16 - misalignment) : 0;
-}
-
#endif /* darwin_HOST_OS || ios_HOST_OS */
=====================================
rts/linker/MachO.h
=====================================
@@ -13,7 +13,6 @@ int ocGetNames_MachO ( ObjectCode* oc );
int ocResolve_MachO ( ObjectCode* oc );
int ocRunInit_MachO ( ObjectCode* oc );
int ocRunFini_MachO ( ObjectCode* oc );
-int machoGetMisalignment ( FILE * );
int ocAllocateExtras_MachO ( ObjectCode* oc );
SectionKind getSectionKind_MachO ( MachOSection *macho );
=====================================
rts/linker/PEi386.c
=====================================
@@ -780,6 +780,12 @@ COFF_OBJ_TYPE getObjectType ( char* image, pathchar* fileName )
*************/
COFF_HEADER_INFO* getHeaderInfo ( ObjectCode* oc )
{
+ //No guarantee it's a valid file/oc at this point as we call
+ //getHeaderInfo during verify.
+ if((size_t) oc->fileSize < sizeof(IMAGE_FILE_HEADER)) {
+ IF_DEBUG(linker, ocErrorBelch ("Supposed COFF file smaller than minimum header size.\n"));
+ return NULL;
+ }
COFF_OBJ_TYPE coff_type = getObjectType (oc->image, OC_INFORMATIVE_FILENAME(oc));
COFF_HEADER_INFO* info
@@ -808,11 +814,23 @@ COFF_HEADER_INFO* getHeaderInfo ( ObjectCode* oc )
info->numberOfSections = hdr->NumberOfSections;
}
break;
+ case COFF_IMPORT_LIB:
+ {
+ errorBelch ("Unexpected COFF_IMPORT_LIB in getHeaderInfo.\n");
+ stgFree(info);
+ info = NULL;
+ break;
+ }
default:
{
stgFree (info);
info = NULL;
errorBelch ("Unknown COFF %d type in getHeaderInfo.", coff_type);
+ if(oc->archiveMemberName) {
+ errorBelch ("Archive %" PATH_FMT ".\n", oc->archiveMemberName);
+ }
+ errorBelch ("In %" PATH_FMT ".\n", oc->fileName);
+
}
break;
}
=====================================
rts/linker/SymbolExtras.c
=====================================
@@ -63,14 +63,10 @@ int ocAllocateExtras(ObjectCode* oc, int count, int first, int bssSize)
// round up to the nearest 4
int aligned = (oc->fileSize + 3) & ~3;
- int misalignment = oc->misalignment;
- oc->image -= misalignment;
oc->image = stgReallocBytes( oc->image,
- misalignment +
aligned + extras_size,
"ocAllocateExtras" );
- oc->image += misalignment;
oc->symbol_extras = (SymbolExtra *) (oc->image + aligned);
} else if (USE_CONTIGUOUS_MMAP || RtsFlags.MiscFlags.linkerAlwaysPic) {
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/a5755c4681d76b261f6bd03f576e3bb...
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/a5755c4681d76b261f6bd03f576e3bb...
You're receiving this email because of your account on gitlab.haskell.org.