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 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 Examples: \n\ 184 \n\ 185 expr my_struct->a = my_array[3] \n\ 186 expr -f bin -- (index * 8) + 5 \n\ 187 expr char c[] = \"foo\"; c[0]\n"); 188 189 CommandArgumentEntry arg; 190 CommandArgumentData expression_arg; 191 192 // Define the first (and only) variant of this arg. 193 expression_arg.arg_type = eArgTypeExpression; 194 expression_arg.arg_repetition = eArgRepeatPlain; 195 196 // There is only one variant this argument could be; put it into the argument entry. 197 arg.push_back (expression_arg); 198 199 // Push the data for the first argument into the m_arguments vector. 200 m_arguments.push_back (arg); 201 202 // Add the "--format" and "--gdb-format" 203 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); 204 m_option_group.Append (&m_command_options); 205 m_option_group.Finalize(); 206 } 207 208 CommandObjectExpression::~CommandObjectExpression () 209 { 210 } 211 212 Options * 213 CommandObjectExpression::GetOptions () 214 { 215 return &m_option_group; 216 } 217 218 size_t 219 CommandObjectExpression::MultiLineExpressionCallback 220 ( 221 void *baton, 222 InputReader &reader, 223 lldb::InputReaderAction notification, 224 const char *bytes, 225 size_t bytes_len 226 ) 227 { 228 CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton; 229 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 230 231 switch (notification) 232 { 233 case eInputReaderActivate: 234 if (!batch_mode) 235 { 236 StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream()); 237 if (async_strm_sp) 238 { 239 async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n"); 240 async_strm_sp->Flush(); 241 } 242 } 243 // Fall through 244 case eInputReaderReactivate: 245 break; 246 247 case eInputReaderDeactivate: 248 break; 249 250 case eInputReaderAsynchronousOutputWritten: 251 break; 252 253 case eInputReaderGotToken: 254 ++cmd_object_expr->m_expr_line_count; 255 if (bytes && bytes_len) 256 { 257 cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1); 258 } 259 260 if (bytes_len == 0) 261 reader.SetIsDone(true); 262 break; 263 264 case eInputReaderInterrupt: 265 cmd_object_expr->m_expr_lines.clear(); 266 reader.SetIsDone (true); 267 if (!batch_mode) 268 { 269 StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream()); 270 if (async_strm_sp) 271 { 272 async_strm_sp->PutCString("Expression evaluation cancelled.\n"); 273 async_strm_sp->Flush(); 274 } 275 } 276 break; 277 278 case eInputReaderEndOfFile: 279 reader.SetIsDone (true); 280 break; 281 282 case eInputReaderDone: 283 if (cmd_object_expr->m_expr_lines.size() > 0) 284 { 285 StreamSP output_stream = reader.GetDebugger().GetAsyncOutputStream(); 286 StreamSP error_stream = reader.GetDebugger().GetAsyncErrorStream(); 287 cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 288 output_stream.get(), 289 error_stream.get()); 290 output_stream->Flush(); 291 error_stream->Flush(); 292 } 293 break; 294 } 295 296 return bytes_len; 297 } 298 299 bool 300 CommandObjectExpression::EvaluateExpression 301 ( 302 const char *expr, 303 Stream *output_stream, 304 Stream *error_stream, 305 CommandReturnObject *result 306 ) 307 { 308 Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); 309 310 if (!target) 311 target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get(); 312 313 if (target) 314 { 315 lldb::ValueObjectSP result_valobj_sp; 316 317 ExecutionResults exe_results; 318 319 bool keep_in_memory = true; 320 lldb::DynamicValueType use_dynamic; 321 // If use dynamic is not set, get it from the target: 322 switch (m_command_options.use_dynamic) 323 { 324 case eLazyBoolCalculate: 325 use_dynamic = target->GetPreferDynamicValue(); 326 break; 327 case eLazyBoolYes: 328 use_dynamic = lldb::eDynamicCanRunTarget; 329 break; 330 case eLazyBoolNo: 331 use_dynamic = lldb::eNoDynamicValues; 332 break; 333 } 334 335 EvaluateExpressionOptions options; 336 options.SetCoerceToId(m_command_options.print_object) 337 .SetUnwindOnError(m_command_options.unwind_on_error) 338 .SetKeepInMemory(keep_in_memory) 339 .SetUseDynamic(use_dynamic) 340 .SetRunOthers(m_command_options.try_all_threads) 341 .SetTimeoutUsec(m_command_options.timeout); 342 343 exe_results = target->EvaluateExpression (expr, 344 m_interpreter.GetExecutionContext().GetFramePtr(), 345 result_valobj_sp, 346 options); 347 348 if (exe_results == eExecutionInterrupted && !m_command_options.unwind_on_error) 349 { 350 uint32_t start_frame = 0; 351 uint32_t num_frames = 1; 352 uint32_t num_frames_with_source = 0; 353 Thread *thread = m_interpreter.GetExecutionContext().GetThreadPtr(); 354 if (thread) 355 { 356 thread->GetStatus (result->GetOutputStream(), 357 start_frame, 358 num_frames, 359 num_frames_with_source); 360 } 361 else 362 { 363 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 364 if (process) 365 { 366 bool only_threads_with_stop_reason = true; 367 process->GetThreadStatus (result->GetOutputStream(), 368 only_threads_with_stop_reason, 369 start_frame, 370 num_frames, 371 num_frames_with_source); 372 } 373 } 374 } 375 376 if (result_valobj_sp) 377 { 378 Format format = m_format_options.GetFormat(); 379 380 if (result_valobj_sp->GetError().Success()) 381 { 382 if (format != eFormatVoid) 383 { 384 if (format != eFormatDefault) 385 result_valobj_sp->SetFormat (format); 386 387 ValueObject::DumpValueObjectOptions options; 388 options.SetMaximumPointerDepth(0) 389 .SetMaximumDepth(UINT32_MAX) 390 .SetShowLocation(false) 391 .SetShowTypes(m_command_options.show_types) 392 .SetUseObjectiveC(m_command_options.print_object) 393 .SetUseDynamicType(use_dynamic) 394 .SetScopeChecked(true) 395 .SetFlatOutput(false) 396 .SetUseSyntheticValue(true) 397 .SetIgnoreCap(false) 398 .SetFormat(format) 399 .SetSummary() 400 .SetShowSummary(!m_command_options.print_object) 401 .SetHideRootType(m_command_options.print_object); 402 403 ValueObject::DumpValueObject (*(output_stream), 404 result_valobj_sp.get(), // Variable object to dump 405 options); 406 if (result) 407 result->SetStatus (eReturnStatusSuccessFinishResult); 408 } 409 } 410 else 411 { 412 if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult) 413 { 414 if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid()) 415 { 416 error_stream->PutCString("(void)\n"); 417 } 418 419 if (result) 420 result->SetStatus (eReturnStatusSuccessFinishResult); 421 } 422 else 423 { 424 const char *error_cstr = result_valobj_sp->GetError().AsCString(); 425 if (error_cstr && error_cstr[0]) 426 { 427 int error_cstr_len = strlen (error_cstr); 428 const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n'; 429 if (strstr(error_cstr, "error:") != error_cstr) 430 error_stream->PutCString ("error: "); 431 error_stream->Write(error_cstr, error_cstr_len); 432 if (!ends_with_newline) 433 error_stream->EOL(); 434 } 435 else 436 { 437 error_stream->PutCString ("error: unknown error\n"); 438 } 439 440 if (result) 441 result->SetStatus (eReturnStatusFailed); 442 } 443 } 444 } 445 } 446 else 447 { 448 error_stream->Printf ("error: invalid execution context for expression\n"); 449 return false; 450 } 451 452 return true; 453 } 454 455 bool 456 CommandObjectExpression::DoExecute 457 ( 458 const char *command, 459 CommandReturnObject &result 460 ) 461 { 462 m_option_group.NotifyOptionParsingStarting(); 463 464 const char * expr = NULL; 465 466 if (command[0] == '\0') 467 { 468 m_expr_lines.clear(); 469 m_expr_line_count = 0; 470 471 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 472 if (reader_sp) 473 { 474 Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback, 475 this, // baton 476 eInputReaderGranularityLine, // token size, to pass to callback function 477 NULL, // end token 478 NULL, // prompt 479 true)); // echo input 480 if (err.Success()) 481 { 482 m_interpreter.GetDebugger().PushInputReader (reader_sp); 483 result.SetStatus (eReturnStatusSuccessFinishNoResult); 484 } 485 else 486 { 487 result.AppendError (err.AsCString()); 488 result.SetStatus (eReturnStatusFailed); 489 } 490 } 491 else 492 { 493 result.AppendError("out of memory"); 494 result.SetStatus (eReturnStatusFailed); 495 } 496 return result.Succeeded(); 497 } 498 499 if (command[0] == '-') 500 { 501 // We have some options and these options MUST end with --. 502 const char *end_options = NULL; 503 const char *s = command; 504 while (s && s[0]) 505 { 506 end_options = ::strstr (s, "--"); 507 if (end_options) 508 { 509 end_options += 2; // Get past the "--" 510 if (::isspace (end_options[0])) 511 { 512 expr = end_options; 513 while (::isspace (*expr)) 514 ++expr; 515 break; 516 } 517 } 518 s = end_options; 519 } 520 521 if (end_options) 522 { 523 Args args (command, end_options - command); 524 if (!ParseOptions (args, result)) 525 return false; 526 527 Error error (m_option_group.NotifyOptionParsingFinished()); 528 if (error.Fail()) 529 { 530 result.AppendError (error.AsCString()); 531 result.SetStatus (eReturnStatusFailed); 532 return false; 533 } 534 } 535 } 536 537 if (expr == NULL) 538 expr = command; 539 540 if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result)) 541 return true; 542 543 result.SetStatus (eReturnStatusFailed); 544 return false; 545 } 546 547