summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF
diff options
context:
space:
mode:
authorSimon Atanasyan <simon@atanasyan.com>2015-07-21 05:54:30 +0000
committerSimon Atanasyan <simon@atanasyan.com>2015-07-21 05:54:30 +0000
commitb1600f2eeef217506839c60b6e47c579e73ad352 (patch)
tree75e4ea0c93299152613a7eb37cb0d428613933f0 /lld/lib/ReaderWriter/ELF
parentf9db71eaec623d4e50f0efe6dc327388f70d8de3 (diff)
downloadbcm5719-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.cpp22
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp9
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)
OpenPOWER on IntegriCloud