diff options
Diffstat (limited to 'lldb/source/Expression/DWARFExpression.cpp')
-rw-r--r-- | lldb/source/Expression/DWARFExpression.cpp | 297 |
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 = |