diff options
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp | 22 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp | 9 | ||||
| -rw-r--r-- | lld/test/elf/Mips/rel-dynamic-15.test | 81 |
3 files changed, 101 insertions, 11 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp index c0feb735960..66267c6a318 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp @@ -320,12 +320,12 @@ static ErrorOr<int64_t> relocJalr(uint64_t P, uint64_t S, bool isCrossJump, return ins; } -static int64_t relocRel32(int64_t A) { +static int64_t relocRel32(uint64_t S, int64_t A, bool isLocal) { // If output relocation format is REL and the input one is RELA, the only // method to transfer the relocation addend from the input relocation // to the output dynamic relocation is to save this addend to the location // modified by R_MIPS_REL32. - return A; + return isLocal ? S + A : A; } static std::error_code adjustJumpOpCode(uint64_t &ins, uint64_t tgt, @@ -383,8 +383,8 @@ template <class ELFT> static ErrorOr<int64_t> calculateRelocation(Reference::KindValue kind, Reference::Addend addend, uint64_t tgtAddr, uint64_t relAddr, uint64_t gpAddr, - bool isGP, bool isCrossJump, bool isDynamic, - uint8_t *location) { + uint8_t *location, bool isGP, bool isCrossJump, + bool isDynamic, bool isLocalSym) { switch (kind) { case R_MIPS_NONE: return 0; @@ -490,7 +490,7 @@ calculateRelocation(Reference::KindValue kind, Reference::Addend addend, // We do not do JALR optimization now. return 0; case R_MIPS_REL32: - return relocRel32(addend); + return relocRel32(tgtAddr, addend, isLocalSym); case R_MIPS_JUMP_SLOT: case R_MIPS_COPY: // Ignore runtime relocations. @@ -585,6 +585,12 @@ static uint8_t getRelShift(Reference::KindValue kind, return shift; } +static bool isLocalTarget(const Atom *a) { + if (auto *da = dyn_cast<DefinedAtom>(a)) + return da->scope() == Atom::scopeTranslationUnit; + return false; +} + template <class ELFT> std::error_code RelocationHandler<ELFT>::applyRelocation( ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom, @@ -595,6 +601,7 @@ std::error_code RelocationHandler<ELFT>::applyRelocation( uint64_t gpAddr = _targetLayout.getGPAddr(); bool isGpDisp = ref.target()->name() == "_gp_disp"; + bool isLocalSym = isLocalTarget(ref.target()); uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset; uint8_t *location = atomContent + ref.offsetInAtom(); @@ -616,8 +623,9 @@ std::error_code RelocationHandler<ELFT>::applyRelocation( if (kind == R_MIPS_NONE) break; auto params = getRelocationParams(kind); - res = calculateRelocation<ELFT>(kind, *res, sym, relAddr, gpAddr, isGpDisp, - isCrossJump, _ctx.isDynamic(), location); + res = calculateRelocation<ELFT>(kind, *res, sym, relAddr, gpAddr, location, + isGpDisp, isCrossJump, _ctx.isDynamic(), + isLocalSym); if (auto ec = res.getError()) return ec; // Check result for the last relocation only. diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp index 99d2ccf9676..75a9ae57170 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp @@ -586,7 +586,8 @@ std::error_code RelocationPass<ELFT>::perform(SimpleFile &mf) { // Create R_MIPS_REL32 relocations. for (auto *ref : _rel32Candidates) { - if (!isDynamic(ref->target()) || hasPLTEntry(ref->target())) + bool forceRel = isLocal(ref->target()) && _ctx.getOutputELFType() == ET_DYN; + if (!forceRel && (!isDynamic(ref->target()) || hasPLTEntry(ref->target()))) continue; ref->setKindValue(R_MIPS_REL32); if (ELFT::Is64Bits) @@ -817,10 +818,10 @@ RelocationPass<ELFT>::collectReferenceInfo(const MipsELFDefinedAtom<ELFT> &atom, if (!isConstrainSym(atom, refKind)) return std::error_code(); - if (mightBeDynamic(atom, refKind)) - _rel32Candidates.push_back(&ref); - else + if (!mightBeDynamic(atom, refKind)) _hasStaticRelocations.insert(ref.target()); + else if (refKind == R_MIPS_32 || refKind == R_MIPS_64) + _rel32Candidates.push_back(&ref); if (!isBranchReloc(refKind) && !isAllCallReloc(refKind) && refKind != R_MIPS_EH) diff --git a/lld/test/elf/Mips/rel-dynamic-15.test b/lld/test/elf/Mips/rel-dynamic-15.test new file mode 100644 index 00000000000..8bd486f0127 --- /dev/null +++ b/lld/test/elf/Mips/rel-dynamic-15.test @@ -0,0 +1,81 @@ +# Check that LLD generates dynamic relocation R_MIPS_REL32 for local +# symbols if the symbols referenced by R_MIPS_32 relocation. + +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t.o +# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=RAW %s +# RUN: llvm-readobj -r %t.so | FileCheck -check-prefix=REL %s + +# RAW: Contents of section .text: +# RAW-NEXT: 0120 00000000 00000000 +# RAW: Contents of section .data.rel.local: +# RAW-NEXT: 2000 20010000 00000000 + +# REL: Relocations [ +# REL-NEXT: Section (4) .rel.dyn { +# REL-NEXT: 0x2000 R_MIPS_REL32 - 0x0 +# REL-NEXT: 0x2004 R_MIPS_REL32 T1 0x0 +# REL-NEXT: } +# REL-NEXT: ] + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, + EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Size: 8 + + - Name: .data.rel.local + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 4 + Size: 8 + + - Name: .rel.data.rel.local + Type: SHT_REL + Link: .symtab + AddressAlign: 4 + Info: .data.rel.local + Relocations: + - Offset: 0 + Symbol: .text + Type: R_MIPS_32 + - Offset: 4 + Symbol: T1 + Type: R_MIPS_32 + +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: T0 + Type: STT_FUNC + Section: .text + Value: 0 + Size: 4 + - Name: .data.rel.local + Type: STT_SECTION + Section: .data.rel.local + + Global: + - Name: D0 + Type: STT_OBJECT + Section: .data.rel.local + Value: 0 + Size: 8 + - Name: T1 + Type: STT_FUNC + Section: .text + Value: 4 + Size: 4 +... |

