summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
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);