[llvm-objdump] Add -R option

This option prints dynamic relocation entries of the given file

Differential Revision: https://reviews.llvm.org/D47493

llvm-svn: 334196
This commit is contained in:
Paul Semel 2018-06-07 13:30:55 +00:00
parent 01ef4c2c64
commit cb0f043cec
4 changed files with 114 additions and 19 deletions

View File

@ -15,6 +15,7 @@
#define LLVM_OBJECT_ELFOBJECTFILE_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
@ -83,6 +84,8 @@ public:
SubtargetFeatures getRISCVFeatures() const;
void setARMSubArch(Triple &TheTriple) const override;
virtual uint16_t getEType() const = 0;
};
class ELFSectionRef : public SectionRef {
@ -200,6 +203,7 @@ ELFObjectFileBase::symbols() const {
template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
uint16_t getEMachine() const override;
uint16_t getEType() const override;
uint64_t getSymbolSize(DataRefImpl Sym) const override;
public:
@ -256,6 +260,7 @@ protected:
bool isSectionVirtual(DataRefImpl Sec) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
std::vector<SectionRef> dynamic_relocation_sections() const override;
section_iterator getRelocatedSection(DataRefImpl Sec) const override;
void moveRelocationNext(DataRefImpl &Rel) const override;
@ -507,6 +512,10 @@ uint16_t ELFObjectFile<ELFT>::getEMachine() const {
return EF.getHeader()->e_machine;
}
template <class ELFT> uint16_t ELFObjectFile<ELFT>::getEType() const {
return EF.getHeader()->e_type;
}
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const {
return getSymbol(Sym)->st_size;
@ -711,6 +720,35 @@ bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const {
EShdr->sh_type == ELF::SHT_NOBITS;
}
template <class ELFT>
std::vector<SectionRef>
ELFObjectFile<ELFT>::dynamic_relocation_sections() const {
std::vector<SectionRef> Res;
std::vector<uintptr_t> Offsets;
auto SectionsOrErr = EF.sections();
if (!SectionsOrErr)
return Res;
for (const Elf_Shdr &Sec : *SectionsOrErr) {
if (Sec.sh_type != ELF::SHT_DYNAMIC)
continue;
Elf_Dyn *Dynamic =
reinterpret_cast<Elf_Dyn *>((uintptr_t)base() + Sec.sh_offset);
for (; Dynamic->d_tag != ELF::DT_NULL; Dynamic++) {
if (Dynamic->d_tag == ELF::DT_REL || Dynamic->d_tag == ELF::DT_RELA ||
Dynamic->d_tag == ELF::DT_JMPREL) {
Offsets.push_back(Dynamic->d_un.d_val);
}
}
}
for (const Elf_Shdr &Sec : *SectionsOrErr) {
if (is_contained(Offsets, Sec.sh_offset))
Res.emplace_back(toDRI(&Sec), this);
}
return Res;
}
template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const {
return getSection(Sec)->sh_type == ELF::SHT_NOBITS;
@ -792,8 +830,6 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
assert(EF.getHeader()->e_type == ELF::ET_REL &&
"Only relocatable object files have relocation offsets");
const Elf_Shdr *sec = getRelSection(Rel);
if (sec->sh_type == ELF::SHT_REL)
return getRel(Rel)->r_offset;

View File

@ -262,6 +262,10 @@ public:
return getCommonSymbolSizeImpl(Symb);
}
virtual std::vector<SectionRef> dynamic_relocation_sections() const {
return std::vector<SectionRef>();
}
using symbol_iterator_range = iterator_range<symbol_iterator>;
symbol_iterator_range symbols() const {
return symbol_iterator_range(symbol_begin(), symbol_end());

View File

@ -93,6 +93,13 @@ static StringSet<> DisasmFuncsSet;
cl::opt<bool>
llvm::Relocations("r", cl::desc("Display the relocation entries in the file"));
cl::opt<bool>
llvm::DynamicRelocations("dynamic-reloc",
cl::desc("Display the dynamic relocation entries in the file"));
static cl::alias
DynamicRelocationsd("R", cl::desc("Alias for --dynamic-reloc"),
cl::aliasopt(DynamicRelocations));
cl::opt<bool>
llvm::SectionContents("s", cl::desc("Display the content of each section"));
@ -431,6 +438,10 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
return errorToErrorCode(StrTabOrErr.takeError());
StringRef StrTab = *StrTabOrErr;
int64_t addend = 0;
// If there is no Symbol associated with the relocation, we set the undef
// boolean value to 'true'. This will prevent us from calling functions that
// requires the relocation to be associated with a symbol.
bool undef = false;
switch (Sec->sh_type) {
default:
return object_error::parse_failed;
@ -441,27 +452,31 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
case ELF::SHT_RELA: {
const Elf_Rela *ERela = Obj->getRela(Rel);
addend = ERela->r_addend;
undef = ERela->getSymbol(false) == 0;
break;
}
}
symbol_iterator SI = RelRef.getSymbol();
const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl());
StringRef Target;
if (symb->getType() == ELF::STT_SECTION) {
Expected<section_iterator> SymSI = SI->getSection();
if (!SymSI)
return errorToErrorCode(SymSI.takeError());
const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl());
auto SecName = EF.getSectionName(SymSec);
if (!SecName)
return errorToErrorCode(SecName.takeError());
Target = *SecName;
} else {
Expected<StringRef> SymName = symb->getName(StrTab);
if (!SymName)
return errorToErrorCode(SymName.takeError());
Target = *SymName;
}
if (!undef) {
symbol_iterator SI = RelRef.getSymbol();
const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl());
if (symb->getType() == ELF::STT_SECTION) {
Expected<section_iterator> SymSI = SI->getSection();
if (!SymSI)
return errorToErrorCode(SymSI.takeError());
const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl());
auto SecName = EF.getSectionName(SymSec);
if (!SecName)
return errorToErrorCode(SecName.takeError());
Target = *SecName;
} else {
Expected<StringRef> SymName = symb->getName(StrTab);
if (!SymName)
return errorToErrorCode(SymName.takeError());
Target = *SymName;
}
} else
Target = "*ABS*";
// Default scheme is to print Target, as well as "+ <addend>" for nonzero
// addend. Should be acceptable for all normal purposes.
@ -1727,6 +1742,41 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {
}
}
void llvm::PrintDynamicRelocations(const ObjectFile *Obj) {
// For the moment, this option is for ELF only
if (!Obj->isELF())
return;
const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj);
if (!Elf || Elf->getEType() != ELF::ET_DYN) {
error("not a dynamic object");
return;
}
StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
std::vector<SectionRef> DynRelSec = Obj->dynamic_relocation_sections();
if (DynRelSec.empty())
return;
outs() << "DYNAMIC RELOCATION RECORDS\n";
for (const SectionRef &Section : DynRelSec) {
if (Section.relocation_begin() == Section.relocation_end())
continue;
for (const RelocationRef &Reloc : Section.relocations()) {
uint64_t address = Reloc.getOffset();
SmallString<32> relocname;
SmallString<32> valuestr;
Reloc.getTypeName(relocname);
error(getRelocationValueString(Reloc, valuestr));
outs() << format(Fmt.data(), address) << " " << relocname << " "
<< valuestr << "\n";
}
}
}
void llvm::PrintSectionHeaders(const ObjectFile *Obj) {
outs() << "Sections:\n"
"Idx Name Size Address Type\n";
@ -2069,6 +2119,8 @@ static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {
DisassembleObject(o, Relocations);
if (Relocations && !Disassemble)
PrintRelocations(o);
if (DynamicRelocations)
PrintDynamicRelocations(o);
if (SectionHeaders)
PrintSectionHeaders(o);
if (SectionContents)
@ -2186,6 +2238,7 @@ int main(int argc, char **argv) {
Disassemble = true;
if (!Disassemble
&& !Relocations
&& !DynamicRelocations
&& !SectionHeaders
&& !SectionContents
&& !SymbolTable

View File

@ -56,6 +56,7 @@ extern cl::opt<bool> ObjcMetaData;
extern cl::opt<std::string> DisSymName;
extern cl::opt<bool> NonVerbose;
extern cl::opt<bool> Relocations;
extern cl::opt<bool> DynamicRelocations;
extern cl::opt<bool> SectionHeaders;
extern cl::opt<bool> SectionContents;
extern cl::opt<bool> SymbolTable;
@ -88,6 +89,7 @@ void printLazyBindTable(object::ObjectFile *o);
void printWeakBindTable(object::ObjectFile *o);
void printRawClangAST(const object::ObjectFile *o);
void PrintRelocations(const object::ObjectFile *o);
void PrintDynamicRelocations(const object::ObjectFile *o);
void PrintSectionHeaders(const object::ObjectFile *o);
void PrintSectionContents(const object::ObjectFile *o);
void PrintSymbolTable(const object::ObjectFile *o, StringRef ArchiveName,