diff --git a/llvm/include/llvm/ObjectYAML/DWARFEmitter.h b/llvm/include/llvm/ObjectYAML/DWARFEmitter.h --- a/llvm/include/llvm/ObjectYAML/DWARFEmitter.h +++ b/llvm/include/llvm/ObjectYAML/DWARFEmitter.h @@ -29,7 +29,7 @@ Error emitDebugAbbrev(raw_ostream &OS, const Data &DI); Error emitDebugStr(raw_ostream &OS, const Data &DI); - +Error emitDebugStrDWO(raw_ostream &OS, const Data &DI); Error emitDebugAranges(raw_ostream &OS, const Data &DI); Error emitDebugRanges(raw_ostream &OS, const Data &DI); Error emitDebugPubnames(raw_ostream &OS, const Data &DI); diff --git a/llvm/include/llvm/ObjectYAML/DWARFYAML.h b/llvm/include/llvm/ObjectYAML/DWARFYAML.h --- a/llvm/include/llvm/ObjectYAML/DWARFYAML.h +++ b/llvm/include/llvm/ObjectYAML/DWARFYAML.h @@ -213,6 +213,7 @@ std::vector DebugAbbrev; Optional> DebugStrings; Optional> DebugStrOffsets; + Optional> DebugStringsDWO; Optional> DebugAranges; Optional> DebugRanges; Optional> DebugAddr; diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -101,7 +101,7 @@ case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: return sizeof(object::Elf_CGProfile_Impl); default: - if (SecName == ".debug_str") + if (SecName == ".debug_str" || SecName == ".debug_str.dwo") return 1; return 0; } diff --git a/llvm/lib/ObjectYAML/DWARFEmitter.cpp b/llvm/lib/ObjectYAML/DWARFEmitter.cpp --- a/llvm/lib/ObjectYAML/DWARFEmitter.cpp +++ b/llvm/lib/ObjectYAML/DWARFEmitter.cpp @@ -84,12 +84,23 @@ OS, IsLittleEndian)); } -Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) { - for (StringRef Str : *DI.DebugStrings) { +static void emitDebugStrings(raw_ostream &OS, + const std::vector &DebugStrs) { + for (StringRef Str : DebugStrs) { OS.write(Str.data(), Str.size()); OS.write('\0'); } +} + +Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) { + assert(DI.DebugStrings && "unexpected emitDebugStr() call"); + emitDebugStrings(OS, *DI.DebugStrings); + return Error::success(); +} +Error DWARFYAML::emitDebugStrDWO(raw_ostream &OS, const DWARFYAML::Data &DI) { + assert(DI.DebugStringsDWO && "unexpected emitDebugStrDWO() call"); + emitDebugStrings(OS, *DI.DebugStringsDWO); return Error::success(); } @@ -1022,6 +1033,7 @@ .Case("debug_ranges", DWARFYAML::emitDebugRanges) .Case("debug_rnglists", DWARFYAML::emitDebugRnglists) .Case("debug_str", DWARFYAML::emitDebugStr) + .Case("debug_str.dwo", DWARFYAML::emitDebugStrDWO) .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets) .Default([&](raw_ostream &, const DWARFYAML::Data &) { return createStringError(errc::not_supported, diff --git a/llvm/lib/ObjectYAML/DWARFYAML.cpp b/llvm/lib/ObjectYAML/DWARFYAML.cpp --- a/llvm/lib/ObjectYAML/DWARFYAML.cpp +++ b/llvm/lib/ObjectYAML/DWARFYAML.cpp @@ -52,6 +52,8 @@ SecNames.insert("debug_rnglists"); if (DebugLoclists) SecNames.insert("debug_loclists"); + if (DebugStringsDWO) + SecNames.insert("debug_str.dwo"); return SecNames; } @@ -93,6 +95,7 @@ DWARFYAML::DWARFContext DWARFCtx; IO.setContext(&DWARFCtx); IO.mapOptional("debug_str", DWARF.DebugStrings); + IO.mapOptional("debug_str.dwo", DWARF.DebugStringsDWO); IO.mapOptional("debug_abbrev", DWARF.DebugAbbrev); IO.mapOptional("debug_aranges", DWARF.DebugAranges); IO.mapOptional("debug_ranges", DWARF.DebugRanges); diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -1127,6 +1127,8 @@ SHeader.sh_flags = *YAMLSec->Flags; else if (Name == ".debug_str") SHeader.sh_flags = ELF::SHF_MERGE | ELF::SHF_STRINGS; + else if (Name == ".debug_str.dwo") + SHeader.sh_flags = ELF::SHF_EXCLUDE | ELF::SHF_MERGE | ELF::SHF_STRINGS; assignSectionAddress(SHeader, YAMLSec); } diff --git a/llvm/test/tools/obj2yaml/ELF/DWARF/debug-str.yaml b/llvm/test/tools/obj2yaml/ELF/DWARF/debug-str.yaml --- a/llvm/test/tools/obj2yaml/ELF/DWARF/debug-str.yaml +++ b/llvm/test/tools/obj2yaml/ELF/DWARF/debug-str.yaml @@ -1,59 +1,94 @@ -## Test how we dump the .debug_str section. +## Test how we dump the .debug_str[.dwo] section. -## a) Test dumping a .debug_str section with a default section header. +## a) Test dumping a .debug_str[.dwo] section with a default section header. # RUN: yaml2obj --docnum=1 %s | obj2yaml | \ -# RUN: FileCheck %s --check-prefix=BASIC --implicit-check-not='Name: .debug_str' +# RUN: FileCheck -DSECNAME=debug_str %s --check-prefix=BASIC --implicit-check-not='Name: .debug_str' -## b) Test dumping a .debug_str section whose section header properties are overridden. +# RUN: yaml2obj --docnum=1 -DSECNAME=debug_str.dwo %s | obj2yaml | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %s --check-prefix=BASIC --implicit-check-not='Name: .debug_str.dwo' + +## b) Test dumping a .debug_str[.dwo] 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: FileCheck -DSECNAME=debug_str %s --check-prefixes=BASIC,COMMON \ # RUN: -DTYPE=STRTAB -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=1 +# RUN: yaml2obj --docnum=1 -DSECNAME=debug_str.dwo -DTYPE=STRTAB %s | obj2yaml | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %s --check-prefixes=BASIC,COMMON \ +# RUN: -DTYPE=STRTAB -DFLAGS="[ SHF_EXCLUDE, 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: FileCheck -DSECNAME=debug_str %s --check-prefixes=BASIC,COMMON \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_ALLOC ]" -D#%x,ADDRALIGN=1 + +# RUN: yaml2obj --docnum=1 -DSECNAME=debug_str.dwo -DFLAGS=[SHF_ALLOC] %s | obj2yaml | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %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: FileCheck -DSECNAME=debug_str %s --check-prefixes=BASIC,COMMON,LINK \ # RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -DLINK=.sec -D#%x,ADDRALIGN=1 +# RUN: yaml2obj --docnum=1 -DSECNAME=debug_str.dwo -DLINK=.sec %s | obj2yaml | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %s --check-prefixes=BASIC,COMMON,LINK \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_EXCLUDE, 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: FileCheck -DSECNAME=debug_str %s --check-prefixes=BASIC,COMMON,ADDRESS \ # RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=1 -D#%x,ADDRESS=0x2020 +# RUN: yaml2obj --docnum=1 -DSECNAME=debug_str.dwo -DADDRESS=0x2022 %s | obj2yaml | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %s --check-prefixes=BASIC,COMMON,ADDRESS \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=1 -D#%x,ADDRESS=0x2022 + ## Override the sh_addralign field. # RUN: yaml2obj --docnum=1 -DADDRALIGN=3 %s | obj2yaml | \ -# RUN: FileCheck %s --check-prefixes=BASIC,COMMON \ +# RUN: FileCheck -DSECNAME=debug_str %s --check-prefixes=BASIC,COMMON \ # RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=3 +# RUN: yaml2obj --docnum=1 -DSECNAME=debug_str.dwo -DADDRALIGN=3 %s | obj2yaml | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %s --check-prefixes=BASIC,COMMON \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_EXCLUDE, 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: FileCheck -DSECNAME=debug_str %s --check-prefixes=BASIC,COMMON,ENTSIZE \ # RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=1 -D#%x,ENTSIZE=3 +# RUN: yaml2obj --docnum=1 -DSECNAME=debug_str.dwo -DENTSIZE=3 %s | obj2yaml | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %s --check-prefixes=BASIC,COMMON,ENTSIZE \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_EXCLUDE, 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: FileCheck -DSECNAME=debug_str %s --check-prefixes=BASIC,COMMON,ENTSIZE \ # RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_MERGE, SHF_STRINGS ]" -D#%x,ADDRALIGN=1 -D#%x,ENTSIZE=0 +# RUN: yaml2obj --docnum=1 -DSECNAME=debug_str.dwo -DENTSIZE=0 %s | obj2yaml | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %s --check-prefixes=BASIC,COMMON,ENTSIZE \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_EXCLUDE, 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: FileCheck -DSECNAME=debug_str %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 +# RUN: yaml2obj --docnum=1 -DSECNAME=debug_str.dwo -DINFO=3 %s | obj2yaml | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %s --check-prefixes=BASIC,COMMON,INFO \ +# RUN: -DTYPE=PROGBITS -DFLAGS="[ SHF_EXCLUDE, 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 + - Name: .[[SECNAME=debug_str]] Type: SHT_[[TYPE=PROGBITS]] Flags: [[FLAGS=]] Link: [[LINK=]] @@ -64,12 +99,12 @@ - Name: .sec Type: SHT_PROGBITS DWARF: - debug_str: + [[SECNAME=debug_str]]: - a - b - abc -# COMMON: - Name: .debug_str +# COMMON: - Name: .[[SECNAME]] # COMMON-NEXT: Type: SHT_[[TYPE]] # COMMON-NEXT: Flags: [[FLAGS]] # LINK-NEXT: Link: .sec @@ -78,18 +113,19 @@ # ENTSIZE-NEXT: EntSize: 0x[[#%x,ENTSIZE]] # INFO-NEXT: Info: 0x[[#%x,INFO]] # BASIC: DWARF: -# BASIC-NEXT: debug_str: +# BASIC-NEXT: [[SECNAME]]: # BASIC-NEXT: - a # BASIC-NEXT: - b # BASIC-NEXT: - abc # BASIC-NEXT: ... -## c) Test dumping an empty .debug_str section. +## c) Test dumping empty .debug_str and .debug_str.dwo sections. # RUN: yaml2obj --docnum=2 %s | obj2yaml | FileCheck %s --check-prefix=EMPTY --implicit-check-not=Sections # EMPTY: DWARF: # EMPTY-NEXT: debug_str: [] +# EMPTY-NEXT: debug_str.dwo: [] # EMPTY-NEXT: ... --- !ELF @@ -99,18 +135,23 @@ Type: ET_EXEC DWARF: debug_str: [] + debug_str.dwo: [] -## d) Test that yaml2obj stops parsing the .debug_str section if it encounters a +## d) Test that obj2yaml stops parsing the .debug_str[.dwo] section if it encounters a ## string without a null terminator. The output uses a raw content section instead of -## the DWARF tag to represent the broken .debug_str section. +## the DWARF tag to represent the broken .debug_str[.dwo] section. + +# RUN: yaml2obj --docnum=3 %s | obj2yaml | \ +# RUN: FileCheck -DFLAGS='[ SHF_MERGE, SHF_STRINGS ]' %s --check-prefix=NO-TERMINATOR -# RUN: yaml2obj --docnum=3 %s | obj2yaml | FileCheck %s --check-prefix=NO-TERMINATOR +# RUN: yaml2obj --docnum=3 -DSECNAME=debug_str.dwo %s | obj2yaml | \ +# RUN: FileCheck -DFLAGS='[ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ]' %s --check-prefix=NO-TERMINATOR # NO-TERMINATOR-NOT: DWARF: # NO-TERMINATOR: Sections: # NO-TERMINATOR-NEXT: - Name: .debug_str # NO-TERMINATOR-NEXT: Type: SHT_PROGBITS -# NO-TERMINATOR-NEXT: Flags: [ SHF_MERGE, SHF_STRINGS ] +# NO-TERMINATOR-NEXT: Flags: [[FLAGS]] # NO-TERMINATOR-NEXT: Content: '61626300616263' # NO-TERMINATOR-NEXT: ... @@ -120,6 +161,6 @@ Data: ELFDATA2LSB Type: ET_EXEC Sections: - - Name: .debug_str + - Name: .[[SECNAME=debug_str]] Type: SHT_PROGBITS Content: "61626300616263" ## "abc\0abc" diff --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-str.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-str.yaml --- a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-str.yaml +++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-str.yaml @@ -1,22 +1,27 @@ -## Test that yaml2obj emits .debug_str section. +## Test that yaml2obj emits .debug_str[.dwo] section. -## a) Generate the .debug_str section from the "DWARF" entry. +## a) Generate the .debug_str[.dwo] section from the "DWARF" entry. # RUN: yaml2obj --docnum=1 %s -o %t1.o -# RUN: llvm-readelf --string-dump=.debug_str %t1.o | FileCheck %s --check-prefix=DWARF-DEFAULT +# RUN: llvm-readelf --string-dump=.debug_str --string-dump=.debug_str.dwo %t1.o | FileCheck %s --check-prefix=DWARF-DEFAULT # DWARF-DEFAULT: String dump of section '.debug_str': # DWARF-DEFAULT-NEXT: [ 0] a # DWARF-DEFAULT-NEXT: [ 2] b # DWARF-DEFAULT-NEXT: [ 4] c +# DWARF-DEFAULT: String dump of section '.debug_str.dwo': +# DWARF-DEFAULT-NEXT: [ 0] b +# DWARF-DEFAULT-NEXT: [ 2] a +# DWARF-DEFAULT-NEXT: [ 4] c ## Check the default sh_type, sh_entsize, sh_info, sh_flags and sh_addralign of the -## .debug_str section header. +## .debug_str[.dwo] section header. -# RUN: llvm-readelf -S %t1.o | FileCheck -DSIZE=000006 %s --check-prefix=SHDRS-DEFAULT +# RUN: llvm-readelf -S %t1.o | FileCheck -DSIZE=000006 -DOFFSET1=000040 -DOFFSET2=000046 %s --check-prefix=SHDRS-DEFAULT -# SHDRS-DEFAULT: Name Type Address Off Size ES Flg Lk Inf Al -# SHDRS-DEFAULT: .debug_str PROGBITS 0000000000000000 000040 [[SIZE]] 01 MS 0 0 1 +# SHDRS-DEFAULT: Name Type Address Off Size ES Flg Lk Inf Al +# SHDRS-DEFAULT: .debug_str PROGBITS 0000000000000000 [[OFFSET1]] [[SIZE]] 01 MS 0 0 1 +# SHDRS-DEFAULT: .debug_str.dwo PROGBITS 0000000000000000 [[OFFSET2]] [[SIZE]] 01 MSE 0 0 1 --- !ELF FileHeader: @@ -28,15 +33,20 @@ - a - b - c + debug_str.dwo: + - b + - a + - c -## b) Generate the .debug_str section from the raw section content. +## b) Generate the .debug_str[.dwo] section from the raw section content. # RUN: yaml2obj --docnum=2 %s -o %t2.o -# RUN: llvm-readelf --string-dump=.debug_str %t2.o | FileCheck %s --check-prefix=DWARF-DEFAULT +# RUN: llvm-readelf --string-dump=.debug_str --string-dump=.debug_str.dwo %t2.o | FileCheck %s --check-prefix=DWARF-DEFAULT # RUN: llvm-readelf -S %t2.o | FileCheck %s --check-prefix=SHDRS -# SHDRS: Name Type Address Off Size ES Flg Lk Inf Al -# SHDRS: .debug_str PROGBITS 0000000000000000 000040 000006 01 MS 0 0 0 +# SHDRS: Name Type Address Off Size ES Flg Lk Inf Al +# SHDRS: .debug_str PROGBITS 0000000000000000 000040 000006 01 MS 0 0 0 +# SHDRS: .debug_str.dwo PROGBITS 0000000000000000 000046 000006 01 MSE 0 0 0 --- !ELF FileHeader: @@ -47,19 +57,27 @@ - Name: .debug_str Type: SHT_PROGBITS Content: "610062006300" + - Name: .debug_str.dwo + Type: SHT_PROGBITS + Content: "620061006300" -## c) Generate the .debug_str section when the "Size" is specified. +## c) Generate the .debug_str[.dwo] section when the "Size" is specified. # RUN: yaml2obj --docnum=3 %s -o %t3.o # RUN: llvm-readelf -S %t3.o | FileCheck %s --check-prefix=SIZE -# RUN: llvm-readelf --hex-dump=.debug_str %t3.o | FileCheck %s --check-prefix=SIZE-CONTENT +# RUN: llvm-readelf --hex-dump=.debug_str --hex-dump=.debug_str.dwo %t3.o | FileCheck %s --check-prefix=SIZE-CONTENT -# SIZE: Name Type Address Off Size ES Flg Lk Inf Al -# SIZE: .debug_str PROGBITS 0000000000000000 000040 000010 01 MS 0 0 0 +# SIZE: Name Type Address Off Size ES Flg Lk Inf Al +# SIZE: .debug_str PROGBITS 0000000000000000 000040 000010 01 MS 0 0 0 +# SIZE: .debug_str.dwo PROGBITS 0000000000000000 000050 000012 01 MSE 0 0 0 # SIZE-CONTENT: Hex dump of section '.debug_str': # SIZE-CONTENT-NEXT: 0x00000000 00000000 00000000 00000000 00000000 ................ # SIZE-CONTENT-EMPTY: +# SIZE-CONTENT: Hex dump of section '.debug_str.dwo': +# SIZE-CONTENT-NEXT: 0x00000000 00000000 00000000 00000000 00000000 ................ +# SIZE-CONTENT-NEXT: 0x00000010 0000 .. +# SIZE-CONTENT-EMPTY: --- !ELF FileHeader: @@ -70,13 +88,22 @@ - Name: .debug_str Type: SHT_PROGBITS Size: 0x10 + - Name: .debug_str.dwo + Type: SHT_PROGBITS + Size: 0x12 -## d) Test that yaml2obj emits an error message when both the "Size" and the +## d.1) Test that yaml2obj emits an error message when both the "Size" and the ## "debug_str" entry are specified at the same time. -# RUN: not yaml2obj --docnum=4 %s -o %t4.o 2>&1 | FileCheck %s --check-prefix=ERROR +# RUN: not yaml2obj --docnum=4 %s -o %t4.1.o 2>&1 | FileCheck -DSECNAME=debug_str %s --check-prefix=ERROR + +## d.2) Test that yaml2obj emits an error message when both the "Size" and the +## "debug_str.dwo" entry are specified at the same time. -# ERROR: yaml2obj: error: cannot specify section '.debug_str' contents in the 'DWARF' entry and the 'Content' or 'Size' in the 'Sections' entry at the same time +# RUN: not yaml2obj --docnum=4 -DSECNAME=debug_str.dwo %s -o %t4.2.o 2>&1 | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %s --check-prefix=ERROR + +# ERROR: yaml2obj: error: cannot specify section '.[[SECNAME]]' contents in the 'DWARF' entry and the 'Content' or 'Size' in the 'Sections' entry at the same time --- !ELF FileHeader: @@ -84,17 +111,23 @@ Data: ELFDATA2LSB Type: ET_EXEC Sections: - - Name: .debug_str + - Name: .[[SECNAME=debug_str]] Type: SHT_PROGBITS Size: 0x10 DWARF: - debug_str: + [[SECNAME=debug_str]]: - a -## e) Test that yaml2obj emits an error message when both the "Content" and the +## e.1) Test that yaml2obj emits an error message when both the "Content" and the ## "debug_str" entry are specified at the same time. -# RUN: not yaml2obj --docnum=5 %s -o %t5.o 2>&1 | FileCheck %s --check-prefix=ERROR +# RUN: not yaml2obj --docnum=5 %s -o %t5.1.o 2>&1 | FileCheck -DSECNAME=debug_str %s --check-prefix=ERROR + +## e.2) Test that yaml2obj emits an error message when both the "Content" and the +## "debug_str.dwo" entry are specified at the same time. + +# RUN: not yaml2obj --docnum=5 -DSECNAME=debug_str.dwo %s -o %t5.2.o 2>&1 | \ +# RUN: FileCheck -DSECNAME=debug_str.dwo %s --check-prefix=ERROR --- !ELF FileHeader: @@ -102,22 +135,23 @@ Data: ELFDATA2LSB Type: ET_EXEC Sections: - - Name: .debug_str + - Name: .[[SECNAME=debug_str]] Type: SHT_PROGBITS Content: "6100" DWARF: - debug_str: + [[SECNAME=debug_str]]: - a ## f) Test that all the properties can be overridden by the section header when -## the "debug_str" entry doesn't exist. +## the "debug_str[.dwo]" entry doesn't exist. # RUN: yaml2obj --docnum=6 %s -o %t6.o # RUN: llvm-readelf -S %t6.o | FileCheck %s --check-prefix=OVERRIDDEN -# OVERRIDDEN: [Nr] Name Type Address Off Size ES Flg Lk Inf Al -# OVERRIDDEN: [ 1] .sec STRTAB 0000000000000000 000040 000000 00 0 0 0 -# OVERRIDDEN: [ 2] .debug_str STRTAB 0000000000002020 000050 000006 02 A 1 1 2 +# OVERRIDDEN: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# OVERRIDDEN: [ 1] .sec STRTAB 0000000000000000 000040 000000 00 0 0 0 +# OVERRIDDEN: [ 2] .debug_str STRTAB 0000000000002020 000050 000006 02 A 1 1 2 +# OVERRIDDEN: [ 3] .debug_str.dwo STRTAB 0000000000002022 000066 000006 02 A 1 1 2 --- !ELF FileHeader: @@ -125,7 +159,7 @@ Data: ELFDATA2LSB Type: ET_EXEC Sections: - - Name: .sec # Linked by .debug_str. + - Name: .sec # Linked by .debug_str[.dwo]. Type: SHT_STRTAB - Name: .debug_str Type: SHT_STRTAB # SHT_PROGBITS by default. @@ -137,12 +171,22 @@ Address: 0x0000000000002020 # 0x00 by default. Offset: 0x00000050 # 0x40 for the first section. Size: 6 # Set the "Size" so that we can reuse the check tag "OVERRIDDEN" + - Name: .debug_str.dwo + Type: SHT_STRTAB # SHT_PROGBITS by default. + Flags: [SHF_ALLOC] # [SHF_STRINGS, SHF_MERGE, SHF_EXCLUDE] by default. + Link: .sec # 0 by default. + EntSize: 2 # 1 by default. + Info: 1 # 0 by default. + AddressAlign: 2 # 0 by default. + Address: 0x0000000000002022 # 0x00 by default. + Offset: 0x00000066 # 0x56 for the second section. + Size: 6 # Set the "Size" so that we can reuse the check tag "OVERRIDDEN" ## g) Test that all the properties can be overridden by the section header when -## the "debug_str" entry is used. +## the "debug_str[.dwo]" entry is used. # RUN: yaml2obj --docnum=7 %s -o %t7.o -# RUN: llvm-readelf --string-dump=.debug_str %t7.o | FileCheck %s --check-prefix=DWARF-DEFAULT +# RUN: llvm-readelf --string-dump=.debug_str --string-dump=.debug_str.dwo %t7.o | FileCheck %s --check-prefix=DWARF-DEFAULT # RUN: llvm-readelf -S %t7.o | FileCheck %s --check-prefix=OVERRIDDEN --- !ELF @@ -151,7 +195,7 @@ Data: ELFDATA2LSB Type: ET_EXEC Sections: - - Name: .sec # Linked by .debug_str. + - Name: .sec # Linked by .debug_str[.dwo]. Type: SHT_STRTAB - Name: .debug_str Type: SHT_STRTAB # SHT_PROGBITS by default. @@ -162,26 +206,51 @@ AddressAlign: 2 # 1 by default. Address: 0x0000000000002020 # 0x00 by default. Offset: 0x00000050 # 0x40 for the first section. + - Name: .debug_str.dwo + Type: SHT_STRTAB # SHT_PROGBITS by default. + Flags: [SHF_ALLOC] # [SHF_STRINGS, SHF_MERGE, SHF_EXCLUDE] by default. + Link: .sec # 0 by default. + EntSize: 2 # 1 by default. + Info: 1 # 0 by default. + AddressAlign: 2 # 1 by default. + Address: 0x0000000000002022 # 0x00 by default. + Offset: 0x00000066 # 0x56 for the second section. DWARF: debug_str: - a - b - c + debug_str.dwo: + - b + - a + - c -## h) Test that if we try to initialize the .debug_str section with a "Type" with non-standard +## h.1) Test that if we try to initialize the .debug_str section with a "Type" with non-standard ## syntax, e.g., SHT_DYNAMIC, yaml2obj will treat it as a dynamic section and discard the ## content in the "DWARF" entry. -# RUN: yaml2obj --docnum=8 %s -o %t8.o -# RUN: llvm-readelf -S %t8.o | FileCheck %s --check-prefix=DYN-SHDR -# RUN: llvm-readelf -d %t8.o | FileCheck %s --check-prefix=DYNAMIC +# RUN: yaml2obj --docnum=8 %s -o %t8.1.o +# RUN: llvm-readelf -S %t8.1.o | FileCheck -DSECNAME=debug_str %s --check-prefix=DYN-SHDR +# RUN: llvm-readelf -d %t8.1.o | FileCheck -DSECNAME=debug_str %s --check-prefix=DYNAMIC -# RUN: yaml2obj --docnum=9 %s -o %t9.o -# RUN: llvm-readelf -S %t9.o | FileCheck %s --check-prefix=DYN-SHDR -# RUN: llvm-readelf -d %t9.o | FileCheck %s --check-prefix=DYNAMIC +# RUN: yaml2obj --docnum=9 %s -o %t9.1.o +# RUN: llvm-readelf -S %t9.1.o | FileCheck -DSECNAME=debug_str %s --check-prefix=DYN-SHDR +# RUN: llvm-readelf -d %t9.1.o | FileCheck -DSECNAME=debug_str %s --check-prefix=DYNAMIC -# DYN-SHDR: Name Type Address Off Size ES Flg Lk Inf Al -# DYN-SHDR: .debug_str DYNAMIC 0000000000000000 000040 000010 10 0 0 0 +## h.2) Test that if we try to initialize the .debug_str.dwo section with a "Type" with non-standard +## syntax, e.g., SHT_DYNAMIC, yaml2obj will treat it as a dynamic section and discard the +## content in the "DWARF" entry. + +# RUN: yaml2obj --docnum=8 -DSECNAME=debug_str.dwo %s -o %t8.2.o +# RUN: llvm-readelf -S %t8.2.o | FileCheck -DSECNAME=debug_str.dwo %s --check-prefix=DYN-SHDR +# RUN: llvm-readelf -d %t8.2.o | FileCheck -DSECNAME=debug_str.dwo %s --check-prefix=DYNAMIC + +# RUN: yaml2obj --docnum=9 -DSECNAME=debug_str.dwo %s -o %t9.2.o +# RUN: llvm-readelf -S %t9.2.o | FileCheck -DSECNAME=debug_str.dwo %s --check-prefix=DYN-SHDR +# RUN: llvm-readelf -d %t9.2.o | FileCheck -DSECNAME=debug_str.dwo %s --check-prefix=DYNAMIC + +# DYN-SHDR: Name Type Address Off Size ES Flg Lk Inf Al +# DYN-SHDR: .[[SECNAME]] DYNAMIC 0000000000000000 000040 000010 10 0 0 0 # DYNAMIC: Dynamic section at offset 0x40 contains 1 entries: # DYNAMIC-NEXT: Tag Type Name/Value @@ -193,7 +262,7 @@ Data: ELFDATA2LSB Type: ET_EXEC Sections: - - Name: .debug_str + - Name: .[[SECNAME=debug_str]] Type: SHT_DYNAMIC Entries: - Tag: DT_NULL @@ -205,20 +274,20 @@ Data: ELFDATA2LSB Type: ET_EXEC Sections: - - Name: .debug_str + - Name: .[[SECNAME=debug_str]] Type: SHT_DYNAMIC Entries: - Tag: DT_NULL Value: 0 DWARF: - debug_str: + [[SECNAME=debug_str]]: - a -## i) Test that the .debug_str section header is emitted if the "debug_str" +## i) Test that the .debug_str[.dwo] section header is emitted if the "debug_str[.dwo]" ## entry is empty. # RUN: yaml2obj --docnum=10 %s -o %t10.o -# RUN: llvm-readelf -S %t10.o | FileCheck -DSIZE=000000 %s --check-prefix=SHDRS-DEFAULT +# RUN: llvm-readelf -S %t10.o | FileCheck -DSIZE=000000 -DOFFSET1=000040 -DOFFSET2=000040 %s --check-prefix=SHDRS-DEFAULT --- !ELF FileHeader: @@ -227,3 +296,4 @@ Type: ET_EXEC DWARF: debug_str: [] + debug_str.dwo: [] diff --git a/llvm/tools/obj2yaml/dwarf2yaml.cpp b/llvm/tools/obj2yaml/dwarf2yaml.cpp --- a/llvm/tools/obj2yaml/dwarf2yaml.cpp +++ b/llvm/tools/obj2yaml/dwarf2yaml.cpp @@ -80,8 +80,9 @@ return Error::success(); } -Error dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) { - DataExtractor StrData = DCtx.getStringExtractor(); +Error dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y, bool IsDWO) { + DataExtractor StrData = + IsDWO ? DCtx.getStringDWOExtractor() : DCtx.getStringExtractor(); uint64_t Offset = 0; std::vector DebugStr; Error Err = Error::success(); @@ -92,7 +93,10 @@ DebugStr.push_back(CStr); } - Y.DebugStrings = DebugStr; + if (IsDWO) + Y.DebugStringsDWO = DebugStr; + else + Y.DebugStrings = DebugStr; return Err; } 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 @@ -210,6 +210,9 @@ if (SecName == "debug_str") return ShFlags != ELFYAML::ELF_SHF(ELF::SHF_MERGE | ELF::SHF_STRINGS); + else if (SecName == "debug_str.dwo") + return ShFlags != ELFYAML::ELF_SHF(ELF::SHF_MERGE | ELF::SHF_STRINGS | + ELF::SHF_EXCLUDE); return ShFlags != ELFYAML::ELF_SHF{0}; } @@ -531,7 +534,9 @@ if (RawSec->Name == ".debug_aranges") Err = dumpDebugARanges(*DWARFCtx.get(), DWARF); else if (RawSec->Name == ".debug_str") - Err = dumpDebugStrings(*DWARFCtx.get(), DWARF); + Err = dumpDebugStrings(*DWARFCtx.get(), DWARF, /*IsDWO=*/false); + else if (RawSec->Name == ".debug_str.dwo") + Err = dumpDebugStrings(*DWARFCtx.get(), DWARF, /*IsDWO=*/true); else if (RawSec->Name == ".debug_ranges") Err = dumpDebugRanges(*DWARFCtx.get(), DWARF); else if (RawSec->Name == ".debug_addr") diff --git a/llvm/tools/obj2yaml/macho2yaml.cpp b/llvm/tools/obj2yaml/macho2yaml.cpp --- a/llvm/tools/obj2yaml/macho2yaml.cpp +++ b/llvm/tools/obj2yaml/macho2yaml.cpp @@ -159,7 +159,7 @@ if (SecName == "__debug_ranges") return dumpDebugRanges(DCtx, DWARF); if (SecName == "__debug_str") - return dumpDebugStrings(DCtx, DWARF); + return dumpDebugStrings(DCtx, DWARF, /*IsDWO=*/false); return createStringError(errc::not_supported, "dumping " + SecName + " section is not supported"); } diff --git a/llvm/tools/obj2yaml/obj2yaml.h b/llvm/tools/obj2yaml/obj2yaml.h --- a/llvm/tools/obj2yaml/obj2yaml.h +++ b/llvm/tools/obj2yaml/obj2yaml.h @@ -51,7 +51,7 @@ void dumpDebugInfo(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); void dumpDebugLines(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); llvm::Error dumpDebugRanges(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); -llvm::Error dumpDebugStrings(llvm::DWARFContext &DCtx, - llvm::DWARFYAML::Data &Y); +llvm::Error dumpDebugStrings(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y, + bool IsDWO); #endif