llvm.org GIT mirror llvm / 13c5e09
[llvm-readobj] Print MIPS PLT table Now the -mips-plt-got prints both MIPS GOT and PLT tables. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241836 91177308-0d34-0410-b5e6-96231b3b80d8 Simon Atanasyan 5 years ago
3 changed file(s) with 204 addition(s) and 79 deletion(s). Raw diff Collapse all Expand all
0 RUN: llvm-readobj -mips-plt-got %p/Inputs/got-plt.exe.elf-mipsel | FileCheck %s
1
2 CHECK: PLT GOT {
3 CHECK-NEXT: Reserved entries [
4 CHECK-NEXT: Entry {
5 CHECK-NEXT: Address: 0x410814
6 CHECK-NEXT: Initial: 0x0
7 CHECK-NEXT: Purpose: PLT lazy resolver
8 CHECK-NEXT: }
9 CHECK-NEXT: Entry {
10 CHECK-NEXT: Address: 0x410818
11 CHECK-NEXT: Initial: 0x0
12 CHECK-NEXT: Purpose: Module pointer
13 CHECK-NEXT: }
14 CHECK-NEXT: ]
15 CHECK-NEXT: Entries [
16 CHECK-NEXT: Entry {
17 CHECK-NEXT: Address: 0x41081C
18 CHECK-NEXT: Initial: 0x4007C0
19 CHECK-NEXT: Value: 0x0
20 CHECK-NEXT: Type: Function (0x2)
21 CHECK-NEXT: Section: Undefined (0x0)
22 CHECK-NEXT: Name: puts@GLIBC_2.0 (71)
23 CHECK-NEXT: }
24 CHECK-NEXT: Entry {
25 CHECK-NEXT: Address: 0x410820
26 CHECK-NEXT: Initial: 0x4007C0
27 CHECK-NEXT: Value: 0x0
28 CHECK-NEXT: Type: Function (0x2)
29 CHECK-NEXT: Section: Undefined (0x0)
30 CHECK-NEXT: Name: __libc_start_main@GLIBC_2.0 (53)
31 CHECK-NEXT: }
32 CHECK-NEXT: ]
33 CHECK-NEXT: }
11611161 typedef typename ObjectFile::Elf_Shdr Elf_Shdr;
11621162 typedef typename ObjectFile::Elf_Sym Elf_Sym;
11631163
1164 MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) : Obj(Obj), W(W) {}
1165
1166 void parseGOT(const Elf_Shdr &GOTShdr);
1164 MipsGOTParser(const ObjectFile *Obj, StreamWriter &W);
1165
1166 void parseGOT();
1167 void parsePLT();
11671168
11681169 private:
11691170 typedef typename ObjectFile::Elf_Addr GOTEntry;
11721173
11731174 const ObjectFile *Obj;
11741175 StreamWriter &W;
1176 llvm::Optional DtPltGot;
1177 llvm::Optional DtLocalGotNum;
1178 llvm::Optional DtGotSym;
1179 llvm::Optional DtMipsPltGot;
1180 llvm::Optional DtJmpRel;
11751181
11761182 std::size_t getGOTTotal(ArrayRef GOT) const;
11771183 GOTIter makeGOTIter(ArrayRef GOT, std::size_t EntryNum);
11781184
1179 bool getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym);
11801185 void printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It);
11811186 void printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It,
11821187 const Elf_Sym *Sym, bool IsDynamic);
1188 void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It,
1189 StringRef Purpose);
1190 void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It,
1191 const Elf_Sym *Sym);
11831192 };
11841193 }
11851194
11861195 template
1187 void MipsGOTParser::parseGOT(const Elf_Shdr &GOTShdr) {
1196 MipsGOTParser::MipsGOTParser(const ObjectFile *Obj, StreamWriter &W)
1197 : Obj(Obj), W(W) {
1198 for (const auto &Entry : Obj->dynamic_table()) {
1199 switch (Entry.getTag()) {
1200 case ELF::DT_PLTGOT:
1201 DtPltGot = Entry.getVal();
1202 break;
1203 case ELF::DT_MIPS_LOCAL_GOTNO:
1204 DtLocalGotNum = Entry.getVal();
1205 break;
1206 case ELF::DT_MIPS_GOTSYM:
1207 DtGotSym = Entry.getVal();
1208 break;
1209 case ELF::DT_MIPS_PLTGOT:
1210 DtMipsPltGot = Entry.getVal();
1211 break;
1212 case ELF::DT_JMPREL:
1213 DtJmpRel = Entry.getVal();
1214 break;
1215 }
1216 }
1217 }
1218
1219 template void MipsGOTParser::parseGOT() {
11881220 // See "Global Offset Table" in Chapter 5 in the following document
11891221 // for detailed GOT description.
11901222 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
1191
1192 ErrorOr> GOT = Obj->getSectionContents(&GOTShdr);
1223 if (!DtPltGot) {
1224 W.startLine() << "Cannot find PLTGOT dynamic table tag.\n";
1225 return;
1226 }
1227 if (!DtLocalGotNum) {
1228 W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n";
1229 return;
1230 }
1231 if (!DtGotSym) {
1232 W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n";
1233 return;
1234 }
1235
1236 const Elf_Shdr *GOTShdr = findSectionByAddress(Obj, *DtPltGot);
1237 if (!GOTShdr) {
1238 W.startLine() << "There is no .got section in the file.\n";
1239 return;
1240 }
1241
1242 ErrorOr> GOT = Obj->getSectionContents(GOTShdr);
11931243 if (!GOT) {
11941244 W.startLine() << "The .got section is empty.\n";
11951245 return;
11961246 }
11971247
1198 uint64_t DtLocalGotNum;
1199 uint64_t DtGotSym;
1200 if (!getGOTTags(DtLocalGotNum, DtGotSym))
1201 return;
1202
1203 if (DtLocalGotNum > getGOTTotal(*GOT)) {
1248 if (*DtLocalGotNum > getGOTTotal(*GOT)) {
12041249 W.startLine() << "MIPS_LOCAL_GOTNO exceeds a number of GOT entries.\n";
12051250 return;
12061251 }
12091254 const Elf_Sym *DynSymEnd = Obj->dynamic_symbol_end();
12101255 std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
12111256
1212 if (DtGotSym > DynSymTotal) {
1257 if (*DtGotSym > DynSymTotal) {
12131258 W.startLine() << "MIPS_GOTSYM exceeds a number of dynamic symbols.\n";
12141259 return;
12151260 }
12161261
1217 std::size_t GlobalGotNum = DynSymTotal - DtGotSym;
1218
1219 if (DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) {
1262 std::size_t GlobalGotNum = DynSymTotal - *DtGotSym;
1263
1264 if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) {
12201265 W.startLine() << "Number of global GOT entries exceeds the size of GOT.\n";
12211266 return;
12221267 }
12231268
12241269 GOTIter GotBegin = makeGOTIter(*GOT, 0);
1225 GOTIter GotLocalEnd = makeGOTIter(*GOT, DtLocalGotNum);
1270 GOTIter GotLocalEnd = makeGOTIter(*GOT, *DtLocalGotNum);
12261271 GOTIter It = GotBegin;
12271272
12281273 DictScope GS(W, "Primary GOT");
12291274
1230 W.printHex("Canonical gp value", GOTShdr.sh_addr + 0x7ff0);
1275 W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0);
12311276 {
12321277 ListScope RS(W, "Reserved entries");
12331278
12341279 {
12351280 DictScope D(W, "Entry");
1236 printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
1281 printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
12371282 W.printString("Purpose", StringRef("Lazy resolver"));
12381283 }
12391284
12401285 if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) {
12411286 DictScope D(W, "Entry");
1242 printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
1287 printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
12431288 W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
12441289 }
12451290 }
12471292 ListScope LS(W, "Local entries");
12481293 for (; It != GotLocalEnd; ++It) {
12491294 DictScope D(W, "Entry");
1250 printGotEntry(GOTShdr.sh_addr, GotBegin, It);
1295 printGotEntry(GOTShdr->sh_addr, GotBegin, It);
12511296 }
12521297 }
12531298 {
12541299 ListScope GS(W, "Global entries");
12551300
1256 GOTIter GotGlobalEnd = makeGOTIter(*GOT, DtLocalGotNum + GlobalGotNum);
1257 const Elf_Sym *GotDynSym = DynSymBegin + DtGotSym;
1301 GOTIter GotGlobalEnd = makeGOTIter(*GOT, *DtLocalGotNum + GlobalGotNum);
1302 const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym;
12581303 for (; It != GotGlobalEnd; ++It) {
12591304 DictScope D(W, "Entry");
1260 printGlobalGotEntry(GOTShdr.sh_addr, GotBegin, It, GotDynSym++, true);
1261 }
1262 }
1263
1264 std::size_t SpecGotNum = getGOTTotal(*GOT) - DtLocalGotNum - GlobalGotNum;
1305 printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, true);
1306 }
1307 }
1308
1309 std::size_t SpecGotNum = getGOTTotal(*GOT) - *DtLocalGotNum - GlobalGotNum;
12651310 W.printNumber("Number of TLS and multi-GOT entries", uint64_t(SpecGotNum));
1311 }
1312
1313 template void MipsGOTParser::parsePLT() {
1314 if (!DtMipsPltGot) {
1315 W.startLine() << "Cannot find MIPS_PLTGOT dynamic table tag.\n";
1316 return;
1317 }
1318 if (!DtJmpRel) {
1319 W.startLine() << "Cannot find JMPREL dynamic table tag.\n";
1320 return;
1321 }
1322
1323 const Elf_Shdr *PLTShdr = findSectionByAddress(Obj, *DtMipsPltGot);
1324 if (!PLTShdr) {
1325 W.startLine() << "There is no .got.plt section in the file.\n";
1326 return;
1327 }
1328 ErrorOr> PLT = Obj->getSectionContents(PLTShdr);
1329 if (!PLT) {
1330 W.startLine() << "The .got.plt section is empty.\n";
1331 return;
1332 }
1333
1334 const Elf_Shdr *PLTRelShdr = findSectionByAddress(Obj, *DtJmpRel);
1335 if (!PLTShdr) {
1336 W.startLine() << "There is no .rel.plt section in the file.\n";
1337 return;
1338 }
1339
1340 GOTIter PLTBegin = makeGOTIter(*PLT, 0);
1341 GOTIter PLTEnd = makeGOTIter(*PLT, getGOTTotal(*PLT));
1342 GOTIter It = PLTBegin;
1343
1344 DictScope GS(W, "PLT GOT");
1345 {
1346 ListScope RS(W, "Reserved entries");
1347 printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "PLT lazy resolver");
1348 if (It != PLTEnd)
1349 printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "Module pointer");
1350 }
1351 {
1352 ListScope GS(W, "Entries");
1353
1354 switch (PLTRelShdr->sh_type) {
1355 case ELF::SHT_REL:
1356 for (typename ObjectFile::Elf_Rel_Iter RI = Obj->rel_begin(PLTRelShdr),
1357 RE = Obj->rel_end(PLTRelShdr);
1358 RI != RE && It != PLTEnd; ++RI, ++It) {
1359 const Elf_Sym *Sym =
1360 Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second;
1361 printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, Sym);
1362 }
1363 break;
1364 case ELF::SHT_RELA:
1365 for (typename ObjectFile::Elf_Rela_Iter RI = Obj->rela_begin(PLTRelShdr),
1366 RE = Obj->rela_end(PLTRelShdr);
1367 RI != RE && It != PLTEnd; ++RI, ++It) {
1368 const Elf_Sym *Sym =
1369 Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second;
1370 printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, Sym);
1371 }
1372 break;
1373 }
1374 }
12661375 }
12671376
12681377 template
12751384 MipsGOTParser::makeGOTIter(ArrayRef GOT, std::size_t EntryNum) {
12761385 const char *Data = reinterpret_cast(GOT.data());
12771386 return GOTIter(sizeof(GOTEntry), Data + EntryNum * sizeof(GOTEntry));
1278 }
1279
1280 template
1281 bool MipsGOTParser::getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym) {
1282 bool FoundLocalGotNum = false;
1283 bool FoundGotSym = false;
1284 for (const auto &Entry : Obj->dynamic_table()) {
1285 switch (Entry.getTag()) {
1286 case ELF::DT_MIPS_LOCAL_GOTNO:
1287 LocalGotNum = Entry.getVal();
1288 FoundLocalGotNum = true;
1289 break;
1290 case ELF::DT_MIPS_GOTSYM:
1291 GotSym = Entry.getVal();
1292 FoundGotSym = true;
1293 break;
1294 }
1295 }
1296
1297 if (!FoundLocalGotNum) {
1298 W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n";
1299 return false;
1300 }
1301
1302 if (!FoundGotSym) {
1303 W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n";
1304 return false;
1305 }
1306
1307 return true;
13081387 }
13091388
13101389 template
13341413 W.printNumber("Name", FullSymbolName, Sym->st_name);
13351414 }
13361415
1416 template
1417 void MipsGOTParser::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt,
1418 GOTIter It, StringRef Purpose) {
1419 DictScope D(W, "Entry");
1420 int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
1421 W.printHex("Address", PLTAddr + Offset);
1422 W.printHex("Initial", *It);
1423 W.printString("Purpose", Purpose);
1424 }
1425
1426 template
1427 void MipsGOTParser::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt,
1428 GOTIter It, const Elf_Sym *Sym) {
1429 DictScope D(W, "Entry");
1430 int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
1431 W.printHex("Address", PLTAddr + Offset);
1432 W.printHex("Initial", *It);
1433 W.printHex("Value", Sym->st_value);
1434 W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
1435
1436 unsigned SectionIndex = 0;
1437 StringRef SectionName;
1438 getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
1439 W.printHex("Section", SectionName, SectionIndex);
1440
1441 std::string FullSymbolName = getFullSymbolName(*Obj, Sym, true);
1442 W.printNumber("Name", FullSymbolName, Sym->st_name);
1443 }
1444
13371445 template void ELFDumper::printMipsPLTGOT() {
13381446 if (Obj->getHeader()->e_machine != EM_MIPS) {
13391447 W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n";
13401448 return;
13411449 }
13421450
1343 llvm::Optional DtPltGot;
1344 for (const auto &Entry : Obj->dynamic_table()) {
1345 if (Entry.getTag() == ELF::DT_PLTGOT) {
1346 DtPltGot = Entry.getVal();
1347 break;
1348 }
1349 }
1350
1351 if (!DtPltGot) {
1352 W.startLine() << "Cannot find PLTGOT dynamic table tag.\n";
1353 return;
1354 }
1355
1356 const Elf_Shdr *GotShdr = findSectionByAddress(Obj, *DtPltGot);
1357 if (!GotShdr) {
1358 W.startLine() << "There is no .got section in the file.\n";
1359 return;
1360 }
1361
1362 MipsGOTParser(Obj, W).parseGOT(*GotShdr);
1451 MipsGOTParser GOTParser(Obj, W);
1452 GOTParser.parseGOT();
1453 GOTParser.parsePLT();
13631454 }
13641455
13651456 static const EnumEntry ElfMipsISAExtType[] = {