Skip to content

Commit 8043390

Browse files
committedJun 18, 2014
[llvm-readobj][ELF] New -mips-plt-got command line option to output
MIPS GOT section. Patch reviewed by Rafael Espindola. llvm-svn: 211150
1 parent 831d728 commit 8043390

File tree

6 files changed

+547
-0
lines changed

6 files changed

+547
-0
lines changed
 
Binary file not shown.
+306
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
RUN: llvm-readobj -mips-plt-got %p/Inputs/relocs.obj.elf-mips | \
2+
RUN: FileCheck %s -check-prefix GOT-OBJ
3+
RUN: llvm-readobj -mips-plt-got %p/Inputs/dynamic-table-exe.mips | \
4+
RUN: FileCheck %s -check-prefix GOT-EXE
5+
RUN: llvm-readobj -mips-plt-got %p/Inputs/dynamic-table-so.mips | \
6+
RUN: FileCheck %s -check-prefix GOT-SO
7+
RUN: llvm-readobj -mips-plt-got %p/Inputs/got-tls.so.elf-mips64el | \
8+
RUN: FileCheck %s -check-prefix GOT-TLS
9+
10+
GOT-OBJ: Cannot find PLTGOT dynamic table tag.
11+
12+
GOT-EXE: Primary GOT {
13+
GOT-EXE-NEXT: Canonical gp value: 0x418880
14+
GOT-EXE-NEXT: Reserved entries [
15+
GOT-EXE-NEXT: Entry {
16+
GOT-EXE-NEXT: Address: 0x410890
17+
GOT-EXE-NEXT: Access: -32752
18+
GOT-EXE-NEXT: Initial: 0x0
19+
GOT-EXE-NEXT: Purpose: Lazy resolver
20+
GOT-EXE-NEXT: }
21+
GOT-EXE-NEXT: Entry {
22+
GOT-EXE-NEXT: Address: 0x410894
23+
GOT-EXE-NEXT: Access: -32748
24+
GOT-EXE-NEXT: Initial: 0x80000000
25+
GOT-EXE-NEXT: Purpose: Module pointer (GNU extension)
26+
GOT-EXE-NEXT: }
27+
GOT-EXE-NEXT: ]
28+
GOT-EXE-NEXT: Local entries [
29+
GOT-EXE-NEXT: Entry {
30+
GOT-EXE-NEXT: Address: 0x410898
31+
GOT-EXE-NEXT: Access: -32744
32+
GOT-EXE-NEXT: Initial: 0x400418
33+
GOT-EXE-NEXT: }
34+
GOT-EXE-NEXT: Entry {
35+
GOT-EXE-NEXT: Address: 0x41089C
36+
GOT-EXE-NEXT: Access: -32740
37+
GOT-EXE-NEXT: Initial: 0x410840
38+
GOT-EXE-NEXT: }
39+
GOT-EXE-NEXT: Entry {
40+
GOT-EXE-NEXT: Address: 0x4108A0
41+
GOT-EXE-NEXT: Access: -32736
42+
GOT-EXE-NEXT: Initial: 0x0
43+
GOT-EXE-NEXT: }
44+
GOT-EXE-NEXT: ]
45+
GOT-EXE-NEXT: Global entries [
46+
GOT-EXE-NEXT: Entry {
47+
GOT-EXE-NEXT: Address: 0x4108A4
48+
GOT-EXE-NEXT: Access: -32732
49+
GOT-EXE-NEXT: Initial: 0x0
50+
GOT-EXE-NEXT: Value: 0x0
51+
GOT-EXE-NEXT: Type: Function (0x2)
52+
GOT-EXE-NEXT: Section: Undefined (0x0)
53+
GOT-EXE-NEXT: Name: __gmon_start__@ (1)
54+
GOT-EXE-NEXT: }
55+
GOT-EXE-NEXT: ]
56+
GOT-EXE-NEXT: Number of TLS and multi-GOT entries: 0
57+
GOT-EXE-NEXT: }
58+
59+
GOT-SO: Primary GOT {
60+
GOT-SO-NEXT: Canonical gp value: 0x188D0
61+
GOT-SO-NEXT: Reserved entries [
62+
GOT-SO-NEXT: Entry {
63+
GOT-SO-NEXT: Address: 0x108E0
64+
GOT-SO-NEXT: Access: -32752
65+
GOT-SO-NEXT: Initial: 0x0
66+
GOT-SO-NEXT: Purpose: Lazy resolver
67+
GOT-SO-NEXT: }
68+
GOT-SO-NEXT: Entry {
69+
GOT-SO-NEXT: Address: 0x108E4
70+
GOT-SO-NEXT: Access: -32748
71+
GOT-SO-NEXT: Initial: 0x80000000
72+
GOT-SO-NEXT: Purpose: Module pointer (GNU extension)
73+
GOT-SO-NEXT: }
74+
GOT-SO-NEXT: ]
75+
GOT-SO-NEXT: Local entries [
76+
GOT-SO-NEXT: Entry {
77+
GOT-SO-NEXT: Address: 0x108E8
78+
GOT-SO-NEXT: Access: -32744
79+
GOT-SO-NEXT: Initial: 0x108E0
80+
GOT-SO-NEXT: }
81+
GOT-SO-NEXT: Entry {
82+
GOT-SO-NEXT: Address: 0x108EC
83+
GOT-SO-NEXT: Access: -32740
84+
GOT-SO-NEXT: Initial: 0x10000
85+
GOT-SO-NEXT: }
86+
GOT-SO-NEXT: Entry {
87+
GOT-SO-NEXT: Address: 0x108F0
88+
GOT-SO-NEXT: Access: -32736
89+
GOT-SO-NEXT: Initial: 0x10920
90+
GOT-SO-NEXT: }
91+
GOT-SO-NEXT: Entry {
92+
GOT-SO-NEXT: Address: 0x108F4
93+
GOT-SO-NEXT: Access: -32732
94+
GOT-SO-NEXT: Initial: 0x108CC
95+
GOT-SO-NEXT: }
96+
GOT-SO-NEXT: Entry {
97+
GOT-SO-NEXT: Address: 0x108F8
98+
GOT-SO-NEXT: Access: -32728
99+
GOT-SO-NEXT: Initial: 0x0
100+
GOT-SO-NEXT: }
101+
GOT-SO-NEXT: Entry {
102+
GOT-SO-NEXT: Address: 0x108FC
103+
GOT-SO-NEXT: Access: -32724
104+
GOT-SO-NEXT: Initial: 0x0
105+
GOT-SO-NEXT: }
106+
GOT-SO-NEXT: Entry {
107+
GOT-SO-NEXT: Address: 0x10900
108+
GOT-SO-NEXT: Access: -32720
109+
GOT-SO-NEXT: Initial: 0x0
110+
GOT-SO-NEXT: }
111+
GOT-SO-NEXT: Entry {
112+
GOT-SO-NEXT: Address: 0x10904
113+
GOT-SO-NEXT: Access: -32716
114+
GOT-SO-NEXT: Initial: 0x0
115+
GOT-SO-NEXT: }
116+
GOT-SO-NEXT: ]
117+
GOT-SO-NEXT: Global entries [
118+
GOT-SO-NEXT: Entry {
119+
GOT-SO-NEXT: Address: 0x10908
120+
GOT-SO-NEXT: Access: -32712
121+
GOT-SO-NEXT: Initial: 0x0
122+
GOT-SO-NEXT: Value: 0x0
123+
GOT-SO-NEXT: Type: None (0x0)
124+
GOT-SO-NEXT: Section: Undefined (0x0)
125+
GOT-SO-NEXT: Name: _ITM_registerTMCloneTable@ (87)
126+
GOT-SO-NEXT: }
127+
GOT-SO-NEXT: Entry {
128+
GOT-SO-NEXT: Address: 0x1090C
129+
GOT-SO-NEXT: Access: -32708
130+
GOT-SO-NEXT: Initial: 0x0
131+
GOT-SO-NEXT: Value: 0x0
132+
GOT-SO-NEXT: Type: None (0x0)
133+
GOT-SO-NEXT: Section: Undefined (0x0)
134+
GOT-SO-NEXT: Name: _Jv_RegisterClasses@ (128)
135+
GOT-SO-NEXT: }
136+
GOT-SO-NEXT: Entry {
137+
GOT-SO-NEXT: Address: 0x10910
138+
GOT-SO-NEXT: Access: -32704
139+
GOT-SO-NEXT: Initial: 0x0
140+
GOT-SO-NEXT: Value: 0x0
141+
GOT-SO-NEXT: Type: Function (0x2)
142+
GOT-SO-NEXT: Section: Undefined (0x0)
143+
GOT-SO-NEXT: Name: __gmon_start__@ (23)
144+
GOT-SO-NEXT: }
145+
GOT-SO-NEXT: Entry {
146+
GOT-SO-NEXT: Address: 0x10914
147+
GOT-SO-NEXT: Access: -32700
148+
GOT-SO-NEXT: Initial: 0x840
149+
GOT-SO-NEXT: Value: 0x840
150+
GOT-SO-NEXT: Type: Function (0x2)
151+
GOT-SO-NEXT: Section: Undefined (0x0)
152+
GOT-SO-NEXT: Name: puts@GLIBC_2.0 (162)
153+
GOT-SO-NEXT: }
154+
GOT-SO-NEXT: Entry {
155+
GOT-SO-NEXT: Address: 0x10918
156+
GOT-SO-NEXT: Access: -32696
157+
GOT-SO-NEXT: Initial: 0x0
158+
GOT-SO-NEXT: Value: 0x0
159+
GOT-SO-NEXT: Type: None (0x0)
160+
GOT-SO-NEXT: Section: Undefined (0x0)
161+
GOT-SO-NEXT: Name: _ITM_deregisterTMCloneTable@ (59)
162+
GOT-SO-NEXT: }
163+
GOT-SO-NEXT: Entry {
164+
GOT-SO-NEXT: Address: 0x1091C
165+
GOT-SO-NEXT: Access: -32692
166+
GOT-SO-NEXT: Initial: 0x0
167+
GOT-SO-NEXT: Value: 0x0
168+
GOT-SO-NEXT: Type: Function (0x2)
169+
GOT-SO-NEXT: Section: Undefined (0x0)
170+
GOT-SO-NEXT: Name: __cxa_finalize@GLIBC_2.2 (113)
171+
GOT-SO-NEXT: }
172+
GOT-SO-NEXT: ]
173+
GOT-SO-NEXT: Number of TLS and multi-GOT entries: 0
174+
GOT-SO-NEXT: }
175+
176+
GOT-TLS: Primary GOT {
177+
GOT-TLS-NEXT: Canonical gp value: 0x18BF0
178+
GOT-TLS-NEXT: Reserved entries [
179+
GOT-TLS-NEXT: Entry {
180+
GOT-TLS-NEXT: Address: 0x10C00
181+
GOT-TLS-NEXT: Access: -32752
182+
GOT-TLS-NEXT: Initial: 0x0
183+
GOT-TLS-NEXT: Purpose: Lazy resolver
184+
GOT-TLS-NEXT: }
185+
GOT-TLS-NEXT: Entry {
186+
GOT-TLS-NEXT: Address: 0x10C08
187+
GOT-TLS-NEXT: Access: -32744
188+
GOT-TLS-NEXT: Initial: 0x8000000000000000
189+
GOT-TLS-NEXT: Purpose: Module pointer (GNU extension)
190+
GOT-TLS-NEXT: }
191+
GOT-TLS-NEXT: ]
192+
GOT-TLS-NEXT: Local entries [
193+
GOT-TLS-NEXT: Entry {
194+
GOT-TLS-NEXT: Address: 0x10C10
195+
GOT-TLS-NEXT: Access: -32736
196+
GOT-TLS-NEXT: Initial: 0x10000
197+
GOT-TLS-NEXT: }
198+
GOT-TLS-NEXT: Entry {
199+
GOT-TLS-NEXT: Address: 0x10C18
200+
GOT-TLS-NEXT: Access: -32728
201+
GOT-TLS-NEXT: Initial: 0x10C00
202+
GOT-TLS-NEXT: }
203+
GOT-TLS-NEXT: Entry {
204+
GOT-TLS-NEXT: Address: 0x10C20
205+
GOT-TLS-NEXT: Access: -32720
206+
GOT-TLS-NEXT: Initial: 0x10CB8
207+
GOT-TLS-NEXT: }
208+
GOT-TLS-NEXT: Entry {
209+
GOT-TLS-NEXT: Address: 0x10C28
210+
GOT-TLS-NEXT: Access: -32712
211+
GOT-TLS-NEXT: Initial: 0x10BF0
212+
GOT-TLS-NEXT: }
213+
GOT-TLS-NEXT: Entry {
214+
GOT-TLS-NEXT: Address: 0x10C30
215+
GOT-TLS-NEXT: Access: -32704
216+
GOT-TLS-NEXT: Initial: 0x0
217+
GOT-TLS-NEXT: }
218+
GOT-TLS-NEXT: Entry {
219+
GOT-TLS-NEXT: Address: 0x10C38
220+
GOT-TLS-NEXT: Access: -32696
221+
GOT-TLS-NEXT: Initial: 0x948
222+
GOT-TLS-NEXT: }
223+
GOT-TLS-NEXT: Entry {
224+
GOT-TLS-NEXT: Address: 0x10C40
225+
GOT-TLS-NEXT: Access: -32688
226+
GOT-TLS-NEXT: Initial: 0xA20
227+
GOT-TLS-NEXT: }
228+
GOT-TLS-NEXT: Entry {
229+
GOT-TLS-NEXT: Address: 0x10C48
230+
GOT-TLS-NEXT: Access: -32680
231+
GOT-TLS-NEXT: Initial: 0xAF0
232+
GOT-TLS-NEXT: }
233+
GOT-TLS-NEXT: Entry {
234+
GOT-TLS-NEXT: Address: 0x10C50
235+
GOT-TLS-NEXT: Access: -32672
236+
GOT-TLS-NEXT: Initial: 0x0
237+
GOT-TLS-NEXT: }
238+
GOT-TLS-NEXT: Entry {
239+
GOT-TLS-NEXT: Address: 0x10C58
240+
GOT-TLS-NEXT: Access: -32664
241+
GOT-TLS-NEXT: Initial: 0x0
242+
GOT-TLS-NEXT: }
243+
GOT-TLS-NEXT: Entry {
244+
GOT-TLS-NEXT: Address: 0x10C60
245+
GOT-TLS-NEXT: Access: -32656
246+
GOT-TLS-NEXT: Initial: 0x0
247+
GOT-TLS-NEXT: }
248+
GOT-TLS-NEXT: ]
249+
GOT-TLS-NEXT: Global entries [
250+
GOT-TLS-NEXT: Entry {
251+
GOT-TLS-NEXT: Address: 0x10C68
252+
GOT-TLS-NEXT: Access: -32648
253+
GOT-TLS-NEXT: Initial: 0x0
254+
GOT-TLS-NEXT: Value: 0x0
255+
GOT-TLS-NEXT: Type: None (0x0)
256+
GOT-TLS-NEXT: Section: Undefined (0x0)
257+
GOT-TLS-NEXT: Name: _ITM_registerTMCloneTable@ (78)
258+
GOT-TLS-NEXT: }
259+
GOT-TLS-NEXT: Entry {
260+
GOT-TLS-NEXT: Address: 0x10C70
261+
GOT-TLS-NEXT: Access: -32640
262+
GOT-TLS-NEXT: Initial: 0x0
263+
GOT-TLS-NEXT: Value: 0x0
264+
GOT-TLS-NEXT: Type: None (0x0)
265+
GOT-TLS-NEXT: Section: Undefined (0x0)
266+
GOT-TLS-NEXT: Name: _Jv_RegisterClasses@ (119)
267+
GOT-TLS-NEXT: }
268+
GOT-TLS-NEXT: Entry {
269+
GOT-TLS-NEXT: Address: 0x10C78
270+
GOT-TLS-NEXT: Access: -32632
271+
GOT-TLS-NEXT: Initial: 0x0
272+
GOT-TLS-NEXT: Value: 0x0
273+
GOT-TLS-NEXT: Type: Function (0x2)
274+
GOT-TLS-NEXT: Section: Undefined (0x0)
275+
GOT-TLS-NEXT: Name: __gmon_start__@ (23)
276+
GOT-TLS-NEXT: }
277+
GOT-TLS-NEXT: Entry {
278+
GOT-TLS-NEXT: Address: 0x10C80
279+
GOT-TLS-NEXT: Access: -32624
280+
GOT-TLS-NEXT: Initial: 0xB60
281+
GOT-TLS-NEXT: Value: 0xB60
282+
GOT-TLS-NEXT: Type: Function (0x2)
283+
GOT-TLS-NEXT: Section: Undefined (0x0)
284+
GOT-TLS-NEXT: Name: __tls_get_addr@GLIBC_2.3 (150)
285+
GOT-TLS-NEXT: }
286+
GOT-TLS-NEXT: Entry {
287+
GOT-TLS-NEXT: Address: 0x10C88
288+
GOT-TLS-NEXT: Access: -32616
289+
GOT-TLS-NEXT: Initial: 0x0
290+
GOT-TLS-NEXT: Value: 0x0
291+
GOT-TLS-NEXT: Type: None (0x0)
292+
GOT-TLS-NEXT: Section: Undefined (0x0)
293+
GOT-TLS-NEXT: Name: _ITM_deregisterTMCloneTable@ (50)
294+
GOT-TLS-NEXT: }
295+
GOT-TLS-NEXT: Entry {
296+
GOT-TLS-NEXT: Address: 0x10C90
297+
GOT-TLS-NEXT: Access: -32608
298+
GOT-TLS-NEXT: Initial: 0x0
299+
GOT-TLS-NEXT: Value: 0x0
300+
GOT-TLS-NEXT: Type: Function (0x2)
301+
GOT-TLS-NEXT: Section: Undefined (0x0)
302+
GOT-TLS-NEXT: Name: __cxa_finalize@GLIBC_2.2 (104)
303+
GOT-TLS-NEXT: }
304+
GOT-TLS-NEXT: ]
305+
GOT-TLS-NEXT: Number of TLS and multi-GOT entries: 4
306+
GOT-TLS-NEXT: }

