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