[llvm-readobj][ELF] New -mips-plt-got command line option to output

MIPS GOT section.

Patch reviewed by Rafael Espindola.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211150 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Simon Atanasyan 2014-06-18 08:47:09 +00:00
parent 02b4e6e7ab
commit 42469f61f5
6 changed files with 547 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,306 @@
RUN: llvm-readobj -mips-plt-got %p/Inputs/relocs.obj.elf-mips | \
RUN: FileCheck %s -check-prefix GOT-OBJ
RUN: llvm-readobj -mips-plt-got %p/Inputs/dynamic-table-exe.mips | \
RUN: FileCheck %s -check-prefix GOT-EXE
RUN: llvm-readobj -mips-plt-got %p/Inputs/dynamic-table-so.mips | \
RUN: FileCheck %s -check-prefix GOT-SO
RUN: llvm-readobj -mips-plt-got %p/Inputs/got-tls.so.elf-mips64el | \
RUN: FileCheck %s -check-prefix GOT-TLS
GOT-OBJ: Cannot find PLTGOT dynamic table tag.
GOT-EXE: Primary GOT {
GOT-EXE-NEXT: Canonical gp value: 0x418880
GOT-EXE-NEXT: Reserved entries [
GOT-EXE-NEXT: Entry {
GOT-EXE-NEXT: Address: 0x410890
GOT-EXE-NEXT: Access: -32752
GOT-EXE-NEXT: Initial: 0x0
GOT-EXE-NEXT: Purpose: Lazy resolver
GOT-EXE-NEXT: }
GOT-EXE-NEXT: Entry {
GOT-EXE-NEXT: Address: 0x410894
GOT-EXE-NEXT: Access: -32748
GOT-EXE-NEXT: Initial: 0x80000000
GOT-EXE-NEXT: Purpose: Module pointer (GNU extension)
GOT-EXE-NEXT: }
GOT-EXE-NEXT: ]
GOT-EXE-NEXT: Local entries [
GOT-EXE-NEXT: Entry {
GOT-EXE-NEXT: Address: 0x410898
GOT-EXE-NEXT: Access: -32744
GOT-EXE-NEXT: Initial: 0x400418
GOT-EXE-NEXT: }
GOT-EXE-NEXT: Entry {
GOT-EXE-NEXT: Address: 0x41089C
GOT-EXE-NEXT: Access: -32740
GOT-EXE-NEXT: Initial: 0x410840
GOT-EXE-NEXT: }
GOT-EXE-NEXT: Entry {
GOT-EXE-NEXT: Address: 0x4108A0
GOT-EXE-NEXT: Access: -32736
GOT-EXE-NEXT: Initial: 0x0
GOT-EXE-NEXT: }
GOT-EXE-NEXT: ]
GOT-EXE-NEXT: Global entries [
GOT-EXE-NEXT: Entry {
GOT-EXE-NEXT: Address: 0x4108A4
GOT-EXE-NEXT: Access: -32732
GOT-EXE-NEXT: Initial: 0x0
GOT-EXE-NEXT: Value: 0x0
GOT-EXE-NEXT: Type: Function (0x2)
GOT-EXE-NEXT: Section: Undefined (0x0)
GOT-EXE-NEXT: Name: __gmon_start__@ (1)
GOT-EXE-NEXT: }
GOT-EXE-NEXT: ]
GOT-EXE-NEXT: Number of TLS and multi-GOT entries: 0
GOT-EXE-NEXT: }
GOT-SO: Primary GOT {
GOT-SO-NEXT: Canonical gp value: 0x188D0
GOT-SO-NEXT: Reserved entries [
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x108E0
GOT-SO-NEXT: Access: -32752
GOT-SO-NEXT: Initial: 0x0
GOT-SO-NEXT: Purpose: Lazy resolver
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x108E4
GOT-SO-NEXT: Access: -32748
GOT-SO-NEXT: Initial: 0x80000000
GOT-SO-NEXT: Purpose: Module pointer (GNU extension)
GOT-SO-NEXT: }
GOT-SO-NEXT: ]
GOT-SO-NEXT: Local entries [
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x108E8
GOT-SO-NEXT: Access: -32744
GOT-SO-NEXT: Initial: 0x108E0
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x108EC
GOT-SO-NEXT: Access: -32740
GOT-SO-NEXT: Initial: 0x10000
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x108F0
GOT-SO-NEXT: Access: -32736
GOT-SO-NEXT: Initial: 0x10920
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x108F4
GOT-SO-NEXT: Access: -32732
GOT-SO-NEXT: Initial: 0x108CC
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x108F8
GOT-SO-NEXT: Access: -32728
GOT-SO-NEXT: Initial: 0x0
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x108FC
GOT-SO-NEXT: Access: -32724
GOT-SO-NEXT: Initial: 0x0
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x10900
GOT-SO-NEXT: Access: -32720
GOT-SO-NEXT: Initial: 0x0
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x10904
GOT-SO-NEXT: Access: -32716
GOT-SO-NEXT: Initial: 0x0
GOT-SO-NEXT: }
GOT-SO-NEXT: ]
GOT-SO-NEXT: Global entries [
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x10908
GOT-SO-NEXT: Access: -32712
GOT-SO-NEXT: Initial: 0x0
GOT-SO-NEXT: Value: 0x0
GOT-SO-NEXT: Type: None (0x0)
GOT-SO-NEXT: Section: Undefined (0x0)
GOT-SO-NEXT: Name: _ITM_registerTMCloneTable@ (87)
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x1090C
GOT-SO-NEXT: Access: -32708
GOT-SO-NEXT: Initial: 0x0
GOT-SO-NEXT: Value: 0x0
GOT-SO-NEXT: Type: None (0x0)
GOT-SO-NEXT: Section: Undefined (0x0)
GOT-SO-NEXT: Name: _Jv_RegisterClasses@ (128)
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x10910
GOT-SO-NEXT: Access: -32704
GOT-SO-NEXT: Initial: 0x0
GOT-SO-NEXT: Value: 0x0
GOT-SO-NEXT: Type: Function (0x2)
GOT-SO-NEXT: Section: Undefined (0x0)
GOT-SO-NEXT: Name: __gmon_start__@ (23)
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x10914
GOT-SO-NEXT: Access: -32700
GOT-SO-NEXT: Initial: 0x840
GOT-SO-NEXT: Value: 0x840
GOT-SO-NEXT: Type: Function (0x2)
GOT-SO-NEXT: Section: Undefined (0x0)
GOT-SO-NEXT: Name: puts@GLIBC_2.0 (162)
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x10918
GOT-SO-NEXT: Access: -32696
GOT-SO-NEXT: Initial: 0x0
GOT-SO-NEXT: Value: 0x0
GOT-SO-NEXT: Type: None (0x0)
GOT-SO-NEXT: Section: Undefined (0x0)
GOT-SO-NEXT: Name: _ITM_deregisterTMCloneTable@ (59)
GOT-SO-NEXT: }
GOT-SO-NEXT: Entry {
GOT-SO-NEXT: Address: 0x1091C
GOT-SO-NEXT: Access: -32692
GOT-SO-NEXT: Initial: 0x0
GOT-SO-NEXT: Value: 0x0
GOT-SO-NEXT: Type: Function (0x2)
GOT-SO-NEXT: Section: Undefined (0x0)
GOT-SO-NEXT: Name: __cxa_finalize@GLIBC_2.2 (113)
GOT-SO-NEXT: }
GOT-SO-NEXT: ]
GOT-SO-NEXT: Number of TLS and multi-GOT entries: 0
GOT-SO-NEXT: }
GOT-TLS: Primary GOT {
GOT-TLS-NEXT: Canonical gp value: 0x18BF0
GOT-TLS-NEXT: Reserved entries [
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C00
GOT-TLS-NEXT: Access: -32752
GOT-TLS-NEXT: Initial: 0x0
GOT-TLS-NEXT: Purpose: Lazy resolver
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C08
GOT-TLS-NEXT: Access: -32744
GOT-TLS-NEXT: Initial: 0x8000000000000000
GOT-TLS-NEXT: Purpose: Module pointer (GNU extension)
GOT-TLS-NEXT: }
GOT-TLS-NEXT: ]
GOT-TLS-NEXT: Local entries [
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C10
GOT-TLS-NEXT: Access: -32736
GOT-TLS-NEXT: Initial: 0x10000
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C18
GOT-TLS-NEXT: Access: -32728
GOT-TLS-NEXT: Initial: 0x10C00
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C20
GOT-TLS-NEXT: Access: -32720
GOT-TLS-NEXT: Initial: 0x10CB8
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C28
GOT-TLS-NEXT: Access: -32712
GOT-TLS-NEXT: Initial: 0x10BF0
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C30
GOT-TLS-NEXT: Access: -32704
GOT-TLS-NEXT: Initial: 0x0
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C38
GOT-TLS-NEXT: Access: -32696
GOT-TLS-NEXT: Initial: 0x948
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C40
GOT-TLS-NEXT: Access: -32688
GOT-TLS-NEXT: Initial: 0xA20
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C48
GOT-TLS-NEXT: Access: -32680
GOT-TLS-NEXT: Initial: 0xAF0
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C50
GOT-TLS-NEXT: Access: -32672
GOT-TLS-NEXT: Initial: 0x0
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C58
GOT-TLS-NEXT: Access: -32664
GOT-TLS-NEXT: Initial: 0x0
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C60
GOT-TLS-NEXT: Access: -32656
GOT-TLS-NEXT: Initial: 0x0
GOT-TLS-NEXT: }
GOT-TLS-NEXT: ]
GOT-TLS-NEXT: Global entries [
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C68
GOT-TLS-NEXT: Access: -32648
GOT-TLS-NEXT: Initial: 0x0
GOT-TLS-NEXT: Value: 0x0
GOT-TLS-NEXT: Type: None (0x0)
GOT-TLS-NEXT: Section: Undefined (0x0)
GOT-TLS-NEXT: Name: _ITM_registerTMCloneTable@ (78)
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C70
GOT-TLS-NEXT: Access: -32640
GOT-TLS-NEXT: Initial: 0x0
GOT-TLS-NEXT: Value: 0x0
GOT-TLS-NEXT: Type: None (0x0)
GOT-TLS-NEXT: Section: Undefined (0x0)
GOT-TLS-NEXT: Name: _Jv_RegisterClasses@ (119)
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C78
GOT-TLS-NEXT: Access: -32632
GOT-TLS-NEXT: Initial: 0x0
GOT-TLS-NEXT: Value: 0x0
GOT-TLS-NEXT: Type: Function (0x2)
GOT-TLS-NEXT: Section: Undefined (0x0)
GOT-TLS-NEXT: Name: __gmon_start__@ (23)
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C80
GOT-TLS-NEXT: Access: -32624
GOT-TLS-NEXT: Initial: 0xB60
GOT-TLS-NEXT: Value: 0xB60
GOT-TLS-NEXT: Type: Function (0x2)
GOT-TLS-NEXT: Section: Undefined (0x0)
GOT-TLS-NEXT: Name: __tls_get_addr@GLIBC_2.3 (150)
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C88
GOT-TLS-NEXT: Access: -32616
GOT-TLS-NEXT: Initial: 0x0
GOT-TLS-NEXT: Value: 0x0
GOT-TLS-NEXT: Type: None (0x0)
GOT-TLS-NEXT: Section: Undefined (0x0)
GOT-TLS-NEXT: Name: _ITM_deregisterTMCloneTable@ (50)
GOT-TLS-NEXT: }
GOT-TLS-NEXT: Entry {
GOT-TLS-NEXT: Address: 0x10C90
GOT-TLS-NEXT: Access: -32608
GOT-TLS-NEXT: Initial: 0x0
GOT-TLS-NEXT: Value: 0x0
GOT-TLS-NEXT: Type: Function (0x2)
GOT-TLS-NEXT: Section: Undefined (0x0)
GOT-TLS-NEXT: Name: __cxa_finalize@GLIBC_2.2 (104)
GOT-TLS-NEXT: }
GOT-TLS-NEXT: ]
GOT-TLS-NEXT: Number of TLS and multi-GOT entries: 4
GOT-TLS-NEXT: }

