llvm.org GIT mirror llvm / 6572bcd
[llvm-readobj] Support 'GNU' style for MIPS GOT/PLT dumping This change adds `printMipsGOT` and `printMipsPLT` methods to the `DumpStyle` class and overrides them in the `GNUStyle` and `LLVMStyle` descendants. To pass information about GOT/PLT layout into these methods, the `MipsGOTParser` class has been extended to hold all necessary data. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@321253 91177308-0d34-0410-b5e6-96231b3b80d8 Simon Atanasyan 2 years ago
3 changed file(s) with 645 addition(s) and 297 deletion(s). Raw diff Collapse all Expand all
None RUN: llvm-readobj -mips-plt-got %p/Inputs/relocs.obj.elf-mips | \
0 RUN: not llvm-readobj -mips-plt-got %p/Inputs/relocs.obj.elf-mips 2>&1 | \
11 RUN: FileCheck %s -check-prefix GOT-OBJ
22 RUN: llvm-readobj -mips-plt-got %p/Inputs/dynamic-table-exe.mips | \
33 RUN: FileCheck %s -check-prefix GOT-EXE
1010 RUN: llvm-readobj -mips-plt-got %p/Inputs/got-static.exe.mips | \
1111 RUN: FileCheck %s -check-prefix GOT-STATIC
1212
13 GOT-OBJ: Cannot find .got section
13 RUN: not llvm-readobj -mips-plt-got %p/Inputs/relocs.obj.elf-mips \
14 RUN: --elf-output-style=GNU 2>&1 | \
15 RUN: FileCheck %s -check-prefix GNU-GOT-OBJ
16 RUN: llvm-readobj -mips-plt-got %p/Inputs/dynamic-table-exe.mips \
17 RUN: --elf-output-style=GNU | \
18 RUN: FileCheck %s -check-prefix GNU-GOT-EXE
19 RUN: llvm-readobj -mips-plt-got %p/Inputs/dynamic-table-so.mips \
20 RUN: --elf-output-style=GNU | \
21 RUN: FileCheck %s -check-prefix GNU-GOT-SO
22 RUN: llvm-readobj -mips-plt-got %p/Inputs/got-tls.so.elf-mips64el \
23 RUN: --elf-output-style=GNU | \
24 RUN: FileCheck %s -check-prefix GNU-GOT-TLS
25 RUN: llvm-readobj -mips-plt-got %p/Inputs/got-empty.exe.mipsel \
26 RUN: --elf-output-style=GNU | \
27 RUN: FileCheck %s -check-prefix GNU-GOT-EMPTY
28 RUN: llvm-readobj -mips-plt-got %p/Inputs/got-static.exe.mips \
29 RUN: --elf-output-style=GNU | \
30 RUN: FileCheck %s -check-prefix GNU-GOT-STATIC
31
32 GOT-OBJ: Error reading file: Cannot find .got section.
1433
1534 GOT-EXE: Primary GOT {
1635 GOT-EXE-NEXT: Canonical gp value: 0x418880
365384 GOT-STATIC-NEXT: }
366385 GOT-STATIC-NEXT: ]
367386 GOT-STATIC-NEXT: }
387
388 GNU-GOT-OBJ: Error reading file: Cannot find .got section.
389
390 GNU-GOT-EXE: Primary GOT:
391 GNU-GOT-EXE-NEXT: Canonical gp value: 00418880
392
393 GNU-GOT-EXE: Reserved entries:
394 GNU-GOT-EXE-NEXT: Address Access Initial Purpose
395 GNU-GOT-EXE-NEXT: 00410890 -32752(gp) 00000000 Lazy resolver
396 GNU-GOT-EXE-NEXT: 00410894 -32748(gp) 80000000 Module pointer (GNU extension)
397
398 GNU-GOT-EXE: Local entries:
399 GNU-GOT-EXE-NEXT: Address Access Initial
400 GNU-GOT-EXE-NEXT: 00410898 -32744(gp) 00400418
401 GNU-GOT-EXE-NEXT: 0041089c -32740(gp) 00410840
402 GNU-GOT-EXE-NEXT: 004108a0 -32736(gp) 00000000
403
404 GNU-GOT-EXE: Global entries:
405 GNU-GOT-EXE-NEXT: Address Access Initial Sym.Val. Type Ndx Name
406 GNU-GOT-EXE-NEXT: 004108a4 -32732(gp) 00000000 00000000 FUNC UND __gmon_start__
407
408 GNU-GOT-EXE: PLT GOT:
409
410 GNU-GOT-EXE: Reserved entries:
411 GNU-GOT-EXE-NEXT: Address Initial Purpose
412 GNU-GOT-EXE-NEXT: 00410854 00000000 PLT lazy resolver
413 GNU-GOT-EXE-NEXT: 00410894 80000000 Module pointer
414
415 GNU-GOT-EXE: Entries:
416 GNU-GOT-EXE-NEXT: Address Initial Sym.Val. Type Ndx Name
417 GNU-GOT-EXE-NEXT: 0041085c 00400800 00000000 FUNC UND puts
418 GNU-GOT-EXE-NEXT: 00410860 00400800 00000000 FUNC UND __libc_start_main
419
420 GNU-GOT-SO: Primary GOT:
421 GNU-GOT-SO-NEXT: Canonical gp value: 000188d0
422
423 GNU-GOT-SO: Reserved entries:
424 GNU-GOT-SO-NEXT: Address Access Initial Purpose
425 GNU-GOT-SO-NEXT: 000108e0 -32752(gp) 00000000 Lazy resolver
426 GNU-GOT-SO-NEXT: 000108e4 -32748(gp) 80000000 Module pointer (GNU extension)
427
428 GNU-GOT-SO: Local entries:
429 GNU-GOT-SO-NEXT: Address Access Initial
430 GNU-GOT-SO-NEXT: 000108e8 -32744(gp) 000108e0
431 GNU-GOT-SO-NEXT: 000108ec -32740(gp) 00010000
432 GNU-GOT-SO-NEXT: 000108f0 -32736(gp) 00010920
433 GNU-GOT-SO-NEXT: 000108f4 -32732(gp) 000108cc
434 GNU-GOT-SO-NEXT: 000108f8 -32728(gp) 00000000
435 GNU-GOT-SO-NEXT: 000108fc -32724(gp) 00000000
436 GNU-GOT-SO-NEXT: 00010900 -32720(gp) 00000000
437 GNU-GOT-SO-NEXT: 00010904 -32716(gp) 00000000
438
439 GNU-GOT-SO: Global entries:
440 GNU-GOT-SO-NEXT: Address Access Initial Sym.Val. Type Ndx Name
441 GNU-GOT-SO-NEXT: 00010908 -32712(gp) 00000000 00000000 NOTYPE UND _ITM_registerTMCloneTable
442 GNU-GOT-SO-NEXT: 0001090c -32708(gp) 00000000 00000000 NOTYPE UND _Jv_RegisterClasses
443 GNU-GOT-SO-NEXT: 00010910 -32704(gp) 00000000 00000000 FUNC UND __gmon_start__
444 GNU-GOT-SO-NEXT: 00010914 -32700(gp) 00000840 00000840 FUNC UND puts
445 GNU-GOT-SO-NEXT: 00010918 -32696(gp) 00000000 00000000 NOTYPE UND _ITM_deregisterTMCloneTable
446 GNU-GOT-SO-NEXT: 0001091c -32692(gp) 00000000 00000000 FUNC UND __cxa_finalize
447
448 GNU-GOT-TLS: Primary GOT:
449 GNU-GOT-TLS-NEXT: Canonical gp value: 0000000000018bf0
450
451 GNU-GOT-TLS: Reserved entries:
452 GNU-GOT-TLS-NEXT: Address Access Initial Purpose
453 GNU-GOT-TLS-NEXT: 0000000000010c00 -32752(gp) 0000000000000000 Lazy resolver
454 GNU-GOT-TLS-NEXT: 0000000000010c08 -32744(gp) 8000000000000000 Module pointer (GNU extension)
455
456 GNU-GOT-TLS: Local entries:
457 GNU-GOT-TLS-NEXT: Address Access Initial
458 GNU-GOT-TLS-NEXT: 0000000000010c10 -32736(gp) 0000000000010000
459 GNU-GOT-TLS-NEXT: 0000000000010c18 -32728(gp) 0000000000010c00
460 GNU-GOT-TLS-NEXT: 0000000000010c20 -32720(gp) 0000000000010cb8
461 GNU-GOT-TLS-NEXT: 0000000000010c28 -32712(gp) 0000000000010bf0
462 GNU-GOT-TLS-NEXT: 0000000000010c30 -32704(gp) 0000000000000000
463 GNU-GOT-TLS-NEXT: 0000000000010c38 -32696(gp) 0000000000000948
464 GNU-GOT-TLS-NEXT: 0000000000010c40 -32688(gp) 0000000000000a20
465 GNU-GOT-TLS-NEXT: 0000000000010c48 -32680(gp) 0000000000000af0
466 GNU-GOT-TLS-NEXT: 0000000000010c50 -32672(gp) 0000000000000000
467 GNU-GOT-TLS-NEXT: 0000000000010c58 -32664(gp) 0000000000000000
468 GNU-GOT-TLS-NEXT: 0000000000010c60 -32656(gp) 0000000000000000
469
470 GNU-GOT-TLS: Global entries:
471 GNU-GOT-TLS-NEXT: Address Access Initial Sym.Val. Type Ndx Name
472 GNU-GOT-TLS-NEXT: 0000000000010c68 -32648(gp) 0000000000000000 0000000000000000 NOTYPE UND _ITM_registerTMCloneTable
473 GNU-GOT-TLS-NEXT: 0000000000010c70 -32640(gp) 0000000000000000 0000000000000000 NOTYPE UND _Jv_RegisterClasses
474 GNU-GOT-TLS-NEXT: 0000000000010c78 -32632(gp) 0000000000000000 0000000000000000 FUNC UND __gmon_start__
475 GNU-GOT-TLS-NEXT: 0000000000010c80 -32624(gp) 0000000000000b60 0000000000000b60 FUNC UND __tls_get_addr
476 GNU-GOT-TLS-NEXT: 0000000000010c88 -32616(gp) 0000000000000000 0000000000000000 NOTYPE UND _ITM_deregisterTMCloneTable
477 GNU-GOT-TLS-NEXT: 0000000000010c90 -32608(gp) 0000000000000000 0000000000000000 FUNC UND __cxa_finalize
478
479 GNU-GOTY : Primary GOT:
480 GNU-GOT-EMPTY: Canonical gp value: 00409ff0
481
482 GNU-GOTY : Reserved entries:
483 GNU-GOT-EMPTY: Address Access Initial Purpose
484 GNU-GOT-EMPTY: 00402000 -32752(gp) 00000000 Lazy resolver
485 GNU-GOT-EMPTY: 00402004 -32748(gp) 80000000 Module pointer (GNU extension)
486
487 GNU-GOT-STATIC: Static GOT:
488 GNU-GOT-STATIC-NEXT: Canonical gp value: 00418100
489
490 GNU-GOT-STATIC: Reserved entries:
491 GNU-GOT-STATIC-NEXT: Address Access Initial Purpose
492 GNU-GOT-STATIC-NEXT: 00410110 -32752(gp) 00000000 Lazy resolver
493 GNU-GOT-STATIC-NEXT: 00410114 -32748(gp) 80000000 Module pointer (GNU extension)
494
495 GNU-GOT-STATIC: Local entries:
496 GNU-GOT-STATIC-NEXT: Address Access Initial
497 GNU-GOT-STATIC-NEXT: 00410118 -32744(gp) 00400000
498 GNU-GOT-STATIC-NEXT: 0041011c -32740(gp) 00400100
499 GNU-GOT-STATIC-NEXT: 00410120 -32736(gp) 00400104
0 RUN: llvm-readobj -mips-plt-got %p/Inputs/got-plt.exe.elf-mipsel | FileCheck %s
1 RUN: llvm-readobj -mips-plt-got --elf-output-style=GNU \
2 RUN: %p/Inputs/got-plt.exe.elf-mipsel \
3 RUN: | FileCheck --check-prefix=GNU %s
14
25 CHECK: PLT GOT {
36 CHECK-NEXT: Reserved entries [
3134 CHECK-NEXT: }
3235 CHECK-NEXT: ]
3336 CHECK-NEXT: }
37
38 GNU: Primary GOT:
39 GNU-NEXT: Canonical gp value: 00418840
40
41 GNU: Reserved entries:
42 GNU-NEXT: Address Access Initial Purpose
43 GNU-NEXT: 00410850 -32752(gp) 00000000 Lazy resolver
44 GNU-NEXT: 00410854 -32748(gp) 80000000 Module pointer (GNU extension)
45
46 GNU: Local entries:
47 GNU-NEXT: Address Access Initial
48 GNU-NEXT: 00410858 -32744(gp) 004003d4
49 GNU-NEXT: 0041085c -32740(gp) 00410800
50 GNU-NEXT: 00410860 -32736(gp) 00000000
51
52 GNU: Global entries:
53 GNU-NEXT: Address Access Initial Sym.Val. Type Ndx Name
54 GNU-NEXT: 00410864 -32732(gp) 00000000 00000000 FUNC UND __gmon_start__
55 GNU-NEXT: PLT GOT:
56
57 GNU: Reserved entries:
58 GNU-NEXT: Address Initial Purpose
59 GNU-NEXT: 00410814 00000000 PLT lazy resolver
60 GNU-NEXT: 00410854 80000000 Module pointer
61
62 GNU: Entries:
63 GNU-NEXT: Address Initial Sym.Val. Type Ndx Name
64 GNU-NEXT: 0041081c 004007c0 00000000 FUNC UND puts
65 GNU-NEXT: 00410820 004007c0 00000000 FUNC UND __libc_start_main
7676
7777 #define TYPEDEF_ELF_TYPES(ELFT) \
7878 using ELFO = ELFFile; \
79 using Elf_Addr = typename ELFO::Elf_Addr; \
7980 using Elf_Shdr = typename ELFO::Elf_Shdr; \
8081 using Elf_Sym = typename ELFO::Elf_Sym; \
8182 using Elf_Dyn = typename ELFO::Elf_Dyn; \
248249 Elf_Rela_Range dyn_relas() const;
249250 std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable,
250251 bool IsDynamic) const;
252 void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym,
253 StringRef &SectionName,
254 unsigned &SectionIndex) const;
251255
252256 void printSymbolsHelper(bool IsDynamic) const;
253257 const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
286290 ELFDumperStyle->printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic);
287291 }
288292
293 template class MipsGOTParser;
294
289295 template class DumpStyle {
290296 public:
291297 using Elf_Shdr = typename ELFFile::Elf_Shdr;
309315 virtual void printProgramHeaders(const ELFFile *Obj) = 0;
310316 virtual void printHashHistogram(const ELFFile *Obj) = 0;
311317 virtual void printNotes(const ELFFile *Obj) = 0;
318 virtual void printMipsGOT(const MipsGOTParser &Parser) = 0;
319 virtual void printMipsPLT(const MipsGOTParser &Parser) = 0;
312320 const ELFDumper *dumper() const { return Dumper; }
313321
314322 private:
336344 void printProgramHeaders(const ELFO *Obj) override;
337345 void printHashHistogram(const ELFFile *Obj) override;
338346 void printNotes(const ELFFile *Obj) override;
347 void printMipsGOT(const MipsGOTParser &Parser) override;
348 void printMipsPLT(const MipsGOTParser &Parser) override;
339349
340350 private:
341351 struct Field {
394404 void printProgramHeaders(const ELFO *Obj) override;
395405 void printHashHistogram(const ELFFile *Obj) override;
396406 void printNotes(const ELFFile *Obj) override;
407 void printMipsGOT(const MipsGOTParser &Parser) override;
408 void printMipsPLT(const MipsGOTParser &Parser) override;
397409
398410 private:
399411 void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab);
734746 }
735747
736748 template
737 static void
738 getSectionNameIndex(const ELFFile &Obj, const typename ELFT::Sym *Symbol,
739 const typename ELFT::Sym *FirstSym,
740 ArrayRef ShndxTable,
741 StringRef &SectionName, unsigned &SectionIndex) {
749 void ELFDumper::getSectionNameIndex(const Elf_Sym *Symbol,
750 const Elf_Sym *FirstSym,
751 StringRef &SectionName,
752 unsigned &SectionIndex) const {
742753 SectionIndex = Symbol->st_shndx;
743754 if (Symbol->isUndefined())
744755 SectionName = "Undefined";
757768 SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex(
758769 Symbol, FirstSym, ShndxTable));
759770 const typename ELFT::Shdr *Sec =
760 unwrapOrError(Obj.getSection(SectionIndex));
761 SectionName = unwrapOrError(Obj.getSectionName(Sec));
771 unwrapOrError(Obj->getSection(SectionIndex));
772 SectionName = unwrapOrError(Obj->getSectionName(Sec));
762773 }
763774 }
764775
19041915 template class MipsGOTParser {
19051916 public:
19061917 TYPEDEF_ELF_TYPES(ELFT)
1907 using GOTEntry = typename ELFO::Elf_Addr;
1908
1909 MipsGOTParser(ELFDumper *Dumper, const ELFO *Obj,
1910 Elf_Dyn_Range DynTable, ScopedPrinter &W);
1911
1912 void parseStaticGOT();
1913 void parseGOT();
1914 void parsePLT();
1918 using Entry = typename ELFO::Elf_Addr;
1919 using Entries = ArrayRef;
1920
1921 const bool IsStatic;
1922 const ELFO * const Obj;
1923
1924 MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable, Elf_Sym_Range DynSyms);
1925
1926 bool hasGot() const { return !GotEntries.empty(); }
1927 bool hasPlt() const { return !PltEntries.empty(); }
1928
1929 uint64_t getGp() const;
1930
1931 const Entry *getGotLazyResolver() const;
1932 const Entry *getGotModulePointer() const;
1933 const Entry *getPltLazyResolver() const;
1934 const Entry *getPltModulePointer() const;
1935
1936 Entries getLocalEntries() const;
1937 Entries getGlobalEntries() const;
1938 Entries getOtherEntries() const;
1939 Entries getPltEntries() const;
1940
1941 uint64_t getGotAddress(const Entry * E) const;
1942 int64_t getGotOffset(const Entry * E) const;
1943 const Elf_Sym *getGotSym(const Entry *E) const;
1944
1945 uint64_t getPltAddress(const Entry * E) const;
1946 const Elf_Sym *getPltSym(const Entry *E) const;
1947
1948 StringRef getPltStrTable() const { return PltStrTable; }
19151949
19161950 private:
1917 ELFDumper *Dumper;
1918 const ELFO *Obj;
1919 ScopedPrinter &W;
1951 const Elf_Shdr *GotSec;
1952 size_t LocalNum;
1953 size_t GlobalNum;
1954
1955 const Elf_Shdr *PltSec;
1956 const Elf_Shdr *PltRelSec;
1957 const Elf_Shdr *PltSymTable;
1958 Elf_Sym_Range GotDynSyms;
1959 StringRef PltStrTable;
1960
1961 Entries GotEntries;
1962 Entries PltEntries;
1963 };
1964
1965 } // end anonymous namespace
1966
1967 template
1968 MipsGOTParser::MipsGOTParser(const ELFO *Obj, Elf_Dyn_Range DynTable,
1969 Elf_Sym_Range DynSyms)
1970 : IsStatic(DynTable.empty()), Obj(Obj), GotSec(nullptr), LocalNum(0),
1971 GlobalNum(0), PltSec(nullptr), PltRelSec(nullptr), PltSymTable(nullptr) {
1972 // See "Global Offset Table" in Chapter 5 in the following document
1973 // for detailed GOT description.
1974 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
1975
1976 // Find static GOT secton.
1977 if (IsStatic) {
1978 GotSec = findSectionByName(*Obj, ".got");
1979 if (!GotSec)
1980 reportError("Cannot find .got section");
1981
1982 ArrayRef Content = unwrapOrError(Obj->getSectionContents(GotSec));
1983 GotEntries = Entries(reinterpret_cast(Content.data()),
1984 Content.size() / sizeof(Entry));
1985 LocalNum = GotEntries.size();
1986 return;
1987 }
1988
1989 // Lookup dynamic table tags which define GOT/PLT layouts.
19201990 Optional DtPltGot;
19211991 Optional DtLocalGotNum;
19221992 Optional DtGotSym;
19231993 Optional DtMipsPltGot;
19241994 Optional DtJmpRel;
1925
1926 std::size_t getGOTTotal(ArrayRef GOT) const;
1927 const GOTEntry *makeGOTIter(ArrayRef GOT, std::size_t EntryNum);
1928
1929 void printLocalGOT(const Elf_Shdr *GOTShdr, size_t Num);
1930 void printGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt,
1931 const GOTEntry *It);
1932 void printGlobalGotEntry(uint64_t GotAddr, const GOTEntry *BeginIt,
1933 const GOTEntry *It, const Elf_Sym *Sym,
1934 StringRef StrTable);
1935 void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt,
1936 const GOTEntry *It, StringRef Purpose);
1937 void printPLTEntry(uint64_t PLTAddr, const GOTEntry *BeginIt,
1938 const GOTEntry *It, StringRef StrTable,
1939 const Elf_Sym *Sym);
1940 };
1941
1942 } // end anonymous namespace
1943
1944 template
1945 MipsGOTParser::MipsGOTParser(ELFDumper *Dumper, const ELFO *Obj,
1946 Elf_Dyn_Range DynTable, ScopedPrinter &W)
1947 : Dumper(Dumper), Obj(Obj), W(W) {
19481995 for (const auto &Entry : DynTable) {
19491996 switch (Entry.getTag()) {
19501997 case ELF::DT_PLTGOT:
19642011 break;
19652012 }
19662013 }
1967 }
1968
1969 template
1970 void MipsGOTParser::printLocalGOT(const Elf_Shdr *GOTShdr, size_t Num) {
1971 ArrayRef GOT = unwrapOrError(Obj->getSectionContents(GOTShdr));
1972
1973 const GOTEntry *GotBegin = makeGOTIter(GOT, 0);
1974 const GOTEntry *GotEnd = makeGOTIter(GOT, Num);
1975 const GOTEntry *It = GotBegin;
1976
1977 W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0);
1978 {
1979 ListScope RS(W, "Reserved entries");
1980
1981 {
1982 DictScope D(W, "Entry");
1983 printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
1984 W.printString("Purpose", StringRef("Lazy resolver"));
1985 }
1986
1987 if (It != GotEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) {
1988 DictScope D(W, "Entry");
1989 printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
1990 W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
1991 }
1992 }
1993 {
1994 ListScope LS(W, "Local entries");
1995 for (; It != GotEnd; ++It) {
1996 DictScope D(W, "Entry");
1997 printGotEntry(GOTShdr->sh_addr, GotBegin, It);
1998 }
1999 }
2000 }
2001
2002 template void MipsGOTParser::parseStaticGOT() {
2003 const Elf_Shdr *GOTShdr = findSectionByName(*Obj, ".got");
2004 if (!GOTShdr) {
2005 W.startLine() << "Cannot find .got section.\n";
2006 return;
2007 }
2008
2009 DictScope GS(W, "Static GOT");
2010 printLocalGOT(GOTShdr, GOTShdr->sh_size / sizeof(GOTEntry));
2011 }
2012
2013 template void MipsGOTParser::parseGOT() {
2014 // See "Global Offset Table" in Chapter 5 in the following document
2015 // for detailed GOT description.
2016 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
2017 if (!DtPltGot) {
2018 W.startLine() << "Cannot find PLTGOT dynamic table tag.\n";
2019 return;
2020 }
2021 if (!DtLocalGotNum) {
2022 W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n";
2023 return;
2024 }
2025 if (!DtGotSym) {
2026 W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n";
2027 return;
2028 }
2029
2030 std::size_t DynSymTotal = Dumper->dynamic_symbols().size();
2031
2032 if (*DtGotSym > DynSymTotal)
2033 report_fatal_error("MIPS_GOTSYM exceeds a number of dynamic symbols");
2034
2035 std::size_t GlobalGotNum = DynSymTotal - *DtGotSym;
2036
2037 if (*DtLocalGotNum + GlobalGotNum == 0) {
2038 W.startLine() << "GOT is empty.\n";
2039 return;
2040 }
2041
2042 const Elf_Shdr *GOTShdr = findNotEmptySectionByAddress(Obj, *DtPltGot);
2043 if (!GOTShdr)
2044 report_fatal_error("There is no not empty GOT section at 0x" +
2045 Twine::utohexstr(*DtPltGot));
2046
2047 ArrayRef GOT = unwrapOrError(Obj->getSectionContents(GOTShdr));
2048
2049 if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(GOT))
2050 report_fatal_error("Number of GOT entries exceeds the size of GOT section");
2051
2052 DictScope GS(W, "Primary GOT");
2053 printLocalGOT(GOTShdr, *DtLocalGotNum);
2054
2055 {
2056 ListScope GS(W, "Global entries");
2057
2058 const GOTEntry *GotBegin = makeGOTIter(GOT, 0);
2059 const GOTEntry *GotEnd = makeGOTIter(GOT, *DtLocalGotNum + GlobalGotNum);
2060 const Elf_Sym *GotDynSym = Dumper->dynamic_symbols().begin() + *DtGotSym;
2061 for (auto It = makeGOTIter(GOT, *DtLocalGotNum); It != GotEnd; ++It) {
2062 DictScope D(W, "Entry");
2063 printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++,
2064 Dumper->getDynamicStringTable());
2065 }
2066 }
2067
2068 std::size_t SpecGotNum = getGOTTotal(GOT) - *DtLocalGotNum - GlobalGotNum;
2069 W.printNumber("Number of TLS and multi-GOT entries", uint64_t(SpecGotNum));
2070 }
2071
2072 template void MipsGOTParser::parsePLT() {
2073 if (!DtMipsPltGot) {
2074 W.startLine() << "Cannot find MIPS_PLTGOT dynamic table tag.\n";
2075 return;
2076 }
2077 if (!DtJmpRel) {
2078 W.startLine() << "Cannot find JMPREL dynamic table tag.\n";
2079 return;
2080 }
2081
2082 const Elf_Shdr *PLTShdr = findNotEmptySectionByAddress(Obj, *DtMipsPltGot);
2083 if (!PLTShdr)
2084 report_fatal_error("There is no not empty PLTGOT section at 0x " +
2085 Twine::utohexstr(*DtMipsPltGot));
2086 ArrayRef PLT = unwrapOrError(Obj->getSectionContents(PLTShdr));
2087
2088 const Elf_Shdr *PLTRelShdr = findNotEmptySectionByAddress(Obj, *DtJmpRel);
2089 if (!PLTRelShdr)
2090 report_fatal_error("There is no not empty RELPLT section at 0x" +
2091 Twine::utohexstr(*DtJmpRel));
2092 const Elf_Shdr *SymTable =
2093 unwrapOrError(Obj->getSection(PLTRelShdr->sh_link));
2094 StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTable));
2095
2096 const GOTEntry *PLTBegin = makeGOTIter(PLT, 0);
2097 const GOTEntry *PLTEnd = makeGOTIter(PLT, getGOTTotal(PLT));
2098 const GOTEntry *It = PLTBegin;
2099
2100 DictScope GS(W, "PLT GOT");
2101 {
2102 ListScope RS(W, "Reserved entries");
2103 printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "PLT lazy resolver");
2104 if (It != PLTEnd)
2105 printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "Module pointer");
2106 }
2107 {
2108 ListScope GS(W, "Entries");
2109
2110 switch (PLTRelShdr->sh_type) {
2111 case ELF::SHT_REL:
2112 for (const Elf_Rel &Rel : unwrapOrError(Obj->rels(PLTRelShdr))) {
2113 const Elf_Sym *Sym =
2114 unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTable));
2115 printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, StrTable, Sym);
2116 if (++It == PLTEnd)
2117 break;
2118 }
2119 break;
2120 case ELF::SHT_RELA:
2121 for (const Elf_Rela &Rel : unwrapOrError(Obj->relas(PLTRelShdr))) {
2122 const Elf_Sym *Sym =
2123 unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTable));
2124 printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, StrTable, Sym);
2125 if (++It == PLTEnd)
2126 break;
2127 }
2128 break;
2129 }
2130 }
2131 }
2132
2133 template
2134 std::size_t MipsGOTParser::getGOTTotal(ArrayRef GOT) const {
2135 return GOT.size() / sizeof(GOTEntry);
2136 }
2137
2138 template
2139 const typename MipsGOTParser::GOTEntry *
2140 MipsGOTParser::makeGOTIter(ArrayRef GOT, std::size_t EntryNum) {
2141 const char *Data = reinterpret_cast(GOT.data());
2142 return reinterpret_cast(Data + EntryNum * sizeof(GOTEntry));
2143 }
2144
2145 template
2146 void MipsGOTParser::printGotEntry(uint64_t GotAddr,
2147 const GOTEntry *BeginIt,
2148 const GOTEntry *It) {
2149 int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
2150 W.printHex("Address", GotAddr + Offset);
2151 W.printNumber("Access", Offset - 0x7ff0);
2152 W.printHex("Initial", *It);
2153 }
2154
2155 template
2156 void MipsGOTParser::printGlobalGotEntry(uint64_t GotAddr,
2157 const GOTEntry *BeginIt,
2158 const GOTEntry *It,
2159 const Elf_Sym *Sym,
2160 StringRef StrTable) {
2161 printGotEntry(GotAddr, BeginIt, It);
2162
2163 W.printHex("Value", Sym->st_value);
2164 W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
2165
2166 unsigned SectionIndex = 0;
2167 StringRef SectionName;
2168 getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(),
2169 Dumper->getShndxTable(), SectionName, SectionIndex);
2170 W.printHex("Section", SectionName, SectionIndex);
2171
2172 std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true);
2173 W.printNumber("Name", FullSymbolName, Sym->st_name);
2174 }
2175
2176 template
2177 void MipsGOTParser::printPLTEntry(uint64_t PLTAddr,
2178 const GOTEntry *BeginIt,
2179 const GOTEntry *It, StringRef Purpose) {
2180 DictScope D(W, "Entry");
2181 int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
2182 W.printHex("Address", PLTAddr + Offset);
2183 W.printHex("Initial", *It);
2184 W.printString("Purpose", Purpose);
2185 }
2186
2187 template
2188 void MipsGOTParser::printPLTEntry(uint64_t PLTAddr,
2189 const GOTEntry *BeginIt,
2190 const GOTEntry *It, StringRef StrTable,
2191 const Elf_Sym *Sym) {
2192 DictScope D(W, "Entry");
2193 int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
2194 W.printHex("Address", PLTAddr + Offset);
2195 W.printHex("Initial", *It);
2196 W.printHex("Value", Sym->st_value);
2197 W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
2198
2199 unsigned SectionIndex = 0;
2200 StringRef SectionName;
2201 getSectionNameIndex(*Obj, Sym, Dumper->dynamic_symbols().begin(),
2202 Dumper->getShndxTable(), SectionName, SectionIndex);
2203 W.printHex("Section", SectionName, SectionIndex);
2204
2205 std::string FullSymbolName = Dumper->getFullSymbolName(Sym, StrTable, true);
2206 W.printNumber("Name", FullSymbolName, Sym->st_name);
2014
2015 // Find dynamic GOT section.
2016 if (DtPltGot || DtLocalGotNum || DtGotSym) {
2017 if (!DtPltGot)
2018 report_fatal_error("Cannot find PLTGOT dynamic table tag.");
2019 if (!DtLocalGotNum)
2020 report_fatal_error("Cannot find MIPS_LOCAL_GOTNO dynamic table tag.");
2021 if (!DtGotSym)
2022 report_fatal_error("Cannot find MIPS_GOTSYM dynamic table tag.");
2023
2024 size_t DynSymTotal = DynSyms.size();
2025 if (*DtGotSym > DynSymTotal)
2026 reportError("MIPS_GOTSYM exceeds a number of dynamic symbols");
2027
2028 GotSec = findNotEmptySectionByAddress(Obj, *DtPltGot);
2029 if (!GotSec)
2030 reportError("There is no not empty GOT section at 0x" +
2031 Twine::utohexstr(*DtPltGot));
2032
2033 LocalNum = *DtLocalGotNum;
2034 GlobalNum = DynSymTotal - *DtGotSym;
2035
2036 ArrayRef Content = unwrapOrError(Obj->getSectionContents(GotSec));
2037 GotEntries = Entries(reinterpret_cast(Content.data()),
2038 Content.size() / sizeof(Entry));
2039 GotDynSyms = DynSyms.drop_front(*DtGotSym);
2040 }
2041
2042 // Find PLT section.
2043 if (DtMipsPltGot || DtJmpRel) {
2044 if (!DtMipsPltGot)
2045 report_fatal_error("Cannot find MIPS_PLTGOT dynamic table tag.");
2046 if (!DtJmpRel)
2047 report_fatal_error("Cannot find JMPREL dynamic table tag.");
2048
2049 PltSec = findNotEmptySectionByAddress(Obj, *DtMipsPltGot);
2050 if (!PltSec)
2051 report_fatal_error("There is no not empty PLTGOT section at 0x " +
2052 Twine::utohexstr(*DtMipsPltGot));
2053
2054 PltRelSec = findNotEmptySectionByAddress(Obj, *DtJmpRel);
2055 if (!PltRelSec)
2056 report_fatal_error("There is no not empty RELPLT section at 0x" +
2057 Twine::utohexstr(*DtJmpRel));
2058
2059 ArrayRef PltContent =
2060 unwrapOrError(Obj->getSectionContents(PltSec));
2061 PltEntries = Entries(reinterpret_cast(PltContent.data()),
2062 PltContent.size() / sizeof(Entry));
2063
2064 PltSymTable = unwrapOrError(Obj->getSection(PltRelSec->sh_link));
2065 PltStrTable = unwrapOrError(Obj->getStringTableForSymtab(*PltSymTable));
2066 }
2067 }
2068
2069 template uint64_t MipsGOTParser::getGp() const {
2070 return GotSec->sh_addr + 0x7ff0;
2071 }
2072
2073 template
2074 const typename MipsGOTParser::Entry *
2075 MipsGOTParser::getGotLazyResolver() const {
2076 return LocalNum > 0 ? &GotEntries[0] : nullptr;
2077 }
2078
2079 template
2080 const typename MipsGOTParser::Entry *
2081 MipsGOTParser::getGotModulePointer() const {
2082 if (LocalNum < 2)
2083 return nullptr;
2084 const Entry &E = GotEntries[1];
2085 if ((E >> (sizeof(Entry) * 8 - 1)) == 0)
2086 return nullptr;
2087 return &E;
2088 }
2089
2090 template
2091 typename MipsGOTParser::Entries
2092 MipsGOTParser::getLocalEntries() const {
2093 size_t Skip = getGotModulePointer() ? 2 : 1;
2094 if (LocalNum - Skip <= 0)
2095 return Entries();
2096 return GotEntries.slice(Skip, LocalNum - Skip);
2097 }
2098
2099 template
2100 typename MipsGOTParser::Entries
2101 MipsGOTParser::getGlobalEntries() const {
2102 if (GlobalNum == 0)
2103 return Entries();
2104 return GotEntries.slice(LocalNum, GlobalNum);
2105 }
2106
2107 template
2108 typename MipsGOTParser::Entries
2109 MipsGOTParser::getOtherEntries() const {
2110 size_t OtherNum = GotEntries.size() - LocalNum - GlobalNum;
2111 if (OtherNum == 0)
2112 return Entries();
2113 return GotEntries.slice(LocalNum + GlobalNum, OtherNum);
2114 }
2115
2116 template
2117 uint64_t MipsGOTParser::getGotAddress(const Entry *E) const {
2118 int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);
2119 return GotSec->sh_addr + Offset;
2120 }
2121
2122 template
2123 int64_t MipsGOTParser::getGotOffset(const Entry *E) const {
2124 int64_t Offset = std::distance(GotEntries.data(), E) * sizeof(Entry);
2125 return Offset - 0x7ff0;
2126 }
2127
2128 template
2129 const typename MipsGOTParser::Elf_Sym *
2130 MipsGOTParser::getGotSym(const Entry *E) const {
2131 int64_t Offset = std::distance(GotEntries.data(), E);
2132 return &GotDynSyms[Offset - LocalNum];
2133 }
2134
2135 template
2136 const typename MipsGOTParser::Entry *
2137 MipsGOTParser::getPltLazyResolver() const {
2138 return PltEntries.empty() ? nullptr : &PltEntries[0];
2139 }
2140
2141 template
2142 const typename MipsGOTParser::Entry *
2143 MipsGOTParser::getPltModulePointer() const {
2144 return PltEntries.size() < 2 ? nullptr : &PltEntries[1];
2145 }
2146
2147 template
2148 typename MipsGOTParser::Entries
2149 MipsGOTParser::getPltEntries() const {
2150 if (PltEntries.size() <= 2)
2151 return Entries();
2152 return PltEntries.slice(2, PltEntries.size() - 2);
2153 }
2154
2155 template
2156 uint64_t MipsGOTParser::getPltAddress(const Entry *E) const {
2157 int64_t Offset = std::distance(PltEntries.data(), E) * sizeof(Entry);
2158 return PltSec->sh_addr + Offset;
2159 }
2160
2161 template
2162 const typename MipsGOTParser::Elf_Sym *
2163 MipsGOTParser::getPltSym(const Entry *E) const {
2164 int64_t Offset = std::distance(getPltEntries().data(), E);
2165 if (PltRelSec->sh_type == ELF::SHT_REL) {
2166 Elf_Rel_Range Rels = unwrapOrError(Obj->rels(PltRelSec));
2167 return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));
2168 } else {
2169 Elf_Rela_Range Rels = unwrapOrError(Obj->relas(PltRelSec));
2170 return unwrapOrError(Obj->getRelocationSymbol(&Rels[Offset], PltSymTable));
2171 }
22072172 }
22082173
22092174 template void ELFDumper::printMipsPLTGOT() {
2210 if (Obj->getHeader()->e_machine != EM_MIPS) {
2211 W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n";
2212 return;
2213 }
2214
2215 MipsGOTParser GOTParser(this, Obj, dynamic_table(), W);
2216 if (dynamic_table().empty())
2217 GOTParser.parseStaticGOT();
2218 else {
2219 GOTParser.parseGOT();
2220 GOTParser.parsePLT();
2221 }
2175 if (Obj->getHeader()->e_machine != EM_MIPS)
2176 reportError("MIPS PLT GOT is available for MIPS targets only");
2177
2178 MipsGOTParser Parser(Obj, dynamic_table(), dynamic_symbols());
2179 if (Parser.hasGot())
2180 ELFDumperStyle->printMipsGOT(Parser);
2181 if (Parser.hasPlt())
2182 ELFDumperStyle->printMipsPLT(Parser);
22222183 }
22232184
22242185 static const EnumEntry ElfMipsISAExtType[] = {
35963557 }
35973558 }
35983559
3560 template
3561 void GNUStyle::printMipsGOT(const MipsGOTParser &Parser) {
3562 size_t Bias = ELFT::Is64Bits ? 8 : 0;
3563 auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {
3564 OS.PadToColumn(2);
3565 OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias);
3566 OS.PadToColumn(11 + Bias);
3567 OS << format_decimal(Parser.getGotOffset(E), 6) << "(gp)";
3568 OS.PadToColumn(22 + Bias);
3569 OS << format_hex_no_prefix(*E, 8 + Bias);
3570 OS.PadToColumn(31 + 2 * Bias);
3571 OS << Purpose << "\n";
3572 };
3573
3574 OS << (Parser.IsStatic ? "Static GOT:\n" : "Primary GOT:\n");
3575 OS << " Canonical gp value: "
3576 << format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n";
3577
3578 OS << " Reserved entries:\n";
3579 OS << " Address Access Initial Purpose\n";
3580 PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver");
3581 if (Parser.getGotModulePointer())
3582 PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)");
3583
3584 if (!Parser.getLocalEntries().empty()) {
3585 OS << "\n";
3586 OS << " Local entries:\n";
3587 OS << " Address Access Initial\n";
3588 for (auto &E : Parser.getLocalEntries())
3589 PrintEntry(&E, "");
3590 }
3591
3592 if (Parser.IsStatic)
3593 return;
3594
3595 if (!Parser.getGlobalEntries().empty()) {
3596 OS << "\n";
3597 OS << " Global entries:\n";
3598 OS << " Address Access Initial Sym.Val. Type Ndx Name\n";
3599 for (auto &E : Parser.getGlobalEntries()) {
3600 const Elf_Sym *Sym = Parser.getGotSym(&E);
3601 std::string SymName = this->dumper()->getFullSymbolName(
3602 Sym, this->dumper()->getDynamicStringTable(), false);
3603
3604 OS.PadToColumn(2);
3605 OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias));
3606 OS.PadToColumn(11 + Bias);
3607 OS << to_string(format_decimal(Parser.getGotOffset(&E), 6)) + "(gp)";
3608 OS.PadToColumn(22 + Bias);
3609 OS << to_string(format_hex_no_prefix(E, 8 + Bias));
3610 OS.PadToColumn(31 + 2 * Bias);
3611 OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias));
3612 OS.PadToColumn(40 + 3 * Bias);
3613 OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes));
3614 OS.PadToColumn(48 + 3 * Bias);
3615 OS << getSymbolSectionNdx(Parser.Obj, Sym,
3616 this->dumper()->dynamic_symbols().begin());
3617 OS.PadToColumn(52 + 3 * Bias);
3618 OS << SymName << "\n";
3619 }
3620 }
3621
3622 if (!Parser.getOtherEntries().empty())
3623 OS << "\n Number of TLS and multi-GOT entries "
3624 << Parser.getOtherEntries().size() << "\n";
3625 }
3626
3627 template
3628 void GNUStyle::printMipsPLT(const MipsGOTParser &Parser) {
3629 size_t Bias = ELFT::Is64Bits ? 8 : 0;
3630 auto PrintEntry = [&](const Elf_Addr *E, StringRef Purpose) {
3631 OS.PadToColumn(2);
3632 OS << format_hex_no_prefix(Parser.getGotAddress(E), 8 + Bias);
3633 OS.PadToColumn(11 + Bias);
3634 OS << format_hex_no_prefix(*E, 8 + Bias);
3635 OS.PadToColumn(20 + 2 * Bias);
3636 OS << Purpose << "\n";
3637 };
3638
3639 OS << "PLT GOT:\n\n";
3640
3641 OS << " Reserved entries:\n";
3642 OS << " Address Initial Purpose\n";
3643 PrintEntry(Parser.getPltLazyResolver(), "PLT lazy resolver");
3644 if (Parser.getPltModulePointer())
3645 PrintEntry(Parser.getGotModulePointer(), "Module pointer");
3646
3647 if (!Parser.getPltEntries().empty()) {
3648 OS << "\n";
3649 OS << " Entries:\n";
3650 OS << " Address Initial Sym.Val. Type Ndx Name\n";
3651 for (auto &E : Parser.getPltEntries()) {
3652 const Elf_Sym *Sym = Parser.getPltSym(&E);
3653 std::string SymName = this->dumper()->getFullSymbolName(
3654 Sym, this->dumper()->getDynamicStringTable(), false);
3655
3656 OS.PadToColumn(2);
3657 OS << to_string(format_hex_no_prefix(Parser.getGotAddress(&E), 8 + Bias));
3658 OS.PadToColumn(11 + Bias);
3659 OS << to_string(format_hex_no_prefix(E, 8 + Bias));
3660 OS.PadToColumn(20 + 2 * Bias);
3661 OS << to_string(format_hex_no_prefix(Sym->st_value, 8 + Bias));
3662 OS.PadToColumn(29 + 3 * Bias);
3663 OS << printEnum(Sym->getType(), makeArrayRef(ElfSymbolTypes));
3664 OS.PadToColumn(37 + 3 * Bias);
3665 OS << getSymbolSectionNdx(Parser.Obj, Sym,
3666 this->dumper()->dynamic_symbols().begin());
3667 OS.PadToColumn(41 + 3 * Bias);
3668 OS << SymName << "\n";
3669 }
3670 }
3671 }
3672
35993673 template void LLVMStyle::printFileHeaders(const ELFO *Obj) {
36003674 const Elf_Ehdr *e = Obj->getHeader();
36013675 {
38533927 bool IsDynamic) {
38543928 unsigned SectionIndex = 0;
38553929 StringRef SectionName;
3856 getSectionNameIndex(*Obj, Symbol, First, this->dumper()->getShndxTable(),
3857 SectionName, SectionIndex);
3930 this->dumper()->getSectionNameIndex(Symbol, First, SectionName, SectionIndex);
38583931 std::string FullSymbolName =
38593932 this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic);
38603933 unsigned char SymbolType = Symbol->getType();
39914064 void LLVMStyle::printNotes(const ELFFile *Obj) {
39924065 W.startLine() << "printNotes not implemented!\n";
39934066 }
4067
4068 template
4069 void LLVMStyle::printMipsGOT(const MipsGOTParser &Parser) {
4070 auto PrintEntry = [&](const Elf_Addr *E) {
4071 W.printHex("Address", Parser.getGotAddress(E));
4072 W.printNumber("Access", Parser.getGotOffset(E));
4073 W.printHex("Initial", *E);
4074 };
4075
4076 DictScope GS(W, Parser.IsStatic ? "Static GOT" : "Primary GOT");
4077
4078 W.printHex("Canonical gp value", Parser.getGp());
4079 {
4080 ListScope RS(W, "Reserved entries");
4081 {
4082 DictScope D(W, "Entry");
4083 PrintEntry(Parser.getGotLazyResolver());
4084 W.printString("Purpose", StringRef("Lazy resolver"));
4085 }
4086
4087 if (Parser.getGotModulePointer()) {
4088 DictScope D(W, "Entry");
4089 PrintEntry(Parser.getGotModulePointer());
4090 W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
4091 }
4092 }
4093 {
4094 ListScope LS(W, "Local entries");
4095 for (auto &E : Parser.getLocalEntries()) {
4096 DictScope D(W, "Entry");
4097 PrintEntry(&E);
4098 }
4099 }
4100
4101 if (Parser.IsStatic)
4102 return;
4103
4104 {
4105 ListScope GS(W, "Global entries");
4106 for (auto &E : Parser.getGlobalEntries()) {
4107 DictScope D(W, "Entry");
4108
4109 PrintEntry(&E);
4110
4111 const Elf_Sym *Sym = Parser.getGotSym(&E);
4112 W.printHex("Value", Sym->st_value);
4113 W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
4114
4115 unsigned SectionIndex = 0;
4116 StringRef SectionName;
4117 this->dumper()->getSectionNameIndex(
4118 Sym, this->dumper()->dynamic_symbols().begin(), SectionName,
4119 SectionIndex);
4120 W.printHex("Section", SectionName, SectionIndex);
4121
4122 std::string SymName = this->dumper()->getFullSymbolName(
4123 Sym, this->dumper()->getDynamicStringTable(), true);
4124 W.printNumber("Name", SymName, Sym->st_name);
4125 }
4126 }
4127
4128 W.printNumber("Number of TLS and multi-GOT entries",
4129 Parser.getOtherEntries().size());
4130 }
4131
4132 template
4133 void LLVMStyle::printMipsPLT(const MipsGOTParser &Parser) {
4134 auto PrintEntry = [&](const Elf_Addr *E) {
4135 W.printHex("Address", Parser.getPltAddress(E));
4136 W.printHex("Initial", *E);
4137 };
4138
4139 DictScope GS(W, "PLT GOT");
4140
4141 {
4142 ListScope RS(W, "Reserved entries");
4143 {
4144 DictScope D(W, "Entry");
4145 PrintEntry(Parser.getPltLazyResolver());
4146 W.printString("Purpose", StringRef("PLT lazy resolver"));
4147 }
4148
4149 if (auto E = Parser.getPltModulePointer()) {
4150 DictScope D(W, "Entry");
4151 PrintEntry(E);
4152 W.printString("Purpose", StringRef("Module pointer"));
4153 }
4154 }
4155 {
4156 ListScope LS(W, "Entries");
4157 for (auto &E : Parser.getPltEntries()) {
4158 DictScope D(W, "Entry");
4159 PrintEntry(&E);
4160
4161 const Elf_Sym *Sym = Parser.getPltSym(&E);
4162 W.printHex("Value", Sym->st_value);
4163 W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
4164
4165 unsigned SectionIndex = 0;
4166 StringRef SectionName;
4167 this->dumper()->getSectionNameIndex(
4168 Sym, this->dumper()->dynamic_symbols().begin(), SectionName,
4169 SectionIndex);
4170 W.printHex("Section", SectionName, SectionIndex);
4171
4172 std::string SymName =
4173 this->dumper()->getFullSymbolName(Sym, Parser.getPltStrTable(), true);
4174 W.printNumber("Name", SymName, Sym->st_name);
4175 }
4176 }
4177 }