add support for powerpc/powerpc64 unaligned relocations
authorSamuel Holland <samuel@sholland.org>
Sun, 30 Jun 2019 12:39:20 +0000 (07:39 -0500)
committerRich Felker <dalias@aerifal.cx>
Sun, 11 Aug 2019 21:43:57 +0000 (17:43 -0400)
R_PPC_UADDR32 (R_PPC64_UADDR64) has the same meaning as R_PPC_ADDR32
(R_PPC64_ADDR64), except that its address need not be aligned. For
powerpc64, BFD ld(1) will automatically convert between ADDR<->UADDR
relocations when the address is/isn't at its native alignment. This
will happen if, for example, there is a pointer in a packed struct.

gold and lld do not currently generate R_PPC64_UADDR64, but pass
through misaligned R_PPC64_ADDR64 relocations from object files,
possibly relaxing them to misaligned R_PPC64_RELATIVE. In both cases
(relaxed or not) this violates the PSABI, which defines the relevant
field type as "a 64-bit field occupying 8 bytes, the alignment of
which is 8 bytes unless otherwise specified."

All three linkers violate the PSABI on 32-bit powerpc, where the only
difference is that the field is 32 bits wide, aligned to 4 bytes.

Currently musl fails to load executables linked by BFD ld containing
R_PPC64_UADDR64, with the error "unsupported relocation type 43".
This change provides compatibility with BFD ld on powerpc64, and any
static linker on either architecture that starts following the PSABI
more closely.

arch/powerpc/reloc.h
arch/powerpc64/reloc.h
ldso/dynlink.c
src/internal/dynlink.h

index 1b4cab36a60878c81bb20e06ea1fdc6e22d346df..527b6b7cdc5f4409e6419b3a177d5cb7320a0ea3 100644 (file)
@@ -9,6 +9,7 @@
 #define TPOFF_K (-0x7000)
 
 #define REL_SYMBOLIC    R_PPC_ADDR32
+#define REL_USYMBOLIC   R_PPC_UADDR32
 #define REL_GOT         R_PPC_GLOB_DAT
 #define REL_PLT         R_PPC_JMP_SLOT
 #define REL_RELATIVE    R_PPC_RELATIVE
index faf70acd752c6f950ba6126cd09b75624fc0abf9..5bdaeede5437bbc99b5f47bd1271e5ef87c55d3d 100644 (file)
@@ -11,6 +11,7 @@
 #define TPOFF_K (-0x7000)
 
 #define REL_SYMBOLIC    R_PPC64_ADDR64
+#define REL_USYMBOLIC   R_PPC64_UADDR64
 #define REL_GOT         R_PPC64_GLOB_DAT
 #define REL_PLT         R_PPC64_JMP_SLOT
 #define REL_RELATIVE    R_PPC64_RELATIVE
index 531811cc57656c246a79812f774bb5f9484b71ec..edd91acde257f6b185d35e28855b903d6cd50098 100644 (file)
@@ -407,6 +407,9 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
                case REL_PLT:
                        *reloc_addr = sym_val + addend;
                        break;
+               case REL_USYMBOLIC:
+                       memcpy(reloc_addr, &(size_t){sym_val + addend}, sizeof(size_t));
+                       break;
                case REL_RELATIVE:
                        *reloc_addr = (size_t)base + addend;
                        break;
index 165bbedbb8d0d5c8245f56d7b42fa426c7a512d1..ffd06b0471b9855691cc70c40486313c09d7da7c 100644 (file)
@@ -28,6 +28,7 @@ typedef Elf64_Sym Sym;
 enum {
        REL_NONE = 0,
        REL_SYMBOLIC = -100,
+       REL_USYMBOLIC,
        REL_GOT,
        REL_PLT,
        REL_RELATIVE,