From 25f6cfa0aaa69e0989735c6219ee34d92d1fba94 Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Wed, 25 Dec 2019 14:05:56 +0700 Subject: [PATCH] [DWARF] Return Error from DWARFDebugArangeSet::extract(). This helps to detect and report parsing errors better. The patch follows the ideas of LLDB's patches D59370 and D59381. It adds tests for valid and some invalid cases. More checks and tests to come. Note that the patch fixes validation of the Length field because the value does not include the field itself. The existing users are updated to show the error messages. Differential Revision: https://reviews.llvm.org/D71875 --- .../DebugInfo/DWARF/DWARFDebugArangeSet.h | 3 +- lib/DebugInfo/DWARF/DWARFContext.cpp | 7 +- lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp | 122 +++---- lib/DebugInfo/DWARF/DWARFDebugAranges.cpp | 6 +- test/DebugInfo/X86/dwarfdump-debug-aranges.s | 43 ++- test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml | 12 - test/ObjectYAML/MachO/DWARF-debug_str.yaml | 12 - test/ObjectYAML/MachO/DWARF-pubsections.yaml | 12 - .../MachO/DWARF2-AddrSize8-FormValues.yaml | 12 - .../ObjectYAML/MachO/DWARF5-abbrevValues.yaml | 12 - .../llvm-dwarfdump/X86/debug_aranges-error.s | 21 ++ .../macho-DWARF-debug_aranges-error.yaml | 301 ++++++++++++++++++ tools/obj2yaml/dwarf2yaml.cpp | 14 +- tools/obj2yaml/macho2yaml.cpp | 14 +- tools/obj2yaml/obj2yaml.cpp | 2 +- tools/obj2yaml/obj2yaml.h | 4 +- unittests/DebugInfo/DWARF/CMakeLists.txt | 1 + .../DWARF/DWARFDebugArangeSetTest.cpp | 75 +++++ 18 files changed, 536 insertions(+), 137 deletions(-) create mode 100644 test/tools/llvm-dwarfdump/X86/debug_aranges-error.s create mode 100644 test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml create mode 100644 unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h index ebe4ad6e24d..d03c3414e73 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h +++ b/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 @@ public: 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; } diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index aaa6d5250f2..01073aff566 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -453,8 +453,13 @@ void DWARFContext::dump( 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, diff --git a/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp b/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp index b8478bdc48f..c35297b1b81 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp +++ b/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 @@ void DWARFDebugArangeSet::clear() { ArangeDescriptors.clear(); } -bool -DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) { - if (data.isValidOffset(*offset_ptr)) { - ArangeDescriptors.clear(); - Offset = *offset_ptr; +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); + // 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; - } + // 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; + // 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; + *offset_ptr = Offset + first_tuple_offset; - Descriptor arangeDescriptor; + Descriptor arangeDescriptor; - static_assert(sizeof(arangeDescriptor.Address) == - sizeof(arangeDescriptor.Length), - "Different datatypes for addresses and sizes!"); - assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize); + 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); + 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. + // 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 { diff --git a/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp index fa157e86885..9ca9021e205 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -26,7 +26,11 @@ void DWARFDebugAranges::extract(DataExtractor DebugArangesData) { 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; diff --git a/test/DebugInfo/X86/dwarfdump-debug-aranges.s b/test/DebugInfo/X86/dwarfdump-debug-aranges.s index 0ee166da4c2..359543baa6d 100644 --- a/test/DebugInfo/X86/dwarfdump-debug-aranges.s +++ b/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: diff --git a/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml b/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml index 07365148bb8..8301aa69172 100644 --- a/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml +++ b/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml @@ -189,18 +189,6 @@ LoadCommands: 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 diff --git a/test/ObjectYAML/MachO/DWARF-debug_str.yaml b/test/ObjectYAML/MachO/DWARF-debug_str.yaml index 84c5e22d255..40890349f5c 100644 --- a/test/ObjectYAML/MachO/DWARF-debug_str.yaml +++ b/test/ObjectYAML/MachO/DWARF-debug_str.yaml @@ -126,18 +126,6 @@ LoadCommands: 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 diff --git a/test/ObjectYAML/MachO/DWARF-pubsections.yaml b/test/ObjectYAML/MachO/DWARF-pubsections.yaml index a3c05ca5b35..f2eadd20d8a 100644 --- a/test/ObjectYAML/MachO/DWARF-pubsections.yaml +++ b/test/ObjectYAML/MachO/DWARF-pubsections.yaml @@ -189,18 +189,6 @@ LoadCommands: 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 diff --git a/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml b/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml index a7aa4e205d2..8e30d495327 100644 --- a/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml +++ b/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml @@ -189,18 +189,6 @@ LoadCommands: 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 diff --git a/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml b/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml index 047ee749d67..817830d3542 100644 --- a/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml +++ b/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml @@ -189,18 +189,6 @@ LoadCommands: 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 diff --git a/test/tools/llvm-dwarfdump/X86/debug_aranges-error.s b/test/tools/llvm-dwarfdump/X86/debug_aranges-error.s new file mode 100644 index 00000000000..7c44810a21a --- /dev/null +++ b/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: diff --git a/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml b/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml new file mode 100644 index 00000000000..680b7c6e80a --- /dev/null +++ b/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 diff --git a/tools/obj2yaml/dwarf2yaml.cpp b/tools/obj2yaml/dwarf2yaml.cpp index f684b465504..524f43e71bd 100644 --- a/tools/obj2yaml/dwarf2yaml.cpp +++ b/tools/obj2yaml/dwarf2yaml.cpp @@ -56,13 +56,15 @@ void dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) { } } -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 @@ void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) { } Y.ARanges.push_back(Range); } + return ErrorSuccess(); } void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y, @@ -346,12 +349,13 @@ void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) { } } -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(); } diff --git a/tools/obj2yaml/macho2yaml.cpp b/tools/obj2yaml/macho2yaml.cpp index 517e7f196ee..0ee8814d35a 100644 --- a/tools/obj2yaml/macho2yaml.cpp +++ b/tools/obj2yaml/macho2yaml.cpp @@ -198,7 +198,7 @@ Expected> MachODumper::dump() { 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 @@ Error macho2yaml(raw_ostream &Out, const object::MachOUniversalBinary &Obj) { 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); } diff --git a/tools/obj2yaml/obj2yaml.cpp b/tools/obj2yaml/obj2yaml.cpp index f03b1ef4bad..67ba0e416e6 100644 --- a/tools/obj2yaml/obj2yaml.cpp +++ b/tools/obj2yaml/obj2yaml.cpp @@ -42,7 +42,7 @@ static Error dumpInput(StringRef File) { // 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); diff --git a/tools/obj2yaml/obj2yaml.h b/tools/obj2yaml/obj2yaml.h index 4f4a5330429..b538ff87ac2 100644 --- a/tools/obj2yaml/obj2yaml.h +++ b/tools/obj2yaml/obj2yaml.h @@ -23,7 +23,7 @@ std::error_code coff2yaml(llvm::raw_ostream &Out, 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 @@ struct Data; } } -std::error_code dwarf2yaml(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); +llvm::Error dwarf2yaml(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y); #endif diff --git a/unittests/DebugInfo/DWARF/CMakeLists.txt b/unittests/DebugInfo/DWARF/CMakeLists.txt index 4fb79b2a96e..611621dbd37 100644 --- a/unittests/DebugInfo/DWARF/CMakeLists.txt +++ b/unittests/DebugInfo/DWARF/CMakeLists.txt @@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS add_llvm_unittest(DebugInfoDWARFTests DwarfGenerator.cpp DwarfUtils.cpp + DWARFDebugArangeSetTest.cpp DWARFDebugInfoTest.cpp DWARFDebugLineTest.cpp DWARFDieTest.cpp diff --git a/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp b/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp new file mode 100644 index 00000000000..61937c54c63 --- /dev/null +++ b/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