diff options
author | Zejun Wu <watashi@fb.com> | 2018-10-15 13:52:36 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2018-10-15 19:24:16 -0400 |
commit | 104599f3f157613589e78627c915e4dc20ee54b4 (patch) | |
tree | e640f6b00972a83a0dda163757cf144acd4ef70d /rts/linker/SymbolExtras.c | |
parent | 165d3d5ddaecc7dbe7f5ac051834a7619463efb0 (diff) | |
download | haskell-104599f3f157613589e78627c915e4dc20ee54b4.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
Diffstat (limited to 'rts/linker/SymbolExtras.c')
-rw-r--r-- | rts/linker/SymbolExtras.c | 61 |
1 files changed, 39 insertions, 22 deletions
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; |