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