mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-27 21:50:29 +00:00
DWARF: Fix a regression in location list dumping
Summary: While fixing the handling of some error cases, r370363 introduced new problems -- assertion failures due to unchecked errors (my excuse is that a very early version of that patch used Optional<T> instead of Expected). This patch adds proper handling of parsing errors encountered when dumping location lists from inside DWARF DIEs, and adds a bunch of additional tests. I reorder the arguments of the location list dumping functions to make them consistent, and also be able to dump the two kinds of location lists generically. Reviewers: JDevlieghere, dblaikie, probinson Subscribers: aprantl, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67102 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@370868 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
95f6d02cc9
commit
7c8f17874e
@ -40,8 +40,8 @@ public:
|
||||
/// All the locations in which the variable is stored.
|
||||
SmallVector<Entry, 2> Entries;
|
||||
/// Dump this list on OS.
|
||||
void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize,
|
||||
const MCRegisterInfo *MRI, DWARFUnit *U, uint64_t BaseAddress,
|
||||
void dump(raw_ostream &OS, uint64_t BaseAddress, bool IsLittleEndian,
|
||||
unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U,
|
||||
unsigned Indent) const;
|
||||
};
|
||||
|
||||
|
@ -35,11 +35,10 @@ static void dumpExpression(raw_ostream &OS, ArrayRef<uint8_t> Data,
|
||||
DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI, U);
|
||||
}
|
||||
|
||||
void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
|
||||
void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, uint64_t BaseAddress,
|
||||
bool IsLittleEndian,
|
||||
unsigned AddressSize,
|
||||
const MCRegisterInfo *MRI,
|
||||
DWARFUnit *U,
|
||||
uint64_t BaseAddress,
|
||||
const MCRegisterInfo *MRI, DWARFUnit *U,
|
||||
unsigned Indent) const {
|
||||
for (const Entry &E : Entries) {
|
||||
OS << '\n';
|
||||
@ -67,7 +66,7 @@ void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
|
||||
Optional<uint64_t> Offset) const {
|
||||
auto DumpLocationList = [&](const LocationList &L) {
|
||||
OS << format("0x%8.8" PRIx64 ": ", L.Offset);
|
||||
L.dump(OS, IsLittleEndian, AddressSize, MRI, nullptr, 0, 12);
|
||||
L.dump(OS, 0, IsLittleEndian, AddressSize, MRI, nullptr, 12);
|
||||
OS << "\n\n";
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/FormatAdapters.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/WithColor.h"
|
||||
@ -91,21 +92,27 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
|
||||
}
|
||||
|
||||
FormValue.dump(OS, DumpOpts);
|
||||
const auto &DumpLL = [&](auto ExpectedLL) {
|
||||
if (ExpectedLL) {
|
||||
uint64_t BaseAddr = 0;
|
||||
if (Optional<object::SectionedAddress> BA = U->getBaseAddress())
|
||||
BaseAddr = BA->Address;
|
||||
ExpectedLL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(),
|
||||
MRI, U, Indent);
|
||||
} else {
|
||||
OS << '\n';
|
||||
OS.indent(Indent);
|
||||
OS << formatv("error extracting location list: {0}",
|
||||
fmt_consume(ExpectedLL.takeError()));
|
||||
}
|
||||
};
|
||||
if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
|
||||
uint64_t Offset = *FormValue.getAsSectionOffset();
|
||||
if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()) {
|
||||
DWARFDebugLoc DebugLoc;
|
||||
DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(),
|
||||
Obj.getAddressSize());
|
||||
auto LL = DebugLoc.parseOneLocationList(Data, &Offset);
|
||||
if (LL) {
|
||||
uint64_t BaseAddr = 0;
|
||||
if (Optional<object::SectionedAddress> BA = U->getBaseAddress())
|
||||
BaseAddr = BA->Address;
|
||||
LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U,
|
||||
BaseAddr, Indent);
|
||||
} else
|
||||
OS << "error extracting location list.";
|
||||
DumpLL(DebugLoc.parseOneLocationList(Data, &Offset));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -121,18 +128,8 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
|
||||
// Modern locations list (.debug_loclists) are used starting from v5.
|
||||
// Ideally we should take the version from the .debug_loclists section
|
||||
// header, but using CU's version for simplicity.
|
||||
auto LL = DWARFDebugLoclists::parseOneLocationList(
|
||||
Data, &Offset, UseLocLists ? U->getVersion() : 4);
|
||||
|
||||
uint64_t BaseAddr = 0;
|
||||
if (Optional<object::SectionedAddress> BA = U->getBaseAddress())
|
||||
BaseAddr = BA->Address;
|
||||
|
||||
if (LL)
|
||||
LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI,
|
||||
U, Indent);
|
||||
else
|
||||
OS << "error extracting location list.";
|
||||
DumpLL(DWARFDebugLoclists::parseOneLocationList(
|
||||
Data, &Offset, UseLocLists ? U->getVersion() : 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
121
test/DebugInfo/X86/dwarfdump-debug-loc-error-cases2.s
Normal file
121
test/DebugInfo/X86/dwarfdump-debug-loc-error-cases2.s
Normal file
@ -0,0 +1,121 @@
|
||||
# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t
|
||||
# RUN: llvm-dwarfdump %t | FileCheck %s
|
||||
|
||||
# CHECK: DW_AT_name ("x0")
|
||||
# CHECK-NEXT: DW_AT_location (0x00000000
|
||||
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000002): DW_OP_reg5 RDI
|
||||
# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg0 RAX)
|
||||
|
||||
# CHECK: DW_AT_name ("x1")
|
||||
# CHECK-NEXT: DW_AT_location (0xdeadbeef
|
||||
# CHECK-NEXT: error extracting location list: unexpected end of data)
|
||||
|
||||
# CHECK: DW_AT_name ("x2")
|
||||
# CHECK-NEXT: DW_AT_location (0x00000036
|
||||
# CHECK-NEXT: error extracting location list: unexpected end of data)
|
||||
|
||||
|
||||
.type f,@function
|
||||
f: # @f
|
||||
.Lfunc_begin0:
|
||||
movl %edi, %eax
|
||||
.Ltmp0:
|
||||
retq
|
||||
.Ltmp1:
|
||||
.Lfunc_end0:
|
||||
.size f, .Lfunc_end0-f
|
||||
|
||||
.section .debug_str,"MS",@progbits,1
|
||||
.Linfo_string0:
|
||||
.asciz "Hand-written DWARF"
|
||||
.Linfo_string3:
|
||||
.asciz "f"
|
||||
.Linfo_string4:
|
||||
.asciz "int"
|
||||
.Lx0:
|
||||
.asciz "x0"
|
||||
.Lx1:
|
||||
.asciz "x1"
|
||||
.Lx2:
|
||||
.asciz "x2"
|
||||
|
||||
.section .debug_loc,"",@progbits
|
||||
.Ldebug_loc0:
|
||||
.quad .Lfunc_begin0-.Lfunc_begin0
|
||||
.quad .Ltmp0-.Lfunc_begin0
|
||||
.short 1 # Loc expr size
|
||||
.byte 85 # super-register DW_OP_reg5
|
||||
.quad .Ltmp0-.Lfunc_begin0
|
||||
.quad .Lfunc_end0-.Lfunc_begin0
|
||||
.short 1 # Loc expr size
|
||||
.byte 80 # super-register DW_OP_reg0
|
||||
.quad 0
|
||||
.quad 0
|
||||
.Ldebug_loc2:
|
||||
.quad .Lfunc_begin0-.Lfunc_begin0
|
||||
.quad .Lfunc_end0-.Lfunc_begin0
|
||||
.short 0xdead # Loc expr size
|
||||
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.byte 1 # Abbreviation Code
|
||||
.byte 17 # DW_TAG_compile_unit
|
||||
.byte 1 # DW_CHILDREN_yes
|
||||
.byte 37 # DW_AT_producer
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 19 # DW_AT_language
|
||||
.byte 5 # DW_FORM_data2
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 2 # Abbreviation Code
|
||||
.byte 46 # DW_TAG_subprogram
|
||||
.byte 1 # DW_CHILDREN_yes
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 3 # Abbreviation Code
|
||||
.byte 5 # DW_TAG_formal_parameter
|
||||
.byte 0 # DW_CHILDREN_no
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 2 # DW_AT_location
|
||||
.byte 23 # DW_FORM_sec_offset
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 4 # Abbreviation Code
|
||||
.byte 36 # DW_TAG_base_type
|
||||
.byte 0 # DW_CHILDREN_no
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 62 # DW_AT_encoding
|
||||
.byte 11 # DW_FORM_data1
|
||||
.byte 11 # DW_AT_byte_size
|
||||
.byte 11 # DW_FORM_data1
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 0 # EOM(3)
|
||||
|
||||
.section .debug_info,"",@progbits
|
||||
.Lcu_begin0:
|
||||
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
|
||||
.Ldebug_info_start0:
|
||||
.short 4 # DWARF version number
|
||||
.long .debug_abbrev # Offset Into Abbrev. Section
|
||||
.byte 8 # Address Size (in bytes)
|
||||
.byte 1 # Abbrev [1] 0xb:0x50 DW_TAG_compile_unit
|
||||
.long .Linfo_string0 # DW_AT_producer
|
||||
.short 12 # DW_AT_language
|
||||
.byte 2 # Abbrev [2] 0x2a:0x29 DW_TAG_subprogram
|
||||
.long .Linfo_string3 # DW_AT_name
|
||||
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
|
||||
.long .Lx0 # DW_AT_name
|
||||
.long .Ldebug_loc0 # DW_AT_location
|
||||
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
|
||||
.long .Lx1 # DW_AT_name
|
||||
.long 0xdeadbeef # DW_AT_location
|
||||
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
|
||||
.long .Lx2 # DW_AT_name
|
||||
.long .Ldebug_loc2 # DW_AT_location
|
||||
.byte 0 # End Of Children Mark
|
||||
.byte 0 # End Of Children Mark
|
||||
.Ldebug_info_end0:
|
132
test/DebugInfo/X86/dwarfdump-debug-loclists-error-cases2.s
Normal file
132
test/DebugInfo/X86/dwarfdump-debug-loclists-error-cases2.s
Normal file
@ -0,0 +1,132 @@
|
||||
# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t
|
||||
# RUN: llvm-dwarfdump %t | FileCheck %s
|
||||
|
||||
# CHECK: DW_AT_name ("x0")
|
||||
# CHECK-NEXT: DW_AT_location (0x0000000c
|
||||
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000002): DW_OP_reg5 RDI
|
||||
# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg0 RAX)
|
||||
|
||||
# CHECK: DW_AT_name ("x1")
|
||||
# CHECK-NEXT: DW_AT_location (0xdeadbeef
|
||||
# CHECK-NEXT: error extracting location list: unexpected end of data)
|
||||
|
||||
# CHECK: DW_AT_name ("x2")
|
||||
# CHECK-NEXT: DW_AT_location (0x00000025
|
||||
# CHECK-NEXT: error extracting location list: unexpected end of data)
|
||||
|
||||
|
||||
.type f,@function
|
||||
f: # @f
|
||||
.Lfunc_begin0:
|
||||
movl %edi, %eax
|
||||
.Ltmp0:
|
||||
retq
|
||||
.Ltmp1:
|
||||
.Lfunc_end0:
|
||||
.size f, .Lfunc_end0-f
|
||||
|
||||
.section .debug_str,"MS",@progbits,1
|
||||
.Linfo_string0:
|
||||
.asciz "Hand-written DWARF"
|
||||
.Linfo_string3:
|
||||
.asciz "f"
|
||||
.Linfo_string4:
|
||||
.asciz "int"
|
||||
.Lx0:
|
||||
.asciz "x0"
|
||||
.Lx1:
|
||||
.asciz "x1"
|
||||
.Lx2:
|
||||
.asciz "x2"
|
||||
|
||||
.section .debug_loclists,"",@progbits
|
||||
.long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 # Length
|
||||
.Ldebug_loclist_table_start0:
|
||||
.short 5 # Version
|
||||
.byte 8 # Address size
|
||||
.byte 0 # Segment selector size
|
||||
.long 0 # Offset entry count
|
||||
.Lloclists_table_base0:
|
||||
.Ldebug_loc0:
|
||||
.byte 8 # DW_LLE_start_length
|
||||
.quad .Lfunc_begin0-.Lfunc_begin0 # starting offset
|
||||
.uleb128 .Ltmp0-.Lfunc_begin0 # size
|
||||
.byte 1 # Loc expr size
|
||||
.byte 85 # super-register DW_OP_reg5
|
||||
.byte 8 # DW_LLE_start_length
|
||||
.quad .Ltmp0-.Lfunc_begin0 # starting offset
|
||||
.uleb128 .Lfunc_end0-.Ltmp0 # size
|
||||
.byte 1 # Loc expr size
|
||||
.byte 80 # super-register DW_OP_reg0
|
||||
.byte 0 # DW_LLE_end_of_list
|
||||
.Ldebug_loc2:
|
||||
.byte 8 # DW_LLE_start_length
|
||||
.quad .Lfunc_begin0-.Lfunc_begin0 # starting offset
|
||||
.uleb128 .Ltmp0-.Lfunc_begin0 # size
|
||||
.uleb128 0xdeadbeef # Loc expr size
|
||||
.Ldebug_loclist_table_end0:
|
||||
|
||||
.section .debug_abbrev,"",@progbits
|
||||
.byte 1 # Abbreviation Code
|
||||
.byte 17 # DW_TAG_compile_unit
|
||||
.byte 1 # DW_CHILDREN_yes
|
||||
.byte 37 # DW_AT_producer
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 19 # DW_AT_language
|
||||
.byte 5 # DW_FORM_data2
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 2 # Abbreviation Code
|
||||
.byte 46 # DW_TAG_subprogram
|
||||
.byte 1 # DW_CHILDREN_yes
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 3 # Abbreviation Code
|
||||
.byte 5 # DW_TAG_formal_parameter
|
||||
.byte 0 # DW_CHILDREN_no
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 2 # DW_AT_location
|
||||
.byte 23 # DW_FORM_sec_offset
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 4 # Abbreviation Code
|
||||
.byte 36 # DW_TAG_base_type
|
||||
.byte 0 # DW_CHILDREN_no
|
||||
.byte 3 # DW_AT_name
|
||||
.byte 14 # DW_FORM_strp
|
||||
.byte 62 # DW_AT_encoding
|
||||
.byte 11 # DW_FORM_data1
|
||||
.byte 11 # DW_AT_byte_size
|
||||
.byte 11 # DW_FORM_data1
|
||||
.byte 0 # EOM(1)
|
||||
.byte 0 # EOM(2)
|
||||
.byte 0 # EOM(3)
|
||||
|
||||
.section .debug_info,"",@progbits
|
||||
.Lcu_begin0:
|
||||
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
|
||||
.Ldebug_info_start0:
|
||||
.short 5 # DWARF version number
|
||||
.byte 1 # DWARF Unit Type
|
||||
.byte 8 # Address Size (in bytes)
|
||||
.long .debug_abbrev # Offset Into Abbrev. Section
|
||||
.byte 1 # Abbrev [1] 0xb:0x50 DW_TAG_compile_unit
|
||||
.long .Linfo_string0 # DW_AT_producer
|
||||
.short 12 # DW_AT_language
|
||||
.byte 2 # Abbrev [2] 0x2a:0x29 DW_TAG_subprogram
|
||||
.long .Linfo_string3 # DW_AT_name
|
||||
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
|
||||
.long .Lx0 # DW_AT_name
|
||||
.long .Ldebug_loc0 # DW_AT_location
|
||||
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
|
||||
.long .Lx1 # DW_AT_name
|
||||
.long 0xdeadbeef # DW_AT_location
|
||||
.byte 3 # Abbrev [3] DW_TAG_formal_parameter
|
||||
.long .Lx2 # DW_AT_name
|
||||
.long .Ldebug_loc2 # DW_AT_location
|
||||
.byte 0 # End Of Children Mark
|
||||
.byte 0 # End Of Children Mark
|
||||
.Ldebug_info_end0:
|
Loading…
Reference in New Issue
Block a user