diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /lldb/source/Expression | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'lldb/source/Expression')
-rw-r--r-- | lldb/source/Expression/DWARFExpression.cpp | 297 | ||||
-rw-r--r-- | lldb/source/Expression/DiagnosticManager.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Expression/Expression.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Expression/ExpressionVariable.cpp | 14 | ||||
-rw-r--r-- | lldb/source/Expression/FunctionCaller.cpp | 7 | ||||
-rw-r--r-- | lldb/source/Expression/IRExecutionUnit.cpp | 61 | ||||
-rw-r--r-- | lldb/source/Expression/IRInterpreter.cpp | 59 | ||||
-rw-r--r-- | lldb/source/Expression/IRMemoryMap.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Expression/LLVMUserExpression.cpp | 19 | ||||
-rw-r--r-- | lldb/source/Expression/Materializer.cpp | 47 | ||||
-rw-r--r-- | lldb/source/Expression/REPL.cpp | 36 | ||||
-rw-r--r-- | lldb/source/Expression/UserExpression.cpp | 124 | ||||
-rw-r--r-- | lldb/source/Expression/UtilityFunction.cpp | 2 |
13 files changed, 230 insertions, 444 deletions
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 69c84640ef93a..6050c1922564c 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 = diff --git a/lldb/source/Expression/DiagnosticManager.cpp b/lldb/source/Expression/DiagnosticManager.cpp index 48eba3586d30a..08977066e3330 100644 --- a/lldb/source/Expression/DiagnosticManager.cpp +++ b/lldb/source/Expression/DiagnosticManager.cpp @@ -1,4 +1,4 @@ -//===-- DiagnosticManager.cpp -----------------------------------*- C++ -*-===// +//===-- DiagnosticManager.cpp ---------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -49,7 +49,7 @@ std::string DiagnosticManager::GetString(char separator) { for (const auto &diagnostic : Diagnostics()) { ret.append(StringForSeverity(diagnostic->GetSeverity())); - ret.append(diagnostic->GetMessage()); + ret.append(std::string(diagnostic->GetMessage())); ret.push_back(separator); } diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index 71369d0b9eec3..93f585edfce3d 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -1,4 +1,4 @@ -//===-- Expression.cpp ------------------------------------------*- C++ -*-===// +//===-- Expression.cpp ----------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Expression/ExpressionVariable.cpp b/lldb/source/Expression/ExpressionVariable.cpp index ed8da0ad8675b..d95f0745cf4ba 100644 --- a/lldb/source/Expression/ExpressionVariable.cpp +++ b/lldb/source/Expression/ExpressionVariable.cpp @@ -1,4 +1,4 @@ -//===-- ExpressionVariable.cpp ----------------------------------*- C++ -*-===// +//===-- ExpressionVariable.cpp --------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -69,20 +69,10 @@ void PersistentExpressionState::RegisterExecutionUnit( // of the demangled name will find the mangled one (needed for looking up // metadata pointers.) Mangled mangler(global_var.m_name); - mangler.GetDemangledName(lldb::eLanguageTypeUnknown); + mangler.GetDemangledName(); m_symbol_map[global_var.m_name.GetCString()] = global_var.m_remote_addr; LLDB_LOGF(log, " Symbol: %s at 0x%" PRIx64 ".", global_var.m_name.GetCString(), global_var.m_remote_addr); } } } - -ConstString PersistentExpressionState::GetNextPersistentVariableName( - Target &target, llvm::StringRef Prefix) { - llvm::SmallString<64> name; - { - llvm::raw_svector_ostream os(name); - os << Prefix << target.GetNextPersistentVariableIndex(); - } - return ConstString(name); -} diff --git a/lldb/source/Expression/FunctionCaller.cpp b/lldb/source/Expression/FunctionCaller.cpp index dc80c8169d7d2..26ab4bfaff539 100644 --- a/lldb/source/Expression/FunctionCaller.cpp +++ b/lldb/source/Expression/FunctionCaller.cpp @@ -1,4 +1,4 @@ -//===-- FunctionCaller.cpp ---------------------------------------*- C++-*-===// +//===-- FunctionCaller.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -364,8 +364,9 @@ lldb::ExpressionResults FunctionCaller::ExecuteFunction( if (return_value != lldb::eExpressionCompleted) { LLDB_LOGF(log, "== [FunctionCaller::ExecuteFunction] Execution of \"%s\" " - "completed abnormally ==", - m_name.c_str()); + "completed abnormally: %s ==", + m_name.c_str(), + Process::ExecutionResultAsCString(return_value)); } else { LLDB_LOGF(log, "== [FunctionCaller::ExecuteFunction] Execution of \"%s\" " diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index e033b90cfd8bf..e3c9c1d7fdf54 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -1,4 +1,4 @@ -//===-- IRExecutionUnit.cpp -------------------------------------*- C++ -*-===// +//===-- IRExecutionUnit.cpp -----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -265,11 +265,9 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, builder.setEngineKind(llvm::EngineKind::JIT) .setErrorStr(&error_string) - .setRelocationModel(triple.isOSBinFormatMachO() - ? llvm::Reloc::PIC_ - : llvm::Reloc::Static) - .setMCJITMemoryManager( - std::unique_ptr<MemoryManager>(new MemoryManager(*this))) + .setRelocationModel(triple.isOSBinFormatMachO() ? llvm::Reloc::PIC_ + : llvm::Reloc::Static) + .setMCJITMemoryManager(std::make_unique<MemoryManager>(*this)) .setOptLevel(llvm::CodeGenOpt::Less); llvm::StringRef mArch; @@ -404,9 +402,7 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, ss.PutCString("\n"); emitNewLine = true; ss.PutCString(" "); - ss.PutCString(Mangled(failed_lookup) - .GetDemangledName(lldb::eLanguageTypeObjC_plus_plus) - .AsCString()); + ss.PutCString(Mangled(failed_lookup).GetDemangledName().GetStringRef()); } m_failed_lookups.clear(); @@ -645,10 +641,8 @@ uint8_t *IRExecutionUnit::MemoryManager::allocateDataSection( return return_value; } -static ConstString -FindBestAlternateMangledName(ConstString demangled, - const lldb::LanguageType &lang_type, - const SymbolContext &sym_ctx) { +static ConstString FindBestAlternateMangledName(ConstString demangled, + const SymbolContext &sym_ctx) { CPlusPlusLanguage::MethodName cpp_name(demangled); std::string scope_qualified_name = cpp_name.GetScopeQualifiedName(); @@ -670,7 +664,7 @@ FindBestAlternateMangledName(ConstString demangled, for (size_t i = 0; i < alternates.size(); i++) { ConstString alternate_mangled_name = alternates[i]; Mangled mangled(alternate_mangled_name); - ConstString demangled = mangled.GetDemangledName(lang_type); + ConstString demangled = mangled.GetDemangledName(); CPlusPlusLanguage::MethodName alternate_cpp_name(demangled); if (!cpp_name.IsValid()) @@ -718,12 +712,11 @@ void IRExecutionUnit::CollectCandidateCPlusPlusNames( if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) { Mangled mangled(name); - ConstString demangled = - mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus); + ConstString demangled = mangled.GetDemangledName(); if (demangled) { - ConstString best_alternate_mangled_name = FindBestAlternateMangledName( - demangled, lldb::eLanguageTypeC_plus_plus, sc); + ConstString best_alternate_mangled_name = + FindBestAlternateMangledName(demangled, sc); if (best_alternate_mangled_name) { CPP_specs.push_back(best_alternate_mangled_name); @@ -746,20 +739,22 @@ void IRExecutionUnit::CollectFallbackNames( for (const SearchSpec &C_spec : C_specs) { ConstString name = C_spec.name; - if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) { - Mangled mangled_name(name); - ConstString demangled_name = - mangled_name.GetDemangledName(lldb::eLanguageTypeC_plus_plus); - if (!demangled_name.IsEmpty()) { - const char *demangled_cstr = demangled_name.AsCString(); - const char *lparen_loc = strchr(demangled_cstr, '('); - if (lparen_loc) { - llvm::StringRef base_name(demangled_cstr, - lparen_loc - demangled_cstr); - fallback_specs.push_back(ConstString(base_name)); - } - } - } + if (!CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) + continue; + + Mangled mangled_name(name); + ConstString demangled_name = mangled_name.GetDemangledName(); + if (demangled_name.IsEmpty()) + continue; + + const char *demangled_cstr = demangled_name.AsCString(); + const char *lparen_loc = strchr(demangled_cstr, '('); + if (!lparen_loc) + continue; + + llvm::StringRef base_name(demangled_cstr, + lparen_loc - demangled_cstr); + fallback_specs.push_back(ConstString(base_name)); } } @@ -849,7 +844,7 @@ lldb::addr_t IRExecutionUnit::FindInSymbols( }; if (sc.module_sp) { - sc.module_sp->FindFunctions(spec.name, nullptr, spec.mask, + sc.module_sp->FindFunctions(spec.name, CompilerDeclContext(), spec.mask, true, // include_symbols false, // include_inlines sc_list); diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index b2e4be5e40fd7..4c7a656265981 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -1,4 +1,4 @@ -//===-- IRInterpreter.cpp ---------------------------------------*- C++ -*-===// +//===-- IRInterpreter.cpp -------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -144,10 +144,10 @@ public: ss.Printf(" 0x%llx", (unsigned long long)addr); } - return ss.GetString(); + return std::string(ss.GetString()); } - bool AssignToMatchType(lldb_private::Scalar &scalar, uint64_t u64value, + bool AssignToMatchType(lldb_private::Scalar &scalar, llvm::APInt value, Type *type) { size_t type_size = m_target_data.getTypeStoreSize(type); @@ -157,7 +157,7 @@ public: if (type_size != 1) type_size = PowerOf2Ceil(type_size); - scalar = llvm::APInt(type_size*8, u64value); + scalar = value.zextOrTrunc(type_size * 8); return true; } @@ -171,32 +171,32 @@ public: if (!ResolveConstantValue(value_apint, constant)) return false; - return AssignToMatchType(scalar, value_apint.getLimitedValue(), - value->getType()); - } else { - lldb::addr_t process_address = ResolveValue(value, module); - size_t value_size = m_target_data.getTypeStoreSize(value->getType()); + return AssignToMatchType(scalar, value_apint, value->getType()); + } - lldb_private::DataExtractor value_extractor; - lldb_private::Status extract_error; + lldb::addr_t process_address = ResolveValue(value, module); + size_t value_size = m_target_data.getTypeStoreSize(value->getType()); - m_execution_unit.GetMemoryData(value_extractor, process_address, - value_size, extract_error); + lldb_private::DataExtractor value_extractor; + lldb_private::Status extract_error; - if (!extract_error.Success()) - return false; + m_execution_unit.GetMemoryData(value_extractor, process_address, + value_size, extract_error); - lldb::offset_t offset = 0; - if (value_size <= 8) { - uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size); - return AssignToMatchType(scalar, u64value, value->getType()); - } + if (!extract_error.Success()) + return false; + + lldb::offset_t offset = 0; + if (value_size <= 8) { + uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size); + return AssignToMatchType(scalar, llvm::APInt(64, u64value), + value->getType()); } return false; } - bool AssignValue(const Value *value, lldb_private::Scalar &scalar, + bool AssignValue(const Value *value, lldb_private::Scalar scalar, Module &module) { lldb::addr_t process_address = ResolveValue(value, module); @@ -205,7 +205,9 @@ public: lldb_private::Scalar cast_scalar; - if (!AssignToMatchType(cast_scalar, scalar.ULongLong(), value->getType())) + scalar.MakeUnsigned(); + if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()), + value->getType())) return false; size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType()); @@ -403,7 +405,7 @@ public: ss.Printf("%02hhx ", buf.GetBytes()[i]); } - return ss.GetString(); + return std::string(ss.GetString()); } lldb::addr_t ResolveValue(const Value *value, Module &module) { @@ -433,8 +435,6 @@ static const char *unsupported_opcode_error = "Interpreter doesn't handle one of the expression's opcodes"; static const char *unsupported_operand_error = "Interpreter doesn't handle one of the expression's operands"; -// static const char *interpreter_initialization_error = "Interpreter couldn't -// be initialized"; static const char *interpreter_internal_error = "Interpreter encountered an internal error"; static const char *bad_value_error = @@ -444,8 +444,6 @@ static const char *memory_allocation_error = static const char *memory_write_error = "Interpreter couldn't write to memory"; static const char *memory_read_error = "Interpreter couldn't read from memory"; static const char *infinite_loop_error = "Interpreter ran for too many cycles"; -// static const char *bad_result_error = "Result of expression -// is in bad memory"; static const char *too_many_functions_error = "Interpreter doesn't handle modules with multiple function bodies."; @@ -597,7 +595,8 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, switch (operand_type->getTypeID()) { default: break; - case Type::VectorTyID: { + case Type::FixedVectorTyID: + case Type::ScalableVectorTyID: { LLDB_LOGF(log, "Unsupported operand type: %s", PrintType(operand_type).c_str()); error.SetErrorString(unsupported_operand_error); @@ -1370,7 +1369,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, // Find the address of the callee function lldb_private::Scalar I; - const llvm::Value *val = call_inst->getCalledValue(); + const llvm::Value *val = call_inst->getCalledOperand(); if (!frame.EvaluateValue(I, val, module)) { error.SetErrorToGenericError(); @@ -1510,7 +1509,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, lldb_private::ValueObject *vobj = retVal.get(); // Check if the return value is valid - if (vobj == nullptr || retVal.empty()) { + if (vobj == nullptr || !retVal) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("unable to get the return value"); return false; diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp index 02a875ec833ba..6b1e4c313a391 100644 --- a/lldb/source/Expression/IRMemoryMap.cpp +++ b/lldb/source/Expression/IRMemoryMap.cpp @@ -1,4 +1,4 @@ -//===-- IRMemoryMap.cpp -----------------------------------------*- C++ -*-===// +//===-- IRMemoryMap.cpp ---------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp index 1fc878bbd6163..187b427e66aa9 100644 --- a/lldb/source/Expression/LLVMUserExpression.cpp +++ b/lldb/source/Expression/LLVMUserExpression.cpp @@ -1,4 +1,4 @@ -//===-- LLVMUserExpression.cpp ----------------------------------*- C++ -*-===// +//===-- LLVMUserExpression.cpp --------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -134,6 +134,10 @@ LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, return lldb::eExpressionSetupError; } + // Store away the thread ID for error reporting, in case it exits + // during execution: + lldb::tid_t expr_thread_id = exe_ctx.GetThreadRef().GetID(); + Address wrapper_address(m_jit_start_addr); std::vector<lldb::addr_t> args; @@ -223,6 +227,14 @@ LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, "Use \"thread return -x\" to return to the state before expression " "evaluation."); return execution_result; + } else if (execution_result == lldb::eExpressionThreadVanished) { + diagnostic_manager.Printf( + eDiagnosticSeverityError, + "Couldn't complete execution; the thread " + "on which the expression was being run: 0x%" PRIx64 + " exited during its execution.", + expr_thread_id); + return execution_result; } else if (execution_result != lldb::eExpressionCompleted) { diagnostic_manager.Printf( eDiagnosticSeverityError, "Couldn't execute function; result was %s", @@ -357,8 +369,3 @@ bool LLVMUserExpression::PrepareToExecuteJITExpression( return true; } -lldb::ModuleSP LLVMUserExpression::GetJITModule() { - if (m_execution_unit_sp) - return m_execution_unit_sp->GetJITModule(); - return lldb::ModuleSP(); -} diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp index cd332484debbc..f33462053f22a 100644 --- a/lldb/source/Expression/Materializer.cpp +++ b/lldb/source/Expression/Materializer.cpp @@ -1,4 +1,4 @@ -//===-- Materializer.cpp ----------------------------------------*- C++ -*-===// +//===-- Materializer.cpp --------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -399,7 +399,8 @@ uint32_t Materializer::AddPersistentVariable( lldb::ExpressionVariableSP &persistent_variable_sp, PersistentVariableDelegate *delegate, Status &err) { EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset(new EntityPersistentVariable(persistent_variable_sp, delegate)); + *iter = std::make_unique<EntityPersistentVariable>(persistent_variable_sp, + delegate); uint32_t ret = AddStructMember(**iter); (*iter)->SetOffset(ret); return ret; @@ -698,7 +699,7 @@ public: lldb::offset_t offset; - ptr = extractor.GetPointer(&offset); + ptr = extractor.GetAddress(&offset); dump_stream.PutChar('\n'); } @@ -752,7 +753,7 @@ private: uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Status &err) { EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset(new EntityVariable(variable_sp)); + *iter = std::make_unique<EntityVariable>(variable_sp); uint32_t ret = AddStructMember(**iter); (*iter)->SetOffset(ret); return ret; @@ -784,7 +785,9 @@ public: const lldb::addr_t load_addr = process_address + m_offset; - ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); + ExecutionContextScope *exe_scope = frame_sp.get(); + if (!exe_scope) + exe_scope = map.GetBestExecutionContextScope(); llvm::Optional<uint64_t> byte_size = m_type.GetByteSize(exe_scope); if (!byte_size) { @@ -834,7 +837,9 @@ public: lldb::addr_t frame_bottom, Status &err) override { err.Clear(); - ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); + ExecutionContextScope *exe_scope = frame_sp.get(); + if (!exe_scope) + exe_scope = map.GetBestExecutionContextScope(); if (!exe_scope) { err.SetErrorString("Couldn't dematerialize a result variable: invalid " @@ -881,11 +886,9 @@ public: return; } - ConstString name = - m_delegate - ? m_delegate->GetName() - : persistent_state->GetNextPersistentVariableName( - *target_sp, persistent_state->GetPersistentVariablePrefix()); + ConstString name = m_delegate + ? m_delegate->GetName() + : persistent_state->GetNextPersistentVariableName(); lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable( exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize()); @@ -972,7 +975,7 @@ public: lldb::offset_t offset; - ptr = extractor.GetPointer(&offset); + ptr = extractor.GetAddress(&offset); dump_stream.PutChar('\n'); } @@ -1032,8 +1035,8 @@ uint32_t Materializer::AddResultVariable(const CompilerType &type, PersistentVariableDelegate *delegate, Status &err) { EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset(new EntityResultVariable(type, is_program_reference, - keep_in_memory, delegate)); + *iter = std::make_unique<EntityResultVariable>(type, is_program_reference, + keep_in_memory, delegate); uint32_t ret = AddStructMember(**iter); (*iter)->SetOffset(ret); return ret; @@ -1062,7 +1065,9 @@ public: const Address sym_address = m_symbol.GetAddress(); - ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); + ExecutionContextScope *exe_scope = frame_sp.get(); + if (!exe_scope) + exe_scope = map.GetBestExecutionContextScope(); lldb::TargetSP target_sp; @@ -1149,7 +1154,7 @@ private: uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Status &err) { EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset(new EntitySymbol(symbol_sp)); + *iter = std::make_unique<EntitySymbol>(symbol_sp); uint32_t ret = AddStructMember(**iter); (*iter)->SetOffset(ret); return ret; @@ -1326,15 +1331,12 @@ private: uint32_t Materializer::AddRegister(const RegisterInfo ®ister_info, Status &err) { EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset(new EntityRegister(register_info)); + *iter = std::make_unique<EntityRegister>(register_info); uint32_t ret = AddStructMember(**iter); (*iter)->SetOffset(ret); return ret; } -Materializer::Materializer() - : m_dematerializer_wp(), m_current_offset(0), m_struct_alignment(8) {} - Materializer::~Materializer() { DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); @@ -1346,7 +1348,6 @@ Materializer::DematerializerSP Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &error) { ExecutionContextScope *exe_scope = frame_sp.get(); - if (!exe_scope) exe_scope = map.GetBestExecutionContextScope(); @@ -1397,7 +1398,9 @@ void Materializer::Dematerializer::Dematerialize(Status &error, if (thread_sp) frame_sp = thread_sp->GetFrameWithStackID(m_stack_id); - ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope(); + ExecutionContextScope *exe_scope = frame_sp.get(); + if (!exe_scope) + exe_scope = m_map->GetBestExecutionContextScope(); if (!IsValid()) { error.SetErrorToGenericError(); diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp index fcd0836847389..fd7c39686921d 100644 --- a/lldb/source/Expression/REPL.cpp +++ b/lldb/source/Expression/REPL.cpp @@ -1,4 +1,4 @@ -//===-- REPL.cpp ------------------------------------------------*- C++ -*-===// +//===-- REPL.cpp ----------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -53,11 +53,11 @@ std::string REPL::GetSourcePath() { ConstString file_basename = GetSourceFileBasename(); FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir(); if (tmpdir_file_spec) { - tmpdir_file_spec.GetFilename().SetCString(file_basename.AsCString()); + tmpdir_file_spec.GetFilename() = file_basename; m_repl_source_path = tmpdir_file_spec.GetPath(); } else { tmpdir_file_spec = FileSpec("/tmp"); - tmpdir_file_spec.AppendPathComponent(file_basename.AsCString()); + tmpdir_file_spec.AppendPathComponent(file_basename.GetStringRef()); } return tmpdir_file_spec.GetPath(); @@ -216,7 +216,7 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { ci.SetPromptOnQuit(false); // Execute the command - CommandReturnObject result; + CommandReturnObject result(debugger.GetUseColor()); result.SetImmediateOutputStream(output_sp); result.SetImmediateErrorStream(error_sp); ci.HandleCommand(code.c_str(), eLazyBoolNo, result); @@ -252,7 +252,7 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler()); if (io_handler_sp) { io_handler_sp->SetIsDone(false); - debugger.PushIOHandler(ci.GetIOHandler()); + debugger.RunIOHandlerAsync(ci.GetIOHandler()); } } } @@ -291,12 +291,10 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { const char *expr_prefix = nullptr; lldb::ValueObjectSP result_valobj_sp; Status error; - lldb::ModuleSP jit_module_sp; lldb::ExpressionResults execution_results = UserExpression::Evaluate(exe_ctx, expr_options, code.c_str(), expr_prefix, result_valobj_sp, error, - nullptr, // Fixed Expression - &jit_module_sp); + nullptr); // fixed expression // CommandInterpreter &ci = debugger.GetCommandInterpreter(); @@ -370,7 +368,7 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler()); if (io_handler_sp) { io_handler_sp->SetIsDone(false); - debugger.PushIOHandler(ci.GetIOHandler()); + debugger.RunIOHandlerAsync(ci.GetIOHandler()); } } break; @@ -390,6 +388,11 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { error_sp->Printf("error: stopped for debug -- %s\n", error.AsCString()); break; + case lldb::eExpressionThreadVanished: + // Shoulnd't happen??? + error_sp->Printf("error: expression thread vanished -- %s\n", + error.AsCString()); + break; } } @@ -454,6 +457,10 @@ void REPL::IOHandlerComplete(IOHandler &io_handler, debugger.GetCommandInterpreter().HandleCompletion(sub_request); StringList matches, descriptions; sub_result.GetMatches(matches); + // Prepend command prefix that was excluded in the completion request. + if (request.GetCursorIndex() == 0) + for (auto &match : matches) + match.insert(0, 1, ':'); sub_result.GetDescriptions(descriptions); request.AddCompletions(matches, descriptions); return; @@ -488,14 +495,7 @@ void REPL::IOHandlerComplete(IOHandler &io_handler, current_code.append("\n"); current_code += request.GetRawLine(); - StringList matches; - int result = CompleteCode(current_code, matches); - if (result == -2) { - assert(matches.GetSize() == 1); - request.AddCompletion(matches.GetStringAtIndex(0), "", - CompletionMode::RewriteLine); - } else - request.AddCompletions(matches); + CompleteCode(current_code, request); } bool QuitCommandOverrideCallback(void *baton, const char **argv) { @@ -530,7 +530,7 @@ Status REPL::RunLoop() { save_default_line); } - debugger.PushIOHandler(io_handler_sp); + debugger.RunIOHandlerAsync(io_handler_sp); // Check if we are in dedicated REPL mode where LLDB was start with the "-- // repl" option from the command line. Currently we know this by checking if diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp index 3b507da8e4ab4..47d13f052bfb1 100644 --- a/lldb/source/Expression/UserExpression.cpp +++ b/lldb/source/Expression/UserExpression.cpp @@ -1,4 +1,4 @@ -//===-- UserExpression.cpp ---------------------------------*- C++ -*-===// +//===-- UserExpression.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -53,8 +53,9 @@ UserExpression::UserExpression(ExecutionContextScope &exe_scope, lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options) - : Expression(exe_scope), m_expr_text(expr), m_expr_prefix(prefix), - m_language(language), m_desired_type(desired_type), m_options(options) {} + : Expression(exe_scope), m_expr_text(std::string(expr)), + m_expr_prefix(std::string(prefix)), m_language(language), + m_desired_type(desired_type), m_options(options) {} UserExpression::~UserExpression() {} @@ -116,7 +117,7 @@ lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp, lldb::ValueObjectSP valobj_sp; valobj_sp = frame_sp->GetValueForVariableExpressionPath( - object_name.AsCString(), lldb::eNoDynamicValues, + object_name.GetStringRef(), lldb::eNoDynamicValues, StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsNoFragileObjcIvar | StackFrame::eExpressionPathOptionsNoSyntheticChildren | @@ -138,12 +139,12 @@ lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp, return ret; } -lldb::ExpressionResults UserExpression::Evaluate( - ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, - llvm::StringRef expr, llvm::StringRef prefix, - lldb::ValueObjectSP &result_valobj_sp, Status &error, - std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr, - ValueObject *ctx_obj) { +lldb::ExpressionResults +UserExpression::Evaluate(ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, + llvm::StringRef expr, llvm::StringRef prefix, + lldb::ValueObjectSP &result_valobj_sp, Status &error, + std::string *fixed_expression, ValueObject *ctx_obj) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); @@ -167,8 +168,8 @@ lldb::ExpressionResults UserExpression::Evaluate( Target *target = exe_ctx.GetTargetPtr(); if (!target) { - LLDB_LOGF(log, "== [UserExpression::Evaluate] Passed a NULL target, can't " - "run expressions."); + LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a NULL target, can't " + "run expressions."); error.SetErrorString("expression passed a null target"); return lldb::eExpressionSetupError; } @@ -177,9 +178,8 @@ lldb::ExpressionResults UserExpression::Evaluate( if (process == nullptr || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { - LLDB_LOGF(log, - "== [UserExpression::Evaluate] Expression may not run, but " - "is not constant =="); + LLDB_LOG(log, "== [UserExpression::Evaluate] Expression may not run, but " + "is not constant =="); error.SetErrorString("expression needed to run but couldn't"); @@ -201,8 +201,8 @@ lldb::ExpressionResults UserExpression::Evaluate( llvm::StringRef option_prefix(options.GetPrefix()); std::string full_prefix_storage; if (!prefix.empty() && !option_prefix.empty()) { - full_prefix_storage = prefix; - full_prefix_storage.append(option_prefix); + full_prefix_storage = std::string(prefix); + full_prefix_storage.append(std::string(option_prefix)); full_prefix = full_prefix_storage; } else if (!prefix.empty()) full_prefix = prefix; @@ -224,15 +224,13 @@ lldb::ExpressionResults UserExpression::Evaluate( desired_type, options, ctx_obj, error)); if (error.Fail()) { - if (log) - LLDB_LOGF(log, "== [UserExpression::Evaluate] Getting expression: %s ==", - error.AsCString()); + LLDB_LOG(log, "== [UserExpression::Evaluate] Getting expression: {0} ==", + error.AsCString()); return lldb::eExpressionSetupError; } - if (log) - LLDB_LOGF(log, "== [UserExpression::Evaluate] Parsing expression %s ==", - expr.str().c_str()); + LLDB_LOG(log, "== [UserExpression::Evaluate] Parsing expression {0} ==", + expr.str()); const bool keep_expression_in_memory = true; const bool generate_debug_info = options.GetGenerateDebugInfo(); @@ -261,25 +259,40 @@ lldb::ExpressionResults UserExpression::Evaluate( // If there is a fixed expression, try to parse it: if (!parse_success) { + // Delete the expression that failed to parse before attempting to parse + // the next expression. + user_expression_sp.reset(); + execution_results = lldb::eExpressionParseError; if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts()) { - lldb::UserExpressionSP fixed_expression_sp( - target->GetUserExpressionForLanguage(fixed_expression->c_str(), - full_prefix, language, - desired_type, options, ctx_obj, - error)); - DiagnosticManager fixed_diagnostic_manager; - parse_success = fixed_expression_sp->Parse( - fixed_diagnostic_manager, exe_ctx, execution_policy, - keep_expression_in_memory, generate_debug_info); - if (parse_success) { - diagnostic_manager.Clear(); - user_expression_sp = fixed_expression_sp; - } else { - // If the fixed expression failed to parse, don't tell the user about, - // that won't help. - fixed_expression->clear(); + const uint64_t max_fix_retries = options.GetRetriesWithFixIts(); + for (uint64_t i = 0; i < max_fix_retries; ++i) { + // Try parsing the fixed expression. + lldb::UserExpressionSP fixed_expression_sp( + target->GetUserExpressionForLanguage( + fixed_expression->c_str(), full_prefix, language, desired_type, + options, ctx_obj, error)); + DiagnosticManager fixed_diagnostic_manager; + parse_success = fixed_expression_sp->Parse( + fixed_diagnostic_manager, exe_ctx, execution_policy, + keep_expression_in_memory, generate_debug_info); + if (parse_success) { + diagnostic_manager.Clear(); + user_expression_sp = fixed_expression_sp; + break; + } else { + // The fixed expression also didn't parse. Let's check for any new + // Fix-Its we could try. + if (fixed_expression_sp->GetFixedText()) { + *fixed_expression = fixed_expression_sp->GetFixedText(); + } else { + // Fixed expression didn't compile without a fixit, don't retry and + // don't tell the user about it. + fixed_expression->clear(); + break; + } + } } } @@ -301,19 +314,12 @@ lldb::ExpressionResults UserExpression::Evaluate( } if (parse_success) { - // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module - // if one was created - if (jit_module_sp_ptr) - *jit_module_sp_ptr = user_expression_sp->GetJITModule(); - lldb::ExpressionVariableSP expr_result; if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { - if (log) - LLDB_LOGF(log, - "== [UserExpression::Evaluate] Expression may not run, but " - "is not constant =="); + LLDB_LOG(log, "== [UserExpression::Evaluate] Expression may not run, but " + "is not constant =="); if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError(lldb::eExpressionSetupError, @@ -333,17 +339,15 @@ lldb::ExpressionResults UserExpression::Evaluate( diagnostic_manager.Clear(); - if (log) - LLDB_LOGF(log, "== [UserExpression::Evaluate] Executing expression =="); + LLDB_LOG(log, "== [UserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result); if (execution_results != lldb::eExpressionCompleted) { - if (log) - LLDB_LOGF(log, "== [UserExpression::Evaluate] Execution completed " - "abnormally =="); + LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed " + "abnormally =="); if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError( @@ -355,15 +359,13 @@ lldb::ExpressionResults UserExpression::Evaluate( if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); - if (log) - LLDB_LOGF(log, - "== [UserExpression::Evaluate] Execution completed " - "normally with result %s ==", - result_valobj_sp->GetValueAsCString()); + LLDB_LOG(log, + "== [UserExpression::Evaluate] Execution completed " + "normally with result %s ==", + result_valobj_sp->GetValueAsCString()); } else { - if (log) - LLDB_LOGF(log, "== [UserExpression::Evaluate] Execution completed " - "normally with no result =="); + LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed " + "normally with no result =="); error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); } diff --git a/lldb/source/Expression/UtilityFunction.cpp b/lldb/source/Expression/UtilityFunction.cpp index 2dbc0e9d73edc..3de2ee2acbbf1 100644 --- a/lldb/source/Expression/UtilityFunction.cpp +++ b/lldb/source/Expression/UtilityFunction.cpp @@ -1,4 +1,4 @@ -//===-- UtilityFunction.cpp -------------------------------------*- C++ -*-===// +//===-- UtilityFunction.cpp -----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. |