Use llvm for dumping DWARF expressions

Summary:
It uses the new ability of ABI plugins to vend llvm::MCRegisterInfo
structs (which is what is needed to turn dwarf register numbers into
strings).

Reviewers: JDevlieghere, aprantl, jasonmolenda

Subscribers: tatyana-krasnukha, lldb-commits

Differential Revision: https://reviews.llvm.org/D67966

llvm-svn: 373208
This commit is contained in:
Pavel Labath 2019-09-30 13:44:17 +00:00
parent ab11b9188d
commit 6f23a68a84
7 changed files with 17 additions and 413 deletions

View File

@ -14,6 +14,7 @@
#include "lldb/lldb-forward.h"
#include "lldb/lldb-types.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/DataExtractor.h"
#include <cassert>
#include <stdint.h>
@ -995,6 +996,11 @@ public:
return {GetDataStart(), size_t(GetByteSize())};
}
llvm::DataExtractor GetAsLLVM() const {
return {GetData(), GetByteOrder() == lldb::eByteOrderLittle,
uint8_t(GetAddressByteSize())};
}
protected:
// Member variables
const uint8_t *m_start; ///< A pointer to the first byte of data.

View File

@ -9,12 +9,12 @@
# RUN: | FileCheck %s
# CHECK-LABEL: image lookup -v -a 0
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = rdi,
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg5 RDI,
# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = ,
# CHECK: Variable: {{.*}}, name = "x2", type = "int", location = ,
# CHECK-LABEL: image lookup -v -a 2
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = rax,
# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg0 RAX,
# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = ,
# CHECK: Variable: {{.*}}, name = "x2", type = "int", location = ,

View File

@ -7,7 +7,7 @@
# RUN: lldb-test symbols %t | FileCheck %s
# CHECK: Variable{0x7fffffff00000011}, name = "color"
# CHECK-SAME: location = DW_OP_addrx(0x0)
# CHECK-SAME: location = DW_OP_addrx 0x0
.text
.section .debug_str,"MS",@progbits,1

View File

