forked from OSchip/llvm-project
[ELF] Customize a relocation table output format (rel / rela).
Add new virtual virtual function `isRelaOutputFormat` to the `ELFLinkingContext` class. Call this function everywhere we need to select a relocation table format. Patch reviewed by Shankar Easwaran and Rui Ueyama. llvm-svn: 199973
This commit is contained in:
parent
4d97536ad0
commit
d8cadd6f17
|
@ -93,6 +93,9 @@ public:
|
|||
|
||||
static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
|
||||
|
||||
/// \brief Use Elf_Rela format to output relocation tables.
|
||||
virtual bool isRelaOutputFormat() const { return true; }
|
||||
|
||||
/// \brief Does this relocation belong in the dynamic plt relocation table?
|
||||
///
|
||||
/// This table holds all of the relocations used for delayed symbol binding.
|
||||
|
|
|
@ -270,7 +270,8 @@ public:
|
|||
RelocationTable<ELFT> *getDynamicRelocationTable() {
|
||||
if (!_dynamicRelocationTable) {
|
||||
_dynamicRelocationTable.reset(new (_allocator) RelocationTable<ELFT>(
|
||||
_context, ".rela.dyn", ORDER_DYNAMIC_RELOCS));
|
||||
_context, _context.isRelaOutputFormat() ? ".rela.dyn" : ".rel.dyn",
|
||||
ORDER_DYNAMIC_RELOCS));
|
||||
addSection(_dynamicRelocationTable.get());
|
||||
}
|
||||
return _dynamicRelocationTable.get();
|
||||
|
@ -280,7 +281,8 @@ public:
|
|||
RelocationTable<ELFT> *getPLTRelocationTable() {
|
||||
if (!_pltRelocationTable) {
|
||||
_pltRelocationTable.reset(new (_allocator) RelocationTable<ELFT>(
|
||||
_context, ".rela.plt", ORDER_DYNAMIC_PLT_RELOCS));
|
||||
_context, _context.isRelaOutputFormat() ? ".rela.plt" : ".rel.plt",
|
||||
ORDER_DYNAMIC_PLT_RELOCS));
|
||||
addSection(_pltRelocationTable.get());
|
||||
}
|
||||
return _pltRelocationTable.get();
|
||||
|
|
|
@ -55,8 +55,13 @@ void ExecutableWriter<ELFT>::addDefaultAtoms() {
|
|||
_runtimeFile->addAbsoluteAtom("__preinit_array_end");
|
||||
_runtimeFile->addAbsoluteAtom("__init_array_start");
|
||||
_runtimeFile->addAbsoluteAtom("__init_array_end");
|
||||
_runtimeFile->addAbsoluteAtom("__rela_iplt_start");
|
||||
_runtimeFile->addAbsoluteAtom("__rela_iplt_end");
|
||||
if (this->_context.isRelaOutputFormat()) {
|
||||
_runtimeFile->addAbsoluteAtom("__rela_iplt_start");
|
||||
_runtimeFile->addAbsoluteAtom("__rela_iplt_end");
|
||||
} else {
|
||||
_runtimeFile->addAbsoluteAtom("__rel_iplt_start");
|
||||
_runtimeFile->addAbsoluteAtom("__rel_iplt_end");
|
||||
}
|
||||
_runtimeFile->addAbsoluteAtom("__fini_array_start");
|
||||
_runtimeFile->addAbsoluteAtom("__fini_array_end");
|
||||
}
|
||||
|
@ -111,7 +116,10 @@ template <class ELFT> void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
|
|||
|
||||
startEnd("preinit_array", ".preinit_array");
|
||||
startEnd("init_array", ".init_array");
|
||||
startEnd("rela_iplt", ".rela.plt");
|
||||
if (this->_context.isRelaOutputFormat())
|
||||
startEnd("rela_iplt", ".rela.plt");
|
||||
else
|
||||
startEnd("rel_iplt", ".rel.plt");
|
||||
startEnd("fini_array", ".fini_array");
|
||||
|
||||
assert(!(bssStartAtomIter == this->_layout->absoluteAtoms().end() ||
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
virtual StringRef entrySymbolName() const;
|
||||
virtual StringRef getDefaultInterpreter() const;
|
||||
virtual void addPasses(PassManager &pm);
|
||||
virtual bool isRelaOutputFormat() const { return false; }
|
||||
virtual bool isPLTRelocation(const DefinedAtom &, const Reference &r) const;
|
||||
};
|
||||
|
||||
|
|
|
@ -900,22 +900,29 @@ private:
|
|||
|
||||
template <class ELFT> class RelocationTable : public Section<ELFT> {
|
||||
public:
|
||||
typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
|
||||
typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
|
||||
|
||||
RelocationTable(const ELFLinkingContext &context, StringRef str,
|
||||
int32_t order)
|
||||
: Section<ELFT>(context, str), _symbolTable(nullptr) {
|
||||
this->setOrder(order);
|
||||
this->_entSize = sizeof(Elf_Rela);
|
||||
this->_align2 = llvm::alignOf<Elf_Rela>();
|
||||
this->_type = SHT_RELA;
|
||||
this->_flags = SHF_ALLOC;
|
||||
if (context.isRelaOutputFormat()) {
|
||||
this->_entSize = sizeof(Elf_Rela);
|
||||
this->_align2 = llvm::alignOf<Elf_Rela>();
|
||||
this->_type = SHT_RELA;
|
||||
} else {
|
||||
this->_entSize = sizeof(Elf_Rel);
|
||||
this->_align2 = llvm::alignOf<Elf_Rel>();
|
||||
this->_type = SHT_REL;
|
||||
}
|
||||
}
|
||||
|
||||
/// \returns the index of the relocation added.
|
||||
uint32_t addRelocation(const DefinedAtom &da, const Reference &r) {
|
||||
_relocs.emplace_back(&da, &r);
|
||||
this->_fsize = _relocs.size() * sizeof(Elf_Rela);
|
||||
this->_fsize = _relocs.size() * this->_entSize;
|
||||
this->_msize = this->_fsize;
|
||||
return _relocs.size() - 1;
|
||||
}
|
||||
|
@ -945,34 +952,52 @@ public:
|
|||
}
|
||||
|
||||
virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) {
|
||||
uint8_t *chunkBuffer = buffer.getBufferStart();
|
||||
uint8_t *dest = chunkBuffer + this->fileOffset();
|
||||
uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
|
||||
for (const auto &rel : _relocs) {
|
||||
Elf_Rela *r = reinterpret_cast<Elf_Rela *>(dest);
|
||||
uint32_t index =
|
||||
_symbolTable ? _symbolTable->getSymbolTableIndex(rel.second->target())
|
||||
: (uint32_t) STN_UNDEF;
|
||||
r->setSymbolAndType(index, rel.second->kindValue());
|
||||
r->r_offset =
|
||||
writer->addressOfAtom(rel.first) + rel.second->offsetInAtom();
|
||||
r->r_addend = 0;
|
||||
// The addend is used only by relative relocations
|
||||
if (this->_context.isRelativeReloc(*rel.second))
|
||||
r->r_addend =
|
||||
writer->addressOfAtom(rel.second->target()) + rel.second->addend();
|
||||
dest += sizeof(Elf_Rela);
|
||||
DEBUG_WITH_TYPE("ELFRelocationTable",
|
||||
llvm::dbgs() << rel.second->kindValue()
|
||||
<< " relocation at " << rel.first->name()
|
||||
<< "@" << r->r_offset << " to "
|
||||
<< rel.second->target()->name() << "@"
|
||||
<< r->r_addend << "\n";);
|
||||
if (this->_context.isRelaOutputFormat())
|
||||
writeRela(writer, *reinterpret_cast<Elf_Rela *>(dest), *rel.first,
|
||||
*rel.second);
|
||||
else
|
||||
writeRel(writer, *reinterpret_cast<Elf_Rel *>(dest), *rel.first,
|
||||
*rel.second);
|
||||
dest += this->_entSize;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<const DefinedAtom *, const Reference *> > _relocs;
|
||||
const DynamicSymbolTable<ELFT> *_symbolTable;
|
||||
|
||||
void writeRela(ELFWriter *writer, Elf_Rela &r, const DefinedAtom &atom,
|
||||
const Reference &ref) {
|
||||
uint32_t index =
|
||||
_symbolTable ? _symbolTable->getSymbolTableIndex(ref.target())
|
||||
: (uint32_t)STN_UNDEF;
|
||||
r.setSymbolAndType(index, ref.kindValue());
|
||||
r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
|
||||
r.r_addend = 0;
|
||||
// The addend is used only by relative relocations
|
||||
if (this->_context.isRelativeReloc(ref))
|
||||
r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend();
|
||||
DEBUG_WITH_TYPE("ELFRelocationTable",
|
||||
llvm::dbgs() << ref.kindValue() << " relocation at "
|
||||
<< atom.name() << "@" << r.r_offset << " to "
|
||||
<< ref.target()->name() << "@" << r.r_addend
|
||||
<< "\n";);
|
||||
}
|
||||
|
||||
void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom,
|
||||
const Reference &ref) {
|
||||
uint32_t index =
|
||||
_symbolTable ? _symbolTable->getSymbolTableIndex(ref.target())
|
||||
: (uint32_t)STN_UNDEF;
|
||||
r.setSymbolAndType(index, ref.kindValue());
|
||||
r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
|
||||
DEBUG_WITH_TYPE("ELFRelocationTable",
|
||||
llvm::dbgs() << ref.kindValue() << " relocation at "
|
||||
<< atom.name() << "@" << r.r_offset << " to "
|
||||
<< ref.target()->name() << "\n";);
|
||||
}
|
||||
};
|
||||
|
||||
template <class ELFT> class HashSection;
|
||||
|
@ -1017,6 +1042,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void createDefaultEntries() {
|
||||
bool isRela = this->_context.isRelaOutputFormat();
|
||||
|
||||
Elf_Dyn dyn;
|
||||
dyn.d_un.d_val = 0;
|
||||
|
||||
|
@ -1035,11 +1062,11 @@ public:
|
|||
dyn.d_tag = DT_FINI_ARRAYSZ;
|
||||
_dt_fini_arraysz = addEntry(dyn);
|
||||
if (_layout->hasDynamicRelocationTable()) {
|
||||
dyn.d_tag = DT_RELA;
|
||||
dyn.d_tag = isRela ? DT_RELA : DT_REL;
|
||||
_dt_rela = addEntry(dyn);
|
||||
dyn.d_tag = DT_RELASZ;
|
||||
dyn.d_tag = isRela ? DT_RELASZ : DT_RELSZ;
|
||||
_dt_relasz = addEntry(dyn);
|
||||
dyn.d_tag = DT_RELAENT;
|
||||
dyn.d_tag = isRela ? DT_RELAENT : DT_RELENT;
|
||||
_dt_relaent = addEntry(dyn);
|
||||
}
|
||||
if (_layout->hasPLTRelocationTable()) {
|
||||
|
@ -1048,7 +1075,7 @@ public:
|
|||
dyn.d_tag = DT_PLTGOT;
|
||||
_dt_pltgot = addEntry(dyn);
|
||||
dyn.d_tag = DT_PLTREL;
|
||||
dyn.d_un.d_val = DT_RELA;
|
||||
dyn.d_un.d_val = isRela ? DT_RELA : DT_REL;
|
||||
_dt_pltrel = addEntry(dyn);
|
||||
dyn.d_un.d_val = 0;
|
||||
dyn.d_tag = DT_JMPREL;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
# Check MIPS specific tags in the dynamic table in case executable linking.
|
||||
|
||||
# Build shared library
|
||||
# RUN: llvm-mc -triple=mipsel -filetype=obj -relocation-model=pic \
|
||||
# RUN: -o=%t-obj %p/Inputs/ext.s
|
||||
# RUN: lld -flavor gnu -target mipsel -shared -o %t-so %t-obj
|
||||
|
||||
# Build executable
|
||||
# RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t-obj %s
|
||||
# RUN: lld -flavor gnu -target mipsel -e glob -o %t-exe %t-obj %t-so
|
||||
# RUN: llvm-readobj -dynamic-table %t-exe | FileCheck %s
|
||||
|
||||
# CHECK: Format: ELF32-mips
|
||||
# CHECK: Arch: mipsel
|
||||
# CHECK: AddressSize: 32bit
|
||||
# CHECK: LoadName:
|
||||
# CHECK: DynamicSection [ (20 entries)
|
||||
# CHECK: Tag Type Name/Value
|
||||
# CHECK: 0x00000004 HASH 0x400110
|
||||
# CHECK: 0x00000005 STRTAB 0x400144
|
||||
# CHECK: 0x00000006 SYMTAB 0x400124
|
||||
# CHECK: 0x0000000A STRSZ 30 (bytes)
|
||||
# CHECK: 0x0000000B SYMENT 16 (bytes)
|
||||
# CHECK: 0x0000001A FINI_ARRAY 0x0
|
||||
# CHECK: 0x0000001C FINI_ARRAYSZ 0 (bytes)
|
||||
# CHECK: 0x00000002 PLTRELSZ 8 (bytes)
|
||||
# CHECK: 0x00000003 PLTGOT 0x402000
|
||||
# CHECK: 0x00000014 PLTREL REL
|
||||
# CHECK: 0x00000017 JMPREL 0x400162
|
||||
# CHECK: 0x70000001 MIPS_RLD_VERSION 1
|
||||
# CHECK: 0x70000005 MIPS_FLAGS 0x2
|
||||
# CHECK: 0x70000006 MIPS_BASE_ADDRESS 0x400000
|
||||
# CHECK: 0x7000000A MIPS_LOCAL_GOTNO 2
|
||||
# CHECK: 0x70000011 MIPS_SYMTABNO 2
|
||||
# CHECK: 0x70000013 MIPS_GOTSYM 0x2
|
||||
# CHECK: 0x00000001 NEEDED SharedLibrary (exe-dynamic.test.{{.*}})
|
||||
# CHECK: 0x00000000 NULL 0x0
|
||||
# CHECK: ]
|
||||
|
||||
.abicalls
|
||||
.global glob
|
||||
.ent glob
|
||||
loc:
|
||||
jal ext1
|
||||
glob:
|
||||
jal loc
|
||||
jal glob
|
||||
.end glob
|
|
@ -27,7 +27,7 @@
|
|||
# CHECK: Type: Executable (0x2)
|
||||
# CHECK: Machine: EM_MIPS (0x8)
|
||||
# CHECK: Version: 1
|
||||
# CHECK: Entry: 0x4001B0
|
||||
# CHECK: Entry: 0x4001A0
|
||||
# CHECK: ProgramHeaderOffset: 0x34
|
||||
# CHECK: SectionHeaderOffset: 0x2268
|
||||
# CHECK: Flags [ (0x70001005)
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
# Executable file has the only relocation for external symbol
|
||||
# EXE-REL: Relocations [
|
||||
# EXE-REL: Section (5) .rela.plt {
|
||||
# EXE-REL: Section (5) .rel.plt {
|
||||
# EXE-REL: 0x402008 R_MIPS_JUMP_SLOT ext1 0x0
|
||||
# EXE-REL: }
|
||||
# EXE-REL: ]
|
||||
|
@ -32,32 +32,32 @@
|
|||
# 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: 400180: 40 00 0f 3c lui $15, 64
|
||||
# EXE: 400184: 08 20 f9 8d lw $25, 8200($15)
|
||||
# EXE: 400188: 08 00 20 03 jr $25
|
||||
# EXE: 40018c: 08 20 f8 25 addiu $24, $15, 8200
|
||||
|
||||
# EXE: Disassembly of section .text:
|
||||
# EXE: glob:
|
||||
# EXE: 4001a0: 09 f8 20 03 jalr $25
|
||||
# EXE: 4001a4: 00 00 00 00 nop
|
||||
# EXE: 400190: 09 f8 20 03 jalr $25
|
||||
# EXE: 400194: 00 00 00 00 nop
|
||||
#
|
||||
# Jump to 'loc' label address
|
||||
# EXE: 4001a8: 6c 00 10 0c jal 4194736
|
||||
# EXE: 4001ac: 00 00 00 00 nop
|
||||
# EXE: 400198: 6c 00 10 0c jal 4194736
|
||||
# EXE: 40019c: 00 00 00 00 nop
|
||||
#
|
||||
# EXE: loc:
|
||||
# Jump to 'glob' label address
|
||||
# EXE: 4001b0: 68 00 10 0c jal 4194720
|
||||
# EXE: 4001b4: 00 00 00 00 nop
|
||||
# EXE: 4001a0: 64 00 10 0c jal 4194704
|
||||
# EXE: 4001a4: 00 00 00 00 nop
|
||||
#
|
||||
# Jump to the first PLT entry (.plt + 32) for ext1 entry
|
||||
# EXE: 4001b8: 64 00 10 0c jal 4194704
|
||||
# EXE: 4001bc: 00 00 00 00 nop
|
||||
# EXE: 4001a8: 60 00 10 0c jal 4194688
|
||||
# EXE: 4001ac: 00 00 00 00 nop
|
||||
|
||||
# EXE: Sections:
|
||||
# EXE: Idx Name Size Address Type
|
||||
# EXE: 6 .plt 00000030 0000000000400170 TEXT DATA
|
||||
# EXE: 6 .plt 00000030 0000000000400160 TEXT DATA
|
||||
# EXE: 10 .got.plt 0000000c 0000000000402000 DATA
|
||||
|
||||
.abicalls
|
||||
|
|
Loading…
Reference in New Issue