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/InputReader.h" 21 #include "lldb/Core/ValueObjectVariable.h" 22 #include "lldb/DataFormatters/ValueObjectPrinter.h" 23 #include "lldb/Expression/ClangExpressionVariable.h" 24 #include "lldb/Expression/ClangUserExpression.h" 25 #include "lldb/Expression/ClangFunction.h" 26 #include "lldb/Expression/DWARFExpression.h" 27 #include "lldb/Host/Host.h" 28 #include "lldb/Core/Debugger.h" 29 #include "lldb/Interpreter/CommandInterpreter.h" 30 #include "lldb/Interpreter/CommandReturnObject.h" 31 #include "lldb/Target/ObjCLanguageRuntime.h" 32 #include "lldb/Symbol/ObjectFile.h" 33 #include "lldb/Symbol/Variable.h" 34 #include "lldb/Target/Process.h" 35 #include "lldb/Target/Frame.h" 36 #include "lldb/Target/Target.h" 37 #include "lldb/Target/Thread.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, 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 default: 152 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 153 break; 154 } 155 156 return error; 157 } 158 159 void 160 CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter) 161 { 162 Process *process = interpreter.GetExecutionContext().GetProcessPtr(); 163 if (process != NULL) 164 { 165 ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions(); 166 unwind_on_error = process->GetUnwindOnErrorInExpressions(); 167 } 168 else 169 { 170 ignore_breakpoints = false; 171 unwind_on_error = true; 172 } 173 174 show_summary = true; 175 try_all_threads = true; 176 timeout = 0; 177 m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; 178 } 179 180 const OptionDefinition* 181 CommandObjectExpression::CommandOptions::GetDefinitions () 182 { 183 return g_option_table; 184 } 185 186 CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) : 187 CommandObjectRaw (interpreter, 188 "expression", 189 "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.", 190 NULL, 191 eFlagProcessMustBePaused | eFlagTryTargetAPILock), 192 m_option_group (interpreter), 193 m_format_options (eFormatDefault), 194 m_command_options (), 195 m_expr_line_count (0), 196 m_expr_lines () 197 { 198 SetHelpLong( 199 "Timeouts:\n\ 200 If the expression can be evaluated statically (without runnning code) then it will be.\n\ 201 Otherwise, by default the expression will run on the current thread with a short timeout:\n\ 202 currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted\n\ 203 and resumed with all threads running. You can use the -a option to disable retrying on all\n\ 204 threads. You can use the -t option to set a shorter timeout.\n\ 205 \n\ 206 User defined variables:\n\ 207 You can define your own variables for convenience or to be used in subsequent expressions.\n\ 208 You define them the same way you would define variables in C. If the first character of \n\ 209 your user defined variable is a $, then the variable's value will be available in future\n\ 210 expressions, otherwise it will just be available in the current expression.\n\ 211 \n\ 212 Examples: \n\ 213 \n\ 214 expr my_struct->a = my_array[3] \n\ 215 expr -f bin -- (index * 8) + 5 \n\ 216 expr unsigned int $foo = 5\n\ 217 expr char c[] = \"foo\"; c[0]\n"); 218 219 CommandArgumentEntry arg; 220 CommandArgumentData expression_arg; 221 222 // Define the first (and only) variant of this arg. 223 expression_arg.arg_type = eArgTypeExpression; 224 expression_arg.arg_repetition = eArgRepeatPlain; 225 226 // There is only one variant this argument could be; put it into the argument entry. 227 arg.push_back (expression_arg); 228 229 // Push the data for the first argument into the m_arguments vector. 230 m_arguments.push_back (arg); 231 232 // Add the "--format" and "--gdb-format" 233 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); 234 m_option_group.Append (&m_command_options); 235 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2); 236 m_option_group.Finalize(); 237 } 238 239 CommandObjectExpression::~CommandObjectExpression () 240 { 241 } 242 243 Options * 244 CommandObjectExpression::GetOptions () 245 { 246 return &m_option_group; 247 } 248 249 size_t 250 CommandObjectExpression::MultiLineExpressionCallback 251 ( 252 void *baton, 253 InputReader &reader, 254 lldb::InputReaderAction notification, 255 const char *bytes, 256 size_t bytes_len 257 ) 258 { 259 CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton; 260 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 261 262 switch (notification) 263 { 264 case eInputReaderActivate: 265 if (!batch_mode) 266 { 267 StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream()); 268 if (async_strm_sp) 269 { 270 async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n"); 271 async_strm_sp->Flush(); 272 } 273 } 274 // Fall through 275 case eInputReaderReactivate: 276 break; 277 278 case eInputReaderDeactivate: 279 break; 280 281 case eInputReaderAsynchronousOutputWritten: 282 break; 283 284 case eInputReaderGotToken: 285 ++cmd_object_expr->m_expr_line_count; 286 if (bytes && bytes_len) 287 { 288 cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1); 289 } 290 291 if (bytes_len == 0) 292 reader.SetIsDone(true); 293 break; 294 295 case eInputReaderInterrupt: 296 cmd_object_expr->m_expr_lines.clear(); 297 reader.SetIsDone (true); 298 if (!batch_mode) 299 { 300 StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream()); 301 if (async_strm_sp) 302 { 303 async_strm_sp->PutCString("Expression evaluation cancelled.\n"); 304 async_strm_sp->Flush(); 305 } 306 } 307 break; 308 309 case eInputReaderEndOfFile: 310 reader.SetIsDone (true); 311 break; 312 313 case eInputReaderDone: 314 if (cmd_object_expr->m_expr_lines.size() > 0) 315 { 316 StreamSP output_stream = reader.GetDebugger().GetAsyncOutputStream(); 317 StreamSP error_stream = reader.GetDebugger().GetAsyncErrorStream(); 318 cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 319 output_stream.get(), 320 error_stream.get()); 321 output_stream->Flush(); 322 error_stream->Flush(); 323 } 324 break; 325 } 326 327 return bytes_len; 328 } 329 330 bool 331 CommandObjectExpression::EvaluateExpression 332 ( 333 const char *expr, 334 Stream *output_stream, 335 Stream *error_stream, 336 CommandReturnObject *result 337 ) 338 { 339 // Don't use m_exe_ctx as this might be called asynchronously 340 // after the command object DoExecute has finished when doing 341 // multi-line expression that use an input reader... 342 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 343 344 Target *target = exe_ctx.GetTargetPtr(); 345 346 if (!target) 347 target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get(); 348 349 if (target) 350 { 351 lldb::ValueObjectSP result_valobj_sp; 352 353 ExecutionResults exe_results; 354 355 bool keep_in_memory = true; 356 357 EvaluateExpressionOptions options; 358 options.SetCoerceToId(m_varobj_options.use_objc) 359 .SetUnwindOnError(m_command_options.unwind_on_error) 360 .SetIgnoreBreakpoints (m_command_options.ignore_breakpoints) 361 .SetKeepInMemory(keep_in_memory) 362 .SetUseDynamic(m_varobj_options.use_dynamic) 363 .SetRunOthers(m_command_options.try_all_threads) 364 .SetTimeoutUsec(m_command_options.timeout); 365 366 exe_results = target->EvaluateExpression (expr, 367 exe_ctx.GetFramePtr(), 368 result_valobj_sp, 369 options); 370 371 if (result_valobj_sp) 372 { 373 Format format = m_format_options.GetFormat(); 374 375 if (result_valobj_sp->GetError().Success()) 376 { 377 if (format != eFormatVoid) 378 { 379 if (format != eFormatDefault) 380 result_valobj_sp->SetFormat (format); 381 382 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format)); 383 384 result_valobj_sp->Dump(*output_stream,options); 385 386 if (result) 387 result->SetStatus (eReturnStatusSuccessFinishResult); 388 } 389 } 390 else 391 { 392 if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult) 393 { 394 if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid()) 395 { 396 error_stream->PutCString("(void)\n"); 397 } 398 399 if (result) 400 result->SetStatus (eReturnStatusSuccessFinishResult); 401 } 402 else 403 { 404 const char *error_cstr = result_valobj_sp->GetError().AsCString(); 405 if (error_cstr && error_cstr[0]) 406 { 407 const size_t error_cstr_len = strlen (error_cstr); 408 const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n'; 409 if (strstr(error_cstr, "error:") != error_cstr) 410 error_stream->PutCString ("error: "); 411 error_stream->Write(error_cstr, error_cstr_len); 412 if (!ends_with_newline) 413 error_stream->EOL(); 414 } 415 else 416 { 417 error_stream->PutCString ("error: unknown error\n"); 418 } 419 420 if (result) 421 result->SetStatus (eReturnStatusFailed); 422 } 423 } 424 } 425 } 426 else 427 { 428 error_stream->Printf ("error: invalid execution context for expression\n"); 429 return false; 430 } 431 432 return true; 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 m_expr_lines.clear(); 449 m_expr_line_count = 0; 450 451 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 452 if (reader_sp) 453 { 454 Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback, 455 this, // baton 456 eInputReaderGranularityLine, // token size, to pass to callback function 457 NULL, // end token 458 NULL, // prompt 459 true)); // echo input 460 if (err.Success()) 461 { 462 m_interpreter.GetDebugger().PushInputReader (reader_sp); 463 result.SetStatus (eReturnStatusSuccessFinishNoResult); 464 } 465 else 466 { 467 result.AppendError (err.AsCString()); 468 result.SetStatus (eReturnStatusFailed); 469 } 470 } 471 else 472 { 473 result.AppendError("out of memory"); 474 result.SetStatus (eReturnStatusFailed); 475 } 476 return result.Succeeded(); 477 } 478 479 if (command[0] == '-') 480 { 481 // We have some options and these options MUST end with --. 482 const char *end_options = NULL; 483 const char *s = command; 484 while (s && s[0]) 485 { 486 end_options = ::strstr (s, "--"); 487 if (end_options) 488 { 489 end_options += 2; // Get past the "--" 490 if (::isspace (end_options[0])) 491 { 492 expr = end_options; 493 while (::isspace (*expr)) 494 ++expr; 495 break; 496 } 497 } 498 s = end_options; 499 } 500 501 if (end_options) 502 { 503 Args args (command, end_options - command); 504 if (!ParseOptions (args, result)) 505 return false; 506 507 Error error (m_option_group.NotifyOptionParsingFinished()); 508 if (error.Fail()) 509 { 510 result.AppendError (error.AsCString()); 511 result.SetStatus (eReturnStatusFailed); 512 return false; 513 } 514 } 515 } 516 517 if (expr == NULL) 518 expr = command; 519 520 if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result)) 521 return true; 522 523 result.SetStatus (eReturnStatusFailed); 524 return false; 525 } 526 527