diff options
author | Ben Gamari <bgamari.foss@gmail.com> | 2016-11-02 15:01:15 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2016-11-02 15:42:00 -0400 |
commit | 3f05126253a7d68b37a388c26b586d94e871614e (patch) | |
tree | 16ac13364193992be02b12ddf0068d2343ad91b6 /rts/Linker.c | |
parent | 43c8c1c4a21c3b0a281433394163ba46a124a925 (diff) | |
download | haskell-3f05126253a7d68b37a388c26b586d94e871614e.tar.gz |
linker: Split symbol extras logic into new source file
Test Plan: Validate
Reviewers: erikd, austin, simonmar
Reviewed By: simonmar
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D2646
Diffstat (limited to 'rts/Linker.c')
-rw-r--r-- | rts/Linker.c | 201 |
1 files changed, 1 insertions, 200 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index 74b48225eb..8147ed8552 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -29,6 +29,7 @@ #include "sm/OSMem.h" #include "linker/M32Alloc.h" #include "linker/CacheFlush.h" +#include "linker/SymbolExtras.h" #include "PathUtils.h" #if !defined(mingw32_HOST_OS) @@ -2667,206 +2668,6 @@ addSection (Section *s, SectionKind kind, SectionAlloc alloc, size, kind )); } - -/* -------------------------------------------------------------------------- - * Symbol Extras. - * This is about allocating a small chunk of memory for every symbol in the - * object file. We make sure that the SymboLExtras are always "in range" of - * limited-range PC-relative instructions on various platforms by allocating - * them right next to the object code itself. - */ - -#if NEED_SYMBOL_EXTRAS -#if !defined(x86_64_HOST_ARCH) || !defined(mingw32_HOST_OS) - -/* - ocAllocateSymbolExtras - - Allocate additional space at the end of the object file image to make room - for jump islands (powerpc, x86_64, arm) and GOT entries (x86_64). - - PowerPC relative branch instructions have a 24 bit displacement field. - As PPC code is always 4-byte-aligned, this yields a +-32MB range. - If a particular imported symbol is outside this range, we have to redirect - the jump to a short piece of new code that just loads the 32bit absolute - address and jumps there. - On x86_64, PC-relative jumps and PC-relative accesses to the GOT are limited - to 32 bits (+-2GB). - - This function just allocates space for one SymbolExtra for every - undefined symbol in the object file. The code for the jump islands is - filled in by makeSymbolExtra below. -*/ - -static int ocAllocateSymbolExtras( ObjectCode* oc, int count, int first ) -{ - size_t n; - - if (RTS_LINKER_USE_MMAP && USE_CONTIGUOUS_MMAP) { - n = roundUpToPage(oc->fileSize); - - /* Keep image and symbol_extras contiguous */ - void *new = mmapForLinker(n + (sizeof(SymbolExtra) * count), - MAP_ANONYMOUS, -1, 0); - if (new) { - memcpy(new, oc->image, oc->fileSize); - if (oc->imageMapped) { - munmap(oc->image, n); - } - oc->image = new; - oc->imageMapped = rtsTrue; - oc->fileSize = n + (sizeof(SymbolExtra) * count); - oc->symbol_extras = (SymbolExtra *) (oc->image + n); - } - else { - oc->symbol_extras = NULL; - return 0; - } - } - else if( count > 0 ) { - if (RTS_LINKER_USE_MMAP) { - n = roundUpToPage(oc->fileSize); - - 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 ); - } - - oc->first_symbol_extra = first; - oc->n_symbol_extras = count; - - return 1; -} - -#endif -#endif // NEED_SYMBOL_EXTRAS - -#if defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) -#if !defined(x86_64_HOST_ARCH) || !defined(mingw32_HOST_OS) - -static SymbolExtra* makeSymbolExtra( ObjectCode* oc, - unsigned long symbolNumber, - unsigned long target ) -{ - SymbolExtra *extra; - - ASSERT( symbolNumber >= oc->first_symbol_extra - && symbolNumber - oc->first_symbol_extra < oc->n_symbol_extras); - - extra = &oc->symbol_extras[symbolNumber - oc->first_symbol_extra]; - -#ifdef powerpc_HOST_ARCH - // lis r12, hi16(target) - extra->jumpIsland.lis_r12 = 0x3d80; - extra->jumpIsland.hi_addr = target >> 16; - - // ori r12, r12, lo16(target) - extra->jumpIsland.ori_r12_r12 = 0x618c; - extra->jumpIsland.lo_addr = target & 0xffff; - - // mtctr r12 - extra->jumpIsland.mtctr_r12 = 0x7d8903a6; - - // bctr - extra->jumpIsland.bctr = 0x4e800420; -#endif -#ifdef x86_64_HOST_ARCH - // jmp *-14(%rip) - static uint8_t jmp[] = { 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xFF }; - extra->addr = target; - memcpy(extra->jumpIsland, jmp, 6); -#endif - - return extra; -} - -#endif -#endif // defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) - -#ifdef arm_HOST_ARCH -static SymbolExtra* makeArmSymbolExtra( ObjectCode* oc, - unsigned long symbolNumber, - unsigned long target, - int fromThumb, - int toThumb ) -{ - SymbolExtra *extra; - - ASSERT( symbolNumber >= oc->first_symbol_extra - && symbolNumber - oc->first_symbol_extra < oc->n_symbol_extras); - - extra = &oc->symbol_extras[symbolNumber - oc->first_symbol_extra]; - - // Make sure instruction mode bit is set properly - if (toThumb) - target |= 1; - else - target &= ~1; - - if (!fromThumb) { - // In ARM encoding: - // movw r12, #0 - // movt r12, #0 - // bx r12 - uint32_t code[] = { 0xe300c000, 0xe340c000, 0xe12fff1c }; - - // Patch lower half-word into movw - code[0] |= ((target>>12) & 0xf) << 16; - code[0] |= target & 0xfff; - // Patch upper half-word into movt - target >>= 16; - code[1] |= ((target>>12) & 0xf) << 16; - code[1] |= target & 0xfff; - - memcpy(extra->jumpIsland, code, 12); - - } else { - // In Thumb encoding: - // movw r12, #0 - // movt r12, #0 - // bx r12 - uint16_t code[] = { 0xf240, 0x0c00, - 0xf2c0, 0x0c00, - 0x4760 }; - - // Patch lower half-word into movw - code[0] |= (target>>12) & 0xf; - code[0] |= ((target>>11) & 0x1) << 10; - code[1] |= ((target>>8) & 0x7) << 12; - code[1] |= target & 0xff; - // Patch upper half-word into movt - target >>= 16; - code[2] |= (target>>12) & 0xf; - code[2] |= ((target>>11) & 0x1) << 10; - code[3] |= ((target>>8) & 0x7) << 12; - code[3] |= target & 0xff; - - memcpy(extra->jumpIsland, code, 10); - } - - return extra; -} -#endif // arm_HOST_ARCH - - /* -------------------------------------------------------------------------- * PEi386(+) specifics (Win32 targets) * ------------------------------------------------------------------------*/ |