‎llvm/tools/llvm-readobj/ELFDumper.cpp

+217
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "Error.h"
1919
#include "ObjDumper.h"
2020
#include "StreamWriter.h"
21+
#include "llvm/ADT/Optional.h"
2122
#include "llvm/ADT/SmallString.h"
2223
#include "llvm/ADT/StringExtras.h"
2324
#include "llvm/Object/ELFObjectFile.h"
@@ -54,6 +55,7 @@ class ELFDumper : public ObjDumper {
5455
void printProgramHeaders() override;
5556

5657
void printAttributes() override;
58+
void printMipsPLTGOT() override;
5759

5860
private:
5961
typedef ELFFile<ELFT> ELFO;
@@ -159,6 +161,15 @@ getSectionNameIndex(const ELFO &Obj, typename ELFO::Elf_Sym_Iter Symbol,
159161
}
160162
}
161163

164+
template <class ELFT>
165+
static const typename ELFFile<ELFT>::Elf_Shdr *
166+
findSectionByAddress(const ELFFile<ELFT> *Obj, uint64_t Addr) {
167+
for (const auto &Shdr : Obj->sections())
168+
if (Shdr.sh_addr == Addr)
169+
return &Shdr;
170+
return nullptr;
171+
}
172+
162173
static const EnumEntry<unsigned> ElfClass[] = {
163174
{ "None", ELF::ELFCLASSNONE },
164175
{ "32-bit", ELF::ELFCLASS32 },
@@ -1021,3 +1032,209 @@ void ELFDumper<ELFType<support::little, 2, false> >::printAttributes() {
10211032
}
10221033
}
10231034

