[Mips] Fix addend writing for R_MIPS_REL32 relocation

llvm-svn: 242760
This commit is contained in:
Simon Atanasyan 2015-07-21 05:54:30 +00:00
parent f9db71eaec
commit b1600f2eee
3 changed files with 101 additions and 11 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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
...