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 @@ -32,6 +32,7 @@ void EmitDebugStr(raw_ostream &OS, const Data &DI); void EmitDebugAranges(raw_ostream &OS, const Data &DI); +void EmitDebugRanges(raw_ostream &OS, const Data &DI); void EmitPubSection(raw_ostream &OS, const PubSection &Sect, bool IsLittleEndian); void EmitDebugInfo(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 @@ -71,6 +71,17 @@ std::vector Descriptors; }; +struct RangeDescriptor { + llvm::yaml::Hex64 LowOffset; ///< Offset from the CU base address. + llvm::yaml::Hex64 HighOffset; ///< Offset from the CU base address. +}; + +struct Ranges { + llvm::yaml::Hex32 Offset; + llvm::yaml::Hex8 AddrSize; + std::vector Descriptors; +}; + struct PubEntry { llvm::yaml::Hex32 DieOffset; llvm::yaml::Hex8 Descriptor; @@ -145,6 +156,7 @@ std::vector AbbrevDecls; std::vector DebugStrings; std::vector ARanges; + std::vector Ranges; PubSection PubNames; PubSection PubTypes; @@ -165,6 +177,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Abbrev) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::ARangeDescriptor) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::ARange) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::RangeDescriptor) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Ranges) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::PubEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Unit) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::FormValue) @@ -196,6 +210,14 @@ static void mapping(IO &IO, DWARFYAML::ARange &Range); }; +template <> struct MappingTraits { + static void mapping(IO &IO, DWARFYAML::RangeDescriptor &Descriptor); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, DWARFYAML::Ranges &Ranges); +}; + template <> struct MappingTraits { static void mapping(IO &IO, DWARFYAML::PubEntry &Entry); }; 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 @@ -114,6 +114,22 @@ } } +void DWARFYAML::EmitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) { + const size_t RangesOffset = OS.tell(); + for (auto Ranges : DI.Ranges) { + const size_t CurrOffset = OS.tell() - RangesOffset; + if (Ranges.Offset > CurrOffset) + ZeroFillBytes(OS, Ranges.Offset - CurrOffset); + for (auto Descriptor : Ranges.Descriptors) { + writeVariableSizedInteger(Descriptor.LowOffset, Ranges.AddrSize, OS, + DI.IsLittleEndian); + writeVariableSizedInteger(Descriptor.HighOffset, Ranges.AddrSize, OS, + DI.IsLittleEndian); + } + ZeroFillBytes(OS, Ranges.AddrSize * 2); + } +} + void DWARFYAML::EmitPubSection(raw_ostream &OS, const DWARFYAML::PubSection &Sect, bool IsLittleEndian) { @@ -377,5 +393,7 @@ DebugSections); EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugAranges, "debug_aranges", DebugSections); + EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugRanges, "debug_ranges", + DebugSections); return std::move(DebugSections); } 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 @@ -28,6 +28,8 @@ IO.mapOptional("debug_abbrev", DWARF.AbbrevDecls); if (!DWARF.ARanges.empty() || !IO.outputting()) IO.mapOptional("debug_aranges", DWARF.ARanges); + if (!DWARF.Ranges.empty() || !IO.outputting()) + IO.mapOptional("debug_ranges", DWARF.Ranges); if (!DWARF.PubNames.Entries.empty() || !IO.outputting()) IO.mapOptional("debug_pubnames", DWARF.PubNames); if (!DWARF.PubTypes.Entries.empty() || !IO.outputting()) @@ -73,6 +75,19 @@ IO.mapRequired("Descriptors", Range.Descriptors); } +void MappingTraits::mapping( + IO &IO, DWARFYAML::RangeDescriptor &Descriptor) { + IO.mapRequired("LowOffset", Descriptor.LowOffset); + IO.mapRequired("HighOffset", Descriptor.HighOffset); +} + +void MappingTraits::mapping(IO &IO, + DWARFYAML::Ranges &Ranges) { + IO.mapRequired("Offset", Ranges.Offset); + IO.mapRequired("AddrSize", Ranges.AddrSize); + IO.mapRequired("Descriptors", Ranges.Descriptors); +} + void MappingTraits::mapping(IO &IO, DWARFYAML::PubEntry &Entry) { IO.mapRequired("DieOffset", Entry.DieOffset); diff --git a/llvm/lib/ObjectYAML/MachOEmitter.cpp b/llvm/lib/ObjectYAML/MachOEmitter.cpp --- a/llvm/lib/ObjectYAML/MachOEmitter.cpp +++ b/llvm/lib/ObjectYAML/MachOEmitter.cpp @@ -287,6 +287,8 @@ DWARFYAML::EmitDebugAbbrev(OS, Obj.DWARF); } else if (0 == strncmp(&Sec.sectname[0], "__debug_aranges", 16)) { DWARFYAML::EmitDebugAranges(OS, Obj.DWARF); + } else if (0 == strncmp(&Sec.sectname[0], "__debug_ranges", 16)) { + DWARFYAML::EmitDebugRanges(OS, Obj.DWARF); } else if (0 == strncmp(&Sec.sectname[0], "__debug_pubnames", 16)) { DWARFYAML::EmitPubSection(OS, Obj.DWARF.PubNames, Obj.IsLittleEndian); diff --git a/llvm/test/tools/obj2yaml/macho-DWARF-debug-ranges.yaml b/llvm/test/tools/obj2yaml/macho-DWARF-debug-ranges.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/obj2yaml/macho-DWARF-debug-ranges.yaml @@ -0,0 +1,295 @@ +# Test that yaml2obj and obj2yaml can create mach-o files with valid +# __debug_ranges section. +# +# The DWARF should end up looking like: +# +# 0x0000000b: DW_TAG_compile_unit +# DW_AT_name ("/tmp/main.c") +# DW_AT_language (DW_LANG_C_plus_plus) +# DW_AT_low_pc (0x0000000000000000) +# DW_AT_ranges (0x00000000 +# [0x0000000000000000, 0x0000000000000020) +# [0x0000000000000000, 0x0000000000000030) +# [0x0000000000001000, 0x0000000000002000)) +# DW_AT_stmt_list (0x00000000) +# +# 0x00000022: DW_TAG_subprogram +# DW_AT_name ("stripped1") +# DW_AT_low_pc (0x0000000000000000) +# DW_AT_high_pc (0x0000000000000020) +# +# 0x00000033: DW_TAG_subprogram +# DW_AT_name ("stripped2") +# DW_AT_low_pc (0x0000000000000000) +# DW_AT_high_pc (0x0000000000000030) +# +# 0x00000048: DW_TAG_subprogram +# DW_AT_name ("main") +# DW_AT_low_pc (0x0000000000001000) +# DW_AT_high_pc (0x0000000000002000) +# +# 0x00000059: NULL + +# RUN: yaml2obj %s | obj2yaml | FileCheck %s + +# CHECK: - sectname: __debug_ranges +# CHECK-NEXT: segname: __DWARF +# CHECK-NEXT: addr: 0x00000000000000C6 +# CHECK-NEXT: size: 64 +# CHECK-NEXT: offset: 0x00000326 +# CHECK-NEXT: align: 0 +# CHECK-NEXT: reloff: 0x00000000 + +# CHECK: debug_ranges: +# CHECK-NEXT: - Offset: 0x00000000 +# CHECK-NEXT: AddrSize: 0x08 +# CHECK-NEXT: Descriptors: +# CHECK-NEXT: - LowOffset: 0x0000000000000000 +# CHECK-NEXT: HighOffset: 0x0000000000000020 +# CHECK-NEXT: - LowOffset: 0x0000000000000000 +# CHECK-NEXT: HighOffset: 0x0000000000000030 +# CHECK-NEXT: - LowOffset: 0x0000000000001000 +# CHECK-NEXT: HighOffset: 0x0000000000002000 + + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x00000001 + ncmds: 4 + sizeofcmds: 544 + flags: 0x00002000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 472 + segname: '' + vmaddr: 0 + vmsize: 300 + fileoff: 608 + filesize: 300 + maxprot: 7 + initprot: 7 + nsects: 5 + flags: 0 + Sections: + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x0000000000000000 + size: 38 + offset: 0x00000260 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 011101030E13051101551710170000022E00030E110112060000032E00030E11011201000000 + - sectname: __debug_info + segname: __DWARF + addr: 0x0000000000000026 + size: 90 + offset: 0x00000286 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 56000000040000000000080101000000040000000000000000000000000000000000020D000000000000000000000020000000031700000000000000000000003000000000000000022100000000100000000000000010000000 + - sectname: __debug_line + segname: __DWARF + addr: 0x0000000000000080 + size: 70 + offset: 0x000002E0 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 420000000200220000000101FB0E0D0001010101000000010000012F746D7000006D61696E2E6300010000000009020010000000000000030A0102800403010102801C000101 + - sectname: __debug_ranges + segname: __DWARF + addr: 0x00000000000000C6 + size: 64 + offset: 0x00000326 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: '00000000000000002000000000000000000000000000000030000000000000000010000000000000002000000000000000000000000000000000000000000000' + - sectname: __debug_str + segname: __DWARF + addr: 0x0000000000000106 + size: 38 + offset: 0x00000366 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 002F746D702F6D61696E2E630073747269707065643100737472697070656432006D61696E00 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 0 + nsyms: 0 + stroff: 912 + strsize: 8 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 658944 + sdk: 658944 + ntools: 1 + Tools: + - tool: 3 + version: 34734080 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 912 + datasize: 0 +LinkEditData: + StringTable: + - ' ' + - '' + - '' + - '' + - '' + - '' + - '' +DWARF: + debug_str: + - '' + - '/tmp/main.c' + - stripped1 + - stripped2 + - main + debug_abbrev: + - Code: 0x00000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_ranges + Form: DW_FORM_sec_offset + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Code: 0x00000002 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Code: 0x00000003 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_addr + debug_ranges: + - Offset: 0x00000000 + AddrSize: 0x08 + Descriptors: + - LowOffset: 0x0000000000000000 + HighOffset: 0x0000000000000020 + - LowOffset: 0x0000000000000000 + HighOffset: 0x0000000000000030 + - LowOffset: 0x0000000000001000 + HighOffset: 0x0000000000002000 + debug_info: + - Length: + TotalLength: 86 + Version: 4 + AbbrOffset: 0 + AddrSize: 8 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x0000000000000001 + - Value: 0x0000000000000004 + - Value: 0x0000000000000000 + - Value: 0x0000000000000000 + - Value: 0x0000000000000000 + - AbbrCode: 0x00000002 + Values: + - Value: 0x000000000000000D + - Value: 0x0000000000000000 + - Value: 0x0000000000000020 + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000017 + - Value: 0x0000000000000000 + - Value: 0x0000000000000030 + - AbbrCode: 0x00000002 + Values: + - Value: 0x0000000000000021 + - Value: 0x0000000000001000 + - Value: 0x0000000000001000 + - AbbrCode: 0x00000000 + Values: [] + debug_line: + - Length: + TotalLength: 66 + Version: 2 + PrologueLength: 34 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - '/tmp' + Files: + - Name: main.c + DirIdx: 1 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4096 + - Opcode: DW_LNS_advance_line + SData: 10 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 512 + - Opcode: DW_LNS_advance_line + SData: 1 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 3584 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 +... 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 @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/ObjectYAML/DWARFYAML.h" #include @@ -82,6 +83,35 @@ return ErrorSuccess(); } +Error dumpDebugRanges(DWARFContext &DCtx, DWARFYAML::Data &Y) { + + // We are assuming all address byte sizes will be consistent across all + // compile units. + uint32_t AddrSize = 0; + for (const auto &CU : DCtx.compile_units()) { + AddrSize = CU->getAddressByteSize(); + break; + } + + DWARFDataExtractor Data(DCtx.getDWARFObj().getRangesSection().Data, + DCtx.isLittleEndian(), AddrSize); + uint64_t Offset = 0; + DWARFDebugRangeList DwarfRanges; + + while (Data.isValidOffset(Offset)) { + DWARFYAML::Ranges YamlRanges; + YamlRanges.Offset = Offset; + YamlRanges.AddrSize = AddrSize; + if (Error E = DwarfRanges.extract(Data, &Offset)) + return E; + for (const auto &RLE: DwarfRanges.getEntries()) + YamlRanges.Descriptors.push_back({RLE.StartAddress, RLE.EndAddress}); + Y.Ranges.push_back(std::move(YamlRanges)); + } + return ErrorSuccess(); +} + + void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y, DWARFSection Section) { DWARFDataExtractor PubSectionData(DCtx.getDWARFObj(), Section, @@ -354,6 +384,8 @@ dumpDebugStrings(DCtx, Y); if (Error E = dumpDebugARanges(DCtx, Y)) return E; + if (Error E = dumpDebugRanges(DCtx, Y)) + return E; dumpDebugPubSections(DCtx, Y); dumpDebugInfo(DCtx, Y); dumpDebugLines(DCtx, Y);