Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h @@ -11,6 +11,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Error.h" #include #include @@ -57,7 +58,7 @@ DWARFDebugArangeSet() { clear(); } void clear(); - bool extract(DataExtractor data, uint64_t *offset_ptr); + Error extract(DataExtractor data, uint64_t *offset_ptr); void dump(raw_ostream &OS) const; uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } Index: llvm/lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -453,8 +453,13 @@ uint64_t offset = 0; DataExtractor arangesData(DObj->getArangesSection(), isLittleEndian(), 0); DWARFDebugArangeSet set; - while (set.extract(arangesData, &offset)) + while (arangesData.isValidOffset(offset)) { + if (Error E = set.extract(arangesData, &offset)) { + WithColor::error() << toString(std::move(E)) << '\n'; + break; + } set.dump(OS); + } } auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser, Index: llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include @@ -29,73 +30,78 @@ ArangeDescriptors.clear(); } -bool -DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) { - if (data.isValidOffset(*offset_ptr)) { - ArangeDescriptors.clear(); - Offset = *offset_ptr; - - // 7.20 Address Range Table - // - // Each set of entries in the table of address ranges contained in - // the .debug_aranges section begins with a header consisting of: a - // 4-byte length containing the length of the set of entries for this - // compilation unit, not including the length field itself; a 2-byte - // version identifier containing the value 2 for DWARF Version 2; a - // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer - // containing the size in bytes of an address (or the offset portion of - // an address for segmented addressing) on the target system; and a - // 1-byte unsigned integer containing the size in bytes of a segment - // descriptor on the target system. This header is followed by a series - // of tuples. Each tuple consists of an address and a length, each in - // the size appropriate for an address on the target architecture. - HeaderData.Length = data.getU32(offset_ptr); - HeaderData.Version = data.getU16(offset_ptr); - HeaderData.CuOffset = data.getU32(offset_ptr); - HeaderData.AddrSize = data.getU8(offset_ptr); - HeaderData.SegSize = data.getU8(offset_ptr); - - // Perform basic validation of the header fields. - if (!data.isValidOffsetForDataOfSize(Offset, HeaderData.Length) || - (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)) { - clear(); - return false; - } - - // The first tuple following the header in each set begins at an offset - // that is a multiple of the size of a single tuple (that is, twice the - // size of an address). The header is padded, if necessary, to the - // appropriate boundary. - const uint32_t header_size = *offset_ptr - Offset; - const uint32_t tuple_size = HeaderData.AddrSize * 2; - uint32_t first_tuple_offset = 0; - while (first_tuple_offset < header_size) - first_tuple_offset += tuple_size; - - *offset_ptr = Offset + first_tuple_offset; - - Descriptor arangeDescriptor; - - static_assert(sizeof(arangeDescriptor.Address) == - sizeof(arangeDescriptor.Length), - "Different datatypes for addresses and sizes!"); - assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize); - - while (data.isValidOffset(*offset_ptr)) { - arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize); - arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize); - - // Each set of tuples is terminated by a 0 for the address and 0 - // for the length. - if (arangeDescriptor.Address || arangeDescriptor.Length) - ArangeDescriptors.push_back(arangeDescriptor); - else - return true; // We are done if we get a zero address and length - } - - return false; // No termination tuple is found. +Error DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) { + assert(data.isValidOffset(*offset_ptr)); + ArangeDescriptors.clear(); + Offset = *offset_ptr; + + // 7.20 Address Range Table + // + // Each set of entries in the table of address ranges contained in + // the .debug_aranges section begins with a header consisting of: a + // 4-byte length containing the length of the set of entries for this + // compilation unit, not including the length field itself; a 2-byte + // version identifier containing the value 2 for DWARF Version 2; a + // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer + // containing the size in bytes of an address (or the offset portion of + // an address for segmented addressing) on the target system; and a + // 1-byte unsigned integer containing the size in bytes of a segment + // descriptor on the target system. This header is followed by a series + // of tuples. Each tuple consists of an address and a length, each in + // the size appropriate for an address on the target architecture. + HeaderData.Length = data.getU32(offset_ptr); + HeaderData.Version = data.getU16(offset_ptr); + HeaderData.CuOffset = data.getU32(offset_ptr); + HeaderData.AddrSize = data.getU8(offset_ptr); + HeaderData.SegSize = data.getU8(offset_ptr); + + // Perform basic validation of the header fields. + if (!data.isValidOffsetForDataOfSize(Offset, HeaderData.Length + 4)) + return createStringError(errc::invalid_argument, + "the length of address range table at offset " + "0x%" PRIx64 " exceeds section size", + Offset); + if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) + return createStringError(errc::invalid_argument, + "address range table at offset 0x%" PRIx64 + " has unsupported address size: %d " + "(4 and 8 supported)", + Offset, HeaderData.AddrSize); + + // The first tuple following the header in each set begins at an offset + // that is a multiple of the size of a single tuple (that is, twice the + // size of an address). The header is padded, if necessary, to the + // appropriate boundary. + const uint32_t header_size = *offset_ptr - Offset; + const uint32_t tuple_size = HeaderData.AddrSize * 2; + uint32_t first_tuple_offset = 0; + while (first_tuple_offset < header_size) + first_tuple_offset += tuple_size; + + *offset_ptr = Offset + first_tuple_offset; + + Descriptor arangeDescriptor; + + static_assert(sizeof(arangeDescriptor.Address) == + sizeof(arangeDescriptor.Length), + "Different datatypes for addresses and sizes!"); + assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize); + + while (data.isValidOffset(*offset_ptr)) { + arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize); + arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize); + + // Each set of tuples is terminated by a 0 for the address and 0 + // for the length. + if (arangeDescriptor.Address == 0 && arangeDescriptor.Length == 0) + return ErrorSuccess(); + ArangeDescriptors.push_back(arangeDescriptor); } - return false; + + return createStringError(errc::invalid_argument, + "address range table at offset 0x%" PRIx64 + " is not terminated by null entry", + Offset); } void DWARFDebugArangeSet::dump(raw_ostream &OS) const { Index: llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -26,7 +26,11 @@ uint64_t Offset = 0; DWARFDebugArangeSet Set; - while (Set.extract(DebugArangesData, &Offset)) { + while (DebugArangesData.isValidOffset(Offset)) { + if (Error E = Set.extract(DebugArangesData, &Offset)) { + WithColor::error() << toString(std::move(E)) << '\n'; + return; + } uint64_t CUOffset = Set.getCompileUnitDIEOffset(); for (const auto &Desc : Set.descriptors()) { uint64_t LowPC = Desc.Address; Index: llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s =================================================================== --- llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s +++ llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s @@ -5,7 +5,7 @@ .section .debug_aranges,"",@progbits # CHECK: .debug_aranges contents: -## Check that an empty set of ranges is supported. +## Case 1: Check that an empty set of ranges is supported. .long .L1end - .L1version # Length # CHECK: Address Range Header: length = 0x00000014, .L1version: @@ -22,3 +22,44 @@ .long 0, 0 # Termination tuple # CHECK-NOT: [0x .L1end: + +## Case 2: Check that the address size of 4 is supported. + .long .L2end - .L2version # Length +# CHECK: Address Range Header: length = 0x0000001c, +.L2version: + .short 2 # Version + .long 0x11223344 # Debug Info Offset + .byte 4 # Address Size + .byte 0 # Segment Selector Size +# CHECK-SAME: version = 0x0002, +# CHECK-SAME: cu_offset = 0x11223344, +# CHECK-SAME: addr_size = 0x04, +# CHECK-SAME: seg_size = 0x00 + .space 4 # Padding +.L2tuples: + .long 0x11223344, 0x01020304 # Address and length +# CHECK-NEXT: [0x11223344, 0x12243648) + .long 0, 0 # Termination tuple +# CHECK-NOT: [0x +.L2end: + +## Case 3: Check that the address size of 8 is also supported. + .long .L3end - .L3version # Length +# CHECK: Address Range Header: length = 0x0000002c, +.L3version: + .short 2 # Version + .long 0x22334455 # Debug Info Offset + .byte 8 # Address Size + .byte 0 # Segment Selector Size +# CHECK-SAME: version = 0x0002, +# CHECK-SAME: cu_offset = 0x22334455, +# CHECK-SAME: addr_size = 0x08, +# CHECK-SAME: seg_size = 0x00 + .space 4 # Padding +.L3tuples: + .quad 0x1122334455667788 # Address + .quad 0x0102030405060708 # Length +# CHECK-NEXT: [0x1122334455667788, 0x122436485a6c7e90) + .quad 0, 0 # Termination tuple +# CHECK-NOT: [0x +.L3end: Index: llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml +++ llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml @@ -189,18 +189,6 @@ reserved1: 0x00000000 reserved2: 0x00000000 reserved3: 0x00000000 - - sectname: __debug_aranges - segname: __DWARF - addr: 0x0000000100003083 - size: 48 - offset: 0x00002083 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x00000000 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - sectname: __debug_info segname: __DWARF addr: 0x00000001000030B3 Index: llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml +++ llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml @@ -126,18 +126,6 @@ reserved1: 0x00000000 reserved2: 0x00000000 reserved3: 0x00000000 - - sectname: __debug_aranges - segname: __DWARF - addr: 0x0000000100002084 - size: 48 - offset: 0x00002084 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x00000000 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - sectname: __debug_info segname: __DWARF addr: 0x00000001000020B4 Index: llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml +++ llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml @@ -189,18 +189,6 @@ reserved1: 0x00000000 reserved2: 0x00000000 reserved3: 0x00000000 - - sectname: __debug_aranges - segname: __DWARF - addr: 0x0000000100003083 - size: 48 - offset: 0x00002083 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x00000000 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - sectname: __debug_info segname: __DWARF addr: 0x00000001000030B3 Index: llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml +++ llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml @@ -189,18 +189,6 @@ reserved1: 0x00000000 reserved2: 0x00000000 reserved3: 0x00000000 - - sectname: __debug_aranges - segname: __DWARF - addr: 0x0000000100003083 - size: 48 - offset: 0x00002083 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x00000000 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - sectname: __debug_info segname: __DWARF addr: 0x00000001000030B3 Index: llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml =================================================================== --- llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml +++ llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml @@ -189,18 +189,6 @@ reserved1: 0x00000000 reserved2: 0x00000000 reserved3: 0x00000000 - - sectname: __debug_aranges - segname: __DWARF - addr: 0x0000000100003083 - size: 48 - offset: 0x00002083 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x00000000 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - sectname: __debug_info segname: __DWARF addr: 0x00000001000030B3 Index: llvm/test/tools/llvm-dwarfdump/X86/debug_aranges-error.s =================================================================== --- /dev/null +++ llvm/test/tools/llvm-dwarfdump/X86/debug_aranges-error.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o +# RUN: llvm-dwarfdump -debug-aranges %t.o 2>&1 | FileCheck %s +# RUN: llvm-dwarfdump -lookup 10 %t.o 2>&1 | FileCheck %s + +## This checks that llvm-dwarfdump shows parsing errors in .debug_aranges. +## For more error cases see unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp. + +# CHECK: the length of address range table at offset 0x0 exceeds section size + + .section .debug_aranges,"",@progbits + .long .Lend - .Lversion + 1 # The length exceeds the section boundaries +.Lversion: + .short 2 # Version + .long 0 # Debug Info Offset + .byte 4 # Address Size + .byte 0 # Segment Selector Size + .space 4 # Padding +.Ltuples: + .long 0, 1 # Address and length + .long 0, 0 # Termination tuple +.Lend: Index: llvm/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml =================================================================== --- /dev/null +++ llvm/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml @@ -0,0 +1,301 @@ +# RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x0000000A + ncmds: 5 + sizeofcmds: 1800 + flags: 0x00000000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __PAGEZERO + vmaddr: 0 + vmsize: 4294967296 + fileoff: 0 + filesize: 0 + maxprot: 0 + initprot: 0 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 472 + segname: __TEXT + vmaddr: 4294967296 + vmsize: 4096 + fileoff: 0 + filesize: 0 + maxprot: 7 + initprot: 5 + nsects: 5 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000100000F50 + size: 52 + offset: 0x00000000 + align: 4 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __stubs + segname: __TEXT + addr: 0x0000000100000F84 + size: 6 + offset: 0x00000000 + align: 1 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000408 + reserved1: 0x00000000 + reserved2: 0x00000006 + reserved3: 0x00000000 + - sectname: __stub_helper + segname: __TEXT + addr: 0x0000000100000F8C + size: 26 + offset: 0x00000000 + align: 2 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __cstring + segname: __TEXT + addr: 0x0000000100000FA6 + size: 14 + offset: 0x00000000 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000002 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __unwind_info + segname: __TEXT + addr: 0x0000000100000FB4 + size: 72 + offset: 0x00000000 + align: 2 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __DATA + vmaddr: 4294971392 + vmsize: 4096 + fileoff: 0 + filesize: 0 + maxprot: 7 + initprot: 3 + nsects: 2 + flags: 0 + Sections: + - sectname: __nl_symbol_ptr + segname: __DATA + addr: 0x0000000100001000 + size: 16 + offset: 0x00000000 + align: 3 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000006 + reserved1: 0x00000001 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __la_symbol_ptr + segname: __DATA + addr: 0x0000000100001010 + size: 8 + offset: 0x00000000 + align: 3 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000007 + reserved1: 0x00000003 + reserved2: 0x00000000 + reserved3: 0x00000000 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 4294975488 + vmsize: 4096 + fileoff: 4096 + filesize: 60 + maxprot: 7 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 952 + segname: __DWARF + vmaddr: 4294979584 + vmsize: 4096 + fileoff: 8192 + filesize: 764 + maxprot: 7 + initprot: 3 + nsects: 11 + flags: 0 + Sections: + - sectname: __debug_line + segname: __DWARF + addr: 0x0000000100003000 + size: 69 + offset: 0x00002000 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_pubnames + segname: __DWARF + addr: 0x0000000100003045 + size: 27 + offset: 0x00002045 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_pubtypes + segname: __DWARF + addr: 0x0000000100003060 + size: 35 + offset: 0x00002060 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_aranges + segname: __DWARF + addr: 0x0000000100003083 + size: 48 + offset: 0x00002083 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_info + segname: __DWARF + addr: 0x00000001000030B3 + size: 121 + offset: 0x000020B3 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x000000010000312C + size: 76 + offset: 0x0000212C + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_str + segname: __DWARF + addr: 0x0000000100003178 + size: 142 + offset: 0x00002178 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_names + segname: __DWARF + addr: 0x0000000100003206 + size: 60 + offset: 0x00002206 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_namespac + segname: __DWARF + addr: 0x0000000100003242 + size: 36 + offset: 0x00002242 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_types + segname: __DWARF + addr: 0x0000000100003266 + size: 114 + offset: 0x00002266 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_objc + segname: __DWARF + addr: 0x00000001000032D8 + size: 36 + offset: 0x000022D8 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 +DWARF: + debug_aranges: + - Length: + TotalLength: 45 + Version: 2 + CuOffset: 0 + AddrSize: 8 + SegSize: 0 + Descriptors: + - Address: 0x0000000100000F50 + Length: 52 +... + +#CHECK: the length of address range table at offset 0x0 exceeds section size Index: llvm/tools/obj2yaml/dwarf2yaml.cpp =================================================================== --- llvm/tools/obj2yaml/dwarf2yaml.cpp +++ llvm/tools/obj2yaml/dwarf2yaml.cpp @@ -56,13 +56,15 @@ } } -void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) { +Error dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) { DataExtractor ArangesData(DCtx.getDWARFObj().getArangesSection(), DCtx.isLittleEndian(), 0); uint64_t Offset = 0; DWARFDebugArangeSet Set; - while (Set.extract(ArangesData, &Offset)) { + while (ArangesData.isValidOffset(Offset)) { + if (Error E = Set.extract(ArangesData, &Offset)) + return E; DWARFYAML::ARange Range; Range.Length.setLength(Set.getHeader().Length); Range.Version = Set.getHeader().Version; @@ -77,6 +79,7 @@ } Y.ARanges.push_back(Range); } + return ErrorSuccess(); } void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y, @@ -346,12 +349,13 @@ } } -std::error_code dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) { +llvm::Error dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) { dumpDebugAbbrev(DCtx, Y); dumpDebugStrings(DCtx, Y); - dumpDebugARanges(DCtx, Y); + if (Error E = dumpDebugARanges(DCtx, Y)) + return E; dumpDebugPubSections(DCtx, Y); dumpDebugInfo(DCtx, Y); dumpDebugLines(DCtx, Y); - return obj2yaml_error::success; + return ErrorSuccess(); } Index: llvm/tools/obj2yaml/macho2yaml.cpp =================================================================== --- llvm/tools/obj2yaml/macho2yaml.cpp +++ llvm/tools/obj2yaml/macho2yaml.cpp @@ -198,7 +198,7 @@ std::unique_ptr DICtx = DWARFContext::create(Obj); if (auto Err = dwarf2yaml(*DICtx, Y->DWARF)) - return errorCodeToError(Err); + return std::move(Err); return std::move(Y); } @@ -543,20 +543,20 @@ return Error::success(); } -std::error_code macho2yaml(raw_ostream &Out, const object::Binary &Binary) { +Error macho2yaml(raw_ostream &Out, const object::Binary &Binary) { if (const auto *MachOObj = dyn_cast(&Binary)) { if (auto Err = macho2yaml(Out, *MachOObj)) { - return errorToErrorCode(std::move(Err)); + return Err; } - return obj2yaml_error::success; + return Error::success(); } if (const auto *MachOObj = dyn_cast(&Binary)) { if (auto Err = macho2yaml(Out, *MachOObj)) { - return errorToErrorCode(std::move(Err)); + return Err; } - return obj2yaml_error::success; + return Error::success(); } - return obj2yaml_error::unsupported_obj_file_format; + return errorCodeToError(obj2yaml_error::unsupported_obj_file_format); } Index: llvm/tools/obj2yaml/obj2yaml.h =================================================================== --- llvm/tools/obj2yaml/obj2yaml.h +++ llvm/tools/obj2yaml/obj2yaml.h @@ -23,7 +23,7 @@ const llvm::object::COFFObjectFile &Obj); llvm::Error elf2yaml(llvm::raw_ostream &Out, const llvm::object::ObjectFile &Obj); -std::error_code macho2yaml(llvm::raw_ostream &Out, +llvm::Error macho2yaml(llvm::raw_ostream &Out, const llvm::object::Binary &Obj); llvm::Error minidump2yaml(llvm::raw_ostream &Out, const llvm::object::MinidumpFile &Obj); @@ -40,6 +40,6 @@ } } -std::error_code dwarf2yaml(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); +llvm::Error dwarf2yaml(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); #endif Index: llvm/tools/obj2yaml/obj2yaml.cpp =================================================================== --- llvm/tools/obj2yaml/obj2yaml.cpp +++ llvm/tools/obj2yaml/obj2yaml.cpp @@ -42,7 +42,7 @@ // Universal MachO is not a subclass of ObjectFile, so it needs to be handled // here with the other binary types. if (Binary.isMachO() || Binary.isMachOUniversalBinary()) - return errorCodeToError(macho2yaml(outs(), Binary)); + return macho2yaml(outs(), Binary); // TODO: If this is an archive, then burst it and dump each entry if (ObjectFile *Obj = dyn_cast(&Binary)) return dumpObject(*Obj); Index: llvm/unittests/DebugInfo/DWARF/CMakeLists.txt =================================================================== --- llvm/unittests/DebugInfo/DWARF/CMakeLists.txt +++ llvm/unittests/DebugInfo/DWARF/CMakeLists.txt @@ -11,6 +11,7 @@ add_llvm_unittest(DebugInfoDWARFTests DwarfGenerator.cpp DwarfUtils.cpp + DWARFDebugArangeSetTest.cpp DWARFDebugInfoTest.cpp DWARFDebugLineTest.cpp DWARFDieTest.cpp Index: llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp =================================================================== --- /dev/null +++ llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp @@ -0,0 +1,75 @@ +//===- llvm/unittest/DebugInfo/DWARFDebugArangeSetTest.cpp-----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +template +void ExpectExtractError(const char (&SecDataRaw)[SecSize], + const char *ErrorMessage) { + DataExtractor Extractor(StringRef(SecDataRaw, SecSize - 1), + /* IsLittleEndian = */ true, + /* AddressSize = */ 4); + DWARFDebugArangeSet Set; + uint64_t Offset = 0; + Error E = Set.extract(Extractor, &Offset); + ASSERT_TRUE(E.operator bool()); + EXPECT_STREQ(ErrorMessage, toString(std::move(E)).c_str()); +} + +TEST(DWARFDebugArangeSet, LengthExceedsSectionSize) { + static const char DebugArangesSecRaw[] = + "\x15\x00\x00\x00" // The length exceeds the section boundaries + "\x02\x00" // Version + "\x00\x00\x00\x00" // Debug Info Offset + "\x04" // Address Size + "\x00" // Segment Selector Size + "\x00\x00\x00\x00" // Padding + "\x00\x00\x00\x00" // Termination tuple + "\x00\x00\x00\x00"; + ExpectExtractError( + DebugArangesSecRaw, + "the length of address range table at offset 0x0 exceeds section size"); +} + +TEST(DWARFDebugArangeSet, UnsupportedAddressSize) { + static const char DebugArangesSecRaw[] = + "\x0c\x00\x00\x00" // Length + "\x02\x00" // Version + "\x00\x00\x00\x00" // Debug Info Offset + "\x02" // Address Size (not supported) + "\x00" // Segment Selector Size + // No padding + "\x00\x00\x00\x00"; // Termination tuple + ExpectExtractError( + DebugArangesSecRaw, + "address range table at offset 0x0 has unsupported address size: 2 " + "(4 and 8 supported)"); +} + +TEST(DWARFDebugArangeSet, NoTerminationEntry) { + static const char DebugArangesSecRaw[] = + "\x14\x00\x00\x00" // Length + "\x02\x00" // Version + "\x00\x00\x00\x00" // Debug Info Offset + "\x04" // Address Size + "\x00" // Segment Selector Size + "\x00\x00\x00\x00" // Padding + "\x00\x00\x00\x00" // Entry: Address + "\x01\x00\x00\x00" // Length + ; // No termination tuple + ExpectExtractError( + DebugArangesSecRaw, + "address range table at offset 0x0 is not terminated by null entry"); +} + +} // end anonymous namespace