forked from OSchip/llvm-project
[Mips] Implement .plt and .got.plt section creation.
llvm-svn: 199516
This commit is contained in:
parent
66338224be
commit
362bdc125e
|
@ -56,3 +56,16 @@ void MipsLinkingContext::addPasses(PassManager &pm) {
|
|||
pm.add(std::move(pass));
|
||||
ELFLinkingContext::addPasses(pm);
|
||||
}
|
||||
|
||||
bool MipsLinkingContext::isPLTRelocation(const DefinedAtom &,
|
||||
const Reference &r) const {
|
||||
if (r.kindNamespace() != Reference::KindNamespace::ELF)
|
||||
return false;
|
||||
assert(r.kindArch() == Reference::KindArch::Mips);
|
||||
switch (r.kindValue()) {
|
||||
case llvm::ELF::R_MIPS_JUMP_SLOT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,11 @@ enum {
|
|||
/// \brief The same as R_MIPS_GOT16 but for global symbols.
|
||||
LLD_R_MIPS_GLOBAL_GOT16 = 1025,
|
||||
/// \brief The same as R_MIPS_26 but for global symbols.
|
||||
LLD_R_MIPS_GLOBAL_26 = 1026
|
||||
LLD_R_MIPS_GLOBAL_26 = 1026,
|
||||
/// \brief Setup hi 16 bits using the symbol this reference refers to.
|
||||
LLD_R_MIPS_HI16 = 1027,
|
||||
/// \brief Setup low 16 bits using the symbol this reference refers to.
|
||||
LLD_R_MIPS_LO16 = 1028
|
||||
};
|
||||
|
||||
typedef llvm::object::ELFType<llvm::support::little, 2, false> Mips32ElELFType;
|
||||
|
@ -41,6 +45,7 @@ public:
|
|||
virtual StringRef entrySymbolName() const;
|
||||
virtual StringRef getDefaultInterpreter() const;
|
||||
virtual void addPasses(PassManager &pm);
|
||||
virtual bool isPLTRelocation(const DefinedAtom &, const Reference &r) const;
|
||||
};
|
||||
|
||||
} // elf
|
||||
|
|
|
@ -105,6 +105,18 @@ void relocCall16(uint8_t *location, uint64_t P, uint64_t S, int64_t A,
|
|||
applyReloc(location, result);
|
||||
}
|
||||
|
||||
/// \brief LLD_R_MIPS_HI16
|
||||
void relocLldHi16(uint8_t *location, uint64_t S) {
|
||||
int32_t result = lld::scatterBits<uint32_t>((S + 0x8000) >> 16, 0xffff);
|
||||
applyReloc(location, result);
|
||||
}
|
||||
|
||||
/// \brief LLD_R_MIPS_LO16
|
||||
void relocLldLo16(uint8_t *location, uint64_t S) {
|
||||
int32_t result = lld::scatterBits<uint32_t>(S, 0xffff);
|
||||
applyReloc(location, result);
|
||||
}
|
||||
|
||||
} // end anon namespace
|
||||
|
||||
MipsTargetRelocationHandler::MipsTargetRelocationHandler(
|
||||
|
@ -200,6 +212,9 @@ error_code MipsTargetRelocationHandler::applyRelocation(
|
|||
case R_MIPS_JALR:
|
||||
// We do not do JALR optimization now.
|
||||
break;
|
||||
case R_MIPS_JUMP_SLOT:
|
||||
// Ignore runtime relocations.
|
||||
break;
|
||||
case LLD_R_MIPS_GLOBAL_GOT:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
@ -210,6 +225,12 @@ error_code MipsTargetRelocationHandler::applyRelocation(
|
|||
case LLD_R_MIPS_GLOBAL_26:
|
||||
reloc26(location, relocVAddress, targetVAddress, false);
|
||||
break;
|
||||
case LLD_R_MIPS_HI16:
|
||||
relocLldHi16(location, targetVAddress);
|
||||
break;
|
||||
case LLD_R_MIPS_LO16:
|
||||
relocLldLo16(location, targetVAddress);
|
||||
break;
|
||||
default: {
|
||||
std::string str;
|
||||
llvm::raw_string_ostream s(str);
|
||||
|
|
|
@ -24,6 +24,26 @@ const uint8_t mipsGot0AtomContent[] = { 0x00, 0x00, 0x00, 0x00 };
|
|||
// Module pointer
|
||||
const uint8_t mipsGotModulePointerAtomContent[] = { 0x00, 0x00, 0x00, 0x80 };
|
||||
|
||||
// PLT0 entry
|
||||
const uint8_t mipsPlt0AtomContent[] = {
|
||||
0x00, 0x00, 0x1c, 0x3c, // lui $28, %hi(&GOTPLT[0])
|
||||
0x00, 0x00, 0x99, 0x8f, // lw $25, %lo(&GOTPLT[0])($28)
|
||||
0x00, 0x00, 0x9c, 0x27, // addiu $28, $28, %lo(&GOTPLT[0])
|
||||
0x23, 0xc0, 0x1c, 0x03, // subu $24, $24, $28
|
||||
0x21, 0x78, 0xe0, 0x03, // move $15, $31
|
||||
0x82, 0xc0, 0x18, 0x00, // srl $24, $24, 2
|
||||
0x09, 0xf8, 0x20, 0x03, // jalr $25
|
||||
0xfe, 0xff, 0x18, 0x27 // subu $24, $24, 2
|
||||
};
|
||||
|
||||
// Regular PLT entry
|
||||
const uint8_t mipsPltAAtomContent[] = {
|
||||
0x00, 0x00, 0x0f, 0x3c, // lui $15, %hi(.got.plt entry)
|
||||
0x00, 0x00, 0xf9, 0x8d, // l[wd] $25, %lo(.got.plt entry)($15)
|
||||
0x08, 0x00, 0x20, 0x03, // jr $25
|
||||
0x00, 0x00, 0xf8, 0x25 // addiu $24, $15, %lo(.got.plt entry)
|
||||
};
|
||||
|
||||
/// \brief Abstract base class represent MIPS GOT entries.
|
||||
class MipsGOTAtom : public GOTAtom {
|
||||
public:
|
||||
|
@ -52,6 +72,36 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class PLT0Atom : public PLTAtom {
|
||||
public:
|
||||
PLT0Atom(const File &f) : PLTAtom(f, ".plt") {}
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return llvm::makeArrayRef(mipsPlt0AtomContent);
|
||||
}
|
||||
};
|
||||
|
||||
class PLTAAtom : public PLTAtom {
|
||||
public:
|
||||
PLTAAtom(const File &f) : PLTAtom(f, ".plt") {}
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return llvm::makeArrayRef(mipsPltAAtomContent);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief MIPS GOT PLT entry
|
||||
class GOTPLTAtom : public GOTAtom {
|
||||
public:
|
||||
GOTPLTAtom(const File &f) : GOTAtom(f, ".got.plt") {}
|
||||
|
||||
virtual Alignment alignment() const { return Alignment(2); }
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return llvm::makeArrayRef(mipsGot0AtomContent);
|
||||
}
|
||||
};
|
||||
|
||||
class RelocationPassFile : public SimpleFile {
|
||||
public:
|
||||
RelocationPassFile(const ELFLinkingContext &ctx)
|
||||
|
@ -90,6 +140,20 @@ public:
|
|||
got->setOrdinal(ordinal++);
|
||||
mf->addAtom(*got);
|
||||
}
|
||||
|
||||
for (auto &plt : _pltVector) {
|
||||
DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ PLT ] Adding "
|
||||
<< plt->name() << "\n");
|
||||
plt->setOrdinal(ordinal++);
|
||||
mf->addAtom(*plt);
|
||||
}
|
||||
|
||||
for (auto &gotplt : _gotpltVector) {
|
||||
DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ GOTPLT ] Adding "
|
||||
<< gotplt->name() << "\n");
|
||||
gotplt->setOrdinal(ordinal++);
|
||||
mf->addAtom(*gotplt);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -105,6 +169,15 @@ private:
|
|||
/// \brief the list of global GOT atoms.
|
||||
std::vector<GOTAtom *> _globalGotVector;
|
||||
|
||||
/// \brief Map Atoms to their PLT entries.
|
||||
llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
|
||||
|
||||
/// \brief the list of PLT atoms.
|
||||
std::vector<PLTAtom *> _pltVector;
|
||||
|
||||
/// \brief the list of GOTPLT atoms.
|
||||
std::vector<GOTAtom *> _gotpltVector;
|
||||
|
||||
/// \brief Handle a specific reference.
|
||||
void handleReference(const DefinedAtom &atom, const Reference &ref) {
|
||||
if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
|
||||
|
@ -131,7 +204,8 @@ private:
|
|||
if (ref.kindValue() == R_MIPS_26 && !isLocal(ref.target()))
|
||||
const_cast<Reference &>(ref).setKindValue(LLD_R_MIPS_GLOBAL_26);
|
||||
|
||||
// FIXME (simon): Create PLT entry.
|
||||
if (isa<SharedLibraryAtom>(ref.target()))
|
||||
const_cast<Reference &>(ref).setTarget(getPLTEntry(ref.target()));
|
||||
}
|
||||
|
||||
void handleGOT(const Reference &ref) {
|
||||
|
@ -187,6 +261,69 @@ private:
|
|||
|
||||
return ga;
|
||||
}
|
||||
|
||||
void createPLTHeader() {
|
||||
assert(_pltVector.empty() && _gotpltVector.empty());
|
||||
|
||||
auto pa = new (_file._alloc) PLT0Atom(_file);
|
||||
_pltVector.push_back(pa);
|
||||
|
||||
auto ga0 = new (_file._alloc) GOTPLTAtom(_file);
|
||||
_gotpltVector.push_back(ga0);
|
||||
auto ga1 = new (_file._alloc) GOTPLTAtom(_file);
|
||||
_gotpltVector.push_back(ga1);
|
||||
|
||||
// Setup reference to fixup the PLT0 entry.
|
||||
pa->addReferenceELF_Mips(LLD_R_MIPS_HI16, 0, ga0, 0);
|
||||
pa->addReferenceELF_Mips(LLD_R_MIPS_LO16, 4, ga0, 0);
|
||||
pa->addReferenceELF_Mips(LLD_R_MIPS_LO16, 8, ga0, 0);
|
||||
|
||||
DEBUG_WITH_TYPE("MipsGOT", {
|
||||
pa->_name = "__plt0";
|
||||
llvm::dbgs() << "[ PLT ] Create PLT0\n";
|
||||
ga0->_name = "__gotplt0";
|
||||
llvm::dbgs() << "[ GOTPLT ] Create GOTPLT0\n";
|
||||
ga1->_name = "__gotplt1";
|
||||
llvm::dbgs() << "[ GOTPLT ] Create GOTPLT1\n";
|
||||
});
|
||||
}
|
||||
|
||||
const PLTAtom *getPLTEntry(const Atom *a) {
|
||||
auto plt = _pltMap.find(a);
|
||||
if (plt != _pltMap.end())
|
||||
return plt->second;
|
||||
|
||||
if (_pltVector.empty())
|
||||
createPLTHeader();
|
||||
|
||||
auto pa = new (_file._alloc) PLTAAtom(_file);
|
||||
_pltMap[a] = pa;
|
||||
_pltVector.push_back(pa);
|
||||
|
||||
auto ga = new (_file._alloc) GOTPLTAtom(_file);
|
||||
_gotpltVector.push_back(ga);
|
||||
|
||||
// Setup reference to fixup the PLT entry.
|
||||
pa->addReferenceELF_Mips(LLD_R_MIPS_HI16, 0, ga, 0);
|
||||
pa->addReferenceELF_Mips(LLD_R_MIPS_LO16, 4, ga, 0);
|
||||
pa->addReferenceELF_Mips(LLD_R_MIPS_LO16, 12, ga, 0);
|
||||
|
||||
// Setup reference to assign initial value to the .got.plt entry.
|
||||
ga->addReferenceELF_Mips(R_MIPS_32, 0, _pltVector.front(), 0);
|
||||
// Create dynamic relocation to adjust the .got.plt entry at runtime.
|
||||
ga->addReferenceELF_Mips(R_MIPS_JUMP_SLOT, 0, a, 0);
|
||||
|
||||
DEBUG_WITH_TYPE("MipsGOT", {
|
||||
pa->_name = "__plt_";
|
||||
pa->_name += a->name();
|
||||
llvm::dbgs() << "[ PLT ] Create " << a->name() << "\n";
|
||||
ga->_name = "__got_plt_";
|
||||
ga->_name += a->name();
|
||||
llvm::dbgs() << "[ GOTPLT ] Create " << a->name() << "\n";
|
||||
});
|
||||
|
||||
return pa;
|
||||
}
|
||||
};
|
||||
|
||||
} // end anon namespace
|
||||
|
|
|
@ -201,8 +201,11 @@ const Registry::KindStrings MipsTargetHandler::kindStrings[] = {
|
|||
LLD_KIND_STRING_ENTRY(R_MIPS_GOT16),
|
||||
LLD_KIND_STRING_ENTRY(R_MIPS_CALL16),
|
||||
LLD_KIND_STRING_ENTRY(R_MIPS_JALR),
|
||||
LLD_KIND_STRING_ENTRY(R_MIPS_JUMP_SLOT),
|
||||
LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT),
|
||||
LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT16),
|
||||
LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_26),
|
||||
LLD_KIND_STRING_ENTRY(LLD_R_MIPS_HI16),
|
||||
LLD_KIND_STRING_ENTRY(LLD_R_MIPS_LO16),
|
||||
LLD_KIND_STRING_END
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
createSection(StringRef name, int32_t type,
|
||||
DefinedAtom::ContentPermissions permissions,
|
||||
Layout::SectionOrder order) {
|
||||
if (type == DefinedAtom::typeGOT)
|
||||
if (type == DefinedAtom::typeGOT && name == ".got")
|
||||
return _gotSection;
|
||||
return DefaultLayout<ELFType>::createSection(name, type, permissions,
|
||||
order);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# Check initialization of .plt header entries.
|
||||
|
||||
# Build shared library
|
||||
# RUN: llvm-mc -triple=mipsel -filetype=obj -relocation-model=pic \
|
||||
# RUN: -o=%t1 %p/Inputs/ext.s
|
||||
# RUN: lld -flavor gnu -target mipsel -shared -o %t2 %t1
|
||||
|
||||
# Build executable
|
||||
# RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t3 %s
|
||||
# RUN: lld -flavor gnu -target mipsel -e glob -o %t4 %t3 %t2
|
||||
# RUN: llvm-objdump -section-headers -disassemble %t4 | \
|
||||
# RUN: FileCheck -check-prefix=EXE %s
|
||||
|
||||
# EXE: Disassembly of section .plt:
|
||||
# EXE: .plt:
|
||||
# PLT0 entry. Points to the .got.plt[0]
|
||||
# EXE: 400170: 40 00 1c 3c lui $gp, 64
|
||||
# EXE: 400174: 00 20 99 8f lw $25, 8192($gp)
|
||||
# EXE: 400178: 00 20 9c 27 addiu $gp, $gp, 8192
|
||||
# EXE: 40017c: 23 c0 1c 03 subu $24, $24, $gp
|
||||
# EXE: 400180: 21 78 e0 03 move $15, $ra
|
||||
# EXE: 400184: 82 c0 18 00 srl $24, $24, 2
|
||||
# EXE: 400188: 09 f8 20 03 jalr $25
|
||||
# EXE: 40018c: fe ff 18 27 addiu $24, $24, -2
|
||||
|
||||
# EXE: Sections:
|
||||
# EXE: Idx Name Size Address Type
|
||||
# EXE: 6 .plt 00000030 0000000000400170 TEXT DATA
|
||||
# EXE: 10 .got.plt 0000000c 0000000000402000 DATA
|
||||
|
||||
.abicalls
|
||||
.global glob
|
||||
.ent glob
|
||||
glob:
|
||||
jal $t9
|
||||
jal loc
|
||||
loc:
|
||||
jal glob
|
||||
jal ext1
|
||||
.end glob
|
|
@ -7,33 +7,58 @@
|
|||
|
||||
# Build executable
|
||||
# RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t3 %s
|
||||
# RUN: llvm-objdump -r %t3 | FileCheck -check-prefix=REL %s
|
||||
# RUN: llvm-readobj -relocations %t3 | FileCheck -check-prefix=OBJ-REL %s
|
||||
# RUN: lld -flavor gnu -target mipsel -e glob -o %t4 %t3 %t2
|
||||
# RUN: llvm-objdump -disassemble %t4 | FileCheck -check-prefix=EXE %s
|
||||
# RUN: llvm-objdump -section-headers -disassemble %t4 | \
|
||||
# RUN: FileCheck -check-prefix=EXE %s
|
||||
# RUN: llvm-readobj -relocations %t4 | FileCheck -check-prefix=EXE-REL %s
|
||||
|
||||
# Object file has three R_MIPS_26 relocations
|
||||
# REL: RELOCATION RECORDS FOR [.rel.text]:
|
||||
# REL: 8 R_MIPS_26 Unknown
|
||||
# REL: 16 R_MIPS_26 Unknown
|
||||
# REL: 24 R_MIPS_26 Unknown
|
||||
# OBJ-REL: Relocations [
|
||||
# OBJ-REL: Section (2) .rel.text {
|
||||
# OBJ-REL: 0x8 R_MIPS_26 .text 0x0
|
||||
# OBJ-REL: 0x10 R_MIPS_26 glob 0x0
|
||||
# OBJ-REL: 0x18 R_MIPS_26 ext1 0x0
|
||||
# OBJ-REL: }
|
||||
# OBJ-REL: ]
|
||||
|
||||
# Executable file has the only relocation for external symbol
|
||||
# EXE-REL: Relocations [
|
||||
# EXE-REL: Section (5) .rela.plt {
|
||||
# EXE-REL: 0x402008 R_MIPS_JUMP_SLOT ext1 0x0
|
||||
# EXE-REL: }
|
||||
# EXE-REL: ]
|
||||
|
||||
# EXE: Disassembly of section .plt:
|
||||
# EXE: .plt:
|
||||
# PLTA entry. Points to the .got.plt[1]
|
||||
# EXE: 400190: 40 00 0f 3c lui $15, 64
|
||||
# EXE: 400194: 08 20 f9 8d lw $25, 8200($15)
|
||||
# EXE: 400198: 08 00 20 03 jr $25
|
||||
# EXE: 40019c: 08 20 f8 25 addiu $24, $15, 8200
|
||||
|
||||
# EXE: Disassembly of section .text:
|
||||
# EXE: glob:
|
||||
# EXE: 40014c: 09 f8 20 03 jalr $25
|
||||
# EXE: 400150: 00 00 00 00 nop
|
||||
# EXE: 4001a0: 09 f8 20 03 jalr $25
|
||||
# EXE: 4001a4: 00 00 00 00 nop
|
||||
#
|
||||
# Jump to 'loc' label address
|
||||
# EXE: 400154: 57 00 10 0c jal 4194652
|
||||
# EXE: 400158: 00 00 00 00 nop
|
||||
# EXE: 4001a8: 6c 00 10 0c jal 4194736
|
||||
# EXE: 4001ac: 00 00 00 00 nop
|
||||
#
|
||||
# EXE: loc:
|
||||
# Jump to 'glob' label address
|
||||
# EXE: 40015c: 53 00 10 0c jal 4194636
|
||||
# EXE: 400160: 00 00 00 00 nop
|
||||
# EXE: 4001b0: 68 00 10 0c jal 4194720
|
||||
# EXE: 4001b4: 00 00 00 00 nop
|
||||
#
|
||||
# Jump to the first PLT entry (.plt + 32) for ext1 entry
|
||||
# EXE: 400164: 00 00 00 0c jal 0
|
||||
# EXE: 400168: 00 00 00 00 nop
|
||||
# EXE: 4001b8: 64 00 10 0c jal 4194704
|
||||
# EXE: 4001bc: 00 00 00 00 nop
|
||||
|
||||
# EXE: Sections:
|
||||
# EXE: Idx Name Size Address Type
|
||||
# EXE: 6 .plt 00000030 0000000000400170 TEXT DATA
|
||||
# EXE: 10 .got.plt 0000000c 0000000000402000 DATA
|
||||
|
||||
.abicalls
|
||||
.global glob
|
||||
|
|
Loading…
Reference in New Issue