Index: test/tools/llvm-readobj/elf-broken-dynsym-link.test =================================================================== --- /dev/null +++ test/tools/llvm-readobj/elf-broken-dynsym-link.test @@ -0,0 +1,60 @@ +## Test that we are able to dump section headers even if the +## .dynsym section's sh_link field is broken. + +## Case 1: sh_link is set to 0. +# RUN: yaml2obj %s -o %t1 +# RUN: llvm-readobj -S %t1 2>&1 | FileCheck %s --check-prefixes=LLVM,ERR +# RUN: llvm-readelf -S %t1 2>&1 | FileCheck %s --check-prefixes=GNU,ERR + +# ERR: warning: invalid sh_type for string table, expected SHT_STRTAB + +# LLVM: Name: .dynsym +# LLVM-NEXT: Type: SHT_DYNSYM +# LLVM-NEXT: Flags [ +# LLVM-NEXT: SHF_ALLOC +# LLVM-NEXT: ] +# LLVM-NEXT: Address: 0x0 +# LLVM-NEXT: Offset: 0x180 +# LLVM-NEXT: Size: 24 +# LLVM-NEXT: Link: 0 + +# GNU: Section Headers: +# GNU-NEXT: [Nr] Name Type Address Off Size ES Flg Lk +# GNU-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 +# GNU-NEXT: [ 1] .dynsym DYNSYM 0000000000000000 000180 000018 18 A 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .dynsym + Type: SHT_DYNSYM + +## TODO: Remove precompiled input object after fixing yaml2obj. +## See https://bugs.llvm.org/show_bug.cgi?id=42216. + +## Case 2: sh_link is set to 255, which is larger than the number of the sections. +# RUN: llvm-readobj -S %p/Inputs/elf-broken-dynsym-link.elf-x86-64 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=LLVM2,ERR2 +# RUN: llvm-readelf -S %p/Inputs/elf-broken-dynsym-link.elf-x86-64 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=GNU2,ERR2 + +# ERR2: warning: invalid section index + +# LLVM2: Name: .dynsym +# LLVM2-NEXT: Type: SHT_DYNSYM +# LLVM2-NEXT: Flags [ +# LLVM2-NEXT: SHF_ALLOC +# LLVM2-NEXT: ] +# LLVM2-NEXT: Address: 0x0 +# LLVM2-NEXT: Offset: 0x180 +# LLVM2-NEXT: Size: 2 +# LLVM2-NEXT: Link: 255 + +# GNU2: Section Headers: +# GNU2-NEXT: [Nr] Name Type Address Off Size ES Flg Lk +# GNU2-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 +# GNU2-NEXT: [ 1] .dynsym DYNSYM 0000000000000000 000180 000002 18 A 255 Index: test/tools/yaml2obj/explicit-dynsym-no-dynstr.yaml =================================================================== --- test/tools/yaml2obj/explicit-dynsym-no-dynstr.yaml +++ test/tools/yaml2obj/explicit-dynsym-no-dynstr.yaml @@ -2,14 +2,14 @@ ## explicitly, but .dynstr is not present. # RUN: yaml2obj %s -o %t -# RUN: not llvm-readelf --section-headers %t 2>&1 | FileCheck %s +# RUN: llvm-readelf --section-headers %t | FileCheck %s -## TODO: Check that .dynsym has Link field set to 0. -## GNU readelf is able to dump sections headers, -## but llvm-readelf reports an error below too early. -## See https://bugs.llvm.org/show_bug.cgi?id=42215. +## Check that .dynsym has Link field set to 0. -# CHECK: error: invalid sh_type for string table, expected SHT_STRTAB +# CHECK: Section Headers: +# CHECK-NEXT: [Nr] Name Type Address Off Size ES Flg Lk +# CHECK-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 +# CHECK-NEXT: [ 1] .dynsym DYNSYM 0000000000000000 000180 000018 18 A 0 --- !ELF FileHeader: Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -1423,7 +1423,7 @@ // This is only used (if Elf_Shdr present)for naming section in GNU // style DynSymtabName = unwrapOrError(Obj->getSectionName(&Sec)); - DynamicStringTable = unwrapOrError(Obj->getStringTableForSymtab(Sec)); + DynamicStringTable = unwrapOrWarn(Obj->getStringTableForSymtab(Sec)); } break; case ELF::SHT_SYMTAB_SHNDX: Index: tools/llvm-readobj/llvm-readobj.h =================================================================== --- tools/llvm-readobj/llvm-readobj.h +++ tools/llvm-readobj/llvm-readobj.h @@ -44,6 +44,16 @@ OS.flush(); reportError(Buf); } + template T unwrapOrWarn(Expected EO) { + if (EO) + return *EO; + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(EO.takeError(), OS); + OS.flush(); + reportWarning(Buf); + return {}; + } } // namespace llvm namespace opts {