[ELF] Support R_PPC64_ADDR16_HIGH
authorFangrui Song <i@maskray.me>
Tue, 19 Jan 2021 19:42:52 +0000 (11:42 -0800)
committerFangrui Song <i@maskray.me>
Tue, 19 Jan 2021 19:42:53 +0000 (11:42 -0800)
R_PPC64_ADDR16_HI represents bits 16-31 of a 32-bit value
R_PPC64_ADDR16_HIGH represents bits 16-31 of a 64-bit value.

In the Linux kernel, `LOAD_REG_IMMEDIATE_SYM` defined in `arch/powerpc/include/asm/ppc_asm.h`
uses @l, @high, @higher, @highest to load the 64-bit value of a symbol.

Fixes https://github.com/ClangBuiltLinux/linux/issues/1260

lld/ELF/Arch/PPC64.cpp
lld/test/ELF/ppc64-reloc-addr.s
lld/test/ELF/ppc64-reloc-addr16-err.s

index ebd94f6..03ecc81 100644 (file)
@@ -948,6 +948,7 @@ RelExpr PPC64::getRelExpr(RelType type, const Symbol &s,
   case R_PPC64_ADDR16_DS:
   case R_PPC64_ADDR16_HA:
   case R_PPC64_ADDR16_HI:
+  case R_PPC64_ADDR16_HIGH:
   case R_PPC64_ADDR16_HIGHER:
   case R_PPC64_ADDR16_HIGHERA:
   case R_PPC64_ADDR16_HIGHEST:
@@ -1230,6 +1231,9 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     checkInt(loc, val, 32, rel);
     write16(loc, hi(val));
     break;
+  case R_PPC64_ADDR16_HIGH:
+    write16(loc, hi(val));
+    break;
   case R_PPC64_ADDR16_HIGHER:
   case R_PPC64_TPREL16_HIGHER:
     write16(loc, higher(val));
index 7eb13c2..d7b0a3d 100644 (file)
 .section .R_PPC64_ADDR16_HA,"ax",@progbits
   lis 4, b@ha
 
+# CHECK-LABEL: <.R_PPC64_ADDR16_HIGH>:
+# CHECK-NEXT:    lis 4, -30293
+.section .R_PPC64_ADDR16_HIGH,"ax",@progbits
+  lis 4, a@high
+
 # CHECK-LABEL: <.R_PPC64_ADDR16_HIGHER>:
 # CHECK-NEXT:    li 3, 17767
 .section .R_PPC64_ADDR16_HIGHER,"ax",@progbits
index 1b221d5..fe225b5 100644 (file)
@@ -18,3 +18,5 @@ lis 4, a@h  # R_PPC64_ADDR16_HI
 .ifdef HA
 lis 4, a@ha  # R_PPC64_ADDR16_HA
 .endif
+
+lis 4, a@high  # R_PPC64_ADDR16_HIGH