1 //===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/lldb-python.h" 11 12 #include "CommandObjectExpression.h" 13 14 // C Includes 15 // C++ Includes 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/Interpreter/Args.h" 19 #include "lldb/Core/Value.h" 20 #include "lldb/Core/ValueObjectVariable.h" 21 #include "lldb/DataFormatters/ValueObjectPrinter.h" 22 #include "lldb/Expression/ClangExpressionVariable.h" 23 #include "lldb/Expression/ClangUserExpression.h" 24 #include "lldb/Expression/ClangFunction.h" 25 #include "lldb/Expression/DWARFExpression.h" 26 #include "lldb/Host/Host.h" 27 #include "lldb/Core/Debugger.h" 28 #include "lldb/Interpreter/CommandInterpreter.h" 29 #include "lldb/Interpreter/CommandReturnObject.h" 30 #include "lldb/Target/ObjCLanguageRuntime.h" 31 #include "lldb/Symbol/ObjectFile.h" 32 #include "lldb/Symbol/Variable.h" 33 #include "lldb/Target/Process.h" 34 #include "lldb/Target/StackFrame.h" 35 #include "lldb/Target/Target.h" 36 #include "lldb/Target/Thread.h" 37 #include "llvm/ADT/StringRef.h" 38 39 using namespace lldb; 40 using namespace lldb_private; 41 42 CommandObjectExpression::CommandOptions::CommandOptions () : 43 OptionGroup() 44 { 45 } 46 47 48 CommandObjectExpression::CommandOptions::~CommandOptions () 49 { 50 } 51 52 static OptionEnumValueElement g_description_verbosity_type[] = 53 { 54 { eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", "Only show the description string"}, 55 { eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", "Show the full output, including persistent variable's name and type"}, 56 { 0, NULL, NULL } 57 }; 58 59 OptionDefinition 60 CommandObjectExpression::CommandOptions::g_option_table[] = 61 { 62 { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, 63 { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, 64 { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, 65 { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."}, 66 { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."}, 67 { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, 68 }; 69 70 71 uint32_t 72 CommandObjectExpression::CommandOptions::GetNumDefinitions () 73 { 74 return sizeof(g_option_table)/sizeof(OptionDefinition); 75 } 76 77 Error 78 CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &interpreter, 79 uint32_t option_idx, 80 const char *option_arg) 81 { 82 Error error; 83 84 const int short_option = g_option_table[option_idx].short_option; 85 86 switch (short_option) 87 { 88 //case 'l': 89 //if (language.SetLanguageFromCString (option_arg) == false) 90 //{ 91 // error.SetErrorStringWithFormat("invalid language option argument '%s'", option_arg); 92 //} 93 //break; 94 95 case 'a': 96 { 97 bool success; 98 bool result; 99 result = Args::StringToBoolean(option_arg, true, &success); 100 if (!success) 101 error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg); 102 else 103 try_all_threads = result; 104 } 105 break; 106 107 case 'i': 108 { 109 bool success; 110 bool tmp_value = Args::StringToBoolean(option_arg, true, &success); 111 if (success) 112 ignore_breakpoints = tmp_value; 113 else 114 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); 115 break; 116 } 117 case 't': 118 { 119 bool success; 120 uint32_t result; 121 result = Args::StringToUInt32(option_arg, 0, 0, &success); 122 if (success) 123 timeout = result; 124 else 125 error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg); 126 } 127 break; 128 129 case 'u': 130 { 131 bool success; 132 bool tmp_value = Args::StringToBoolean(option_arg, true, &success); 133 if (success) 134 unwind_on_error = tmp_value; 135 else 136 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); 137 break; 138 } 139 140 case 'v': 141 if (!option_arg) 142 { 143 m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull; 144 break; 145 } 146 m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); 147 if (!error.Success()) 148 error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg); 149 break; 150 151 case 'g': 152 debug = true; 153 unwind_on_error = false; 154 ignore_breakpoints = false; 155 break; 156 157 default: 158 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 159 break; 160 } 161 162 return error; 163 } 164 165 void 166 CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter) 167 { 168 Process *process = interpreter.GetExecutionContext().GetProcessPtr(); 169 if (process != NULL) 170 { 171 ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions(); 172 unwind_on_error = process->GetUnwindOnErrorInExpressions(); 173 } 174 else 175 { 176 ignore_breakpoints = true; 177 unwind_on_error = true; 178 } 179 180 show_summary = true; 181 try_all_threads = true; 182 timeout = 0; 183 debug = false; 184 m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; 185 } 186 187 const OptionDefinition* 188 CommandObjectExpression::CommandOptions::GetDefinitions () 189 { 190 return g_option_table; 191 } 192 193 CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) : 194 CommandObjectRaw (interpreter, 195 "expression", 196 "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.", 197 NULL, 198 eFlagProcessMustBePaused | eFlagTryTargetAPILock), 199 IOHandlerDelegate (IOHandlerDelegate::Completion::Expression), 200 m_option_group (interpreter), 201 m_format_options (eFormatDefault), 202 m_command_options (), 203 m_expr_line_count (0), 204 m_expr_lines () 205 { 206 SetHelpLong( 207 "Timeouts:\n\ 208 If the expression can be evaluated statically (without runnning code) then it will be.\n\ 209 Otherwise, by default the expression will run on the current thread with a short timeout:\n\ 210 currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted\n\ 211 and resumed with all threads running. You can use the -a option to disable retrying on all\n\ 212 threads. You can use the -t option to set a shorter timeout.\n\ 213 \n\ 214 User defined variables:\n\ 215 You can define your own variables for convenience or to be used in subsequent expressions.\n\ 216 You define them the same way you would define variables in C. If the first character of \n\ 217 your user defined variable is a $, then the variable's value will be available in future\n\ 218 expressions, otherwise it will just be available in the current expression.\n\ 219 \n\ 220 Examples: \n\ 221 \n\ 222 expr my_struct->a = my_array[3] \n\ 223 expr -f bin -- (index * 8) + 5 \n\ 224 expr unsigned int $foo = 5\n\ 225 expr char c[] = \"foo\"; c[0]\n"); 226 227 CommandArgumentEntry arg; 228 CommandArgumentData expression_arg; 229 230 // Define the first (and only) variant of this arg. 231 expression_arg.arg_type = eArgTypeExpression; 232 expression_arg.arg_repetition = eArgRepeatPlain; 233 234 // There is only one variant this argument could be; put it into the argument entry. 235 arg.push_back (expression_arg); 236 237 // Push the data for the first argument into the m_arguments vector. 238 m_arguments.push_back (arg); 239 240 // Add the "--format" and "--gdb-format" 241 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); 242 m_option_group.Append (&m_command_options); 243 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2); 244 m_option_group.Finalize(); 245 } 246 247 CommandObjectExpression::~CommandObjectExpression () 248 { 249 } 250 251 Options * 252 CommandObjectExpression::GetOptions () 253 { 254 return &m_option_group; 255 } 256 257 bool 258 CommandObjectExpression::EvaluateExpression 259 ( 260 const char *expr, 261 Stream *output_stream, 262 Stream *error_stream, 263 CommandReturnObject *result 264 ) 265 { 266 // Don't use m_exe_ctx as this might be called asynchronously 267 // after the command object DoExecute has finished when doing 268 // multi-line expression that use an input reader... 269 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 270 271 Target *target = exe_ctx.GetTargetPtr(); 272 273 if (!target) 274 target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get(); 275 276 if (target) 277 { 278 lldb::ValueObjectSP result_valobj_sp; 279 280 bool keep_in_memory = true; 281 282 EvaluateExpressionOptions options; 283 options.SetCoerceToId(m_varobj_options.use_objc); 284 options.SetUnwindOnError(m_command_options.unwind_on_error); 285 options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints); 286 options.SetKeepInMemory(keep_in_memory); 287 options.SetUseDynamic(m_varobj_options.use_dynamic); 288 options.SetTryAllThreads(m_command_options.try_all_threads); 289 options.SetDebug(m_command_options.debug); 290 291 // If there is any chance we are going to stop and want to see 292 // what went wrong with our expression, we should generate debug info 293 if (!m_command_options.ignore_breakpoints || 294 !m_command_options.unwind_on_error) 295 options.SetGenerateDebugInfo(true); 296 297 if (m_command_options.timeout > 0) 298 options.SetTimeoutUsec(m_command_options.timeout); 299 else 300 options.SetTimeoutUsec(0); 301 302 target->EvaluateExpression(expr, exe_ctx.GetFramePtr(), 303 result_valobj_sp, options); 304 305 if (result_valobj_sp) 306 { 307 Format format = m_format_options.GetFormat(); 308 309 if (result_valobj_sp->GetError().Success()) 310 { 311 if (format != eFormatVoid) 312 { 313 if (format != eFormatDefault) 314 result_valobj_sp->SetFormat (format); 315 316 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format)); 317 318 result_valobj_sp->Dump(*output_stream,options); 319 320 if (result) 321 result->SetStatus (eReturnStatusSuccessFinishResult); 322 } 323 } 324 else 325 { 326 if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult) 327 { 328 if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid()) 329 { 330 error_stream->PutCString("(void)\n"); 331 } 332 333 if (result) 334 result->SetStatus (eReturnStatusSuccessFinishResult); 335 } 336 else 337 { 338 const char *error_cstr = result_valobj_sp->GetError().AsCString(); 339 if (error_cstr && error_cstr[0]) 340 { 341 const size_t error_cstr_len = strlen (error_cstr); 342 const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n'; 343 if (strstr(error_cstr, "error:") != error_cstr) 344 error_stream->PutCString ("error: "); 345 error_stream->Write(error_cstr, error_cstr_len); 346 if (!ends_with_newline) 347 error_stream->EOL(); 348 } 349 else 350 { 351 error_stream->PutCString ("error: unknown error\n"); 352 } 353 354 if (result) 355 result->SetStatus (eReturnStatusFailed); 356 } 357 } 358 } 359 } 360 else 361 { 362 error_stream->Printf ("error: invalid execution context for expression\n"); 363 return false; 364 } 365 366 return true; 367 } 368 369 void 370 CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::string &line) 371 { 372 io_handler.SetIsDone(true); 373 // StreamSP output_stream = io_handler.GetDebugger().GetAsyncOutputStream(); 374 // StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream(); 375 StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 376 StreamFileSP error_sp(io_handler.GetErrorStreamFile()); 377 378 EvaluateExpression (line.c_str(), 379 output_sp.get(), 380 error_sp.get()); 381 if (output_sp) 382 output_sp->Flush(); 383 if (error_sp) 384 error_sp->Flush(); 385 } 386 387 LineStatus 388 CommandObjectExpression::IOHandlerLinesUpdated (IOHandler &io_handler, 389 StringList &lines, 390 uint32_t line_idx, 391 Error &error) 392 { 393 if (line_idx == UINT32_MAX) 394 { 395 // Remove the last line from "lines" so it doesn't appear 396 // in our final expression 397 lines.PopBack(); 398 error.Clear(); 399 return LineStatus::Done; 400 } 401 else if (line_idx + 1 == lines.GetSize()) 402 { 403 // The last line was edited, if this line is empty, then we are done 404 // getting our multiple lines. 405 if (lines[line_idx].empty()) 406 return LineStatus::Done; 407 } 408 return LineStatus::Success; 409 } 410 411 void 412 CommandObjectExpression::GetMultilineExpression () 413 { 414 m_expr_lines.clear(); 415 m_expr_line_count = 0; 416 417 Debugger &debugger = GetCommandInterpreter().GetDebugger(); 418 const bool multiple_lines = true; // Get multiple lines 419 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, 420 "lldb-expr", // Name of input reader for history 421 NULL, // No prompt 422 multiple_lines, 423 1, // Show line numbers starting at 1 424 *this)); 425 426 StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile()); 427 if (output_sp) 428 { 429 output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n"); 430 output_sp->Flush(); 431 } 432 debugger.PushIOHandler(io_handler_sp); 433 } 434 435 bool 436 CommandObjectExpression::DoExecute 437 ( 438 const char *command, 439 CommandReturnObject &result 440 ) 441 { 442 m_option_group.NotifyOptionParsingStarting(); 443 444 const char * expr = NULL; 445 446 if (command[0] == '\0') 447 { 448 GetMultilineExpression (); 449 return result.Succeeded(); 450 } 451 452 if (command[0] == '-') 453 { 454 // We have some options and these options MUST end with --. 455 const char *end_options = NULL; 456 const char *s = command; 457 while (s && s[0]) 458 { 459 end_options = ::strstr (s, "--"); 460 if (end_options) 461 { 462 end_options += 2; // Get past the "--" 463 if (::isspace (end_options[0])) 464 { 465 expr = end_options; 466 while (::isspace (*expr)) 467 ++expr; 468 break; 469 } 470 } 471 s = end_options; 472 } 473 474 if (end_options) 475 { 476 Args args (command, end_options - command); 477 if (!ParseOptions (args, result)) 478 return false; 479 480 Error error (m_option_group.NotifyOptionParsingFinished()); 481 if (error.Fail()) 482 { 483 result.AppendError (error.AsCString()); 484 result.SetStatus (eReturnStatusFailed); 485 return false; 486 } 487 488 // No expression following options 489 if (expr == NULL || expr[0] == '\0') 490 { 491 GetMultilineExpression (); 492 return result.Succeeded(); 493 } 494 } 495 } 496 497 if (expr == NULL) 498 expr = command; 499 500 if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result)) 501 return true; 502 503 result.SetStatus (eReturnStatusFailed); 504 return false; 505 } 506 507