summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Target.cpp13
-rw-r--r--lld/test/ELF/Inputs/mips-dynamic.s17
-rw-r--r--lld/test/ELF/mips-plt-copy.s42
3 files changed, 72 insertions, 0 deletions
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index 2b1e9f7308d..70edfd30342 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -196,6 +196,7 @@ public:
MipsTargetInfo();
unsigned getDynRel(unsigned Type) const override;
void writeGotHeader(uint8_t *Buf) const override;
+ bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
bool needsGot(uint32_t Type, const SymbolBody &S) const override;
bool needsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
@@ -1386,6 +1387,7 @@ void AMDGPUTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
}
template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
+ CopyRel = R_MIPS_COPY;
PageSize = 65536;
GotHeaderEntriesNum = 2;
RelativeRel = R_MIPS_REL32;
@@ -1426,6 +1428,17 @@ void MipsTargetInfo<ELFT>::writeGotHeader(uint8_t *Buf) const {
}
template <class ELFT>
+bool MipsTargetInfo<ELFT>::needsCopyRel(uint32_t Type,
+ const SymbolBody &S) const {
+ if (Config->Shared)
+ return false;
+ if (Type == R_MIPS_HI16 || Type == R_MIPS_LO16 || isRelRelative(Type))
+ if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(&S))
+ return SS->Sym.getType() == STT_OBJECT;
+ return false;
+}
+
+template <class ELFT>
bool MipsTargetInfo<ELFT>::needsGot(uint32_t Type, const SymbolBody &S) const {
return Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16;
}
diff --git a/lld/test/ELF/Inputs/mips-dynamic.s b/lld/test/ELF/Inputs/mips-dynamic.s
index eba5b7f327b..baf07c1daad 100644
--- a/lld/test/ELF/Inputs/mips-dynamic.s
+++ b/lld/test/ELF/Inputs/mips-dynamic.s
@@ -1,4 +1,21 @@
+ .option pic2
.text
.globl _foo
_foo:
nop
+
+ .globl foo
+ .type foo, @function
+foo:
+ nop
+
+ .data
+ .globl data0
+ .type data0, @object
+data0:
+ .word 0
+
+ .globl data1
+ .type data1, @object
+data1:
+ .word 0
diff --git a/lld/test/ELF/mips-plt-copy.s b/lld/test/ELF/mips-plt-copy.s
new file mode 100644
index 00000000000..6ef05ab9dcc
--- /dev/null
+++ b/lld/test/ELF/mips-plt-copy.s
@@ -0,0 +1,42 @@
+# Check creating of R_MIPS_COPY dynamic relocation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: %S/Inputs/mips-dynamic.s -o %t.so.o
+# RUN: ld.lld %t.so.o -shared -o %t.so
+# RUN: ld.lld %t.o %t.so -o %t.exe
+# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Relocations [
+# CHECK-NEXT: Section (7) .rel.dyn {
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_COPY data0 0x0
+# CHECK-NEXT: 0x{{[0-9A-F]+}} R_MIPS_COPY data1 0x0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+# CHECK: Primary GOT {
+# CHECK: Local entries [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Global entries [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Number of TLS and multi-GOT entries: 0
+# CHECK-NEXT: }
+
+ .text
+ .globl __start
+__start:
+ lui $t0,%hi(data0) # R_MIPS_HI16 requires COPY rel for DSO defined data.
+ addi $t0,$t0,%lo(data0)
+ lui $t0,%hi(gd) # Does not require COPY rel for locally defined data.
+ addi $t0,$t0,%lo(gd)
+ lui $t0,%hi(ld) # Does not require COPY rel for local data.
+ addi $t0,$t0,%lo(ld)
+
+ .data
+ .globl gd
+gd:
+ .word 0
+ld:
+ .word data1+8-. # R_MIPS_PC32 requires COPY rel for DSO defined data.
OpenPOWER on IntegriCloud