1035+
namespace {
1036+
template <class ELFT> class MipsGOTParser {
1037+
public:
1038+
typedef object::ELFFile<ELFT> ObjectFile;
1039+
typedef typename ObjectFile::Elf_Shdr Elf_Shdr;
1040+
1041+
MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) : Obj(Obj), W(W) {}
1042+
1043+
void ParseGOT(const Elf_Shdr &GOTShdr);
1044+
1045+
private:
1046+
typedef typename ObjectFile::Elf_Sym_Iter Elf_Sym_Iter;
1047+
typedef typename ObjectFile::Elf_Addr GOTEntry;
1048+
typedef typename ObjectFile::template ELFEntityIterator<const GOTEntry>
1049+
GOTIter;
1050+
1051+
const ObjectFile *Obj;
1052+
StreamWriter &W;
1053+
1054+
std::size_t GetGOTTotal(ArrayRef<uint8_t> GOT) const;
1055+
GOTIter MakeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum);
1056+
1057+
bool getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym);
1058+
void printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It);
1059+
void printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It,
1060+
Elf_Sym_Iter Sym);
1061+
};
1062+
}
1063+
1064+
template <class ELFT>
1065+
void MipsGOTParser<ELFT>::ParseGOT(const Elf_Shdr &GOTShdr) {
1066+
// See "Global Offset Table" in Chapter 5 in the following document
1067+
// for detailed GOT description.
1068+
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
1069+
1070+
ErrorOr<ArrayRef<uint8_t>> GOT = Obj->getSectionContents(&GOTShdr);
1071+
if (!GOT) {
1072+
W.startLine() << "The .got section is empty.\n";
1073+
return;
1074+
}
1075+
1076+
uint64_t DtLocalGotNum;
1077+
uint64_t DtGotSym;
1078+
if (!getGOTTags(DtLocalGotNum, DtGotSym))
1079+
return;
1080+
1081+
if (DtLocalGotNum > GetGOTTotal(*GOT)) {
1082+
W.startLine() << "MIPS_LOCAL_GOTNO exceeds a number of GOT entries.\n";
1083+
return;
1084+
}
1085+
1086+
Elf_Sym_Iter DynSymBegin = Obj->begin_dynamic_symbols();
1087+
Elf_Sym_Iter DynSymEnd = Obj->end_dynamic_symbols();
1088+
std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
1089+
1090+
if (DtGotSym + 1 > DynSymTotal) {
1091+
W.startLine() << "MIPS_GOTSYM exceeds a number of dynamic symbols.\n";
1092+
return;
1093+
}
1094+
1095+
std::size_t GlobalGotNum = DynSymTotal - DtGotSym;
1096+
1097+
if (DtLocalGotNum + GlobalGotNum > GetGOTTotal(*GOT)) {
1098+
W.startLine() << "Number of global GOT entries exceeds the size of GOT.\n";
1099+
return;
1100+
}
1101+
1102+
GOTIter GotBegin = MakeGOTIter(*GOT, 0);
1103+
GOTIter GotLocalEnd = MakeGOTIter(*GOT, DtLocalGotNum);
1104+
GOTIter It = GotBegin;
1105+
1106+
DictScope GS(W, "Primary GOT");
1107+
1108+
W.printHex("Canonical gp value", GOTShdr.sh_addr + 0x7ff0);
1109+
{
1110+
ListScope RS(W, "Reserved entries");
1111+
1112+
{
1113+
DictScope D(W, "Entry");
1114+
printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
1115+
W.printString("Purpose", StringRef("Lazy resolver"));
1116+
}
1117+
1118+
if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) {
1119+
DictScope D(W, "Entry");
1120+
printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
1121+
W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
1122+
}
1123+
}
1124+
{
1125+
ListScope LS(W, "Local entries");
1126+
for (; It != GotLocalEnd; ++It) {
1127+
DictScope D(W, "Entry");
1128+
printGotEntry(GOTShdr.sh_addr, GotBegin, It);
1129+
}
1130+
}
1131+
{
1132+
ListScope GS(W, "Global entries");
1133+
1134+
GOTIter GotGlobalEnd = MakeGOTIter(*GOT, DtLocalGotNum + GlobalGotNum);
1135+
Elf_Sym_Iter GotDynSym = DynSymBegin + DtGotSym;
1136+
for (; It != GotGlobalEnd; ++It) {
1137+
DictScope D(W, "Entry");
1138+
printGlobalGotEntry(GOTShdr.sh_addr, GotBegin, It, GotDynSym++);
1139+
}
1140+
}
1141+
1142+
std::size_t SpecGotNum = GetGOTTotal(*GOT) - DtLocalGotNum - GlobalGotNum;
1143+
W.printNumber("Number of TLS and multi-GOT entries", SpecGotNum);
1144+
}
1145+
1146+
template <class ELFT>
1147+
std::size_t MipsGOTParser<ELFT>::GetGOTTotal(ArrayRef<uint8_t> GOT) const {
1148+
return GOT.size() / sizeof(GOTEntry);
1149+
}
1150+
1151+
template <class ELFT>
1152+
typename MipsGOTParser<ELFT>::GOTIter
1153+
MipsGOTParser<ELFT>::MakeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum) {
1154+
const char *Data = reinterpret_cast<const char *>(GOT.data());
1155+
return GOTIter(sizeof(GOTEntry), Data + EntryNum * sizeof(GOTEntry));
1156+
}
1157+
1158+
template <class ELFT>
1159+
bool MipsGOTParser<ELFT>::getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym) {
1160+
bool FoundLocalGotNum = false;
1161+
bool FoundGotSym = false;
1162+
for (const auto &Entry : Obj->dynamic_table()) {
1163+
switch (Entry.getTag()) {
1164+
case ELF::DT_MIPS_LOCAL_GOTNO:
1165+
LocalGotNum = Entry.getVal();
1166+
FoundLocalGotNum = true;
1167+
break;
1168+
case ELF::DT_MIPS_GOTSYM:
1169+
GotSym = Entry.getVal();
1170+
FoundGotSym = true;
1171+
break;
1172+
}
1173+
}
1174+
1175+
if (!FoundLocalGotNum) {
1176+
W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n";
1177+
return false;
1178+
}
1179+
1180+
if (!FoundGotSym) {
1181+
W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n";
1182+
return false;
1183+
}
1184+
1185+
return true;
1186+
}
1187+
1188+
template <class ELFT>
1189+
void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr, GOTIter BeginIt,
1190+
GOTIter It) {
1191+
int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
1192+
W.printHex("Address", GotAddr + Offset);
1193+
W.printNumber("Access", Offset - 0x7ff0);
1194+
W.printHex("Initial", *It);
1195+
}
1196+
1197+
template <class ELFT>
1198+
void MipsGOTParser<ELFT>::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt,
1199+
GOTIter It, Elf_Sym_Iter Sym) {
1200+
printGotEntry(GotAddr, BeginIt, It);
1201+
1202+
W.printHex("Value", Sym->st_value);
1203+
W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
1204+
1205+
unsigned SectionIndex = 0;
1206+
StringRef SectionName;
1207+
getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
1208+
W.printHex("Section", SectionName, SectionIndex);
1209+
1210+
std::string FullSymbolName = getFullSymbolName(*Obj, Sym);
1211+
W.printNumber("Name", FullSymbolName, Sym->st_name);
1212+
}
1213+
1214+
template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
1215+
if (Obj->getHeader()->e_machine != EM_MIPS) {
1216+
W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n";
1217+
return;
1218+
}
1219+
1220+
llvm::Optional<uint64_t> DtPltGot;
1221+
for (const auto &Entry : Obj->dynamic_table()) {
1222+
if (Entry.getTag() == ELF::DT_PLTGOT) {
1223+
DtPltGot = Entry.getVal();
1224+
break;
1225+
}
1226+
}
1227+
1228+
if (!DtPltGot) {
1229+
W.startLine() << "Cannot find PLTGOT dynamic table tag.\n";
1230+
return;
1231+
}
1232+
1233+
const Elf_Shdr *GotShdr = findSectionByAddress(Obj, *DtPltGot);
1234+
if (!GotShdr) {
1235+
W.startLine() << "There is no .got section in the file.\n";
1236+
return;
1237+
}
1238+
1239+
MipsGOTParser<ELFT>(Obj, W).ParseGOT(*GotShdr);
1240+
}

