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/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 OptionDefinition 53 CommandObjectExpression::CommandOptions::g_option_table[] = 54 { 55 { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', required_argument, NULL, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, 56 { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', required_argument, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, 57 { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value for running the expression."}, 58 { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, breakpoint hit or signal."}, 59 }; 60 61 62 uint32_t 63 CommandObjectExpression::CommandOptions::GetNumDefinitions () 64 { 65 return sizeof(g_option_table)/sizeof(OptionDefinition); 66 } 67 68 Error 69 CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &interpreter, 70 uint32_t option_idx, 71 const char *option_arg) 72 { 73 Error error; 74 75 const int short_option = g_option_table[option_idx].short_option; 76 77 switch (short_option) 78 { 79 //case 'l': 80 //if (language.SetLanguageFromCString (option_arg) == false) 81 //{ 82 // error.SetErrorStringWithFormat("invalid language option argument '%s'", option_arg); 83 //} 84 //break; 85 86 case 'a': 87 { 88 bool success; 89 bool result; 90 result = Args::StringToBoolean(option_arg, true, &success); 91 if (!success) 92 error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg); 93 else 94 try_all_threads = result; 95 } 96 break; 97 98 case 'i': 99 { 100 bool success; 101 bool tmp_value = Args::StringToBoolean(option_arg, true, &success); 102 if (success) 103 ignore_breakpoints = tmp_value; 104 else 105 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); 106 break; 107 } 108 case 't': 109 { 110 bool success; 111 uint32_t result; 112 result = Args::StringToUInt32(option_arg, 0, 0, &success); 113 if (success) 114 timeout = result; 115 else 116 error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg); 117 } 118 break; 119 120 case 'u': 121 { 122 bool success; 123 bool tmp_value = Args::StringToBoolean(option_arg, true, &success); 124 if (success) 125 unwind_on_error = tmp_value; 126 else 127 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); 128 break; 129 } 130 default: 131 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 132 break; 133 } 134 135 return error; 136 } 137 138 void 139 CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter) 140 { 141 Process *process = interpreter.GetExecutionContext().GetProcessPtr(); 142 if (process != NULL) 143 { 144 ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions(); 145 unwind_on_error = process->GetUnwindOnErrorInExpressions(); 146 } 147 else 148 { 149 ignore_breakpoints = false; 150 unwind_on_error = true; 151 } 152 153 show_summary = true; 154 try_all_threads = true; 155 timeout = 0; 156 } 157 158 const OptionDefinition* 159 CommandObjectExpression::CommandOptions::GetDefinitions () 160 { 161 return g_option_table; 162 } 163 164 CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) : 165 CommandObjectRaw (interpreter, 166 "expression", 167 "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.", 168 NULL, 169 eFlagProcessMustBePaused | eFlagTryTargetAPILock), 170 m_option_group (interpreter), 171 m_format_options (eFormatDefault), 172 m_command_options (), 173 m_expr_line_count (0), 174 m_expr_lines () 175 { 176 SetHelpLong( 177 "Timeouts:\n\ 178 If the expression can be evaluated statically (without runnning code) then it will be.\n\ 179 Otherwise, by default the expression will run on the current thread with a short timeout:\n\ 180 currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted\n\ 181 and resumed with all threads running. You can use the -a option to disable retrying on all\n\ 182 threads. You can use the -t option to set a shorter timeout.\n\ 183 \n\ 184 User defined variables:\n\ 185 You can define your own variables for convenience or to be used in subsequent expressions.\n\ 186 You define them the same way you would define variables in C. If the first character of \n\ 187 your user defined variable is a $, then the variable's value will be available in future\n\ 188 expressions, otherwise it will just be available in the current expression.\n\ 189 \n\ 190 Examples: \n\ 191 \n\ 192 expr my_struct->a = my_array[3] \n\ 193 expr -f bin -- (index * 8) + 5 \n\ 194 expr unsigned int $foo = 5\n\ 195 expr char c[] = \"foo\"; c[0]\n"); 196 197 CommandArgumentEntry arg; 198 CommandArgumentData expression_arg; 199 200 // Define the first (and only) variant of this arg. 201 expression_arg.arg_type = eArgTypeExpression; 202 expression_arg.arg_repetition = eArgRepeatPlain; 203 204 // There is only one variant this argument could be; put it into the argument entry. 205 arg.push_back (expression_arg); 206 207 // Push the data for the first argument into the m_arguments vector. 208 m_arguments.push_back (arg); 209 210 // Add the "--format" and "--gdb-format" 211 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); 212 m_option_group.Append (&m_command_options); 213 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2); 214 m_option_group.Finalize(); 215 } 216 217 CommandObjectExpression::~CommandObjectExpression () 218 { 219 } 220 221 Options * 222 CommandObjectExpression::GetOptions () 223 { 224 return &m_option_group; 225 } 226 227 size_t 228 CommandObjectExpression::MultiLineExpressionCallback 229 ( 230 void *baton, 231 InputReader &reader, 232 lldb::InputReaderAction notification, 233 const char *bytes, 234 size_t bytes_len 235 ) 236 { 237 CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton; 238 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 239 240 switch (notification) 241 { 242 case eInputReaderActivate: 243 if (!batch_mode) 244 { 245 StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream()); 246 if (async_strm_sp) 247 { 248 async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n"); 249 async_strm_sp->Flush(); 250 } 251 } 252 // Fall through 253 case eInputReaderReactivate: 254 break; 255 256 case eInputReaderDeactivate: 257 break; 258 259 case eInputReaderAsynchronousOutputWritten: 260 break; 261 262 case eInputReaderGotToken: 263 ++cmd_object_expr->m_expr_line_count; 264 if (bytes && bytes_len) 265 { 266 cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1); 267 } 268 269 if (bytes_len == 0) 270 reader.SetIsDone(true); 271 break; 272 273 case eInputReaderInterrupt: 274 cmd_object_expr->m_expr_lines.clear(); 275 reader.SetIsDone (true); 276 if (!batch_mode) 277 { 278 StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream()); 279 if (async_strm_sp) 280 { 281 async_strm_sp->PutCString("Expression evaluation cancelled.\n"); 282 async_strm_sp->Flush(); 283 } 284 } 285 break; 286 287 case eInputReaderEndOfFile: 288 reader.SetIsDone (true); 289 break; 290 291 case eInputReaderDone: 292 if (cmd_object_expr->m_expr_lines.size() > 0) 293 { 294 StreamSP output_stream = reader.GetDebugger().GetAsyncOutputStream(); 295 StreamSP error_stream = reader.GetDebugger().GetAsyncErrorStream(); 296 cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 297 output_stream.get(), 298 error_stream.get()); 299 output_stream->Flush(); 300 error_stream->Flush(); 301 } 302 break; 303 } 304 305 return bytes_len; 306 } 307 308 bool 309 CommandObjectExpression::EvaluateExpression 310 ( 311 const char *expr, 312 Stream *output_stream, 313 Stream *error_stream, 314 CommandReturnObject *result 315 ) 316 { 317 // Don't use m_exe_ctx as this might be called asynchronously 318 // after the command object DoExecute has finished when doing 319 // multi-line expression that use an input reader... 320 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); 321 322 Target *target = exe_ctx.GetTargetPtr(); 323 324 if (!target) 325 target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get(); 326 327 if (target) 328 { 329 lldb::ValueObjectSP result_valobj_sp; 330 331 ExecutionResults exe_results; 332 333 bool keep_in_memory = true; 334 335 EvaluateExpressionOptions options; 336 options.SetCoerceToId(m_varobj_options.use_objc) 337 .SetUnwindOnError(m_command_options.unwind_on_error) 338 .SetIgnoreBreakpoints (m_command_options.ignore_breakpoints) 339 .SetKeepInMemory(keep_in_memory) 340 .SetUseDynamic(m_varobj_options.use_dynamic) 341 .SetRunOthers(m_command_options.try_all_threads) 342 .SetTimeoutUsec(m_command_options.timeout); 343 344 exe_results = target->EvaluateExpression (expr, 345 exe_ctx.GetFramePtr(), 346 result_valobj_sp, 347 options); 348 349 if ((exe_results == eExecutionInterrupted && !m_command_options.unwind_on_error) 350 ||(exe_results == eExecutionHitBreakpoint && !m_command_options.ignore_breakpoints)) 351 { 352 uint32_t start_frame = 0; 353 uint32_t num_frames = 1; 354 uint32_t num_frames_with_source = 0; 355 Thread *thread = exe_ctx.GetThreadPtr(); 356 if (thread) 357 { 358 thread->GetStatus (result->GetOutputStream(), 359 start_frame, 360 num_frames, 361 num_frames_with_source); 362 } 363 else 364 { 365 Process *process = exe_ctx.GetProcessPtr(); 366 if (process) 367 { 368 bool only_threads_with_stop_reason = true; 369 process->GetThreadStatus (result->GetOutputStream(), 370 only_threads_with_stop_reason, 371 start_frame, 372 num_frames, 373 num_frames_with_source); 374 } 375 } 376 } 377 378 if (result_valobj_sp) 379 { 380 Format format = m_format_options.GetFormat(); 381 382 if (result_valobj_sp->GetError().Success()) 383 { 384 if (format != eFormatVoid) 385 { 386 if (format != eFormatDefault) 387 result_valobj_sp->SetFormat (format); 388 389 ValueObject::DumpValueObjectOptions options; 390 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth); 391 if (m_varobj_options.use_objc) 392 options.SetShowSummary(false); 393 else 394 options.SetOmitSummaryDepth(m_varobj_options.no_summary_depth); 395 options.SetMaximumDepth(m_varobj_options.max_depth) 396 .SetShowTypes(m_varobj_options.show_types) 397 .SetShowLocation(m_varobj_options.show_location) 398 .SetUseObjectiveC(m_varobj_options.use_objc) 399 .SetUseDynamicType(m_varobj_options.use_dynamic) 400 .SetUseSyntheticValue(m_varobj_options.use_synth) 401 .SetFlatOutput(m_varobj_options.flat_output) 402 .SetIgnoreCap(m_varobj_options.ignore_cap) 403 .SetFormat(format) 404 .SetHideRootType(m_varobj_options.use_objc) 405 .SetHideName(m_varobj_options.use_objc) 406 .SetHideValue(m_varobj_options.use_objc); 407 408 if (m_varobj_options.be_raw) 409 options.SetRawDisplay(true); 410 411 ValueObject::DumpValueObject (*(output_stream), 412 result_valobj_sp.get(), // Variable object to dump 413 options); 414 if (result) 415 result->SetStatus (eReturnStatusSuccessFinishResult); 416 } 417 } 418 else 419 { 420 if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult) 421 { 422 if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid()) 423 { 424 error_stream->PutCString("(void)\n"); 425 } 426 427 if (result) 428 result->SetStatus (eReturnStatusSuccessFinishResult); 429 } 430 else 431 { 432 const char *error_cstr = result_valobj_sp->GetError().AsCString(); 433 if (error_cstr && error_cstr[0]) 434 { 435 const size_t error_cstr_len = strlen (error_cstr); 436 const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n'; 437 if (strstr(error_cstr, "error:") != error_cstr) 438 error_stream->PutCString ("error: "); 439 error_stream->Write(error_cstr, error_cstr_len); 440 if (!ends_with_newline) 441 error_stream->EOL(); 442 } 443 else 444 { 445 error_stream->PutCString ("error: unknown error\n"); 446 } 447 448 if (result) 449 result->SetStatus (eReturnStatusFailed); 450 } 451 } 452 } 453 } 454 else 455 { 456 error_stream->Printf ("error: invalid execution context for expression\n"); 457 return false; 458 } 459 460 return true; 461 } 462 463 bool 464 CommandObjectExpression::DoExecute 465 ( 466 const char *command, 467 CommandReturnObject &result 468 ) 469 { 470 m_option_group.NotifyOptionParsingStarting(); 471 472 const char * expr = NULL; 473 474 if (command[0] == '\0') 475 { 476 m_expr_lines.clear(); 477 m_expr_line_count = 0; 478 479 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 480 if (reader_sp) 481 { 482 Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback, 483 this, // baton 484 eInputReaderGranularityLine, // token size, to pass to callback function 485 NULL, // end token 486 NULL, // prompt 487 true)); // echo input 488 if (err.Success()) 489 { 490 m_interpreter.GetDebugger().PushInputReader (reader_sp); 491 result.SetStatus (eReturnStatusSuccessFinishNoResult); 492 } 493 else 494 { 495 result.AppendError (err.AsCString()); 496 result.SetStatus (eReturnStatusFailed); 497 } 498 } 499 else 500 { 501 result.AppendError("out of memory"); 502 result.SetStatus (eReturnStatusFailed); 503 } 504 return result.Succeeded(); 505 } 506 507 if (command[0] == '-') 508 { 509 // We have some options and these options MUST end with --. 510 const char *end_options = NULL; 511 const char *s = command; 512 while (s && s[0]) 513 { 514 end_options = ::strstr (s, "--"); 515 if (end_options) 516 { 517 end_options += 2; // Get past the "--" 518 if (::isspace (end_options[0])) 519 { 520 expr = end_options; 521 while (::isspace (*expr)) 522 ++expr; 523 break; 524 } 525 } 526 s = end_options; 527 } 528 529 if (end_options) 530 { 531 Args args (command, end_options - command); 532 if (!ParseOptions (args, result)) 533 return false; 534 535 Error error (m_option_group.NotifyOptionParsingFinished()); 536 if (error.Fail()) 537 { 538 result.AppendError (error.AsCString()); 539 result.SetStatus (eReturnStatusFailed); 540 return false; 541 } 542 } 543 } 544 545 if (expr == NULL) 546 expr = command; 547 548 if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result)) 549 return true; 550 551 result.SetStatus (eReturnStatusFailed); 552 return false; 553 } 554 555