llvm.org GIT mirror llvm / 42469f6
[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 Simon Atanasyan 6 years ago
6 changed file(s) with 547 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 RUN: llvm-readobj -mips-plt-got %p/Inputs/relocs.obj.elf-mips | \
1 RUN: FileCheck %s -check-prefix GOT-OBJ
2 RUN: llvm-readobj -mips-plt-got %p/Inputs/dynamic-table-exe.mips | \
3 RUN: FileCheck %s -check-prefix GOT-EXE
4 RUN: llvm-readobj -mips-plt-got %p/Inputs/dynamic-table-so.mips | \
5 RUN: FileCheck %s -check-prefix GOT-SO
6 RUN: llvm-readobj -mips-plt-got %p/Inputs/got-tls.so.elf-mips64el | \
7 RUN: FileCheck %s -check-prefix GOT-TLS
8
9 GOT-OBJ: Cannot find PLTGOT dynamic table tag.
10
11 GOT-EXE: Primary GOT {
12 GOT-EXE-NEXT: Canonical gp value: 0x418880
13 GOT-EXE-NEXT: Reserved entries [
14 GOT-EXE-NEXT: Entry {
15 GOT-EXE-NEXT: Address: 0x410890
16 GOT-EXE-NEXT: Access: -32752
17 GOT-EXE-NEXT: Initial: 0x0
18 GOT-EXE-NEXT: Purpose: Lazy resolver
19 GOT-EXE-NEXT: }
20 GOT-EXE-NEXT: Entry {
21 GOT-EXE-NEXT: Address: 0x410894
22 GOT-EXE-NEXT: Access: -32748
23 GOT-EXE-NEXT: Initial: 0x80000000
24 GOT-EXE-NEXT: Purpose: Module pointer (GNU extension)
25 GOT-EXE-NEXT: }
26 GOT-EXE-NEXT: ]
27 GOT-EXE-NEXT: Local entries [
28 GOT-EXE-NEXT: Entry {
29 GOT-EXE-NEXT: Address: 0x410898
30 GOT-EXE-NEXT: Access: -32744
31 GOT-EXE-NEXT: Initial: 0x400418
32 GOT-EXE-NEXT: }
33 GOT-EXE-NEXT: Entry {
34 GOT-EXE-NEXT: Address: 0x41089C
35 GOT-EXE-NEXT: Access: -32740
36 GOT-EXE-NEXT: Initial: 0x410840
37 GOT-EXE-NEXT: }
38 GOT-EXE-NEXT: Entry {
39 GOT-EXE-NEXT: Address: 0x4108A0
40 GOT-EXE-NEXT: Access: -32736
41 GOT-EXE-NEXT: Initial: 0x0
42 GOT-EXE-NEXT: }
43 GOT-EXE-NEXT: ]
44 GOT-EXE-NEXT: Global entries [
45 GOT-EXE-NEXT: Entry {
46 GOT-EXE-NEXT: Address: 0x4108A4
47 GOT-EXE-NEXT: Access: -32732
48 GOT-EXE-NEXT: Initial: 0x0
49 GOT-EXE-NEXT: Value: 0x0
50 GOT-EXE-NEXT: Type: Function (0x2)
51 GOT-EXE-NEXT: Section: Undefined (0x0)
52 GOT-EXE-NEXT: Name: __gmon_start__@ (1)
53 GOT-EXE-NEXT: }
54 GOT-EXE-NEXT: ]
55 GOT-EXE-NEXT: Number of TLS and multi-GOT entries: 0
56 GOT-EXE-NEXT: }
57
58 GOT-SO: Primary GOT {
59 GOT-SO-NEXT: Canonical gp value: 0x188D0
60 GOT-SO-NEXT: Reserved entries [
61 GOT-SO-NEXT: Entry {
62 GOT-SO-NEXT: Address: 0x108E0
63 GOT-SO-NEXT: Access: -32752
64 GOT-SO-NEXT: Initial: 0x0
65 GOT-SO-NEXT: Purpose: Lazy resolver
66 GOT-SO-NEXT: }
67 GOT-SO-NEXT: Entry {
68 GOT-SO-NEXT: Address: 0x108E4
69 GOT-SO-NEXT: Access: -32748
70 GOT-SO-NEXT: Initial: 0x80000000
71 GOT-SO-NEXT: Purpose: Module pointer (GNU extension)
72 GOT-SO-NEXT: }
73 GOT-SO-NEXT: ]
74 GOT-SO-NEXT: Local entries [
75 GOT-SO-NEXT: Entry {
76 GOT-SO-NEXT: Address: 0x108E8
77 GOT-SO-NEXT: Access: -32744
78 GOT-SO-NEXT: Initial: 0x108E0
79 GOT-SO-NEXT: }
80 GOT-SO-NEXT: Entry {
81 GOT-SO-NEXT: Address: 0x108EC
82 GOT-SO-NEXT: Access: -32740
83 GOT-SO-NEXT: Initial: 0x10000
84 GOT-SO-NEXT: }
85 GOT-SO-NEXT: Entry {
86 GOT-SO-NEXT: Address: 0x108F0
87 GOT-SO-NEXT: Access: -32736
88 GOT-SO-NEXT: Initial: 0x10920
89 GOT-SO-NEXT: }
90 GOT-SO-NEXT: Entry {
91 GOT-SO-NEXT: Address: 0x108F4
92 GOT-SO-NEXT: Access: -32732
93 GOT-SO-NEXT: Initial: 0x108CC
94 GOT-SO-NEXT: }
95 GOT-SO-NEXT: Entry {
96 GOT-SO-NEXT: Address: 0x108F8
97 GOT-SO-NEXT: Access: -32728
98 GOT-SO-NEXT: Initial: 0x0
99 GOT-SO-NEXT: }
100 GOT-SO-NEXT: Entry {
101 GOT-SO-NEXT: Address: 0x108FC
102 GOT-SO-NEXT: Access: -32724
103 GOT-SO-NEXT: Initial: 0x0
104 GOT-SO-NEXT: }
105 GOT-SO-NEXT: Entry {
106 GOT-SO-NEXT: Address: 0x10900
107 GOT-SO-NEXT: Access: -32720
108 GOT-SO-NEXT: Initial: 0x0
109 GOT-SO-NEXT: }
110 GOT-SO-NEXT: Entry {
111 GOT-SO-NEXT: Address: 0x10904
112 GOT-SO-NEXT: Access: -32716
113 GOT-SO-NEXT: Initial: 0x0
114 GOT-SO-NEXT: }
115 GOT-SO-NEXT: ]
116 GOT-SO-NEXT: Global entries [
117 GOT-SO-NEXT: Entry {
118 GOT-SO-NEXT: Address: 0x10908
119 GOT-SO-NEXT: Access: -32712
120 GOT-SO-NEXT: Initial: 0x0
121 GOT-SO-NEXT: Value: 0x0
122 GOT-SO-NEXT: Type: None (0x0)
123 GOT-SO-NEXT: Section: Undefined (0x0)
124 GOT-SO-NEXT: Name: _ITM_registerTMCloneTable@ (87)
125 GOT-SO-NEXT: }
126 GOT-SO-NEXT: Entry {
127 GOT-SO-NEXT: Address: 0x1090C
128 GOT-SO-NEXT: Access: -32708
129 GOT-SO-NEXT: Initial: 0x0
130 GOT-SO-NEXT: Value: 0x0
131 GOT-SO-NEXT: Type: None (0x0)
132 GOT-SO-NEXT: Section: Undefined (0x0)
133 GOT-SO-NEXT: Name: _Jv_RegisterClasses@ (128)
134 GOT-SO-NEXT: }
135 GOT-SO-NEXT: Entry {
136 GOT-SO-NEXT: Address: 0x10910
137 GOT-SO-NEXT: Access: -32704
138 GOT-SO-NEXT: Initial: 0x0
139 GOT-SO-NEXT: Value: 0x0
140 GOT-SO-NEXT: Type: Function (0x2)
141 GOT-SO-NEXT: Section: Undefined (0x0)
142 GOT-SO-NEXT: Name: __gmon_start__@ (23)
143 GOT-SO-NEXT: }
144 GOT-SO-NEXT: Entry {
145 GOT-SO-NEXT: Address: 0x10914
146 GOT-SO-NEXT: Access: -32700
147 GOT-SO-NEXT: Initial: 0x840
148 GOT-SO-NEXT: Value: 0x840
149 GOT-SO-NEXT: Type: Function (0x2)
150 GOT-SO-NEXT: Section: Undefined (0x0)
151 GOT-SO-NEXT: Name: puts@GLIBC_2.0 (162)
152 GOT-SO-NEXT: }
153 GOT-SO-NEXT: Entry {
154 GOT-SO-NEXT: Address: 0x10918
155 GOT-SO-NEXT: Access: -32696
156 GOT-SO-NEXT: Initial: 0x0
157 GOT-SO-NEXT: Value: 0x0
158 GOT-SO-NEXT: Type: None (0x0)
159 GOT-SO-NEXT: Section: Undefined (0x0)
160 GOT-SO-NEXT: Name: _ITM_deregisterTMCloneTable@ (59)
161 GOT-SO-NEXT: }
162 GOT-SO-NEXT: Entry {
163 GOT-SO-NEXT: Address: 0x1091C
164 GOT-SO-NEXT: Access: -32692
165 GOT-SO-NEXT: Initial: 0x0
166 GOT-SO-NEXT: Value: 0x0
167 GOT-SO-NEXT: Type: Function (0x2)
168 GOT-SO-NEXT: Section: Undefined (0x0)
169 GOT-SO-NEXT: Name: __cxa_finalize@GLIBC_2.2 (113)
170 GOT-SO-NEXT: }
171 GOT-SO-NEXT: ]
172 GOT-SO-NEXT: Number of TLS and multi-GOT entries: 0
173 GOT-SO-NEXT: }
174
175 GOT-TLS: Primary GOT {
176 GOT-TLS-NEXT: Canonical gp value: 0x18BF0
177 GOT-TLS-NEXT: Reserved entries [
178 GOT-TLS-NEXT: Entry {
179 GOT-TLS-NEXT: Address: 0x10C00
180 GOT-TLS-NEXT: Access: -32752
181 GOT-TLS-NEXT: Initial: 0x0
182 GOT-TLS-NEXT: Purpose: Lazy resolver
183 GOT-TLS-NEXT: }
184 GOT-TLS-NEXT: Entry {
185 GOT-TLS-NEXT: Address: 0x10C08
186 GOT-TLS-NEXT: Access: -32744
187 GOT-TLS-NEXT: Initial: 0x8000000000000000
188 GOT-TLS-NEXT: Purpose: Module pointer (GNU extension)
189 GOT-TLS-NEXT: }
190 GOT-TLS-NEXT: ]
191 GOT-TLS-NEXT: Local entries [
192 GOT-TLS-NEXT: Entry {
193 GOT-TLS-NEXT: Address: 0x10C10
194 GOT-TLS-NEXT: Access: -32736
195 GOT-TLS-NEXT: Initial: 0x10000
196 GOT-TLS-NEXT: }
197 GOT-TLS-NEXT: Entry {
198 GOT-TLS-NEXT: Address: 0x10C18
199 GOT-TLS-NEXT: Access: -32728
200 GOT-TLS-NEXT: Initial: 0x10C00
201 GOT-TLS-NEXT: }
202 GOT-TLS-NEXT: Entry {
203 GOT-TLS-NEXT: Address: 0x10C20
204 GOT-TLS-NEXT: Access: -32720
205 GOT-TLS-NEXT: Initial: 0x10CB8
206 GOT-TLS-NEXT: }
207 GOT-TLS-NEXT: Entry {
208 GOT-TLS-NEXT: Address: 0x10C28
209 GOT-TLS-NEXT: Access: -32712
210 GOT-TLS-NEXT: Initial: 0x10BF0
211 GOT-TLS-NEXT: }
212 GOT-TLS-NEXT: Entry {
213 GOT-TLS-NEXT: Address: 0x10C30
214 GOT-TLS-NEXT: Access: -32704
215 GOT-TLS-NEXT: Initial: 0x0
216 GOT-TLS-NEXT: }
217 GOT-TLS-NEXT: Entry {
218 GOT-TLS-NEXT: Address: 0x10C38
219 GOT-TLS-NEXT: Access: -32696
220 GOT-TLS-NEXT: Initial: 0x948
221 GOT-TLS-NEXT: }
222 GOT-TLS-NEXT: Entry {
223 GOT-TLS-NEXT: Address: 0x10C40
224 GOT-TLS-NEXT: Access: -32688
225 GOT-TLS-NEXT: Initial: 0xA20
226 GOT-TLS-NEXT: }
227 GOT-TLS-NEXT: Entry {
228 GOT-TLS-NEXT: Address: 0x10C48
229 GOT-TLS-NEXT: Access: -32680
230 GOT-TLS-NEXT: Initial: 0xAF0
231 GOT-TLS-NEXT: }
232 GOT-TLS-NEXT: Entry {
233 GOT-TLS-NEXT: Address: 0x10C50
234 GOT-TLS-NEXT: Access: -32672
235 GOT-TLS-NEXT: Initial: 0x0
236 GOT-TLS-NEXT: }
237 GOT-TLS-NEXT: Entry {
238 GOT-TLS-NEXT: Address: 0x10C58
239 GOT-TLS-NEXT: Access: -32664
240 GOT-TLS-NEXT: Initial: 0x0
241 GOT-TLS-NEXT: }
242 GOT-TLS-NEXT: Entry {
243 GOT-TLS-NEXT: Address: 0x10C60
244 GOT-TLS-NEXT: Access: -32656
245 GOT-TLS-NEXT: Initial: 0x0
246 GOT-TLS-NEXT: }
247 GOT-TLS-NEXT: ]
248 GOT-TLS-NEXT: Global entries [
249 GOT-TLS-NEXT: Entry {
250 GOT-TLS-NEXT: Address: 0x10C68
251 GOT-TLS-NEXT: Access: -32648
252 GOT-TLS-NEXT: Initial: 0x0
253 GOT-TLS-NEXT: Value: 0x0
254 GOT-TLS-NEXT: Type: None (0x0)
255 GOT-TLS-NEXT: Section: Undefined (0x0)
256 GOT-TLS-NEXT: Name: _ITM_registerTMCloneTable@ (78)
257 GOT-TLS-NEXT: }
258 GOT-TLS-NEXT: Entry {
259 GOT-TLS-NEXT: Address: 0x10C70
260 GOT-TLS-NEXT: Access: -32640
261 GOT-TLS-NEXT: Initial: 0x0
262 GOT-TLS-NEXT: Value: 0x0
263 GOT-TLS-NEXT: Type: None (0x0)
264 GOT-TLS-NEXT: Section: Undefined (0x0)
265 GOT-TLS-NEXT: Name: _Jv_RegisterClasses@ (119)
266 GOT-TLS-NEXT: }
267 GOT-TLS-NEXT: Entry {
268 GOT-TLS-NEXT: Address: 0x10C78
269 GOT-TLS-NEXT: Access: -32632
270 GOT-TLS-NEXT: Initial: 0x0
271 GOT-TLS-NEXT: Value: 0x0
272 GOT-TLS-NEXT: Type: Function (0x2)
273 GOT-TLS-NEXT: Section: Undefined (0x0)
274 GOT-TLS-NEXT: Name: __gmon_start__@ (23)
275 GOT-TLS-NEXT: }
276 GOT-TLS-NEXT: Entry {
277 GOT-TLS-NEXT: Address: 0x10C80
278 GOT-TLS-NEXT: Access: -32624
279 GOT-TLS-NEXT: Initial: 0xB60
280 GOT-TLS-NEXT: Value: 0xB60
281 GOT-TLS-NEXT: Type: Function (0x2)
282 GOT-TLS-NEXT: Section: Undefined (0x0)
283 GOT-TLS-NEXT: Name: __tls_get_addr@GLIBC_2.3 (150)
284 GOT-TLS-NEXT: }
285 GOT-TLS-NEXT: Entry {
286 GOT-TLS-NEXT: Address: 0x10C88
287 GOT-TLS-NEXT: Access: -32616
288 GOT-TLS-NEXT: Initial: 0x0
289 GOT-TLS-NEXT: Value: 0x0
290 GOT-TLS-NEXT: Type: None (0x0)
291 GOT-TLS-NEXT: Section: Undefined (0x0)
292 GOT-TLS-NEXT: Name: _ITM_deregisterTMCloneTable@ (50)
293 GOT-TLS-NEXT: }
294 GOT-TLS-NEXT: Entry {
295 GOT-TLS-NEXT: Address: 0x10C90
296 GOT-TLS-NEXT: Access: -32608
297 GOT-TLS-NEXT: Initial: 0x0
298 GOT-TLS-NEXT: Value: 0x0
299 GOT-TLS-NEXT: Type: Function (0x2)
300 GOT-TLS-NEXT: Section: Undefined (0x0)
301 GOT-TLS-NEXT: Name: __cxa_finalize@GLIBC_2.2 (104)
302 GOT-TLS-NEXT: }
303 GOT-TLS-NEXT: ]
304 GOT-TLS-NEXT: Number of TLS and multi-GOT entries: 4
305 GOT-TLS-NEXT: }
1717 #include "Error.h"
1818 #include "ObjDumper.h"
1919 #include "StreamWriter.h"
20 #include "llvm/ADT/Optional.h"
2021 #include "llvm/ADT/SmallString.h"
2122 #include "llvm/ADT/StringExtras.h"
2223 #include "llvm/Object/ELFObjectFile.h"
5354 void printProgramHeaders() override;
5455
5556 void printAttributes() override;
57 void printMipsPLTGOT() override;
5658
5759 private:
5860 typedef ELFFile ELFO;
156158 const typename ELFO::Elf_Shdr *Sec = Obj.getSection(SectionIndex);
157159 SectionName = errorOrDefault(Obj.getSectionName(Sec));
158160 }
161 }
162
163 template
164 static const typename ELFFile::Elf_Shdr *
165 findSectionByAddress(const ELFFile *Obj, uint64_t Addr) {
166 for (const auto &Shdr : Obj->sections())
167 if (Shdr.sh_addr == Addr)
168 return &Shdr;
169 return nullptr;
159170 }
160171
161172 static const EnumEntry ElfClass[] = {
10201031 }
10211032 }
10221033
1034 namespace {
1035 template class MipsGOTParser {
1036 public:
1037 typedef object::ELFFile ObjectFile;
1038 typedef typename ObjectFile::Elf_Shdr Elf_Shdr;
1039
1040 MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) : Obj(Obj), W(W) {}
1041
1042 void ParseGOT(const Elf_Shdr &GOTShdr);
1043
1044 private:
1045 typedef typename ObjectFile::Elf_Sym_Iter Elf_Sym_Iter;
1046 typedef typename ObjectFile::Elf_Addr GOTEntry;
1047 typedef typename ObjectFile::template ELFEntityIterator
1048 GOTIter;
1049
1050 const ObjectFile *Obj;
1051 StreamWriter &W;
1052
1053 std::size_t GetGOTTotal(ArrayRef GOT) const;
1054 GOTIter MakeGOTIter(ArrayRef GOT, std::size_t EntryNum);
1055
1056 bool getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym);
1057 void printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It);
1058 void printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It,
1059 Elf_Sym_Iter Sym);
1060 };
1061 }
1062
1063 template
1064 void MipsGOTParser::ParseGOT(const Elf_Shdr &GOTShdr) {
1065 // See "Global Offset Table" in Chapter 5 in the following document
1066 // for detailed GOT description.
1067 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
1068
1069 ErrorOr> GOT = Obj->getSectionContents(&GOTShdr);
1070 if (!GOT) {
1071 W.startLine() << "The .got section is empty.\n";
1072 return;
1073 }
1074
1075 uint64_t DtLocalGotNum;
1076 uint64_t DtGotSym;
1077 if (!getGOTTags(DtLocalGotNum, DtGotSym))
1078 return;
1079
1080 if (DtLocalGotNum > GetGOTTotal(*GOT)) {
1081 W.startLine() << "MIPS_LOCAL_GOTNO exceeds a number of GOT entries.\n";
1082 return;
1083 }
1084
1085 Elf_Sym_Iter DynSymBegin = Obj->begin_dynamic_symbols();
1086 Elf_Sym_Iter DynSymEnd = Obj->end_dynamic_symbols();
1087 std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
1088
1089 if (DtGotSym + 1 > DynSymTotal) {
1090 W.startLine() << "MIPS_GOTSYM exceeds a number of dynamic symbols.\n";
1091 return;
1092 }
1093
1094 std::size_t GlobalGotNum = DynSymTotal - DtGotSym;
1095
1096 if (DtLocalGotNum + GlobalGotNum > GetGOTTotal(*GOT)) {
1097 W.startLine() << "Number of global GOT entries exceeds the size of GOT.\n";
1098 return;
1099 }
1100
1101 GOTIter GotBegin = MakeGOTIter(*GOT, 0);
1102 GOTIter GotLocalEnd = MakeGOTIter(*GOT, DtLocalGotNum);
1103 GOTIter It = GotBegin;
1104
1105 DictScope GS(W, "Primary GOT");
1106
1107 W.printHex("Canonical gp value", GOTShdr.sh_addr + 0x7ff0);
1108 {
1109 ListScope RS(W, "Reserved entries");
1110
1111 {
1112 DictScope D(W, "Entry");
1113 printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
1114 W.printString("Purpose", StringRef("Lazy resolver"));
1115 }
1116
1117 if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) {
1118 DictScope D(W, "Entry");
1119 printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
1120 W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
1121 }
1122 }
1123 {
1124 ListScope LS(W, "Local entries");
1125 for (; It != GotLocalEnd; ++It) {
1126 DictScope D(W, "Entry");
1127 printGotEntry(GOTShdr.sh_addr, GotBegin, It);
1128 }
1129 }
1130 {
1131 ListScope GS(W, "Global entries");
1132
1133 GOTIter GotGlobalEnd = MakeGOTIter(*GOT, DtLocalGotNum + GlobalGotNum);
1134 Elf_Sym_Iter GotDynSym = DynSymBegin + DtGotSym;
1135 for (; It != GotGlobalEnd; ++It) {
1136 DictScope D(W, "Entry");
1137 printGlobalGotEntry(GOTShdr.sh_addr, GotBegin, It, GotDynSym++);
1138 }
1139 }
1140
1141 std::size_t SpecGotNum = GetGOTTotal(*GOT) - DtLocalGotNum - GlobalGotNum;
1142 W.printNumber("Number of TLS and multi-GOT entries", SpecGotNum);
1143 }
1144
1145 template
1146 std::size_t MipsGOTParser::GetGOTTotal(ArrayRef GOT) const {
1147 return GOT.size() / sizeof(GOTEntry);
1148 }
1149
1150 template
1151 typename MipsGOTParser::GOTIter
1152 MipsGOTParser::MakeGOTIter(ArrayRef GOT, std::size_t EntryNum) {
1153 const char *Data = reinterpret_cast(GOT.data());
1154 return GOTIter(sizeof(GOTEntry), Data + EntryNum * sizeof(GOTEntry));
1155 }
1156
1157 template
1158 bool MipsGOTParser::getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym) {
1159 bool FoundLocalGotNum = false;
1160 bool FoundGotSym = false;
1161 for (const auto &Entry : Obj->dynamic_table()) {
1162 switch (Entry.getTag()) {
1163 case ELF::DT_MIPS_LOCAL_GOTNO:
1164 LocalGotNum = Entry.getVal();
1165 FoundLocalGotNum = true;
1166 break;
1167 case ELF::DT_MIPS_GOTSYM:
1168 GotSym = Entry.getVal();
1169 FoundGotSym = true;
1170 break;
1171 }
1172 }
1173
1174 if (!FoundLocalGotNum) {
1175 W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n";
1176 return false;
1177 }
1178
1179 if (!FoundGotSym) {
1180 W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n";
1181 return false;
1182 }
1183
1184 return true;
1185 }
1186
1187 template
1188 void MipsGOTParser::printGotEntry(uint64_t GotAddr, GOTIter BeginIt,
1189 GOTIter It) {
1190 int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
1191 W.printHex("Address", GotAddr + Offset);
1192 W.printNumber("Access", Offset - 0x7ff0);
1193 W.printHex("Initial", *It);
1194 }
1195
1196 template
1197 void MipsGOTParser::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt,
1198 GOTIter It, Elf_Sym_Iter Sym) {
1199 printGotEntry(GotAddr, BeginIt, It);
1200
1201 W.printHex("Value", Sym->st_value);
1202 W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
1203
1204 unsigned SectionIndex = 0;
1205 StringRef SectionName;
1206 getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
1207 W.printHex("Section", SectionName, SectionIndex);
1208
1209 std::string FullSymbolName = getFullSymbolName(*Obj, Sym);
1210 W.printNumber("Name", FullSymbolName, Sym->st_name);
1211 }
1212
1213 template void ELFDumper::printMipsPLTGOT() {
1214 if (Obj->getHeader()->e_machine != EM_MIPS) {
1215 W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n";
1216 return;
1217 }
1218
1219 llvm::Optional DtPltGot;
1220 for (const auto &Entry : Obj->dynamic_table()) {
1221 if (Entry.getTag() == ELF::DT_PLTGOT) {
1222 DtPltGot = Entry.getVal();
1223 break;
1224 }
1225 }
1226
1227 if (!DtPltGot) {
1228 W.startLine() << "Cannot find PLTGOT dynamic table tag.\n";
1229 return;
1230 }
1231
1232 const Elf_Shdr *GotShdr = findSectionByAddress(Obj, *DtPltGot);
1233 if (!GotShdr) {
1234 W.startLine() << "There is no .got section in the file.\n";
1235 return;
1236 }
1237
1238 MipsGOTParser(Obj, W).ParseGOT(*GotShdr);
1239 }
3939 // Only implemented for ARM ELF at this time.
4040 virtual void printAttributes() { }
4141
42 // Only implemented for MIPS ELF at this time.
43 virtual void printMipsPLTGOT() { }
44
4245 protected:
4346 StreamWriter& W;
4447 };
134134 cl::desc("Display the ARM attributes section"));
135135 cl::alias ARMAttributesShort("-a", cl::desc("Alias for --arm-attributes"),
136136 cl::aliasopt(ARMAttributes));
137
138 // -mips-plt-got
139 cl::opt
140 MipsPLTGOT("mips-plt-got",
141 cl::desc("Display the MIPS GOT and PLT GOT sections"));
137142 } // namespace opts
138143
139144 static int ReturnValue = EXIT_SUCCESS;
174179
175180 errs() << Input << ": " << Message << "\n";
176181 ReturnValue = EXIT_FAILURE;
182 }
183
184 static bool isMipsArch(unsigned Arch) {
185 switch (Arch) {
186 case llvm::Triple::mips:
187 case llvm::Triple::mipsel:
188 case llvm::Triple::mips64:
189 case llvm::Triple::mips64el:
190 return true;
191 default:
192 return false;
193 }
177194 }
178195
179196 /// @brief Creates an format-specific object file dumper.
233250 if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())
234251 if (opts::ARMAttributes)
235252 Dumper->printAttributes();
253 if (isMipsArch(Obj->getArch()) && Obj->isELF())
254 if (opts::MipsPLTGOT)
255 Dumper->printMipsPLTGOT();
236256 }
237257
238258
3737 extern llvm::cl::opt ExpandRelocs;
3838 extern llvm::cl::opt CodeViewLineTables;
3939 extern llvm::cl::opt ARMAttributes;
40 extern llvm::cl::opt MipsPLTGOT;
4041 } // namespace opts
4142
4243 #define LLVM_READOBJ_ENUM_ENT(ns, enum) \