diff options
| author | wolfgang <unknown> | 2005-06-13 02:44:22 +0000 |
|---|---|---|
| committer | wolfgang <unknown> | 2005-06-13 02:44:22 +0000 |
| commit | c26a153cb20aa69dce35cf0317205336f4e5f0bb (patch) | |
| tree | b17dabbfe451c723ccce41b0f8ed5b8fb5cdec18 | |
| parent | 4302b12e6fd876a190ce6091e6ce14dbeb15bc00 (diff) | |
| download | haskell-c26a153cb20aa69dce35cf0317205336f4e5f0bb.tar.gz | |
[project @ 2005-06-13 02:44:22 by wolfgang]
Darwin:
Deal with the fact that the code and data in a .o file might not be
16-byte aligned even if it contains instructions that require 16-byte
alignment.
This fixes floating point related crashes on Darwin/x86; there might
also have been problems on Darwin/ppc if people load .o files with
AltiVec code into GHCi.
| -rw-r--r-- | ghc/rts/Linker.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/ghc/rts/Linker.c b/ghc/rts/Linker.c index 9cee55a11b..52412dcb35 100644 --- a/ghc/rts/Linker.c +++ b/ghc/rts/Linker.c @@ -110,6 +110,7 @@ static int ocVerifyImage_MachO ( ObjectCode* oc ); static int ocGetNames_MachO ( ObjectCode* oc ); static int ocResolve_MachO ( ObjectCode* oc ); +static int machoGetMisalignment( FILE * ); #ifdef powerpc_HOST_ARCH static int ocAllocateJumpIslands_MachO ( ObjectCode* oc ); static void machoInitSymbolsWithoutUnderscore( void ); @@ -690,7 +691,7 @@ static RtsSymbolVal rtsSyms[] = { // dyld stub code contains references to this, // but it should never be called because we treat // lazy pointers as nonlazy. - { "dyld_stub_binding_helper", 0xDEADBEEF }, + { "dyld_stub_binding_helper", (void*)0xDEADBEEF }, #endif { 0, 0 } /* sentinel */ }; @@ -1029,6 +1030,7 @@ loadObj( char *path ) void *map_addr = NULL; #else FILE *f; + int misalignment; #endif initLinker(); @@ -1133,13 +1135,29 @@ loadObj( char *path ) #else /* !USE_MMAP */ - oc->image = stgMallocBytes(oc->fileSize, "loadObj(image)"); - /* load the image into memory */ f = fopen(path, "rb"); if (!f) barf("loadObj: can't read `%s'", path); +#ifdef 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 oc->image on purpose so + // that the actual sections end up aligned again. + misalignment = machoGetMisalignment(f); +#else + misalignment = 0; +#endif + + oc->image = stgMallocBytes(oc->fileSize + misalignment, "loadObj(image)"); + oc->image += misalignment; + n = fread ( oc->image, 1, oc->fileSize, f ); if (n != oc->fileSize) barf("loadObj: error whilst reading `%s'", path); @@ -4021,4 +4039,26 @@ static void machoInitSymbolsWithoutUnderscore() #undef Sym } #endif + +/* + * 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 + */ +static int machoGetMisalignment( FILE * f ) +{ + struct mach_header header; + int misalignment; + + fread(&header, sizeof(header), 1, f); + rewind(f); + + if(header.magic != MH_MAGIC) + return 0; + + misalignment = (header.sizeofcmds + sizeof(header)) + & 0xF; + + return misalignment ? (16 - misalignment) : 0; +} + #endif |
