[Git][ghc/ghc][wip/angerman/aarch64-ncg] 7 commits: [MachO] cleanup compiler warnings
Moritz Angermann
gitlab at gitlab.haskell.org
Fri Oct 9 10:47:26 UTC 2020
Moritz Angermann pushed to branch wip/angerman/aarch64-ncg at Glasgow Haskell Compiler / GHC
Commits:
00440cdd by Moritz Angermann at 2020-10-08T11:57:15+08:00
[MachO] cleanup compiler warnings
- - - - -
a6d2c4d0 by Moritz Angermann at 2020-10-08T11:57:57+08:00
[macOS/arm64] do not use read_only_relocs on arm64
The linker simply doesn't support it and will complain
loudly.
- - - - -
37a62ae9 by Moritz Angermann at 2020-10-08T11:58:51+08:00
[Storage/Adjustor] Drop size check in allocExec
This is violated by ghci, in InfoTable.hsc we call
_allocateExec with a size that does not guarantee to
be of ffi_closure size.
Other allocateExec implementations do not have this
check either; I highly doubt it's sensible to have
this check in the presence of ghci's allocateExec calls.
- - - - -
2dac1fda by Moritz Angermann at 2020-10-09T18:43:37+08:00
[linker/elf] better errors (with error message)
- - - - -
a40bc126 by Moritz Angermann at 2020-10-09T18:44:09+08:00
[darwin] always pic, ios AND mac AND tv AND ...
- - - - -
05a8a2f5 by Moritz Angermann at 2020-10-09T18:45:08+08:00
[aarch64/codegen] pack ccall arguments on darwin
This is annoying, but the darwinpcs does not match the default aapcs :facepalm:
- - - - -
046365b3 by Moritz Angermann at 2020-10-09T18:47:00+08:00
[linker:MachO] split PLT logic out.
Why was this missing in the first place? It's now a bit more aligned to the
elf plt logic.
- - - - -
15 changed files:
- compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
- compiler/GHC/SysTools.hs
- includes/rts/Flags.h
- rts/Linker.c
- rts/ghc.mk
- rts/linker/Elf.c
- rts/linker/MachO.c
- rts/linker/MachOTypes.h
- + rts/linker/macho/plt.c
- + rts/linker/macho/plt.h
- + rts/linker/macho/plt_aarch64.c
- + rts/linker/macho/plt_aarch64.h
- rts/package.conf.in
- rts/rts.cabal.in
- rts/sm/Storage.c
Changes:
=====================================
compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
=====================================
@@ -1092,7 +1092,16 @@ genCCall target dest_regs arg_regs bid = do
-- this will give us the format information to match on.
arg_regs' <- mapM getSomeReg arg_regs
- (stackArgs, passRegs, passArgumentsCode) <- passArguments allGpArgRegs allFpArgRegs arg_regs' 0 [] nilOL
+ platform <- getPlatform
+ let packStack = platformOS platform == OSDarwin
+
+ (stackSpace', passRegs, passArgumentsCode) <- passArguments packStack allGpArgRegs allFpArgRegs arg_regs' 0 [] nilOL
+
+ -- if we pack the stack, we may need to adjust to multiple of 8byte.
+ -- if we don't pack the stack, it will always be multiple of 8.
+ let stackSpace = if stackSpace' `mod` 8 /= 0
+ then 8 * (stackSpace' `div` 8 + 1)
+ else stackSpace'
(returnRegs, readResultsCode) <- readResults allGpArgRegs allFpArgRegs dest_regs [] nilOL
@@ -1110,11 +1119,11 @@ genCCall target dest_regs arg_regs bid = do
, DELTA 0 ]
let code = call_target_code -- compute the label (possibly into a register)
- `appOL` moveStackDown stackArgs
+ `appOL` moveStackDown (stackSpace `div` 8)
`appOL` passArgumentsCode -- put the arguments into x0, ...
`appOL` (unitOL $ BL call_target passRegs returnRegs) -- branch and link.
`appOL` readResultsCode -- parse the results into registers
- `appOL` moveStackUp stackArgs
+ `appOL` moveStackUp (stackSpace `div` 8)
return (code, Nothing)
-- or a possibly side-effecting machine operation
@@ -1237,17 +1246,17 @@ genCCall target dest_regs arg_regs bid = do
genCCall (ForeignTarget target cconv) dest_regs arg_regs bid
-- XXX: Optimize using paired load LDP
- passArguments :: [Reg] -> [Reg] -> [(Reg, Format, InstrBlock)] -> Int -> [Reg] -> InstrBlock -> NatM (Int, [Reg], InstrBlock)
- passArguments _ _ [] stackArgs accumRegs accumCode = return (stackArgs, accumRegs, accumCode)
- -- passArguments _ _ [] accumCode stackArgs | isEven stackArgs = return $ SUM (OpReg W64 x31) (OpReg W64 x31) OpImm (ImmInt (-8 * stackArgs))
- -- passArguments _ _ [] accumCode stackArgs = return $ SUM (OpReg W64 x31) (OpReg W64 x31) OpImm (ImmInt (-8 * (stackArgs + 1)))
+ passArguments :: Bool -> [Reg] -> [Reg] -> [(Reg, Format, InstrBlock)] -> Int -> [Reg] -> InstrBlock -> NatM (Int, [Reg], InstrBlock)
+ passArguments _packStack _ _ [] stackSpace accumRegs accumCode = return (stackSpace, accumRegs, accumCode)
+ -- passArguments _ _ [] accumCode stackSpace | isEven stackSpace = return $ SUM (OpReg W64 x31) (OpReg W64 x31) OpImm (ImmInt (-8 * stackSpace))
+ -- passArguments _ _ [] accumCode stackSpace = return $ SUM (OpReg W64 x31) (OpReg W64 x31) OpImm (ImmInt (-8 * (stackSpace + 1)))
-- passArguments [] fpRegs (arg0:arg1:args) stack accumCode = do
-- -- allocate this on the stack
-- (r0, format0, code_r0) <- getSomeReg arg0
-- (r1, format1, code_r1) <- getSomeReg arg1
-- let w0 = formatToWidth format0
-- w1 = formatToWidth format1
- -- stackCode = unitOL $ STP (OpReg w0 r0) (OpReg w1 R1), (OpAddr (AddrRegImm x31 (ImmInt (stackArgs * 8)))
+ -- stackCode = unitOL $ STP (OpReg w0 r0) (OpReg w1 R1), (OpAddr (AddrRegImm x31 (ImmInt (stackSpace * 8)))
-- passArguments gpRegs (fpReg:fpRegs) args (stackCode `appOL` accumCode)
-- float promotion.
@@ -1276,34 +1285,40 @@ genCCall target dest_regs arg_regs bid = do
-- For AArch64 specificies see: https://developer.arm.com/docs/ihi0055/latest/procedure-call-standard-for-the-arm-64-bit-architecture
--
-- Still have GP regs, and we want to pass an GP argument.
- passArguments (gpReg:gpRegs) fpRegs ((r, format, code_r):args) stackArgs accumRegs accumCode | isIntFormat format = do
+ passArguments pack (gpReg:gpRegs) fpRegs ((r, format, code_r):args) stackSpace accumRegs accumCode | isIntFormat format = do
let w = formatToWidth format
- passArguments gpRegs fpRegs args stackArgs (gpReg:accumRegs) (accumCode `appOL` code_r `snocOL` (ANN (text $ "Pass gp argument: " ++ show r) $ MOV (OpReg w gpReg) (OpReg w r)))
+ passArguments pack gpRegs fpRegs args stackSpace (gpReg:accumRegs) (accumCode `appOL` code_r `snocOL` (ANN (text $ "Pass gp argument: " ++ show r) $ MOV (OpReg w gpReg) (OpReg w r)))
-- Still have FP regs, and we want to pass an FP argument.
- passArguments gpRegs (fpReg:fpRegs) ((r, format, code_r):args) stackArgs accumRegs accumCode | isFloatFormat format = do
+ passArguments pack gpRegs (fpReg:fpRegs) ((r, format, code_r):args) stackSpace accumRegs accumCode | isFloatFormat format = do
let w = formatToWidth format
- passArguments gpRegs fpRegs args stackArgs (fpReg:accumRegs) (accumCode `appOL` code_r `snocOL` (ANN (text $ "Pass fp argument: " ++ show r) $ MOV (OpReg w fpReg) (OpReg w r)))
+ passArguments pack gpRegs fpRegs args stackSpace (fpReg:accumRegs) (accumCode `appOL` code_r `snocOL` (ANN (text $ "Pass fp argument: " ++ show r) $ MOV (OpReg w fpReg) (OpReg w r)))
-- No mor regs left to pass. Must pass on stack.
- passArguments [] [] ((r, format, code_r):args) stackArgs accumRegs accumCode = do
+ passArguments pack [] [] ((r, format, code_r):args) stackSpace accumRegs accumCode = do
let w = formatToWidth format
- stackCode = code_r `snocOL` (ANN (text $ "Pass argument: " ++ show r) $ STR format (OpReg w r) (OpAddr (AddrRegImm (regSingle 31) (ImmInt (stackArgs * 8)))))
- passArguments [] [] args (stackArgs+1) accumRegs (stackCode `appOL` accumCode)
+ bytes = widthInBits w `div` 8
+ space = if pack then bytes else 8
+ stackCode = code_r `snocOL` (ANN (text $ "Pass argument (size " ++ show w ++ ") on the stack: " ++ show r) $ STR format (OpReg w r) (OpAddr (AddrRegImm (regSingle 31) (ImmInt stackSpace))))
+ passArguments pack [] [] args (stackSpace+space) accumRegs (stackCode `appOL` accumCode)
-- Still have fpRegs left, but want to pass a GP argument. Must be passed on the stack then.
- passArguments [] fpRegs ((r, format, code_r):args) stackArgs accumRegs accumCode | isIntFormat format = do
+ passArguments pack [] fpRegs ((r, format, code_r):args) stackSpace accumRegs accumCode | isIntFormat format = do
let w = formatToWidth format
- stackCode = code_r `snocOL` (ANN (text $ "Pass argument: " ++ show r) $ STR format (OpReg w r) (OpAddr (AddrRegImm (regSingle 31) (ImmInt (stackArgs * 8)))))
- passArguments [] fpRegs args (stackArgs+1) accumRegs (stackCode `appOL` accumCode)
+ bytes = widthInBits w `div` 8
+ space = if pack then bytes else 8
+ stackCode = code_r `snocOL` (ANN (text $ "Pass argument (size " ++ show w ++ ") on the stack: " ++ show r) $ STR format (OpReg w r) (OpAddr (AddrRegImm (regSingle 31) (ImmInt stackSpace))))
+ passArguments pack [] fpRegs args (stackSpace+space) accumRegs (stackCode `appOL` accumCode)
-- Still have gpRegs left, but want to pass a FP argument. Must be passed on the stack then.
- passArguments gpRegs [] ((r, format, code_r):args) stackArgs accumRegs accumCode | isFloatFormat format = do
+ passArguments pack gpRegs [] ((r, format, code_r):args) stackSpace accumRegs accumCode | isFloatFormat format = do
let w = formatToWidth format
- stackCode = code_r `snocOL` (ANN (text $ "Pass argument: " ++ show r) $ STR format (OpReg w r) (OpAddr (AddrRegImm (regSingle 31) (ImmInt (stackArgs * 8)))))
- passArguments gpRegs [] args (stackArgs+1) accumRegs (stackCode `appOL` accumCode)
+ bytes = widthInBits w `div` 8
+ space = if pack then bytes else 8
+ stackCode = code_r `snocOL` (ANN (text $ "Pass argument (size " ++ show w ++ ") on the stack: " ++ show r) $ STR format (OpReg w r) (OpAddr (AddrRegImm (regSingle 31) (ImmInt stackSpace))))
+ passArguments pack gpRegs [] args (stackSpace+space) accumRegs (stackCode `appOL` accumCode)
- passArguments _ _ _ _ _ _ = pprPanic "passArguments" (text "invalid state")
+ passArguments _ _ _ _ _ _ _ = pprPanic "passArguments" (text "invalid state")
readResults :: [Reg] -> [Reg] -> [LocalReg] -> [Reg]-> InstrBlock -> NatM ([Reg], InstrBlock)
readResults _ _ [] accumRegs accumCode = return (accumRegs, accumCode)
=====================================
compiler/GHC/SysTools.hs
=====================================
@@ -380,7 +380,7 @@ linkDynLib dflags0 o_files dep_packages
++ [ Option "-undefined",
Option "dynamic_lookup",
Option "-single_module" ]
- ++ (if platformArch platform == ArchX86_64
+ ++ (if platformArch platform `elem` [ ArchX86_64, ArchAArch64 ]
then [ ]
else [ Option "-Wl,-read_only_relocs,suppress" ])
++ [ Option "-install_name", Option instName ]
=====================================
includes/rts/Flags.h
=====================================
@@ -199,8 +199,10 @@ typedef struct _CONCURRENT_FLAGS {
* When linkerAlwaysPic is true, the runtime linker assume that all object
* files were compiled with -fPIC -fexternal-dynamic-refs and load them
* anywhere in the address space.
+ * Note that there is no 32bit darwin system we can realistically expect to
+ * run on or compile for.
*/
-#if defined(x86_64_HOST_ARCH) && defined(darwin_HOST_OS)
+#if defined(darwin_HOST_OS)
#define DEFAULT_LINKER_ALWAYS_PIC true
#else
#define DEFAULT_LINKER_ALWAYS_PIC false
=====================================
rts/Linker.c
=====================================
@@ -1522,7 +1522,7 @@ preloadObjectFile (pathchar *path)
*
* See also the misalignment logic for darwin below.
*/
-#if defined(ios_HOST_OS)
+#if defined(darwin_HOST_OS)
image = mmapForLinker(fileSize, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
#else
image = mmapForLinker(fileSize, PROT_READ|PROT_WRITE|PROT_EXEC,
=====================================
rts/ghc.mk
=====================================
@@ -37,7 +37,7 @@ $(eval $(call all-target,rts,$(ALL_RTS_LIBS)))
# -----------------------------------------------------------------------------
# Defining the sources
-ALL_DIRS = hooks sm eventlog linker
+ALL_DIRS = hooks sm eventlog linker linker/macho
ifeq "$(TargetOS_CPP)" "mingw32"
ALL_DIRS += win32
@@ -329,8 +329,8 @@ $(eval $(call distdir-opts,rts,dist,1))
# We like plenty of warnings.
WARNING_OPTS += -Wall
WARNING_OPTS += -Wextra
-WARNING_OPTS += -Wstrict-prototypes
-WARNING_OPTS += -Wmissing-prototypes
+WARNING_OPTS += -Wstrict-prototypes
+WARNING_OPTS += -Wmissing-prototypes
WARNING_OPTS += -Wmissing-declarations
WARNING_OPTS += -Winline
WARNING_OPTS += -Wpointer-arith
@@ -346,7 +346,7 @@ WARNING_OPTS += -Wno-aggregate-return
#WARNING_OPTS += -Wshadow
#WARNING_OPTS += -Wcast-qual
-# This one seems buggy on GCC 4.1.2, which is the only GCC version we
+# This one seems buggy on GCC 4.1.2, which is the only GCC version we
# have that can bootstrap the SPARC build. We end up with lots of supurious
# warnings of the form "cast increases required alignment of target type".
# Some legitimate warnings can be fixed by adding an intermediate cast to
@@ -383,7 +383,7 @@ rts_CC_OPTS += -DUSE_LIBFFI_FOR_ADJUSTORS
endif
# We *want* type-checking of hand-written cmm.
-rts_HC_OPTS += -dcmm-lint
+rts_HC_OPTS += -dcmm-lint
# -fno-strict-aliasing is required for the runtime, because we often
# use a variety of types to represent closure pointers (StgPtr,
@@ -658,4 +658,3 @@ install_libffi_headers :
$(eval $(call clean-target,rts,dist,rts/dist))
BINDIST_EXTRAS += rts/package.conf.in
-
=====================================
rts/linker/Elf.c
=====================================
@@ -754,8 +754,8 @@ ocGetNames_ELF ( ObjectCode* oc )
void * mem = mmapForLinker(size+stub_space, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
if( mem == MAP_FAILED ) {
- barf("failed to mmap allocated memory to load section %d. "
- "errno = %d", i, errno);
+ sysErrorBelch("failed to mmap allocated memory to load section %d. "
+ "errno = %d", i, errno);
}
/* copy only the image part over; we don't want to copy data
=====================================
rts/linker/MachO.c
=====================================
@@ -42,6 +42,9 @@
*) add still more sanity checks.
*/
#if defined(aarch64_HOST_ARCH)
+# define NEED_PLT
+# include "macho/plt.h"
+
/* aarch64 linker by moritz angermann <moritz at lichtzwerge.de> */
/* often times we need to extend some value of certain number of bits
@@ -49,7 +52,7 @@
*/
int64_t signExtend(uint64_t val, uint8_t bits);
/* Helper functions to check some instruction properties */
-bool isVectorPp(uint32_t *p);
+bool isVectorOp(uint32_t *p);
bool isLoadStore(uint32_t *p);
/* aarch64 relocations may contain an addend already in the position
@@ -65,9 +68,9 @@ void encodeAddend(ObjectCode * oc, Section * section,
/* finding and making stubs. We don't need to care about the symbol they
* represent. As long as two stubs point to the same address, they are identical
*/
-bool findStub(Section * section, void ** addr);
-bool makeStub(Section * section, void ** addr);
-void freeStubs(Section * section);
+// bool findStub(Section * section, void ** addr);
+// bool makeStub(Section * section, void ** addr);
+// void freeStubs(Section * section);
/* Global Offset Table logic */
bool isGotLoad(MachORelocationInfo * ri);
@@ -272,12 +275,12 @@ signExtend(uint64_t val, uint8_t bits) {
return (int64_t)(val << (64-bits)) >> (64-bits);
}
-bool
+inline bool
isVectorOp(uint32_t *p) {
return (*p & 0x04800000) == 0x04800000;
}
-bool
+inline bool
isLoadStore(uint32_t *p) {
return (*p & 0x3B000000) == 0x39000000;
}
@@ -345,7 +348,7 @@ decodeAddend(ObjectCode * oc, Section * section, MachORelocationInfo * ri) {
inline bool
fitsBits(size_t bits, int64_t value) {
if(bits == 64) return true;
- if(bits > 64) barf("fits_bits with %d bits and an 64bit integer!", bits);
+ if(bits > 64) barf("fits_bits with %zu bits and an 64bit integer!", bits);
return 0 == (value >> bits) // All bits off: 0
|| -1 == (value >> bits); // All bits on: -1
}
@@ -425,67 +428,6 @@ isGotLoad(struct relocation_info * ri) {
|| ri->r_type == ARM64_RELOC_GOT_LOAD_PAGEOFF12;
}
-/* This is very similar to makeSymbolExtra
- * However, as we load sections into different
- * pages, that may be further apart than
- * branching allows, we'll use some extra
- * space at the end of each section allocated
- * for stubs.
- */
-bool
-findStub(Section * section, void ** addr) {
-
- for(Stub * s = section->info->stubs; s != NULL; s = s->next) {
- if(s->target == *addr) {
- *addr = s->addr;
- return EXIT_SUCCESS;
- }
- }
- return EXIT_FAILURE;
-}
-
-bool
-makeStub(Section * section, void ** addr) {
-
- Stub * s = stgCallocBytes(1, sizeof(Stub), "makeStub(Stub)");
- s->target = *addr;
- s->addr = (uint8_t*)section->info->stub_offset
- + ((8+8)*section->info->nstubs) + 8;
- s->next = NULL;
-
- /* target address */
- *(uint64_t*)((uint8_t*)s->addr - 8) = (uint64_t)s->target;
- /* ldr x16, - (8 bytes) */
- *(uint32_t*)(s->addr) = (uint32_t)0x58ffffd0;
- /* br x16 */
- *(uint32_t*)((uint8_t*)s->addr + 4) = (uint32_t)0xd61f0200;
-
- if(section->info->nstubs == 0) {
- /* no stubs yet, let's just create this one */
- section->info->stubs = s;
- } else {
- Stub * tail = section->info->stubs;
- while(tail->next != NULL) tail = tail->next;
- tail->next = s;
- }
- section->info->nstubs += 1;
- *addr = s->addr;
- return EXIT_SUCCESS;
-}
-void
-freeStubs(Section * section) {
- if(section->info->nstubs == 0)
- return;
- Stub * last = section->info->stubs;
- while(last->next != NULL) {
- Stub * t = last;
- last = last->next;
- stgFree(t);
- }
- section->info->stubs = NULL;
- section->info->nstubs = 0;
-}
-
/*
* Check if we need a global offset table slot for a
* given symbol
@@ -618,9 +560,9 @@ relocateSectionAarch64(ObjectCode * oc, Section * section)
if((value - pc + addend) >> (2 + 26)) {
/* we need a stub */
/* check if we already have that stub */
- if(findStub(section, (void**)&value)) {
+ if(findStub(section, (void**)&value, 0)) {
/* did not find it. Crete a new stub. */
- if(makeStub(section, (void**)&value)) {
+ if(makeStub(section, (void**)&value, 0)) {
barf("could not find or make stub");
}
}
@@ -1231,9 +1173,15 @@ ocGetNames_MachO(ObjectCode* oc)
size_t alignment = 1 << section->align;
SectionKind kind = getSectionKind_MachO(section);
+ SectionAlloc alloc = SECTION_NOMEM;
+ void *start = NULL, *mapped_start = NULL;
+ StgWord mapped_size = 0, mapped_offset = 0;
+ StgWord size = section->size;
void *secMem = (void *)roundUpToAlign((size_t)curMem, alignment);
+ start = secMem;
+
IF_DEBUG(linker,
debugBelch("ocGetNames_MachO: loading section %d in segment %d "
"(#%d, %s %s)\n"
@@ -1246,28 +1194,56 @@ ocGetNames_MachO(ObjectCode* oc)
case S_GB_ZEROFILL:
IF_DEBUG(linker, debugBelch("ocGetNames_MachO: memset to 0 a ZEROFILL section\n"));
memset(secMem, 0, section->size);
+ addSection(&secArray[sec_idx], kind, alloc, start, size,
+ mapped_offset, mapped_start, mapped_size);
break;
default:
IF_DEBUG(linker,
debugBelch("ocGetNames_MachO: copying from %p to %p"
" a block of %" PRIu64 " bytes\n",
(void *) (oc->image + section->offset), secMem, section->size));
+#if defined(NEED_PLT)
+ unsigned nstubs = numberOfStubsForSection(oc, sec_idx);
+ unsigned stub_space = STUB_SIZE * nstubs;
- memcpy(secMem, oc->image + section->offset, section->size);
- }
+ void * mem = mmapForLinker(section->size+stub_space, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
+ if( mem == MAP_FAILED ) {
+ sysErrorBelch("failed to mmap allocated memory to load section %d. "
+ "errno = %d", sec_idx, errno);
+ }
+ /* copy only the image part over; we don't want to copy data
+ * into the stub part.
+ */
+ memcpy( mem, oc->image + section->offset, size );
+
+ alloc = SECTION_MMAP;
+ mapped_offset = 0;
+ mapped_size = roundUpToPage(size+stub_space);
+ start = mem;
+ mapped_start = mem;
+#else
+ memcpy(secMem, oc->image + section->offset, section->size);
+#endif
+ addSection(&secArray[sec_idx], kind, alloc, start, size,
+ mapped_offset, mapped_start, mapped_size);
/* SECTION_NOMEM since memory is already allocated in segments */
- addSection(&secArray[sec_idx], kind, SECTION_NOMEM,
- secMem, section->size,
- 0, 0, 0);
- addProddableBlock(oc, secMem, section->size);
- curMem = (char*) secMem + section->size;
+#if defined(NEED_PLT)
+ secArray[sec_idx].info->nstubs = 0;
+ secArray[sec_idx].info->stub_offset = (uint8_t*)mem + size;
+ secArray[sec_idx].info->stub_size = stub_space;
+ secArray[sec_idx].info->stubs = NULL;
+#else
+ secArray[sec_idx].info->nstubs = 0;
+ secArray[sec_idx].info->stub_offset = NULL;
+ secArray[sec_idx].info->stub_size = 0;
+ secArray[sec_idx].info->stubs = NULL;
+#endif
+ addProddableBlock(oc, start, section->size);
+ }
- secArray[sec_idx].info->nstubs = 0;
- secArray[sec_idx].info->stub_offset = NULL;
- secArray[sec_idx].info->stub_size = 0;
- secArray[sec_idx].info->stubs = NULL;
+ curMem = (char*) secMem + section->size;
secArray[sec_idx].info->macho_section = section;
secArray[sec_idx].info->relocation_info
@@ -1451,6 +1427,26 @@ ocMprotect_MachO( ObjectCode *oc )
mmapForLinkerMarkExecutable(segment->start, segment->size);
}
}
+
+ // Also mark mmaped, sections executable. Those are not part of the
+ // segments anymore and have been mapped separately.
+ for(int i=0; i < oc->n_sections; i++) {
+ Section *section = &oc->sections[i];
+ if(section->size == 0) continue;
+ if(section->alloc != SECTION_MMAP) continue;
+ // N.B. m32 handles protection of its allocations during
+ // flushing.
+ if(section->alloc == SECTION_M32) continue;
+ switch (section->kind) {
+ case SECTIONKIND_CODE_OR_RODATA: {
+ mmapForLinkerMarkExecutable(section->mapped_start, section->mapped_size);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
return true;
}
=====================================
rts/linker/MachOTypes.h
=====================================
@@ -103,6 +103,11 @@ typedef
struct _Stub {
void * addr;
void * target;
+ /* flags can hold architecture specific information they are used during
+ * lookup of stubs as well. Thus two stubs for the same target with
+ * different flags are considered unequal.
+ */
+ uint8_t flags;
struct _Stub * next;
}
Stub;
=====================================
rts/linker/macho/plt.c
=====================================
@@ -0,0 +1,93 @@
+#include "Rts.h"
+#include "plt.h"
+
+#if defined(aarch64_HOST_ARCH)
+
+#if defined(OBJFORMAT_MACHO)
+
+#include <mach/machine.h>
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#include <mach-o/nlist.h>
+#include <mach-o/reloc.h>
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+
+#define _makeStub ADD_SUFFIX(makeStub)
+#define needStubForRel ADD_SUFFIX(needStubForRel)
+
+unsigned
+numberOfStubsForSection( ObjectCode *oc, unsigned sectionIndex) {
+ unsigned n = 0;
+
+ MachOSection *section = &oc->info->macho_sections[sectionIndex];
+ MachORelocationInfo *relocation_info = (MachORelocationInfo*)(oc->image + section->reloff);
+ if(section->size > 0)
+ for(size_t i = 0; i < section->nreloc; i++)
+ if(needStubForRel(&relocation_info[i]))
+ n += 1;
+
+ return n;
+}
+
+bool
+findStub(Section * section,
+ void* * addr,
+ uint8_t flags) {
+ for(Stub * s = section->info->stubs; s != NULL; s = s->next) {
+ if( s->target == *addr
+ && s->flags == flags) {
+ *addr = s->addr;
+ return EXIT_SUCCESS;
+ }
+ }
+ return EXIT_FAILURE;
+}
+
+bool
+makeStub(Section * section,
+ void* * addr,
+ uint8_t flags) {
+
+ Stub * s = calloc(1, sizeof(Stub));
+ ASSERT(s != NULL);
+ s->target = *addr;
+ s->flags = flags;
+ s->next = NULL;
+ s->addr = (uint8_t *)section->info->stub_offset + 8
+ + STUB_SIZE * section->info->nstubs;
+
+ if((*_makeStub)(s))
+ return EXIT_FAILURE;
+
+ if(section->info->stubs == NULL) {
+ ASSERT(section->info->nstubs == 0);
+ /* no stubs yet, let's just create this one */
+ section->info->stubs = s;
+ } else {
+ Stub * tail = section->info->stubs;
+ while(tail->next != NULL) tail = tail->next;
+ tail->next = s;
+ }
+ section->info->nstubs += 1;
+ *addr = s->addr;
+ return EXIT_SUCCESS;
+}
+
+void
+freeStubs(Section * section) {
+ if(section->info->nstubs == 0)
+ return;
+ Stub * last = section->info->stubs;
+ while(last->next != NULL) {
+ Stub * t = last;
+ last = last->next;
+ free(t);
+ }
+ section->info->stubs = NULL;
+ section->info->nstubs = 0;
+}
+
+#endif // OBJECTFORMAT_MACHO
+#endif // aarch64_HOST_ARCH
\ No newline at end of file
=====================================
rts/linker/macho/plt.h
=====================================
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <LinkerInternals.h>
+
+#include "plt_aarch64.h"
+
+#if defined(aarch64_HOST_ARCH)
+
+#if defined(OBJFORMAT_MACHO)
+
+#if defined(__x86_64__)
+#define __suffix__ X86_64
+#elif defined(__aarch64__) || defined(__arm64__)
+#define __suffix__ Aarch64
+#else
+#error "unknown architecture"
+#endif
+
+#define PASTE(x,y) x ## y
+#define EVAL(x,y) PASTE(x,y)
+#define ADD_SUFFIX(x) EVAL(PASTE(x,),__suffix__)
+
+unsigned numberOfStubsForSection( ObjectCode *oc, unsigned sectionIndex);
+
+#define STUB_SIZE ADD_SUFFIX(stubSize)
+
+bool findStub(Section * section, void* * addr, uint8_t flags);
+bool makeStub(Section * section, void* * addr, uint8_t flags);
+
+void freeStubs(Section * section);
+
+#endif // OBJECTFORMAT_MACHO
+
+#endif // aarch64_HOST_ARCH
\ No newline at end of file
=====================================
rts/linker/macho/plt_aarch64.c
=====================================
@@ -0,0 +1,61 @@
+#include "Rts.h"
+#include "plt_aarch64.h"
+
+#include <stdlib.h>
+
+#if defined(aarch64_HOST_ARCH)
+
+#if defined(OBJFORMAT_MACHO)
+
+#include <mach/machine.h>
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#include <mach-o/nlist.h>
+#include <mach-o/reloc.h>
+
+/* five 4 byte instructions */
+const size_t instSizeAarch64 = 4;
+const size_t stubSizeAarch64 = 5 * 4;
+
+bool needStubForRelAarch64(MachORelocationInfo * rel) {
+ switch(rel->r_type) {
+ case ARM64_RELOC_BRANCH26:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* see the elf_plt_aarch64.c for the discussion on this */
+bool
+makeStubAarch64(Stub * s) {
+ uint32_t mov__hw0_x16 = 0xd2800000 | 16;
+ uint32_t movk_hw0_x16 = mov__hw0_x16 | (1 << 29);
+
+ uint32_t mov__hw3_x16 = mov__hw0_x16 | (3 << 21);
+ uint32_t movk_hw2_x16 = movk_hw0_x16 | (2 << 21);
+ uint32_t movk_hw1_x16 = movk_hw0_x16 | (1 << 21);
+
+
+ uint32_t br_x16 = 0xd61f0000 | 16 << 5;
+
+ uint32_t *P = (uint32_t*)s->addr;
+
+ /* target address */
+ uint64_t addr = (uint64_t)s->target;
+ uint16_t addr_hw0 = (uint16_t)(addr >> 0);
+ uint16_t addr_hw1 = (uint16_t)(addr >> 16);
+ uint16_t addr_hw2 = (uint16_t)(addr >> 32);
+ uint16_t addr_hw3 = (uint16_t)(addr >> 48);
+
+ P[0] = mov__hw3_x16 | ((uint32_t)addr_hw3 << 5);
+ P[1] = movk_hw2_x16 | ((uint32_t)addr_hw2 << 5);
+ P[2] = movk_hw1_x16 | ((uint32_t)addr_hw1 << 5);
+ P[3] = movk_hw0_x16 | ((uint32_t)addr_hw0 << 5);
+ P[4] = br_x16;
+
+ return EXIT_SUCCESS;
+}
+
+#endif
+#endif
\ No newline at end of file
=====================================
rts/linker/macho/plt_aarch64.h
=====================================
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <LinkerInternals.h>
+
+#if defined(OBJFORMAT_MACHO)
+
+#if defined(x86_64_HOST_ARCH)
+# include <mach-o/x86_64/reloc.h>
+#endif
+
+#if defined(aarch64_HOST_ARCH)
+# include <mach-o/arm64/reloc.h>
+#endif
+
+#include "../MachOTypes.h"
+
+
+extern const size_t stubSizeAarch64;
+bool needStubForRelAarch64(MachORelocationInfo * rel);
+bool makeStubAarch64(Stub * s);
+
+#endif
\ No newline at end of file
=====================================
rts/package.conf.in
=====================================
@@ -318,7 +318,7 @@ ld-options:
, "-Wl,-search_paths_first"
#endif
-#if defined(darwin_HOST_OS) && !defined(x86_64_HOST_ARCH)
+#if defined(darwin_HOST_OS) && !defined(x86_64_HOST_ARCH) && !defined(aarch64_HOST_ARCH)
, "-read_only_relocs", "warning"
#endif
=====================================
rts/rts.cabal.in
=====================================
@@ -385,7 +385,7 @@ library
if os(osx)
ld-options: "-Wl,-search_paths_first"
- if !arch(x86_64)
+ if !arch(x86_64) && !arch(aarch64)
ld-options: -read_only_relocs warning
cmm-sources: Apply.cmm
@@ -478,6 +478,8 @@ library
linker/LoadArchive.c
linker/M32Alloc.c
linker/MachO.c
+ linker/macho/plt.c
+ linker/macho/plt_aarch64.c
linker/PEi386.c
linker/SymbolExtras.c
linker/elf_got.c
=====================================
rts/sm/Storage.c
=====================================
@@ -1733,9 +1733,6 @@ AdjustorWritable allocateExec(W_ bytes, AdjustorExecutable *exec_ret)
{
AdjustorWritable writ;
ffi_closure* cl;
- if (bytes != sizeof(ffi_closure)) {
- barf("allocateExec: for ffi_closure only");
- }
ACQUIRE_SM_LOCK;
cl = writ = ffi_closure_alloc((size_t)bytes, exec_ret);
if (cl != NULL) {
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e9d9d48daaeebedf97d10269524bc8e8e76b53cd...046365b34996756242037e8f62c1ac8c6e4687ff
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e9d9d48daaeebedf97d10269524bc8e8e76b53cd...046365b34996756242037e8f62c1ac8c6e4687ff
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20201009/8b206407/attachment-0001.html>
More information about the ghc-commits
mailing list