1 //===-- Debugger.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/API/SBDebugger.h" 11 12 #include "lldb/Core/Debugger.h" 13 14 #include <map> 15 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/Type.h" 18 19 #include "lldb/lldb-private.h" 20 #include "lldb/Core/ConnectionFileDescriptor.h" 21 #include "lldb/Core/DataVisualization.h" 22 #include "lldb/Core/FormatManager.h" 23 #include "lldb/Core/InputReader.h" 24 #include "lldb/Core/Module.h" 25 #include "lldb/Core/PluginManager.h" 26 #include "lldb/Core/RegisterValue.h" 27 #include "lldb/Core/State.h" 28 #include "lldb/Core/StreamAsynchronousIO.h" 29 #include "lldb/Core/StreamCallback.h" 30 #include "lldb/Core/StreamString.h" 31 #include "lldb/Core/Timer.h" 32 #include "lldb/Core/ValueObject.h" 33 #include "lldb/Core/ValueObjectVariable.h" 34 #include "lldb/Host/DynamicLibrary.h" 35 #include "lldb/Host/Terminal.h" 36 #include "lldb/Interpreter/CommandInterpreter.h" 37 #include "lldb/Interpreter/OptionValueSInt64.h" 38 #include "lldb/Interpreter/OptionValueString.h" 39 #include "lldb/Symbol/ClangASTContext.h" 40 #include "lldb/Symbol/CompileUnit.h" 41 #include "lldb/Symbol/Function.h" 42 #include "lldb/Symbol/Symbol.h" 43 #include "lldb/Symbol/VariableList.h" 44 #include "lldb/Target/TargetList.h" 45 #include "lldb/Target/Process.h" 46 #include "lldb/Target/RegisterContext.h" 47 #include "lldb/Target/StopInfo.h" 48 #include "lldb/Target/Thread.h" 49 #include "lldb/Utility/AnsiTerminal.h" 50 51 using namespace lldb; 52 using namespace lldb_private; 53 54 55 static uint32_t g_shared_debugger_refcount = 0; 56 static lldb::user_id_t g_unique_id = 1; 57 58 #pragma mark Static Functions 59 60 static Mutex & 61 GetDebuggerListMutex () 62 { 63 static Mutex g_mutex(Mutex::eMutexTypeRecursive); 64 return g_mutex; 65 } 66 67 typedef std::vector<DebuggerSP> DebuggerList; 68 69 static DebuggerList & 70 GetDebuggerList() 71 { 72 // hide the static debugger list inside a singleton accessor to avoid 73 // global init contructors 74 static DebuggerList g_list; 75 return g_list; 76 } 77 78 OptionEnumValueElement 79 g_show_disassembly_enum_values[] = 80 { 81 { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, 82 { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."}, 83 { Debugger::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."}, 84 { 0, NULL, NULL } 85 }; 86 87 OptionEnumValueElement 88 g_language_enumerators[] = 89 { 90 { eScriptLanguageNone, "none", "Disable scripting languages."}, 91 { eScriptLanguagePython, "python", "Select python as the default scripting language."}, 92 { eScriptLanguageDefault, "default", "Select the lldb default as the default scripting language."}, 93 { 0, NULL, NULL } 94 }; 95 96 #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" 97 #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" 98 99 #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\ 100 "{, ${frame.pc}}"\ 101 MODULE_WITH_FUNC\ 102 FILE_AND_LINE\ 103 "{, stop reason = ${thread.stop-reason}}"\ 104 "{\\nReturn value: ${thread.return-value}}"\ 105 "\\n" 106 107 #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ 108 MODULE_WITH_FUNC\ 109 FILE_AND_LINE\ 110 "\\n" 111 112 113 114 static PropertyDefinition 115 g_properties[] = 116 { 117 { "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, 118 { "frame-format", OptionValue::eTypeString , true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." }, 119 { "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, 120 { "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, 121 { "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, 122 { "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, 123 { "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." }, 124 { "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come after the current source line when displaying a stopped context." }, 125 { "stop-line-count-before", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come before the current source line when displaying a stopped context." }, 126 { "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, 127 { "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, 128 { "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." }, 129 130 { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } 131 }; 132 133 enum 134 { 135 ePropertyAutoConfirm = 0, 136 ePropertyFrameFormat, 137 ePropertyNotiftVoid, 138 ePropertyPrompt, 139 ePropertyScriptLanguage, 140 ePropertyStopDisassemblyCount, 141 ePropertyStopDisassemblyDisplay, 142 ePropertyStopLineCountAfter, 143 ePropertyStopLineCountBefore, 144 ePropertyTerminalWidth, 145 ePropertyThreadFormat, 146 ePropertyUseExternalEditor 147 }; 148 149 // 150 //const char * 151 //Debugger::GetFrameFormat() const 152 //{ 153 // return m_properties_sp->GetFrameFormat(); 154 //} 155 //const char * 156 //Debugger::GetThreadFormat() const 157 //{ 158 // return m_properties_sp->GetThreadFormat(); 159 //} 160 // 161 162 163 Error 164 Debugger::SetPropertyValue (const ExecutionContext *exe_ctx, 165 VarSetOperationType op, 166 const char *property_path, 167 const char *value) 168 { 169 Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value)); 170 if (error.Success()) 171 { 172 if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0) 173 { 174 const char *new_prompt = GetPrompt(); 175 EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt))); 176 GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp); 177 } 178 } 179 return error; 180 } 181 182 bool 183 Debugger::GetAutoConfirm () const 184 { 185 const uint32_t idx = ePropertyAutoConfirm; 186 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 187 } 188 189 const char * 190 Debugger::GetFrameFormat() const 191 { 192 const uint32_t idx = ePropertyFrameFormat; 193 return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 194 } 195 196 bool 197 Debugger::GetNotifyVoid () const 198 { 199 const uint32_t idx = ePropertyNotiftVoid; 200 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 201 } 202 203 const char * 204 Debugger::GetPrompt() const 205 { 206 const uint32_t idx = ePropertyPrompt; 207 return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 208 } 209 210 void 211 Debugger::SetPrompt(const char *p) 212 { 213 const uint32_t idx = ePropertyPrompt; 214 m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p); 215 const char *new_prompt = GetPrompt(); 216 EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));; 217 GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp); 218 } 219 220 const char * 221 Debugger::GetThreadFormat() const 222 { 223 const uint32_t idx = ePropertyThreadFormat; 224 return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); 225 } 226 227 lldb::ScriptLanguage 228 Debugger::GetScriptLanguage() const 229 { 230 const uint32_t idx = ePropertyScriptLanguage; 231 return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 232 } 233 234 bool 235 Debugger::SetScriptLanguage (lldb::ScriptLanguage script_lang) 236 { 237 const uint32_t idx = ePropertyScriptLanguage; 238 return m_collection_sp->SetPropertyAtIndexAsEnumeration (NULL, idx, script_lang); 239 } 240 241 uint32_t 242 Debugger::GetTerminalWidth () const 243 { 244 const uint32_t idx = ePropertyTerminalWidth; 245 return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 246 } 247 248 bool 249 Debugger::SetTerminalWidth (uint32_t term_width) 250 { 251 const uint32_t idx = ePropertyTerminalWidth; 252 return m_collection_sp->SetPropertyAtIndexAsSInt64 (NULL, idx, term_width); 253 } 254 255 bool 256 Debugger::GetUseExternalEditor () const 257 { 258 const uint32_t idx = ePropertyUseExternalEditor; 259 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 260 } 261 262 bool 263 Debugger::SetUseExternalEditor (bool b) 264 { 265 const uint32_t idx = ePropertyUseExternalEditor; 266 return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); 267 } 268 269 uint32_t 270 Debugger::GetStopSourceLineCount (bool before) const 271 { 272 const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; 273 return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 274 } 275 276 Debugger::StopDisassemblyType 277 Debugger::GetStopDisassemblyDisplay () const 278 { 279 const uint32_t idx = ePropertyStopDisassemblyDisplay; 280 return (Debugger::StopDisassemblyType)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); 281 } 282 283 uint32_t 284 Debugger::GetDisassemblyLineCount () const 285 { 286 const uint32_t idx = ePropertyStopDisassemblyCount; 287 return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value); 288 } 289 290 #pragma mark Debugger 291 292 //const DebuggerPropertiesSP & 293 //Debugger::GetSettings() const 294 //{ 295 // return m_properties_sp; 296 //} 297 // 298 299 int 300 Debugger::TestDebuggerRefCount () 301 { 302 return g_shared_debugger_refcount; 303 } 304 305 void 306 Debugger::Initialize () 307 { 308 if (g_shared_debugger_refcount++ == 0) 309 lldb_private::Initialize(); 310 } 311 312 void 313 Debugger::Terminate () 314 { 315 if (g_shared_debugger_refcount > 0) 316 { 317 g_shared_debugger_refcount--; 318 if (g_shared_debugger_refcount == 0) 319 { 320 lldb_private::WillTerminate(); 321 lldb_private::Terminate(); 322 323 // Clear our master list of debugger objects 324 Mutex::Locker locker (GetDebuggerListMutex ()); 325 GetDebuggerList().clear(); 326 } 327 } 328 } 329 330 void 331 Debugger::SettingsInitialize () 332 { 333 Target::SettingsInitialize (); 334 } 335 336 void 337 Debugger::SettingsTerminate () 338 { 339 Target::SettingsTerminate (); 340 } 341 342 bool 343 Debugger::LoadPlugin (const FileSpec& spec) 344 { 345 lldb::DynamicLibrarySP dynlib_sp(new lldb_private::DynamicLibrary(spec)); 346 lldb::DebuggerSP debugger_sp(shared_from_this()); 347 lldb::SBDebugger debugger_sb(debugger_sp); 348 // TODO: mangle this differently for your system - on OSX, the first underscore needs to be removed and the second one stays 349 LLDBCommandPluginInit init_func = dynlib_sp->GetSymbol<LLDBCommandPluginInit>("_ZN4lldb16PluginInitializeENS_10SBDebuggerE"); 350 if (!init_func) 351 return false; 352 if (init_func(debugger_sb)) 353 { 354 m_loaded_plugins.push_back(dynlib_sp); 355 return true; 356 } 357 return false; 358 } 359 360 static FileSpec::EnumerateDirectoryResult 361 LoadPluginCallback 362 ( 363 void *baton, 364 FileSpec::FileType file_type, 365 const FileSpec &file_spec 366 ) 367 { 368 Error error; 369 370 static ConstString g_dylibext("dylib"); 371 372 if (!baton) 373 return FileSpec::eEnumerateDirectoryResultQuit; 374 375 Debugger *debugger = (Debugger*)baton; 376 377 // If we have a regular file, a symbolic link or unknown file type, try 378 // and process the file. We must handle unknown as sometimes the directory 379 // enumeration might be enumerating a file system that doesn't have correct 380 // file type information. 381 if (file_type == FileSpec::eFileTypeRegular || 382 file_type == FileSpec::eFileTypeSymbolicLink || 383 file_type == FileSpec::eFileTypeUnknown ) 384 { 385 FileSpec plugin_file_spec (file_spec); 386 plugin_file_spec.ResolvePath (); 387 388 if (plugin_file_spec.GetFileNameExtension() != g_dylibext) 389 return FileSpec::eEnumerateDirectoryResultNext; 390 391 debugger->LoadPlugin (plugin_file_spec); 392 393 return FileSpec::eEnumerateDirectoryResultNext; 394 } 395 396 else if (file_type == FileSpec::eFileTypeUnknown || 397 file_type == FileSpec::eFileTypeDirectory || 398 file_type == FileSpec::eFileTypeSymbolicLink ) 399 { 400 // Try and recurse into anything that a directory or symbolic link. 401 // We must also do this for unknown as sometimes the directory enumeration 402 // might be enurating a file system that doesn't have correct file type 403 // information. 404 return FileSpec::eEnumerateDirectoryResultEnter; 405 } 406 407 return FileSpec::eEnumerateDirectoryResultNext; 408 } 409 410 void 411 Debugger::InstanceInitialize () 412 { 413 FileSpec dir_spec; 414 const bool find_directories = true; 415 const bool find_files = true; 416 const bool find_other = true; 417 char dir_path[PATH_MAX]; 418 if (Host::GetLLDBPath (ePathTypeLLDBSystemPlugins, dir_spec)) 419 { 420 if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 421 { 422 FileSpec::EnumerateDirectory (dir_path, 423 find_directories, 424 find_files, 425 find_other, 426 LoadPluginCallback, 427 this); 428 } 429 } 430 431 if (Host::GetLLDBPath (ePathTypeLLDBUserPlugins, dir_spec)) 432 { 433 if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) 434 { 435 FileSpec::EnumerateDirectory (dir_path, 436 find_directories, 437 find_files, 438 find_other, 439 LoadPluginCallback, 440 this); 441 } 442 } 443 444 PluginManager::DebuggerInitialize (*this); 445 } 446 447 DebuggerSP 448 Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton) 449 { 450 DebuggerSP debugger_sp (new Debugger(log_callback, baton)); 451 if (g_shared_debugger_refcount > 0) 452 { 453 Mutex::Locker locker (GetDebuggerListMutex ()); 454 GetDebuggerList().push_back(debugger_sp); 455 } 456 debugger_sp->InstanceInitialize (); 457 return debugger_sp; 458 } 459 460 void 461 Debugger::Destroy (DebuggerSP &debugger_sp) 462 { 463 if (debugger_sp.get() == NULL) 464 return; 465 466 debugger_sp->Clear(); 467 468 if (g_shared_debugger_refcount > 0) 469 { 470 Mutex::Locker locker (GetDebuggerListMutex ()); 471 DebuggerList &debugger_list = GetDebuggerList (); 472 DebuggerList::iterator pos, end = debugger_list.end(); 473 for (pos = debugger_list.begin (); pos != end; ++pos) 474 { 475 if ((*pos).get() == debugger_sp.get()) 476 { 477 debugger_list.erase (pos); 478 return; 479 } 480 } 481 } 482 } 483 484 DebuggerSP 485 Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name) 486 { 487 DebuggerSP debugger_sp; 488 if (g_shared_debugger_refcount > 0) 489 { 490 Mutex::Locker locker (GetDebuggerListMutex ()); 491 DebuggerList &debugger_list = GetDebuggerList(); 492 DebuggerList::iterator pos, end = debugger_list.end(); 493 494 for (pos = debugger_list.begin(); pos != end; ++pos) 495 { 496 if ((*pos).get()->m_instance_name == instance_name) 497 { 498 debugger_sp = *pos; 499 break; 500 } 501 } 502 } 503 return debugger_sp; 504 } 505 506 TargetSP 507 Debugger::FindTargetWithProcessID (lldb::pid_t pid) 508 { 509 TargetSP target_sp; 510 if (g_shared_debugger_refcount > 0) 511 { 512 Mutex::Locker locker (GetDebuggerListMutex ()); 513 DebuggerList &debugger_list = GetDebuggerList(); 514 DebuggerList::iterator pos, end = debugger_list.end(); 515 for (pos = debugger_list.begin(); pos != end; ++pos) 516 { 517 target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid); 518 if (target_sp) 519 break; 520 } 521 } 522 return target_sp; 523 } 524 525 TargetSP 526 Debugger::FindTargetWithProcess (Process *process) 527 { 528 TargetSP target_sp; 529 if (g_shared_debugger_refcount > 0) 530 { 531 Mutex::Locker locker (GetDebuggerListMutex ()); 532 DebuggerList &debugger_list = GetDebuggerList(); 533 DebuggerList::iterator pos, end = debugger_list.end(); 534 for (pos = debugger_list.begin(); pos != end; ++pos) 535 { 536 target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process); 537 if (target_sp) 538 break; 539 } 540 } 541 return target_sp; 542 } 543 544 Debugger::Debugger (lldb::LogOutputCallback log_callback, void *baton) : 545 UserID (g_unique_id++), 546 Properties(OptionValuePropertiesSP(new OptionValueProperties())), 547 m_input_comm("debugger.input"), 548 m_input_file (), 549 m_output_file (), 550 m_error_file (), 551 m_terminal_state (), 552 m_target_list (*this), 553 m_platform_list (), 554 m_listener ("lldb.Debugger"), 555 m_source_manager(*this), 556 m_source_file_cache(), 557 m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)), 558 m_input_reader_stack (), 559 m_input_reader_data (), 560 m_instance_name() 561 { 562 char instance_cstr[256]; 563 snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); 564 m_instance_name.SetCString(instance_cstr); 565 if (log_callback) 566 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 567 m_command_interpreter_ap->Initialize (); 568 // Always add our default platform to the platform list 569 PlatformSP default_platform_sp (Platform::GetDefaultPlatform()); 570 assert (default_platform_sp.get()); 571 m_platform_list.Append (default_platform_sp, true); 572 573 m_collection_sp->Initialize (g_properties); 574 m_collection_sp->AppendProperty (ConstString("target"), 575 ConstString("Settings specify to debugging targets."), 576 true, 577 Target::GetGlobalProperties()->GetValueProperties()); 578 if (m_command_interpreter_ap.get()) 579 { 580 m_collection_sp->AppendProperty (ConstString("interpreter"), 581 ConstString("Settings specify to the debugger's command interpreter."), 582 true, 583 m_command_interpreter_ap->GetValueProperties()); 584 } 585 OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64 (NULL, ePropertyTerminalWidth); 586 term_width->SetMinimumValue(10); 587 term_width->SetMaximumValue(1024); 588 } 589 590 Debugger::~Debugger () 591 { 592 Clear(); 593 } 594 595 void 596 Debugger::Clear() 597 { 598 CleanUpInputReaders(); 599 m_listener.Clear(); 600 int num_targets = m_target_list.GetNumTargets(); 601 for (int i = 0; i < num_targets; i++) 602 { 603 TargetSP target_sp (m_target_list.GetTargetAtIndex (i)); 604 if (target_sp) 605 { 606 ProcessSP process_sp (target_sp->GetProcessSP()); 607 if (process_sp) 608 { 609 if (process_sp->GetShouldDetach()) 610 process_sp->Detach(); 611 } 612 target_sp->Destroy(); 613 } 614 } 615 BroadcasterManager::Clear (); 616 617 // Close the input file _before_ we close the input read communications class 618 // as it does NOT own the input file, our m_input_file does. 619 m_terminal_state.Clear(); 620 GetInputFile().Close (); 621 // Now that we have closed m_input_file, we can now tell our input communication 622 // class to close down. Its read thread should quickly exit after we close 623 // the input file handle above. 624 m_input_comm.Clear (); 625 } 626 627 bool 628 Debugger::GetCloseInputOnEOF () const 629 { 630 return m_input_comm.GetCloseOnEOF(); 631 } 632 633 void 634 Debugger::SetCloseInputOnEOF (bool b) 635 { 636 m_input_comm.SetCloseOnEOF(b); 637 } 638 639 bool 640 Debugger::GetAsyncExecution () 641 { 642 return !m_command_interpreter_ap->GetSynchronous(); 643 } 644 645 void 646 Debugger::SetAsyncExecution (bool async_execution) 647 { 648 m_command_interpreter_ap->SetSynchronous (!async_execution); 649 } 650 651 652 void 653 Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) 654 { 655 File &in_file = GetInputFile(); 656 in_file.SetStream (fh, tranfer_ownership); 657 if (in_file.IsValid() == false) 658 in_file.SetStream (stdin, true); 659 660 // Disconnect from any old connection if we had one 661 m_input_comm.Disconnect (); 662 // Pass false as the second argument to ConnectionFileDescriptor below because 663 // our "in_file" above will already take ownership if requested and we don't 664 // want to objects trying to own and close a file descriptor. 665 m_input_comm.SetConnection (new ConnectionFileDescriptor (in_file.GetDescriptor(), false)); 666 m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this); 667 668 // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState. 669 SaveInputTerminalState (); 670 671 Error error; 672 if (m_input_comm.StartReadThread (&error) == false) 673 { 674 File &err_file = GetErrorFile(); 675 676 err_file.Printf ("error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error"); 677 exit(1); 678 } 679 } 680 681 void 682 Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership) 683 { 684 File &out_file = GetOutputFile(); 685 out_file.SetStream (fh, tranfer_ownership); 686 if (out_file.IsValid() == false) 687 out_file.SetStream (stdout, false); 688 689 // do not create the ScriptInterpreter just for setting the output file handle 690 // as the constructor will know how to do the right thing on its own 691 const bool can_create = false; 692 ScriptInterpreter* script_interpreter = GetCommandInterpreter().GetScriptInterpreter(can_create); 693 if (script_interpreter) 694 script_interpreter->ResetOutputFileHandle (fh); 695 } 696 697 void 698 Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) 699 { 700 File &err_file = GetErrorFile(); 701 err_file.SetStream (fh, tranfer_ownership); 702 if (err_file.IsValid() == false) 703 err_file.SetStream (stderr, false); 704 } 705 706 void 707 Debugger::SaveInputTerminalState () 708 { 709 File &in_file = GetInputFile(); 710 if (in_file.GetDescriptor() != File::kInvalidDescriptor) 711 m_terminal_state.Save(in_file.GetDescriptor(), true); 712 } 713 714 void 715 Debugger::RestoreInputTerminalState () 716 { 717 m_terminal_state.Restore(); 718 } 719 720 ExecutionContext 721 Debugger::GetSelectedExecutionContext () 722 { 723 ExecutionContext exe_ctx; 724 TargetSP target_sp(GetSelectedTarget()); 725 exe_ctx.SetTargetSP (target_sp); 726 727 if (target_sp) 728 { 729 ProcessSP process_sp (target_sp->GetProcessSP()); 730 exe_ctx.SetProcessSP (process_sp); 731 if (process_sp && process_sp->IsRunning() == false) 732 { 733 ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); 734 if (thread_sp) 735 { 736 exe_ctx.SetThreadSP (thread_sp); 737 exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame()); 738 if (exe_ctx.GetFramePtr() == NULL) 739 exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0)); 740 } 741 } 742 } 743 return exe_ctx; 744 745 } 746 747 InputReaderSP 748 Debugger::GetCurrentInputReader () 749 { 750 InputReaderSP reader_sp; 751 752 if (!m_input_reader_stack.IsEmpty()) 753 { 754 // Clear any finished readers from the stack 755 while (CheckIfTopInputReaderIsDone()) ; 756 757 if (!m_input_reader_stack.IsEmpty()) 758 reader_sp = m_input_reader_stack.Top(); 759 } 760 761 return reader_sp; 762 } 763 764 void 765 Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len) 766 { 767 if (bytes_len > 0) 768 ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len); 769 else 770 ((Debugger *)baton)->DispatchInputEndOfFile (); 771 } 772 773 774 void 775 Debugger::DispatchInput (const char *bytes, size_t bytes_len) 776 { 777 if (bytes == NULL || bytes_len == 0) 778 return; 779 780 WriteToDefaultReader (bytes, bytes_len); 781 } 782 783 void 784 Debugger::DispatchInputInterrupt () 785 { 786 m_input_reader_data.clear(); 787 788 InputReaderSP reader_sp (GetCurrentInputReader ()); 789 if (reader_sp) 790 { 791 reader_sp->Notify (eInputReaderInterrupt); 792 793 // If notifying the reader of the interrupt finished the reader, we should pop it off the stack. 794 while (CheckIfTopInputReaderIsDone ()) ; 795 } 796 } 797 798 void 799 Debugger::DispatchInputEndOfFile () 800 { 801 m_input_reader_data.clear(); 802 803 InputReaderSP reader_sp (GetCurrentInputReader ()); 804 if (reader_sp) 805 { 806 reader_sp->Notify (eInputReaderEndOfFile); 807 808 // If notifying the reader of the end-of-file finished the reader, we should pop it off the stack. 809 while (CheckIfTopInputReaderIsDone ()) ; 810 } 811 } 812 813 void 814 Debugger::CleanUpInputReaders () 815 { 816 m_input_reader_data.clear(); 817 818 // The bottom input reader should be the main debugger input reader. We do not want to close that one here. 819 while (m_input_reader_stack.GetSize() > 1) 820 { 821 InputReaderSP reader_sp (GetCurrentInputReader ()); 822 if (reader_sp) 823 { 824 reader_sp->Notify (eInputReaderEndOfFile); 825 reader_sp->SetIsDone (true); 826 } 827 } 828 } 829 830 void 831 Debugger::NotifyTopInputReader (InputReaderAction notification) 832 { 833 InputReaderSP reader_sp (GetCurrentInputReader()); 834 if (reader_sp) 835 { 836 reader_sp->Notify (notification); 837 838 // Flush out any input readers that are done. 839 while (CheckIfTopInputReaderIsDone ()) 840 /* Do nothing. */; 841 } 842 } 843 844 bool 845 Debugger::InputReaderIsTopReader (const InputReaderSP& reader_sp) 846 { 847 InputReaderSP top_reader_sp (GetCurrentInputReader()); 848 849 return (reader_sp.get() == top_reader_sp.get()); 850 } 851 852 853 void 854 Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len) 855 { 856 if (bytes && bytes_len) 857 m_input_reader_data.append (bytes, bytes_len); 858 859 if (m_input_reader_data.empty()) 860 return; 861 862 while (!m_input_reader_stack.IsEmpty() && !m_input_reader_data.empty()) 863 { 864 // Get the input reader from the top of the stack 865 InputReaderSP reader_sp (GetCurrentInputReader ()); 866 if (!reader_sp) 867 break; 868 869 size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(), 870 m_input_reader_data.size()); 871 if (bytes_handled) 872 { 873 m_input_reader_data.erase (0, bytes_handled); 874 } 875 else 876 { 877 // No bytes were handled, we might not have reached our 878 // granularity, just return and wait for more data 879 break; 880 } 881 } 882 883 // Flush out any input readers that are done. 884 while (CheckIfTopInputReaderIsDone ()) 885 /* Do nothing. */; 886 887 } 888 889 void 890 Debugger::PushInputReader (const InputReaderSP& reader_sp) 891 { 892 if (!reader_sp) 893 return; 894 895 // Deactivate the old top reader 896 InputReaderSP top_reader_sp (GetCurrentInputReader ()); 897 898 if (top_reader_sp) 899 top_reader_sp->Notify (eInputReaderDeactivate); 900 901 m_input_reader_stack.Push (reader_sp); 902 reader_sp->Notify (eInputReaderActivate); 903 ActivateInputReader (reader_sp); 904 } 905 906 bool 907 Debugger::PopInputReader (const InputReaderSP& pop_reader_sp) 908 { 909 bool result = false; 910 911 // The reader on the stop of the stack is done, so let the next 912 // read on the stack referesh its prompt and if there is one... 913 if (!m_input_reader_stack.IsEmpty()) 914 { 915 // Cannot call GetCurrentInputReader here, as that would cause an infinite loop. 916 InputReaderSP reader_sp(m_input_reader_stack.Top()); 917 918 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get()) 919 { 920 m_input_reader_stack.Pop (); 921 reader_sp->Notify (eInputReaderDeactivate); 922 reader_sp->Notify (eInputReaderDone); 923 result = true; 924 925 if (!m_input_reader_stack.IsEmpty()) 926 { 927 reader_sp = m_input_reader_stack.Top(); 928 if (reader_sp) 929 { 930 ActivateInputReader (reader_sp); 931 reader_sp->Notify (eInputReaderReactivate); 932 } 933 } 934 } 935 } 936 return result; 937 } 938 939 bool 940 Debugger::CheckIfTopInputReaderIsDone () 941 { 942 bool result = false; 943 if (!m_input_reader_stack.IsEmpty()) 944 { 945 // Cannot call GetCurrentInputReader here, as that would cause an infinite loop. 946 InputReaderSP reader_sp(m_input_reader_stack.Top()); 947 948 if (reader_sp && reader_sp->IsDone()) 949 { 950 result = true; 951 PopInputReader (reader_sp); 952 } 953 } 954 return result; 955 } 956 957 void 958 Debugger::ActivateInputReader (const InputReaderSP &reader_sp) 959 { 960 int input_fd = m_input_file.GetFile().GetDescriptor(); 961 962 if (input_fd >= 0) 963 { 964 Terminal tty(input_fd); 965 966 tty.SetEcho(reader_sp->GetEcho()); 967 968 switch (reader_sp->GetGranularity()) 969 { 970 case eInputReaderGranularityByte: 971 case eInputReaderGranularityWord: 972 tty.SetCanonical (false); 973 break; 974 975 case eInputReaderGranularityLine: 976 case eInputReaderGranularityAll: 977 tty.SetCanonical (true); 978 break; 979 980 default: 981 break; 982 } 983 } 984 } 985 986 StreamSP 987 Debugger::GetAsyncOutputStream () 988 { 989 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 990 CommandInterpreter::eBroadcastBitAsynchronousOutputData)); 991 } 992 993 StreamSP 994 Debugger::GetAsyncErrorStream () 995 { 996 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 997 CommandInterpreter::eBroadcastBitAsynchronousErrorData)); 998 } 999 1000 uint32_t 1001 Debugger::GetNumDebuggers() 1002 { 1003 if (g_shared_debugger_refcount > 0) 1004 { 1005 Mutex::Locker locker (GetDebuggerListMutex ()); 1006 return GetDebuggerList().size(); 1007 } 1008 return 0; 1009 } 1010 1011 lldb::DebuggerSP 1012 Debugger::GetDebuggerAtIndex (uint32_t index) 1013 { 1014 DebuggerSP debugger_sp; 1015 1016 if (g_shared_debugger_refcount > 0) 1017 { 1018 Mutex::Locker locker (GetDebuggerListMutex ()); 1019 DebuggerList &debugger_list = GetDebuggerList(); 1020 1021 if (index < debugger_list.size()) 1022 debugger_sp = debugger_list[index]; 1023 } 1024 1025 return debugger_sp; 1026 } 1027 1028 DebuggerSP 1029 Debugger::FindDebuggerWithID (lldb::user_id_t id) 1030 { 1031 DebuggerSP debugger_sp; 1032 1033 if (g_shared_debugger_refcount > 0) 1034 { 1035 Mutex::Locker locker (GetDebuggerListMutex ()); 1036 DebuggerList &debugger_list = GetDebuggerList(); 1037 DebuggerList::iterator pos, end = debugger_list.end(); 1038 for (pos = debugger_list.begin(); pos != end; ++pos) 1039 { 1040 if ((*pos).get()->GetID() == id) 1041 { 1042 debugger_sp = *pos; 1043 break; 1044 } 1045 } 1046 } 1047 return debugger_sp; 1048 } 1049 1050 static void 1051 TestPromptFormats (StackFrame *frame) 1052 { 1053 if (frame == NULL) 1054 return; 1055 1056 StreamString s; 1057 const char *prompt_format = 1058 "{addr = '${addr}'\n}" 1059 "{process.id = '${process.id}'\n}" 1060 "{process.name = '${process.name}'\n}" 1061 "{process.file.basename = '${process.file.basename}'\n}" 1062 "{process.file.fullpath = '${process.file.fullpath}'\n}" 1063 "{thread.id = '${thread.id}'\n}" 1064 "{thread.index = '${thread.index}'\n}" 1065 "{thread.name = '${thread.name}'\n}" 1066 "{thread.queue = '${thread.queue}'\n}" 1067 "{thread.stop-reason = '${thread.stop-reason}'\n}" 1068 "{target.arch = '${target.arch}'\n}" 1069 "{module.file.basename = '${module.file.basename}'\n}" 1070 "{module.file.fullpath = '${module.file.fullpath}'\n}" 1071 "{file.basename = '${file.basename}'\n}" 1072 "{file.fullpath = '${file.fullpath}'\n}" 1073 "{frame.index = '${frame.index}'\n}" 1074 "{frame.pc = '${frame.pc}'\n}" 1075 "{frame.sp = '${frame.sp}'\n}" 1076 "{frame.fp = '${frame.fp}'\n}" 1077 "{frame.flags = '${frame.flags}'\n}" 1078 "{frame.reg.rdi = '${frame.reg.rdi}'\n}" 1079 "{frame.reg.rip = '${frame.reg.rip}'\n}" 1080 "{frame.reg.rsp = '${frame.reg.rsp}'\n}" 1081 "{frame.reg.rbp = '${frame.reg.rbp}'\n}" 1082 "{frame.reg.rflags = '${frame.reg.rflags}'\n}" 1083 "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" 1084 "{frame.reg.carp = '${frame.reg.carp}'\n}" 1085 "{function.id = '${function.id}'\n}" 1086 "{function.name = '${function.name}'\n}" 1087 "{function.name-with-args = '${function.name-with-args}'\n}" 1088 "{function.addr-offset = '${function.addr-offset}'\n}" 1089 "{function.line-offset = '${function.line-offset}'\n}" 1090 "{function.pc-offset = '${function.pc-offset}'\n}" 1091 "{line.file.basename = '${line.file.basename}'\n}" 1092 "{line.file.fullpath = '${line.file.fullpath}'\n}" 1093 "{line.number = '${line.number}'\n}" 1094 "{line.start-addr = '${line.start-addr}'\n}" 1095 "{line.end-addr = '${line.end-addr}'\n}" 1096 ; 1097 1098 SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything)); 1099 ExecutionContext exe_ctx; 1100 frame->CalculateExecutionContext(exe_ctx); 1101 const char *end = NULL; 1102 if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, &end)) 1103 { 1104 printf("%s\n", s.GetData()); 1105 } 1106 else 1107 { 1108 printf ("error: at '%s'\n", end); 1109 printf ("what we got: %s\n", s.GetData()); 1110 } 1111 } 1112 1113 static bool 1114 ScanFormatDescriptor (const char* var_name_begin, 1115 const char* var_name_end, 1116 const char** var_name_final, 1117 const char** percent_position, 1118 Format* custom_format, 1119 ValueObject::ValueObjectRepresentationStyle* val_obj_display) 1120 { 1121 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1122 *percent_position = ::strchr(var_name_begin,'%'); 1123 if (!*percent_position || *percent_position > var_name_end) 1124 { 1125 if (log) 1126 log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping"); 1127 *var_name_final = var_name_end; 1128 } 1129 else 1130 { 1131 *var_name_final = *percent_position; 1132 char* format_name = new char[var_name_end-*var_name_final]; format_name[var_name_end-*var_name_final-1] = '\0'; 1133 memcpy(format_name, *var_name_final+1, var_name_end-*var_name_final-1); 1134 if (log) 1135 log->Printf("ScanFormatDescriptor] parsing %s as a format descriptor", format_name); 1136 if ( !FormatManager::GetFormatFromCString(format_name, 1137 true, 1138 *custom_format) ) 1139 { 1140 if (log) 1141 log->Printf("ScanFormatDescriptor] %s is an unknown format", format_name); 1142 // if this is an @ sign, print ObjC description 1143 if (*format_name == '@') 1144 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; 1145 // if this is a V, print the value using the default format 1146 else if (*format_name == 'V') 1147 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1148 // if this is an L, print the location of the value 1149 else if (*format_name == 'L') 1150 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; 1151 // if this is an S, print the summary after all 1152 else if (*format_name == 'S') 1153 *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 1154 else if (*format_name == '#') 1155 *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; 1156 else if (*format_name == 'T') 1157 *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; 1158 else if (log) 1159 log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name); 1160 } 1161 // a good custom format tells us to print the value using it 1162 else 1163 { 1164 if (log) 1165 log->Printf("ScanFormatDescriptor] will display value for this VO"); 1166 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1167 } 1168 delete format_name; 1169 } 1170 if (log) 1171 log->Printf("ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d", 1172 *custom_format, 1173 *val_obj_display); 1174 return true; 1175 } 1176 1177 static bool 1178 ScanBracketedRange (const char* var_name_begin, 1179 const char* var_name_end, 1180 const char* var_name_final, 1181 const char** open_bracket_position, 1182 const char** separator_position, 1183 const char** close_bracket_position, 1184 const char** var_name_final_if_array_range, 1185 int64_t* index_lower, 1186 int64_t* index_higher) 1187 { 1188 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1189 *open_bracket_position = ::strchr(var_name_begin,'['); 1190 if (*open_bracket_position && *open_bracket_position < var_name_final) 1191 { 1192 *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield 1193 *close_bracket_position = ::strchr(*open_bracket_position,']'); 1194 // as usual, we assume that [] will come before % 1195 //printf("trying to expand a []\n"); 1196 *var_name_final_if_array_range = *open_bracket_position; 1197 if (*close_bracket_position - *open_bracket_position == 1) 1198 { 1199 if (log) 1200 log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 1201 *index_lower = 0; 1202 } 1203 else if (*separator_position == NULL || *separator_position > var_name_end) 1204 { 1205 char *end = NULL; 1206 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 1207 *index_higher = *index_lower; 1208 if (log) 1209 log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower); 1210 } 1211 else if (*close_bracket_position && *close_bracket_position < var_name_end) 1212 { 1213 char *end = NULL; 1214 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 1215 *index_higher = ::strtoul (*separator_position+1, &end, 0); 1216 if (log) 1217 log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher); 1218 } 1219 else 1220 { 1221 if (log) 1222 log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it"); 1223 return false; 1224 } 1225 if (*index_lower > *index_higher && *index_higher > 0) 1226 { 1227 if (log) 1228 log->Printf("[ScanBracketedRange] swapping indices"); 1229 int temp = *index_lower; 1230 *index_lower = *index_higher; 1231 *index_higher = temp; 1232 } 1233 } 1234 else if (log) 1235 log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 1236 return true; 1237 } 1238 1239 static ValueObjectSP 1240 ExpandIndexedExpression (ValueObject* valobj, 1241 uint32_t index, 1242 StackFrame* frame, 1243 bool deref_pointer) 1244 { 1245 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1246 const char* ptr_deref_format = "[%d]"; 1247 std::auto_ptr<char> ptr_deref_buffer(new char[10]); 1248 ::sprintf(ptr_deref_buffer.get(), ptr_deref_format, index); 1249 if (log) 1250 log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.get()); 1251 const char* first_unparsed; 1252 ValueObject::GetValueForExpressionPathOptions options; 1253 ValueObject::ExpressionPathEndResultType final_value_type; 1254 ValueObject::ExpressionPathScanEndReason reason_to_stop; 1255 ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1256 ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.get(), 1257 &first_unparsed, 1258 &reason_to_stop, 1259 &final_value_type, 1260 options, 1261 &what_next); 1262 if (!item) 1263 { 1264 if (log) 1265 log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," 1266 " final_value_type %d", 1267 first_unparsed, reason_to_stop, final_value_type); 1268 } 1269 else 1270 { 1271 if (log) 1272 log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1273 " final_value_type %d", 1274 first_unparsed, reason_to_stop, final_value_type); 1275 } 1276 return item; 1277 } 1278 1279 bool 1280 Debugger::FormatPrompt 1281 ( 1282 const char *format, 1283 const SymbolContext *sc, 1284 const ExecutionContext *exe_ctx, 1285 const Address *addr, 1286 Stream &s, 1287 const char **end, 1288 ValueObject* valobj 1289 ) 1290 { 1291 ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers 1292 bool success = true; 1293 const char *p; 1294 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1295 for (p = format; *p != '\0'; ++p) 1296 { 1297 if (realvalobj) 1298 { 1299 valobj = realvalobj; 1300 realvalobj = NULL; 1301 } 1302 size_t non_special_chars = ::strcspn (p, "${}\\"); 1303 if (non_special_chars > 0) 1304 { 1305 if (success) 1306 s.Write (p, non_special_chars); 1307 p += non_special_chars; 1308 } 1309 1310 if (*p == '\0') 1311 { 1312 break; 1313 } 1314 else if (*p == '{') 1315 { 1316 // Start a new scope that must have everything it needs if it is to 1317 // to make it into the final output stream "s". If you want to make 1318 // a format that only prints out the function or symbol name if there 1319 // is one in the symbol context you can use: 1320 // "{function =${function.name}}" 1321 // The first '{' starts a new scope that end with the matching '}' at 1322 // the end of the string. The contents "function =${function.name}" 1323 // will then be evaluated and only be output if there is a function 1324 // or symbol with a valid name. 1325 StreamString sub_strm; 1326 1327 ++p; // Skip the '{' 1328 1329 if (FormatPrompt (p, sc, exe_ctx, addr, sub_strm, &p, valobj)) 1330 { 1331 // The stream had all it needed 1332 s.Write(sub_strm.GetData(), sub_strm.GetSize()); 1333 } 1334 if (*p != '}') 1335 { 1336 success = false; 1337 break; 1338 } 1339 } 1340 else if (*p == '}') 1341 { 1342 // End of a enclosing scope 1343 break; 1344 } 1345 else if (*p == '$') 1346 { 1347 // We have a prompt variable to print 1348 ++p; 1349 if (*p == '{') 1350 { 1351 ++p; 1352 const char *var_name_begin = p; 1353 const char *var_name_end = ::strchr (p, '}'); 1354 1355 if (var_name_end && var_name_begin < var_name_end) 1356 { 1357 // if we have already failed to parse, skip this variable 1358 if (success) 1359 { 1360 const char *cstr = NULL; 1361 Address format_addr; 1362 bool calculate_format_addr_function_offset = false; 1363 // Set reg_kind and reg_num to invalid values 1364 RegisterKind reg_kind = kNumRegisterKinds; 1365 uint32_t reg_num = LLDB_INVALID_REGNUM; 1366 FileSpec format_file_spec; 1367 const RegisterInfo *reg_info = NULL; 1368 RegisterContext *reg_ctx = NULL; 1369 bool do_deref_pointer = false; 1370 ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 1371 ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; 1372 1373 // Each variable must set success to true below... 1374 bool var_success = false; 1375 switch (var_name_begin[0]) 1376 { 1377 case '*': 1378 case 'v': 1379 case 's': 1380 { 1381 if (!valobj) 1382 break; 1383 1384 if (log) 1385 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1386 1387 // check for *var and *svar 1388 if (*var_name_begin == '*') 1389 { 1390 do_deref_pointer = true; 1391 var_name_begin++; 1392 } 1393 1394 if (log) 1395 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1396 1397 if (*var_name_begin == 's') 1398 { 1399 if (!valobj->IsSynthetic()) 1400 valobj = valobj->GetSyntheticValue().get(); 1401 if (!valobj) 1402 break; 1403 var_name_begin++; 1404 } 1405 1406 if (log) 1407 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1408 1409 // should be a 'v' by now 1410 if (*var_name_begin != 'v') 1411 break; 1412 1413 if (log) 1414 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1415 1416 ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? 1417 ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1418 ValueObject::GetValueForExpressionPathOptions options; 1419 options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); 1420 ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 1421 ValueObject* target = NULL; 1422 Format custom_format = eFormatInvalid; 1423 const char* var_name_final = NULL; 1424 const char* var_name_final_if_array_range = NULL; 1425 const char* close_bracket_position = NULL; 1426 int64_t index_lower = -1; 1427 int64_t index_higher = -1; 1428 bool is_array_range = false; 1429 const char* first_unparsed; 1430 bool was_plain_var = false; 1431 bool was_var_format = false; 1432 bool was_var_indexed = false; 1433 1434 if (!valobj) break; 1435 // simplest case ${var}, just print valobj's value 1436 if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0) 1437 { 1438 was_plain_var = true; 1439 target = valobj; 1440 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1441 } 1442 else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0) 1443 { 1444 was_var_format = true; 1445 // this is a variable with some custom format applied to it 1446 const char* percent_position; 1447 target = valobj; 1448 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1449 ScanFormatDescriptor (var_name_begin, 1450 var_name_end, 1451 &var_name_final, 1452 &percent_position, 1453 &custom_format, 1454 &val_obj_display); 1455 } 1456 // this is ${var.something} or multiple .something nested 1457 else if (::strncmp (var_name_begin, "var", strlen("var")) == 0) 1458 { 1459 if (::strncmp(var_name_begin, "var[", strlen("var[")) == 0) 1460 was_var_indexed = true; 1461 const char* percent_position; 1462 ScanFormatDescriptor (var_name_begin, 1463 var_name_end, 1464 &var_name_final, 1465 &percent_position, 1466 &custom_format, 1467 &val_obj_display); 1468 1469 const char* open_bracket_position; 1470 const char* separator_position; 1471 ScanBracketedRange (var_name_begin, 1472 var_name_end, 1473 var_name_final, 1474 &open_bracket_position, 1475 &separator_position, 1476 &close_bracket_position, 1477 &var_name_final_if_array_range, 1478 &index_lower, 1479 &index_higher); 1480 1481 Error error; 1482 1483 std::auto_ptr<char> expr_path(new char[var_name_final-var_name_begin-1]); 1484 ::memset(expr_path.get(), 0, var_name_final-var_name_begin-1); 1485 memcpy(expr_path.get(), var_name_begin+3,var_name_final-var_name_begin-3); 1486 1487 if (log) 1488 log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.get()); 1489 1490 target = valobj->GetValueForExpressionPath(expr_path.get(), 1491 &first_unparsed, 1492 &reason_to_stop, 1493 &final_value_type, 1494 options, 1495 &what_next).get(); 1496 1497 if (!target) 1498 { 1499 if (log) 1500 log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," 1501 " final_value_type %d", 1502 first_unparsed, reason_to_stop, final_value_type); 1503 break; 1504 } 1505 else 1506 { 1507 if (log) 1508 log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1509 " final_value_type %d", 1510 first_unparsed, reason_to_stop, final_value_type); 1511 } 1512 } 1513 else 1514 break; 1515 1516 is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || 1517 final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); 1518 1519 do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); 1520 1521 if (do_deref_pointer && !is_array_range) 1522 { 1523 // I have not deref-ed yet, let's do it 1524 // this happens when we are not going through GetValueForVariableExpressionPath 1525 // to get to the target ValueObject 1526 Error error; 1527 target = target->Dereference(error).get(); 1528 if (error.Fail()) 1529 { 1530 if (log) 1531 log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ 1532 break; 1533 } 1534 do_deref_pointer = false; 1535 } 1536 1537 // <rdar://problem/11338654> 1538 // we do not want to use the summary for a bitfield of type T:n 1539 // if we were originally dealing with just a T - that would get 1540 // us into an endless recursion 1541 if (target->IsBitfield() && was_var_indexed) 1542 { 1543 // TODO: check for a (T:n)-specific summary - we should still obey that 1544 StreamString bitfield_name; 1545 bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); 1546 lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); 1547 if (!DataVisualization::GetSummaryForType(type_sp)) 1548 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1549 } 1550 1551 // TODO use flags for these 1552 bool is_array = ClangASTContext::IsArrayType(target->GetClangType()); 1553 bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType()); 1554 bool is_aggregate = ClangASTContext::IsAggregateType(target->GetClangType()); 1555 1556 if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions 1557 { 1558 StreamString str_temp; 1559 if (log) 1560 log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); 1561 1562 if (target->HasSpecialPrintableRepresentation(val_obj_display, 1563 custom_format)) 1564 { 1565 // try to use the special cases 1566 var_success = target->DumpPrintableRepresentation(str_temp, 1567 val_obj_display, 1568 custom_format); 1569 if (log) 1570 log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't"); 1571 1572 // should not happen 1573 if (!var_success) 1574 s << "<invalid usage of pointer value as object>"; 1575 else 1576 s << str_temp.GetData(); 1577 var_success = true; 1578 break; 1579 } 1580 else 1581 { 1582 if (was_plain_var) // if ${var} 1583 { 1584 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1585 } 1586 else if (is_pointer) // if pointer, value is the address stored 1587 { 1588 target->DumpPrintableRepresentation (s, 1589 val_obj_display, 1590 custom_format, 1591 ValueObject::ePrintableRepresentationSpecialCasesDisable); 1592 } 1593 else 1594 { 1595 s << "<invalid usage of pointer value as object>"; 1596 } 1597 var_success = true; 1598 break; 1599 } 1600 } 1601 1602 // if directly trying to print ${var}, and this is an aggregate, display a nice 1603 // type @ location message 1604 if (is_aggregate && was_plain_var) 1605 { 1606 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1607 var_success = true; 1608 break; 1609 } 1610 1611 // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it 1612 if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) 1613 { 1614 s << "<invalid use of aggregate type>"; 1615 var_success = true; 1616 break; 1617 } 1618 1619 if (!is_array_range) 1620 { 1621 if (log) 1622 log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 1623 var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1624 } 1625 else 1626 { 1627 if (log) 1628 log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 1629 if (!is_array && !is_pointer) 1630 break; 1631 if (log) 1632 log->Printf("[Debugger::FormatPrompt] handle as array"); 1633 const char* special_directions = NULL; 1634 StreamString special_directions_writer; 1635 if (close_bracket_position && (var_name_end-close_bracket_position > 1)) 1636 { 1637 ConstString additional_data; 1638 additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); 1639 special_directions_writer.Printf("${%svar%s}", 1640 do_deref_pointer ? "*" : "", 1641 additional_data.GetCString()); 1642 special_directions = special_directions_writer.GetData(); 1643 } 1644 1645 // let us display items index_lower thru index_higher of this array 1646 s.PutChar('['); 1647 var_success = true; 1648 1649 if (index_higher < 0) 1650 index_higher = valobj->GetNumChildren() - 1; 1651 1652 uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 1653 1654 for (;index_lower<=index_higher;index_lower++) 1655 { 1656 ValueObject* item = ExpandIndexedExpression (target, 1657 index_lower, 1658 exe_ctx->GetFramePtr(), 1659 false).get(); 1660 1661 if (!item) 1662 { 1663 if (log) 1664 log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower); 1665 } 1666 else 1667 { 1668 if (log) 1669 log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions); 1670 } 1671 1672 if (!special_directions) 1673 var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1674 else 1675 var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item); 1676 1677 if (--max_num_children == 0) 1678 { 1679 s.PutCString(", ..."); 1680 break; 1681 } 1682 1683 if (index_lower < index_higher) 1684 s.PutChar(','); 1685 } 1686 s.PutChar(']'); 1687 } 1688 } 1689 break; 1690 case 'a': 1691 if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0) 1692 { 1693 if (addr && addr->IsValid()) 1694 { 1695 var_success = true; 1696 format_addr = *addr; 1697 } 1698 } 1699 else if (::strncmp (var_name_begin, "ansi.", strlen("ansi.")) == 0) 1700 { 1701 var_success = true; 1702 var_name_begin += strlen("ansi."); // Skip the "ansi." 1703 if (::strncmp (var_name_begin, "fg.", strlen("fg.")) == 0) 1704 { 1705 var_name_begin += strlen("fg."); // Skip the "fg." 1706 if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0) 1707 { 1708 s.Printf ("%s%s%s", 1709 lldb_utility::ansi::k_escape_start, 1710 lldb_utility::ansi::k_fg_black, 1711 lldb_utility::ansi::k_escape_end); 1712 } 1713 else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0) 1714 { 1715 s.Printf ("%s%s%s", 1716 lldb_utility::ansi::k_escape_start, 1717 lldb_utility::ansi::k_fg_red, 1718 lldb_utility::ansi::k_escape_end); 1719 } 1720 else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0) 1721 { 1722 s.Printf ("%s%s%s", 1723 lldb_utility::ansi::k_escape_start, 1724 lldb_utility::ansi::k_fg_green, 1725 lldb_utility::ansi::k_escape_end); 1726 } 1727 else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0) 1728 { 1729 s.Printf ("%s%s%s", 1730 lldb_utility::ansi::k_escape_start, 1731 lldb_utility::ansi::k_fg_yellow, 1732 lldb_utility::ansi::k_escape_end); 1733 } 1734 else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0) 1735 { 1736 s.Printf ("%s%s%s", 1737 lldb_utility::ansi::k_escape_start, 1738 lldb_utility::ansi::k_fg_blue, 1739 lldb_utility::ansi::k_escape_end); 1740 } 1741 else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0) 1742 { 1743 s.Printf ("%s%s%s", 1744 lldb_utility::ansi::k_escape_start, 1745 lldb_utility::ansi::k_fg_purple, 1746 lldb_utility::ansi::k_escape_end); 1747 } 1748 else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0) 1749 { 1750 s.Printf ("%s%s%s", 1751 lldb_utility::ansi::k_escape_start, 1752 lldb_utility::ansi::k_fg_cyan, 1753 lldb_utility::ansi::k_escape_end); 1754 } 1755 else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0) 1756 { 1757 s.Printf ("%s%s%s", 1758 lldb_utility::ansi::k_escape_start, 1759 lldb_utility::ansi::k_fg_white, 1760 lldb_utility::ansi::k_escape_end); 1761 } 1762 else 1763 { 1764 var_success = false; 1765 } 1766 } 1767 else if (::strncmp (var_name_begin, "bg.", strlen("bg.")) == 0) 1768 { 1769 var_name_begin += strlen("bg."); // Skip the "bg." 1770 if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0) 1771 { 1772 s.Printf ("%s%s%s", 1773 lldb_utility::ansi::k_escape_start, 1774 lldb_utility::ansi::k_bg_black, 1775 lldb_utility::ansi::k_escape_end); 1776 } 1777 else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0) 1778 { 1779 s.Printf ("%s%s%s", 1780 lldb_utility::ansi::k_escape_start, 1781 lldb_utility::ansi::k_bg_red, 1782 lldb_utility::ansi::k_escape_end); 1783 } 1784 else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0) 1785 { 1786 s.Printf ("%s%s%s", 1787 lldb_utility::ansi::k_escape_start, 1788 lldb_utility::ansi::k_bg_green, 1789 lldb_utility::ansi::k_escape_end); 1790 } 1791 else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0) 1792 { 1793 s.Printf ("%s%s%s", 1794 lldb_utility::ansi::k_escape_start, 1795 lldb_utility::ansi::k_bg_yellow, 1796 lldb_utility::ansi::k_escape_end); 1797 } 1798 else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0) 1799 { 1800 s.Printf ("%s%s%s", 1801 lldb_utility::ansi::k_escape_start, 1802 lldb_utility::ansi::k_bg_blue, 1803 lldb_utility::ansi::k_escape_end); 1804 } 1805 else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0) 1806 { 1807 s.Printf ("%s%s%s", 1808 lldb_utility::ansi::k_escape_start, 1809 lldb_utility::ansi::k_bg_purple, 1810 lldb_utility::ansi::k_escape_end); 1811 } 1812 else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0) 1813 { 1814 s.Printf ("%s%s%s", 1815 lldb_utility::ansi::k_escape_start, 1816 lldb_utility::ansi::k_bg_cyan, 1817 lldb_utility::ansi::k_escape_end); 1818 } 1819 else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0) 1820 { 1821 s.Printf ("%s%s%s", 1822 lldb_utility::ansi::k_escape_start, 1823 lldb_utility::ansi::k_bg_white, 1824 lldb_utility::ansi::k_escape_end); 1825 } 1826 else 1827 { 1828 var_success = false; 1829 } 1830 } 1831 else if (::strncmp (var_name_begin, "normal}", strlen ("normal}")) == 0) 1832 { 1833 s.Printf ("%s%s%s", 1834 lldb_utility::ansi::k_escape_start, 1835 lldb_utility::ansi::k_ctrl_normal, 1836 lldb_utility::ansi::k_escape_end); 1837 } 1838 else if (::strncmp (var_name_begin, "bold}", strlen("bold}")) == 0) 1839 { 1840 s.Printf ("%s%s%s", 1841 lldb_utility::ansi::k_escape_start, 1842 lldb_utility::ansi::k_ctrl_bold, 1843 lldb_utility::ansi::k_escape_end); 1844 } 1845 else if (::strncmp (var_name_begin, "faint}", strlen("faint}")) == 0) 1846 { 1847 s.Printf ("%s%s%s", 1848 lldb_utility::ansi::k_escape_start, 1849 lldb_utility::ansi::k_ctrl_faint, 1850 lldb_utility::ansi::k_escape_end); 1851 } 1852 else if (::strncmp (var_name_begin, "italic}", strlen("italic}")) == 0) 1853 { 1854 s.Printf ("%s%s%s", 1855 lldb_utility::ansi::k_escape_start, 1856 lldb_utility::ansi::k_ctrl_italic, 1857 lldb_utility::ansi::k_escape_end); 1858 } 1859 else if (::strncmp (var_name_begin, "underline}", strlen("underline}")) == 0) 1860 { 1861 s.Printf ("%s%s%s", 1862 lldb_utility::ansi::k_escape_start, 1863 lldb_utility::ansi::k_ctrl_underline, 1864 lldb_utility::ansi::k_escape_end); 1865 } 1866 else if (::strncmp (var_name_begin, "slow-blink}", strlen("slow-blink}")) == 0) 1867 { 1868 s.Printf ("%s%s%s", 1869 lldb_utility::ansi::k_escape_start, 1870 lldb_utility::ansi::k_ctrl_slow_blink, 1871 lldb_utility::ansi::k_escape_end); 1872 } 1873 else if (::strncmp (var_name_begin, "fast-blink}", strlen("fast-blink}")) == 0) 1874 { 1875 s.Printf ("%s%s%s", 1876 lldb_utility::ansi::k_escape_start, 1877 lldb_utility::ansi::k_ctrl_fast_blink, 1878 lldb_utility::ansi::k_escape_end); 1879 } 1880 else if (::strncmp (var_name_begin, "negative}", strlen("negative}")) == 0) 1881 { 1882 s.Printf ("%s%s%s", 1883 lldb_utility::ansi::k_escape_start, 1884 lldb_utility::ansi::k_ctrl_negative, 1885 lldb_utility::ansi::k_escape_end); 1886 } 1887 else if (::strncmp (var_name_begin, "conceal}", strlen("conceal}")) == 0) 1888 { 1889 s.Printf ("%s%s%s", 1890 lldb_utility::ansi::k_escape_start, 1891 lldb_utility::ansi::k_ctrl_conceal, 1892 lldb_utility::ansi::k_escape_end); 1893 1894 } 1895 else if (::strncmp (var_name_begin, "crossed-out}", strlen("crossed-out}")) == 0) 1896 { 1897 s.Printf ("%s%s%s", 1898 lldb_utility::ansi::k_escape_start, 1899 lldb_utility::ansi::k_ctrl_crossed_out, 1900 lldb_utility::ansi::k_escape_end); 1901 } 1902 else 1903 { 1904 var_success = false; 1905 } 1906 } 1907 break; 1908 1909 case 'p': 1910 if (::strncmp (var_name_begin, "process.", strlen("process.")) == 0) 1911 { 1912 if (exe_ctx) 1913 { 1914 Process *process = exe_ctx->GetProcessPtr(); 1915 if (process) 1916 { 1917 var_name_begin += ::strlen ("process."); 1918 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 1919 { 1920 s.Printf("%" PRIu64, process->GetID()); 1921 var_success = true; 1922 } 1923 else if ((::strncmp (var_name_begin, "name}", strlen("name}")) == 0) || 1924 (::strncmp (var_name_begin, "file.basename}", strlen("file.basename}")) == 0) || 1925 (::strncmp (var_name_begin, "file.fullpath}", strlen("file.fullpath}")) == 0)) 1926 { 1927 Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1928 if (exe_module) 1929 { 1930 if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') 1931 { 1932 format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); 1933 var_success = format_file_spec; 1934 } 1935 else 1936 { 1937 format_file_spec = exe_module->GetFileSpec(); 1938 var_success = format_file_spec; 1939 } 1940 } 1941 } 1942 } 1943 } 1944 } 1945 break; 1946 1947 case 't': 1948 if (::strncmp (var_name_begin, "thread.", strlen("thread.")) == 0) 1949 { 1950 if (exe_ctx) 1951 { 1952 Thread *thread = exe_ctx->GetThreadPtr(); 1953 if (thread) 1954 { 1955 var_name_begin += ::strlen ("thread."); 1956 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 1957 { 1958 s.Printf("0x%4.4" PRIx64, thread->GetID()); 1959 var_success = true; 1960 } 1961 else if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) 1962 { 1963 s.Printf("%u", thread->GetIndexID()); 1964 var_success = true; 1965 } 1966 else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) 1967 { 1968 cstr = thread->GetName(); 1969 var_success = cstr && cstr[0]; 1970 if (var_success) 1971 s.PutCString(cstr); 1972 } 1973 else if (::strncmp (var_name_begin, "queue}", strlen("queue}")) == 0) 1974 { 1975 cstr = thread->GetQueueName(); 1976 var_success = cstr && cstr[0]; 1977 if (var_success) 1978 s.PutCString(cstr); 1979 } 1980 else if (::strncmp (var_name_begin, "stop-reason}", strlen("stop-reason}")) == 0) 1981 { 1982 StopInfoSP stop_info_sp = thread->GetStopInfo (); 1983 if (stop_info_sp && stop_info_sp->IsValid()) 1984 { 1985 cstr = stop_info_sp->GetDescription(); 1986 if (cstr && cstr[0]) 1987 { 1988 s.PutCString(cstr); 1989 var_success = true; 1990 } 1991 } 1992 } 1993 else if (::strncmp (var_name_begin, "return-value}", strlen("return-value}")) == 0) 1994 { 1995 StopInfoSP stop_info_sp = thread->GetStopInfo (); 1996 if (stop_info_sp && stop_info_sp->IsValid()) 1997 { 1998 ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 1999 if (return_valobj_sp) 2000 { 2001 ValueObject::DumpValueObjectOptions dump_options; 2002 ValueObject::DumpValueObject (s, return_valobj_sp.get(), dump_options); 2003 var_success = true; 2004 } 2005 } 2006 } 2007 } 2008 } 2009 } 2010 else if (::strncmp (var_name_begin, "target.", strlen("target.")) == 0) 2011 { 2012 // TODO: hookup properties 2013 // if (!target_properties_sp) 2014 // { 2015 // Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2016 // if (target) 2017 // target_properties_sp = target->GetProperties(); 2018 // } 2019 // 2020 // if (target_properties_sp) 2021 // { 2022 // var_name_begin += ::strlen ("target."); 2023 // const char *end_property = strchr(var_name_begin, '}'); 2024 // if (end_property) 2025 // { 2026 // ConstString property_name(var_name_begin, end_property - var_name_begin); 2027 // std::string property_value (target_properties_sp->GetPropertyValue(property_name)); 2028 // if (!property_value.empty()) 2029 // { 2030 // s.PutCString (property_value.c_str()); 2031 // var_success = true; 2032 // } 2033 // } 2034 // } 2035 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2036 if (target) 2037 { 2038 var_name_begin += ::strlen ("target."); 2039 if (::strncmp (var_name_begin, "arch}", strlen("arch}")) == 0) 2040 { 2041 ArchSpec arch (target->GetArchitecture ()); 2042 if (arch.IsValid()) 2043 { 2044 s.PutCString (arch.GetArchitectureName()); 2045 var_success = true; 2046 } 2047 } 2048 } 2049 } 2050 break; 2051 2052 2053 case 'm': 2054 if (::strncmp (var_name_begin, "module.", strlen("module.")) == 0) 2055 { 2056 if (sc && sc->module_sp.get()) 2057 { 2058 Module *module = sc->module_sp.get(); 2059 var_name_begin += ::strlen ("module."); 2060 2061 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 2062 { 2063 if (module->GetFileSpec()) 2064 { 2065 var_name_begin += ::strlen ("file."); 2066 2067 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 2068 { 2069 format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); 2070 var_success = format_file_spec; 2071 } 2072 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 2073 { 2074 format_file_spec = module->GetFileSpec(); 2075 var_success = format_file_spec; 2076 } 2077 } 2078 } 2079 } 2080 } 2081 break; 2082 2083 2084 case 'f': 2085 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 2086 { 2087 if (sc && sc->comp_unit != NULL) 2088 { 2089 var_name_begin += ::strlen ("file."); 2090 2091 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 2092 { 2093 format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); 2094 var_success = format_file_spec; 2095 } 2096 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 2097 { 2098 format_file_spec = *sc->comp_unit; 2099 var_success = format_file_spec; 2100 } 2101 } 2102 } 2103 else if (::strncmp (var_name_begin, "frame.", strlen("frame.")) == 0) 2104 { 2105 if (exe_ctx) 2106 { 2107 StackFrame *frame = exe_ctx->GetFramePtr(); 2108 if (frame) 2109 { 2110 var_name_begin += ::strlen ("frame."); 2111 if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) 2112 { 2113 s.Printf("%u", frame->GetFrameIndex()); 2114 var_success = true; 2115 } 2116 else if (::strncmp (var_name_begin, "pc}", strlen("pc}")) == 0) 2117 { 2118 reg_kind = eRegisterKindGeneric; 2119 reg_num = LLDB_REGNUM_GENERIC_PC; 2120 var_success = true; 2121 } 2122 else if (::strncmp (var_name_begin, "sp}", strlen("sp}")) == 0) 2123 { 2124 reg_kind = eRegisterKindGeneric; 2125 reg_num = LLDB_REGNUM_GENERIC_SP; 2126 var_success = true; 2127 } 2128 else if (::strncmp (var_name_begin, "fp}", strlen("fp}")) == 0) 2129 { 2130 reg_kind = eRegisterKindGeneric; 2131 reg_num = LLDB_REGNUM_GENERIC_FP; 2132 var_success = true; 2133 } 2134 else if (::strncmp (var_name_begin, "flags}", strlen("flags}")) == 0) 2135 { 2136 reg_kind = eRegisterKindGeneric; 2137 reg_num = LLDB_REGNUM_GENERIC_FLAGS; 2138 var_success = true; 2139 } 2140 else if (::strncmp (var_name_begin, "reg.", strlen ("reg.")) == 0) 2141 { 2142 reg_ctx = frame->GetRegisterContext().get(); 2143 if (reg_ctx) 2144 { 2145 var_name_begin += ::strlen ("reg."); 2146 if (var_name_begin < var_name_end) 2147 { 2148 std::string reg_name (var_name_begin, var_name_end); 2149 reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); 2150 if (reg_info) 2151 var_success = true; 2152 } 2153 } 2154 } 2155 } 2156 } 2157 } 2158 else if (::strncmp (var_name_begin, "function.", strlen("function.")) == 0) 2159 { 2160 if (sc && (sc->function != NULL || sc->symbol != NULL)) 2161 { 2162 var_name_begin += ::strlen ("function."); 2163 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 2164 { 2165 if (sc->function) 2166 s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); 2167 else 2168 s.Printf("symbol[%u]", sc->symbol->GetID()); 2169 2170 var_success = true; 2171 } 2172 else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) 2173 { 2174 if (sc->function) 2175 cstr = sc->function->GetName().AsCString (NULL); 2176 else if (sc->symbol) 2177 cstr = sc->symbol->GetName().AsCString (NULL); 2178 if (cstr) 2179 { 2180 s.PutCString(cstr); 2181 2182 if (sc->block) 2183 { 2184 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2185 if (inline_block) 2186 { 2187 const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 2188 if (inline_info) 2189 { 2190 s.PutCString(" [inlined] "); 2191 inline_info->GetName().Dump(&s); 2192 } 2193 } 2194 } 2195 var_success = true; 2196 } 2197 } 2198 else if (::strncmp (var_name_begin, "name-with-args}", strlen("name-with-args}")) == 0) 2199 { 2200 // Print the function name with arguments in it 2201 2202 if (sc->function) 2203 { 2204 var_success = true; 2205 ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; 2206 cstr = sc->function->GetName().AsCString (NULL); 2207 if (cstr) 2208 { 2209 const InlineFunctionInfo *inline_info = NULL; 2210 VariableListSP variable_list_sp; 2211 bool get_function_vars = true; 2212 if (sc->block) 2213 { 2214 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2215 2216 if (inline_block) 2217 { 2218 get_function_vars = false; 2219 inline_info = sc->block->GetInlinedFunctionInfo(); 2220 if (inline_info) 2221 variable_list_sp = inline_block->GetBlockVariableList (true); 2222 } 2223 } 2224 2225 if (get_function_vars) 2226 { 2227 variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); 2228 } 2229 2230 if (inline_info) 2231 { 2232 s.PutCString (cstr); 2233 s.PutCString (" [inlined] "); 2234 cstr = inline_info->GetName().GetCString(); 2235 } 2236 2237 VariableList args; 2238 if (variable_list_sp) 2239 { 2240 const size_t num_variables = variable_list_sp->GetSize(); 2241 for (size_t var_idx = 0; var_idx < num_variables; ++var_idx) 2242 { 2243 VariableSP var_sp (variable_list_sp->GetVariableAtIndex(var_idx)); 2244 if (var_sp->GetScope() == eValueTypeVariableArgument) 2245 args.AddVariable (var_sp); 2246 } 2247 2248 } 2249 if (args.GetSize() > 0) 2250 { 2251 const char *open_paren = strchr (cstr, '('); 2252 const char *close_paren = NULL; 2253 if (open_paren) 2254 close_paren = strchr (open_paren, ')'); 2255 2256 if (open_paren) 2257 s.Write(cstr, open_paren - cstr + 1); 2258 else 2259 { 2260 s.PutCString (cstr); 2261 s.PutChar ('('); 2262 } 2263 const size_t num_args = args.GetSize(); 2264 for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) 2265 { 2266 VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); 2267 ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); 2268 const char *var_name = var_value_sp->GetName().GetCString(); 2269 const char *var_value = var_value_sp->GetValueAsCString(); 2270 if (var_value_sp->GetError().Success()) 2271 { 2272 if (arg_idx > 0) 2273 s.PutCString (", "); 2274 s.Printf ("%s=%s", var_name, var_value); 2275 } 2276 } 2277 2278 if (close_paren) 2279 s.PutCString (close_paren); 2280 else 2281 s.PutChar(')'); 2282 2283 } 2284 else 2285 { 2286 s.PutCString(cstr); 2287 } 2288 } 2289 } 2290 else if (sc->symbol) 2291 { 2292 cstr = sc->symbol->GetName().AsCString (NULL); 2293 if (cstr) 2294 { 2295 s.PutCString(cstr); 2296 var_success = true; 2297 } 2298 } 2299 } 2300 else if (::strncmp (var_name_begin, "addr-offset}", strlen("addr-offset}")) == 0) 2301 { 2302 var_success = addr != NULL; 2303 if (var_success) 2304 { 2305 format_addr = *addr; 2306 calculate_format_addr_function_offset = true; 2307 } 2308 } 2309 else if (::strncmp (var_name_begin, "line-offset}", strlen("line-offset}")) == 0) 2310 { 2311 var_success = sc->line_entry.range.GetBaseAddress().IsValid(); 2312 if (var_success) 2313 { 2314 format_addr = sc->line_entry.range.GetBaseAddress(); 2315 calculate_format_addr_function_offset = true; 2316 } 2317 } 2318 else if (::strncmp (var_name_begin, "pc-offset}", strlen("pc-offset}")) == 0) 2319 { 2320 StackFrame *frame = exe_ctx->GetFramePtr(); 2321 var_success = frame != NULL; 2322 if (var_success) 2323 { 2324 format_addr = frame->GetFrameCodeAddress(); 2325 calculate_format_addr_function_offset = true; 2326 } 2327 } 2328 } 2329 } 2330 break; 2331 2332 case 'l': 2333 if (::strncmp (var_name_begin, "line.", strlen("line.")) == 0) 2334 { 2335 if (sc && sc->line_entry.IsValid()) 2336 { 2337 var_name_begin += ::strlen ("line."); 2338 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 2339 { 2340 var_name_begin += ::strlen ("file."); 2341 2342 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 2343 { 2344 format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); 2345 var_success = format_file_spec; 2346 } 2347 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 2348 { 2349 format_file_spec = sc->line_entry.file; 2350 var_success = format_file_spec; 2351 } 2352 } 2353 else if (::strncmp (var_name_begin, "number}", strlen("number}")) == 0) 2354 { 2355 var_success = true; 2356 s.Printf("%u", sc->line_entry.line); 2357 } 2358 else if ((::strncmp (var_name_begin, "start-addr}", strlen("start-addr}")) == 0) || 2359 (::strncmp (var_name_begin, "end-addr}", strlen("end-addr}")) == 0)) 2360 { 2361 var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); 2362 if (var_success) 2363 { 2364 format_addr = sc->line_entry.range.GetBaseAddress(); 2365 if (var_name_begin[0] == 'e') 2366 format_addr.Slide (sc->line_entry.range.GetByteSize()); 2367 } 2368 } 2369 } 2370 } 2371 break; 2372 } 2373 2374 if (var_success) 2375 { 2376 // If format addr is valid, then we need to print an address 2377 if (reg_num != LLDB_INVALID_REGNUM) 2378 { 2379 StackFrame *frame = exe_ctx->GetFramePtr(); 2380 // We have a register value to display... 2381 if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) 2382 { 2383 format_addr = frame->GetFrameCodeAddress(); 2384 } 2385 else 2386 { 2387 if (reg_ctx == NULL) 2388 reg_ctx = frame->GetRegisterContext().get(); 2389 2390 if (reg_ctx) 2391 { 2392 if (reg_kind != kNumRegisterKinds) 2393 reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 2394 reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); 2395 var_success = reg_info != NULL; 2396 } 2397 } 2398 } 2399 2400 if (reg_info != NULL) 2401 { 2402 RegisterValue reg_value; 2403 var_success = reg_ctx->ReadRegister (reg_info, reg_value); 2404 if (var_success) 2405 { 2406 reg_value.Dump(&s, reg_info, false, false, eFormatDefault); 2407 } 2408 } 2409 2410 if (format_file_spec) 2411 { 2412 s << format_file_spec; 2413 } 2414 2415 // If format addr is valid, then we need to print an address 2416 if (format_addr.IsValid()) 2417 { 2418 var_success = false; 2419 2420 if (calculate_format_addr_function_offset) 2421 { 2422 Address func_addr; 2423 2424 if (sc) 2425 { 2426 if (sc->function) 2427 { 2428 func_addr = sc->function->GetAddressRange().GetBaseAddress(); 2429 if (sc->block) 2430 { 2431 // Check to make sure we aren't in an inline 2432 // function. If we are, use the inline block 2433 // range that contains "format_addr" since 2434 // blocks can be discontiguous. 2435 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2436 AddressRange inline_range; 2437 if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 2438 func_addr = inline_range.GetBaseAddress(); 2439 } 2440 } 2441 else if (sc->symbol && sc->symbol->ValueIsAddress()) 2442 func_addr = sc->symbol->GetAddress(); 2443 } 2444 2445 if (func_addr.IsValid()) 2446 { 2447 if (func_addr.GetSection() == format_addr.GetSection()) 2448 { 2449 addr_t func_file_addr = func_addr.GetFileAddress(); 2450 addr_t addr_file_addr = format_addr.GetFileAddress(); 2451 if (addr_file_addr > func_file_addr) 2452 s.Printf(" + %" PRIu64, addr_file_addr - func_file_addr); 2453 else if (addr_file_addr < func_file_addr) 2454 s.Printf(" - %" PRIu64, func_file_addr - addr_file_addr); 2455 var_success = true; 2456 } 2457 else 2458 { 2459 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2460 if (target) 2461 { 2462 addr_t func_load_addr = func_addr.GetLoadAddress (target); 2463 addr_t addr_load_addr = format_addr.GetLoadAddress (target); 2464 if (addr_load_addr > func_load_addr) 2465 s.Printf(" + %" PRIu64, addr_load_addr - func_load_addr); 2466 else if (addr_load_addr < func_load_addr) 2467 s.Printf(" - %" PRIu64, func_load_addr - addr_load_addr); 2468 var_success = true; 2469 } 2470 } 2471 } 2472 } 2473 else 2474 { 2475 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2476 addr_t vaddr = LLDB_INVALID_ADDRESS; 2477 if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 2478 vaddr = format_addr.GetLoadAddress (target); 2479 if (vaddr == LLDB_INVALID_ADDRESS) 2480 vaddr = format_addr.GetFileAddress (); 2481 2482 if (vaddr != LLDB_INVALID_ADDRESS) 2483 { 2484 int addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 2485 if (addr_width == 0) 2486 addr_width = 16; 2487 s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); 2488 var_success = true; 2489 } 2490 } 2491 } 2492 } 2493 2494 if (var_success == false) 2495 success = false; 2496 } 2497 p = var_name_end; 2498 } 2499 else 2500 break; 2501 } 2502 else 2503 { 2504 // We got a dollar sign with no '{' after it, it must just be a dollar sign 2505 s.PutChar(*p); 2506 } 2507 } 2508 else if (*p == '\\') 2509 { 2510 ++p; // skip the slash 2511 switch (*p) 2512 { 2513 case 'a': s.PutChar ('\a'); break; 2514 case 'b': s.PutChar ('\b'); break; 2515 case 'f': s.PutChar ('\f'); break; 2516 case 'n': s.PutChar ('\n'); break; 2517 case 'r': s.PutChar ('\r'); break; 2518 case 't': s.PutChar ('\t'); break; 2519 case 'v': s.PutChar ('\v'); break; 2520 case '\'': s.PutChar ('\''); break; 2521 case '\\': s.PutChar ('\\'); break; 2522 case '0': 2523 // 1 to 3 octal chars 2524 { 2525 // Make a string that can hold onto the initial zero char, 2526 // up to 3 octal digits, and a terminating NULL. 2527 char oct_str[5] = { 0, 0, 0, 0, 0 }; 2528 2529 int i; 2530 for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) 2531 oct_str[i] = p[i]; 2532 2533 // We don't want to consume the last octal character since 2534 // the main for loop will do this for us, so we advance p by 2535 // one less than i (even if i is zero) 2536 p += i - 1; 2537 unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 2538 if (octal_value <= UINT8_MAX) 2539 { 2540 char octal_char = octal_value; 2541 s.Write (&octal_char, 1); 2542 } 2543 } 2544 break; 2545 2546 case 'x': 2547 // hex number in the format 2548 if (isxdigit(p[1])) 2549 { 2550 ++p; // Skip the 'x' 2551 2552 // Make a string that can hold onto two hex chars plus a 2553 // NULL terminator 2554 char hex_str[3] = { 0,0,0 }; 2555 hex_str[0] = *p; 2556 if (isxdigit(p[1])) 2557 { 2558 ++p; // Skip the first of the two hex chars 2559 hex_str[1] = *p; 2560 } 2561 2562 unsigned long hex_value = strtoul (hex_str, NULL, 16); 2563 if (hex_value <= UINT8_MAX) 2564 s.PutChar (hex_value); 2565 } 2566 else 2567 { 2568 s.PutChar('x'); 2569 } 2570 break; 2571 2572 default: 2573 // Just desensitize any other character by just printing what 2574 // came after the '\' 2575 s << *p; 2576 break; 2577 2578 } 2579 2580 } 2581 } 2582 if (end) 2583 *end = p; 2584 return success; 2585 } 2586 2587 void 2588 Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) 2589 { 2590 // For simplicity's sake, I am not going to deal with how to close down any 2591 // open logging streams, I just redirect everything from here on out to the 2592 // callback. 2593 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 2594 } 2595 2596 bool 2597 Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream) 2598 { 2599 Log::Callbacks log_callbacks; 2600 2601 StreamSP log_stream_sp; 2602 if (m_log_callback_stream_sp) 2603 { 2604 log_stream_sp = m_log_callback_stream_sp; 2605 // For now when using the callback mode you always get thread & timestamp. 2606 log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 2607 } 2608 else if (log_file == NULL || *log_file == '\0') 2609 { 2610 log_stream_sp.reset(new StreamFile(GetOutputFile().GetDescriptor(), false)); 2611 } 2612 else 2613 { 2614 LogStreamMap::iterator pos = m_log_streams.find(log_file); 2615 if (pos == m_log_streams.end()) 2616 { 2617 log_stream_sp.reset (new StreamFile (log_file)); 2618 m_log_streams[log_file] = log_stream_sp; 2619 } 2620 else 2621 log_stream_sp = pos->second; 2622 } 2623 assert (log_stream_sp.get()); 2624 2625 if (log_options == 0) 2626 log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 2627 2628 if (Log::GetLogChannelCallbacks (channel, log_callbacks)) 2629 { 2630 log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream); 2631 return true; 2632 } 2633 else 2634 { 2635 LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel)); 2636 if (log_channel_sp) 2637 { 2638 if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories)) 2639 { 2640 return true; 2641 } 2642 else 2643 { 2644 error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2645 return false; 2646 } 2647 } 2648 else 2649 { 2650 error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2651 return false; 2652 } 2653 } 2654 return false; 2655 } 2656 2657