diff options
author | Zejun Wu <watashi@fb.com> | 2018-10-15 13:52:36 -0400 |
---|---|---|
committer | Ray Shih <rayshih@fb.com> | 2020-07-14 10:39:34 -0700 |
commit | cb3f710d952c0a2bad539f76c2ab6d07ba894bea (patch) | |
tree | 5f055b2817769d110178237c3b2c6f268d135d48 | |
parent | 2c538aec7125412c4afb18cb93379a79c1c5df15 (diff) | |
download | haskell-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.rst | 28 | ||||
-rw-r--r-- | includes/rts/Flags.h | 12 | ||||
-rw-r--r-- | libraries/base/GHC/RTS/Flags.hsc | 3 | ||||
-rw-r--r-- | rts/Linker.c | 33 | ||||
-rw-r--r-- | rts/RtsFlags.c | 11 | ||||
-rw-r--r-- | rts/linker/Elf.c | 25 | ||||
-rw-r--r-- | rts/linker/MachO.c | 21 | ||||
-rw-r--r-- | rts/linker/SymbolExtras.c | 61 |
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; |