@@ -203,7 +203,8 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
203
203
{ObjF->getELFFile ()->base () + S->sh_offset , S->sh_size , S->sh_entsize });
204
204
}
205
205
206
- void parseDynamicTable (ArrayRef<const Elf_Phdr *> LoadSegments);
206
+ void loadDynamicTable (const ELFFile<ELFT> *Obj);
207
+ void parseDynamicTable ();
207
208
208
209
void printValue (uint64_t Type, uint64_t Value);
209
210
@@ -1329,21 +1330,72 @@ static const char *getElfMipsOptionsOdkType(unsigned Odk) {
1329
1330
}
1330
1331
1331
1332
template <typename ELFT>
1332
- ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> *ObjF,
1333
- ScopedPrinter &Writer)
1334
- : ObjDumper(Writer), ObjF(ObjF) {
1335
- SmallVector<const Elf_Phdr *, 4 > LoadSegments;
1336
- const ELFFile<ELFT> *Obj = ObjF->getELFFile ();
1333
+ void ELFDumper<ELFT>::loadDynamicTable(const ELFFile<ELFT> *Obj) {
1334
+ const Elf_Phdr *DynamicPhdr = nullptr ;
1337
1335
for (const Elf_Phdr &Phdr : unwrapOrError (Obj->program_headers ())) {
1338
- if (Phdr.p_type == ELF::PT_DYNAMIC) {
1339
- DynamicTable = createDRIFrom (&Phdr, sizeof (Elf_Dyn));
1336
+ if (Phdr.p_type != ELF::PT_DYNAMIC)
1340
1337
continue ;
1341
- }
1342
- if (Phdr.p_type != ELF::PT_LOAD || Phdr.p_filesz == 0 )
1338
+ DynamicPhdr = &Phdr;
1339
+ break ;
1340
+ }
1341
+
1342
+ // We do not want to dump dynamic section if we have no PT_DYNAMIC header.
1343
+ // This matches GNU's behavior.
1344
+ if (!DynamicPhdr)
1345
+ return ;
1346
+
1347
+ // Try to locate the .dynamic section in the sections header table.
1348
+ const Elf_Shdr *DynamicSec = nullptr ;
1349
+ for (const Elf_Shdr &Sec : unwrapOrError (Obj->sections ())) {
1350
+ if (Sec.sh_type != ELF::SHT_DYNAMIC)
1343
1351
continue ;
1344
- LoadSegments.push_back (&Phdr);
1352
+ DynamicSec = &Sec;
1353
+ break ;
1345
1354
}
1346
1355
1356
+ // Information in the section header has priority over the information
1357
+ // in a PT_DYNAMIC header.
1358
+ // Ignore sh_entsize and use the expected value for entry size explicitly.
1359
+ // This allows us to dump the dynamic sections with a broken sh_entsize
1360
+ // field.
1361
+ if (DynamicSec)
1362
+ DynamicTable = checkDRI ({ObjF->getELFFile ()->base () + DynamicSec->sh_offset ,
1363
+ DynamicSec->sh_size , sizeof (Elf_Dyn)});
1364
+
1365
+ if (DynamicPhdr->p_offset + DynamicPhdr->p_filesz >
1366
+ ObjF->getMemoryBufferRef ().getBufferSize ())
1367
+ reportError (
1368
+ " PT_DYNAMIC segment offset + size exceeds the size of the file" );
1369
+
1370
+ if (!DynamicSec) {
1371
+ DynamicTable = createDRIFrom (DynamicPhdr, sizeof (Elf_Dyn));
1372
+ parseDynamicTable ();
1373
+ return ;
1374
+ }
1375
+
1376
+ StringRef Name = unwrapOrError (Obj->getSectionName (DynamicSec));
1377
+
1378
+ if (DynamicSec->sh_addr + DynamicSec->sh_size >
1379
+ DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz ||
1380
+ DynamicSec->sh_addr < DynamicPhdr->p_vaddr )
1381
+ reportWarning (" The SHT_DYNAMIC section '" + Name +
1382
+ " ' is not contained within the "
1383
+ " PT_DYNAMIC segment" );
1384
+
1385
+ if (DynamicSec->sh_addr != DynamicPhdr->p_vaddr )
1386
+ reportWarning (" The SHT_DYNAMIC section '" + Name +
1387
+ " ' is not at the start of "
1388
+ " PT_DYNAMIC segment" );
1389
+
1390
+ parseDynamicTable ();
1391
+ }
1392
+
1393
+ template <typename ELFT>
1394
+ ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> *ObjF,
1395
+ ScopedPrinter &Writer)
1396
+ : ObjDumper(Writer), ObjF(ObjF) {
1397
+ const ELFFile<ELFT> *Obj = ObjF->getELFFile ();
1398
+
1347
1399
for (const Elf_Shdr &Sec : unwrapOrError (Obj->sections ())) {
1348
1400
switch (Sec.sh_type ) {
1349
1401
case ELF::SHT_SYMTAB:
@@ -1390,17 +1442,15 @@ ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> *ObjF,
1390
1442
}
1391
1443
}
1392
1444
1393
- parseDynamicTable (LoadSegments );
1445
+ loadDynamicTable (Obj );
1394
1446
1395
1447
if (opts::Output == opts::GNU)
1396
1448
ELFDumperStyle.reset (new GNUStyle<ELFT>(Writer, this ));
1397
1449
else
1398
1450
ELFDumperStyle.reset (new LLVMStyle<ELFT>(Writer, this ));
1399
1451
}
1400
1452
1401
- template <typename ELFT>
1402
- void ELFDumper<ELFT>::parseDynamicTable(
1403
- ArrayRef<const Elf_Phdr *> LoadSegments) {
1453
+ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
1404
1454
auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * {
1405
1455
auto MappedAddrOrError = ObjF->getELFFile ()->toMappedAddr (VAddr);
1406
1456
if (!MappedAddrOrError)
0 commit comments