diff --git a/llvm/test/tools/obj2yaml/ELF/DWARF/debug-str.yaml b/llvm/test/tools/obj2yaml/ELF/DWARF/debug-str.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/obj2yaml/ELF/DWARF/debug-str.yaml @@ -0,0 +1,101 @@ +## Test how we dump the .debug_str section. + +## a) Test dumping a .debug_str section with a default section header. + +# RUN: yaml2obj --docnum=1 %s | obj2yaml | \ +# RUN: FileCheck %s --check-prefix=BASIC --implicit-check-not='Name: .debug_str' + +## b) Test dumping a .debug_str section whose section header properties are overridden. + +## Override the sh_type field. +# RUN: yaml2obj --docnum=1 -DTYPE=STRTAB %s | obj2yaml | \ +# RUN: FileCheck %s --check-prefixes=BASIC,COMMON \ +# RUN: -DTYPE=STRTAB -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=1 + +## Override the sh_flags field. +# RUN: yaml2obj --docnum=1 -DFLAGS=[SHF_ALLOC] %s | obj2yaml | \ +# RUN: FileCheck %s --check-prefixes=BASIC,COMMON \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_ALLOC ]" -D#%x,ADDRALIGN=1 + +## Override the sh_link field. +# RUN: yaml2obj --docnum=1 -DLINK=.sec %s | obj2yaml | \ +# RUN: FileCheck %s --check-prefixes=BASIC,COMMON,LINK \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -DLINK=.sec -D#%x,ADDRALIGN=1 + +## Override the sh_addr field. +# RUN: yaml2obj --docnum=1 -DADDRESS=0x2020 %s | obj2yaml | \ +# RUN: FileCheck %s --check-prefixes=BASIC,COMMON,ADDRESS \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=1 -D#%x,ADDRESS=0x2020 + +## Override the sh_addralign field. +# RUN: yaml2obj --docnum=1 -DADDRALIGN=3 %s | obj2yaml | \ +# RUN: FileCheck %s --check-prefixes=BASIC,COMMON \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=3 + +## Override the sh_entsize field (sh_entsize=3). +# RUN: yaml2obj --docnum=1 -DENTSIZE=3 %s | obj2yaml | \ +# RUN: FileCheck %s --check-prefixes=BASIC,COMMON,ENTSIZE \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=1 -D#%x,ENTSIZE=3 + +## Override the sh_entsize field (sh_entsize=0). +# RUN: yaml2obj --docnum=1 -DENTSIZE=0 %s | obj2yaml | \ +# RUN: FileCheck %s --check-prefixes=BASIC,COMMON,ENTSIZE \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=1 -D#%x,ENTSIZE=0 + +## Override the sh_info field. +# RUN: yaml2obj --docnum=1 -DINFO=3 %s | obj2yaml | \ +# RUN: FileCheck %s --check-prefixes=BASIC,COMMON,INFO \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,INFO=3 -D#%x,ADDRALIGN=1 -D#%x,ENTSIZE=1 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC +Sections: + - Name: .debug_str + Type: SHT_[[TYPE=PROGBITS]] + Flags: [[FLAGS=]] + Link: [[LINK='']] + EntSize: [[ENTSIZE=1]] + Info: [[INFO=]] + AddressAlign: [[ADDRALIGN=1]] + Address: [[ADDRESS=]] + - Name: .sec + Type: SHT_PROGBITS +DWARF: + debug_str: + - a + - b + - abc + +# COMMON: - Name: .debug_str +# COMMON-NEXT: Type: SHT_[[TYPE]] +# COMMON-NEXT: Flags: [[FLAGS]] +# LINK-NEXT: Link: .sec +# ADDRESS-NEXT: Address: 0x[[#%.16x,ADDRESS]] +# COMMON-NEXT: AddressAlign: 0x[[#%.16x,ADDRALIGN]] +# ENTSIZE-NEXT: EntSize: 0x[[#%.16x,ENTSIZE]] +# INFO-NEXT: Info: 0x[[#%.16x,INFO]] +# BASIC: DWARF: +# BASIC-NEXT: debug_str: +# BASIC-NEXT: - a +# BASIC-NEXT: - b +# BASIC-NEXT: - abc +# BASIC-NEXT: ... + +## c) Test dumping an empty .debug_str section. + +# RUN: yaml2obj --docnum=2 %s | obj2yaml | FileCheck %s --check-prefix=EMPTY --implicit-check-not=Sections + +# EMPTY: DWARF: +# EMPTY-NEXT: debug_str: [] +# EMPTY-NEXT: ... + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC +DWARF: + debug_str: [] diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp --- a/llvm/tools/obj2yaml/elf2yaml.cpp +++ b/llvm/tools/obj2yaml/elf2yaml.cpp @@ -197,12 +197,22 @@ // entry but their section headers may have special flags, entry size, address // alignment, etc. We will preserve the header for them under such // circumstances. - if (DWARF && DWARF->getNonEmptySectionNames().count(S.Name.substr(1))) { + StringRef SecName = S.Name.substr(1); + if (DWARF && DWARF->getNonEmptySectionNames().count(SecName)) { if (const ELFYAML::RawContentSection *RawSec = - dyn_cast(&S)) - return RawSec->Type != ELF::SHT_PROGBITS || RawSec->Flags || - !RawSec->Link.empty() || RawSec->Info || - RawSec->AddressAlign != 1 || RawSec->EntSize; + dyn_cast(&S)) { + if (RawSec->Type != ELF::SHT_PROGBITS || !RawSec->Link.empty() || + RawSec->Info || RawSec->AddressAlign != 1 || RawSec->Address || + RawSec->EntSize) + return true; + + ELFYAML::ELF_SHF ShFlags = RawSec->Flags.getValueOr(ELFYAML::ELF_SHF(0)); + + if (SecName == "debug_str") + return ShFlags != ELFYAML::ELF_SHF(ELF::SHF_MERGE | ELF::SHF_STRINGS); + + return ShFlags != 0; + } } // Normally we use "Symbols:" and "DynamicSymbols:" to describe contents of @@ -404,6 +414,8 @@ if (RawSec->Name == ".debug_aranges") Err = dumpDebugARanges(*DWARFCtx.get(), DWARF); + else if (RawSec->Name == ".debug_str") + dumpDebugStrings(*DWARFCtx.get(), DWARF); // If the DWARF section cannot be successfully parsed, emit raw content // instead of an entry in the DWARF section of the YAML. @@ -622,7 +634,8 @@ } template -static unsigned getDefaultShEntSize(ELFYAML::ELF_SHT SecType) { +static unsigned getDefaultShEntSize(ELFYAML::ELF_SHT SecType, + StringRef SecName) { switch (SecType) { case ELF::SHT_REL: return sizeof(typename ELFT::Rel); @@ -633,6 +646,8 @@ case ELF::SHT_DYNAMIC: return sizeof(typename ELFT::Dyn); default: + if (SecName == ".debug_str") + return 1; return 0; } } @@ -649,9 +664,6 @@ S.Address = static_cast(Shdr->sh_addr); S.AddressAlign = Shdr->sh_addralign; - if (Shdr->sh_entsize != getDefaultShEntSize(S.Type)) - S.EntSize = static_cast(Shdr->sh_entsize); - S.OriginalSecNdx = Shdr - &Sections[0]; auto NameOrErr = getUniquedSectionName(Shdr); @@ -659,6 +671,9 @@ return NameOrErr.takeError(); S.Name = NameOrErr.get(); + if (Shdr->sh_entsize != getDefaultShEntSize(S.Type, S.Name)) + S.EntSize = static_cast(Shdr->sh_entsize); + if (Shdr->sh_link != ELF::SHN_UNDEF) { auto LinkSection = Obj.getSection(Shdr->sh_link); if (!LinkSection)