Index: llvm/trunk/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test =================================================================== --- llvm/trunk/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test +++ llvm/trunk/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test @@ -1,16 +1,23 @@ -# Show that no dumping occurs if there is no PT_DYNAMIC header. +## Show that dumping occurs even if there is no PT_DYNAMIC header. +## This is inconsistent with the GNU behavior, but seems to be more reasonable. # RUN: yaml2obj %s -o %t.no-phdr # RUN: llvm-readobj --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=LLVM -# RUN: llvm-readelf --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=GNU --allow-empty +# RUN: llvm-readelf --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=GNU # LLVM: File: {{.*}}.no-phdr # LLVM-NEXT: Format: ELF64-x86-64 # LLVM-NEXT: Arch: x86_64 # LLVM-NEXT: AddressSize: 64bit # LLVM-NEXT: LoadName:{{ *}} -# LLVM-NOT: {{.}} +# LLVM-NEXT: DynamicSection [ (1 entries) +# LLVM-NEXT: Tag Type Name/Value +# LLVM-NEXT: 0x0000000000000000 NULL 0x0 +# LLVM-NEXT: ] -# GNU-NOT: {{.}} +# GNU: DynamicSection [ (1 entries) +# GNU-NEXT: Tag Type Name/Value +# GNU-NEXT: 0x0000000000000000 NULL 0x0 +# GNU-NEXT: ] --- !ELF FileHeader: Index: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp +++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp @@ -1331,6 +1331,7 @@ template void ELFDumper::loadDynamicTable(const ELFFile *Obj) { + // Try to locate the PT_DYNAMIC header. const Elf_Phdr *DynamicPhdr = nullptr; for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { if (Phdr.p_type != ELF::PT_DYNAMIC) @@ -1339,11 +1340,6 @@ break; } - // We do not want to dump dynamic section if we have no PT_DYNAMIC header. - // This matches GNU's behavior. - if (!DynamicPhdr) - return; - // Try to locate the .dynamic section in the sections header table. const Elf_Shdr *DynamicSec = nullptr; for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { @@ -1358,9 +1354,16 @@ // Ignore sh_entsize and use the expected value for entry size explicitly. // This allows us to dump the dynamic sections with a broken sh_entsize // field. - if (DynamicSec) + if (DynamicSec) { DynamicTable = checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn)}); + parseDynamicTable(); + } + + // If we have a PT_DYNAMIC header, we will either check the found dynamic + // section or take the dynamic table data directly from the header. + if (!DynamicPhdr) + return; if (DynamicPhdr->p_offset + DynamicPhdr->p_filesz > ObjF->getMemoryBufferRef().getBufferSize()) @@ -1374,7 +1377,6 @@ } StringRef Name = unwrapOrError(Obj->getSectionName(DynamicSec)); - if (DynamicSec->sh_addr + DynamicSec->sh_size > DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz || DynamicSec->sh_addr < DynamicPhdr->p_vaddr) @@ -1386,8 +1388,6 @@ reportWarning("The SHT_DYNAMIC section '" + Name + "' is not at the start of " "PT_DYNAMIC segment"); - - parseDynamicTable(); } template