[lldb] Remove custom DWARF expression printing code

The llvm DWARFExpression dump is nearly identical, but better -- for
example it does print a spurious space after zero-argument expressions.

Some parts of our code (variable locations) have been already switched
to llvm-based expression dumping. This switches the remainder: unwind
plans and some unit tests.
This commit is contained in:
Pavel Labath 2020-05-25 15:59:48 +02:00
parent 46e5c5fe77
commit ba03bcbc4a
14 changed files with 46 additions and 652 deletions

View File

@ -217,14 +217,6 @@ public:
lldb::addr_t func_load_addr, lldb::addr_t address,
ABI *abi);
static bool PrintDWARFExpression(Stream &s, const DataExtractor &data,
int address_size, int dwarf_ref_size,
bool location_expression);
static void PrintDWARFLocationList(Stream &s, const DWARFUnit *cu,
const DataExtractor &debug_loc_data,
lldb::offset_t offset);
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op);
private:

View File

@ -2566,235 +2566,6 @@ bool DWARFExpression::Evaluate(
return true; // Return true on success
}
static bool print_dwarf_exp_op(Stream &s, const DataExtractor &data,
lldb::offset_t *offset_ptr, int address_size,
int dwarf_ref_size) {
uint8_t opcode = data.GetU8(offset_ptr);
DRC_class opcode_class;
uint64_t uint;
int64_t sint;
int size;
opcode_class = DW_OP_value_to_class(opcode) & (~DRC_DWARFv3);
s.Printf("%s ", DW_OP_value_to_name(opcode));
/* Does this take zero parameters? If so we can shortcut this function. */
if (opcode_class == DRC_ZEROOPERANDS)
return true;
if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx) {
uint = data.GetULEB128(offset_ptr);
sint = data.GetSLEB128(offset_ptr);
s.Printf("%" PRIu64 " %" PRIi64, uint, sint);
return true;
}
if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_entry_value) {
uint = data.GetULEB128(offset_ptr);
s.Printf("%" PRIu64 " ", uint);
return true;
}
if (opcode_class != DRC_ONEOPERAND) {
s.Printf("UNKNOWN OP %u", opcode);
return false;
}
switch (opcode) {
case DW_OP_addr:
size = address_size;
break;
case DW_OP_const1u:
size = 1;
break;
case DW_OP_const1s:
size = -1;
break;
case DW_OP_const2u:
size = 2;
break;
case DW_OP_const2s:
size = -2;
break;
case DW_OP_const4u:
size = 4;
break;
case DW_OP_const4s:
size = -4;
break;
case DW_OP_const8u:
size = 8;
break;
case DW_OP_const8s:
size = -8;
break;
case DW_OP_constu:
size = 128;
break;
case DW_OP_consts:
size = -128;
break;
case DW_OP_fbreg:
size = -128;
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:
size = -128;
break;
case DW_OP_pick:
case DW_OP_deref_size:
case DW_OP_xderef_size:
size = 1;
break;
case DW_OP_skip:
case DW_OP_bra:
size = -2;
break;
case DW_OP_call2:
size = 2;
break;
case DW_OP_call4:
size = 4;
break;
case DW_OP_call_ref:
size = dwarf_ref_size;
break;
case DW_OP_addrx:
case DW_OP_piece:
case DW_OP_plus_uconst:
case DW_OP_regx:
case DW_OP_GNU_addr_index:
case DW_OP_GNU_const_index:
case DW_OP_entry_value:
size = 128;
break;
default:
s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
return false;
}
switch (size) {
case -1:
sint = (int8_t)data.GetU8(offset_ptr);
s.Printf("%+" PRIi64, sint);
break;
case -2:
sint = (int16_t)data.GetU16(offset_ptr);
s.Printf("%+" PRIi64, sint);
break;
case -4:
sint = (int32_t)data.GetU32(offset_ptr);
s.Printf("%+" PRIi64, sint);
break;
case -8:
sint = (int64_t)data.GetU64(offset_ptr);
s.Printf("%+" PRIi64, sint);
break;
case -128:
sint = data.GetSLEB128(offset_ptr);
s.Printf("%+" PRIi64, sint);
break;
case 1:
uint = data.GetU8(offset_ptr);
s.Printf("0x%2.2" PRIx64, uint);
break;
case 2:
uint = data.GetU16(offset_ptr);
s.Printf("0x%4.4" PRIx64, uint);
break;
case 4:
uint = data.GetU32(offset_ptr);
s.Printf("0x%8.8" PRIx64, uint);
break;
case 8:
uint = data.GetU64(offset_ptr);
s.Printf("0x%16.16" PRIx64, uint);
break;
case 128:
uint = data.GetULEB128(offset_ptr);
s.Printf("0x%" PRIx64, uint);
break;
}
return true;
}
bool DWARFExpression::PrintDWARFExpression(Stream &s, const DataExtractor &data,
int address_size, int dwarf_ref_size,
bool location_expression) {
int op_count = 0;
lldb::offset_t offset = 0;
while (data.ValidOffset(offset)) {
if (location_expression && op_count > 0)
return false;
if (op_count > 0)
s.PutCString(", ");
if (!print_dwarf_exp_op(s, data, &offset, address_size, dwarf_ref_size))
return false;
op_count++;
}
return true;
}
void DWARFExpression::PrintDWARFLocationList(
Stream &s, const DWARFUnit *cu, const DataExtractor &debug_loc_data,
lldb::offset_t offset) {
uint64_t start_addr, end_addr;
uint32_t addr_size = DWARFUnit::GetAddressByteSize(cu);
s.SetAddressByteSize(DWARFUnit::GetAddressByteSize(cu));
dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
while (debug_loc_data.ValidOffset(offset)) {
start_addr = debug_loc_data.GetMaxU64(&offset, addr_size);
end_addr = debug_loc_data.GetMaxU64(&offset, addr_size);
if (start_addr == 0 && end_addr == 0)
break;
s.PutCString("\n ");
s.Indent();
if (cu)
DumpAddressRange(s.AsRawOstream(), start_addr + base_addr,
end_addr + base_addr, cu->GetAddressByteSize(), nullptr,
": ");
uint32_t loc_length = debug_loc_data.GetU16(&offset);
DataExtractor locationData(debug_loc_data, offset, loc_length);
PrintDWARFExpression(s, locationData, addr_size, 4, false);
offset += loc_length;
}
}
static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc,
ByteOrder byte_order, uint32_t addr_size) {
auto buffer_sp =

View File

@ -58,321 +58,6 @@ const char *DW_OP_value_to_name(uint32_t val) {
return llvmstr.data();
}
DRC_class DW_OP_value_to_class(uint32_t val) {
// FIXME: If we just used llvm's DWARFExpression printer, we could delete
// all this code (and more in lldb's DWARFExpression.cpp).
switch (val) {
case 0x03:
return DRC_ONEOPERAND;
case 0x06:
return DRC_ZEROOPERANDS;
case 0x08:
return DRC_ONEOPERAND;
case 0x09:
return DRC_ONEOPERAND;
case 0x0a:
return DRC_ONEOPERAND;
case 0x0b:
return DRC_ONEOPERAND;
case 0x0c:
return DRC_ONEOPERAND;
case 0x0d:
return DRC_ONEOPERAND;
case 0x0e:
return DRC_ONEOPERAND;
case 0x0f:
return DRC_ONEOPERAND;
case 0x10:
return DRC_ONEOPERAND;
case 0x11:
return DRC_ONEOPERAND;
case 0x12:
return DRC_ZEROOPERANDS;
case 0x13:
return DRC_ZEROOPERANDS;
case 0x14:
return DRC_ZEROOPERANDS;
case 0x15:
return DRC_ONEOPERAND;
case 0x16:
return DRC_ZEROOPERANDS;
case 0x17:
return DRC_ZEROOPERANDS;
case 0x18:
return DRC_ZEROOPERANDS;
case 0x19:
return DRC_ZEROOPERANDS;
case 0x1a:
return DRC_ZEROOPERANDS;
case 0x1b:
return DRC_ZEROOPERANDS;
case 0x1c:
return DRC_ZEROOPERANDS;
case 0x1d:
return DRC_ZEROOPERANDS;
case 0x1e:
return DRC_ZEROOPERANDS;
case 0x1f:
return DRC_ZEROOPERANDS;
case 0x20:
return DRC_ZEROOPERANDS;
case 0x21:
return DRC_ZEROOPERANDS;
case 0x22:
return DRC_ZEROOPERANDS;
case 0x23:
return DRC_ONEOPERAND;
case 0x24:
return DRC_ZEROOPERANDS;
case 0x25:
return DRC_ZEROOPERANDS;
case 0x26:
return DRC_ZEROOPERANDS;
case 0x27:
return DRC_ZEROOPERANDS;
case 0x2f:
return DRC_ONEOPERAND;
case 0x28:
return DRC_ONEOPERAND;
case 0x29:
return DRC_ZEROOPERANDS;
case 0x2a:
return DRC_ZEROOPERANDS;
case 0x2b:
return DRC_ZEROOPERANDS;
case 0x2c:
return DRC_ZEROOPERANDS;
case 0x2d:
return DRC_ZEROOPERANDS;
case 0x2e:
return DRC_ZEROOPERANDS;
case 0x30:
return DRC_ZEROOPERANDS;
case 0x31:
return DRC_ZEROOPERANDS;
case 0x32:
return DRC_ZEROOPERANDS;
case 0x33:
return DRC_ZEROOPERANDS;
case 0x34:
return DRC_ZEROOPERANDS;
case 0x35:
return DRC_ZEROOPERANDS;
case 0x36:
return DRC_ZEROOPERANDS;
case 0x37:
return DRC_ZEROOPERANDS;
case 0x38:
return DRC_ZEROOPERANDS;
case 0x39:
return DRC_ZEROOPERANDS;
case 0x3a:
return DRC_ZEROOPERANDS;
case 0x3b:
return DRC_ZEROOPERANDS;
case 0x3c:
return DRC_ZEROOPERANDS;
case 0x3d:
return DRC_ZEROOPERANDS;
case 0x3e:
return DRC_ZEROOPERANDS;
case 0x3f:
return DRC_ZEROOPERANDS;
case 0x40:
return DRC_ZEROOPERANDS;
case 0x41:
return DRC_ZEROOPERANDS;
case 0x42:
return DRC_ZEROOPERANDS;
case 0x43:
return DRC_ZEROOPERANDS;
case 0x44:
return DRC_ZEROOPERANDS;
case 0x45:
return DRC_ZEROOPERANDS;
case 0x46:
return DRC_ZEROOPERANDS;
case 0x47:
return DRC_ZEROOPERANDS;
case 0x48:
return DRC_ZEROOPERANDS;
case 0x49:
return DRC_ZEROOPERANDS;
case 0x4a:
return DRC_ZEROOPERANDS;
case 0x4b:
return DRC_ZEROOPERANDS;
case 0x4c:
return DRC_ZEROOPERANDS;
case 0x4d:
return DRC_ZEROOPERANDS;
case 0x4e:
return DRC_ZEROOPERANDS;
case 0x4f:
return DRC_ZEROOPERANDS;
case 0x50:
return DRC_ZEROOPERANDS;
case 0x51:
return DRC_ZEROOPERANDS;
case 0x52:
return DRC_ZEROOPERANDS;
case 0x53:
return DRC_ZEROOPERANDS;
case 0x54:
return DRC_ZEROOPERANDS;
case 0x55:
return DRC_ZEROOPERANDS;
case 0x56:
return DRC_ZEROOPERANDS;
case 0x57:
return DRC_ZEROOPERANDS;
case 0x58:
return DRC_ZEROOPERANDS;
case 0x59:
return DRC_ZEROOPERANDS;
case 0x5a:
return DRC_ZEROOPERANDS;
case 0x5b:
return DRC_ZEROOPERANDS;
case 0x5c:
return DRC_ZEROOPERANDS;
case 0x5d:
return DRC_ZEROOPERANDS;
case 0x5e:
return DRC_ZEROOPERANDS;
case 0x5f:
return DRC_ZEROOPERANDS;
case 0x60:
return DRC_ZEROOPERANDS;
case 0x61:
return DRC_ZEROOPERANDS;
case 0x62:
return DRC_ZEROOPERANDS;
case 0x63:
return DRC_ZEROOPERANDS;
case 0x64:
return DRC_ZEROOPERANDS;
case 0x65:
return DRC_ZEROOPERANDS;
case 0x66:
return DRC_ZEROOPERANDS;
case 0x67:
return DRC_ZEROOPERANDS;
case 0x68:
return DRC_ZEROOPERANDS;
case 0x69:
return DRC_ZEROOPERANDS;
case 0x6a:
return DRC_ZEROOPERANDS;
case 0x6b:
return DRC_ZEROOPERANDS;
case 0x6c:
return DRC_ZEROOPERANDS;
case 0x6d:
return DRC_ZEROOPERANDS;
case 0x6e:
return DRC_ZEROOPERANDS;
case 0x6f:
return DRC_ZEROOPERANDS;
case 0x70:
return DRC_ONEOPERAND;
case 0x71:
return DRC_ONEOPERAND;
case 0x72:
return DRC_ONEOPERAND;
case 0x73:
return DRC_ONEOPERAND;
case 0x74:
return DRC_ONEOPERAND;
case 0x75:
return DRC_ONEOPERAND;
case 0x76:
return DRC_ONEOPERAND;
case 0x77:
return DRC_ONEOPERAND;
case 0x78:
return DRC_ONEOPERAND;
case 0x79:
return DRC_ONEOPERAND;
case 0x7a:
return DRC_ONEOPERAND;
case 0x7b:
return DRC_ONEOPERAND;
case 0x7c:
return DRC_ONEOPERAND;
case 0x7d:
return DRC_ONEOPERAND;
case 0x7e:
return DRC_ONEOPERAND;
case 0x7f:
return DRC_ONEOPERAND;
case 0x80:
return DRC_ONEOPERAND;
case 0x81:
return DRC_ONEOPERAND;
case 0x82:
return DRC_ONEOPERAND;
case 0x83:
return DRC_ONEOPERAND;
case 0x84:
return DRC_ONEOPERAND;
case 0x85:
return DRC_ONEOPERAND;
case 0x86:
return DRC_ONEOPERAND;
case 0x87:
return DRC_ONEOPERAND;
case 0x88:
return DRC_ONEOPERAND;
case 0x89:
return DRC_ONEOPERAND;
case 0x8a:
return DRC_ONEOPERAND;
case 0x8b:
return DRC_ONEOPERAND;
case 0x8c:
return DRC_ONEOPERAND;
case 0x8d:
return DRC_ONEOPERAND;
case 0x8e:
return DRC_ONEOPERAND;
case 0x8f:
return DRC_ONEOPERAND;
case 0x90:
return DRC_ONEOPERAND;
case 0x91:
return DRC_ONEOPERAND;
case 0x92:
return DRC_TWOOPERANDS;
case 0x93:
return DRC_ONEOPERAND;
case 0x94:
return DRC_ONEOPERAND;
case 0x95:
return DRC_ONEOPERAND;
case 0x96:
return DRC_ZEROOPERANDS;
case 0x97:
return DRC_DWARFv3 | DRC_ZEROOPERANDS;
case 0x98:
return DRC_DWARFv3 | DRC_ONEOPERAND;
case 0x99:
return DRC_DWARFv3 | DRC_ONEOPERAND;
case 0x9a:
return DRC_DWARFv3 | DRC_ONEOPERAND;
case 0xa3: /* DW_OP_entry_value */
return DRC_TWOOPERANDS;
case 0xf0:
return DRC_ZEROOPERANDS; /* DW_OP_APPLE_uninit */
case 0xe0:
return 0;
case 0xff:
return 0;
default:
return 0;
}
}
const char *DW_ATE_value_to_name(uint32_t val) {
static char invalid[100];
llvm::StringRef llvmstr = llvm::dwarf::AttributeEncodingString(val);

View File

@ -26,52 +26,12 @@ const char *DW_FORM_value_to_name(uint32_t val);
const char *DW_OP_value_to_name(uint32_t val);
DRC_class DW_OP_value_to_class(uint32_t val);
const char *DW_ATE_value_to_name(uint32_t val);
const char *DW_LANG_value_to_name(uint32_t val);
const char *DW_LNS_value_to_name(uint32_t val);
/* These DRC are entirely our own construction,
although they are derived from various comments in the DWARF standard.
Most of these are not useful to the parser, but the DW_AT and DW_FORM
classes should prove to be usable in some fashion. */
#define DRC_0x65 0x1
#define DRC_ADDRESS 0x2
#define DRC_BLOCK 0x4
#define DRC_CONSTANT 0x8
#define DRC_DWARFv3 0x10
#define DRC_FLAG 0x20
#define DRC_INDIRECT_SPECIAL 0x40
#define DRC_LINEPTR 0x80
#define DRC_LOCEXPR 0x100
#define DRC_LOCLISTPTR 0x200
#define DRC_MACPTR 0x400
#define DRC_ONEOPERAND 0x800
#define DRC_OPERANDONE_1BYTE_DELTA 0x1000
#define DRC_OPERANDONE_2BYTE_DELTA 0x2000
#define DRC_OPERANDONE_4BYTE_DELTA 0x4000
#define DRC_OPERANDONE_ADDRESS 0x8000
#define DRC_OPERANDONE_BLOCK 0x10000
#define DRC_OPERANDONE_SLEB128_OFFSET 0x20000
#define DRC_OPERANDONE_ULEB128_OFFSET 0x40000
#define DRC_OPERANDONE_ULEB128_REGISTER 0x80000
#define DRC_OPERANDTWO_BLOCK 0x100000
#define DRC_OPERANDTWO_SLEB128_OFFSET 0x200000
#define DRC_OPERANDTWO_ULEB128_OFFSET 0x400000
#define DRC_OPERANDTWO_ULEB128_REGISTER 0x800000
#define DRC_OPERNADONE_ULEB128_REGISTER 0x1000000
#define DRC_RANGELISTPTR 0x2000000
#define DRC_REFERENCE 0x4000000
#define DRC_STRING 0x8000000
#define DRC_TWOOPERANDS 0x10000000
#define DRC_VENDOR_GNU 0x20000000
#define DRC_VENDOR_MIPS 0x40000000
#define DRC_ZEROOPERANDS 0x80000000
} // namespace lldb_private
#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEFINES_H

View File

@ -15,6 +15,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
using namespace lldb;
using namespace lldb_private;
@ -79,13 +80,10 @@ GetByteOrderAndAddrSize(Thread *thread) {
static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *thread) {
if (auto order_and_width = GetByteOrderAndAddrSize(thread)) {
DataExtractor extractor(expr.data(), expr.size(), order_and_width->first,
order_and_width->second);
if (!DWARFExpression::PrintDWARFExpression(s, extractor,
order_and_width->second,
/*dwarf_ref_size*/ 4,
/*location_expression*/ false))
s.PutCString("invalid-dwarf-expr");
llvm::DataExtractor data(expr, order_and_width->first == eByteOrderLittle,
order_and_width->second);
llvm::DWARFExpression(data, order_and_width->second, llvm::dwarf::DWARF32)
.print(s.AsRawOstream(), nullptr, nullptr);
} else
s.PutCString("dwarf-expr");
}

View File

@ -6,8 +6,7 @@
# CHECK: Symbol file UnwindPlan:
# CHECK: row[0]: 0: CFA=DW_OP_breg13 +0, DW_OP_consts +0, DW_OP_plus => pc=DW_OP_breg14 +0
# CHECK-NEXT: row[1]: 2: CFA=DW_OP_breg13 +0, DW_OP_consts +8, DW_OP_plus => r7=DW_OP_pick 0x00, DW_OP_consts -8, DW_OP_plus , DW_OP_deref pc=DW_OP_pick 0x00, DW_OP_consts -4, DW_OP_plus , DW_OP_deref
#
# CHECK-NEXT: row[1]: 2: CFA=DW_OP_breg13 +0, DW_OP_consts +8, DW_OP_plus => r7=DW_OP_pick 0x0, DW_OP_consts -8, DW_OP_plus, DW_OP_deref pc=DW_OP_pick 0x0, DW_OP_consts -4, DW_OP_plus, DW_OP_deref
--- !minidump
Streams:

View File

@ -11,8 +11,8 @@ image show-unwind -n func0
# CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes.
# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: no.
# CHECK-NEXT: Address range of this UnwindPlan: [stack-cfi-parsing.out..module_image + 0-0x0000000000000002)
# CHECK-NEXT: row[0]: 0: CFA=DW_OP_breg7 +0 => rbp=DW_OP_breg7 +0 rip=DW_OP_pick 0x00
# CHECK-NEXT: row[1]: 1: CFA=DW_OP_breg7 +0 => rbx=DW_OP_breg2 +0 rbp=DW_OP_breg0 +0 rip=DW_OP_pick 0x00
# CHECK-NEXT: row[0]: 0: CFA=DW_OP_breg7 +0 => rbp=DW_OP_breg7 +0 rip=DW_OP_pick 0x0
# CHECK-NEXT: row[1]: 1: CFA=DW_OP_breg7 +0 => rbx=DW_OP_breg2 +0 rbp=DW_OP_breg0 +0 rip=DW_OP_pick 0x0
# The following plans are all (syntactically) invalid for various reasons.
# Processing those should not cause a crash.

View File

@ -13,13 +13,13 @@ image show-unwind -n call_many
# CHECK: This UnwindPlan is sourced from the compiler: yes.
# CHECK: This UnwindPlan is valid at all instruction locations: no.
# CHECK: Address range of this UnwindPlan: [unwind-via-stack-win.exe..module_image + 4112-0x0000107d)
# CHECK: row[0]: 0: CFA=RaSearch@SP+0 => esp=DW_OP_pick 0x00, DW_OP_consts +4, DW_OP_plus eip=DW_OP_pick 0x00, DW_OP_deref
# CHECK: row[0]: 0: CFA=RaSearch@SP+0 => esp=DW_OP_pick 0x0, DW_OP_consts +4, DW_OP_plus eip=DW_OP_pick 0x0, DW_OP_deref
image show-unwind -n nonzero_frame_size
# CHECK-LABEL: image show-unwind -n nonzero_frame_size
# CHECK: UNWIND PLANS for unwind-via-stack-win.exe`nonzero_frame_size
# CHECK: Symbol file UnwindPlan:
# CHECK: row[0]: 0: CFA=RaSearch@SP+12 => esp=DW_OP_pick 0x00, DW_OP_consts +4, DW_OP_plus eip=DW_OP_pick 0x00, DW_OP_deref
# CHECK: row[0]: 0: CFA=RaSearch@SP+12 => esp=DW_OP_pick 0x0, DW_OP_consts +4, DW_OP_plus eip=DW_OP_pick 0x0, DW_OP_deref
# Then, some invalid rules.
image show-unwind -n complex_rasearch

View File

@ -13,7 +13,7 @@ image show-unwind -n bar
# CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes.
# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: no.
# CHECK-NEXT: Address range of this UnwindPlan: [unwind-via-stack-cfi..module_image + 1056-0x0000000000000449)
# CHECK-NEXT: row[0]: 0: CFA=DW_OP_breg6 +0, DW_OP_deref => rbp=DW_OP_pick 0x00, DW_OP_deref rsp=DW_OP_pick 0x00, DW_OP_consts +16, DW_OP_plus rip=DW_OP_pick 0x00, DW_OP_consts +8, DW_OP_plus , DW_OP_deref
# CHECK-NEXT: row[0]: 0: CFA=DW_OP_breg6 +0, DW_OP_deref => rbp=DW_OP_pick 0x0, DW_OP_deref rsp=DW_OP_pick 0x0, DW_OP_consts +16, DW_OP_plus rip=DW_OP_pick 0x0, DW_OP_consts +8, DW_OP_plus, DW_OP_deref
thread backtrace
# CHECK-LABEL: thread backtrace

View File

@ -15,7 +15,7 @@ image show-unwind -n call_many
# CHECK: This UnwindPlan is sourced from the compiler: yes.
# CHECK: This UnwindPlan is valid at all instruction locations: no.
# CHECK: Address range of this UnwindPlan: [unwind-via-stack-win.exe..module_image + 4112-0x0000107d)
# CHECK: row[0]: 0: CFA=DW_OP_breg7 +0, DW_OP_consts +80, DW_OP_plus => esp=DW_OP_pick 0x00, DW_OP_consts +4, DW_OP_plus eip=DW_OP_pick 0x00, DW_OP_deref
# CHECK: row[0]: 0: CFA=DW_OP_breg7 +0, DW_OP_consts +80, DW_OP_plus => esp=DW_OP_pick 0x0, DW_OP_consts +4, DW_OP_plus eip=DW_OP_pick 0x0, DW_OP_deref
# Then, some invalid rules.
image show-unwind -n bogus_rule
@ -43,7 +43,7 @@ image show-unwind -n temporary_var
# CHECK: This UnwindPlan is sourced from the compiler: yes.
# CHECK: This UnwindPlan is valid at all instruction locations: no.
# CHECK: Address range of this UnwindPlan: [unwind-via-stack-win.exe..module_image + 4400-0x00001134)
# CHECK: row[0]: 0: CFA=DW_OP_breg7 +0 => esp=DW_OP_pick 0x00, DW_OP_consts +4, DW_OP_plus eip=DW_OP_pick 0x00, DW_OP_deref
# CHECK: row[0]: 0: CFA=DW_OP_breg7 +0 => esp=DW_OP_pick 0x0, DW_OP_consts +4, DW_OP_plus eip=DW_OP_pick 0x0, DW_OP_deref
# And finally, check that backtracing works as a whole by unwinding a simple
# stack.

View File

@ -20,4 +20,4 @@ thread backtrace
target modules show-unwind -n foo
# CHECK: eh_frame UnwindPlan:
# CHECK: row[0]: 0: CFA=rsp +8 => rip=DW_OP_lit8 , DW_OP_minus , DW_OP_deref , DW_OP_const1u 0x47, DW_OP_minus
# CHECK: row[0]: 0: CFA=rsp +8 => rip=DW_OP_lit8, DW_OP_minus, DW_OP_deref, DW_OP_const1u 0x47, DW_OP_minus

View File

@ -11,4 +11,4 @@ process launch
target modules show-unwind -n main
# CHECK: eh_frame UnwindPlan:
# CHECK: row[0]: 0: CFA=DW_OP_breg7 +0, DW_OP_const1u 0x00, DW_OP_plus => rip=DW_OP_const1s -8, DW_OP_plus , DW_OP_deref
# CHECK: row[0]: 0: CFA=DW_OP_breg7 +0, DW_OP_const1u 0x0, DW_OP_plus => rip=DW_OP_const1s -8, DW_OP_plus, DW_OP_deref

View File

@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
#include "lldb/Symbol/PostfixExpression.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gmock/gmock.h"
@ -152,17 +152,14 @@ static std::string ParseAndGenerateDWARF(llvm::StringRef expr) {
ToDWARF(*ast, dwarf);
// print dwarf expression to comparable textual representation
DataExtractor extractor(dwarf.GetData(), dwarf.GetSize(),
lldb::eByteOrderLittle, addr_size);
llvm::DataExtractor extractor(dwarf.GetString(), /*IsLittleEndian=*/true,
addr_size);
StreamString result;
if (!DWARFExpression::PrintDWARFExpression(result, extractor, addr_size,
/*dwarf_ref_size*/ 4,
/*location_expression*/ false)) {
return "DWARF printing failed.";
}
return std::string(result.GetString());
std::string result;
llvm::raw_string_ostream os(result);
llvm::DWARFExpression(extractor, addr_size, llvm::dwarf::DWARF32)
.print(os, nullptr, nullptr);
return std::move(os.str());
}
TEST(PostfixExpression, ToDWARF) {
@ -170,28 +167,28 @@ TEST(PostfixExpression, ToDWARF) {
EXPECT_EQ("DW_OP_breg1 +0", ParseAndGenerateDWARF("R1"));
EXPECT_EQ("DW_OP_bregx 65 0", ParseAndGenerateDWARF("R65"));
EXPECT_EQ("DW_OP_bregx 0x41 +0", ParseAndGenerateDWARF("R65"));
EXPECT_EQ("DW_OP_pick 0x00", ParseAndGenerateDWARF("INIT"));
EXPECT_EQ("DW_OP_pick 0x0", ParseAndGenerateDWARF("INIT"));
EXPECT_EQ("DW_OP_pick 0x00, DW_OP_pick 0x01, DW_OP_plus ",
EXPECT_EQ("DW_OP_pick 0x0, DW_OP_pick 0x1, DW_OP_plus",
ParseAndGenerateDWARF("INIT INIT +"));
EXPECT_EQ("DW_OP_breg1 +0, DW_OP_pick 0x01, DW_OP_plus ",
EXPECT_EQ("DW_OP_breg1 +0, DW_OP_pick 0x1, DW_OP_plus",
ParseAndGenerateDWARF("R1 INIT +"));
EXPECT_EQ("DW_OP_consts +1, DW_OP_pick 0x01, DW_OP_deref , DW_OP_plus ",
EXPECT_EQ("DW_OP_consts +1, DW_OP_pick 0x1, DW_OP_deref, DW_OP_plus",
ParseAndGenerateDWARF("1 INIT ^ +"));
EXPECT_EQ("DW_OP_consts +4, DW_OP_consts +5, DW_OP_plus ",
EXPECT_EQ("DW_OP_consts +4, DW_OP_consts +5, DW_OP_plus",
ParseAndGenerateDWARF("4 5 +"));
EXPECT_EQ("DW_OP_consts +4, DW_OP_consts +5, DW_OP_minus ",
EXPECT_EQ("DW_OP_consts +4, DW_OP_consts +5, DW_OP_minus",
ParseAndGenerateDWARF("4 5 -"));
EXPECT_EQ("DW_OP_consts +4, DW_OP_deref ", ParseAndGenerateDWARF("4 ^"));
EXPECT_EQ("DW_OP_consts +4, DW_OP_deref", ParseAndGenerateDWARF("4 ^"));
EXPECT_EQ("DW_OP_breg6 +0, DW_OP_consts +128, DW_OP_lit1 "
", DW_OP_minus , DW_OP_not , DW_OP_and ",
EXPECT_EQ("DW_OP_breg6 +0, DW_OP_consts +128, DW_OP_lit1, DW_OP_minus, "
"DW_OP_not, DW_OP_and",
ParseAndGenerateDWARF("R6 128 @"));
}

View File

@ -11,11 +11,11 @@
#include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h"
#include "lldb/Core/StreamBuffer.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
using namespace lldb;
using namespace lldb_private;
@ -27,30 +27,22 @@ static void
CheckValidProgramTranslation(llvm::StringRef fpo_program,
llvm::StringRef target_register_name,
llvm::StringRef expected_dwarf_expression) {
// initial setup
ArchSpec arch_spec("i686-pc-windows");
llvm::Triple::ArchType arch_type = arch_spec.GetMachine();
ByteOrder byte_order = arch_spec.GetByteOrder();
uint32_t address_size = arch_spec.GetAddressByteSize();
uint32_t byte_size = arch_spec.GetDataByteSize();
// program translation
StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
StreamBuffer<32> stream(Stream::eBinary, 4, eByteOrderLittle);
ASSERT_TRUE(TranslateFPOProgramToDWARFExpression(
fpo_program, target_register_name, arch_type, stream));
fpo_program, target_register_name, llvm::Triple::x86, stream));
// print dwarf expression to comparable textual representation
DataBufferSP buffer =
std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
DataExtractor extractor(buffer, byte_order, address_size, byte_size);
llvm::DataExtractor extractor({stream.GetData(), stream.GetSize()},
/*IsLittleEndian=*/true, /*AddressSize=*/4);
StreamString result_dwarf_expression;
ASSERT_TRUE(DWARFExpression::PrintDWARFExpression(
result_dwarf_expression, extractor, address_size, 4, false));
std::string result;
llvm::raw_string_ostream os(result);
llvm::DWARFExpression(extractor, /*AddressSize=*/4, llvm::dwarf::DWARF32)
.print(os, nullptr, nullptr);
// actual check
ASSERT_STREQ(expected_dwarf_expression.data(),
result_dwarf_expression.GetString().data());
ASSERT_EQ(expected_dwarf_expression, os.str());
}
TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentRegisterRef) {
@ -64,9 +56,9 @@ TEST(PDBFPOProgramToDWARFExpressionTests, MultipleIndependentAssignments) {
TEST(PDBFPOProgramToDWARFExpressionTests, MultipleDependentAssignments) {
CheckValidProgramTranslation(
"$T1 $ebp 4 + = $T0 $T1 8 - 128 @ = ", "$T0",
"DW_OP_breg6 +0, DW_OP_consts +4, DW_OP_plus , DW_OP_consts +8, "
"DW_OP_minus , DW_OP_consts +128, DW_OP_lit1 , DW_OP_minus , DW_OP_not , "
"DW_OP_and ");
"DW_OP_breg6 +0, DW_OP_consts +4, DW_OP_plus, DW_OP_consts +8, "
"DW_OP_minus, DW_OP_consts +128, DW_OP_lit1, DW_OP_minus, DW_OP_not, "
"DW_OP_and");
}
TEST(PDBFPOProgramToDWARFExpressionTests, DependencyChain) {