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