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 @@ -38,6 +38,7 @@ Error emitDebugInfo(raw_ostream &OS, const Data &DI); Error emitDebugLine(raw_ostream &OS, const Data &DI); Error emitDebugAddr(raw_ostream &OS, const Data &DI); +Error emitDebugRnglists(raw_ostream &OS, const Data &DI); Expected>> emitDebugSections(StringRef YAMLString, bool ApplyFixups = false, 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 @@ -177,6 +177,26 @@ std::vector SegAddrPairs; }; +struct RnglistEntry { + dwarf::RnglistEntries Operator; + std::vector Values; +}; + +struct Rnglist { + std::vector Entries; +}; + +struct RnglistsEntry { + dwarf::DwarfFormat Format; + Optional Length; + yaml::Hex16 Version; + Optional AddrSize; + yaml::Hex8 SegSelectorSize; + Optional OffsetEntryCount; + Optional> Offsets; + std::vector Lists; +}; + struct Data { bool IsLittleEndian; bool Is64bit; @@ -194,6 +214,7 @@ std::vector CompileUnits; std::vector DebugLines; + std::vector DebugRnglists; bool isEmpty() const; @@ -218,6 +239,9 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LineTableOpcode) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::SegAddrPair) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AddrTableEntry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::RnglistsEntry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Rnglist) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::RnglistEntry) namespace llvm { namespace yaml { @@ -286,6 +310,18 @@ static void mapping(IO &IO, DWARFYAML::SegAddrPair &SegAddrPair); }; +template <> struct MappingTraits { + static void mapping(IO &IO, DWARFYAML::RnglistsEntry &RnglistsEntry); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, DWARFYAML::Rnglist &Rnglist); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, DWARFYAML::RnglistEntry &RnglistEntry); +}; + template <> struct MappingTraits { static void mapping(IO &IO, DWARFYAML::AddrTableEntry &AddrTable); }; @@ -369,6 +405,15 @@ } }; +#define HANDLE_DW_RLE(unused, name) \ + io.enumCase(value, "DW_RLE_" #name, dwarf::DW_RLE_##name); + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, dwarf::RnglistEntries &value) { +#include "llvm/BinaryFormat/Dwarf.def" + } +}; + } // end namespace yaml } // end namespace llvm 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 @@ -416,6 +416,160 @@ return Error::success(); } +static Expected +writeRnglistEntry(raw_ostream &OS, const DWARFYAML::RnglistEntry &Entry, + uint8_t AddrSize, bool IsLittleEndian) { + uint64_t BeginOffset = OS.tell(); + writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian); + + auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error { + if (Entry.Values.size() != ExpectedOperands) { + return createStringError( + errc::invalid_argument, + "invalid number of operands for the operator: %s", + dwarf::RangeListEncodingString(Entry.Operator).str().c_str()); + } + + return Error::success(); + }; + + auto WriteAddress = [&](uint64_t Addr) -> Error { + if (Error Err = + writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian)) + return createStringError( + errc::not_supported, + "unable to write address for the operator %s: %s", + dwarf::RangeListEncodingString(Entry.Operator).str().c_str(), + toString(std::move(Err)).c_str()); + return Error::success(); + }; + + switch (Entry.Operator) { + case dwarf::DW_RLE_end_of_list: + if (Error Err = CheckOperands(0)) + return std::move(Err); + break; + case dwarf::DW_RLE_base_addressx: + if (Error Err = CheckOperands(1)) + return std::move(Err); + encodeULEB128(Entry.Values[0], OS); + break; + case dwarf::DW_RLE_startx_endx: + case dwarf::DW_RLE_startx_length: + case dwarf::DW_RLE_offset_pair: + if (Error Err = CheckOperands(2)) + return std::move(Err); + encodeULEB128(Entry.Values[0], OS); + encodeULEB128(Entry.Values[1], OS); + break; + case dwarf::DW_RLE_base_address: + if (Error Err = CheckOperands(1)) + return std::move(Err); + if (Error Err = WriteAddress(Entry.Values[0])) + return std::move(Err); + break; + case dwarf::DW_RLE_start_end: + if (Error Err = CheckOperands(2)) + return std::move(Err); + if (Error Err = WriteAddress(Entry.Values[0])) + return std::move(Err); + cantFail(WriteAddress(Entry.Values[1])); + break; + case dwarf::DW_RLE_start_length: + if (Error Err = CheckOperands(2)) + return std::move(Err); + if (Error Err = WriteAddress(Entry.Values[0])) + return std::move(Err); + encodeULEB128(Entry.Values[1], OS); + break; + default: + llvm_unreachable("unrecognized range list encoding"); + } + + return OS.tell() - BeginOffset; +} + +Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) { + for (const DWARFYAML::RnglistsEntry &RnglistsEntry : DI.DebugRnglists) { + // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) + + // sizeof(offset_entry_count) = 8 + uint64_t Length = 8; + + uint8_t AddrSize; + if (RnglistsEntry.AddrSize) + AddrSize = *RnglistsEntry.AddrSize; + else + AddrSize = DI.Is64bit ? 8 : 4; + + // Since the length of the current range lists entry is undetermined yet, we + // firstly write the content of the range lists to a buffer to calculate the + // length and then serialize the buffer content to the actual output stream. + std::string Buffer; + raw_string_ostream BufferOS(Buffer); + + // Offsets holds offsets for each range list. The i-th element is the offset + // from the beginning of the first range list to the location of the i-th + // range list. + std::vector Offsets; + + for (const DWARFYAML::Rnglist &Rnglist : RnglistsEntry.Lists) { + Offsets.push_back(BufferOS.tell()); + for (const DWARFYAML::RnglistEntry &RnglistEntry : Rnglist.Entries) { + Expected EntrySize = writeRnglistEntry( + BufferOS, RnglistEntry, AddrSize, DI.IsLittleEndian); + if (!EntrySize) + return EntrySize.takeError(); + Length += *EntrySize; + } + // Write DW_RLE_end_of_list to terminate this entry. + BufferOS.write_zeros(1); + Length += 1; + } + + uint32_t OffsetEntryCount; + if (RnglistsEntry.OffsetEntryCount) + OffsetEntryCount = *RnglistsEntry.OffsetEntryCount; + else + OffsetEntryCount = RnglistsEntry.Offsets ? RnglistsEntry.Offsets->size() + : Offsets.size(); + uint64_t OffsetsSize = + OffsetEntryCount * (RnglistsEntry.Format == dwarf::DWARF64 ? 8 : 4); + Length += OffsetsSize; + + // If the length is specified in the YAML description, we use it as the + // actual length. + if (RnglistsEntry.Length) + Length = *RnglistsEntry.Length; + + writeInitialLength(RnglistsEntry.Format, Length, OS, DI.IsLittleEndian); + writeInteger((uint16_t)RnglistsEntry.Version, OS, DI.IsLittleEndian); + writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); + writeInteger((uint8_t)RnglistsEntry.SegSelectorSize, OS, DI.IsLittleEndian); + writeInteger((uint32_t)OffsetEntryCount, OS, DI.IsLittleEndian); + + auto EmitOffsets = [&](const std::vector Offsets, + uint64_t OffsetsSize) { + for (uint64_t Offset : Offsets) { + cantFail(writeVariableSizedInteger( + OffsetsSize + Offset, + RnglistsEntry.Format == dwarf::DWARF64 ? 8 : 4, OS, + DI.IsLittleEndian)); + } + }; + + if (RnglistsEntry.Offsets) + EmitOffsets(std::vector(RnglistsEntry.Offsets->begin(), + RnglistsEntry.Offsets->end()), + 0); + else + EmitOffsets(Offsets, OffsetsSize); + + OS.write(Buffer.data(), Buffer.size()); + } + + return Error::success(); +} + using EmitFuncType = Error (*)(raw_ostream &, const DWARFYAML::Data &); static Error 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 @@ -46,6 +46,8 @@ SecNames.insert("debug_gnu_pubnames"); if (GNUPubTypes) SecNames.insert("debug_gnu_pubtypes"); + if (!DebugRnglists.empty()) + SecNames.insert("debug_rnglists"); return SecNames; } @@ -69,6 +71,7 @@ IO.mapOptional("debug_info", DWARF.CompileUnits); IO.mapOptional("debug_line", DWARF.DebugLines); IO.mapOptional("debug_addr", DWARF.DebugAddr); + IO.mapOptional("debug_rnglists", DWARF.DebugRnglists); IO.setContext(OldContext); } @@ -221,6 +224,29 @@ IO.mapOptional("Entries", AddrTable.SegAddrPairs); } +void MappingTraits::mapping( + IO &IO, DWARFYAML::RnglistEntry &RnglistEntry) { + IO.mapRequired("Operator", RnglistEntry.Operator); + IO.mapOptional("Values", RnglistEntry.Values); +} + +void MappingTraits::mapping(IO &IO, + DWARFYAML::Rnglist &Rnglist) { + IO.mapOptional("Entries", Rnglist.Entries); +} + +void MappingTraits::mapping( + IO &IO, DWARFYAML::RnglistsEntry &RnglistsEntry) { + IO.mapOptional("Format", RnglistsEntry.Format, dwarf::DWARF32); + IO.mapOptional("Length", RnglistsEntry.Length); + IO.mapRequired("Version", RnglistsEntry.Version); + IO.mapOptional("AddressSize", RnglistsEntry.AddrSize); + IO.mapOptional("SegmentSelectorSize", RnglistsEntry.SegSelectorSize, 0); + IO.mapOptional("OffsetEntryCount", RnglistsEntry.OffsetEntryCount); + IO.mapOptional("Offsets", RnglistsEntry.Offsets); + IO.mapOptional("Lists", RnglistsEntry.Lists); +} + void MappingTraits::mapping( IO &IO, DWARFYAML::InitialLength &InitialLength) { IO.mapRequired("TotalLength", InitialLength.TotalLength); 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 @@ -953,6 +953,8 @@ else if (Name == ".debug_gnu_pubtypes") Err = DWARFYAML::emitPubSection(*OS, *DWARF.GNUPubTypes, DWARF.IsLittleEndian, /*IsGNUStyle=*/true); + else if (Name == ".debug_rnglists") + Err = DWARFYAML::emitDebugRnglists(*OS, DWARF); else llvm_unreachable("unexpected emitDWARF() call"); diff --git a/llvm/test/tools/yaml2obj/ELF/DWARF/debug-rnglists.yaml b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-rnglists.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/yaml2obj/ELF/DWARF/debug-rnglists.yaml @@ -0,0 +1,591 @@ +## Test that yaml2obj emits .debug_rnglists section. + +## a) Generate and verify a little endian DWARF32 .debug_rnglists section in a 64-bit object file. + +# RUN: yaml2obj --docnum=1 -DENDIAN=ELFDATA2LSB %s -o %t1.le.dwarf32.o +# RUN: llvm-readobj --sections --section-data %t1.le.dwarf32.o | \ +# RUN: FileCheck -DSIZE=100 -DADDRALIGN=1 %s --check-prefixes=SHDR,DWARF32-LE + +# SHDR: Index: 1 +# SHDR-NEXT: Name: .debug_rnglists (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: 24000000 05000800 02000000 08000000 |$...............| +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^- address_size (1-byte) +## ^- segment_selector_size (1-byte) +## ^------- offset_entry_count (4-byte) +## ^------- offsets[0] (4-byte) +# DWARF32-LE-NEXT: 0010: 11000000 01B42402 B424B424 0003B424 |......$..$.$...$| +## ^------- offsets[1] (4-byte) +## ^- DW_RLE_base_addressx (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +## ^- DW_RLE_startx_endx (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_end_of_list (1-byte) +## ^- DW_RLE_startx_length (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +# DWARF32-LE-NEXT: 0020: B42404B4 24B42400 38000000 05000800 |.$..$.$.8.......| +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_offset_pair (1-byte) +## ^---- operands[0] (ULEB128) 0x1234 +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_end_of_list (1-byte) +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^- address_size (1-byte) +## ^- segment_selector_size (1-byte) +# DWARF32-LE-NEXT: 0030: 02000000 08000000 23000000 05341200 |........#....4..| +## ^------- offset_entry_count (4-byte) +## ^------- offsets[0] (4-byte) +## ^------- offsets[1] (4-byte) +## ^- DW_RLE_base_address (1-byte) +## ^----- operands[0] (8-byte) +# DWARF32-LE-NEXT: 0040: 00000000 00063412 00000000 00003412 |......4.......4.| +## ----------- +## ^- DW_RLE_start_end (1-byte) +## ^----------------- operands[0] (8-byte) +## ^--- operands[1] (8-byte) +# DWARF32-LE-NEXT: 0050: 00000000 00000007 34120000 00000000 |........4.......| +## ------------- +## ^- DW_RLE_end_of_list (1-byte) +## ^- DW_RLE_start_length (1-byte) +## ^---------------- operands[0] (8-byte) +# DWARF32-LE-NEXT: 0060: B4240000 |.$..| +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_end_of_list (1-byte) +## ^- DW_RLE_end_of_list (1-byte) +# DWARF32-LE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: [[ENDIAN]] + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_rnglists: + - Version: 5 + Lists: + - Entries: + - Operator: DW_RLE_base_addressx + Values: [ 0x1234 ] + - Operator: DW_RLE_startx_endx + Values: [ 0x1234, 0x1234 ] + - Entries: + - Operator: DW_RLE_startx_length + Values: [ 0x1234, 0x1234 ] + - Operator: DW_RLE_offset_pair + Values: [ 0x1234, 0x1234 ] + - Version: 5 + Lists: + - Entries: + - Operator: DW_RLE_base_address + Values: [ 0x1234 ] + - Operator: DW_RLE_start_end + Values: [ 0x1234, 0x1234 ] + - Entries: + - Operator: DW_RLE_start_length + Values: [ 0x1234, 0x1234 ] + - Operator: DW_RLE_end_of_list + +## b) Generate and verify a big endian DWARF32 .debug_rnglists section in a 64-bit object file. + +# RUN: yaml2obj --docnum=1 -DENDIAN=ELFDATA2MSB %s -o %t1.be.dwarf32.o +# RUN: llvm-readobj --sections --section-data %t1.be.dwarf32.o | \ +# RUN: FileCheck -DSIZE=100 -DADDRALIGN=1 %s --check-prefixes=SHDR,DWARF32-BE + +# DWARF32-BE-NEXT: SectionData ( +# DWARF32-BE-NEXT: 0000: 00000024 00050800 00000002 00000008 |...$............| +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^- address_size (1-byte) +## ^- segment_selector_size (1-byte) +## ^------- offset_entry_count (4-byte) +## ^------- offsets[0] (4-byte) +# DWARF32-BE-NEXT: 0010: 00000011 01B42402 B424B424 0003B424 |......$..$.$...$| +## ^------- offsets[1] (4-byte) +## ^- DW_RLE_base_addressx (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +## ^- DW_RLE_startx_endx (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_end_of_list (1-byte) +## ^- DW_RLE_startx_length (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +# DWARF32-BE-NEXT: 0020: B42404B4 24B42400 00000038 00050800 |.$..$.$....8....| +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_offset_pair (1-byte) +## ^---- operands[0] (ULEB128) 0x1234 +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_end_of_list (1-byte) +## ^------- unit_length (4-byte) +## ^--- version (2-byte) +## ^- address_size (1-byte) +## ^- segment_selector_size (1-byte) +# DWARF32-BE-NEXT: 0030: 00000002 00000008 00000023 05000000 |...........#....| +## ^------- offset_entry_count (4-byte) +## ^------- offsets[0] (4-byte) +## ^------- offsets[1] (4-byte) +## ^- DW_RLE_base_address (1-byte) +## ^----- operands[0] (8-byte) +# DWARF32-BE-NEXT: 0040: 00000012 34060000 00000000 12340000 |....4........4..| +## ----------- +## ^- DW_RLE_start_end (1-byte) +## ^----------------- operands[0] (8-byte) +## ^--- operands[1] (8-byte) +# DWARF32-BE-NEXT: 0050: 00000000 12340007 00000000 00001234 |.....4.........4| +## ------------- +## ^- DW_RLE_end_of_list (1-byte) +## ^- DW_RLE_start_length (1-byte) +## ^---------------- operands[0] (8-byte) +# DWARF32-BE-NEXT: 0060: B4240000 |.$..| +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_end_of_list (1-byte) +## ^- DW_RLE_end_of_list (1-byte) +# DWARF32-BE-NEXT: ) + +## c) Generate and verify a little endian DWARF64 .debug_rnglists section in a 64-bit object file. + +# RUN: yaml2obj --docnum=2 -DENDIAN=ELFDATA2LSB %s -o %t2.le.dwarf64.o +# RUN: llvm-readobj --sections --section-data %t2.le.dwarf64.o | \ +# RUN: FileCheck -DSIZE=56 -DADDRALIGN=1 %s --check-prefixes=SHDR,DWARF64-LE + +# DWARF64-LE-NEXT: SectionData ( +# DWARF64-LE-NEXT: 0000: FFFFFFFF 2C000000 00000000 05000800 |....,...........| +## ^------------------------- unit_length (12-byte) +## ^--- version (2-byte) +## ^- address_size (1-byte) +## ^- segment_selector_size (1-byte) +# DWARF64-LE-NEXT: 0010: 02000000 10000000 00000000 19000000 |................| +## ^------- offset_entry_count (4-byte) +## ^---------------- offsets[0] (8-byte) +## ^------- offsets[1] (8-byte) +# DWARF64-LE-NEXT: 0020: 00000000 01B42402 B424B424 0003B424 |......$..$.$...$| +## -------- +## ^- DW_RLE_base_addressx (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +## ^- DW_RLE_startx_endx (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_end_of_list (1-byte) +## ^- DW_RLE_startx_length (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +# DWARF64-LE-NEXT: 0030: B42404B4 24B42400 |.$..$.$.| +## ^--- operands[1] (UELB128) 0x1234 +## ^- DW_RLE_offset_pair (1-byte) +## ^---- operands[0] (ULEB128) 0x1234 +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_end_of_list (1-byte) +# DWARF64-LE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: [[ENDIAN]] + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_rnglists: + - Format: DWARF64 + Version: 5 + Lists: + - Entries: + - Operator: DW_RLE_base_addressx + Values: [ 0x1234 ] + - Operator: DW_RLE_startx_endx + Values: [ 0x1234, 0x1234 ] + - Entries: + - Operator: DW_RLE_startx_length + Values: [ 0x1234, 0x1234 ] + - Operator: DW_RLE_offset_pair + Values: [ 0x1234, 0x1234 ] + +## d) Generate and verify a big endian DWARF64 .debug_rnglists section in a 64-bit object file. + +# RUN: yaml2obj --docnum=2 -DENDIAN=ELFDATA2MSB %s -o %t2.be.dwarf64.o +# RUN: llvm-readobj --sections --section-data %t2.be.dwarf64.o | \ +# RUN: FileCheck -DSIZE=56 -DADDRALIGN=1 %s --check-prefixes=SHDR,DWARF64-BE + +# DWARF64-BE-NEXT: SectionData ( +# DWARF64-BE-NEXT: 0000: FFFFFFFF 00000000 0000002C 00050800 |...........,....| +## ^------------------------- unit_length (12-byte) +## ^--- version (2-byte) +## ^- address_size (1-byte) +## ^- segment_selector_size (1-byte) +# DWARF64-BE-NEXT: 0010: 00000002 00000000 00000010 00000000 |................| +## ^------- offset_entry_count (4-byte) +## ^---------------- offsets[0] (8-byte) +## ^------- offsets[1] (8-byte) +# DWARF64-BE-NEXT: 0020: 00000019 01B42402 B424B424 0003B424 |......$..$.$...$| +## -------- +## ^- DW_RLE_base_addressx (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +## ^- DW_RLE_startx_endx (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_end_of_list (1-byte) +## ^- DW_RLE_startx_length (1-byte) +## ^--- operands[0] (ULEB128) 0x1234 +# DWARF64-BE-NEXT: 0030: B42404B4 24B42400 |.$..$.$.| +## ^--- operands[1] (UELB128) 0x1234 +## ^- DW_RLE_offset_pair (1-byte) +## ^---- operands[0] (ULEB128) 0x1234 +## ^--- operands[1] (ULEB128) 0x1234 +## ^- DW_RLE_end_of_list (1-byte) +# DWARF64-BE-NEXT: ) + +## e) Test that the length field can be specified manually. + +# RUN: yaml2obj --docnum=3 %s -o %t3.o +# RUN: llvm-readelf --hex-dump=.debug_rnglists %t3.o | \ +# RUN: FileCheck %s --check-prefix=LENGTH + +# LENGTH: Hex dump of section '.debug_rnglists': +# LENGTH-NEXT: 0x00000000 34120000 05000800 00000000 4........... +## ^------- unit_length + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_rnglists: + - Length: 0x1234 + Version: 5 + Lists: [] + +## f) Test that the offset_entry_count field can be specified manually. + +# RUN: yaml2obj --docnum=4 %s -o %t4.o +# RUN: llvm-readelf --hex-dump=.debug_rnglists %t4.o | \ +# RUN: FileCheck %s --check-prefix=ENTRY-COUNT + +# ENTRY-COUNT: Hex dump of section '.debug_rnglists': +# ENTRY-COUNT-NEXT: 0x00000000 28000000 05000800 05000000 14000000 (............... +## ^------- offset_entry_count +# ENTRY-COUNT-NEXT: 0x00000010 1a000000 03b424b4 240004b4 24b42400 ......$.$...$.$. + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_rnglists: + - Version: 5 + OffsetEntryCount: 5 + Lists: + - Entries: + - Operator: DW_RLE_startx_length + Values: [ 0x1234, 0x1234 ] + - Entries: + - Operator: DW_RLE_offset_pair + Values: [ 0x1234, 0x1234 ] + +## g) Test that the offsets fields can be specified manually. + +# RUN: yaml2obj --docnum=5 %s -o %t5.o +# RUN: llvm-readelf --hex-dump=.debug_rnglists %t5.o | \ +# RUN: FileCheck %s --check-prefix=OFFSETS + +# OFFSETS: Hex dump of section '.debug_rnglists': +# OFFSETS-NEXT: 0x00000000 1c000000 05000800 02000000 12000000 ................ +## ^------- offset_entry_count +## ^------- offsets[0] 0x12 +# OFFSETS-NEXT: 0x00000010 34000000 03b424b4 240004b4 24b42400 4.....$.$...$.$. +## ^------- offsets[1] 0x34 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_rnglists: + - Version: 5 + Offsets: [ 0x12, 0x34 ] + Lists: + - Entries: + - Operator: DW_RLE_startx_length + Values: [ 0x1234, 0x1234 ] + - Entries: + - Operator: DW_RLE_offset_pair + Values: [ 0x1234, 0x1234 ] + +## h) Test that the offset_entry_count and offsets fields can be specified individually. + +# RUN: yaml2obj --docnum=6 %s -o %t6.o +# RUN: llvm-readelf --hex-dump=.debug_rnglists %t6.o | \ +# RUN: FileCheck %s --check-prefix=ENTRY-COUNT-OFFSETS + +# ENTRY-COUNT-OFFSETS: Hex dump of section '.debug_rnglists': +# ENTRY-COUNT-OFFSETS-NEXT: 0x00000000 28000000 05000800 05000000 12000000 (............... +## ^------- offset_entry_count 0x05 +## ^------- offsets[0] 0x12 +# ENTRY-COUNT-OFFSETS-NEXT: 0x00000010 34000000 56000000 03b424b4 240004b4 4...V.....$.$... +## ^------- offsets[1] 0x34 +## ^------- offsets[2] 0x56 +# ENTRY-COUNT-OFFSETS-NEXT: 0x00000020 24b42400 $.$. + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_rnglists: + - Version: 5 + OffsetEntryCount: 5 + Offsets: [ 0x12, 0x34, 0x56 ] + Lists: + - Entries: + - Operator: DW_RLE_startx_length + Values: [ 0x1234, 0x1234 ] + - Entries: + - Operator: DW_RLE_offset_pair + Values: [ 0x1234, 0x1234 ] + +## i) Test that the address_size field can be specified manually and the size of +## corresponding operands will be changed accordingly. + +# RUN: yaml2obj --docnum=7 %s -o %t7.o +# RUN: llvm-readelf --hex-dump=.debug_rnglists %t7.o | \ +# RUN: FileCheck %s --check-prefix=ADDRSIZE + +# ADDRSIZE: Hex dump of section '.debug_rnglists': +# ADDRSIZE-NEXT: 0x00000000 22000000 05000400 01000000 04000000 "............... +## ^- address_size 0x04 +# ADDRSIZE-NEXT: 0x00000010 05341200 00063412 00002143 00000734 .4....4...!C...4 +## ^- DW_RLE_base_address +## ^-------- operands[0] (4-byte) +## ^- DW_RLE_start_end +## ^-------- operands[0] (4-byte) +## ^-------- operands[1] (4-byte) +## ^- DW_RLE_start_length +## ^- operands[0] (4-byte) +# ADDRSIZE-NEXT: 0x00000020 120000b4 2400 ....$. +## ------ +## ^---- operands[1] (ULEB128) +## ^- DW_RLE_end_of_list + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_rnglists: + - Version: 5 + AddressSize: 4 + Lists: + - Entries: + - Operator: DW_RLE_base_address + Values: [ 0x1234 ] + - Operator: DW_RLE_start_end + Values: [ 0x1234, 0x4321 ] + - Operator: DW_RLE_start_length + Values: [ 0x1234, 0x1234 ] + +## j) Test that yaml2obj emits an error message if we try to assign an invalid value to +## 'AddressSize' when there is an entry whose operands contain address. + +# RUN: not yaml2obj --docnum=8 %s 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-ADDRSIZE + +# INVALID-ADDRSIZE: yaml2obj: error: unable to write address for the operator DW_RLE_base_address: invalid integer write size: 3 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_rnglists: + - Version: 5 + AddressSize: 3 + Lists: + - Entries: + - Operator: DW_RLE_base_address + Values: [ 0x1234 ] + +## k) Test that yaml2obj emits an error message if we specify invalid numbers of operands +## to operator. + +# RUN: not yaml2obj --docnum=9 %s 2>&1 | \ +# RUN: FileCheck %s --check-prefix=INVALID-OPERANDS + +# INVALID-OPERANDS: yaml2obj: error: invalid number of operands for the operator: DW_RLE_base_address + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +DWARF: + debug_rnglists: + - Version: 5 + AddressSize: 3 + Lists: + - Entries: + - Operator: DW_RLE_base_address + Values: [ 0x1234, 0x1234 ] + +## l) Generate the .debug_rnglists section from raw section content. + +# RUN: yaml2obj --docnum=10 %s -o %t10.o +# RUN: llvm-readobj --sections --section-data %t10.o | \ +# RUN: FileCheck %s -DSIZE=3 -DADDRALIGN=0 --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_rnglists + Type: SHT_PROGBITS + Content: "112233" + +## m) Generate the .debug_rnglists section when the "Size" is specified. + +# RUN: yaml2obj --docnum=11 %s -o %t11.o +# RUN: llvm-readelf --hex-dump=.debug_rnglists %t11.o | \ +# RUN: FileCheck %s --check-prefix=SIZE + +# SIZE: Hex dump of section '.debug_rnglists': +# SIZE-NEXT: 0x00000000 00000000 00000000 00000000 00000000 ................ +# SIZE-EMPTY: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_rnglists + Type: SHT_PROGBITS + Size: 0x10 + +## n) Test that yaml2obj emits an error message when both the "Size" and the +## "debug_rnglists" entry are specified at the same time. + +# RUN: not yaml2obj --docnum=12 %s 2>&1 | FileCheck %s --check-prefix=ERROR + +# ERROR: yaml2obj: error: cannot specify section '.debug_rnglists' 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_rnglists + Type: SHT_PROGBITS + Size: 0x10 +DWARF: + debug_rnglists: + - Version: 5 + +## o) Test that yaml2obj emits an error message when both the "Content" and the +## "debug_rnglists" entry are specified at the same time. + +# RUN: not yaml2obj --docnum=13 %s 2>&1 | FileCheck %s --check-prefix=ERROR + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_rnglists + Type: SHT_PROGBITS + Content: "00" +DWARF: + debug_rnglists: + - Version: 5 + +## p) Test that all the properties can be overridden by the section header when +## the "debug_rnglists" entry doesn't exist. + +# RUN: yaml2obj --docnum=14 %s -o %t14.o +# RUN: llvm-readelf --sections %t14.o | FileCheck %s --check-prefix=OVERRIDDEN + +# OVERRIDDEN: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# OVERRIDDEN: [ 1] .debug_rnglists STRTAB 0000000000002020 000050 00000c 01 A 2 1 2 +# OVERRIDDEN-NEXT: [ 2] .sec STRTAB 0000000000000000 00005c 000000 00 0 0 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_rnglists + 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: 0x0c ## Set the "Size" so that we can reuse the check tag "OVERRIDDEN". + - Name: .sec ## Linked by .debug_rnglists. + Type: SHT_STRTAB + +## q) Test that all the properties can be overridden by the section header when +## the "debug_rnglists" entry exists. + +# RUN: yaml2obj --docnum=15 %s -o %t15.o +# RUN: llvm-readelf --sections %t15.o | FileCheck %s --check-prefix=OVERRIDDEN + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .debug_rnglists + 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_rnglists. + Type: SHT_STRTAB +DWARF: + debug_rnglists: + - Version: 5