CommandObjectExpression.cpp revision 258884
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/StackFrame.h" 36#include "lldb/Target/Target.h" 37#include "lldb/Target/Thread.h" 38#include "llvm/ADT/StringRef.h" 39 40using namespace lldb; 41using namespace lldb_private; 42 43CommandObjectExpression::CommandOptions::CommandOptions () : 44 OptionGroup() 45{ 46} 47 48 49CommandObjectExpression::CommandOptions::~CommandOptions () 50{ 51} 52 53static 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 60OptionDefinition 61CommandObjectExpression::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 72uint32_t 73CommandObjectExpression::CommandOptions::GetNumDefinitions () 74{ 75 return sizeof(g_option_table)/sizeof(OptionDefinition); 76} 77 78Error 79CommandObjectExpression::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 166void 167CommandObjectExpression::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 = false; 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 188const OptionDefinition* 189CommandObjectExpression::CommandOptions::GetDefinitions () 190{ 191 return g_option_table; 192} 193 194CommandObjectExpression::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 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\ 214User 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\ 220Examples: \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 247CommandObjectExpression::~CommandObjectExpression () 248{ 249} 250 251Options * 252CommandObjectExpression::GetOptions () 253{ 254 return &m_option_group; 255} 256 257size_t 258CommandObjectExpression::MultiLineExpressionCallback 259( 260 void *baton, 261 InputReader &reader, 262 lldb::InputReaderAction notification, 263 const char *bytes, 264 size_t bytes_len 265) 266{ 267 CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton; 268 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 269 270 switch (notification) 271 { 272 case eInputReaderActivate: 273 if (!batch_mode) 274 { 275 StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream()); 276 if (async_strm_sp) 277 { 278 async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n"); 279 async_strm_sp->Flush(); 280 } 281 } 282 // Fall through 283 case eInputReaderReactivate: 284 break; 285 286 case eInputReaderDeactivate: 287 break; 288 289 case eInputReaderAsynchronousOutputWritten: 290 break; 291 292 case eInputReaderGotToken: 293 ++cmd_object_expr->m_expr_line_count; 294 if (bytes && bytes_len) 295 { 296 cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1); 297 } 298 299 if (bytes_len == 0) 300 reader.SetIsDone(true); 301 break; 302 303 case eInputReaderInterrupt: 304 cmd_object_expr->m_expr_lines.clear(); 305 reader.SetIsDone (true); 306 if (!batch_mode) 307 { 308 StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream()); 309 if (async_strm_sp) 310 { 311 async_strm_sp->PutCString("Expression evaluation cancelled.\n"); 312 async_strm_sp->Flush(); 313 } 314 } 315 break; 316 317 case eInputReaderEndOfFile: 318 reader.SetIsDone (true); 319 break; 320 321 case eInputReaderDone: 322 if (cmd_object_expr->m_expr_lines.size() > 0) 323 { 324 StreamSP output_stream = reader.GetDebugger().GetAsyncOutputStream(); 325 StreamSP error_stream = reader.GetDebugger().GetAsyncErrorStream(); 326 cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 327 output_stream.get(), 328 error_stream.get()); 329 output_stream->Flush(); 330 error_stream->Flush(); 331 } 332 break; 333 } 334 335 return bytes_len; 336} 337 338bool 339CommandObjectExpression::EvaluateExpression 340( 341 const char *expr, 342 Stream *output_stream, 343 Stream *error_stream, 344 CommandReturnObject *result 345) 346{ 347 // Don't use m_exe_ctx as this might be called asynchronously 348 // after the command object DoExecute has finished when doing 349 // multi-line expression that use an input reader... 350 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 351 352 Target *target = exe_ctx.GetTargetPtr(); 353 354 if (!target) 355 target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get(); 356 357 if (target) 358 { 359 lldb::ValueObjectSP result_valobj_sp; 360 361 ExecutionResults exe_results; 362 363 bool keep_in_memory = true; 364 365 EvaluateExpressionOptions options; 366 options.SetCoerceToId(m_varobj_options.use_objc); 367 options.SetUnwindOnError(m_command_options.unwind_on_error); 368 options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints); 369 options.SetKeepInMemory(keep_in_memory); 370 options.SetUseDynamic(m_varobj_options.use_dynamic); 371 options.SetTryAllThreads(m_command_options.try_all_threads); 372 options.SetDebug(m_command_options.debug); 373 374 if (m_command_options.timeout > 0) 375 options.SetTimeoutUsec(m_command_options.timeout); 376 377 exe_results = target->EvaluateExpression (expr, 378 exe_ctx.GetFramePtr(), 379 result_valobj_sp, 380 options); 381 382 if (result_valobj_sp) 383 { 384 Format format = m_format_options.GetFormat(); 385 386 if (result_valobj_sp->GetError().Success()) 387 { 388 if (format != eFormatVoid) 389 { 390 if (format != eFormatDefault) 391 result_valobj_sp->SetFormat (format); 392 393 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format)); 394 395 result_valobj_sp->Dump(*output_stream,options); 396 397 if (result) 398 result->SetStatus (eReturnStatusSuccessFinishResult); 399 } 400 } 401 else 402 { 403 if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult) 404 { 405 if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid()) 406 { 407 error_stream->PutCString("(void)\n"); 408 } 409 410 if (result) 411 result->SetStatus (eReturnStatusSuccessFinishResult); 412 } 413 else 414 { 415 const char *error_cstr = result_valobj_sp->GetError().AsCString(); 416 if (error_cstr && error_cstr[0]) 417 { 418 const size_t error_cstr_len = strlen (error_cstr); 419 const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n'; 420 if (strstr(error_cstr, "error:") != error_cstr) 421 error_stream->PutCString ("error: "); 422 error_stream->Write(error_cstr, error_cstr_len); 423 if (!ends_with_newline) 424 error_stream->EOL(); 425 } 426 else 427 { 428 error_stream->PutCString ("error: unknown error\n"); 429 } 430 431 if (result) 432 result->SetStatus (eReturnStatusFailed); 433 } 434 } 435 } 436 } 437 else 438 { 439 error_stream->Printf ("error: invalid execution context for expression\n"); 440 return false; 441 } 442 443 return true; 444} 445 446bool 447CommandObjectExpression::DoExecute 448( 449 const char *command, 450 CommandReturnObject &result 451) 452{ 453 m_option_group.NotifyOptionParsingStarting(); 454 455 const char * expr = NULL; 456 457 if (command[0] == '\0') 458 { 459 m_expr_lines.clear(); 460 m_expr_line_count = 0; 461 462 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 463 if (reader_sp) 464 { 465 Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback, 466 this, // baton 467 eInputReaderGranularityLine, // token size, to pass to callback function 468 NULL, // end token 469 NULL, // prompt 470 true)); // echo input 471 if (err.Success()) 472 { 473 m_interpreter.GetDebugger().PushInputReader (reader_sp); 474 result.SetStatus (eReturnStatusSuccessFinishNoResult); 475 } 476 else 477 { 478 result.AppendError (err.AsCString()); 479 result.SetStatus (eReturnStatusFailed); 480 } 481 } 482 else 483 { 484 result.AppendError("out of memory"); 485 result.SetStatus (eReturnStatusFailed); 486 } 487 return result.Succeeded(); 488 } 489 490 if (command[0] == '-') 491 { 492 // We have some options and these options MUST end with --. 493 const char *end_options = NULL; 494 const char *s = command; 495 while (s && s[0]) 496 { 497 end_options = ::strstr (s, "--"); 498 if (end_options) 499 { 500 end_options += 2; // Get past the "--" 501 if (::isspace (end_options[0])) 502 { 503 expr = end_options; 504 while (::isspace (*expr)) 505 ++expr; 506 break; 507 } 508 } 509 s = end_options; 510 } 511 512 if (end_options) 513 { 514 Args args (command, end_options - command); 515 if (!ParseOptions (args, result)) 516 return false; 517 518 Error error (m_option_group.NotifyOptionParsingFinished()); 519 if (error.Fail()) 520 { 521 result.AppendError (error.AsCString()); 522 result.SetStatus (eReturnStatusFailed); 523 return false; 524 } 525 } 526 } 527 528 if (expr == NULL) 529 expr = command; 530 531 if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result)) 532 return true; 533 534 result.SetStatus (eReturnStatusFailed); 535 return false; 536} 537 538