‎llvm/tools/llvm-readobj/ObjDumper.h

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class ObjDumper {
4040
// Only implemented for ARM ELF at this time.
4141
virtual void printAttributes() { }
4242

43+
// Only implemented for MIPS ELF at this time.
44+
virtual void printMipsPLTGOT() { }
45+
4346
protected:
4447
StreamWriter& W;
4548
};

‎llvm/tools/llvm-readobj/llvm-readobj.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ namespace opts {
135135
cl::desc("Display the ARM attributes section"));
136136
cl::alias ARMAttributesShort("-a", cl::desc("Alias for --arm-attributes"),
137137
cl::aliasopt(ARMAttributes));
138+
139+
// -mips-plt-got
140+
cl::opt<bool>
141+
MipsPLTGOT("mips-plt-got",
142+
cl::desc("Display the MIPS GOT and PLT GOT sections"));
138143
} // namespace opts
139144

140145
static int ReturnValue = EXIT_SUCCESS;
@@ -177,6 +182,18 @@ static void reportError(StringRef Input, StringRef Message) {
177182
ReturnValue = EXIT_FAILURE;
178183
}
179184

185+
static bool isMipsArch(unsigned Arch) {
186+
switch (Arch) {
187+
case llvm::Triple::mips:
188+
case llvm::Triple::mipsel:
189+
case llvm::Triple::mips64:
190+
case llvm::Triple::mips64el:
191+
return true;
192+
default:
193+
return false;
194+
}
195+
}
196+
180197
/// @brief Creates an format-specific object file dumper.
181198
static std::error_code createDumper(const ObjectFile *Obj, StreamWriter &Writer,
182199
std::unique_ptr<ObjDumper> &Result) {
@@ -234,6 +251,9 @@ static void dumpObject(const ObjectFile *Obj) {
234251
if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())
235252
if (opts::ARMAttributes)
236253
Dumper->printAttributes();
254+
if (isMipsArch(Obj->getArch()) && Obj->isELF())
255+
if (opts::MipsPLTGOT)
256+
Dumper->printMipsPLTGOT();
237257
}
238258

239259

‎llvm/tools/llvm-readobj/llvm-readobj.h

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ namespace opts {
3838
extern llvm::cl::opt<bool> ExpandRelocs;
3939
extern llvm::cl::opt<bool> CodeViewLineTables;
4040
extern llvm::cl::opt<bool> ARMAttributes;
41+
extern llvm::cl::opt<bool> MipsPLTGOT;
4142
} // namespace opts
4243

4344
#define LLVM_READOBJ_ENUM_ENT(ns, enum) \

0 commit comments

Comments
 (0)
Please sign in to comment.