From b954cb408f090251d946f1e087e29541dd1e7ee5 Mon Sep 17 00:00:00 2001 From: Xing GUO Date: Fri, 3 Jul 2020 18:13:49 +0800 Subject: [PATCH] [ObjectYAML][ELF] Add support for emitting the .debug_gnu_pubnames/pubtypes sections. This patch helps add support for emitting the .debug_gnu_pubnames and .debug_gnu_pubtypes sections. The .debug_gnu_pub* sections is verified by llvm-dwarfdump. Known issues: - Doesn't support emitting multiple pub-tables. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D82367 --- llvm/lib/ObjectYAML/DWARFYAML.cpp | 4 + llvm/lib/ObjectYAML/ELFEmitter.cpp | 6 + .../ELF/DWARF/debug-gnu-pubnames.yaml | 261 ++++++++++++++++++ .../ELF/DWARF/debug-gnu-pubtypes.yaml | 261 ++++++++++++++++++ 4 files changed, 532 insertions(+) create mode 100644 llvm/test/tools/yaml2obj/ELF/DWARF/debug-gnu-pubnames.yaml create mode 100644 llvm/test/tools/yaml2obj/ELF/DWARF/debug-gnu-pubtypes.yaml diff --git a/llvm/lib/ObjectYAML/DWARFYAML.cpp b/llvm/lib/ObjectYAML/DWARFYAML.cpp index 892f9b6e8de0..bedf31dc8179 100644 --- a/llvm/lib/ObjectYAML/DWARFYAML.cpp +++ b/llvm/lib/ObjectYAML/DWARFYAML.cpp @@ -42,6 +42,10 @@ SetVector DWARFYAML::Data::getUsedSectionNames() const { SecNames.insert("debug_pubnames"); if (PubTypes) SecNames.insert("debug_pubtypes"); + if (GNUPubNames) + SecNames.insert("debug_gnu_pubnames"); + if (GNUPubTypes) + SecNames.insert("debug_gnu_pubtypes"); return SecNames; } diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index c985bd24a4de..218e7df8e39a 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -947,6 +947,12 @@ Expected emitDWARF(typename ELFT::Shdr &SHeader, StringRef Name, Err = DWARFYAML::emitPubSection(*OS, *DWARF.PubNames, DWARF.IsLittleEndian); else if (Name == ".debug_pubtypes") Err = DWARFYAML::emitPubSection(*OS, *DWARF.PubTypes, DWARF.IsLittleEndian); + else if (Name == ".debug_gnu_pubnames") + Err = DWARFYAML::emitPubSection(*OS, *DWARF.GNUPubNames, + DWARF.IsLittleEndian, /*IsGNUStyle=*/true); + else if (Name == ".debug_gnu_pubtypes") + Err = DWARFYAML::emitPubSection(*OS, *DWARF.GNUPubTypes, + DWARF.IsLittleEndian, /*IsGNUStyle=*/true); else llvm_unreachable("unexpected emitDWARF() call"); diff --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-gnu-pubnames.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-gnu-pubnames.yaml new file mode 100644 index 000000000000..4de8cd08fe82 --- /dev/null +++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-gnu-pubnames.yaml @@ -0,0 +1,261 @@ +## Test that yaml2obj emits .debug_gnu_pubnames section. + +## a) Generate the '.debug_gnu_pubnames' section from the 'DWARF' entry. + +## Generate and verify a 32-bit little endian .debug_gnu_pubnames section. + +# RUN: yaml2obj --docnum=1 -DENDIAN=ELFDATA2LSB %s -o %t1.le.o +# RUN: llvm-readobj --sections --section-data %t1.le.o | \ +# RUN: FileCheck -DSIZE=32 -DADDRALIGN=1 %s --check-prefixes=SHDR,DWARF32-LE + +# SHDR: Index: 1 +# SHDR-NEXT: Name: .debug_gnu_pubnames (1) +# SHDR-NEXT: Type: SHT_PROGBITS (0x1) +# SHDR-NEXT: Flags [ (0x0) +# SHDR-NEXT: ] +# SHDR-NEXT: Address: 0x0 +# SHDR-NEXT: Offset: 0x40 +# SHDR-NEXT: Size: [[SIZE]] +# SHDR-NEXT: Link: 0 +# SHDR-NEXT: Info: 0 +# SHDR-NEXT: AddressAlignment: [[ADDRALIGN]] +# SHDR-NEXT: EntrySize: 0 +# DWARF32-LE-NEXT: SectionData ( +# DWARF32-LE-NEXT: 0000: 34120000 02003412 00002143 00007856 |4.....4...!C..xV| +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^-------- debug_info_offset (4-byte) +## ^-------- debug_info_length (4-byte) +## ^--- offset (4-byte) +# DWARF32-LE-NEXT: 0010: 34123061 62630021 43658730 64656600 |4.0abc.!Ce.0def.| +## ---- +## ^- descriptor (1-byte) +## ^-------- name "abc\0" +## ^-------- offset (4-byte) +## ^- descriptor (1-byte) +## ^------- name "def\0" +# DWARF32-LE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: [[ENDIAN]] + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_gnu_pubnames: + Length: + TotalLength: 0x1234 + Version: 2 + UnitOffset: 0x1234 + UnitSize: 0x4321 + Entries: + - DieOffset: 0x12345678 + Descriptor: 0x30 + Name: abc + - DieOffset: 0x87654321 + Descriptor: 0x30 + Name: def + +## Generate and verify a 32-bit big endian .debug_gnu_pubnames section. + +# RUN: yaml2obj --docnum=1 -DENDIAN=ELFDATA2MSB %s -o %t1.be.o +# RUN: llvm-readobj --sections --section-data %t1.be.o | \ +# RUN: FileCheck -DSIZE=32 -DADDRALIGN=1 %s --check-prefixes=SHDR,DWARF32-BE + +# DWARF32-BE-NEXT: SectionData ( +# DWARF32-BE-NEXT: 0000: 00001234 00020000 12340000 43211234 |...4.....4..C!.4| +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^-------- debug_info_offset (4-byte) +## ^-------- debug_info_length (4-byte) +## ^--- offset (4-byte) +# DWARF32-BE-NEXT: 0010: 56783061 62630087 65432130 64656600 |Vx0abc..eC!0def.| +## ---- +## ^- descriptor (1-byte) +## ^-------- name "abc\0" +## ^-------- offset (4-byte) +## ^- descriptor (1-byte) +## ^------- name "def\0" +# DWARF32-BE-NEXT: ) + +## b) Generate the .debug_gnu_pubnames section from raw section content. + +# RUN: yaml2obj --docnum=2 %s -o %t2.o +# RUN: llvm-readobj --sections --section-data %t2.o | \ +# RUN: FileCheck %s -DADDRALIGN=0 -DSIZE=3 --check-prefixes=SHDR,ARBITRARY-CONTENT + +# ARBITRARY-CONTENT: SectionData ( +# ARBITRARY-CONTENT-NEXT: 0000: 112233 +# ARBITRARY-CONTENT-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubnames + Type: SHT_PROGBITS + Content: "112233" + +## c) Generate the .debug_gnu_pubnames section when the "Size" is specified. + +# RUN: yaml2obj --docnum=3 %s -o %t3.o +# RUN: llvm-readobj --sections --section-data %t3.o | \ +# RUN: FileCheck -DSIZE=16 -DADDRALIGN=0 %s --check-prefixes=SHDR,SIZE + +# SIZE: SectionData ( +# SIZE-NEXT: 0000: 00000000 00000000 00000000 00000000 |................| +# SIZE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubnames + Type: SHT_PROGBITS + Size: 0x10 + +## d) Test that yaml2obj emits an error message when both the "Size" and the +## "debug_gnu_pubnames" entry are specified at the same time. + +# RUN: not yaml2obj --docnum=4 %s 2>&1 | FileCheck %s --check-prefix=ERROR + +# ERROR: yaml2obj: error: cannot specify section '.debug_gnu_pubnames' contents in the 'DWARF' entry and the 'Content' or 'Size' in the 'Sections' entry at the same time + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubnames + Type: SHT_PROGBITS + Size: 0x10 +DWARF: + debug_gnu_pubnames: + Length: + TotalLength: 0x1234 + Version: 2 + UnitOffset: 0x1234 + UnitSize: 0x4321 + Entries: [] + +## e) Test that yaml2obj emits an error message when both the "Content" and the +## "debug_gnu_pubnames" entry are specified at the same time. + +# RUN: not yaml2obj --docnum=5 %s 2>&1 | FileCheck %s --check-prefix=ERROR + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubnames + Type: SHT_PROGBITS + Content: "00" +DWARF: + debug_gnu_pubnames: + Length: + TotalLength: 0x1234 + Version: 2 + UnitOffset: 0x1234 + UnitSize: 0x4321 + Entries: [] + +## f) Test that all the properties can be overridden by the section header when +## the "debug_gnu_pubnames" entry doesn't exist. + +# RUN: yaml2obj --docnum=6 %s -o %t6.o +# RUN: llvm-readelf --sections %t6.o | FileCheck %s --check-prefix=OVERRIDDEN + +# OVERRIDDEN: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# OVERRIDDEN: [ 1] .debug_gnu_pubnames STRTAB 0000000000002020 000050 00000e 01 A 2 1 2 +# OVERRIDDEN-NEXT: [ 2] .sec STRTAB 0000000000000000 00005e 000000 00 0 0 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubnames + Type: SHT_STRTAB ## SHT_PROGBITS by default. + Flags: [SHF_ALLOC] ## 0 by default. + Link: .sec ## 0 by default. + EntSize: 1 ## 0 by default. + Info: 1 ## 0 by default. + AddressAlign: 2 ## 0 by default. + Address: 0x2020 ## 0x00 by default. + Offset: 0x50 ## 0x40 for the first section. + Size: 0x0e ## Set the "Size" so that we can reuse the check tag "OVERRIDDEN". + - Name: .sec ## Linked by .debug_gnu_pubnames. + Type: SHT_STRTAB + +## g) Test that all the properties can be overridden by the section header when +## the "debug_gnu_pubnames" entry exists. + +# RUN: yaml2obj --docnum=7 %s -o %t7.o +# RUN: llvm-readelf --sections %t7.o | FileCheck %s --check-prefix=OVERRIDDEN + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubnames + Type: SHT_STRTAB ## SHT_PROGBITS by default. + Flags: [SHF_ALLOC] ## 0 by default. + Link: .sec ## 0 by default. + EntSize: 1 ## 0 by default. + Info: 1 ## 0 by default. + AddressAlign: 2 ## 1 by default. + Address: 0x2020 ## 0x00 by default. + Offset: 0x50 ## 0x40 for the first section. + - Name: .sec ## Linked by .debug_gnu_pubnames. + Type: SHT_STRTAB +DWARF: + debug_gnu_pubnames: + Length: + TotalLength: 0x1234 + Version: 2 + UnitOffset: 0x1234 + UnitSize: 0x4321 + Entries: [] + +## h) Test that yaml2obj emits an error if 'Descriptor' is missing. + +# RUN: not yaml2obj --docnum=8 %s -o %t8.o 2>&1 | FileCheck %s --check-prefix=MISSING-KEY + +# MISSING-KEY: YAML:260:9: error: missing required key 'Descriptor' +# MISSING-KEY-NEXT: - DieOffset: 0x12345678 +# MISSING-KEY-NEXT: ^ +# MISSING-KEY-NEXT: yaml2obj: error: failed to parse YAML input: Invalid argument + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_gnu_pubnames: + Length: + TotalLength: 0x1234 + Version: 2 + UnitOffset: 0x1234 + UnitSize: 0x4321 + Entries: + - DieOffset: 0x12345678 + Name: abc diff --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-gnu-pubtypes.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-gnu-pubtypes.yaml new file mode 100644 index 000000000000..e77417a9834c --- /dev/null +++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-gnu-pubtypes.yaml @@ -0,0 +1,261 @@ +## Test that yaml2obj emits .debug_gnu_pubtypes section. + +## a) Generate the '.debug_gnu_pubtypes' section from the 'DWARF' entry. + +## Generate and verify a 32-bit little endian .debug_gnu_pubtypes section. + +# RUN: yaml2obj --docnum=1 -DENDIAN=ELFDATA2LSB %s -o %t1.le.o +# RUN: llvm-readobj --sections --section-data %t1.le.o | \ +# RUN: FileCheck -DSIZE=32 -DADDRALIGN=1 %s --check-prefixes=SHDR,DWARF32-LE + +# SHDR: Index: 1 +# SHDR-NEXT: Name: .debug_gnu_pubtypes (1) +# SHDR-NEXT: Type: SHT_PROGBITS (0x1) +# SHDR-NEXT: Flags [ (0x0) +# SHDR-NEXT: ] +# SHDR-NEXT: Address: 0x0 +# SHDR-NEXT: Offset: 0x40 +# SHDR-NEXT: Size: [[SIZE]] +# SHDR-NEXT: Link: 0 +# SHDR-NEXT: Info: 0 +# SHDR-NEXT: AddressAlignment: [[ADDRALIGN]] +# SHDR-NEXT: EntrySize: 0 +# DWARF32-LE-NEXT: SectionData ( +# DWARF32-LE-NEXT: 0000: 34120000 02003412 00002143 00007856 |4.....4...!C..xV| +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^-------- debug_info_offset (4-byte) +## ^-------- debug_info_length (4-byte) +## ^--- offset (4-byte) +# DWARF32-LE-NEXT: 0010: 34121261 62630021 43658734 64656600 |4..abc.!Ce.4def.| +## ---- +## ^- descriptor (1-byte) +## ^-------- name "abc\0" +## ^-------- offset (4-byte) +## ^- descriptor (1-byte) +## ^------- name "def\0" +# DWARF32-LE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: [[ENDIAN]] + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_gnu_pubtypes: + Length: + TotalLength: 0x1234 + Version: 2 + UnitOffset: 0x1234 + UnitSize: 0x4321 + Entries: + - DieOffset: 0x12345678 + Descriptor: 0x12 + Name: abc + - DieOffset: 0x87654321 + Descriptor: 0x34 + Name: def + +## Generate and verify a 32-bit big endian .debug_gnu_pubtypes section. + +# RUN: yaml2obj --docnum=1 -DENDIAN=ELFDATA2MSB %s -o %t1.be.o +# RUN: llvm-readobj --sections --section-data %t1.be.o | \ +# RUN: FileCheck -DSIZE=32 -DADDRALIGN=1 %s --check-prefixes=SHDR,DWARF32-BE + +# DWARF32-BE-NEXT: SectionData ( +# DWARF32-BE-NEXT: 0000: 00001234 00020000 12340000 43211234 |...4.....4..C!.4| +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^-------- debug_info_offset (4-byte) +## ^-------- debug_info_length (4-byte) +## ^--- offset (4-byte) +# DWARF32-BE-NEXT: 0010: 56781261 62630087 65432134 64656600 |Vx.abc..eC!4def.| +## ---- +## ^- descriptor (1-byte) +## ^-------- name "abc\0" +## ^-------- offset (4-byte) +## ^- descriptor (1-byte) +## ^------- name "def\0" +# DWARF32-BE-NEXT: ) + +## b) Generate the .debug_gnu_pubtypes section from raw section content. + +# RUN: yaml2obj --docnum=2 %s -o %t2.o +# RUN: llvm-readobj --sections --section-data %t2.o | \ +# RUN: FileCheck %s -DADDRALIGN=0 -DSIZE=3 --check-prefixes=SHDR,ARBITRARY-CONTENT + +# ARBITRARY-CONTENT: SectionData ( +# ARBITRARY-CONTENT-NEXT: 0000: 112233 +# ARBITRARY-CONTENT-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubtypes + Type: SHT_PROGBITS + Content: "112233" + +## c) Generate the .debug_gnu_pubtypes section when the "Size" is specified. + +# RUN: yaml2obj --docnum=3 %s -o %t3.o +# RUN: llvm-readobj --sections --section-data %t3.o | \ +# RUN: FileCheck -DSIZE=16 -DADDRALIGN=0 %s --check-prefixes=SHDR,SIZE + +# SIZE: SectionData ( +# SIZE-NEXT: 0000: 00000000 00000000 00000000 00000000 |................| +# SIZE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubtypes + Type: SHT_PROGBITS + Size: 0x10 + +## d) Test that yaml2obj emits an error message when both the "Size" and the +## "debug_gnu_pubtypes" entry are specified at the same time. + +# RUN: not yaml2obj --docnum=4 %s 2>&1 | FileCheck %s --check-prefix=ERROR + +# ERROR: yaml2obj: error: cannot specify section '.debug_gnu_pubtypes' contents in the 'DWARF' entry and the 'Content' or 'Size' in the 'Sections' entry at the same time + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubtypes + Type: SHT_PROGBITS + Size: 0x10 +DWARF: + debug_gnu_pubtypes: + Length: + TotalLength: 0x1234 + Version: 2 + UnitOffset: 0x1234 + UnitSize: 0x4321 + Entries: [] + +## e) Test that yaml2obj emits an error message when both the "Content" and the +## "debug_gnu_pubtypes" entry are specified at the same time. + +# RUN: not yaml2obj --docnum=5 %s 2>&1 | FileCheck %s --check-prefix=ERROR + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubtypes + Type: SHT_PROGBITS + Content: "00" +DWARF: + debug_gnu_pubtypes: + Length: + TotalLength: 0x1234 + Version: 2 + UnitOffset: 0x1234 + UnitSize: 0x4321 + Entries: [] + +## f) Test that all the properties can be overridden by the section header when +## the "debug_gnu_pubtypes" entry doesn't exist. + +# RUN: yaml2obj --docnum=6 %s -o %t6.o +# RUN: llvm-readelf --sections %t6.o | FileCheck %s --check-prefix=OVERRIDDEN + +# OVERRIDDEN: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# OVERRIDDEN: [ 1] .debug_gnu_pubtypes STRTAB 0000000000002020 000050 00000e 01 A 2 1 2 +# OVERRIDDEN-NEXT: [ 2] .sec STRTAB 0000000000000000 00005e 000000 00 0 0 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubtypes + Type: SHT_STRTAB ## SHT_PROGBITS by default. + Flags: [SHF_ALLOC] ## 0 by default. + Link: .sec ## 0 by default. + EntSize: 1 ## 0 by default. + Info: 1 ## 0 by default. + AddressAlign: 2 ## 0 by default. + Address: 0x2020 ## 0x00 by default. + Offset: 0x50 ## 0x40 for the first section. + Size: 0x0e ## Set the "Size" so that we can reuse the check tag "OVERRIDDEN". + - Name: .sec ## Linked by .debug_gnu_pubtypes. + Type: SHT_STRTAB + +## g) Test that all the properties can be overridden by the section header when +## the "debug_gnu_pubtypes" entry exists. + +# RUN: yaml2obj --docnum=7 %s -o %t7.o +# RUN: llvm-readelf --sections %t7.o | FileCheck %s --check-prefix=OVERRIDDEN + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_gnu_pubtypes + Type: SHT_STRTAB ## SHT_PROGBITS by default. + Flags: [SHF_ALLOC] ## 0 by default. + Link: .sec ## 0 by default. + EntSize: 1 ## 0 by default. + Info: 1 ## 0 by default. + AddressAlign: 2 ## 1 by default. + Address: 0x2020 ## 0x00 by default. + Offset: 0x50 ## 0x40 for the first section. + - Name: .sec ## Linked by .debug_gnu_pubtypes. + Type: SHT_STRTAB +DWARF: + debug_gnu_pubtypes: + Length: + TotalLength: 0x1234 + Version: 2 + UnitOffset: 0x1234 + UnitSize: 0x4321 + Entries: [] + +## h) Test that yaml2obj emits an error if 'Descriptor' is missing. + +# RUN: not yaml2obj --docnum=8 %s -o %t8.o 2>&1 | FileCheck %s --check-prefix=MISSING-KEY + +# MISSING-KEY: YAML:260:9: error: missing required key 'Descriptor' +# MISSING-KEY-NEXT: - DieOffset: 0x12345678 +# MISSING-KEY-NEXT: ^ +# MISSING-KEY-NEXT: yaml2obj: error: failed to parse YAML input: Invalid argument + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_gnu_pubtypes: + Length: + TotalLength: 0x1234 + Version: 2 + UnitOffset: 0x1234 + UnitSize: 0x4321 + Entries: + - DieOffset: 0x12345678 + Name: abc