View File

@ -18,6 +18,7 @@
#include "Error.h"
#include "ObjDumper.h"
#include "StreamWriter.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Object/ELFObjectFile.h"
@ -54,6 +55,7 @@ public:
void printProgramHeaders() override;
void printAttributes() override;
void printMipsPLTGOT() override;
private:
typedef ELFFile<ELFT> ELFO;
@ -159,6 +161,15 @@ getSectionNameIndex(const ELFO &Obj, typename ELFO::Elf_Sym_Iter Symbol,
}
}
template <class ELFT>
static const typename ELFFile<ELFT>::Elf_Shdr *
findSectionByAddress(const ELFFile<ELFT> *Obj, uint64_t Addr) {
for (const auto &Shdr : Obj->sections())
if (Shdr.sh_addr == Addr)
return &Shdr;
return nullptr;
}
static const EnumEntry<unsigned> ElfClass[] = {
{ "None", ELF::ELFCLASSNONE },
{ "32-bit", ELF::ELFCLASS32 },
@ -1021,3 +1032,209 @@ void ELFDumper<ELFType<support::little, 2, false> >::printAttributes() {
}
}
namespace {
template <class ELFT> class MipsGOTParser {
public:
typedef object::ELFFile<ELFT> ObjectFile;
typedef typename ObjectFile::Elf_Shdr Elf_Shdr;
MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) : Obj(Obj), W(W) {}
void ParseGOT(const Elf_Shdr &GOTShdr);
private:
typedef typename ObjectFile::Elf_Sym_Iter Elf_Sym_Iter;
typedef typename ObjectFile::Elf_Addr GOTEntry;
typedef typename ObjectFile::template ELFEntityIterator<const GOTEntry>
GOTIter;
const ObjectFile *Obj;
StreamWriter &W;
std::size_t GetGOTTotal(ArrayRef<uint8_t> GOT) const;
GOTIter MakeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum);
bool getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym);
void printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It);
void printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It,
Elf_Sym_Iter Sym);
};
}
template <class ELFT>
void MipsGOTParser<ELFT>::ParseGOT(const Elf_Shdr &GOTShdr) {
// See "Global Offset Table" in Chapter 5 in the following document
// for detailed GOT description.
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
ErrorOr<ArrayRef<uint8_t>> GOT = Obj->getSectionContents(&GOTShdr);
if (!GOT) {
W.startLine() << "The .got section is empty.\n";
return;
}
uint64_t DtLocalGotNum;
uint64_t DtGotSym;
if (!getGOTTags(DtLocalGotNum, DtGotSym))
return;
if (DtLocalGotNum > GetGOTTotal(*GOT)) {
W.startLine() << "MIPS_LOCAL_GOTNO exceeds a number of GOT entries.\n";
return;
}
Elf_Sym_Iter DynSymBegin = Obj->begin_dynamic_symbols();
Elf_Sym_Iter DynSymEnd = Obj->end_dynamic_symbols();
std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
if (DtGotSym + 1 > DynSymTotal) {
W.startLine() << "MIPS_GOTSYM exceeds a number of dynamic symbols.\n";
return;
}
std::size_t GlobalGotNum = DynSymTotal - DtGotSym;
if (DtLocalGotNum + GlobalGotNum > GetGOTTotal(*GOT)) {
W.startLine() << "Number of global GOT entries exceeds the size of GOT.\n";
return;
}
GOTIter GotBegin = MakeGOTIter(*GOT, 0);
GOTIter GotLocalEnd = MakeGOTIter(*GOT, DtLocalGotNum);
GOTIter It = GotBegin;
DictScope GS(W, "Primary GOT");
W.printHex("Canonical gp value", GOTShdr.sh_addr + 0x7ff0);
{
ListScope RS(W, "Reserved entries");
{
DictScope D(W, "Entry");
printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
W.printString("Purpose", StringRef("Lazy resolver"));
}
if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) {
DictScope D(W, "Entry");
printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
}
}
{
ListScope LS(W, "Local entries");
for (; It != GotLocalEnd; ++It) {
DictScope D(W, "Entry");
printGotEntry(GOTShdr.sh_addr, GotBegin, It);
}
}
{
ListScope GS(W, "Global entries");
GOTIter GotGlobalEnd = MakeGOTIter(*GOT, DtLocalGotNum + GlobalGotNum);
Elf_Sym_Iter GotDynSym = DynSymBegin + DtGotSym;
for (; It != GotGlobalEnd; ++It) {
DictScope D(W, "Entry");
printGlobalGotEntry(GOTShdr.sh_addr, GotBegin, It, GotDynSym++);
}
}
std::size_t SpecGotNum = GetGOTTotal(*GOT) - DtLocalGotNum - GlobalGotNum;
W.printNumber("Number of TLS and multi-GOT entries", SpecGotNum);
}
template <class ELFT>
std::size_t MipsGOTParser<ELFT>::GetGOTTotal(ArrayRef<uint8_t> GOT) const {
return GOT.size() / sizeof(GOTEntry);
}
template <class ELFT>
typename MipsGOTParser<ELFT>::GOTIter
MipsGOTParser<ELFT>::MakeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum) {
const char *Data = reinterpret_cast<const char *>(GOT.data());
return GOTIter(sizeof(GOTEntry), Data + EntryNum * sizeof(GOTEntry));
}
template <class ELFT>
bool MipsGOTParser<ELFT>::getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym) {
bool FoundLocalGotNum = false;
bool FoundGotSym = false;
for (const auto &Entry : Obj->dynamic_table()) {
switch (Entry.getTag()) {
case ELF::DT_MIPS_LOCAL_GOTNO:
LocalGotNum = Entry.getVal();
FoundLocalGotNum = true;
break;
case ELF::DT_MIPS_GOTSYM:
GotSym = Entry.getVal();
FoundGotSym = true;
break;
}
}
if (!FoundLocalGotNum) {
W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n";
return false;
}
if (!FoundGotSym) {
W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n";
return false;
}
return true;
}
template <class ELFT>
void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr, GOTIter BeginIt,
GOTIter It) {
int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
W.printHex("Address", GotAddr + Offset);
W.printNumber("Access", Offset - 0x7ff0);
W.printHex("Initial", *It);
}
template <class ELFT>
void MipsGOTParser<ELFT>::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt,
GOTIter It, Elf_Sym_Iter Sym) {
printGotEntry(GotAddr, BeginIt, It);
W.printHex("Value", Sym->st_value);
W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
unsigned SectionIndex = 0;
StringRef SectionName;
getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
W.printHex("Section", SectionName, SectionIndex);
std::string FullSymbolName = getFullSymbolName(*Obj, Sym);
W.printNumber("Name", FullSymbolName, Sym->st_name);
}
template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
if (Obj->getHeader()->e_machine != EM_MIPS) {
W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n";
return;
}
llvm::Optional<uint64_t> DtPltGot;
for (const auto &Entry : Obj->dynamic_table()) {
if (Entry.getTag() == ELF::DT_PLTGOT) {
DtPltGot = Entry.getVal();
break;
}
}
if (!DtPltGot) {
W.startLine() << "Cannot find PLTGOT dynamic table tag.\n";
return;
}
const Elf_Shdr *GotShdr = findSectionByAddress(Obj, *DtPltGot);
if (!GotShdr) {
W.startLine() << "There is no .got section in the file.\n";
return;
}
MipsGOTParser<ELFT>(Obj, W).ParseGOT(*GotShdr);
}

