999 lines · cpp
1//===-- ClangUserExpression.cpp -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <cstdio>10#include <sys/types.h>11 12#include <cstdlib>13#include <map>14#include <string>15 16#include "ClangUserExpression.h"17 18#include "ASTResultSynthesizer.h"19#include "ClangASTMetadata.h"20#include "ClangDiagnostic.h"21#include "ClangExpressionDeclMap.h"22#include "ClangExpressionParser.h"23#include "ClangModulesDeclVendor.h"24#include "ClangPersistentVariables.h"25#include "CppModuleConfiguration.h"26 27#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"28#include "lldb/Core/Debugger.h"29#include "lldb/Core/Module.h"30#include "lldb/Expression/ExpressionSourceCode.h"31#include "lldb/Expression/IRExecutionUnit.h"32#include "lldb/Expression/IRInterpreter.h"33#include "lldb/Expression/Materializer.h"34#include "lldb/Host/HostInfo.h"35#include "lldb/Symbol/Block.h"36#include "lldb/Symbol/CompileUnit.h"37#include "lldb/Symbol/Function.h"38#include "lldb/Symbol/ObjectFile.h"39#include "lldb/Symbol/SymbolFile.h"40#include "lldb/Symbol/SymbolVendor.h"41#include "lldb/Symbol/Type.h"42#include "lldb/Symbol/VariableList.h"43#include "lldb/Target/ExecutionContext.h"44#include "lldb/Target/Process.h"45#include "lldb/Target/StackFrame.h"46#include "lldb/Target/Target.h"47#include "lldb/Target/ThreadPlan.h"48#include "lldb/Target/ThreadPlanCallUserExpression.h"49#include "lldb/Utility/ConstString.h"50#include "lldb/Utility/LLDBLog.h"51#include "lldb/Utility/Log.h"52#include "lldb/Utility/StreamString.h"53#include "lldb/ValueObject/ValueObjectConstResult.h"54 55#include "clang/AST/DeclCXX.h"56#include "clang/AST/DeclObjC.h"57 58#include "llvm/ADT/ScopeExit.h"59#include "llvm/BinaryFormat/Dwarf.h"60 61using namespace lldb_private;62 63char ClangUserExpression::ID;64 65ClangUserExpression::ClangUserExpression(66 ExecutionContextScope &exe_scope, llvm::StringRef expr,67 llvm::StringRef prefix, SourceLanguage language, ResultType desired_type,68 const EvaluateExpressionOptions &options, ValueObject *ctx_obj)69 : LLVMUserExpression(exe_scope, expr, prefix, language, desired_type,70 options),71 m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() ==72 eExecutionPolicyTopLevel),73 m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) {74 switch (m_language.name) {75 case llvm::dwarf::DW_LNAME_C_plus_plus:76 m_allow_cxx = true;77 break;78 case llvm::dwarf::DW_LNAME_ObjC:79 m_allow_objc = true;80 break;81 case llvm::dwarf::DW_LNAME_ObjC_plus_plus:82 default:83 m_allow_cxx = true;84 m_allow_objc = true;85 break;86 }87}88 89ClangUserExpression::~ClangUserExpression() = default;90 91void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {92 Log *log = GetLog(LLDBLog::Expressions);93 94 LLDB_LOGF(log, "ClangUserExpression::ScanContext()");95 96 m_target = exe_ctx.GetTargetPtr();97 98 if (!(m_allow_cxx || m_allow_objc)) {99 LLDB_LOGF(log, " [CUE::SC] Settings inhibit C++ and Objective-C");100 return;101 }102 103 StackFrame *frame = exe_ctx.GetFramePtr();104 if (frame == nullptr) {105 LLDB_LOGF(log, " [CUE::SC] Null stack frame");106 return;107 }108 109 SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |110 lldb::eSymbolContextBlock);111 112 if (!sym_ctx.function) {113 LLDB_LOGF(log, " [CUE::SC] Null function");114 return;115 }116 117 // Find the block that defines the function represented by "sym_ctx"118 Block *function_block = sym_ctx.GetFunctionBlock();119 120 if (!function_block) {121 LLDB_LOGF(log, " [CUE::SC] Null function block");122 return;123 }124 125 CompilerDeclContext decl_context = function_block->GetDeclContext();126 127 if (!decl_context) {128 LLDB_LOGF(log, " [CUE::SC] Null decl context");129 return;130 }131 132 if (m_ctx_obj) {133 switch (m_ctx_obj->GetObjectRuntimeLanguage()) {134 case lldb::eLanguageTypeC:135 case lldb::eLanguageTypeC89:136 case lldb::eLanguageTypeC99:137 case lldb::eLanguageTypeC11:138 case lldb::eLanguageTypeC_plus_plus:139 case lldb::eLanguageTypeC_plus_plus_03:140 case lldb::eLanguageTypeC_plus_plus_11:141 case lldb::eLanguageTypeC_plus_plus_14:142 m_in_cplusplus_method = true;143 break;144 case lldb::eLanguageTypeObjC:145 case lldb::eLanguageTypeObjC_plus_plus:146 m_in_objectivec_method = true;147 break;148 default:149 break;150 }151 m_needs_object_ptr = true;152 } else if (clang::CXXMethodDecl *method_decl =153 TypeSystemClang::DeclContextGetAsCXXMethodDecl(decl_context)) {154 if (m_allow_cxx && method_decl->isInstance()) {155 if (m_enforce_valid_object) {156 lldb::VariableListSP variable_list_sp(157 function_block->GetBlockVariableList(true));158 159 const char *thisErrorString = "Stopped in a C++ method, but 'this' "160 "isn't available; pretending we are in a "161 "generic context";162 163 if (!variable_list_sp) {164 err = Status::FromErrorString(thisErrorString);165 return;166 }167 168 lldb::VariableSP this_var_sp(169 variable_list_sp->FindVariable(ConstString("this")));170 171 if (!this_var_sp || !this_var_sp->IsInScope(frame) ||172 !this_var_sp->LocationIsValidForFrame(frame)) {173 err = Status::FromErrorString(thisErrorString);174 return;175 }176 }177 178 m_in_cplusplus_method = true;179 m_needs_object_ptr = true;180 }181 } else if (clang::ObjCMethodDecl *method_decl =182 TypeSystemClang::DeclContextGetAsObjCMethodDecl(183 decl_context)) {184 if (m_allow_objc) {185 if (m_enforce_valid_object) {186 lldb::VariableListSP variable_list_sp(187 function_block->GetBlockVariableList(true));188 189 const char *selfErrorString = "Stopped in an Objective-C method, but "190 "'self' isn't available; pretending we "191 "are in a generic context";192 193 if (!variable_list_sp) {194 err = Status::FromErrorString(selfErrorString);195 return;196 }197 198 lldb::VariableSP self_variable_sp =199 variable_list_sp->FindVariable(ConstString("self"));200 201 if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||202 !self_variable_sp->LocationIsValidForFrame(frame)) {203 err = Status::FromErrorString(selfErrorString);204 return;205 }206 }207 208 m_in_objectivec_method = true;209 m_needs_object_ptr = true;210 211 if (!method_decl->isInstanceMethod())212 m_in_static_method = true;213 }214 } else if (clang::FunctionDecl *function_decl =215 TypeSystemClang::DeclContextGetAsFunctionDecl(decl_context)) {216 // We might also have a function that said in the debug information that it217 // captured an object pointer. The best way to deal with getting to the218 // ivars at present is by pretending that this is a method of a class in219 // whatever runtime the debug info says the object pointer belongs to. Do220 // that here.221 222 if (std::optional<ClangASTMetadata> metadata =223 TypeSystemClang::DeclContextGetMetaData(decl_context,224 function_decl);225 metadata && metadata->HasObjectPtr()) {226 lldb::LanguageType language = metadata->GetObjectPtrLanguage();227 if (language == lldb::eLanguageTypeC_plus_plus) {228 if (m_enforce_valid_object) {229 lldb::VariableListSP variable_list_sp(230 function_block->GetBlockVariableList(true));231 232 const char *thisErrorString = "Stopped in a context claiming to "233 "capture a C++ object pointer, but "234 "'this' isn't available; pretending we "235 "are in a generic context";236 237 if (!variable_list_sp) {238 err = Status::FromErrorString(thisErrorString);239 return;240 }241 242 lldb::VariableSP this_var_sp(243 variable_list_sp->FindVariable(ConstString("this")));244 245 if (!this_var_sp || !this_var_sp->IsInScope(frame) ||246 !this_var_sp->LocationIsValidForFrame(frame)) {247 err = Status::FromErrorString(thisErrorString);248 return;249 }250 }251 252 m_in_cplusplus_method = true;253 m_needs_object_ptr = true;254 } else if (language == lldb::eLanguageTypeObjC) {255 if (m_enforce_valid_object) {256 lldb::VariableListSP variable_list_sp(257 function_block->GetBlockVariableList(true));258 259 const char *selfErrorString =260 "Stopped in a context claiming to capture an Objective-C object "261 "pointer, but 'self' isn't available; pretending we are in a "262 "generic context";263 264 if (!variable_list_sp) {265 err = Status::FromErrorString(selfErrorString);266 return;267 }268 269 lldb::VariableSP self_variable_sp =270 variable_list_sp->FindVariable(ConstString("self"));271 272 if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||273 !self_variable_sp->LocationIsValidForFrame(frame)) {274 err = Status::FromErrorString(selfErrorString);275 return;276 }277 278 Type *self_type = self_variable_sp->GetType();279 280 if (!self_type) {281 err = Status::FromErrorString(selfErrorString);282 return;283 }284 285 CompilerType self_clang_type = self_type->GetForwardCompilerType();286 287 if (!self_clang_type) {288 err = Status::FromErrorString(selfErrorString);289 return;290 }291 292 if (TypeSystemClang::IsObjCClassType(self_clang_type)) {293 return;294 } else if (TypeSystemClang::IsObjCObjectPointerType(295 self_clang_type)) {296 m_in_objectivec_method = true;297 m_needs_object_ptr = true;298 } else {299 err = Status::FromErrorString(selfErrorString);300 return;301 }302 } else {303 m_in_objectivec_method = true;304 m_needs_object_ptr = true;305 }306 }307 }308 }309}310 311// This is a really nasty hack, meant to fix Objective-C expressions of the312// form (int)[myArray count]. Right now, because the type information for313// count is not available, [myArray count] returns id, which can't be directly314// cast to int without causing a clang error.315static void ApplyObjcCastHack(std::string &expr) {316 const std::string from = "(int)[";317 const std::string to = "(int)(long long)[";318 319 size_t offset;320 321 while ((offset = expr.find(from)) != expr.npos)322 expr.replace(offset, from.size(), to);323}324 325bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,326 ExecutionContext &exe_ctx) {327 if (Target *target = exe_ctx.GetTargetPtr()) {328 if (PersistentExpressionState *persistent_state =329 target->GetPersistentExpressionStateForLanguage(330 lldb::eLanguageTypeC)) {331 m_clang_state = llvm::cast<ClangPersistentVariables>(persistent_state);332 m_result_delegate.RegisterPersistentState(persistent_state);333 } else {334 diagnostic_manager.PutString(335 lldb::eSeverityError, "couldn't start parsing (no persistent data)");336 return false;337 }338 } else {339 diagnostic_manager.PutString(lldb::eSeverityError,340 "error: couldn't start parsing (no target)");341 return false;342 }343 return true;344}345 346static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target,347 DiagnosticManager &diagnostic_manager) {348 if (!target->GetEnableAutoImportClangModules())349 return;350 351 auto *persistent_state = llvm::cast<ClangPersistentVariables>(352 target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));353 if (!persistent_state)354 return;355 356 std::shared_ptr<ClangModulesDeclVendor> decl_vendor =357 persistent_state->GetClangModulesDeclVendor();358 if (!decl_vendor)359 return;360 361 StackFrame *frame = exe_ctx.GetFramePtr();362 if (!frame)363 return;364 365 Block *block = frame->GetFrameBlock();366 if (!block)367 return;368 SymbolContext sc;369 370 block->CalculateSymbolContext(&sc);371 372 if (!sc.comp_unit)373 return;374 ClangModulesDeclVendor::ModuleVector modules_for_macros =375 persistent_state->GetHandLoadedClangModules();376 377 auto err =378 decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros);379 if (!err)380 return;381 382 // Module load errors aren't fatal to the expression evaluator. Printing383 // them as diagnostics to the console would be too noisy and misleading384 // Hence just print them to the expression log.385 llvm::handleAllErrors(std::move(err), [](const llvm::StringError &e) {386 LLDB_LOG(GetLog(LLDBLog::Expressions), "{0}", e.getMessage());387 });388}389 390ClangExpressionSourceCode::WrapKind ClangUserExpression::GetWrapKind() const {391 assert(m_options.GetExecutionPolicy() != eExecutionPolicyTopLevel &&392 "Top level expressions aren't wrapped.");393 using Kind = ClangExpressionSourceCode::WrapKind;394 if (m_in_cplusplus_method)395 return Kind::CppMemberFunction;396 else if (m_in_objectivec_method) {397 if (m_in_static_method)398 return Kind::ObjCStaticMethod;399 return Kind::ObjCInstanceMethod;400 }401 // Not in any kind of 'special' function, so just wrap it in a normal C402 // function.403 return Kind::Function;404}405 406void ClangUserExpression::CreateSourceCode(407 DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,408 std::vector<std::string> modules_to_import, bool for_completion) {409 410 std::string prefix = m_expr_prefix;411 412 if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {413 m_transformed_text = m_expr_text;414 } else {415 m_source_code.reset(ClangExpressionSourceCode::CreateWrapped(416 m_filename, prefix, m_expr_text, GetWrapKind()));417 418 if (!m_source_code->GetText(m_transformed_text, exe_ctx, !m_ctx_obj,419 for_completion, modules_to_import)) {420 diagnostic_manager.PutString(lldb::eSeverityError,421 "couldn't construct expression body");422 return;423 }424 425 // Find and store the start position of the original code inside the426 // transformed code. We need this later for the code completion.427 std::size_t original_start;428 std::size_t original_end;429 bool found_bounds = m_source_code->GetOriginalBodyBounds(430 m_transformed_text, original_start, original_end);431 if (found_bounds)432 m_user_expression_start_pos = original_start;433 }434}435 436static bool SupportsCxxModuleImport(lldb::LanguageType language) {437 switch (language) {438 case lldb::eLanguageTypeC_plus_plus:439 case lldb::eLanguageTypeC_plus_plus_03:440 case lldb::eLanguageTypeC_plus_plus_11:441 case lldb::eLanguageTypeC_plus_plus_14:442 case lldb::eLanguageTypeObjC_plus_plus:443 return true;444 default:445 return false;446 }447}448 449/// Utility method that puts a message into the expression log and450/// returns an invalid module configuration.451static CppModuleConfiguration LogConfigError(const std::string &msg) {452 Log *log = GetLog(LLDBLog::Expressions);453 LLDB_LOG(log, "[C++ module config] {0}", msg);454 return CppModuleConfiguration();455}456 457CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,458 ExecutionContext &exe_ctx) {459 Log *log = GetLog(LLDBLog::Expressions);460 461 // Don't do anything if this is not a C++ module configuration.462 if (!SupportsCxxModuleImport(language))463 return LogConfigError("Language doesn't support C++ modules");464 465 Target *target = exe_ctx.GetTargetPtr();466 if (!target)467 return LogConfigError("No target");468 469 StackFrame *frame = exe_ctx.GetFramePtr();470 if (!frame)471 return LogConfigError("No frame");472 473 Block *block = frame->GetFrameBlock();474 if (!block)475 return LogConfigError("No block");476 477 SymbolContext sc;478 block->CalculateSymbolContext(&sc);479 if (!sc.comp_unit)480 return LogConfigError("Couldn't calculate symbol context");481 482 // Build a list of files we need to analyze to build the configuration.483 FileSpecList files;484 for (auto &f : sc.comp_unit->GetSupportFiles())485 files.AppendIfUnique(f->Materialize());486 // We also need to look at external modules in the case of -gmodules as they487 // contain the support files for libc++ and the C library.488 llvm::DenseSet<SymbolFile *> visited_symbol_files;489 sc.comp_unit->ForEachExternalModule(490 visited_symbol_files, [&files](Module &module) {491 for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) {492 const SupportFileList &support_files =493 module.GetCompileUnitAtIndex(i)->GetSupportFiles();494 for (auto &f : support_files) {495 files.AppendIfUnique(f->Materialize());496 }497 }498 return false;499 });500 501 LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze",502 files.GetSize());503 if (log && log->GetVerbose()) {504 for (auto &f : files)505 LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}",506 f.GetPath());507 }508 509 // Try to create a configuration from the files. If there is no valid510 // configuration possible with the files, this just returns an invalid511 // configuration.512 return CppModuleConfiguration(files, target->GetArchitecture().GetTriple());513}514 515bool ClangUserExpression::PrepareForParsing(516 DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,517 bool for_completion) {518 InstallContext(exe_ctx);519 520 if (!SetupPersistentState(diagnostic_manager, exe_ctx))521 return false;522 523 Status err;524 ScanContext(exe_ctx, err);525 526 if (!err.Success()) {527 diagnostic_manager.PutString(lldb::eSeverityWarning, err.AsCString());528 }529 530 ////////////////////////////////////531 // Generate the expression532 //533 534 ApplyObjcCastHack(m_expr_text);535 536 SetupDeclVendor(exe_ctx, m_target, diagnostic_manager);537 538 m_filename = m_clang_state->GetNextExprFileName();539 540 if (m_target->GetImportStdModule() == eImportStdModuleTrue)541 SetupCppModuleImports(exe_ctx);542 543 CreateSourceCode(diagnostic_manager, exe_ctx, m_imported_cpp_modules,544 for_completion);545 return true;546}547 548bool ClangUserExpression::TryParse(549 DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,550 lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory,551 bool generate_debug_info) {552 m_materializer_up = std::make_unique<Materializer>();553 554 ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);555 556 auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });557 558 if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {559 diagnostic_manager.PutString(560 lldb::eSeverityError,561 "current process state is unsuitable for expression parsing");562 return false;563 }564 565 if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {566 DeclMap()->SetLookupsEnabled(true);567 }568 569 m_parser = std::make_unique<ClangExpressionParser>(570 exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info,571 diagnostic_manager, m_include_directories, m_filename);572 573 unsigned num_errors = m_parser->Parse(diagnostic_manager);574 575 // Check here for FixItHints. If there are any try to apply the fixits and576 // set the fixed text in m_fixed_text before returning an error.577 if (num_errors) {578 if (diagnostic_manager.HasFixIts()) {579 if (m_parser->RewriteExpression(diagnostic_manager)) {580 size_t fixed_start;581 size_t fixed_end;582 m_fixed_text = diagnostic_manager.GetFixedExpression();583 // Retrieve the original expression in case we don't have a top level584 // expression (which has no surrounding source code).585 if (m_source_code && m_source_code->GetOriginalBodyBounds(586 m_fixed_text, fixed_start, fixed_end))587 m_fixed_text =588 m_fixed_text.substr(fixed_start, fixed_end - fixed_start);589 }590 }591 return false;592 }593 594 //////////////////////////////////////////////////////////////////////////////595 // Prepare the output of the parser for execution, evaluating it statically596 // if possible597 //598 599 {600 Status jit_error = m_parser->PrepareForExecution(601 m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,602 m_can_interpret, execution_policy);603 604 if (!jit_error.Success()) {605 const char *error_cstr = jit_error.AsCString();606 if (error_cstr && error_cstr[0])607 diagnostic_manager.PutString(lldb::eSeverityError, error_cstr);608 else609 diagnostic_manager.PutString(lldb::eSeverityError,610 "expression can't be interpreted or run");611 return false;612 }613 }614 return true;615}616 617void ClangUserExpression::SetupCppModuleImports(ExecutionContext &exe_ctx) {618 Log *log = GetLog(LLDBLog::Expressions);619 620 CppModuleConfiguration module_config =621 GetModuleConfig(m_language.AsLanguageType(), exe_ctx);622 m_imported_cpp_modules = module_config.GetImportedModules();623 m_include_directories = module_config.GetIncludeDirs();624 625 LLDB_LOG(log, "List of imported modules in expression: {0}",626 llvm::make_range(m_imported_cpp_modules.begin(),627 m_imported_cpp_modules.end()));628 LLDB_LOG(log, "List of include directories gathered for modules: {0}",629 llvm::make_range(m_include_directories.begin(),630 m_include_directories.end()));631}632 633static bool shouldRetryWithCppModule(Target &target, ExecutionPolicy exe_policy) {634 // Top-level expression don't yet support importing C++ modules.635 if (exe_policy == ExecutionPolicy::eExecutionPolicyTopLevel)636 return false;637 return target.GetImportStdModule() == eImportStdModuleFallback;638}639 640bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,641 ExecutionContext &exe_ctx,642 lldb_private::ExecutionPolicy execution_policy,643 bool keep_result_in_memory,644 bool generate_debug_info) {645 Log *log = GetLog(LLDBLog::Expressions);646 647 if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false))648 return false;649 650 LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());651 652 ////////////////////////////////////653 // Set up the target and compiler654 //655 656 Target *target = exe_ctx.GetTargetPtr();657 658 if (!target) {659 diagnostic_manager.PutString(lldb::eSeverityError, "invalid target");660 return false;661 }662 663 //////////////////////////664 // Parse the expression665 //666 667 bool parse_success = TryParse(diagnostic_manager, exe_ctx, execution_policy,668 keep_result_in_memory, generate_debug_info);669 // If the expression failed to parse, check if retrying parsing with a loaded670 // C++ module is possible.671 if (!parse_success && shouldRetryWithCppModule(*target, execution_policy)) {672 // Load the loaded C++ modules.673 SetupCppModuleImports(exe_ctx);674 // If we did load any modules, then retry parsing.675 if (!m_imported_cpp_modules.empty()) {676 // Create a dedicated diagnostic manager for the second parse attempt.677 // These diagnostics are only returned to the caller if using the fallback678 // actually succeeded in getting the expression to parse. This prevents679 // that module-specific issues regress diagnostic quality with the680 // fallback mode.681 DiagnosticManager retry_manager;682 // The module imports are injected into the source code wrapper,683 // so recreate those.684 CreateSourceCode(retry_manager, exe_ctx, m_imported_cpp_modules,685 /*for_completion*/ false);686 parse_success = TryParse(retry_manager, exe_ctx, execution_policy,687 keep_result_in_memory, generate_debug_info);688 // Return the parse diagnostics if we were successful.689 if (parse_success)690 diagnostic_manager = std::move(retry_manager);691 }692 }693 if (!parse_success)694 return false;695 696 if (m_execution_unit_sp) {697 bool register_execution_unit = false;698 699 if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {700 register_execution_unit = true;701 }702 703 // If there is more than one external function in the execution unit, it704 // needs to keep living even if it's not top level, because the result705 // could refer to that function.706 707 if (m_execution_unit_sp->GetJittedFunctions().size() > 1) {708 register_execution_unit = true;709 }710 711 if (register_execution_unit) {712 if (auto *persistent_state =713 exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(714 m_language.AsLanguageType()))715 persistent_state->RegisterExecutionUnit(m_execution_unit_sp);716 }717 }718 719 if (generate_debug_info) {720 lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());721 722 if (jit_module_sp) {723 ConstString const_func_name(FunctionName());724 FileSpec jit_file;725 jit_file.SetFilename(const_func_name);726 jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());727 m_jit_module_wp = jit_module_sp;728 target->GetImages().Append(jit_module_sp);729 }730 }731 732 Process *process = exe_ctx.GetProcessPtr();733 if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)734 m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());735 return true;736}737 738/// Converts an absolute position inside a given code string into739/// a column/line pair.740///741/// \param[in] abs_pos742/// A absolute position in the code string that we want to convert743/// to a column/line pair.744///745/// \param[in] code746/// A multi-line string usually representing source code.747///748/// \param[out] line749/// The line in the code that contains the given absolute position.750/// The first line in the string is indexed as 1.751///752/// \param[out] column753/// The column in the line that contains the absolute position.754/// The first character in a line is indexed as 0.755static void AbsPosToLineColumnPos(size_t abs_pos, llvm::StringRef code,756 unsigned &line, unsigned &column) {757 // Reset to code position to beginning of the file.758 line = 0;759 column = 0;760 761 assert(abs_pos <= code.size() && "Absolute position outside code string?");762 763 // We have to walk up to the position and count lines/columns.764 for (std::size_t i = 0; i < abs_pos; ++i) {765 // If we hit a line break, we go back to column 0 and enter a new line.766 // We only handle \n because that's what we internally use to make new767 // lines for our temporary code strings.768 if (code[i] == '\n') {769 ++line;770 column = 0;771 continue;772 }773 ++column;774 }775}776 777bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,778 CompletionRequest &request,779 unsigned complete_pos) {780 Log *log = GetLog(LLDBLog::Expressions);781 782 // We don't want any visible feedback when completing an expression. Mostly783 // because the results we get from an incomplete invocation are probably not784 // correct.785 DiagnosticManager diagnostic_manager;786 787 if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true))788 return false;789 790 LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());791 792 //////////////////////////793 // Parse the expression794 //795 796 m_materializer_up = std::make_unique<Materializer>();797 798 ResetDeclMap(exe_ctx, m_result_delegate, /*keep result in memory*/ true);799 800 auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });801 802 if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {803 diagnostic_manager.PutString(804 lldb::eSeverityError,805 "current process state is unsuitable for expression parsing");806 807 return false;808 }809 810 if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {811 DeclMap()->SetLookupsEnabled(true);812 }813 814 ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,815 false, diagnostic_manager);816 817 // We have to find the source code location where the user text is inside818 // the transformed expression code. When creating the transformed text, we819 // already stored the absolute position in the m_transformed_text string. The820 // only thing left to do is to transform it into the line:column format that821 // Clang expects.822 823 // The line and column of the user expression inside the transformed source824 // code.825 unsigned user_expr_line, user_expr_column;826 if (m_user_expression_start_pos)827 AbsPosToLineColumnPos(*m_user_expression_start_pos, m_transformed_text,828 user_expr_line, user_expr_column);829 else830 return false;831 832 // The actual column where we have to complete is the start column of the833 // user expression + the offset inside the user code that we were given.834 const unsigned completion_column = user_expr_column + complete_pos;835 parser.Complete(request, user_expr_line, completion_column, complete_pos);836 837 return true;838}839 840lldb::addr_t ClangUserExpression::GetCppObjectPointer(841 lldb::StackFrameSP frame_sp, llvm::StringRef object_name, Status &err) {842 auto valobj_sp =843 GetObjectPointerValueObject(std::move(frame_sp), object_name, err);844 845 // We're inside a C++ class method. This could potentially be an unnamed846 // lambda structure. If the lambda captured a "this", that should be847 // the object pointer.848 if (auto thisChildSP = valobj_sp->GetChildMemberWithName("this")) {849 valobj_sp = thisChildSP;850 }851 852 if (!err.Success() || !valobj_sp.get())853 return LLDB_INVALID_ADDRESS;854 855 lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);856 857 if (ret == LLDB_INVALID_ADDRESS) {858 err = Status::FromErrorStringWithFormatv(859 "Couldn't load '{0}' because its value couldn't be evaluated",860 object_name);861 return LLDB_INVALID_ADDRESS;862 }863 864 return ret;865}866 867bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx,868 std::vector<lldb::addr_t> &args,869 lldb::addr_t struct_address,870 DiagnosticManager &diagnostic_manager) {871 lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;872 lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;873 874 if (m_needs_object_ptr) {875 lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();876 if (!frame_sp)877 return true;878 879 if (!m_in_cplusplus_method && !m_in_objectivec_method) {880 diagnostic_manager.PutString(881 lldb::eSeverityError,882 "need object pointer but don't know the language");883 return false;884 }885 886 static constexpr llvm::StringLiteral g_cplusplus_object_name("this");887 static constexpr llvm::StringLiteral g_objc_object_name("self");888 llvm::StringRef object_name =889 m_in_cplusplus_method ? g_cplusplus_object_name : g_objc_object_name;890 891 Status object_ptr_error;892 893 if (m_ctx_obj) {894 ValueObject::AddrAndType address = m_ctx_obj->GetAddressOf(false);895 if (address.address == LLDB_INVALID_ADDRESS ||896 address.type != eAddressTypeLoad)897 object_ptr_error = Status::FromErrorString("Can't get context object's "898 "debuggee address");899 else900 object_ptr = address.address;901 } else {902 if (m_in_cplusplus_method) {903 object_ptr =904 GetCppObjectPointer(frame_sp, object_name, object_ptr_error);905 } else {906 object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);907 }908 }909 910 if (!object_ptr_error.Success()) {911 exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Format(912 "warning: `{0}' is not accessible (substituting 0). {1}\n",913 object_name, object_ptr_error.AsCString());914 object_ptr = 0;915 }916 917 if (m_in_objectivec_method) {918 static constexpr llvm::StringLiteral cmd_name("_cmd");919 920 cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);921 922 if (!object_ptr_error.Success()) {923 diagnostic_manager.Printf(924 lldb::eSeverityWarning,925 "couldn't get cmd pointer (substituting NULL): %s",926 object_ptr_error.AsCString());927 cmd_ptr = 0;928 }929 }930 931 args.push_back(object_ptr);932 933 if (m_in_objectivec_method)934 args.push_back(cmd_ptr);935 936 args.push_back(struct_address);937 } else {938 args.push_back(struct_address);939 }940 return true;941}942 943lldb::ExpressionVariableSP ClangUserExpression::GetResultAfterDematerialization(944 ExecutionContextScope *exe_scope) {945 return m_result_delegate.GetVariable();946}947 948char ClangUserExpression::ClangUserExpressionHelper::ID;949 950void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(951 ExecutionContext &exe_ctx,952 Materializer::PersistentVariableDelegate &delegate,953 bool keep_result_in_memory,954 ValueObject *ctx_obj) {955 std::shared_ptr<ClangASTImporter> ast_importer;956 auto *state = exe_ctx.GetTargetSP()->GetPersistentExpressionStateForLanguage(957 lldb::eLanguageTypeC);958 if (state) {959 auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);960 ast_importer = persistent_vars->GetClangASTImporter();961 }962 m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>(963 keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(), ast_importer,964 ctx_obj);965}966 967clang::ASTConsumer *968ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(969 clang::ASTConsumer *passthrough) {970 m_result_synthesizer_up = std::make_unique<ASTResultSynthesizer>(971 passthrough, m_top_level, m_target);972 973 return m_result_synthesizer_up.get();974}975 976void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() {977 if (m_result_synthesizer_up) {978 m_result_synthesizer_up->CommitPersistentDecls();979 }980}981 982ConstString ClangUserExpression::ResultDelegate::GetName() {983 return m_persistent_state->GetNextPersistentVariableName(false);984}985 986void ClangUserExpression::ResultDelegate::DidDematerialize(987 lldb::ExpressionVariableSP &variable) {988 m_variable = variable;989}990 991void ClangUserExpression::ResultDelegate::RegisterPersistentState(992 PersistentExpressionState *persistent_state) {993 m_persistent_state = persistent_state;994}995 996lldb::ExpressionVariableSP &ClangUserExpression::ResultDelegate::GetVariable() {997 return m_variable;998}999