mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 13:50:11 +00:00
[Mips] Fix addend writing for R_MIPS_REL32 relocation
llvm-svn: 242760
This commit is contained in:
parent
f9db71eaec
commit
b1600f2eee
@ -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.
|
||||
|
@ -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)
|
||||
|
81
lld/test/elf/Mips/rel-dynamic-15.test
Normal file
81
lld/test/elf/Mips/rel-dynamic-15.test
Normal 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
|
||||
...
|
Loading…
Reference in New Issue
Block a user