summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZejun Wu <watashi@fb.com>2018-10-15 13:52:36 -0400
committerRay Shih <rayshih@fb.com>2020-07-14 10:39:34 -0700
commitcb3f710d952c0a2bad539f76c2ab6d07ba894bea (patch)
tree5f055b2817769d110178237c3b2c6f268d135d48
parent2c538aec7125412c4afb18cb93379a79c1c5df15 (diff)
downloadhaskell-cb3f710d952c0a2bad539f76c2ab6d07ba894bea.tar.gz
Add a RTS option -xp to load PIC object anywhere in address space
Add a RTS option -xp to load PIC object anywhere in address space. We do this by relaxing the requirement of <0x80000000 result of `mmapForLinker` and implying USE_CONTIGUOUS_MMAP. We also need to change calls to `ocInit` and `ocGetNames` to avoid dangling pointers when the address of `oc->image` is changed by `ocAllocateSymbolExtra`. Test Plan: ``` $ uname -a Linux localhost 4.18.8-arch1-1-ARCH #1 SMP PREEMPT Sat Sep 15 20:34:48 UTC 2018 x86_64 GNU/Linux $ cat mk/build.mk DYNAMIC_GHC_PROGRAMS = NO DYNAMIC_BY_DEFAULT = NO GhcRTSWays += thr_debug EXTRA_HC_OPTS += -debug WAY_p_HC_OPTS += -fPIC -fexternal-dynamic-refs $ inplace/bin/ghc-stage2 --interactive -prof +RTS -xp GHCi, version 8.7.20180928: http://www.haskell.org/ghc/ :? for help ghc-stage2: R_X86_64_32 relocation out of range: ghczmprim_GHCziTypes_ZMZN_closure = 7f690bffab59 Recompile /data/users/watashi/ghc/libraries/ghc-prim/dist-install/build/HSghc-prim -0.5.3.o with -fPIC -fexternal-dynamic-refs. ghc-stage2: unable to load package `ghc-prim-0.5.3' $ strace -f -e open,mmap inplace/bin/ghc-stage2 --interactive -prof -fexternal-interpreter -opti+RTS -opti-xp ... [pid 1355283] open("/data/users/watashi/ghc/libraries/base/dist-install/build/libHSbas e-4.12.0.0_p.a", O_RDONLY) = 14 [pid 1355283] mmap(NULL, 8192, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6a84842000 [pid 1355283] open("/data/users/watashi/ghc/libraries/base/dist-install/build/libHSbas e-4.12.0.0_p.a", O_RDONLY) = 14 [pid 1355283] mmap(NULL, 8192, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6a84676000 ... Prelude> System.Posix.Process.getProcessID ... [pid 1355283] open("/data/users/watashi/ghc/libraries/unix/dist-install/build/libHSuni x-2.7.2.2_p.a", O_RDONLY) = 14 [pid 1355283] mmap(NULL, 45056, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6a67d60000 [pid 1355283] open("/data/users/watashi/ghc/libraries/unix/dist-install/build/libHSuni x-2.7.2.2_p.a", O_RDONLY) = 14 [pid 1355283] mmap(NULL, 57344, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6a67d52000 ... ``` ``` $ uname -a Darwin watashis-iMac.local 18.0.0 Darwin Kernel Version 18.0.0: Wed Aug 22 20:13:40 PDT 2018; root:xnu-4903.201.2~1/RELEASE_X86_64 x86_64 $ mv /Users/watashi/gao/ghc/libraries/integer-gmp/dist-install/build/HSintege r-gmp-1.0.2.0.o{,._DISABLE_GHC_ISSUE_15105} $ inplace/bin/ghc-stage2 --interactive +RTS -xp GHCi, version 8.7.20181003: http://www.haskell.org/ghc/ :? for help Prelude> System.Posix.Process.getProcessID 42791 Prelude> Data.Set.fromList [1 .. 10] fromList [1,2,3,4,5,6,7,8,9,10] Prelude> Leaving GHCi. $ inplace/bin/ghc-stage2 --interactive -prof -fexternal-interpreter GHCi, version 8.7.20181003: http://www.haskell.org/ghc/ :? for help Prelude> System.Posix.Process.getProcessID 42806 Prelude> Data.Set.fromList [1 .. 10] fromList [1,2,3,4,5,6,7,8,9,10] Prelude> Leaving GHCi. ``` Also test with something that used to hit the 2Gb limit and it loads and runs without problem. Reviewers: simonmar, bgamari, angerman, Phyx, hvr, erikd Reviewed By: simonmar Subscribers: rwbarton, carter Differential Revision: https://phabricator.haskell.org/D5195 (cherry picked from commit 104599f3f157613589e78627c915e4dc20ee54b4) (cherry picked from commit 16c16740a56f587d56f15be9ea07e7bfdb11b102)
-rw-r--r--docs/users_guide/runtime_control.rst28
-rw-r--r--includes/rts/Flags.h12
-rw-r--r--libraries/base/GHC/RTS/Flags.hsc3
-rw-r--r--rts/Linker.c33
-rw-r--r--rts/RtsFlags.c11
-rw-r--r--rts/linker/Elf.c25
-rw-r--r--rts/linker/MachO.c21
-rw-r--r--rts/linker/SymbolExtras.c61
8 files changed, 121 insertions, 73 deletions
diff --git a/docs/users_guide/runtime_control.rst b/docs/users_guide/runtime_control.rst
index a5c2f1474f..0048a51837 100644
--- a/docs/users_guide/runtime_control.rst
+++ b/docs/users_guide/runtime_control.rst
@@ -241,6 +241,28 @@ Miscellaneous RTS options
crashes if exception handling are enabled. In order to get more information
in compiled executables, C code or DLLs symbols need to be available.
+
+.. rts-flag:: -xp
+
+ On 64-bit machines, the runtime linker usually needs to map object code
+ into the low 2Gb of the address space, due to the x86_64 small memory model
+ where most symbol references are 32 bits. The problem is that this 2Gb of
+ address space can fill up, especially if you're loading a very large number
+ of object files into GHCi.
+
+ This flag offers a workaround, albeit a slightly convoluted one. To be able
+ to load an object file outside of the low 2Gb, the object code needs to be
+ compiled with ``-fPIC -fexternal-dynamic-refs``. When the ``+RTS -xp`` flag
+ is passed, the linker will assume that all object files were compiled with
+ ``-fPIC -fexternal-dynamic-refs`` and load them anywhere in the address
+ space. It's up to you to arrange that the object files you load (including
+ all packages) were compiled in the right way. If this is not the case for
+ an object, the linker will probably fail with an error message when the
+ problem is detected.
+
+ On some platforms where PIC is always the case, e.g. x86_64 MacOS X, this
+ flag is enabled by default.
+
.. rts-flag:: -xm ⟨address⟩
.. index::
@@ -250,8 +272,10 @@ Miscellaneous RTS options
This option is for working around memory allocation
problems only. Do not use unless GHCi fails with a message like
- “\ ``failed to mmap() memory below 2Gb``\ ”. If you need to use this
- option to get GHCi working on your machine, please file a bug.
+ “\ ``failed to mmap() memory below 2Gb``\ ”. Consider recompiling
+ the objects with ``-fPIC -fexternal-dynamic-refs`` and using the
+ ``-xp`` flag instead. If you need to use this option to get GHCi
+ working on your machine, please file a bug.
On 64-bit machines, the RTS needs to allocate memory in the low 2Gb
of the address space. Support for this across different operating
diff --git a/includes/rts/Flags.h b/includes/rts/Flags.h
index 63450d5ece..3582e6abde 100644
--- a/includes/rts/Flags.h
+++ b/includes/rts/Flags.h
@@ -188,6 +188,17 @@ typedef struct _CONCURRENT_FLAGS {
*/
#define DEFAULT_TICK_INTERVAL USToTime(10000)
+/*
+ * When linkerAlwaysPic is true, the runtime linker assume that all object
+ * files were compiled with -fPIC -fexternal-dynamic-refs and load them
+ * anywhere in the address space.
+ */
+#if defined(x86_64_HOST_ARCH) && defined(darwin_HOST_OS)
+#define DEFAULT_LINKER_ALWAYS_PIC true
+#else
+#define DEFAULT_LINKER_ALWAYS_PIC false
+#endif
+
/* See Note [Synchronization of flags and base APIs] */
typedef struct _MISC_FLAGS {
Time tickInterval; /* units: TIME_RESOLUTION */
@@ -197,6 +208,7 @@ typedef struct _MISC_FLAGS {
bool generate_stack_trace;
bool machineReadable;
bool internalCounters; /* See Note [Internal Counter Stats] */
+ bool linkerAlwaysPic; /* Assume the object code is always PIC */
StgWord linkerMemBase; /* address to ask the OS for memory
* for the linker, NULL ==> off */
} MISC_FLAGS;
diff --git a/libraries/base/GHC/RTS/Flags.hsc b/libraries/base/GHC/RTS/Flags.hsc
index 12cb828e6a..249bcd5a98 100644
--- a/libraries/base/GHC/RTS/Flags.hsc
+++ b/libraries/base/GHC/RTS/Flags.hsc
@@ -139,6 +139,7 @@ data MiscFlags = MiscFlags
, generateStackTrace :: Bool
, machineReadable :: Bool
, internalCounters :: Bool
+ , linkerAlwaysPic :: Bool
, linkerMemBase :: Word
-- ^ address to ask the OS for memory for the linker, 0 ==> off
} deriving ( Show -- ^ @since 4.8.0.0
@@ -444,6 +445,8 @@ getMiscFlags = do
(#{peek MISC_FLAGS, machineReadable} ptr :: IO CBool))
<*> (toBool <$>
(#{peek MISC_FLAGS, internalCounters} ptr :: IO CBool))
+ <*> (toBool <$>
+ (#{peek MISC_FLAGS, linkerAlwaysPic} ptr :: IO CBool))
<*> #{peek MISC_FLAGS, linkerMemBase} ptr
getDebugFlags :: IO DebugFlags
diff --git a/rts/Linker.c b/rts/Linker.c
index 62959b6707..b9ec12935e 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -73,10 +73,6 @@
# include <mach-o/fat.h>
#endif
-#if defined(x86_64_HOST_ARCH) && defined(darwin_HOST_OS)
-#define ALWAYS_PIC
-#endif
-
#if defined(dragonfly_HOST_OS)
#include <sys/tls.h>
#endif
@@ -224,9 +220,7 @@ int ocTryLoad( ObjectCode* oc );
* We pick a default address based on the OS, but also make this
* configurable via an RTS flag (+RTS -xm)
*/
-#if !defined(ALWAYS_PIC) && defined(x86_64_HOST_ARCH)
-
-#if defined(MAP_32BIT)
+#if defined(MAP_32BIT) || DEFAULT_LINKER_ALWAYS_PIC
// Try to use MAP_32BIT
#define MMAP_32BIT_BASE_DEFAULT 0
#else
@@ -235,7 +229,6 @@ int ocTryLoad( ObjectCode* oc );
#endif
static void *mmap_32bit_base = (void *)MMAP_32BIT_BASE_DEFAULT;
-#endif
static void ghciRemoveSymbolTable(HashTable *table, const SymbolName* key,
ObjectCode *owner)
@@ -511,12 +504,10 @@ initLinker_ (int retain_cafs)
}
# endif
-#if !defined(ALWAYS_PIC) && defined(x86_64_HOST_ARCH)
if (RtsFlags.MiscFlags.linkerMemBase != 0) {
// User-override for mmap_32bit_base
mmap_32bit_base = (void*)RtsFlags.MiscFlags.linkerMemBase;
}
-#endif
if (RTS_LINKER_USE_MMAP)
m32_allocator_init();
@@ -1026,29 +1017,30 @@ mmapForLinker (size_t bytes, uint32_t flags, int fd, int offset)
void *map_addr = NULL;
void *result;
size_t size;
+ uint32_t tryMap32Bit = RtsFlags.MiscFlags.linkerAlwaysPic
+ ? 0
+ : TRY_MAP_32BIT;
static uint32_t fixed = 0;
IF_DEBUG(linker, debugBelch("mmapForLinker: start\n"));
size = roundUpToPage(bytes);
-#if !defined(ALWAYS_PIC) && defined(x86_64_HOST_ARCH)
mmap_again:
if (mmap_32bit_base != 0) {
map_addr = mmap_32bit_base;
}
-#endif
IF_DEBUG(linker,
debugBelch("mmapForLinker: \tprotection %#0x\n",
PROT_EXEC | PROT_READ | PROT_WRITE));
IF_DEBUG(linker,
debugBelch("mmapForLinker: \tflags %#0x\n",
- MAP_PRIVATE | TRY_MAP_32BIT | fixed | flags));
+ MAP_PRIVATE | tryMap32Bit | fixed | flags));
result = mmap(map_addr, size,
PROT_EXEC|PROT_READ|PROT_WRITE,
- MAP_PRIVATE|TRY_MAP_32BIT|fixed|flags, fd, offset);
+ MAP_PRIVATE|tryMap32Bit|fixed|flags, fd, offset);
if (result == MAP_FAILED) {
sysErrorBelch("mmap %" FMT_Word " bytes at %p",(W_)size,map_addr);
@@ -1056,8 +1048,9 @@ mmap_again:
return NULL;
}
-#if !defined(ALWAYS_PIC) && defined(x86_64_HOST_ARCH)
- if (mmap_32bit_base != 0) {
+#if defined(x86_64_HOST_ARCH)
+ if (RtsFlags.MiscFlags.linkerAlwaysPic) {
+ } else if (mmap_32bit_base != 0) {
if (result == map_addr) {
mmap_32bit_base = (StgWord8*)map_addr + size;
} else {
@@ -1231,10 +1224,10 @@ void freeObjectCode (ObjectCode *oc)
#if defined(NEED_SYMBOL_EXTRAS) && (!defined(x86_64_HOST_ARCH) \
|| !defined(mingw32_HOST_OS))
if (RTS_LINKER_USE_MMAP) {
- if (!USE_CONTIGUOUS_MMAP && oc->symbol_extras != NULL) {
- m32_free(oc->symbol_extras,
- sizeof(SymbolExtra) * oc->n_symbol_extras);
- }
+ if (!USE_CONTIGUOUS_MMAP && !RtsFlags.MiscFlags.linkerAlwaysPic &&
+ oc->symbol_extras != NULL) {
+ m32_free(oc->symbol_extras, sizeof(SymbolExtra) * oc->n_symbol_extras);
+ }
}
else {
stgFree(oc->symbol_extras);
diff --git a/rts/RtsFlags.c b/rts/RtsFlags.c
index ff9635ab24..37eafa5c55 100644
--- a/rts/RtsFlags.c
+++ b/rts/RtsFlags.c
@@ -236,6 +236,7 @@ void initRtsFlagsDefaults(void)
RtsFlags.MiscFlags.generate_dump_file = false;
RtsFlags.MiscFlags.machineReadable = false;
RtsFlags.MiscFlags.internalCounters = false;
+ RtsFlags.MiscFlags.linkerAlwaysPic = DEFAULT_LINKER_ALWAYS_PIC;
RtsFlags.MiscFlags.linkerMemBase = 0;
#if defined(THREADED_RTS)
@@ -457,6 +458,11 @@ usage_text[] = {
" -e<n> Maximum number of outstanding local sparks (default: 4096)",
#endif
#if defined(x86_64_HOST_ARCH)
+#if !DEFAULT_LINKER_ALWAYS_PIC
+" -xp Assume that all object files were compiled with -fPIC",
+" -fexternal-dynamic-refs and load them anywhere in the address",
+" space",
+#endif
" -xm Base address to mmap memory in the GHCi linker",
" (hex; must be <80000000)",
#endif
@@ -1502,6 +1508,11 @@ error = true;
break;
#if defined(x86_64_HOST_ARCH)
+ case 'p': /* linkerAlwaysPic */
+ OPTION_UNSAFE;
+ RtsFlags.MiscFlags.linkerAlwaysPic = true;
+ break;
+
case 'm': /* linkerMemBase */
OPTION_UNSAFE;
if (rts_argv[arg][3] != '\0') {
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index e86e49d2a9..a70b3ae5bc 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -169,6 +169,8 @@ get_shndx_table(Elf_Ehdr* ehdr)
void
ocInit_ELF(ObjectCode * oc)
{
+ ocDeinit_ELF(oc);
+
oc->info = (struct ObjectCodeFormatInfo*)stgCallocBytes(
1, sizeof *oc->info,
"ocInit_Elf(ObjectCodeFormatInfo)");
@@ -318,6 +320,7 @@ ocDeinit_ELF(ObjectCode * oc)
}
stgFree(oc->info);
+ oc->info = NULL;
}
}
@@ -750,7 +753,7 @@ ocGetNames_ELF ( ObjectCode* oc )
start = mem;
mapped_start = mem;
#else
- if (USE_CONTIGUOUS_MMAP) {
+ if (USE_CONTIGUOUS_MMAP || RtsFlags.MiscFlags.linkerAlwaysPic) {
// already mapped.
start = oc->image + offset;
alloc = SECTION_NOMEM;
@@ -1613,9 +1616,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
case COMPAT_R_X86_64_PC32:
{
-#if defined(ALWAYS_PIC)
- barf("R_X86_64_PC32 relocation, but ALWAYS_PIC.");
-#else
StgInt64 off = value - P;
if (off != (Elf64_Sword)off && X86_64_ELF_NONPIC_HACK) {
StgInt64 pltAddress =
@@ -1632,7 +1632,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
Elf64_Sword payload = off;
memcpy((void*)P, &payload, sizeof(payload));
-#endif
break;
}
@@ -1645,9 +1644,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
case COMPAT_R_X86_64_32:
{
-#if defined(ALWAYS_PIC)
- barf("R_X86_64_32 relocation, but ALWAYS_PIC.");
-#else
if (value != (Elf64_Word)value && X86_64_ELF_NONPIC_HACK) {
StgInt64 pltAddress =
(StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S)
@@ -1663,15 +1659,11 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
Elf64_Word payload = value;
memcpy((void*)P, &payload, sizeof(payload));
-#endif
break;
}
case COMPAT_R_X86_64_32S:
{
-#if defined(ALWAYS_PIC)
- barf("R_X86_64_32S relocation, but ALWAYS_PIC.");
-#else
if ((StgInt64)value != (Elf64_Sword)value && X86_64_ELF_NONPIC_HACK) {
StgInt64 pltAddress =
(StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S)
@@ -1687,7 +1679,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
Elf64_Sword payload = value;
memcpy((void*)P, &payload, sizeof(payload));
-#endif
break;
}
case COMPAT_R_X86_64_REX_GOTPCRELX:
@@ -1709,9 +1700,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
#if defined(dragonfly_HOST_OS)
case COMPAT_R_X86_64_GOTTPOFF:
{
-#if defined(ALWAYS_PIC)
- barf("R_X86_64_GOTTPOFF relocation, but ALWAYS_PIC.");
-#else
/* determine the offset of S to the current thread's tls
area
XXX: Move this to the beginning of function */
@@ -1729,16 +1717,12 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
Elf64_SWord payload = off;
memcpy((void*)P, &payload, sizeof(payload));
-#endif
break;
}
#endif
case COMPAT_R_X86_64_PLT32:
{
-#if defined(ALWAYS_PIC)
- barf("R_X86_64_PLT32 relocation, but ALWAYS_PIC.");
-#else
StgInt64 off = value - P;
if (off != (Elf64_Sword)off) {
StgInt64 pltAddress = (StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S)
@@ -1753,7 +1737,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
Elf64_Sword payload = off;
memcpy((void*)P, &payload, sizeof(payload));
-#endif
break;
}
#endif
diff --git a/rts/linker/MachO.c b/rts/linker/MachO.c
index c6a6c28440..4a1204dde9 100644
--- a/rts/linker/MachO.c
+++ b/rts/linker/MachO.c
@@ -99,6 +99,8 @@ bool ocMprotect_MachO( ObjectCode *oc );
void
ocInit_MachO(ObjectCode * oc)
{
+ ocDeinit_MachO(oc);
+
oc->info = (struct ObjectCodeFormatInfo*)stgCallocBytes(
1, sizeof *oc->info,
"ocInit_MachO(ObjectCodeFormatInfo)");
@@ -160,16 +162,19 @@ ocInit_MachO(ObjectCode * oc)
void
ocDeinit_MachO(ObjectCode * oc) {
- if(oc->info->n_macho_symbols > 0) {
- stgFree(oc->info->macho_symbols);
- }
+ if (oc->info != NULL) {
+ if(oc->info->n_macho_symbols > 0) {
+ stgFree(oc->info->macho_symbols);
+ }
#if defined(aarch64_HOST_ARCH)
- freeGot(oc);
- for(int i = 0; i < oc->n_sections; i++) {
- freeStubs(&oc->sections[i]);
- }
+ freeGot(oc);
+ for(int i = 0; i < oc->n_sections; i++) {
+ freeStubs(&oc->sections[i]);
+ }
#endif
- stgFree(oc->info);
+ stgFree(oc->info);
+ oc->info = NULL;
+ }
}
static int
diff --git a/rts/linker/SymbolExtras.c b/rts/linker/SymbolExtras.c
index 88541f44d0..4c40b10877 100644
--- a/rts/linker/SymbolExtras.c
+++ b/rts/linker/SymbolExtras.c
@@ -19,6 +19,12 @@
#include "linker/SymbolExtras.h"
#include "linker/M32Alloc.h"
+#if defined(OBJFORMAT_ELF)
+# include "linker/Elf.h"
+#elif defined(OBJFORMAT_MACHO)
+# include "linker/MachO.h"
+#endif
+
#include <string.h>
#if RTS_LINKER_USE_MMAP
#include <sys/mman.h>
@@ -46,8 +52,24 @@
int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first )
{
size_t n;
+ void* oldImage = oc->image;
+
+ if (count > 0) {
+ if (!RTS_LINKER_USE_MMAP) {
+
+ // round up to the nearest 4
+ int aligned = (oc->fileSize + 3) & ~3;
+ int misalignment = oc->misalignment;
- if (RTS_LINKER_USE_MMAP && USE_CONTIGUOUS_MMAP) {
+ oc->image -= misalignment;
+ oc->image = stgReallocBytes( oc->image,
+ misalignment +
+ aligned + sizeof (SymbolExtra) * count,
+ "ocAllocateSymbolExtras" );
+ oc->image += misalignment;
+
+ oc->symbol_extras = (SymbolExtra *) (oc->image + aligned);
+ } else if (USE_CONTIGUOUS_MMAP || RtsFlags.MiscFlags.linkerAlwaysPic) {
n = roundUpToPage(oc->fileSize);
/* Keep image and symbol_extras contiguous */
@@ -63,42 +85,37 @@ int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first )
oc->imageMapped = true;
oc->fileSize = n + (sizeof(SymbolExtra) * count);
oc->symbol_extras = (SymbolExtra *) (oc->image + n);
- if(mprotect(new, allocated_size, PROT_READ | PROT_EXEC) != 0) {
- sysErrorBelch("unable to protect memory");
+ if (mprotect(new, allocated_size,
+ PROT_READ | PROT_WRITE | PROT_EXEC) != 0) {
+ sysErrorBelch("unable to protect memory");
}
}
else {
oc->symbol_extras = NULL;
return 0;
}
- }
- else if( count > 0 ) {
- if (RTS_LINKER_USE_MMAP) {
- n = roundUpToPage(oc->fileSize);
-
+ } else {
oc->symbol_extras = m32_alloc(sizeof(SymbolExtra) * count, 8);
if (oc->symbol_extras == NULL) return 0;
}
- else {
- // 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 + sizeof (SymbolExtra) * count,
- "ocAllocateSymbolExtras" );
- oc->image += misalignment;
-
- oc->symbol_extras = (SymbolExtra *) (oc->image + aligned);
- }
}
if (oc->symbol_extras != NULL) {
memset( oc->symbol_extras, 0, sizeof (SymbolExtra) * count );
}
+ // ObjectCodeFormatInfo contains computed addresses based on offset to
+ // image, if the address of image changes, we need to invalidate
+ // the ObjectCodeFormatInfo and recompute it.
+ if (oc->image != oldImage) {
+#if defined(OBJFORMAT_MACHO)
+ ocInit_MachO( oc );
+#endif
+#if defined(OBJFORMAT_ELF)
+ ocInit_ELF( oc );
+#endif
+ }
+
oc->first_symbol_extra = first;
oc->n_symbol_extras = count;