Index: test/tools/llvm-readobj/dyn-symbols.test =================================================================== --- test/tools/llvm-readobj/dyn-symbols.test +++ test/tools/llvm-readobj/dyn-symbols.test @@ -1,10 +1,11 @@ -RUN: llvm-readobj --dyn-symbols %p/Inputs/dynamic-table-so.x86 | FileCheck %s +# RUN: llvm-readobj --dyn-symbols %p/Inputs/dynamic-table-so.x86 | FileCheck %s -# Check the two-letter alias --dt is equivalent to the --dyn-symbols full flag -# name. -RUN: llvm-readobj --dt %p/Inputs/dynamic-table-so.x86 > %t.readobj-dt-alias -RUN: llvm-readobj --dyn-symbols %p/Inputs/dynamic-table-so.x86 > %t.readobj-dt-no-alias -RUN: diff %t.readobj-dt-alias %t.readobj-dt-no-alias +## Check the two-letter alias --dt is equivalent to the --dyn-symbols full flag +## name. + +# RUN: llvm-readobj --dt %p/Inputs/dynamic-table-so.x86 > %t.readobj-dt-alias +# RUN: llvm-readobj --dyn-symbols %p/Inputs/dynamic-table-so.x86 > %t.readobj-dt-no-alias +# RUN: diff %t.readobj-dt-alias %t.readobj-dt-no-alias # CHECK: DynamicSymbols [ # CHECK-NEXT: Symbol { @@ -161,3 +162,57 @@ # CHECK-NEXT: Section: .fini # CHECK-NEXT: } # CHECK-NEXT: ] + +## Check that we are able to dump dynamic symbols table even when we have no program headers. +## In this case we find the table by it's type (SHT_DYNSYM) and ignore the DT_SYMTAB value. + +# RUN: yaml2obj --docnum=1 %s -o %t1.so +# RUN: llvm-readobj %t.so --dyn-symbols | FileCheck %s --check-prefix=NOPHDRS + +# NOPHDRS: foo + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_SYMTAB + Value: 0 + - Tag: DT_NULL + Value: 0 +DynamicSymbols: + - Name: foo + +## Check we report a warning when there is no SHT_DYNSYM section and we can't map the DT_SYMTAB value +## to address because of absence of the corresponding PT_LOAD program header. + +# RUN: yaml2obj --docnum=2 %s -o %t2.so +# RUN: llvm-readobj %t2.so --dyn-symbols 2>&1 | FileCheck %s -DFILE=%t2.so --check-prefix=NOSHT-DYNSYM + +# NOSHT-DYNSYM: warning: '[[FILE]]': Unable to parse DT_SYMTAB: virtual address is not in any segment: 0x0 +# NOSHT-DYNSYM: DynamicSymbols [ +# NOSHT-DYNSYM-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .dynsym + Type: SHT_PROGBITS + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_SYMTAB + Value: 0 + - Tag: DT_NULL + Value: 0 +DynamicSymbols: + - Name: foo Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -1644,8 +1644,18 @@ StringTableSize = Dyn.getVal(); break; case ELF::DT_SYMTAB: - DynSymRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); - DynSymRegion.EntSize = sizeof(Elf_Sym); + // Normally we find the dynamic symbols section location and size using + // the information in sections headers. That allows us to dump dynamic + // symbols when program headers are absent. This is consistent with GNU + // readelf and seems reasonable because there is no DT_SYMTABSZ tag exist, + // i.e. the only way to get the size of the dynamic symbols table is to + // take it from section headers. But we still need the code below for + // specific cases, for example when we want to dump the dynamic + // relocations and there is no sections table. + if (!DynSymRegion.EntSize) { + DynSymRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); + DynSymRegion.EntSize = sizeof(Elf_Sym); + } break; case ELF::DT_RELA: DynRelaRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());