summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
authorArtem Pyanykh <artempyanykh@gmail.com>2019-02-21 12:10:38 +0300
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-03-20 19:52:39 -0400
commit368187591a5454e47c4e08dae90d39d2af1fad40 (patch)
treece6b0c92dc5b0b9b493a33421bbe1f71ae915e6c /rts
parent3394a7cd27cec64a577ee0a9df887a431ccb3696 (diff)
downloadhaskell-368187591a5454e47c4e08dae90d39d2af1fad40.tar.gz
Adjust section placement and relocation logic for Mach-O
1. Place each section on a separate page to ensure required alignment (wastes lots ot space, needs to be improved). 2. Unwire relocation logic from macho sections (the most fiddly part is adjusting internal relocations). Other todos: 0. Add a test for section alignment. 1. Investigate 32bit relocations! 2. Fix memory leak in ZEROPAGE section allocation. 3. Fix creating redundant jump islands for GOT. 4. Investigate more compact section placement.
Diffstat (limited to 'rts')
-rw-r--r--rts/Linker.c10
-rw-r--r--rts/linker/MachO.c329
-rw-r--r--rts/linker/MachO.h17
-rw-r--r--rts/linker/SymbolExtras.c1
4 files changed, 234 insertions, 123 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index b293b6a839..ba78efe7b6 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -1419,6 +1419,8 @@ preloadObjectFile (pathchar *path)
#endif /* RTS_LINKER_USE_MMAP */
+ IF_DEBUG(linker, debugBelch("loadObj: preloaded image at %p\n", (void *) image));
+
oc = mkOc(path, image, fileSize, true, NULL, misalignment);
#if defined(OBJFORMAT_MACHO)
@@ -1440,7 +1442,7 @@ preloadObjectFile (pathchar *path)
static HsInt loadObj_ (pathchar *path)
{
ObjectCode* oc;
- IF_DEBUG(linker, debugBelch("loadObj %" PATH_FMT "\n", path));
+ IF_DEBUG(linker, debugBelch("loadObj: %" PATH_FMT "\n", path));
/* debugBelch("loadObj %s\n", path ); */
@@ -1611,6 +1613,8 @@ int ocTryLoad (ObjectCode* oc) {
// run init/init_array/ctors/mod_init_func
+ IF_DEBUG(linker, debugBelch("ocTryLoad: ocRunInit start\n"));
+
loading_obj = oc; // tells foreignExportStablePtr what to do
#if defined(OBJFORMAT_ELF)
r = ocRunInit_ELF ( oc );
@@ -1814,8 +1818,8 @@ void freeProddableBlocks (ObjectCode *oc)
*/
void
addSection (Section *s, SectionKind kind, SectionAlloc alloc,
- void* start, StgWord size, StgWord mapped_offset,
- void* mapped_start, StgWord mapped_size)
+ void* start, StgWord size,
+ StgWord mapped_offset, void* mapped_start, StgWord mapped_size)
{
s->start = start; /* actual start of section in memory */
s->size = size; /* actual size of section in memory */
diff --git a/rts/linker/MachO.c b/rts/linker/MachO.c
index adcfcc7c40..7ec3cabef7 100644
--- a/rts/linker/MachO.c
+++ b/rts/linker/MachO.c
@@ -2,13 +2,12 @@
#if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
-#if defined(ios_HOST_OS)
-#if !RTS_LINKER_USE_MMAP
+#if defined(ios_HOST_OS) && !RTS_LINKER_USE_MMAP
#error "ios must use mmap and mprotect!"
#endif
+
/* for roundUpToPage */
#include "sm/OSMem.h"
-#endif
#include "RtsUtils.h"
#include "GetEnv.h"
@@ -680,77 +679,44 @@ relocateSectionAarch64(ObjectCode * oc, Section * section)
}
return 1;
}
-#else /* non aarch64_HOST_ARCH branch -- aarch64 doesn't use relocateAddress */
-
-/*
- * Try to find the final loaded address for some addres.
- * Look through all sections, locating the section that
- * contains the address and compute the absolue address.
- */
-static unsigned long
-relocateAddress(
- ObjectCode* oc,
- int nSections,
- MachOSection* sections,
- unsigned long address)
-{
- int i;
- IF_DEBUG(linker, debugBelch("relocateAddress: start\n"));
- for (i = 0; i < nSections; i++)
- {
- IF_DEBUG(linker, debugBelch(" relocating address in section %d\n", i));
- if (sections[i].addr <= address
- && address < sections[i].addr + sections[i].size)
- {
- return (unsigned long)oc->image
- + sections[i].offset + address - sections[i].addr;
- }
- }
- barf("Invalid Mach-O file:"
- "Address out of bounds while relocating object file");
- return 0;
-}
-
#endif /* aarch64_HOST_ARCH */
#if defined(x86_64_HOST_ARCH)
static int
-relocateSection(
- ObjectCode* oc,
- char *image,
- MachOSymtabCommand *symLC, MachONList *nlist,
- int nSections, MachOSection* sections, MachOSection *sect)
+relocateSection(ObjectCode* oc, int curSection)
{
- MachORelocationInfo *relocs;
- int i, n;
+ Section * sect = &oc->sections[curSection];
+ MachOSection * msect = sect->info->macho_section; // for convenience access
+ MachORelocationInfo * relocs = sect->info->relocation_info;
+ MachOSymbol * symbols = oc->info->macho_symbols;
- IF_DEBUG(linker, debugBelch("relocateSection: start\n"));
+ IF_DEBUG(linker, debugBelch("relocateSection %d (%s, %s): start\n",
+ curSection, msect->segname, msect->sectname));
- if(!strcmp(sect->sectname,"__la_symbol_ptr"))
+ if(!strcmp(msect->sectname,"__la_symbol_ptr"))
return 1;
- else if(!strcmp(sect->sectname,"__nl_symbol_ptr"))
+ else if(!strcmp(msect->sectname,"__nl_symbol_ptr"))
return 1;
- else if(!strcmp(sect->sectname,"__la_sym_ptr2"))
+ else if(!strcmp(msect->sectname,"__la_sym_ptr2"))
return 1;
- else if(!strcmp(sect->sectname,"__la_sym_ptr3"))
+ else if(!strcmp(msect->sectname,"__la_sym_ptr3"))
return 1;
- n = sect->nreloc;
- IF_DEBUG(linker, debugBelch("relocateSection: number of relocations: %d\n", n));
+ IF_DEBUG(linker, debugBelch("relocateSection: number of relocations: %d\n", msect->nreloc));
- relocs = (MachORelocationInfo*) (image + sect->reloff);
-
- for(i = 0; i < n; i++)
+ for(uint32_t i = 0; i < msect->nreloc; i++)
{
MachORelocationInfo *reloc = &relocs[i];
- char *thingPtr = image + sect->offset + reloc->r_address;
+ char *thingPtr = (char *) sect->start + reloc->r_address;
uint64_t thing;
/* We shouldn't need to initialise this, but gcc on OS X 64 bit
complains that it may be used uninitialized if we don't */
uint64_t value = 0;
uint64_t baseValue;
int type = reloc->r_type;
+ int relocLenBytes;
+ int nextInstrAdj = 0;
IF_DEBUG(linker, debugBelch("relocateSection: relocation %d\n", i));
IF_DEBUG(linker, debugBelch(" : type = %d\n", reloc->r_type));
@@ -766,27 +732,47 @@ relocateSection(
case 0:
checkProddableBlock(oc,thingPtr,1);
thing = *(uint8_t*)thingPtr;
- baseValue = (uint64_t)thingPtr + 1;
+ relocLenBytes = 1;
break;
case 1:
checkProddableBlock(oc,thingPtr,2);
thing = *(uint16_t*)thingPtr;
- baseValue = (uint64_t)thingPtr + 2;
+ relocLenBytes = 2;
break;
case 2:
checkProddableBlock(oc,thingPtr,4);
thing = *(uint32_t*)thingPtr;
- baseValue = (uint64_t)thingPtr + 4;
+ relocLenBytes = 4;
break;
case 3:
checkProddableBlock(oc,thingPtr,8);
thing = *(uint64_t*)thingPtr;
- baseValue = (uint64_t)thingPtr + 8;
+ relocLenBytes = 8;
break;
default:
barf("Unknown size.");
}
+ /*
+ * With SIGNED_N the relocation is not at the
+ * end of instruction and baseValue needs to be
+ * adjusted accordingly.
+ */
+ switch (type) {
+ case X86_64_RELOC_SIGNED_1:
+ nextInstrAdj = 1;
+ break;
+ case X86_64_RELOC_SIGNED_2:
+ nextInstrAdj = 2;
+ break;
+ case X86_64_RELOC_SIGNED_4:
+ nextInstrAdj = 4;
+ break;
+ }
+ baseValue = (uint64_t)thingPtr + relocLenBytes + nextInstrAdj;
+
+
+
IF_DEBUG(linker,
debugBelch("relocateSection: length = %d, thing = %" PRId64 ", baseValue = %p\n",
reloc->r_length, thing, (char *)baseValue));
@@ -794,18 +780,19 @@ relocateSection(
if (type == X86_64_RELOC_GOT
|| type == X86_64_RELOC_GOT_LOAD)
{
- MachONList *symbol = &nlist[reloc->r_symbolnum];
- SymbolName* nm = image + symLC->stroff + symbol->n_un.n_strx;
+ MachOSymbol *symbol = &symbols[reloc->r_symbolnum];
+ SymbolName* nm = symbol->name;
SymbolAddr* addr = NULL;
- IF_DEBUG(linker, debugBelch("relocateSection: making jump island for %s, extern = %d, X86_64_RELOC_GOT\n", nm, reloc->r_extern));
+ IF_DEBUG(linker, debugBelch("relocateSection: making jump island for %s, extern = %d, X86_64_RELOC_GOT\n",
+ nm, reloc->r_extern));
- ASSERT(reloc->r_extern);
+ ASSERT(reloc->r_extern); // fixme: redundant?
if (reloc->r_extern == 0) {
errorBelch("\nrelocateSection: global offset table relocation for symbol with r_extern == 0\n");
}
- if (symbol->n_type & N_EXT) {
+ if (symbol->nlist->n_type & N_EXT) {
// The external bit is set, meaning the symbol is exported,
// and therefore can be looked up in this object module's
// symtab, or it is undefined, meaning dlsym must be used
@@ -829,38 +816,41 @@ relocateSection(
// at the location given by the section index and
// symbol address (symbol->n_value)
- if ((symbol->n_type & N_TYPE) == N_SECT) {
- addr = (void *)relocateAddress(oc, nSections, sections, symbol->n_value);
- IF_DEBUG(linker, debugBelch("relocateSection: calculated relocation %p of "
- "non-external X86_64_RELOC_GOT or X86_64_RELOC_GOT_LOAD\n",
- (void *)symbol->n_value));
- IF_DEBUG(linker, debugBelch(" : addr = %p\n", addr));
+ if ((symbol->nlist->n_type & N_TYPE) == N_SECT) {
+ ASSERT(symbol->addr != NULL);
+ addr = symbol->addr;
+ IF_DEBUG(linker, debugBelch("relocateSection: calculated relocation of "
+ "non-external X86_64_RELOC_GOT or X86_64_RELOC_GOT_LOAD\n"));
+ IF_DEBUG(linker, debugBelch(" : addr = %p\n", addr));
} else {
- errorBelch("\nrelocateSection: %s is not exported,"
- " and should be defined in a section, but isn't!\n", nm);
+ errorBelch("\nrelocateSection: %s is not exported,"
+ " and should be defined in a section, but isn't!\n", nm);
}
}
+ // creates a jump island for every relocation entry for a symbol
+ // fixme: use got_addr to store the loc. of a jump island for a symbol
value = (uint64_t) &makeSymbolExtra(oc, reloc->r_symbolnum, (unsigned long)addr)->addr;
type = X86_64_RELOC_SIGNED;
}
else if (reloc->r_extern)
{
- MachONList *symbol = &nlist[reloc->r_symbolnum];
- SymbolName* nm = image + symLC->stroff + symbol->n_un.n_strx;
+ MachOSymbol *symbol = &symbols[reloc->r_symbolnum];
+ SymbolName* nm = symbol->name;
SymbolAddr* addr = NULL;
IF_DEBUG(linker, debugBelch("relocateSection: looking up external symbol %s\n", nm));
- IF_DEBUG(linker, debugBelch(" : type = %d\n", symbol->n_type));
- IF_DEBUG(linker, debugBelch(" : sect = %d\n", symbol->n_sect));
- IF_DEBUG(linker, debugBelch(" : desc = %d\n", symbol->n_desc));
- IF_DEBUG(linker, debugBelch(" : value = %p\n", (void *)symbol->n_value));
-
- if ((symbol->n_type & N_TYPE) == N_SECT) {
- value = relocateAddress(oc, nSections, sections,
- symbol->n_value);
- IF_DEBUG(linker, debugBelch("relocateSection, defined external symbol %s, relocated address %p\n", nm, (void *)value));
+ IF_DEBUG(linker, debugBelch(" : type = %d\n", symbol->nlist->n_type));
+ IF_DEBUG(linker, debugBelch(" : sect = %d\n", symbol->nlist->n_sect));
+ IF_DEBUG(linker, debugBelch(" : desc = %d\n", symbol->nlist->n_desc));
+ IF_DEBUG(linker, debugBelch(" : value = %p\n", (void *)symbol->nlist->n_value));
+
+ if ((symbol->nlist->n_type & N_TYPE) == N_SECT) {
+ ASSERT(symbol->addr != NULL);
+ value = (uint64_t) symbol->addr;
+ IF_DEBUG(linker, debugBelch("relocateSection, defined external symbol %s, relocated address %p\n",
+ nm, (void *)value));
}
else {
addr = lookupSymbol_(nm);
@@ -877,15 +867,83 @@ relocateSection(
}
else
{
- // If the relocation is not through the global offset table
- // or external, then set the value to the baseValue. This
- // will leave displacements into the __const section
- // unchanged (as they ought to be).
+ /* Since the relocation is internal, r_symbolnum contains a section
+ * number relative to which the relocation is. Depending on whether
+ * the relocation is unsigned or signed, the given displacement is
+ * relative to the image or the section respectively.
+ *
+ * For instance, in a signed case:
+ * thing = <displ. to to section r_symbolnum *in the image*> (1)
+ * + <offset within r_symbolnum section>
+ * (1) needs to be updated due to different section layout in memory.
+ */
- value = baseValue;
+ CHECKM(reloc->r_symbolnum > 0,
+ "relocateSection: unsupported r_symbolnum = %" PRIu32 " < 1 for internal relocation",
+ reloc->r_symbolnum);
+
+ int targetSecNum = reloc->r_symbolnum - 1; // sec numbers start with 1
+ Section * targetSec = &oc->sections[targetSecNum];
+ MachOSection * targetMacho = targetSec->info->macho_section;
+
+ IF_DEBUG(linker,
+ debugBelch("relocateSection: internal relocation relative to section %d (%s, %s)\n",
+ targetSecNum, targetMacho->segname, targetMacho->sectname));
+
+ switch (type) {
+ case X86_64_RELOC_UNSIGNED: {
+ CHECKM(thing >= targetMacho->addr,
+ "relocateSection: unsigned displacement %" PRIx64 "before target section start address %" PRIx64 "\n",
+ thing, (uint64_t) targetMacho->addr);
+
+ uint64_t thingRelativeOffset = thing - targetMacho->addr;
+ IF_DEBUG(linker, debugBelch(" "
+ "unsigned displacement %" PRIx64 " with section relative offset %" PRIx64 "\n",
+ thing, thingRelativeOffset));
+
+ thing = (uint64_t) targetSec->start + thingRelativeOffset;
+ IF_DEBUG(linker, debugBelch(" "
+ "relocated address is %p\n", (void *) thing));
+
+ /* Compared to external relocation we don't need to adjust value
+ * any further since thing already has absolute address.
+ */
+ value = 0;
+ break;
+ }
+ case X86_64_RELOC_SIGNED:
+ case X86_64_RELOC_SIGNED_1:
+ case X86_64_RELOC_SIGNED_2:
+ case X86_64_RELOC_SIGNED_4: {
+ uint32_t baseValueOffset = reloc->r_address + relocLenBytes + nextInstrAdj;
+ uint64_t imThingLoc = msect->addr + baseValueOffset + (int64_t) thing;
+
+ CHECKM(imThingLoc >= targetMacho->addr,
+ "relocateSection: target location %p in image before target section start address %p\n",
+ (void *) imThingLoc, (void *) targetMacho->addr);
+
+ int64_t thingRelativeOffset = imThingLoc - targetMacho->addr;
+ IF_DEBUG(linker,
+ debugBelch(" "
+ "original displacement %" PRId64 " to %p with section relative offset %" PRIu64 "\n",
+ thing, (void *) imThingLoc, thingRelativeOffset));
+
+ thing = (int64_t) ((uint64_t) targetSec->start + thingRelativeOffset)
+ - ((uint64_t) sect->start + baseValueOffset);
+ value = baseValue; // so that it further cancels out with baseValue
+ IF_DEBUG(linker,
+ debugBelch(" "
+ "relocated displacement %" PRId64 " to %p\n",
+ (int64_t) thing, (void *) (baseValue + thing)));
+ break;
+ }
+ default:
+ barf("relocateSection: unexpected internal relocation type %d\n", type);
+ return 0;
+ }
}
- IF_DEBUG(linker, debugBelch("relocateSection: value = %p\n", (void *)value));
+ IF_DEBUG(linker, debugBelch("relocateSection: value = %p\n", (void *) value));
if (type == X86_64_RELOC_BRANCH)
{
@@ -920,6 +978,8 @@ relocateSection(
barf("unknown relocation");
}
+ IF_DEBUG(linker, debugBelch("relocateSection: thing = %p\n", (void *) thing));
+
switch(reloc->r_length)
{
case 0:
@@ -961,6 +1021,20 @@ relocateSection(
* addressability for relative or absolute access.
*/
+size_t ocGetRequiredSpace_MachO(ObjectCode* oc)
+{
+ size_t bytesNeeded = 0;
+ size_t sectionSize;
+
+ for(int i = 0; i < oc->n_sections; i++)
+ {
+ sectionSize = oc->info->macho_sections[i].size;
+ bytesNeeded += roundUpToPage(sectionSize);
+ }
+
+ return bytesNeeded;
+}
+
int
ocGetNames_MachO(ObjectCode* oc)
{
@@ -982,6 +1056,19 @@ ocGetNames_MachO(ObjectCode* oc)
IF_DEBUG(linker, debugBelch("ocGetNames_MachO: will load %d sections\n",
oc->n_sections));
+
+#if defined(darwin_HOST_OS)
+ size_t requiredSize = ocGetRequiredSpace_MachO(oc);
+ IF_DEBUG(linker, debugBelch("ocGetNames_MachO: required mmaped space is %zu\n",
+ requiredSize));
+
+ void* memStart = mmapForLinker(requiredSize, MAP_ANONYMOUS, -1, 0);
+ if (memStart == NULL) {
+ barf("ocGetNames_MachO: failed to mmap");
+ }
+ void* memCur = memStart;
+#endif // darwin_HOST_OS
+
for(int i=0; i < oc->n_sections; i++)
{
MachOSection * section = &oc->info->macho_sections[i];
@@ -1105,9 +1192,10 @@ ocGetNames_MachO(ObjectCode* oc)
zeroFillArea = stgCallocBytes(1,section->size,
"ocGetNames_MachO(common symbols)");
}
- section->offset = zeroFillArea - oc->image;
+ section->offset = zeroFillArea - oc->image; // fixme: fails down the road
+ // when zFA < oc->image since offset is unsigned
- addSection(&secArray[i], kind, SECTION_NOMEM,
+ addSection(&secArray[i], kind, SECTION_NOMEM, // fixme: why NOMEM?
(void *)(oc->image + section->offset),
section->size,
0, 0, 0);
@@ -1124,18 +1212,23 @@ ocGetNames_MachO(ObjectCode* oc)
secArray[i].info->macho_section = section;
secArray[i].info->relocation_info
= (MachORelocationInfo*)(oc->image + section->reloff);
- FALLTHROUGH;
+ break;
}
default: {
- // just set the pointer to the loaded image.
- addSection(&secArray[i], kind, SECTION_NOMEM,
- (void *)(oc->image + section->offset),
- section->size,
- 0, 0, 0);
+ size_t sectionRoundedSize = roundUpToPage(section->size);
- addProddableBlock(oc,
- (void *) (oc->image + section->offset),
- section->size);
+ IF_DEBUG(linker, debugBelch("ocGetNames_MachO: copying from %p to %p a block of %" PRIu64 " bytes\n",
+ (void *) (oc->image + section->offset), memCur, section->size));
+ memcpy(memCur, oc->image + section->offset, section->size);
+ IF_DEBUG(linker, debugBelch("ocGetNames_MachO: copied %" PRIu64 " bytes\n",
+ section->size));
+
+ addSection(&secArray[i], kind, SECTION_MMAP,
+ memCur, section->size,
+ 0, memCur, sectionRoundedSize);
+ addProddableBlock(oc, memCur, section->size);
+
+ memCur = (char*) memCur + sectionRoundedSize;
secArray[i].info->nstubs = 0;
secArray[i].info->stub_offset = NULL;
@@ -1156,17 +1249,25 @@ ocGetNames_MachO(ObjectCode* oc)
for(size_t i=0; i < oc->info->n_macho_symbols; i++) {
MachOSymbol * s = &oc->info->macho_symbols[i];
if( N_SECT == (s->nlist->n_type & N_TYPE) ) {
- /* section is given */
+ if( NO_SECT == s->nlist->n_sect )
+ barf("Symbol with N_SECT type, but no section.");
+
+ /* section is given, and n_sect is >0 */
uint8_t n = s->nlist->n_sect - 1;
if(0 == oc->info->macho_sections[n].size) {
continue;
}
- if(s->nlist->n_sect == NO_SECT)
- barf("Symbol with N_SECT type, but no section.");
- /* addr <- offset in memory where this section resides
- * - address rel. to the image where this section is stored
- * + symbol offset in the image
+ /* addr <- address in memory where the relocated section resides | (a)
+ * - section's address in the image | (b)
+ * + symbol's address in the image | (c)
+ * (c) - (b) gives symbol's offset relative to section start
+ * (a) - (b) + (c) gives symbol's address for the relocated section
+ *
+ * (c) and (b) are not _real_ addresses and not equal
+ * to file offsets in the image.
+ * Rather they are (virtual) aligned addresses within
+ * a single segment of MH_OBJECT object file.
*/
s->addr = (uint8_t*)oc->sections[n].start
- oc->info->macho_sections[n].addr
@@ -1209,13 +1310,13 @@ ocGetNames_MachO(ObjectCode* oc)
if (oc->info->symCmd) {
for (size_t i = 0; i < oc->info->n_macho_symbols; i++) {
SymbolName* nm = oc->info->macho_symbols[i].name;
- if(oc->info->nlist[i].n_type & N_STAB)
+ if (oc->info->nlist[i].n_type & N_STAB)
{
IF_DEBUG(linker, debugBelch("ocGetNames_MachO: Skip STAB: %s\n", nm));
}
- else if((oc->info->nlist[i].n_type & N_TYPE) == N_SECT)
+ else if ((oc->info->nlist[i].n_type & N_TYPE) == N_SECT)
{
- if(oc->info->nlist[i].n_type & N_EXT)
+ if (oc->info->nlist[i].n_type & N_EXT)
{
if ( (oc->info->nlist[i].n_desc & N_WEAK_DEF)
&& lookupSymbol_(nm)) {
@@ -1405,9 +1506,7 @@ ocResolve_MachO(ObjectCode* oc)
if (!relocateSectionAarch64(oc, &oc->sections[i]))
return 0;
#else
- if (!relocateSection(oc,oc->image,oc->info->symCmd,oc->info->nlist,
- oc->info->segCmd->nsects,oc->info->macho_sections,
- &oc->info->macho_sections[i]))
+ if (!relocateSection(oc, i))
return 0;
#endif
}
@@ -1433,19 +1532,24 @@ ocRunInit_MachO ( ObjectCode *oc )
getProgEnvv(&envc, &envv);
for (int i = 0; i < oc->n_sections; i++) {
+ IF_DEBUG(linker, debugBelch("ocRunInit_MachO: checking section %d\n", i));
+
// ToDo: replace this with a proper check for the S_MOD_INIT_FUNC_POINTERS
// flag. We should do this elsewhere in the Mach-O linker code
// too. Note that the system linker will *refuse* to honor
// sections which don't have this flag, so this could cause
// weird behavior divergence (albeit reproducible).
- if (0 == strcmp(oc->info->macho_sections[i].sectname,
- "__mod_init_func")) {
+ if (0 == strcmp(oc->info->macho_sections[i].sectname, "__mod_init_func")) {
+ IF_DEBUG(linker, debugBelch("ocRunInit_MachO: running mod init functions\n"));
void *init_startC = oc->sections[i].start;
init_t *init = (init_t*)init_startC;
init_t *init_end = (init_t*)((uint8_t*)init_startC
+ oc->sections[i].info->macho_section->size);
- for (; init < init_end; init++) {
+
+ for (int pn = 0; init < init_end; init++, pn++) {
+ IF_DEBUG(linker, debugBelch("ocRunInit_MachO: function pointer %d at %p to %p\n",
+ pn, (void *) init, (void *) *init));
(*init)(argc, argv, envv);
}
}
@@ -1481,6 +1585,7 @@ machoGetMisalignment( FILE * f )
misalignment = (header.sizeofcmds + sizeof(header))
& 0xF;
+ IF_DEBUG(linker, debugBelch("mach-o misalignment %d\n", misalignment));
return misalignment ? (16 - misalignment) : 0;
}
diff --git a/rts/linker/MachO.h b/rts/linker/MachO.h
index 5e00e2a8d2..20cb2d061a 100644
--- a/rts/linker/MachO.h
+++ b/rts/linker/MachO.h
@@ -6,13 +6,14 @@
#include "MachOTypes.h"
-void ocInit_MachO ( ObjectCode* oc );
-void ocDeinit_MachO ( ObjectCode* oc );
-int ocVerifyImage_MachO ( ObjectCode* oc );
-int ocGetNames_MachO ( ObjectCode* oc );
-int ocResolve_MachO ( ObjectCode* oc );
-int ocRunInit_MachO ( ObjectCode* oc );
-int machoGetMisalignment( FILE * );
-int ocAllocateExtras_MachO ( ObjectCode* oc );
+void ocInit_MachO ( ObjectCode* oc );
+void ocDeinit_MachO ( ObjectCode* oc );
+int ocVerifyImage_MachO ( ObjectCode* oc );
+size_t ocGetRequiredSpace_MachO ( ObjectCode* oc);
+int ocGetNames_MachO ( ObjectCode* oc );
+int ocResolve_MachO ( ObjectCode* oc );
+int ocRunInit_MachO ( ObjectCode* oc );
+int machoGetMisalignment ( FILE * );
+int ocAllocateExtras_MachO ( ObjectCode* oc );
#include "EndPrivate.h"
diff --git a/rts/linker/SymbolExtras.c b/rts/linker/SymbolExtras.c
index a9e4c37967..4149522ba0 100644
--- a/rts/linker/SymbolExtras.c
+++ b/rts/linker/SymbolExtras.c
@@ -149,6 +149,7 @@ SymbolExtra* makeSymbolExtra( ObjectCode const* oc,
#endif /* powerpc_HOST_ARCH */
#if defined(x86_64_HOST_ARCH)
// jmp *-14(%rip)
+ // 0xFF 25 is opcode + ModRM of near absolute indirect jump
static uint8_t jmp[] = { 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xFF };
extra->addr = target;
memcpy(extra->jumpIsland, jmp, 6);