RUN: FileCheck %s -check-prefix GOT-TLS
RUN: llvm-readobj -mips-plt-got %p/Inputs/got-empty.exe.mipsel | \
RUN: FileCheck %s -check-prefix GOT-EMPTY
+RUN: llvm-readobj -mips-plt-got %p/Inputs/got-static.exe.mips | \
+RUN: FileCheck %s -check-prefix GOT-STATIC
-GOT-OBJ: Cannot find PLTGOT dynamic table tag.
+GOT-OBJ: Cannot find .got section
GOT-EXE: Primary GOT {
GOT-EXE-NEXT: Canonical gp value: 0x418880
GOT-EMPTY-NEXT: ]
GOT-EMPTY-NEXT: Number of TLS and multi-GOT entries: 2
GOT-EMPTY-NEXT: }
+
+GOT-STATIC: Static GOT {
+GOT-STATIC-NEXT: Canonical gp value: 0x418100
+GOT-STATIC-NEXT: Reserved entries [
+GOT-STATIC-NEXT: Entry {
+GOT-STATIC-NEXT: Address: 0x410110
+GOT-STATIC-NEXT: Access: -32752
+GOT-STATIC-NEXT: Initial: 0x0
+GOT-STATIC-NEXT: Purpose: Lazy resolver
+GOT-STATIC-NEXT: }
+GOT-STATIC-NEXT: Entry {
+GOT-STATIC-NEXT: Address: 0x410114
+GOT-STATIC-NEXT: Access: -32748
+GOT-STATIC-NEXT: Initial: 0x80000000
+GOT-STATIC-NEXT: Purpose: Module pointer (GNU extension)
+GOT-STATIC-NEXT: }
+GOT-STATIC-NEXT: ]
+GOT-STATIC-NEXT: Local entries [
+GOT-STATIC-NEXT: Entry {
+GOT-STATIC-NEXT: Address: 0x410118
+GOT-STATIC-NEXT: Access: -32744
+GOT-STATIC-NEXT: Initial: 0x400000
+GOT-STATIC-NEXT: }
+GOT-STATIC-NEXT: Entry {
+GOT-STATIC-NEXT: Address: 0x41011C
+GOT-STATIC-NEXT: Access: -32740
+GOT-STATIC-NEXT: Initial: 0x400100
+GOT-STATIC-NEXT: }
+GOT-STATIC-NEXT: Entry {
+GOT-STATIC-NEXT: Address: 0x410120
+GOT-STATIC-NEXT: Access: -32736
+GOT-STATIC-NEXT: Initial: 0x400104
+GOT-STATIC-NEXT: }
+GOT-STATIC-NEXT: ]
+GOT-STATIC-NEXT: }
MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj,
Elf_Dyn_Range DynTable, ScopedPrinter &W);
+ void parseStaticGOT();
void parseGOT();
void parsePLT();
std::size_t getGOTTotal(ArrayRef<uint8_t> GOT) const;
const GOTEntry *makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum);
+ void printLocalGOT(const Elf_Shdr *GOTShdr, size_t Num);
void printGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt,
const GOTEntry *It);
void printGlobalGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt,
}
}
+template <class ELFT>
+void MipsGOTParser<ELFT>::printLocalGOT(const Elf_Shdr *GOTShdr, size_t Num) {
+ ArrayRef<uint8_t> GOT = unwrapOrError(Obj->getSectionContents(GOTShdr));
+
+ const GOTEntry *GotBegin = makeGOTIter(GOT, 0);
+ const GOTEntry *GotEnd = makeGOTIter(GOT, Num);
+ const GOTEntry *It = GotBegin;
+
+ 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 != GotEnd && (*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 != GotEnd; ++It) {
+ DictScope D(W, "Entry");
+ printGotEntry(GOTShdr->sh_addr, GotBegin, It);
+ }
+ }
+}
+
+template <class ELFT> void MipsGOTParser<ELFT>::parseStaticGOT() {
+ const Elf_Shdr *GOTShdr = findSectionByName(*Obj, ".got");
+ if (!GOTShdr) {
+ W.startLine() << "Cannot find .got section.\n";
+ return;
+ }
+
+ DictScope GS(W, "Static GOT");
+ printLocalGOT(GOTShdr, GOTShdr->sh_size / sizeof(GOTEntry));
+}
+
template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
// See "Global Offset Table" in Chapter 5 in the following document
// for detailed GOT description.
if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(GOT))
report_fatal_error("Number of GOT entries exceeds the size of GOT section");
- const GOTEntry *GotBegin = makeGOTIter(GOT, 0);
- const GOTEntry *GotLocalEnd = makeGOTIter(GOT, *DtLocalGotNum);
- const GOTEntry *It = GotBegin;
-
DictScope GS(W, "Primary GOT");
+ printLocalGOT(GOTShdr, *DtLocalGotNum);
- 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");
+ const GOTEntry *GotBegin = makeGOTIter(GOT, 0);
const GOTEntry *GotGlobalEnd =
makeGOTIter(GOT, *DtLocalGotNum + GlobalGotNum);
const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym;
- for (; It != GotGlobalEnd; ++It) {
+ for (auto It = makeGOTIter(GOT, *DtLocalGotNum); It != GotGlobalEnd; ++It) {
DictScope D(W, "Entry");
printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++,
StrTable);
}
MipsGOTParser<ELFT> GOTParser(this, Obj, dynamic_table(), W);
- GOTParser.parseGOT();
- GOTParser.parsePLT();
+ if (dynamic_table().empty())
+ GOTParser.parseStaticGOT();
+ else {
+ GOTParser.parseGOT();
+ GOTParser.parsePLT();
+ }
}
static const EnumEntry<unsigned> ElfMipsISAExtType[] = {