mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-29 11:17:28 +00:00
Fix the verification of DIEs with DW_AT_ranges.
Summary: Previous code would try to verify DW_AT_ranges and if any ranges would overlap, it would stop attributing any ranges after this to the DIE which caused incorrect errors to be reported that a DIE's address ranges were not contained in the parent DIE's ranges. Added a fix and a test. Reviewers: aprantl, labath, probinson, JDevlieghere, jhenderson Subscribers: hiraditya, MaskRay, cmtice, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D79962
This commit is contained in:
parent
bd7defeb94
commit
ccf5a44917
@ -45,6 +45,24 @@ struct DWARFAddressRange {
|
|||||||
return LowPC < RHS.HighPC && RHS.LowPC < HighPC;
|
return LowPC < RHS.HighPC && RHS.LowPC < HighPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Union two address ranges if they intersect.
|
||||||
|
///
|
||||||
|
/// This function will union two address ranges if they intersect by
|
||||||
|
/// modifying this range to be the union of both ranges. If the two ranges
|
||||||
|
/// don't intersect this range will be left alone.
|
||||||
|
///
|
||||||
|
/// \param RHS Another address range to combine with.
|
||||||
|
///
|
||||||
|
/// \returns false if the ranges don't intersect, true if they do and the
|
||||||
|
/// ranges were combined.
|
||||||
|
bool merge(const DWARFAddressRange &RHS) {
|
||||||
|
if (!intersects(RHS))
|
||||||
|
return false;
|
||||||
|
LowPC = std::min<uint64_t>(LowPC, RHS.LowPC);
|
||||||
|
HighPC = std::max<uint64_t>(HighPC, RHS.HighPC);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void dump(raw_ostream &OS, uint32_t AddressSize, DIDumpOptions DumpOpts = {},
|
void dump(raw_ostream &OS, uint32_t AddressSize, DIDumpOptions DumpOpts = {},
|
||||||
const DWARFObject *Obj = nullptr) const;
|
const DWARFObject *Obj = nullptr) const;
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#ifndef LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
|
#ifndef LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
|
||||||
#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
|
#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
#include "llvm/DebugInfo/DIContext.h"
|
#include "llvm/DebugInfo/DIContext.h"
|
||||||
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
|
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
|
||||||
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
|
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
|
||||||
@ -56,11 +57,13 @@ public:
|
|||||||
typedef std::set<DieRangeInfo>::const_iterator die_range_info_iterator;
|
typedef std::set<DieRangeInfo>::const_iterator die_range_info_iterator;
|
||||||
|
|
||||||
/// Inserts the address range. If the range overlaps with an existing
|
/// Inserts the address range. If the range overlaps with an existing
|
||||||
/// range, the range is *not* added and an iterator to the overlapping
|
/// range, the range that it overlaps with will be returned and the two
|
||||||
/// range is returned.
|
/// address ranges will be unioned together in "Ranges".
|
||||||
///
|
///
|
||||||
/// This is used for finding overlapping ranges within the same DIE.
|
/// This is used for finding overlapping ranges in the DW_AT_ranges
|
||||||
address_range_iterator insert(const DWARFAddressRange &R);
|
/// attribute of a DIE. It is also used as a set of address ranges that
|
||||||
|
/// children address ranges must all be contained in.
|
||||||
|
Optional<DWARFAddressRange> insert(const DWARFAddressRange &R);
|
||||||
|
|
||||||
/// Finds an address range in the sorted vector of ranges.
|
/// Finds an address range in the sorted vector of ranges.
|
||||||
address_range_iterator findRange(const DWARFAddressRange &R) const {
|
address_range_iterator findRange(const DWARFAddressRange &R) const {
|
||||||
|
@ -26,24 +26,26 @@ using namespace llvm;
|
|||||||
using namespace dwarf;
|
using namespace dwarf;
|
||||||
using namespace object;
|
using namespace object;
|
||||||
|
|
||||||
DWARFVerifier::DieRangeInfo::address_range_iterator
|
Optional<DWARFAddressRange>
|
||||||
DWARFVerifier::DieRangeInfo::insert(const DWARFAddressRange &R) {
|
DWARFVerifier::DieRangeInfo::insert(const DWARFAddressRange &R) {
|
||||||
auto Begin = Ranges.begin();
|
auto Begin = Ranges.begin();
|
||||||
auto End = Ranges.end();
|
auto End = Ranges.end();
|
||||||
auto Pos = std::lower_bound(Begin, End, R);
|
auto Pos = std::lower_bound(Begin, End, R);
|
||||||
|
|
||||||
if (Pos != End) {
|
if (Pos != End) {
|
||||||
if (Pos->intersects(R))
|
DWARFAddressRange Range(*Pos);
|
||||||
return std::move(Pos);
|
if (Pos->merge(R))
|
||||||
if (Pos != Begin) {
|
return Range;
|
||||||
auto Iter = Pos - 1;
|
}
|
||||||
if (Iter->intersects(R))
|
if (Pos != Begin) {
|
||||||
return std::move(Iter);
|
auto Iter = Pos - 1;
|
||||||
}
|
DWARFAddressRange Range(*Iter);
|
||||||
|
if (Iter->merge(R))
|
||||||
|
return Range;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ranges.insert(Pos, R);
|
Ranges.insert(Pos, R);
|
||||||
return Ranges.end();
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWARFVerifier::DieRangeInfo::die_range_info_iterator
|
DWARFVerifier::DieRangeInfo::die_range_info_iterator
|
||||||
@ -397,22 +399,30 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
|
|||||||
// processing an object file.
|
// processing an object file.
|
||||||
|
|
||||||
if (!IsObjectFile || IsMachOObject || Die.getTag() != DW_TAG_compile_unit) {
|
if (!IsObjectFile || IsMachOObject || Die.getTag() != DW_TAG_compile_unit) {
|
||||||
|
bool DumpDieAfterError = false;
|
||||||
for (auto Range : Ranges) {
|
for (auto Range : Ranges) {
|
||||||
if (!Range.valid()) {
|
if (!Range.valid()) {
|
||||||
++NumErrors;
|
++NumErrors;
|
||||||
error() << "Invalid address range " << Range << "\n";
|
error() << "Invalid address range " << Range << "\n";
|
||||||
|
DumpDieAfterError = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that ranges don't intersect.
|
// Verify that ranges don't intersect and also build up the DieRangeInfo
|
||||||
const auto IntersectingRange = RI.insert(Range);
|
// address ranges. Don't break out of the loop below early, or we will
|
||||||
if (IntersectingRange != RI.Ranges.end()) {
|
// think this DIE doesn't have all of the address ranges it is supposed
|
||||||
|
// to have. Compile units often have DW_AT_ranges that can contain one or
|
||||||
|
// more dead stripped address ranges which tend to all be at the same
|
||||||
|
// address: 0 or -1.
|
||||||
|
if (auto PrevRange = RI.insert(Range)) {
|
||||||
++NumErrors;
|
++NumErrors;
|
||||||
error() << "DIE has overlapping address ranges: " << Range << " and "
|
error() << "DIE has overlapping ranges in DW_AT_ranges attribute: "
|
||||||
<< *IntersectingRange << "\n";
|
<< *PrevRange << " and " << Range << '\n';
|
||||||
break;
|
DumpDieAfterError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (DumpDieAfterError)
|
||||||
|
dump(Die, 2) << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that children don't intersect.
|
// Verify that children don't intersect.
|
||||||
|
@ -0,0 +1,260 @@
|
|||||||
|
# This test verifies that if a DW_TAG_compile_unit has DW_AT_ranges that
|
||||||
|
# overlap, that it doesn't end up producing invalid errors claiming a child
|
||||||
|
# DW_TAG_subprogram DIE is not in the parant (CU) ranges. Prior to the commit
|
||||||
|
# that fixed this, a loop was iterating over all DW_AT_ranges for a DIE and
|
||||||
|
# stopping the loop if any intersecting ranges were found. This would cause
|
||||||
|
# the DW_TAG_subprogram DIEs, like "stripped2" and "main", to improperly report
|
||||||
|
# that they were not contained in the parent's address ranges
|
||||||
|
#
|
||||||
|
# The DWARF looks like:
|
||||||
|
# 0x0000000b: DW_TAG_compile_unit
|
||||||
|
# DW_AT_name ("/tmp/main.c")
|
||||||
|
# DW_AT_language (DW_LANG_C)
|
||||||
|
# DW_AT_low_pc (0x0000000000000000)
|
||||||
|
# DW_AT_ranges (0x00000000
|
||||||
|
# [0x0000000000002000, 0x0000000000003000)
|
||||||
|
# [0x0000000000000000, 0x0000000000000020)
|
||||||
|
# [0x0000000000000000, 0x0000000000000030)
|
||||||
|
# [0x0000000000001000, 0x0000000000002000))
|
||||||
|
#
|
||||||
|
# 0x0000001e: DW_TAG_subprogram
|
||||||
|
# DW_AT_name ("stripped1")
|
||||||
|
# DW_AT_low_pc (0x0000000000000000)
|
||||||
|
# DW_AT_high_pc (0x0000000000000020)
|
||||||
|
#
|
||||||
|
# 0x0000002f: DW_TAG_subprogram
|
||||||
|
# DW_AT_name ("stripped2")
|
||||||
|
# DW_AT_low_pc (0x0000000000000000)
|
||||||
|
# DW_AT_high_pc (0x0000000000000030)
|
||||||
|
#
|
||||||
|
# 0x00000044: DW_TAG_subprogram
|
||||||
|
# DW_AT_name ("main")
|
||||||
|
# DW_AT_low_pc (0x0000000000001000)
|
||||||
|
# DW_AT_high_pc (0x0000000000002000)
|
||||||
|
#
|
||||||
|
# 0x00000055: DW_TAG_subprogram
|
||||||
|
# DW_AT_name ("foo")
|
||||||
|
# DW_AT_low_pc (0x0000000000002000)
|
||||||
|
# DW_AT_high_pc (0x0000000000003000)
|
||||||
|
#
|
||||||
|
# 0x00000066: NULL
|
||||||
|
|
||||||
|
# RUN: yaml2obj %s | not llvm-dwarfdump --verify - | FileCheck %s --implicit-check-not=error:
|
||||||
|
|
||||||
|
# CHECK: error: DIE has overlapping ranges in DW_AT_ranges attribute: [0x0000000000000000, 0x0000000000000020) and [0x0000000000000000, 0x0000000000000030)
|
||||||
|
|
||||||
|
# CHECK: 0x0000000b: DW_TAG_compile_unit
|
||||||
|
# CHECK-NEXT: DW_AT_name ("/tmp/main.c")
|
||||||
|
# CHECK-NEXT: DW_AT_language (DW_LANG_C)
|
||||||
|
# CHECK-NEXT: DW_AT_low_pc (0x0000000000000000)
|
||||||
|
# CHECK-NEXT: DW_AT_ranges (0x00000000
|
||||||
|
# CHECK-NEXT: [0x0000000000002000, 0x0000000000003000)
|
||||||
|
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000020)
|
||||||
|
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000030)
|
||||||
|
# CHECK-NEXT: [0x0000000000001000, 0x0000000000002000))
|
||||||
|
|
||||||
|
# CHECK: error: DIEs have overlapping address ranges:
|
||||||
|
# CHECK: 0x0000002f: DW_TAG_subprogram
|
||||||
|
# CHECK-NEXT: DW_AT_name ("stripped2")
|
||||||
|
# CHECK-NEXT: DW_AT_low_pc (0x0000000000000000)
|
||||||
|
# CHECK-NEXT: DW_AT_high_pc (0x0000000000000030)
|
||||||
|
|
||||||
|
# CHECK: 0x0000001e: DW_TAG_subprogram
|
||||||
|
# CHECK-NEXT: DW_AT_name ("stripped1")
|
||||||
|
# CHECK-NEXT: DW_AT_low_pc (0x0000000000000000)
|
||||||
|
# CHECK-NEXT: DW_AT_high_pc (0x0000000000000020)
|
||||||
|
|
||||||
|
# CHECK: Verifying .debug_info references...
|
||||||
|
|
||||||
|
--- !mach-o
|
||||||
|
FileHeader:
|
||||||
|
magic: 0xFEEDFACF
|
||||||
|
cputype: 0x01000007
|
||||||
|
cpusubtype: 0x00000003
|
||||||
|
filetype: 0x00000001
|
||||||
|
ncmds: 4
|
||||||
|
sizeofcmds: 464
|
||||||
|
flags: 0x00002000
|
||||||
|
reserved: 0x00000000
|
||||||
|
LoadCommands:
|
||||||
|
- cmd: LC_SEGMENT_64
|
||||||
|
cmdsize: 392
|
||||||
|
segname: ''
|
||||||
|
vmaddr: 0
|
||||||
|
vmsize: 261
|
||||||
|
fileoff: 528
|
||||||
|
filesize: 261
|
||||||
|
maxprot: 7
|
||||||
|
initprot: 7
|
||||||
|
nsects: 4
|
||||||
|
flags: 0
|
||||||
|
Sections:
|
||||||
|
- sectname: __debug_abbrev
|
||||||
|
segname: __DWARF
|
||||||
|
addr: 0x0000000000000000
|
||||||
|
size: 36
|
||||||
|
offset: 0x00000210
|
||||||
|
align: 0
|
||||||
|
reloff: 0x00000000
|
||||||
|
nreloc: 0
|
||||||
|
flags: 0x00000000
|
||||||
|
reserved1: 0x00000000
|
||||||
|
reserved2: 0x00000000
|
||||||
|
reserved3: 0x00000000
|
||||||
|
content: 011101030E1305110155170000022E00030E110112060000032E00030E11011201000000
|
||||||
|
- sectname: __debug_info
|
||||||
|
segname: __DWARF
|
||||||
|
addr: 0x0000000000000024
|
||||||
|
size: 103
|
||||||
|
offset: 0x00000234
|
||||||
|
align: 0
|
||||||
|
reloff: 0x00000000
|
||||||
|
nreloc: 0
|
||||||
|
flags: 0x00000000
|
||||||
|
reserved1: 0x00000000
|
||||||
|
reserved2: 0x00000000
|
||||||
|
reserved3: 0x00000000
|
||||||
|
content: 630000000400000000000801010000000200000000000000000000000000020D0000000000000000000000200000000317000000000000000000000030000000000000000221000000001000000000000000100000022600000000200000000000000010000000
|
||||||
|
- sectname: __debug_ranges
|
||||||
|
segname: __DWARF
|
||||||
|
addr: 0x000000000000008B
|
||||||
|
size: 80
|
||||||
|
offset: 0x0000029B
|
||||||
|
align: 0
|
||||||
|
reloff: 0x00000000
|
||||||
|
nreloc: 0
|
||||||
|
flags: 0x00000000
|
||||||
|
reserved1: 0x00000000
|
||||||
|
reserved2: 0x00000000
|
||||||
|
reserved3: 0x00000000
|
||||||
|
content: '0020000000000000003000000000000000000000000000002000000000000000000000000000000030000000000000000010000000000000002000000000000000000000000000000000000000000000'
|
||||||
|
- sectname: __debug_str
|
||||||
|
segname: __DWARF
|
||||||
|
addr: 0x00000000000000DB
|
||||||
|
size: 42
|
||||||
|
offset: 0x000002EB
|
||||||
|
align: 0
|
||||||
|
reloff: 0x00000000
|
||||||
|
nreloc: 0
|
||||||
|
flags: 0x00000000
|
||||||
|
reserved1: 0x00000000
|
||||||
|
reserved2: 0x00000000
|
||||||
|
reserved3: 0x00000000
|
||||||
|
content: 002F746D702F6D61696E2E630073747269707065643100737472697070656432006D61696E00666F6F00
|
||||||
|
- cmd: LC_SYMTAB
|
||||||
|
cmdsize: 24
|
||||||
|
symoff: 0
|
||||||
|
nsyms: 0
|
||||||
|
stroff: 792
|
||||||
|
strsize: 8
|
||||||
|
- cmd: LC_BUILD_VERSION
|
||||||
|
cmdsize: 32
|
||||||
|
platform: 1
|
||||||
|
minos: 658944
|
||||||
|
sdk: 658944
|
||||||
|
ntools: 1
|
||||||
|
Tools:
|
||||||
|
- tool: 3
|
||||||
|
version: 34734080
|
||||||
|
- cmd: LC_DATA_IN_CODE
|
||||||
|
cmdsize: 16
|
||||||
|
dataoff: 792
|
||||||
|
datasize: 0
|
||||||
|
LinkEditData:
|
||||||
|
StringTable:
|
||||||
|
- ' '
|
||||||
|
- ''
|
||||||
|
- ''
|
||||||
|
- ''
|
||||||
|
- ''
|
||||||
|
- ''
|
||||||
|
- ''
|
||||||
|
DWARF:
|
||||||
|
debug_str:
|
||||||
|
- ''
|
||||||
|
- '/tmp/main.c'
|
||||||
|
- stripped1
|
||||||
|
- stripped2
|
||||||
|
- main
|
||||||
|
- foo
|
||||||
|
debug_abbrev:
|
||||||
|
- Code: 0x00000001
|
||||||
|
Tag: DW_TAG_compile_unit
|
||||||
|
Children: DW_CHILDREN_yes
|
||||||
|
Attributes:
|
||||||
|
- Attribute: DW_AT_name
|
||||||
|
Form: DW_FORM_strp
|
||||||
|
- Attribute: DW_AT_language
|
||||||
|
Form: DW_FORM_data2
|
||||||
|
- Attribute: DW_AT_low_pc
|
||||||
|
Form: DW_FORM_addr
|
||||||
|
- Attribute: DW_AT_ranges
|
||||||
|
Form: DW_FORM_sec_offset
|
||||||
|
- Code: 0x00000002
|
||||||
|
Tag: DW_TAG_subprogram
|
||||||
|
Children: DW_CHILDREN_no
|
||||||
|
Attributes:
|
||||||
|
- Attribute: DW_AT_name
|
||||||
|
Form: DW_FORM_strp
|
||||||
|
- Attribute: DW_AT_low_pc
|
||||||
|
Form: DW_FORM_addr
|
||||||
|
- Attribute: DW_AT_high_pc
|
||||||
|
Form: DW_FORM_data4
|
||||||
|
- Code: 0x00000003
|
||||||
|
Tag: DW_TAG_subprogram
|
||||||
|
Children: DW_CHILDREN_no
|
||||||
|
Attributes:
|
||||||
|
- Attribute: DW_AT_name
|
||||||
|
Form: DW_FORM_strp
|
||||||
|
- Attribute: DW_AT_low_pc
|
||||||
|
Form: DW_FORM_addr
|
||||||
|
- Attribute: DW_AT_high_pc
|
||||||
|
Form: DW_FORM_addr
|
||||||
|
debug_ranges:
|
||||||
|
- Offset: 0x00000000
|
||||||
|
AddrSize: 0x08
|
||||||
|
Entries:
|
||||||
|
- LowOffset: 0x0000000000002000
|
||||||
|
HighOffset: 0x0000000000003000
|
||||||
|
- LowOffset: 0x0000000000000000
|
||||||
|
HighOffset: 0x0000000000000020
|
||||||
|
- LowOffset: 0x0000000000000000
|
||||||
|
HighOffset: 0x0000000000000030
|
||||||
|
- LowOffset: 0x0000000000001000
|
||||||
|
HighOffset: 0x0000000000002000
|
||||||
|
debug_info:
|
||||||
|
- Length:
|
||||||
|
TotalLength: 99
|
||||||
|
Version: 4
|
||||||
|
AbbrOffset: 0
|
||||||
|
AddrSize: 8
|
||||||
|
Entries:
|
||||||
|
- AbbrCode: 0x00000001
|
||||||
|
Values:
|
||||||
|
- Value: 0x0000000000000001
|
||||||
|
- Value: 0x0000000000000002
|
||||||
|
- Value: 0x0000000000000000
|
||||||
|
- Value: 0x0000000000000000
|
||||||
|
- AbbrCode: 0x00000002
|
||||||
|
Values:
|
||||||
|
- Value: 0x000000000000000D
|
||||||
|
- Value: 0x0000000000000000
|
||||||
|
- Value: 0x0000000000000020
|
||||||
|
- AbbrCode: 0x00000003
|
||||||
|
Values:
|
||||||
|
- Value: 0x0000000000000017
|
||||||
|
- Value: 0x0000000000000000
|
||||||
|
- Value: 0x0000000000000030
|
||||||
|
- AbbrCode: 0x00000002
|
||||||
|
Values:
|
||||||
|
- Value: 0x0000000000000021
|
||||||
|
- Value: 0x0000000000001000
|
||||||
|
- Value: 0x0000000000001000
|
||||||
|
- AbbrCode: 0x00000002
|
||||||
|
Values:
|
||||||
|
- Value: 0x0000000000000026
|
||||||
|
- Value: 0x0000000000002000
|
||||||
|
- Value: 0x0000000000001000
|
||||||
|
- AbbrCode: 0x00000000
|
||||||
|
Values: []
|
||||||
|
...
|
Loading…
Reference in New Issue
Block a user