summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/InputSection.cpp5
-rw-r--r--lld/test/ELF/i386-reloc-non-alloc.s18
2 files changed, 21 insertions, 2 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 9b21a327190..40f95daaf3d 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -452,7 +452,8 @@ void InputSection<ELFT>::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
Addend += Target->getImplicitAddend(BufLoc, Type);
SymbolBody &Sym = this->File->getRelocTargetSym(Rel);
- if (Target->getRelExpr(Type, Sym) != R_ABS) {
+ RelExpr E = Target->getRelExpr(Type, Sym);
+ if (E != R_ABS && E != R_PC) {
error(this->getLocation(Offset) + ": has non-ABS reloc");
return;
}
@@ -461,7 +462,7 @@ void InputSection<ELFT>::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
uint64_t SymVA = 0;
if (!Sym.isTls() || Out<ELFT>::TlsPhdr)
SymVA = SignExtend64<sizeof(uintX_t) * 8>(
- getRelocTargetVA<ELFT>(Type, Addend, AddrLoc, Sym, R_ABS));
+ getRelocTargetVA<ELFT>(Type, Addend, AddrLoc, Sym, E));
Target->relocateOne(BufLoc, Type, SymVA);
}
}
diff --git a/lld/test/ELF/i386-reloc-non-alloc.s b/lld/test/ELF/i386-reloc-non-alloc.s
new file mode 100644
index 00000000000..98612fe57f7
--- /dev/null
+++ b/lld/test/ELF/i386-reloc-non-alloc.s
@@ -0,0 +1,18 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-objdump -s %t.so | FileCheck %s
+
+// CHECK: Contents of section .text:
+// CHECK-NEXT: 1000 00000000 00000000
+
+// CHECK: Contents of section .bar:
+// CHECK-NEXT: 0000 00100000 fc0f0000
+
+foo:
+.quad 0
+
+.section .bar
+.long foo - .
+.long foo - .
OpenPOWER on IntegriCloud