[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