View File

@ -40,6 +40,9 @@ public:
// Only implemented for ARM ELF at this time.
virtual void printAttributes() { }
// Only implemented for MIPS ELF at this time.
virtual void printMipsPLTGOT() { }
protected:
StreamWriter& W;
};

View File

@ -135,6 +135,11 @@ namespace opts {
cl::desc("Display the ARM attributes section"));
cl::alias ARMAttributesShort("-a", cl::desc("Alias for --arm-attributes"),
cl::aliasopt(ARMAttributes));
// -mips-plt-got
cl::opt<bool>
MipsPLTGOT("mips-plt-got",
cl::desc("Display the MIPS GOT and PLT GOT sections"));
} // namespace opts
static int ReturnValue = EXIT_SUCCESS;
@ -177,6 +182,18 @@ static void reportError(StringRef Input, StringRef Message) {
ReturnValue = EXIT_FAILURE;
}
static bool isMipsArch(unsigned Arch) {
switch (Arch) {
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
return true;
default:
return false;
}
}
/// @brief Creates an format-specific object file dumper.
static std::error_code createDumper(const ObjectFile *Obj, StreamWriter &Writer,
std::unique_ptr<ObjDumper> &Result) {
@ -234,6 +251,9 @@ static void dumpObject(const ObjectFile *Obj) {
if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())
if (opts::ARMAttributes)
Dumper->printAttributes();
if (isMipsArch(Obj->getArch()) && Obj->isELF())
if (opts::MipsPLTGOT)
Dumper->printMipsPLTGOT();
}

View File

@ -38,6 +38,7 @@ namespace opts {
extern llvm::cl::opt<bool> ExpandRelocs;
extern llvm::cl::opt<bool> CodeViewLineTables;
extern llvm::cl::opt<bool> ARMAttributes;
extern llvm::cl::opt<bool> MipsPLTGOT;
} // namespace opts
#define LLVM_READOBJ_ENUM_ENT(ns, enum) \