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 ValueObject::DumpValueObject (*(output_stream), 375 result_valobj_sp.get(), // Variable object to dump 376 options); 377 if (result) 378 result->SetStatus (eReturnStatusSuccessFinishResult); 379 } 380 } 381 else 382 { 383 if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult) 384 { 385 if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid()) 386 { 387 error_stream->PutCString("(void)\n"); 388 } 389 390 if (result) 391 result->SetStatus (eReturnStatusSuccessFinishResult); 392 } 393 else 394 { 395 const char *error_cstr = result_valobj_sp->GetError().AsCString(); 396 if (error_cstr && error_cstr[0]) 397 { 398 int error_cstr_len = strlen (error_cstr); 399 const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n'; 400 if (strstr(error_cstr, "error:") != error_cstr) 401 error_stream->PutCString ("error: "); 402 error_stream->Write(error_cstr, error_cstr_len); 403 if (!ends_with_newline) 404 error_stream->EOL(); 405 } 406 else 407 { 408 error_stream->PutCString ("error: unknown error\n"); 409 } 410 411 if (result) 412 result->SetStatus (eReturnStatusFailed); 413 } 414 } 415 } 416 } 417 else 418 { 419 error_stream->Printf ("error: invalid execution context for expression\n"); 420 return false; 421 } 422 423 return true; 424 } 425 426 bool 427 CommandObjectExpression::DoExecute 428 ( 429 const char *command, 430 CommandReturnObject &result 431 ) 432 { 433 m_option_group.NotifyOptionParsingStarting(); 434 435 const char * expr = NULL; 436 437 if (command[0] == '\0') 438 { 439 m_expr_lines.clear(); 440 m_expr_line_count = 0; 441 442 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 443 if (reader_sp) 444 { 445 Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback, 446 this, // baton 447 eInputReaderGranularityLine, // token size, to pass to callback function 448 NULL, // end token 449 NULL, // prompt 450 true)); // echo input 451 if (err.Success()) 452 { 453 m_interpreter.GetDebugger().PushInputReader (reader_sp); 454 result.SetStatus (eReturnStatusSuccessFinishNoResult); 455 } 456 else 457 { 458 result.AppendError (err.AsCString()); 459 result.SetStatus (eReturnStatusFailed); 460 } 461 } 462 else 463 { 464 result.AppendError("out of memory"); 465 result.SetStatus (eReturnStatusFailed); 466 } 467 return result.Succeeded(); 468 } 469 470 if (command[0] == '-') 471 { 472 // We have some options and these options MUST end with --. 473 const char *end_options = NULL; 474 const char *s = command; 475 while (s && s[0]) 476 { 477 end_options = ::strstr (s, "--"); 478 if (end_options) 479 { 480 end_options += 2; // Get past the "--" 481 if (::isspace (end_options[0])) 482 { 483 expr = end_options; 484 while (::isspace (*expr)) 485 ++expr; 486 break; 487 } 488 } 489 s = end_options; 490 } 491 492 if (end_options) 493 { 494 Args args (command, end_options - command); 495 if (!ParseOptions (args, result)) 496 return false; 497 498 Error error (m_option_group.NotifyOptionParsingFinished()); 499 if (error.Fail()) 500 { 501 result.AppendError (error.AsCString()); 502 result.SetStatus (eReturnStatusFailed); 503 return false; 504 } 505 } 506 } 507 508 if (expr == NULL) 509 expr = command; 510 511 if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result)) 512 return true; 513 514 result.SetStatus (eReturnStatusFailed); 515 return false; 516 } 517 518