@ -88,413 +88,10 @@ void DWARFExpression::DumpLocation(Stream *s, lldb::offset_t offset,
lldb::offset_t length,
lldb::DescriptionLevel level,
ABI *abi) const {
if (!m_data.ValidOffsetForDataOfSize(offset, length))
return;
const lldb::offset_t start_offset = offset;
const lldb::offset_t end_offset = offset + length;
// An operation within a DWARF expression may contain a sub-expression. The
// motivating example for this is DW_OP_entry_value. Keep track of where each
// each sub-expression ends.
std::vector<lldb::offset_t> ends_of_subexprs;
// "Finish" (i.e. print the closing right-parens) for sub-expressions up to
// the specified \p op_offset.
auto finish_subexpressions_to = [&](const lldb::offset_t op_offset) {
while (!ends_of_subexprs.empty() && op_offset >= ends_of_subexprs.back()) {
ends_of_subexprs.pop_back();
s->Printf(")");
if (!ends_of_subexprs.empty())
s->Printf(" ");
}
};
while (m_data.ValidOffset(offset) && offset < end_offset) {
const lldb::offset_t op_offset = offset;
const uint8_t op = m_data.GetU8(&offset);
finish_subexpressions_to(op_offset);
switch (level) {
default:
break;
case lldb::eDescriptionLevelBrief:
if (op_offset > start_offset)
s->PutChar(' ');
break;
case lldb::eDescriptionLevelFull:
case lldb::eDescriptionLevelVerbose:
if (op_offset > start_offset)
s->EOL();
s->Indent();
if (level == lldb::eDescriptionLevelFull)
break;
// Fall through for verbose and print offset and DW_OP prefix..
s->Printf("0x%8.8" PRIx64 ": %s", op_offset,
op >= DW_OP_APPLE_uninit ? "DW_OP_APPLE_" : "DW_OP_");
break;
}
switch (op) {
case DW_OP_addr:
*s << "DW_OP_addr(" << m_data.GetAddress(&offset) << ") ";
break; // 0x03 1 address
case DW_OP_deref:
*s << "DW_OP_deref";
break; // 0x06
case DW_OP_const1u:
s->Printf("DW_OP_const1u(0x%2.2x)", m_data.GetU8(&offset));
break; // 0x08 1 1-byte constant
case DW_OP_const1s:
s->Printf("DW_OP_const1s(0x%2.2x)", m_data.GetU8(&offset));
break; // 0x09 1 1-byte constant
case DW_OP_const2u:
s->Printf("DW_OP_const2u(0x%4.4x)", m_data.GetU16(&offset));
break; // 0x0a 1 2-byte constant
case DW_OP_const2s:
s->Printf("DW_OP_const2s(0x%4.4x)", m_data.GetU16(&offset));
break; // 0x0b 1 2-byte constant
case DW_OP_const4u:
s->Printf("DW_OP_const4u(0x%8.8x)", m_data.GetU32(&offset));
break; // 0x0c 1 4-byte constant
case DW_OP_const4s:
s->Printf("DW_OP_const4s(0x%8.8x)", m_data.GetU32(&offset));
break; // 0x0d 1 4-byte constant
case DW_OP_const8u:
s->Printf("DW_OP_const8u(0x%16.16" PRIx64 ")", m_data.GetU64(&offset));
break; // 0x0e 1 8-byte constant
case DW_OP_const8s:
s->Printf("DW_OP_const8s(0x%16.16" PRIx64 ")", m_data.GetU64(&offset));
break; // 0x0f 1 8-byte constant
case DW_OP_constu:
s->Printf("DW_OP_constu(0x%" PRIx64 ")", m_data.GetULEB128(&offset));
break; // 0x10 1 ULEB128 constant
case DW_OP_consts:
s->Printf("DW_OP_consts(0x%" PRId64 ")", m_data.GetSLEB128(&offset));
break; // 0x11 1 SLEB128 constant
case DW_OP_dup:
s->PutCString("DW_OP_dup");
break; // 0x12
case DW_OP_drop:
s->PutCString("DW_OP_drop");
break; // 0x13
case DW_OP_over:
s->PutCString("DW_OP_over");
break; // 0x14
case DW_OP_pick:
s->Printf("DW_OP_pick(0x%2.2x)", m_data.GetU8(&offset));
break; // 0x15 1 1-byte stack index
case DW_OP_swap:
s->PutCString("DW_OP_swap");
break; // 0x16
case DW_OP_rot:
s->PutCString("DW_OP_rot");
break; // 0x17
case DW_OP_xderef:
s->PutCString("DW_OP_xderef");
break; // 0x18
case DW_OP_abs:
s->PutCString("DW_OP_abs");
break; // 0x19
case DW_OP_and:
s->PutCString("DW_OP_and");
break; // 0x1a
case DW_OP_div:
s->PutCString("DW_OP_div");
break; // 0x1b
case DW_OP_minus:
s->PutCString("DW_OP_minus");
break; // 0x1c
case DW_OP_mod:
s->PutCString("DW_OP_mod");
break; // 0x1d
case DW_OP_mul:
s->PutCString("DW_OP_mul");
break; // 0x1e
case DW_OP_neg:
s->PutCString("DW_OP_neg");
break; // 0x1f
case DW_OP_not:
s->PutCString("DW_OP_not");
break; // 0x20
case DW_OP_or:
s->PutCString("DW_OP_or");
break; // 0x21
case DW_OP_plus:
s->PutCString("DW_OP_plus");
break; // 0x22
case DW_OP_plus_uconst: // 0x23 1 ULEB128 addend
s->Printf("DW_OP_plus_uconst(0x%" PRIx64 ")",
m_data.GetULEB128(&offset));
break;
case DW_OP_shl:
s->PutCString("DW_OP_shl");
break; // 0x24
case DW_OP_shr:
s->PutCString("DW_OP_shr");
break; // 0x25
case DW_OP_shra:
s->PutCString("DW_OP_shra");
break; // 0x26
case DW_OP_xor:
s->PutCString("DW_OP_xor");
break; // 0x27
case DW_OP_skip:
s->Printf("DW_OP_skip(0x%4.4x)", m_data.GetU16(&offset));
break; // 0x2f 1 signed 2-byte constant
case DW_OP_bra:
s->Printf("DW_OP_bra(0x%4.4x)", m_data.GetU16(&offset));
break; // 0x28 1 signed 2-byte constant
case DW_OP_eq:
s->PutCString("DW_OP_eq");
break; // 0x29
case DW_OP_ge:
s->PutCString("DW_OP_ge");
break; // 0x2a
case DW_OP_gt:
s->PutCString("DW_OP_gt");
break; // 0x2b
case DW_OP_le:
s->PutCString("DW_OP_le");
break; // 0x2c
case DW_OP_lt:
s->PutCString("DW_OP_lt");
break; // 0x2d
case DW_OP_ne:
s->PutCString("DW_OP_ne");
break; // 0x2e
case DW_OP_lit0: // 0x30
case DW_OP_lit1: // 0x31
case DW_OP_lit2: // 0x32
case DW_OP_lit3: // 0x33
case DW_OP_lit4: // 0x34
case DW_OP_lit5: // 0x35
case DW_OP_lit6: // 0x36
case DW_OP_lit7: // 0x37
case DW_OP_lit8: // 0x38
case DW_OP_lit9: // 0x39
case DW_OP_lit10: // 0x3A
case DW_OP_lit11: // 0x3B
case DW_OP_lit12: // 0x3C
case DW_OP_lit13: // 0x3D
case DW_OP_lit14: // 0x3E
case DW_OP_lit15: // 0x3F
case DW_OP_lit16: // 0x40
case DW_OP_lit17: // 0x41
case DW_OP_lit18: // 0x42
case DW_OP_lit19: // 0x43
case DW_OP_lit20: // 0x44
case DW_OP_lit21: // 0x45
case DW_OP_lit22: // 0x46
case DW_OP_lit23: // 0x47
case DW_OP_lit24: // 0x48
case DW_OP_lit25: // 0x49
case DW_OP_lit26: // 0x4A
case DW_OP_lit27: // 0x4B
case DW_OP_lit28: // 0x4C
case DW_OP_lit29: // 0x4D
case DW_OP_lit30: // 0x4E
case DW_OP_lit31:
s->Printf("DW_OP_lit%i", op - DW_OP_lit0);
break; // 0x4f
case DW_OP_reg0: // 0x50
case DW_OP_reg1: // 0x51
case DW_OP_reg2: // 0x52
case DW_OP_reg3: // 0x53
case DW_OP_reg4: // 0x54
case DW_OP_reg5: // 0x55
case DW_OP_reg6: // 0x56
case DW_OP_reg7: // 0x57
case DW_OP_reg8: // 0x58
case DW_OP_reg9: // 0x59
case DW_OP_reg10: // 0x5A
case DW_OP_reg11: // 0x5B
case DW_OP_reg12: // 0x5C
case DW_OP_reg13: // 0x5D
case DW_OP_reg14: // 0x5E
case DW_OP_reg15: // 0x5F
case DW_OP_reg16: // 0x60
case DW_OP_reg17: // 0x61
case DW_OP_reg18: // 0x62
case DW_OP_reg19: // 0x63
case DW_OP_reg20: // 0x64
case DW_OP_reg21: // 0x65
case DW_OP_reg22: // 0x66
case DW_OP_reg23: // 0x67
case DW_OP_reg24: // 0x68
case DW_OP_reg25: // 0x69
case DW_OP_reg26: // 0x6A
case DW_OP_reg27: // 0x6B
case DW_OP_reg28: // 0x6C
case DW_OP_reg29: // 0x6D
case DW_OP_reg30: // 0x6E
case DW_OP_reg31: // 0x6F
{
uint32_t reg_num = op - DW_OP_reg0;
if (abi) {
RegisterInfo reg_info;
if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) {
if (reg_info.name) {
s->PutCString(reg_info.name);
break;
} else if (reg_info.alt_name) {
s->PutCString(reg_info.alt_name);
break;
}
}
}
s->Printf("DW_OP_reg%u", reg_num);
break;
} break;
case DW_OP_breg0:
case DW_OP_breg1:
case DW_OP_breg2:
case DW_OP_breg3:
case DW_OP_breg4:
case DW_OP_breg5:
case DW_OP_breg6:
case DW_OP_breg7:
case DW_OP_breg8:
case DW_OP_breg9:
case DW_OP_breg10:
case DW_OP_breg11:
case DW_OP_breg12:
case DW_OP_breg13:
case DW_OP_breg14:
case DW_OP_breg15:
case DW_OP_breg16:
case DW_OP_breg17:
case DW_OP_breg18:
case DW_OP_breg19:
case DW_OP_breg20:
case DW_OP_breg21:
case DW_OP_breg22:
case DW_OP_breg23:
case DW_OP_breg24:
case DW_OP_breg25:
case DW_OP_breg26:
case DW_OP_breg27:
case DW_OP_breg28:
case DW_OP_breg29:
case DW_OP_breg30:
case DW_OP_breg31: {
uint32_t reg_num = op - DW_OP_breg0;
int64_t reg_offset = m_data.GetSLEB128(&offset);
if (abi) {
RegisterInfo reg_info;
if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) {
if (reg_info.name) {
s->Printf("[%s%+" PRIi64 "]", reg_info.name, reg_offset);
break;
} else if (reg_info.alt_name) {
s->Printf("[%s%+" PRIi64 "]", reg_info.alt_name, reg_offset);
break;
}
}
}
s->Printf("DW_OP_breg%i(0x%" PRIx64 ")", reg_num, reg_offset);
} break;
case DW_OP_regx: // 0x90 1 ULEB128 register
{
uint32_t reg_num = m_data.GetULEB128(&offset);
if (abi) {
RegisterInfo reg_info;
if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) {
if (reg_info.name) {
s->PutCString(reg_info.name);
break;
} else if (reg_info.alt_name) {
s->PutCString(reg_info.alt_name);
break;
}
}
}
s->Printf("DW_OP_regx(%" PRIu32 ")", reg_num);
break;
} break;
case DW_OP_fbreg: // 0x91 1 SLEB128 offset
s->Printf("DW_OP_fbreg(%" PRIi64 ")", m_data.GetSLEB128(&offset));
break;
case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset
{
uint32_t reg_num = m_data.GetULEB128(&offset);
int64_t reg_offset = m_data.GetSLEB128(&offset);
if (abi) {
RegisterInfo reg_info;
if (abi->GetRegisterInfoByKind(m_reg_kind, reg_num, reg_info)) {
if (reg_info.name) {
s->Printf("[%s%+" PRIi64 "]", reg_info.name, reg_offset);
break;
} else if (reg_info.alt_name) {
s->Printf("[%s%+" PRIi64 "]", reg_info.alt_name, reg_offset);
break;
}
}
}
s->Printf("DW_OP_bregx(reg=%" PRIu32 ",offset=%" PRIi64 ")", reg_num,
reg_offset);
} break;
case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed
s->Printf("DW_OP_piece(0x%" PRIx64 ")", m_data.GetULEB128(&offset));
break;
case DW_OP_deref_size: // 0x94 1 1-byte size of data retrieved
s->Printf("DW_OP_deref_size(0x%2.2x)", m_data.GetU8(&offset));
break;
case DW_OP_xderef_size: // 0x95 1 1-byte size of data retrieved
s->Printf("DW_OP_xderef_size(0x%2.2x)", m_data.GetU8(&offset));
break;
case DW_OP_nop:
s->PutCString("DW_OP_nop");
break; // 0x96
case DW_OP_push_object_address:
s->PutCString("DW_OP_push_object_address");
break; // 0x97 DWARF3
case DW_OP_call2: // 0x98 DWARF3 1 2-byte offset of DIE
s->Printf("DW_OP_call2(0x%4.4x)", m_data.GetU16(&offset));
break;
case DW_OP_call4: // 0x99 DWARF3 1 4-byte offset of DIE
s->Printf("DW_OP_call4(0x%8.8x)", m_data.GetU32(&offset));
break;
case DW_OP_call_ref: // 0x9a DWARF3 1 4- or 8-byte offset of DIE
s->Printf("DW_OP_call_ref(0x%8.8" PRIx64 ")", m_data.GetAddress(&offset));
break;
case DW_OP_form_tls_address:
s->PutCString("DW_OP_form_tls_address"); // 0x9b
break;
case DW_OP_GNU_addr_index: // 0xfb
s->Printf("DW_OP_GNU_addr_index(0x%" PRIx64 ")",
m_data.GetULEB128(&offset));
break;
case DW_OP_addrx:
s->Printf("DW_OP_addrx(0x%" PRIx64 ")",
m_data.GetULEB128(&offset));
break;
case DW_OP_GNU_const_index: // 0xfc
s->Printf("DW_OP_GNU_const_index(0x%" PRIx64 ")",
m_data.GetULEB128(&offset));
break;
case DW_OP_GNU_push_tls_address:
s->PutCString("DW_OP_GNU_push_tls_address"); // 0xe0
break;
case DW_OP_APPLE_uninit:
s->PutCString("DW_OP_APPLE_uninit"); // 0xF0
break;
case DW_OP_entry_value: {
uint32_t subexpr_len = m_data.GetULEB128(&offset);
s->PutCString("DW_OP_entry_value(");
ends_of_subexprs.push_back(offset + subexpr_len);
break;
}
}
}
finish_subexpressions_to(end_offset);
llvm::DWARFExpression(DataExtractor(m_data, offset, length).GetAsLLVM(),
llvm::dwarf::DWARF_VERSION, m_data.GetAddressByteSize())
.print(s->AsRawOstream(), abi ? &abi->GetMCRegisterInfo() : nullptr,
nullptr);
}
void DWARFExpression::SetLocationListSlide(addr_t slide) {

View File

@ -86,7 +86,6 @@
#include "llvm/Support/raw_ostream.h"
#define DEBUGSERVER_BASENAME "debugserver"
using namespace llvm;
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;

View File

@ -103,8 +103,8 @@
using namespace lldb;
using namespace lldb_private;
using namespace llvm;
using namespace clang;
using llvm::StringSwitch;
namespace {
#ifdef LLDB_CONFIGURATION_DEBUG

View File

@ -16,7 +16,9 @@
#include "llvm/Testing/Support/Error.h"
using namespace lldb_private;
using namespace llvm;
using llvm::APInt;
using llvm::Failed;
using llvm::Succeeded;
template <typename T>
bool checkInequality(T c1, T c2) {