summaryrefslogtreecommitdiff
path: root/rts/Linker.c
diff options
context:
space:
mode:
authorBen Gamari <bgamari.foss@gmail.com>2016-11-02 15:01:15 -0400
committerBen Gamari <ben@smart-cactus.org>2016-11-02 15:42:00 -0400
commit3f05126253a7d68b37a388c26b586d94e871614e (patch)
tree16ac13364193992be02b12ddf0068d2343ad91b6 /rts/Linker.c
parent43c8c1c4a21c3b0a281433394163ba46a124a925 (diff)
downloadhaskell-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.c201
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)
* ------------------------------------------------------------------------*/