1*061da546Spatrick //===-- UserExpression.cpp ---------------------------------*- C++ -*-===// 2*061da546Spatrick // 3*061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*061da546Spatrick // 7*061da546Spatrick //===----------------------------------------------------------------------===// 8*061da546Spatrick 9*061da546Spatrick #include "lldb/Host/Config.h" 10*061da546Spatrick 11*061da546Spatrick #include <stdio.h> 12*061da546Spatrick #if HAVE_SYS_TYPES_H 13*061da546Spatrick #include <sys/types.h> 14*061da546Spatrick #endif 15*061da546Spatrick 16*061da546Spatrick #include <cstdlib> 17*061da546Spatrick #include <map> 18*061da546Spatrick #include <string> 19*061da546Spatrick 20*061da546Spatrick #include "lldb/Core/Module.h" 21*061da546Spatrick #include "lldb/Core/StreamFile.h" 22*061da546Spatrick #include "lldb/Core/ValueObjectConstResult.h" 23*061da546Spatrick #include "lldb/Expression/DiagnosticManager.h" 24*061da546Spatrick #include "lldb/Expression/ExpressionVariable.h" 25*061da546Spatrick #include "lldb/Expression/IRExecutionUnit.h" 26*061da546Spatrick #include "lldb/Expression/IRInterpreter.h" 27*061da546Spatrick #include "lldb/Expression/Materializer.h" 28*061da546Spatrick #include "lldb/Expression/UserExpression.h" 29*061da546Spatrick #include "lldb/Host/HostInfo.h" 30*061da546Spatrick #include "lldb/Symbol/Block.h" 31*061da546Spatrick #include "lldb/Symbol/Function.h" 32*061da546Spatrick #include "lldb/Symbol/ObjectFile.h" 33*061da546Spatrick #include "lldb/Symbol/SymbolVendor.h" 34*061da546Spatrick #include "lldb/Symbol/Type.h" 35*061da546Spatrick #include "lldb/Symbol/TypeSystem.h" 36*061da546Spatrick #include "lldb/Symbol/VariableList.h" 37*061da546Spatrick #include "lldb/Target/ExecutionContext.h" 38*061da546Spatrick #include "lldb/Target/Process.h" 39*061da546Spatrick #include "lldb/Target/StackFrame.h" 40*061da546Spatrick #include "lldb/Target/Target.h" 41*061da546Spatrick #include "lldb/Target/ThreadPlan.h" 42*061da546Spatrick #include "lldb/Target/ThreadPlanCallUserExpression.h" 43*061da546Spatrick #include "lldb/Utility/ConstString.h" 44*061da546Spatrick #include "lldb/Utility/Log.h" 45*061da546Spatrick #include "lldb/Utility/StreamString.h" 46*061da546Spatrick 47*061da546Spatrick using namespace lldb_private; 48*061da546Spatrick 49*061da546Spatrick char UserExpression::ID; 50*061da546Spatrick 51*061da546Spatrick UserExpression::UserExpression(ExecutionContextScope &exe_scope, 52*061da546Spatrick llvm::StringRef expr, llvm::StringRef prefix, 53*061da546Spatrick lldb::LanguageType language, 54*061da546Spatrick ResultType desired_type, 55*061da546Spatrick const EvaluateExpressionOptions &options) 56*061da546Spatrick : Expression(exe_scope), m_expr_text(expr), m_expr_prefix(prefix), 57*061da546Spatrick m_language(language), m_desired_type(desired_type), m_options(options) {} 58*061da546Spatrick 59*061da546Spatrick UserExpression::~UserExpression() {} 60*061da546Spatrick 61*061da546Spatrick void UserExpression::InstallContext(ExecutionContext &exe_ctx) { 62*061da546Spatrick m_jit_process_wp = exe_ctx.GetProcessSP(); 63*061da546Spatrick 64*061da546Spatrick lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); 65*061da546Spatrick 66*061da546Spatrick if (frame_sp) 67*061da546Spatrick m_address = frame_sp->GetFrameCodeAddress(); 68*061da546Spatrick } 69*061da546Spatrick 70*061da546Spatrick bool UserExpression::LockAndCheckContext(ExecutionContext &exe_ctx, 71*061da546Spatrick lldb::TargetSP &target_sp, 72*061da546Spatrick lldb::ProcessSP &process_sp, 73*061da546Spatrick lldb::StackFrameSP &frame_sp) { 74*061da546Spatrick lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock(); 75*061da546Spatrick process_sp = exe_ctx.GetProcessSP(); 76*061da546Spatrick 77*061da546Spatrick if (process_sp != expected_process_sp) 78*061da546Spatrick return false; 79*061da546Spatrick 80*061da546Spatrick process_sp = exe_ctx.GetProcessSP(); 81*061da546Spatrick target_sp = exe_ctx.GetTargetSP(); 82*061da546Spatrick frame_sp = exe_ctx.GetFrameSP(); 83*061da546Spatrick 84*061da546Spatrick if (m_address.IsValid()) { 85*061da546Spatrick if (!frame_sp) 86*061da546Spatrick return false; 87*061da546Spatrick return (Address::CompareLoadAddress(m_address, 88*061da546Spatrick frame_sp->GetFrameCodeAddress(), 89*061da546Spatrick target_sp.get()) == 0); 90*061da546Spatrick } 91*061da546Spatrick 92*061da546Spatrick return true; 93*061da546Spatrick } 94*061da546Spatrick 95*061da546Spatrick bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) { 96*061da546Spatrick lldb::TargetSP target_sp; 97*061da546Spatrick lldb::ProcessSP process_sp; 98*061da546Spatrick lldb::StackFrameSP frame_sp; 99*061da546Spatrick 100*061da546Spatrick return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp); 101*061da546Spatrick } 102*061da546Spatrick 103*061da546Spatrick lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp, 104*061da546Spatrick ConstString &object_name, 105*061da546Spatrick Status &err) { 106*061da546Spatrick err.Clear(); 107*061da546Spatrick 108*061da546Spatrick if (!frame_sp) { 109*061da546Spatrick err.SetErrorStringWithFormat( 110*061da546Spatrick "Couldn't load '%s' because the context is incomplete", 111*061da546Spatrick object_name.AsCString()); 112*061da546Spatrick return LLDB_INVALID_ADDRESS; 113*061da546Spatrick } 114*061da546Spatrick 115*061da546Spatrick lldb::VariableSP var_sp; 116*061da546Spatrick lldb::ValueObjectSP valobj_sp; 117*061da546Spatrick 118*061da546Spatrick valobj_sp = frame_sp->GetValueForVariableExpressionPath( 119*061da546Spatrick object_name.AsCString(), lldb::eNoDynamicValues, 120*061da546Spatrick StackFrame::eExpressionPathOptionCheckPtrVsMember | 121*061da546Spatrick StackFrame::eExpressionPathOptionsNoFragileObjcIvar | 122*061da546Spatrick StackFrame::eExpressionPathOptionsNoSyntheticChildren | 123*061da546Spatrick StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, 124*061da546Spatrick var_sp, err); 125*061da546Spatrick 126*061da546Spatrick if (!err.Success() || !valobj_sp.get()) 127*061da546Spatrick return LLDB_INVALID_ADDRESS; 128*061da546Spatrick 129*061da546Spatrick lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 130*061da546Spatrick 131*061da546Spatrick if (ret == LLDB_INVALID_ADDRESS) { 132*061da546Spatrick err.SetErrorStringWithFormat( 133*061da546Spatrick "Couldn't load '%s' because its value couldn't be evaluated", 134*061da546Spatrick object_name.AsCString()); 135*061da546Spatrick return LLDB_INVALID_ADDRESS; 136*061da546Spatrick } 137*061da546Spatrick 138*061da546Spatrick return ret; 139*061da546Spatrick } 140*061da546Spatrick 141*061da546Spatrick lldb::ExpressionResults UserExpression::Evaluate( 142*061da546Spatrick ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, 143*061da546Spatrick llvm::StringRef expr, llvm::StringRef prefix, 144*061da546Spatrick lldb::ValueObjectSP &result_valobj_sp, Status &error, 145*061da546Spatrick std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr, 146*061da546Spatrick ValueObject *ctx_obj) { 147*061da546Spatrick Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | 148*061da546Spatrick LIBLLDB_LOG_STEP)); 149*061da546Spatrick 150*061da546Spatrick if (ctx_obj) { 151*061da546Spatrick static unsigned const ctx_type_mask = 152*061da546Spatrick lldb::TypeFlags::eTypeIsClass | lldb::TypeFlags::eTypeIsStructUnion; 153*061da546Spatrick if (!(ctx_obj->GetTypeInfo() & ctx_type_mask)) { 154*061da546Spatrick LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of " 155*061da546Spatrick "an invalid type, can't run expressions."); 156*061da546Spatrick error.SetErrorString("a context object of an invalid type passed"); 157*061da546Spatrick return lldb::eExpressionSetupError; 158*061da546Spatrick } 159*061da546Spatrick } 160*061da546Spatrick 161*061da546Spatrick lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); 162*061da546Spatrick lldb::LanguageType language = options.GetLanguage(); 163*061da546Spatrick const ResultType desired_type = options.DoesCoerceToId() 164*061da546Spatrick ? UserExpression::eResultTypeId 165*061da546Spatrick : UserExpression::eResultTypeAny; 166*061da546Spatrick lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; 167*061da546Spatrick 168*061da546Spatrick Target *target = exe_ctx.GetTargetPtr(); 169*061da546Spatrick if (!target) { 170*061da546Spatrick LLDB_LOGF(log, "== [UserExpression::Evaluate] Passed a NULL target, can't " 171*061da546Spatrick "run expressions."); 172*061da546Spatrick error.SetErrorString("expression passed a null target"); 173*061da546Spatrick return lldb::eExpressionSetupError; 174*061da546Spatrick } 175*061da546Spatrick 176*061da546Spatrick Process *process = exe_ctx.GetProcessPtr(); 177*061da546Spatrick 178*061da546Spatrick if (process == nullptr || process->GetState() != lldb::eStateStopped) { 179*061da546Spatrick if (execution_policy == eExecutionPolicyAlways) { 180*061da546Spatrick LLDB_LOGF(log, 181*061da546Spatrick "== [UserExpression::Evaluate] Expression may not run, but " 182*061da546Spatrick "is not constant =="); 183*061da546Spatrick 184*061da546Spatrick error.SetErrorString("expression needed to run but couldn't"); 185*061da546Spatrick 186*061da546Spatrick return execution_results; 187*061da546Spatrick } 188*061da546Spatrick } 189*061da546Spatrick 190*061da546Spatrick if (process == nullptr || !process->CanJIT()) 191*061da546Spatrick execution_policy = eExecutionPolicyNever; 192*061da546Spatrick 193*061da546Spatrick // We need to set the expression execution thread here, turns out parse can 194*061da546Spatrick // call functions in the process of looking up symbols, which will escape the 195*061da546Spatrick // context set by exe_ctx passed to Execute. 196*061da546Spatrick lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); 197*061da546Spatrick ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher( 198*061da546Spatrick thread_sp); 199*061da546Spatrick 200*061da546Spatrick llvm::StringRef full_prefix; 201*061da546Spatrick llvm::StringRef option_prefix(options.GetPrefix()); 202*061da546Spatrick std::string full_prefix_storage; 203*061da546Spatrick if (!prefix.empty() && !option_prefix.empty()) { 204*061da546Spatrick full_prefix_storage = prefix; 205*061da546Spatrick full_prefix_storage.append(option_prefix); 206*061da546Spatrick full_prefix = full_prefix_storage; 207*061da546Spatrick } else if (!prefix.empty()) 208*061da546Spatrick full_prefix = prefix; 209*061da546Spatrick else 210*061da546Spatrick full_prefix = option_prefix; 211*061da546Spatrick 212*061da546Spatrick // If the language was not specified in the expression command, set it to the 213*061da546Spatrick // language in the target's properties if specified, else default to the 214*061da546Spatrick // langage for the frame. 215*061da546Spatrick if (language == lldb::eLanguageTypeUnknown) { 216*061da546Spatrick if (target->GetLanguage() != lldb::eLanguageTypeUnknown) 217*061da546Spatrick language = target->GetLanguage(); 218*061da546Spatrick else if (StackFrame *frame = exe_ctx.GetFramePtr()) 219*061da546Spatrick language = frame->GetLanguage(); 220*061da546Spatrick } 221*061da546Spatrick 222*061da546Spatrick lldb::UserExpressionSP user_expression_sp( 223*061da546Spatrick target->GetUserExpressionForLanguage(expr, full_prefix, language, 224*061da546Spatrick desired_type, options, ctx_obj, 225*061da546Spatrick error)); 226*061da546Spatrick if (error.Fail()) { 227*061da546Spatrick if (log) 228*061da546Spatrick LLDB_LOGF(log, "== [UserExpression::Evaluate] Getting expression: %s ==", 229*061da546Spatrick error.AsCString()); 230*061da546Spatrick return lldb::eExpressionSetupError; 231*061da546Spatrick } 232*061da546Spatrick 233*061da546Spatrick if (log) 234*061da546Spatrick LLDB_LOGF(log, "== [UserExpression::Evaluate] Parsing expression %s ==", 235*061da546Spatrick expr.str().c_str()); 236*061da546Spatrick 237*061da546Spatrick const bool keep_expression_in_memory = true; 238*061da546Spatrick const bool generate_debug_info = options.GetGenerateDebugInfo(); 239*061da546Spatrick 240*061da546Spatrick if (options.InvokeCancelCallback(lldb::eExpressionEvaluationParse)) { 241*061da546Spatrick error.SetErrorString("expression interrupted by callback before parse"); 242*061da546Spatrick result_valobj_sp = ValueObjectConstResult::Create( 243*061da546Spatrick exe_ctx.GetBestExecutionContextScope(), error); 244*061da546Spatrick return lldb::eExpressionInterrupted; 245*061da546Spatrick } 246*061da546Spatrick 247*061da546Spatrick DiagnosticManager diagnostic_manager; 248*061da546Spatrick 249*061da546Spatrick bool parse_success = 250*061da546Spatrick user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy, 251*061da546Spatrick keep_expression_in_memory, generate_debug_info); 252*061da546Spatrick 253*061da546Spatrick // Calculate the fixed expression always, since we need it for errors. 254*061da546Spatrick std::string tmp_fixed_expression; 255*061da546Spatrick if (fixed_expression == nullptr) 256*061da546Spatrick fixed_expression = &tmp_fixed_expression; 257*061da546Spatrick 258*061da546Spatrick const char *fixed_text = user_expression_sp->GetFixedText(); 259*061da546Spatrick if (fixed_text != nullptr) 260*061da546Spatrick fixed_expression->append(fixed_text); 261*061da546Spatrick 262*061da546Spatrick // If there is a fixed expression, try to parse it: 263*061da546Spatrick if (!parse_success) { 264*061da546Spatrick execution_results = lldb::eExpressionParseError; 265*061da546Spatrick if (fixed_expression && !fixed_expression->empty() && 266*061da546Spatrick options.GetAutoApplyFixIts()) { 267*061da546Spatrick lldb::UserExpressionSP fixed_expression_sp( 268*061da546Spatrick target->GetUserExpressionForLanguage(fixed_expression->c_str(), 269*061da546Spatrick full_prefix, language, 270*061da546Spatrick desired_type, options, ctx_obj, 271*061da546Spatrick error)); 272*061da546Spatrick DiagnosticManager fixed_diagnostic_manager; 273*061da546Spatrick parse_success = fixed_expression_sp->Parse( 274*061da546Spatrick fixed_diagnostic_manager, exe_ctx, execution_policy, 275*061da546Spatrick keep_expression_in_memory, generate_debug_info); 276*061da546Spatrick if (parse_success) { 277*061da546Spatrick diagnostic_manager.Clear(); 278*061da546Spatrick user_expression_sp = fixed_expression_sp; 279*061da546Spatrick } else { 280*061da546Spatrick // If the fixed expression failed to parse, don't tell the user about, 281*061da546Spatrick // that won't help. 282*061da546Spatrick fixed_expression->clear(); 283*061da546Spatrick } 284*061da546Spatrick } 285*061da546Spatrick 286*061da546Spatrick if (!parse_success) { 287*061da546Spatrick if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) { 288*061da546Spatrick error.SetExpressionErrorWithFormat( 289*061da546Spatrick execution_results, 290*061da546Spatrick "expression failed to parse, fixed expression suggested:\n %s", 291*061da546Spatrick fixed_expression->c_str()); 292*061da546Spatrick } else { 293*061da546Spatrick if (!diagnostic_manager.Diagnostics().size()) 294*061da546Spatrick error.SetExpressionError(execution_results, 295*061da546Spatrick "expression failed to parse, unknown error"); 296*061da546Spatrick else 297*061da546Spatrick error.SetExpressionError(execution_results, 298*061da546Spatrick diagnostic_manager.GetString().c_str()); 299*061da546Spatrick } 300*061da546Spatrick } 301*061da546Spatrick } 302*061da546Spatrick 303*061da546Spatrick if (parse_success) { 304*061da546Spatrick // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module 305*061da546Spatrick // if one was created 306*061da546Spatrick if (jit_module_sp_ptr) 307*061da546Spatrick *jit_module_sp_ptr = user_expression_sp->GetJITModule(); 308*061da546Spatrick 309*061da546Spatrick lldb::ExpressionVariableSP expr_result; 310*061da546Spatrick 311*061da546Spatrick if (execution_policy == eExecutionPolicyNever && 312*061da546Spatrick !user_expression_sp->CanInterpret()) { 313*061da546Spatrick if (log) 314*061da546Spatrick LLDB_LOGF(log, 315*061da546Spatrick "== [UserExpression::Evaluate] Expression may not run, but " 316*061da546Spatrick "is not constant =="); 317*061da546Spatrick 318*061da546Spatrick if (!diagnostic_manager.Diagnostics().size()) 319*061da546Spatrick error.SetExpressionError(lldb::eExpressionSetupError, 320*061da546Spatrick "expression needed to run but couldn't"); 321*061da546Spatrick } else if (execution_policy == eExecutionPolicyTopLevel) { 322*061da546Spatrick error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); 323*061da546Spatrick return lldb::eExpressionCompleted; 324*061da546Spatrick } else { 325*061da546Spatrick if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) { 326*061da546Spatrick error.SetExpressionError( 327*061da546Spatrick lldb::eExpressionInterrupted, 328*061da546Spatrick "expression interrupted by callback before execution"); 329*061da546Spatrick result_valobj_sp = ValueObjectConstResult::Create( 330*061da546Spatrick exe_ctx.GetBestExecutionContextScope(), error); 331*061da546Spatrick return lldb::eExpressionInterrupted; 332*061da546Spatrick } 333*061da546Spatrick 334*061da546Spatrick diagnostic_manager.Clear(); 335*061da546Spatrick 336*061da546Spatrick if (log) 337*061da546Spatrick LLDB_LOGF(log, "== [UserExpression::Evaluate] Executing expression =="); 338*061da546Spatrick 339*061da546Spatrick execution_results = 340*061da546Spatrick user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, 341*061da546Spatrick user_expression_sp, expr_result); 342*061da546Spatrick 343*061da546Spatrick if (execution_results != lldb::eExpressionCompleted) { 344*061da546Spatrick if (log) 345*061da546Spatrick LLDB_LOGF(log, "== [UserExpression::Evaluate] Execution completed " 346*061da546Spatrick "abnormally =="); 347*061da546Spatrick 348*061da546Spatrick if (!diagnostic_manager.Diagnostics().size()) 349*061da546Spatrick error.SetExpressionError( 350*061da546Spatrick execution_results, "expression failed to execute, unknown error"); 351*061da546Spatrick else 352*061da546Spatrick error.SetExpressionError(execution_results, 353*061da546Spatrick diagnostic_manager.GetString().c_str()); 354*061da546Spatrick } else { 355*061da546Spatrick if (expr_result) { 356*061da546Spatrick result_valobj_sp = expr_result->GetValueObject(); 357*061da546Spatrick 358*061da546Spatrick if (log) 359*061da546Spatrick LLDB_LOGF(log, 360*061da546Spatrick "== [UserExpression::Evaluate] Execution completed " 361*061da546Spatrick "normally with result %s ==", 362*061da546Spatrick result_valobj_sp->GetValueAsCString()); 363*061da546Spatrick } else { 364*061da546Spatrick if (log) 365*061da546Spatrick LLDB_LOGF(log, "== [UserExpression::Evaluate] Execution completed " 366*061da546Spatrick "normally with no result =="); 367*061da546Spatrick 368*061da546Spatrick error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); 369*061da546Spatrick } 370*061da546Spatrick } 371*061da546Spatrick } 372*061da546Spatrick } 373*061da546Spatrick 374*061da546Spatrick if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) { 375*061da546Spatrick error.SetExpressionError( 376*061da546Spatrick lldb::eExpressionInterrupted, 377*061da546Spatrick "expression interrupted by callback after complete"); 378*061da546Spatrick return lldb::eExpressionInterrupted; 379*061da546Spatrick } 380*061da546Spatrick 381*061da546Spatrick if (result_valobj_sp.get() == nullptr) { 382*061da546Spatrick result_valobj_sp = ValueObjectConstResult::Create( 383*061da546Spatrick exe_ctx.GetBestExecutionContextScope(), error); 384*061da546Spatrick } 385*061da546Spatrick 386*061da546Spatrick return execution_results; 387*061da546Spatrick } 388*061da546Spatrick 389*061da546Spatrick lldb::ExpressionResults 390*061da546Spatrick UserExpression::Execute(DiagnosticManager &diagnostic_manager, 391*061da546Spatrick ExecutionContext &exe_ctx, 392*061da546Spatrick const EvaluateExpressionOptions &options, 393*061da546Spatrick lldb::UserExpressionSP &shared_ptr_to_me, 394*061da546Spatrick lldb::ExpressionVariableSP &result_var) { 395*061da546Spatrick lldb::ExpressionResults expr_result = DoExecute( 396*061da546Spatrick diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var); 397*061da546Spatrick Target *target = exe_ctx.GetTargetPtr(); 398*061da546Spatrick if (options.GetResultIsInternal() && result_var && target) { 399*061da546Spatrick if (auto *persistent_state = 400*061da546Spatrick target->GetPersistentExpressionStateForLanguage(m_language)) 401*061da546Spatrick persistent_state->RemovePersistentVariable(result_var); 402*061da546Spatrick } 403*061da546Spatrick return expr_result; 404*061da546Spatrick } 405