summaryrefslogtreecommitdiff
path: root/lldb/source/Expression/DWARFExpression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Expression/DWARFExpression.cpp')
-rw-r--r--lldb/source/Expression/DWARFExpression.cpp297
1 files changed, 43 insertions, 254 deletions
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 69c84640ef93..6050c1922564 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -1,4 +1,4 @@
-//===-- DWARFExpression.cpp -------------------------------------*- C++ -*-===//
+//===-- DWARFExpression.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -88,8 +88,7 @@ void DWARFExpression::UpdateValue(uint64_t const_value,
void DWARFExpression::DumpLocation(Stream *s, const DataExtractor &data,
lldb::DescriptionLevel level,
ABI *abi) const {
- llvm::DWARFExpression(data.GetAsLLVM(), llvm::dwarf::DWARF_VERSION,
- data.GetAddressByteSize())
+ llvm::DWARFExpression(data.GetAsLLVM(), data.GetAddressByteSize())
.print(s->AsRawOstream(), abi ? &abi->GetMCRegisterInfo() : nullptr,
nullptr);
}
@@ -138,12 +137,15 @@ void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level,
m_dwarf_cu->GetLocationTable(m_data);
llvm::MCRegisterInfo *MRI = abi ? &abi->GetMCRegisterInfo() : nullptr;
-
+ llvm::DIDumpOptions DumpOpts;
+ DumpOpts.RecoverableErrorHandler = [&](llvm::Error E) {
+ s->AsRawOstream() << "error: " << toString(std::move(E));
+ };
loctable_up->dumpLocationList(
&offset, s->AsRawOstream(),
llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr}, MRI,
DummyDWARFObject(m_data.GetByteOrder() == eByteOrderLittle), nullptr,
- llvm::DIDumpOptions(), s->GetIndentLevel() + 2);
+ DumpOpts, s->GetIndentLevel() + 2);
} else {
// We have a normal location that contains DW_OP location opcodes
DumpLocation(s, m_data, level, abi);
@@ -394,6 +396,7 @@ static offset_t GetOpcodeDataSize(const DataExtractor &data,
return offset - data_offset;
}
+ case DW_OP_GNU_entry_value:
case DW_OP_entry_value: // 0xa3 ULEB128 size + variable-length block
{
uint64_t subexpr_len = data.GetULEB128(&offset);
@@ -933,7 +936,7 @@ bool DWARFExpression::Evaluate(
Value tmp;
uint32_t reg_num;
- /// Insertion point for evaluating multi-piece expression.
+ /// Insertion point for evaluating multi-piece expression.
uint64_t op_piece_offset = 0;
Value pieces; // Used for DW_OP_piece
@@ -1183,7 +1186,7 @@ bool DWARFExpression::Evaluate(
break;
default:
stack.back().GetScalar() =
- addr_data.GetPointer(&addr_data_offset);
+ addr_data.GetAddress(&addr_data_offset);
}
stack.back().ClearContext();
} else {
@@ -2071,6 +2074,10 @@ bool DWARFExpression::Evaluate(
// not available. Fill with zeros for now by resizing the data and
// appending it
curr_piece.ResizeData(piece_byte_size);
+ // Note that "0" is not a correct value for the unknown bits.
+ // It would be better to also return a mask of valid bits together
+ // with the expression result, so the debugger can print missing
+ // members as "<optimized out>" or something.
::memset(curr_piece.GetBuffer().GetBytes(), 0, piece_byte_size);
pieces.AppendDataToHostBuffer(curr_piece);
} else {
@@ -2128,7 +2135,8 @@ bool DWARFExpression::Evaluate(
case Value::eValueTypeScalar: {
uint32_t bit_size = piece_byte_size * 8;
uint32_t bit_offset = 0;
- if (!curr_piece_source_value.GetScalar().ExtractBitfield(
+ Scalar &scalar = curr_piece_source_value.GetScalar();
+ if (!scalar.ExtractBitfield(
bit_size, bit_offset)) {
if (error_ptr)
error_ptr->SetErrorStringWithFormat(
@@ -2139,7 +2147,14 @@ bool DWARFExpression::Evaluate(
.GetByteSize());
return false;
}
- curr_piece = curr_piece_source_value;
+ // Create curr_piece with bit_size. By default Scalar
+ // grows to the nearest host integer type.
+ llvm::APInt fail_value(1, 0, false);
+ llvm::APInt ap_int = scalar.UInt128(fail_value);
+ assert(ap_int.getBitWidth() >= bit_size);
+ llvm::ArrayRef<uint64_t> buf{ap_int.getRawData(),
+ ap_int.getNumWords()};
+ curr_piece.GetScalar() = Scalar(llvm::APInt(bit_size, buf));
} break;
case Value::eValueTypeVector: {
@@ -2161,7 +2176,7 @@ bool DWARFExpression::Evaluate(
if (op_piece_offset == 0) {
// This is the first piece, we should push it back onto the stack
// so subsequent pieces will be able to access this piece and add
- // to it
+ // to it.
if (pieces.AppendDataToHostBuffer(curr_piece) == 0) {
if (error_ptr)
error_ptr->SetErrorString("failed to append piece data");
@@ -2169,7 +2184,7 @@ bool DWARFExpression::Evaluate(
}
} else {
// If this is the second or later piece there should be a value on
- // the stack
+ // the stack.
if (pieces.GetBuffer().GetByteSize() != op_piece_offset) {
if (error_ptr)
error_ptr->SetErrorStringWithFormat(
@@ -2185,8 +2200,8 @@ bool DWARFExpression::Evaluate(
return false;
}
}
- op_piece_offset += piece_byte_size;
}
+ op_piece_offset += piece_byte_size;
}
} break;
@@ -2307,6 +2322,12 @@ bool DWARFExpression::Evaluate(
// rather is a constant value. The value from the top of the stack is the
// value to be used. This is the actual object value and not the location.
case DW_OP_stack_value:
+ if (stack.empty()) {
+ if (error_ptr)
+ error_ptr->SetErrorString(
+ "Expression stack needs at least 1 item for DW_OP_stack_value.");
+ return false;
+ }
stack.back().SetValueType(Value::eValueTypeScalar);
break;
@@ -2325,8 +2346,8 @@ bool DWARFExpression::Evaluate(
return false;
}
const uint64_t die_offset = opcodes.GetULEB128(&offset);
- Scalar::Type type = Scalar::e_void;
uint64_t bit_size;
+ bool sign;
if (die_offset == 0) {
// The generic type has the size of an address on the target
// machine and an unspecified signedness. Scalar has no
@@ -2336,13 +2357,13 @@ bool DWARFExpression::Evaluate(
error_ptr->SetErrorString("No module");
return false;
}
+ sign = false;
bit_size = module_sp->GetArchitecture().GetAddressByteSize() * 8;
if (!bit_size) {
if (error_ptr)
error_ptr->SetErrorString("unspecified architecture");
return false;
}
- type = Scalar::GetBestTypeForBitSize(bit_size, false);
} else {
// Retrieve the type DIE that the value is being converted to.
// FIXME: the constness has annoying ripple effects.
@@ -2365,11 +2386,11 @@ bool DWARFExpression::Evaluate(
switch (encoding) {
case DW_ATE_signed:
case DW_ATE_signed_char:
- type = Scalar::GetBestTypeForBitSize(bit_size, true);
+ sign = true;
break;
case DW_ATE_unsigned:
case DW_ATE_unsigned_char:
- type = Scalar::GetBestTypeForBitSize(bit_size, false);
+ sign = false;
break;
default:
if (error_ptr)
@@ -2377,13 +2398,8 @@ bool DWARFExpression::Evaluate(
return false;
}
}
- if (type == Scalar::e_void) {
- if (error_ptr)
- error_ptr->SetErrorString("Unsupported pointer size");
- return false;
- }
Scalar &top = stack.back().ResolveValue(exe_ctx);
- top.TruncOrExtendTo(type, bit_size);
+ top.TruncOrExtendTo(bit_size, sign);
break;
}
@@ -2502,6 +2518,7 @@ bool DWARFExpression::Evaluate(
stack.push_back(Scalar(value));
} break;
+ case DW_OP_GNU_entry_value:
case DW_OP_entry_value: {
if (!Evaluate_DW_OP_entry_value(stack, exe_ctx, reg_ctx, opcodes, offset,
error_ptr, log)) {
@@ -2513,9 +2530,10 @@ bool DWARFExpression::Evaluate(
}
default:
- LLDB_LOGF(log, "Unhandled opcode %s in DWARFExpression.",
- DW_OP_value_to_name(op));
- break;
+ if (error_ptr)
+ error_ptr->SetErrorStringWithFormatv(
+ "Unhandled opcode {0} in DWARFExpression", LocationAtom(op));
+ return false;
}
}
@@ -2546,235 +2564,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 =