diff options
| author | Simon Atanasyan <simon@atanasyan.com> | 2015-07-21 05:54:30 +0000 |
|---|---|---|
| committer | Simon Atanasyan <simon@atanasyan.com> | 2015-07-21 05:54:30 +0000 |
| commit | b1600f2eeef217506839c60b6e47c579e73ad352 (patch) | |
| tree | 75e4ea0c93299152613a7eb37cb0d428613933f0 /lld/lib/ReaderWriter/ELF | |
| parent | f9db71eaec623d4e50f0efe6dc327388f70d8de3 (diff) | |
| download | bcm5719-llvm-b1600f2eeef217506839c60b6e47c579e73ad352.tar.gz bcm5719-llvm-b1600f2eeef217506839c60b6e47c579e73ad352.zip | |
[Mips] Fix addend writing for R_MIPS_REL32 relocation
llvm-svn: 242760
Diffstat (limited to 'lld/lib/ReaderWriter/ELF')
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp | 22 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp | 9 |
2 files changed, 20 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) |

