diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h +++ b/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; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/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, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp +++ b/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 { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ b/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; diff --git a/llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s b/llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s --- a/llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s +++ b/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: diff --git a/llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml b/llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml --- a/llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml +++ b/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 diff --git a/llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml b/llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml --- a/llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml +++ b/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 diff --git a/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml b/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml --- a/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml +++ b/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 diff --git a/llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml b/llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml --- a/llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml +++ b/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 diff --git a/llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml b/llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml --- a/llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml +++ b/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 diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_aranges-error.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_aranges-error.s new file mode 100644 --- /dev/null +++ b/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: diff --git a/llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml b/llvm/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml copy from llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml copy to llvm/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml --- a/llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml +++ b/llvm/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml @@ -1,4 +1,4 @@ -# RUN: yaml2obj %s | obj2yaml | FileCheck %s +# RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s --- !mach-o FileHeader: @@ -285,23 +285,17 @@ reserved1: 0x00000000 reserved2: 0x00000000 reserved3: 0x00000000 -DWARF: - debug_abbrev: - - Code: 0x00000001 - Tag: DW_TAG_compile_unit - Children: DW_CHILDREN_yes - Attributes: - - Attribute: 0x2001 - Form: DW_FORM_implicit_const - Value: 0x12345678 +DWARF: + debug_aranges: + - Length: + TotalLength: 45 + Version: 2 + CuOffset: 0 + AddrSize: 8 + SegSize: 0 + Descriptors: + - Address: 0x0000000100000F50 + Length: 52 ... -#CHECK: DWARF: -#CHECK: debug_abbrev: -#CHECK: - Code: 0x00000001 -#CHECK: Tag: DW_TAG_compile_unit -#CHECK: Children: DW_CHILDREN_yes -#CHECK: Attributes: -#CHECK: - Attribute: 0x2001 -#CHECK: Form: DW_FORM_implicit_const -#CHECK: Value: 0x0000000012345678 +#CHECK: the length of address range table at offset 0x0 exceeds section size 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 @@ -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(); } diff --git a/llvm/tools/obj2yaml/macho2yaml.cpp b/llvm/tools/obj2yaml/macho2yaml.cpp --- a/llvm/tools/obj2yaml/macho2yaml.cpp +++ b/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); } diff --git a/llvm/tools/obj2yaml/obj2yaml.h b/llvm/tools/obj2yaml/obj2yaml.h --- a/llvm/tools/obj2yaml/obj2yaml.h +++ b/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 diff --git a/llvm/tools/obj2yaml/obj2yaml.cpp b/llvm/tools/obj2yaml/obj2yaml.cpp --- a/llvm/tools/obj2yaml/obj2yaml.cpp +++ b/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); diff --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt --- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt +++ b/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 diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp new file mode 100644 --- /dev/null +++ b/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