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 "CommandObjectExpression.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Interpreter/Args.h" 17 #include "lldb/Core/Value.h" 18 #include "lldb/Core/InputReader.h" 19 #include "lldb/Core/ValueObjectVariable.h" 20 #include "lldb/Expression/ClangExpressionVariable.h" 21 #include "lldb/Expression/ClangUserExpression.h" 22 #include "lldb/Expression/ClangFunction.h" 23 #include "lldb/Expression/DWARFExpression.h" 24 #include "lldb/Host/Host.h" 25 #include "lldb/Core/Debugger.h" 26 #include "lldb/Interpreter/CommandInterpreter.h" 27 #include "lldb/Interpreter/CommandReturnObject.h" 28 #include "lldb/Target/ObjCLanguageRuntime.h" 29 #include "lldb/Symbol/ObjectFile.h" 30 #include "lldb/Symbol/Variable.h" 31 #include "lldb/Target/Process.h" 32 #include "lldb/Target/StackFrame.h" 33 #include "lldb/Target/Target.h" 34 #include "lldb/Target/Thread.h" 35 #include "llvm/ADT/StringRef.h" 36 37 using namespace lldb; 38 using namespace lldb_private; 39 40 CommandObjectExpression::CommandOptions::CommandOptions () : 41 OptionGroup() 42 { 43 } 44 45 46 CommandObjectExpression::CommandOptions::~CommandOptions () 47 { 48 } 49 50 OptionDefinition 51 CommandObjectExpression::CommandOptions::g_option_table[] = 52 { 53 { 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."}, 54 { 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."}, 55 { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value for running the expression."}, 56 { 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."}, 57 { LLDB_OPT_SET_2 , false, "object-description", 'o', no_argument, NULL, 0, eArgTypeNone, "Print the object description of the value resulting from the expression."}, 58 }; 59 60 61 uint32_t 62 CommandObjectExpression::CommandOptions::GetNumDefinitions () 63 { 64 return sizeof(g_option_table)/sizeof(OptionDefinition); 65 } 66 67 Error 68 CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &interpreter, 69 uint32_t option_idx, 70 const char *option_arg) 71 { 72 Error error; 73 74 const char short_option = (char) g_option_table[option_idx].short_option; 75 76 switch (short_option) 77 { 78 //case 'l': 79 //if (language.SetLanguageFromCString (option_arg) == false) 80 //{ 81 // error.SetErrorStringWithFormat("invalid language option argument '%s'", option_arg); 82 //} 83 //break; 84 85 case 'a': 86 { 87 bool success; 88 bool result; 89 result = Args::StringToBoolean(option_arg, true, &success); 90 if (!success) 91 error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg); 92 else 93 try_all_threads = result; 94 } 95 break; 96 97 case 'd': 98 { 99 bool success; 100 bool result; 101 result = Args::StringToBoolean(option_arg, true, &success); 102 if (!success) 103 error.SetErrorStringWithFormat("invalid dynamic value setting: \"%s\"", option_arg); 104 else 105 { 106 if (result) 107 use_dynamic = eLazyBoolYes; 108 else 109 use_dynamic = eLazyBoolNo; 110 } 111 } 112 break; 113 114 case 'o': 115 print_object = true; 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 unwind_on_error = Args::StringToBoolean(option_arg, true, &success); 134 if (!success) 135 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); 136 break; 137 } 138 default: 139 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 140 break; 141 } 142 143 return error; 144 } 145 146 void 147 CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter) 148 { 149 use_dynamic = eLazyBoolCalculate; 150 print_object = false; 151 unwind_on_error = true; 152 show_types = true; 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), 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.Finalize(); 214 } 215 216 CommandObjectExpression::~CommandObjectExpression () 217 { 218 } 219 220 Options * 221 CommandObjectExpression::GetOptions () 222 { 223 return &m_option_group; 224 } 225 226 size_t 227 CommandObjectExpression::MultiLineExpressionCallback 228 ( 229 void *baton, 230 InputReader &reader, 231 lldb::InputReaderAction notification, 232 const char *bytes, 233 size_t bytes_len 234 ) 235 { 236 CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton; 237 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 238 239 switch (notification) 240 { 241 case eInputReaderActivate: 242 if (!batch_mode) 243 { 244 StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream()); 245 if (async_strm_sp) 246 { 247 async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n"); 248 async_strm_sp->Flush(); 249 } 250 } 251 // Fall through 252 case eInputReaderReactivate: 253 break; 254 255 case eInputReaderDeactivate: 256 break; 257 258 case eInputReaderAsynchronousOutputWritten: 259 break; 260 261 case eInputReaderGotToken: 262 ++cmd_object_expr->m_expr_line_count; 263 if (bytes && bytes_len) 264 { 265 cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1); 266 } 267 268 if (bytes_len == 0) 269 reader.SetIsDone(true); 270 break; 271 272 case eInputReaderInterrupt: 273 cmd_object_expr->m_expr_lines.clear(); 274 reader.SetIsDone (true); 275 if (!batch_mode) 276 { 277 StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream()); 278 if (async_strm_sp) 279 { 280 async_strm_sp->PutCString("Expression evaluation cancelled.\n"); 281 async_strm_sp->Flush(); 282 } 283 } 284 break; 285 286 case eInputReaderEndOfFile: 287 reader.SetIsDone (true); 288 break; 289 290 case eInputReaderDone: 291 if (cmd_object_expr->m_expr_lines.size() > 0) 292 { 293 StreamSP output_stream = reader.GetDebugger().GetAsyncOutputStream(); 294 StreamSP error_stream = reader.GetDebugger().GetAsyncErrorStream(); 295 cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 296 output_stream.get(), 297 error_stream.get()); 298 output_stream->Flush(); 299 error_stream->Flush(); 300 } 301 break; 302 } 303 304 return bytes_len; 305 } 306 307 bool 308 CommandObjectExpression::EvaluateExpression 309 ( 310 const char *expr, 311 Stream *output_stream, 312 Stream *error_stream, 313 CommandReturnObject *result 314 ) 315 { 316 Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); 317 318 if (!target) 319 target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get(); 320 321 if (target) 322 { 323 lldb::ValueObjectSP result_valobj_sp; 324 325 ExecutionResults exe_results; 326 327 bool keep_in_memory = true; 328 lldb::DynamicValueType use_dynamic; 329 // If use dynamic is not set, get it from the target: 330 switch (m_command_options.use_dynamic) 331 { 332 case eLazyBoolCalculate: 333 use_dynamic = target->GetPreferDynamicValue(); 334 break; 335 case eLazyBoolYes: 336 use_dynamic = lldb::eDynamicCanRunTarget; 337 break; 338 case eLazyBoolNo: 339 use_dynamic = lldb::eNoDynamicValues; 340 break; 341 } 342 343 EvaluateExpressionOptions options; 344 options.SetCoerceToId(m_command_options.print_object) 345 .SetUnwindOnError(m_command_options.unwind_on_error) 346 .SetKeepInMemory(keep_in_memory) 347 .SetUseDynamic(use_dynamic) 348 .SetRunOthers(m_command_options.try_all_threads) 349 .SetTimeoutUsec(m_command_options.timeout); 350 351 exe_results = target->EvaluateExpression (expr, 352 m_interpreter.GetExecutionContext().GetFramePtr(), 353 result_valobj_sp, 354 options); 355 356 if (exe_results == eExecutionInterrupted && !m_command_options.unwind_on_error) 357 { 358 uint32_t start_frame = 0; 359 uint32_t num_frames = 1; 360 uint32_t num_frames_with_source = 0; 361 Thread *thread = m_interpreter.GetExecutionContext().GetThreadPtr(); 362 if (thread) 363 { 364 thread->GetStatus (result->GetOutputStream(), 365 start_frame, 366 num_frames, 367 num_frames_with_source); 368 } 369 else 370 { 371 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 372 if (process) 373 { 374 bool only_threads_with_stop_reason = true; 375 process->GetThreadStatus (result->GetOutputStream(), 376 only_threads_with_stop_reason, 377 start_frame, 378 num_frames, 379 num_frames_with_source); 380 } 381 } 382 } 383 384 if (result_valobj_sp) 385 { 386 Format format = m_format_options.GetFormat(); 387 388 if (result_valobj_sp->GetError().Success()) 389 { 390 if (format != eFormatVoid) 391 { 392 if (format != eFormatDefault) 393 result_valobj_sp->SetFormat (format); 394 395 ValueObject::DumpValueObjectOptions options; 396 options.SetMaximumPointerDepth(0) 397 .SetMaximumDepth(UINT32_MAX) 398 .SetShowLocation(false) 399 .SetShowTypes(m_command_options.show_types) 400 .SetUseObjectiveC(m_command_options.print_object) 401 .SetUseDynamicType(use_dynamic) 402 .SetScopeChecked(true) 403 .SetFlatOutput(false) 404 .SetUseSyntheticValue(true) 405 .SetIgnoreCap(false) 406 .SetFormat(format) 407 .SetSummary() 408 .SetShowSummary(!m_command_options.print_object) 409 .SetHideRootType(m_command_options.print_object); 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 int 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