mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
[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
This commit is contained in:
parent
6a79709adb
commit
25f6cfa0aa
@ -11,6 +11,7 @@
|
||||
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
@ -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; }
|
||||
|
@ -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,
|
||||
|
@ -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 <cassert>
|
||||
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
21
test/tools/llvm-dwarfdump/X86/debug_aranges-error.s
Normal file
21
test/tools/llvm-dwarfdump/X86/debug_aranges-error.s
Normal file
@ -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:
|
301
test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml
Normal file
301
test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml
Normal file
@ -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
|
@ -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();
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ Expected<std::unique_ptr<MachOYAML::Object>> MachODumper::dump() {
|
||||
|
||||
std::unique_ptr<DWARFContext> 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<object::MachOUniversalBinary>(&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<object::MachOObjectFile>(&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);
|
||||
}
|
||||
|
@ -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<ObjectFile>(&Binary))
|
||||
return dumpObject(*Obj);
|
||||
|
@ -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
|
||||
|
@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS
|
||||
add_llvm_unittest(DebugInfoDWARFTests
|
||||
DwarfGenerator.cpp
|
||||
DwarfUtils.cpp
|
||||
DWARFDebugArangeSetTest.cpp
|
||||
DWARFDebugInfoTest.cpp
|
||||
DWARFDebugLineTest.cpp
|
||||
DWARFDieTest.cpp
|
||||
|
75
unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp
Normal file
75
unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp
Normal file
@ -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 <size_t SecSize>
|
||||
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
|
Loading…
Reference in New Issue
Block a user