mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 12:19:53 +00:00
[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:
parent
02b4e6e7ab
commit
42469f61f5
BIN
test/tools/llvm-readobj/Inputs/got-tls.so.elf-mips64el
Executable file
BIN
test/tools/llvm-readobj/Inputs/got-tls.so.elf-mips64el
Executable file
Binary file not shown.
306
test/tools/llvm-readobj/mips-got.test
Normal file
306
test/tools/llvm-readobj/mips-got.test
Normal 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: }
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user