diff options
Diffstat (limited to 'lldb/source/Expression')
| -rw-r--r-- | lldb/source/Expression/DWARFExpression.cpp | 118 | ||||
| -rw-r--r-- | lldb/source/Expression/ExpressionVariable.cpp | 8 | ||||
| -rw-r--r-- | lldb/source/Expression/IRExecutionUnit.cpp | 3 | ||||
| -rw-r--r-- | lldb/source/Expression/IRInterpreter.cpp | 10 | ||||
| -rw-r--r-- | lldb/source/Expression/Materializer.cpp | 34 | ||||
| -rw-r--r-- | lldb/source/Expression/REPL.cpp | 44 | ||||
| -rw-r--r-- | lldb/source/Expression/UserExpression.cpp | 1 | ||||
| -rw-r--r-- | lldb/source/Expression/UtilityFunction.cpp | 4 |
8 files changed, 138 insertions, 84 deletions
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 6050c1922564..c30fdf565cd5 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -89,8 +89,8 @@ void DWARFExpression::DumpLocation(Stream *s, const DataExtractor &data, lldb::DescriptionLevel level, ABI *abi) const { llvm::DWARFExpression(data.GetAsLLVM(), data.GetAddressByteSize()) - .print(s->AsRawOstream(), abi ? &abi->GetMCRegisterInfo() : nullptr, - nullptr); + .print(s->AsRawOstream(), llvm::DIDumpOptions(), + abi ? &abi->GetMCRegisterInfo() : nullptr, nullptr); } void DWARFExpression::SetLocationListAddresses(addr_t cu_file_addr, @@ -158,7 +158,7 @@ static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx, Value &value) { if (reg_ctx == nullptr) { if (error_ptr) - error_ptr->SetErrorStringWithFormat("No register context in frame.\n"); + error_ptr->SetErrorString("No register context in frame.\n"); } else { uint32_t native_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); @@ -941,6 +941,16 @@ bool DWARFExpression::Evaluate( Value pieces; // Used for DW_OP_piece Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + // A generic type is "an integral type that has the size of an address and an + // unspecified signedness". For now, just use the signedness of the operand. + // TODO: Implement a real typed stack, and store the genericness of the value + // there. + auto to_generic = [&](auto v) { + bool is_signed = std::is_signed<decltype(v)>::value; + return Scalar(llvm::APSInt( + llvm::APInt(8 * opcodes.GetAddressByteSize(), v, is_signed), + !is_signed)); + }; while (opcodes.ValidOffset(offset)) { const lldb::offset_t op_offset = offset; @@ -1036,22 +1046,21 @@ bool DWARFExpression::Evaluate( LLDB_INVALID_ADDRESS); if (!module_sp) { if (error_ptr) - error_ptr->SetErrorStringWithFormat( + error_ptr->SetErrorString( "need module to resolve file address for DW_OP_deref"); return false; } Address so_addr; if (!module_sp->ResolveFileAddress(file_addr, so_addr)) { if (error_ptr) - error_ptr->SetErrorStringWithFormat( + error_ptr->SetErrorString( "failed to resolve file address in module"); return false; } addr_t load_Addr = so_addr.GetLoadAddress(exe_ctx->GetTargetPtr()); if (load_Addr == LLDB_INVALID_ADDRESS) { if (error_ptr) - error_ptr->SetErrorStringWithFormat( - "failed to resolve load address"); + error_ptr->SetErrorString("failed to resolve load address"); return false; } stack.back().GetScalar() = load_Addr; @@ -1079,13 +1088,12 @@ bool DWARFExpression::Evaluate( } } else { if (error_ptr) - error_ptr->SetErrorStringWithFormat( - "NULL process for DW_OP_deref.\n"); + error_ptr->SetErrorString("NULL process for DW_OP_deref.\n"); return false; } } else { if (error_ptr) - error_ptr->SetErrorStringWithFormat( + error_ptr->SetErrorString( "NULL execution context for DW_OP_deref.\n"); return false; } @@ -1199,13 +1207,12 @@ bool DWARFExpression::Evaluate( } } else { if (error_ptr) - error_ptr->SetErrorStringWithFormat( - "NULL process for DW_OP_deref.\n"); + error_ptr->SetErrorString("NULL process for DW_OP_deref.\n"); return false; } } else { if (error_ptr) - error_ptr->SetErrorStringWithFormat( + error_ptr->SetErrorString( "NULL execution context for DW_OP_deref.\n"); return false; } @@ -1254,37 +1261,42 @@ bool DWARFExpression::Evaluate( // All DW_OP_constXXX opcodes have a single operand as noted below: // // Opcode Operand 1 - // DW_OP_const1u 1-byte unsigned integer constant DW_OP_const1s - // 1-byte signed integer constant DW_OP_const2u 2-byte unsigned integer - // constant DW_OP_const2s 2-byte signed integer constant DW_OP_const4u - // 4-byte unsigned integer constant DW_OP_const4s 4-byte signed integer - // constant DW_OP_const8u 8-byte unsigned integer constant DW_OP_const8s - // 8-byte signed integer constant DW_OP_constu unsigned LEB128 integer - // constant DW_OP_consts signed LEB128 integer constant + // DW_OP_const1u 1-byte unsigned integer constant + // DW_OP_const1s 1-byte signed integer constant + // DW_OP_const2u 2-byte unsigned integer constant + // DW_OP_const2s 2-byte signed integer constant + // DW_OP_const4u 4-byte unsigned integer constant + // DW_OP_const4s 4-byte signed integer constant + // DW_OP_const8u 8-byte unsigned integer constant + // DW_OP_const8s 8-byte signed integer constant + // DW_OP_constu unsigned LEB128 integer constant + // DW_OP_consts signed LEB128 integer constant case DW_OP_const1u: - stack.push_back(Scalar((uint8_t)opcodes.GetU8(&offset))); + stack.push_back(to_generic(opcodes.GetU8(&offset))); break; case DW_OP_const1s: - stack.push_back(Scalar((int8_t)opcodes.GetU8(&offset))); + stack.push_back(to_generic((int8_t)opcodes.GetU8(&offset))); break; case DW_OP_const2u: - stack.push_back(Scalar((uint16_t)opcodes.GetU16(&offset))); + stack.push_back(to_generic(opcodes.GetU16(&offset))); break; case DW_OP_const2s: - stack.push_back(Scalar((int16_t)opcodes.GetU16(&offset))); + stack.push_back(to_generic((int16_t)opcodes.GetU16(&offset))); break; case DW_OP_const4u: - stack.push_back(Scalar((uint32_t)opcodes.GetU32(&offset))); + stack.push_back(to_generic(opcodes.GetU32(&offset))); break; case DW_OP_const4s: - stack.push_back(Scalar((int32_t)opcodes.GetU32(&offset))); + stack.push_back(to_generic((int32_t)opcodes.GetU32(&offset))); break; case DW_OP_const8u: - stack.push_back(Scalar((uint64_t)opcodes.GetU64(&offset))); + stack.push_back(to_generic(opcodes.GetU64(&offset))); break; case DW_OP_const8s: - stack.push_back(Scalar((int64_t)opcodes.GetU64(&offset))); + stack.push_back(to_generic((int64_t)opcodes.GetU64(&offset))); break; + // These should also use to_generic, but we can't do that due to a + // producer-side bug in llvm. See llvm.org/pr48087. case DW_OP_constu: stack.push_back(Scalar(opcodes.GetULEB128(&offset))); break; @@ -1891,7 +1903,7 @@ bool DWARFExpression::Evaluate( case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31: - stack.push_back(Scalar((uint64_t)(op - DW_OP_lit0))); + stack.push_back(to_generic(op - DW_OP_lit0)); break; // OPCODE: DW_OP_regN @@ -2036,7 +2048,7 @@ bool DWARFExpression::Evaluate( } } else { if (error_ptr) - error_ptr->SetErrorStringWithFormat( + error_ptr->SetErrorString( "NULL execution context for DW_OP_fbreg.\n"); return false; } @@ -2156,20 +2168,6 @@ bool DWARFExpression::Evaluate( ap_int.getNumWords()}; curr_piece.GetScalar() = Scalar(llvm::APInt(bit_size, buf)); } break; - - case Value::eValueTypeVector: { - if (curr_piece_source_value.GetVector().length >= piece_byte_size) - curr_piece_source_value.GetVector().length = piece_byte_size; - else { - if (error_ptr) - error_ptr->SetErrorStringWithFormat( - "unable to extract %" PRIu64 " bytes from a %" PRIu64 - " byte vector value.", - piece_byte_size, - (uint64_t)curr_piece_source_value.GetVector().length); - return false; - } - } break; } // Check if this is the first piece? @@ -2238,19 +2236,33 @@ bool DWARFExpression::Evaluate( piece_bit_size, piece_bit_offset); } return false; - - case Value::eValueTypeVector: - if (error_ptr) { - error_ptr->SetErrorStringWithFormat( - "unable to extract DW_OP_bit_piece(bit_size = %" PRIu64 - ", bit_offset = %" PRIu64 ") from a vector value.", - piece_bit_size, piece_bit_offset); - } - return false; } } break; + // OPCODE: DW_OP_implicit_value + // OPERANDS: 2 + // ULEB128 size of the value block in bytes + // uint8_t* block bytes encoding value in target's memory + // representation + // DESCRIPTION: Value is immediately stored in block in the debug info with + // the memory representation of the target. + case DW_OP_implicit_value: { + const uint32_t len = opcodes.GetULEB128(&offset); + const void *data = opcodes.GetData(&offset, len); + + if (!data) { + LLDB_LOG(log, "Evaluate_DW_OP_implicit_value: could not be read data"); + LLDB_ERRORF(error_ptr, "Could not evaluate %s.", + DW_OP_value_to_name(op)); + return false; + } + + Value result(data, len); + stack.push_back(result); + break; + } + // OPCODE: DW_OP_push_object_address // OPERANDS: none // DESCRIPTION: Pushes the address of the object currently being diff --git a/lldb/source/Expression/ExpressionVariable.cpp b/lldb/source/Expression/ExpressionVariable.cpp index d95f0745cf4b..8b3dda7b2fe1 100644 --- a/lldb/source/Expression/ExpressionVariable.cpp +++ b/lldb/source/Expression/ExpressionVariable.cpp @@ -16,10 +16,10 @@ using namespace lldb_private; ExpressionVariable::~ExpressionVariable() {} uint8_t *ExpressionVariable::GetValueBytes() { - const size_t byte_size = m_frozen_sp->GetByteSize(); - if (byte_size > 0) { - if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size) { - m_frozen_sp->GetValue().ResizeData(byte_size); + llvm::Optional<uint64_t> byte_size = m_frozen_sp->GetByteSize(); + if (byte_size && *byte_size) { + if (m_frozen_sp->GetDataExtractor().GetByteSize() < *byte_size) { + m_frozen_sp->GetValue().ResizeData(*byte_size); m_frozen_sp->GetValue().GetData(m_frozen_sp->GetDataExtractor()); } return const_cast<uint8_t *>( diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index e3c9c1d7fdf5..538935da52ee 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -328,8 +328,7 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, if (function.isDeclaration() || function.hasPrivateLinkage()) continue; - const bool external = - function.hasExternalLinkage() || function.hasLinkOnceODRLinkage(); + const bool external = !function.hasLocalLinkage(); void *fun_ptr = m_execution_engine_up->getPointerToFunction(&function); diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index 4c7a65626598..b87a759aadc5 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -1356,14 +1356,14 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, // Check we can actually get a thread if (exe_ctx.GetThreadPtr() == nullptr) { error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("unable to acquire thread"); + error.SetErrorString("unable to acquire thread"); return false; } // Make sure we have a valid process if (!exe_ctx.GetProcessPtr()) { error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("unable to get the process"); + error.SetErrorString("unable to get the process"); return false; } @@ -1404,7 +1404,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, static lldb_private::ABI::CallArgument rawArgs[16]; if (numArgs >= 16) { error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("function takes too many arguments"); + error.SetErrorString("function takes too many arguments"); return false; } @@ -1490,7 +1490,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, // Check that the thread plan completed successfully if (res != lldb::ExpressionResults::eExpressionCompleted) { error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("ThreadPlanCallFunctionUsingABI failed"); + error.SetErrorString("ThreadPlanCallFunctionUsingABI failed"); return false; } @@ -1511,7 +1511,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, // Check if the return value is valid if (vobj == nullptr || !retVal) { error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("unable to get the return value"); + error.SetErrorString("unable to get the return value"); return false; } diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp index f33462053f22..a93c127dd0d0 100644 --- a/lldb/source/Expression/Materializer.cpp +++ b/lldb/source/Expression/Materializer.cpp @@ -67,7 +67,7 @@ public: const bool zero_memory = false; lldb::addr_t mem = map.Malloc( - m_persistent_variable_sp->GetByteSize(), 8, + m_persistent_variable_sp->GetByteSize().getValueOr(0), 8, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, zero_memory, allocate_error); @@ -106,7 +106,8 @@ public: Status write_error; map.WriteMemory(mem, m_persistent_variable_sp->GetValueBytes(), - m_persistent_variable_sp->GetByteSize(), write_error); + m_persistent_variable_sp->GetByteSize().getValueOr(0), + write_error); if (!write_error.Success()) { err.SetErrorStringWithFormat( @@ -234,7 +235,7 @@ public: map.GetBestExecutionContextScope(), m_persistent_variable_sp.get()->GetCompilerType(), m_persistent_variable_sp->GetName(), location, eAddressTypeLoad, - m_persistent_variable_sp->GetByteSize()); + m_persistent_variable_sp->GetByteSize().getValueOr(0)); if (frame_top != LLDB_INVALID_ADDRESS && frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom && @@ -279,7 +280,8 @@ public: LLDB_LOGF(log, "Dematerializing %s from 0x%" PRIx64 " (size = %llu)", m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, - (unsigned long long)m_persistent_variable_sp->GetByteSize()); + (unsigned long long)m_persistent_variable_sp->GetByteSize() + .getValueOr(0)); // Read the contents of the spare memory area @@ -288,7 +290,7 @@ public: Status read_error; map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), mem, - m_persistent_variable_sp->GetByteSize(), read_error); + m_persistent_variable_sp->GetByteSize().getValueOr(0), read_error); if (!read_error.Success()) { err.SetErrorStringWithFormat( @@ -369,10 +371,11 @@ public: if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); } else { - DataBufferHeap data(m_persistent_variable_sp->GetByteSize(), 0); + DataBufferHeap data( + m_persistent_variable_sp->GetByteSize().getValueOr(0), 0); map.ReadMemory(data.GetBytes(), target_address, - m_persistent_variable_sp->GetByteSize(), err); + m_persistent_variable_sp->GetByteSize().getValueOr(0), err); if (!err.Success()) { dump_stream.Printf(" <could not be read>\n"); @@ -514,7 +517,7 @@ public: return; } - if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) { + if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize(scope)) { if (data.GetByteSize() == 0 && !m_variable_sp->LocationExpression().IsValid()) { err.SetErrorStringWithFormat("the variable '%s' has no location, " @@ -525,7 +528,7 @@ public: "size of variable %s (%" PRIu64 ") is larger than the ValueObject's size (%" PRIu64 ")", m_variable_sp->GetName().AsCString(), - m_variable_sp->GetType()->GetByteSize().getValueOr(0), + m_variable_sp->GetType()->GetByteSize(scope).getValueOr(0), data.GetByteSize()); } return; @@ -621,8 +624,8 @@ public: Status extract_error; - map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), - extract_error); + map.GetMemoryData(data, m_temporary_allocation, + valobj_sp->GetByteSize().getValueOr(0), extract_error); if (!extract_error.Success()) { err.SetErrorStringWithFormat("couldn't get the data for variable %s", @@ -797,7 +800,7 @@ public: llvm::Optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope); if (!opt_bit_align) { - err.SetErrorStringWithFormat("can't get the type alignment"); + err.SetErrorString("can't get the type alignment"); return; } @@ -919,7 +922,7 @@ public: ret->ValueUpdated(); - const size_t pvar_byte_size = ret->GetByteSize(); + const size_t pvar_byte_size = ret->GetByteSize().getValueOr(0); uint8_t *pvar_data = ret->GetValueBytes(); map.ReadMemory(pvar_data, address, pvar_byte_size, read_error); @@ -1279,9 +1282,8 @@ public: m_register_contents.reset(); - RegisterValue register_value( - const_cast<uint8_t *>(register_data.GetDataStart()), - register_data.GetByteSize(), register_data.GetByteOrder()); + RegisterValue register_value(register_data.GetData(), + register_data.GetByteOrder()); if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) { err.SetErrorStringWithFormat("couldn't write the value of register %s", diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp index fd7c39686921..c3d14960f74c 100644 --- a/lldb/source/Expression/REPL.cpp +++ b/lldb/source/Expression/REPL.cpp @@ -123,10 +123,11 @@ const char *REPL::IOHandlerGetHelpPrologue() { "Valid statements, expressions, and declarations are immediately " "compiled and executed.\n\n" "The complete set of LLDB debugging commands are also available as " - "described below. Commands " + "described below.\n\nCommands " "must be prefixed with a colon at the REPL prompt (:quit for " "example.) Typing just a colon " - "followed by return will switch to the LLDB prompt.\n\n"; + "followed by return will switch to the LLDB prompt.\n\n" + "Type “< path” to read in code from a text file “path”.\n\n"; } bool REPL::IOHandlerIsInputComplete(IOHandler &io_handler, StringList &lines) { @@ -179,6 +180,36 @@ int REPL::IOHandlerFixIndentation(IOHandler &io_handler, return (int)desired_indent - actual_indent; } +static bool ReadCode(const std::string &path, std::string &code, + lldb::StreamFileSP &error_sp) { + auto &fs = FileSystem::Instance(); + llvm::Twine pathTwine(path); + if (!fs.Exists(pathTwine)) { + error_sp->Printf("no such file at path '%s'\n", path.c_str()); + return false; + } + if (!fs.Readable(pathTwine)) { + error_sp->Printf("could not read file at path '%s'\n", path.c_str()); + return false; + } + const size_t file_size = fs.GetByteSize(pathTwine); + const size_t max_size = code.max_size(); + if (file_size > max_size) { + error_sp->Printf("file at path '%s' too large: " + "file_size = %zu, max_size = %zu\n", + path.c_str(), file_size, max_size); + return false; + } + auto data_sp = fs.CreateDataBuffer(pathTwine); + if (data_sp == nullptr) { + error_sp->Printf("could not create buffer for file at path '%s'\n", + path.c_str()); + return false; + } + code.assign((const char *)data_sp->GetBytes(), data_sp->GetByteSize()); + return true; +} + void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFileSP()); @@ -257,6 +288,15 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { } } } else { + if (code[0] == '<') { + // User wants to read code from a file. + // Interpret rest of line as a literal path. + auto path = llvm::StringRef(code.substr(1)).trim().str(); + if (!ReadCode(path, code, error_sp)) { + return; + } + } + // Unwind any expression we might have been running in case our REPL // expression crashed and the user was looking around if (m_dedicated_repl_mode) { diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp index 47d13f052bfb..5beed4657b37 100644 --- a/lldb/source/Expression/UserExpression.cpp +++ b/lldb/source/Expression/UserExpression.cpp @@ -358,6 +358,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx, } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); + result_valobj_sp->SetPreferredDisplayLanguage(language); LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed " diff --git a/lldb/source/Expression/UtilityFunction.cpp b/lldb/source/Expression/UtilityFunction.cpp index 3de2ee2acbbf..128db0ccbc3e 100644 --- a/lldb/source/Expression/UtilityFunction.cpp +++ b/lldb/source/Expression/UtilityFunction.cpp @@ -41,9 +41,9 @@ char UtilityFunction::ID; /// \param[in] name /// The name of the function, as used in the text. UtilityFunction::UtilityFunction(ExecutionContextScope &exe_scope, - const char *text, const char *name) + std::string text, std::string name) : Expression(exe_scope), m_execution_unit_sp(), m_jit_module_wp(), - m_function_text(), m_function_name(name) {} + m_function_text(std::move(text)), m_function_name(std::move(name)) {} UtilityFunction::~UtilityFunction() { lldb::ProcessSP process_sp(m_jit_process_wp.lock()); |
