powerpc: add basic support for PLT relocations (#10402)
authorSergei Trofimovich <slyfox@gentoo.org>
Tue, 23 Jun 2015 12:39:34 +0000 (07:39 -0500)
committerAustin Seipp <austin@well-typed.com>
Tue, 23 Jun 2015 12:39:46 +0000 (07:39 -0500)
Commit a93ab43ab5f40cadbedea2f6342b93c245e91434
enabled support for proper PIC relocations from
assembler.

Commit adds support for relocations of type:
    R_PPC_REL16_HI
    R_PPC_REL16_HA
    R_PPC_REL16_LO
    R_PPC_PLTREL24

They are used only when GHC is built in
    DYNAMIC_GHC_PROGRAMS = NO
mode.

Verified by running the following test:

    // cat a.c
    #include <stdio.h>

    void ffi_a_hello (int i) {
        fprintf (stderr, "WEEEEEEEE: i=%d\n", i);
    }

    -- cat A.hs
    {-# LANGUAGE ForeignFunctionInterface #-}
    module A where

    import Foreign.C

    foreign import ccall "ffi_a_hello" a :: CInt -> IO ()

    # ghc -fPIC -c a.c -fforce-recomp
    # ghc -fPIC -c A.hs -fforce-recomp
    # ghc --interactive ./a.o A
    ...
    *A> a 42
    WEEEEEEEE: i=42
See gory details in Trac #10402.

Signed-off-by: Colin Watson <cjwatson@debian.org>
Signed-off-by: Sergei Trofimovich <siarheit@google.com>
Reviewed By: bgamari, austin

Differential Revision: https://phabricator.haskell.org/D996

GHC Trac Issues: #10402

rts/Linker.c

index f3b170b..2437e83 100644 (file)
@@ -5952,6 +5952,9 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
             *(Elf32_Word *) P = value - P;
             break;
 
+         case R_PPC_PLTREL24:
+            value -= 0x8000; /* See Note [.LCTOC1 in PPC PIC code] */
+            /* fallthrough */
          case R_PPC_REL24:
             delta = value - P;
 
@@ -5972,6 +5975,18 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
             *(Elf_Word *) P = (*(Elf_Word *) P & 0xfc000003)
                                           | (delta & 0x3fffffc);
             break;
+
+         case R_PPC_REL16_LO:
+            *(Elf32_Half*) P = value - P;
+            break;
+
+         case R_PPC_REL16_HI:
+            *(Elf32_Half*) P = (value - P) >> 16;
+            break;
+
+         case R_PPC_REL16_HA:
+            *(Elf32_Half*) P = (value + 0x8000 - P) >> 16;
+            break;
 #        endif
 
 #if x86_64_HOST_ARCH