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_target_list (*this), 552 m_platform_list (), 553 m_listener ("lldb.Debugger"), 554 m_source_manager(*this), 555 m_source_file_cache(), 556 m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)), 557 m_input_reader_stack (), 558 m_input_reader_data (), 559 m_instance_name() 560 { 561 char instance_cstr[256]; 562 snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); 563 m_instance_name.SetCString(instance_cstr); 564 if (log_callback) 565 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 566 m_command_interpreter_ap->Initialize (); 567 // Always add our default platform to the platform list 568 PlatformSP default_platform_sp (Platform::GetDefaultPlatform()); 569 assert (default_platform_sp.get()); 570 m_platform_list.Append (default_platform_sp, true); 571 572 m_collection_sp->Initialize (g_properties); 573 m_collection_sp->AppendProperty (ConstString("target"), 574 ConstString("Settings specify to debugging targets."), 575 true, 576 Target::GetGlobalProperties()->GetValueProperties()); 577 if (m_command_interpreter_ap.get()) 578 { 579 m_collection_sp->AppendProperty (ConstString("interpreter"), 580 ConstString("Settings specify to the debugger's command interpreter."), 581 true, 582 m_command_interpreter_ap->GetValueProperties()); 583 } 584 OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64 (NULL, ePropertyTerminalWidth); 585 term_width->SetMinimumValue(10); 586 term_width->SetMaximumValue(1024); 587 } 588 589 Debugger::~Debugger () 590 { 591 Clear(); 592 } 593 594 void 595 Debugger::Clear() 596 { 597 CleanUpInputReaders(); 598 m_listener.Clear(); 599 int num_targets = m_target_list.GetNumTargets(); 600 for (int i = 0; i < num_targets; i++) 601 { 602 TargetSP target_sp (m_target_list.GetTargetAtIndex (i)); 603 if (target_sp) 604 { 605 ProcessSP process_sp (target_sp->GetProcessSP()); 606 if (process_sp) 607 { 608 if (process_sp->GetShouldDetach()) 609 process_sp->Detach(); 610 } 611 target_sp->Destroy(); 612 } 613 } 614 BroadcasterManager::Clear (); 615 616 // Close the input file _before_ we close the input read communications class 617 // as it does NOT own the input file, our m_input_file does. 618 GetInputFile().Close (); 619 // Now that we have closed m_input_file, we can now tell our input communication 620 // class to close down. Its read thread should quickly exit after we close 621 // the input file handle above. 622 m_input_comm.Clear (); 623 } 624 625 bool 626 Debugger::GetCloseInputOnEOF () const 627 { 628 return m_input_comm.GetCloseOnEOF(); 629 } 630 631 void 632 Debugger::SetCloseInputOnEOF (bool b) 633 { 634 m_input_comm.SetCloseOnEOF(b); 635 } 636 637 bool 638 Debugger::GetAsyncExecution () 639 { 640 return !m_command_interpreter_ap->GetSynchronous(); 641 } 642 643 void 644 Debugger::SetAsyncExecution (bool async_execution) 645 { 646 m_command_interpreter_ap->SetSynchronous (!async_execution); 647 } 648 649 650 void 651 Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) 652 { 653 File &in_file = GetInputFile(); 654 in_file.SetStream (fh, tranfer_ownership); 655 if (in_file.IsValid() == false) 656 in_file.SetStream (stdin, true); 657 658 // Disconnect from any old connection if we had one 659 m_input_comm.Disconnect (); 660 // Pass false as the second argument to ConnectionFileDescriptor below because 661 // our "in_file" above will already take ownership if requested and we don't 662 // want to objects trying to own and close a file descriptor. 663 m_input_comm.SetConnection (new ConnectionFileDescriptor (in_file.GetDescriptor(), false)); 664 m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this); 665 666 Error error; 667 if (m_input_comm.StartReadThread (&error) == false) 668 { 669 File &err_file = GetErrorFile(); 670 671 err_file.Printf ("error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error"); 672 exit(1); 673 } 674 } 675 676 void 677 Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership) 678 { 679 File &out_file = GetOutputFile(); 680 out_file.SetStream (fh, tranfer_ownership); 681 if (out_file.IsValid() == false) 682 out_file.SetStream (stdout, false); 683 684 GetCommandInterpreter().GetScriptInterpreter()->ResetOutputFileHandle (fh); 685 } 686 687 void 688 Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) 689 { 690 File &err_file = GetErrorFile(); 691 err_file.SetStream (fh, tranfer_ownership); 692 if (err_file.IsValid() == false) 693 err_file.SetStream (stderr, false); 694 } 695 696 ExecutionContext 697 Debugger::GetSelectedExecutionContext () 698 { 699 ExecutionContext exe_ctx; 700 TargetSP target_sp(GetSelectedTarget()); 701 exe_ctx.SetTargetSP (target_sp); 702 703 if (target_sp) 704 { 705 ProcessSP process_sp (target_sp->GetProcessSP()); 706 exe_ctx.SetProcessSP (process_sp); 707 if (process_sp && process_sp->IsRunning() == false) 708 { 709 ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); 710 if (thread_sp) 711 { 712 exe_ctx.SetThreadSP (thread_sp); 713 exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame()); 714 if (exe_ctx.GetFramePtr() == NULL) 715 exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0)); 716 } 717 } 718 } 719 return exe_ctx; 720 721 } 722 723 InputReaderSP 724 Debugger::GetCurrentInputReader () 725 { 726 InputReaderSP reader_sp; 727 728 if (!m_input_reader_stack.IsEmpty()) 729 { 730 // Clear any finished readers from the stack 731 while (CheckIfTopInputReaderIsDone()) ; 732 733 if (!m_input_reader_stack.IsEmpty()) 734 reader_sp = m_input_reader_stack.Top(); 735 } 736 737 return reader_sp; 738 } 739 740 void 741 Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len) 742 { 743 if (bytes_len > 0) 744 ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len); 745 else 746 ((Debugger *)baton)->DispatchInputEndOfFile (); 747 } 748 749 750 void 751 Debugger::DispatchInput (const char *bytes, size_t bytes_len) 752 { 753 if (bytes == NULL || bytes_len == 0) 754 return; 755 756 WriteToDefaultReader (bytes, bytes_len); 757 } 758 759 void 760 Debugger::DispatchInputInterrupt () 761 { 762 m_input_reader_data.clear(); 763 764 InputReaderSP reader_sp (GetCurrentInputReader ()); 765 if (reader_sp) 766 { 767 reader_sp->Notify (eInputReaderInterrupt); 768 769 // If notifying the reader of the interrupt finished the reader, we should pop it off the stack. 770 while (CheckIfTopInputReaderIsDone ()) ; 771 } 772 } 773 774 void 775 Debugger::DispatchInputEndOfFile () 776 { 777 m_input_reader_data.clear(); 778 779 InputReaderSP reader_sp (GetCurrentInputReader ()); 780 if (reader_sp) 781 { 782 reader_sp->Notify (eInputReaderEndOfFile); 783 784 // If notifying the reader of the end-of-file finished the reader, we should pop it off the stack. 785 while (CheckIfTopInputReaderIsDone ()) ; 786 } 787 } 788 789 void 790 Debugger::CleanUpInputReaders () 791 { 792 m_input_reader_data.clear(); 793 794 // The bottom input reader should be the main debugger input reader. We do not want to close that one here. 795 while (m_input_reader_stack.GetSize() > 1) 796 { 797 InputReaderSP reader_sp (GetCurrentInputReader ()); 798 if (reader_sp) 799 { 800 reader_sp->Notify (eInputReaderEndOfFile); 801 reader_sp->SetIsDone (true); 802 } 803 } 804 } 805 806 void 807 Debugger::NotifyTopInputReader (InputReaderAction notification) 808 { 809 InputReaderSP reader_sp (GetCurrentInputReader()); 810 if (reader_sp) 811 { 812 reader_sp->Notify (notification); 813 814 // Flush out any input readers that are done. 815 while (CheckIfTopInputReaderIsDone ()) 816 /* Do nothing. */; 817 } 818 } 819 820 bool 821 Debugger::InputReaderIsTopReader (const InputReaderSP& reader_sp) 822 { 823 InputReaderSP top_reader_sp (GetCurrentInputReader()); 824 825 return (reader_sp.get() == top_reader_sp.get()); 826 } 827 828 829 void 830 Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len) 831 { 832 if (bytes && bytes_len) 833 m_input_reader_data.append (bytes, bytes_len); 834 835 if (m_input_reader_data.empty()) 836 return; 837 838 while (!m_input_reader_stack.IsEmpty() && !m_input_reader_data.empty()) 839 { 840 // Get the input reader from the top of the stack 841 InputReaderSP reader_sp (GetCurrentInputReader ()); 842 if (!reader_sp) 843 break; 844 845 size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(), 846 m_input_reader_data.size()); 847 if (bytes_handled) 848 { 849 m_input_reader_data.erase (0, bytes_handled); 850 } 851 else 852 { 853 // No bytes were handled, we might not have reached our 854 // granularity, just return and wait for more data 855 break; 856 } 857 } 858 859 // Flush out any input readers that are done. 860 while (CheckIfTopInputReaderIsDone ()) 861 /* Do nothing. */; 862 863 } 864 865 void 866 Debugger::PushInputReader (const InputReaderSP& reader_sp) 867 { 868 if (!reader_sp) 869 return; 870 871 // Deactivate the old top reader 872 InputReaderSP top_reader_sp (GetCurrentInputReader ()); 873 874 if (top_reader_sp) 875 top_reader_sp->Notify (eInputReaderDeactivate); 876 877 m_input_reader_stack.Push (reader_sp); 878 reader_sp->Notify (eInputReaderActivate); 879 ActivateInputReader (reader_sp); 880 } 881 882 bool 883 Debugger::PopInputReader (const InputReaderSP& pop_reader_sp) 884 { 885 bool result = false; 886 887 // The reader on the stop of the stack is done, so let the next 888 // read on the stack referesh its prompt and if there is one... 889 if (!m_input_reader_stack.IsEmpty()) 890 { 891 // Cannot call GetCurrentInputReader here, as that would cause an infinite loop. 892 InputReaderSP reader_sp(m_input_reader_stack.Top()); 893 894 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get()) 895 { 896 m_input_reader_stack.Pop (); 897 reader_sp->Notify (eInputReaderDeactivate); 898 reader_sp->Notify (eInputReaderDone); 899 result = true; 900 901 if (!m_input_reader_stack.IsEmpty()) 902 { 903 reader_sp = m_input_reader_stack.Top(); 904 if (reader_sp) 905 { 906 ActivateInputReader (reader_sp); 907 reader_sp->Notify (eInputReaderReactivate); 908 } 909 } 910 } 911 } 912 return result; 913 } 914 915 bool 916 Debugger::CheckIfTopInputReaderIsDone () 917 { 918 bool result = false; 919 if (!m_input_reader_stack.IsEmpty()) 920 { 921 // Cannot call GetCurrentInputReader here, as that would cause an infinite loop. 922 InputReaderSP reader_sp(m_input_reader_stack.Top()); 923 924 if (reader_sp && reader_sp->IsDone()) 925 { 926 result = true; 927 PopInputReader (reader_sp); 928 } 929 } 930 return result; 931 } 932 933 void 934 Debugger::ActivateInputReader (const InputReaderSP &reader_sp) 935 { 936 int input_fd = m_input_file.GetFile().GetDescriptor(); 937 938 if (input_fd >= 0) 939 { 940 Terminal tty(input_fd); 941 942 tty.SetEcho(reader_sp->GetEcho()); 943 944 switch (reader_sp->GetGranularity()) 945 { 946 case eInputReaderGranularityByte: 947 case eInputReaderGranularityWord: 948 tty.SetCanonical (false); 949 break; 950 951 case eInputReaderGranularityLine: 952 case eInputReaderGranularityAll: 953 tty.SetCanonical (true); 954 break; 955 956 default: 957 break; 958 } 959 } 960 } 961 962 StreamSP 963 Debugger::GetAsyncOutputStream () 964 { 965 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 966 CommandInterpreter::eBroadcastBitAsynchronousOutputData)); 967 } 968 969 StreamSP 970 Debugger::GetAsyncErrorStream () 971 { 972 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(), 973 CommandInterpreter::eBroadcastBitAsynchronousErrorData)); 974 } 975 976 uint32_t 977 Debugger::GetNumDebuggers() 978 { 979 if (g_shared_debugger_refcount > 0) 980 { 981 Mutex::Locker locker (GetDebuggerListMutex ()); 982 return GetDebuggerList().size(); 983 } 984 return 0; 985 } 986 987 lldb::DebuggerSP 988 Debugger::GetDebuggerAtIndex (uint32_t index) 989 { 990 DebuggerSP debugger_sp; 991 992 if (g_shared_debugger_refcount > 0) 993 { 994 Mutex::Locker locker (GetDebuggerListMutex ()); 995 DebuggerList &debugger_list = GetDebuggerList(); 996 997 if (index < debugger_list.size()) 998 debugger_sp = debugger_list[index]; 999 } 1000 1001 return debugger_sp; 1002 } 1003 1004 DebuggerSP 1005 Debugger::FindDebuggerWithID (lldb::user_id_t id) 1006 { 1007 DebuggerSP debugger_sp; 1008 1009 if (g_shared_debugger_refcount > 0) 1010 { 1011 Mutex::Locker locker (GetDebuggerListMutex ()); 1012 DebuggerList &debugger_list = GetDebuggerList(); 1013 DebuggerList::iterator pos, end = debugger_list.end(); 1014 for (pos = debugger_list.begin(); pos != end; ++pos) 1015 { 1016 if ((*pos).get()->GetID() == id) 1017 { 1018 debugger_sp = *pos; 1019 break; 1020 } 1021 } 1022 } 1023 return debugger_sp; 1024 } 1025 1026 static void 1027 TestPromptFormats (StackFrame *frame) 1028 { 1029 if (frame == NULL) 1030 return; 1031 1032 StreamString s; 1033 const char *prompt_format = 1034 "{addr = '${addr}'\n}" 1035 "{process.id = '${process.id}'\n}" 1036 "{process.name = '${process.name}'\n}" 1037 "{process.file.basename = '${process.file.basename}'\n}" 1038 "{process.file.fullpath = '${process.file.fullpath}'\n}" 1039 "{thread.id = '${thread.id}'\n}" 1040 "{thread.index = '${thread.index}'\n}" 1041 "{thread.name = '${thread.name}'\n}" 1042 "{thread.queue = '${thread.queue}'\n}" 1043 "{thread.stop-reason = '${thread.stop-reason}'\n}" 1044 "{target.arch = '${target.arch}'\n}" 1045 "{module.file.basename = '${module.file.basename}'\n}" 1046 "{module.file.fullpath = '${module.file.fullpath}'\n}" 1047 "{file.basename = '${file.basename}'\n}" 1048 "{file.fullpath = '${file.fullpath}'\n}" 1049 "{frame.index = '${frame.index}'\n}" 1050 "{frame.pc = '${frame.pc}'\n}" 1051 "{frame.sp = '${frame.sp}'\n}" 1052 "{frame.fp = '${frame.fp}'\n}" 1053 "{frame.flags = '${frame.flags}'\n}" 1054 "{frame.reg.rdi = '${frame.reg.rdi}'\n}" 1055 "{frame.reg.rip = '${frame.reg.rip}'\n}" 1056 "{frame.reg.rsp = '${frame.reg.rsp}'\n}" 1057 "{frame.reg.rbp = '${frame.reg.rbp}'\n}" 1058 "{frame.reg.rflags = '${frame.reg.rflags}'\n}" 1059 "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" 1060 "{frame.reg.carp = '${frame.reg.carp}'\n}" 1061 "{function.id = '${function.id}'\n}" 1062 "{function.name = '${function.name}'\n}" 1063 "{function.name-with-args = '${function.name-with-args}'\n}" 1064 "{function.addr-offset = '${function.addr-offset}'\n}" 1065 "{function.line-offset = '${function.line-offset}'\n}" 1066 "{function.pc-offset = '${function.pc-offset}'\n}" 1067 "{line.file.basename = '${line.file.basename}'\n}" 1068 "{line.file.fullpath = '${line.file.fullpath}'\n}" 1069 "{line.number = '${line.number}'\n}" 1070 "{line.start-addr = '${line.start-addr}'\n}" 1071 "{line.end-addr = '${line.end-addr}'\n}" 1072 ; 1073 1074 SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything)); 1075 ExecutionContext exe_ctx; 1076 frame->CalculateExecutionContext(exe_ctx); 1077 const char *end = NULL; 1078 if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, &end)) 1079 { 1080 printf("%s\n", s.GetData()); 1081 } 1082 else 1083 { 1084 printf ("error: at '%s'\n", end); 1085 printf ("what we got: %s\n", s.GetData()); 1086 } 1087 } 1088 1089 static bool 1090 ScanFormatDescriptor (const char* var_name_begin, 1091 const char* var_name_end, 1092 const char** var_name_final, 1093 const char** percent_position, 1094 Format* custom_format, 1095 ValueObject::ValueObjectRepresentationStyle* val_obj_display) 1096 { 1097 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1098 *percent_position = ::strchr(var_name_begin,'%'); 1099 if (!*percent_position || *percent_position > var_name_end) 1100 { 1101 if (log) 1102 log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping"); 1103 *var_name_final = var_name_end; 1104 } 1105 else 1106 { 1107 *var_name_final = *percent_position; 1108 char* format_name = new char[var_name_end-*var_name_final]; format_name[var_name_end-*var_name_final-1] = '\0'; 1109 memcpy(format_name, *var_name_final+1, var_name_end-*var_name_final-1); 1110 if (log) 1111 log->Printf("ScanFormatDescriptor] parsing %s as a format descriptor", format_name); 1112 if ( !FormatManager::GetFormatFromCString(format_name, 1113 true, 1114 *custom_format) ) 1115 { 1116 if (log) 1117 log->Printf("ScanFormatDescriptor] %s is an unknown format", format_name); 1118 // if this is an @ sign, print ObjC description 1119 if (*format_name == '@') 1120 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; 1121 // if this is a V, print the value using the default format 1122 else if (*format_name == 'V') 1123 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1124 // if this is an L, print the location of the value 1125 else if (*format_name == 'L') 1126 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; 1127 // if this is an S, print the summary after all 1128 else if (*format_name == 'S') 1129 *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 1130 else if (*format_name == '#') 1131 *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; 1132 else if (*format_name == 'T') 1133 *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; 1134 else if (log) 1135 log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name); 1136 } 1137 // a good custom format tells us to print the value using it 1138 else 1139 { 1140 if (log) 1141 log->Printf("ScanFormatDescriptor] will display value for this VO"); 1142 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1143 } 1144 delete format_name; 1145 } 1146 if (log) 1147 log->Printf("ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d", 1148 *custom_format, 1149 *val_obj_display); 1150 return true; 1151 } 1152 1153 static bool 1154 ScanBracketedRange (const char* var_name_begin, 1155 const char* var_name_end, 1156 const char* var_name_final, 1157 const char** open_bracket_position, 1158 const char** separator_position, 1159 const char** close_bracket_position, 1160 const char** var_name_final_if_array_range, 1161 int64_t* index_lower, 1162 int64_t* index_higher) 1163 { 1164 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1165 *open_bracket_position = ::strchr(var_name_begin,'['); 1166 if (*open_bracket_position && *open_bracket_position < var_name_final) 1167 { 1168 *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield 1169 *close_bracket_position = ::strchr(*open_bracket_position,']'); 1170 // as usual, we assume that [] will come before % 1171 //printf("trying to expand a []\n"); 1172 *var_name_final_if_array_range = *open_bracket_position; 1173 if (*close_bracket_position - *open_bracket_position == 1) 1174 { 1175 if (log) 1176 log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); 1177 *index_lower = 0; 1178 } 1179 else if (*separator_position == NULL || *separator_position > var_name_end) 1180 { 1181 char *end = NULL; 1182 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 1183 *index_higher = *index_lower; 1184 if (log) 1185 log->Printf("[ScanBracketedRange] [%lld] detected, high index is same", *index_lower); 1186 } 1187 else if (*close_bracket_position && *close_bracket_position < var_name_end) 1188 { 1189 char *end = NULL; 1190 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); 1191 *index_higher = ::strtoul (*separator_position+1, &end, 0); 1192 if (log) 1193 log->Printf("[ScanBracketedRange] [%lld-%lld] detected", *index_lower, *index_higher); 1194 } 1195 else 1196 { 1197 if (log) 1198 log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it"); 1199 return false; 1200 } 1201 if (*index_lower > *index_higher && *index_higher > 0) 1202 { 1203 if (log) 1204 log->Printf("[ScanBracketedRange] swapping indices"); 1205 int temp = *index_lower; 1206 *index_lower = *index_higher; 1207 *index_higher = temp; 1208 } 1209 } 1210 else if (log) 1211 log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); 1212 return true; 1213 } 1214 1215 static ValueObjectSP 1216 ExpandIndexedExpression (ValueObject* valobj, 1217 uint32_t index, 1218 StackFrame* frame, 1219 bool deref_pointer) 1220 { 1221 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1222 const char* ptr_deref_format = "[%d]"; 1223 std::auto_ptr<char> ptr_deref_buffer(new char[10]); 1224 ::sprintf(ptr_deref_buffer.get(), ptr_deref_format, index); 1225 if (log) 1226 log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.get()); 1227 const char* first_unparsed; 1228 ValueObject::GetValueForExpressionPathOptions options; 1229 ValueObject::ExpressionPathEndResultType final_value_type; 1230 ValueObject::ExpressionPathScanEndReason reason_to_stop; 1231 ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1232 ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.get(), 1233 &first_unparsed, 1234 &reason_to_stop, 1235 &final_value_type, 1236 options, 1237 &what_next); 1238 if (!item) 1239 { 1240 if (log) 1241 log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," 1242 " final_value_type %d", 1243 first_unparsed, reason_to_stop, final_value_type); 1244 } 1245 else 1246 { 1247 if (log) 1248 log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1249 " final_value_type %d", 1250 first_unparsed, reason_to_stop, final_value_type); 1251 } 1252 return item; 1253 } 1254 1255 bool 1256 Debugger::FormatPrompt 1257 ( 1258 const char *format, 1259 const SymbolContext *sc, 1260 const ExecutionContext *exe_ctx, 1261 const Address *addr, 1262 Stream &s, 1263 const char **end, 1264 ValueObject* valobj 1265 ) 1266 { 1267 ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers 1268 bool success = true; 1269 const char *p; 1270 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); 1271 for (p = format; *p != '\0'; ++p) 1272 { 1273 if (realvalobj) 1274 { 1275 valobj = realvalobj; 1276 realvalobj = NULL; 1277 } 1278 size_t non_special_chars = ::strcspn (p, "${}\\"); 1279 if (non_special_chars > 0) 1280 { 1281 if (success) 1282 s.Write (p, non_special_chars); 1283 p += non_special_chars; 1284 } 1285 1286 if (*p == '\0') 1287 { 1288 break; 1289 } 1290 else if (*p == '{') 1291 { 1292 // Start a new scope that must have everything it needs if it is to 1293 // to make it into the final output stream "s". If you want to make 1294 // a format that only prints out the function or symbol name if there 1295 // is one in the symbol context you can use: 1296 // "{function =${function.name}}" 1297 // The first '{' starts a new scope that end with the matching '}' at 1298 // the end of the string. The contents "function =${function.name}" 1299 // will then be evaluated and only be output if there is a function 1300 // or symbol with a valid name. 1301 StreamString sub_strm; 1302 1303 ++p; // Skip the '{' 1304 1305 if (FormatPrompt (p, sc, exe_ctx, addr, sub_strm, &p, valobj)) 1306 { 1307 // The stream had all it needed 1308 s.Write(sub_strm.GetData(), sub_strm.GetSize()); 1309 } 1310 if (*p != '}') 1311 { 1312 success = false; 1313 break; 1314 } 1315 } 1316 else if (*p == '}') 1317 { 1318 // End of a enclosing scope 1319 break; 1320 } 1321 else if (*p == '$') 1322 { 1323 // We have a prompt variable to print 1324 ++p; 1325 if (*p == '{') 1326 { 1327 ++p; 1328 const char *var_name_begin = p; 1329 const char *var_name_end = ::strchr (p, '}'); 1330 1331 if (var_name_end && var_name_begin < var_name_end) 1332 { 1333 // if we have already failed to parse, skip this variable 1334 if (success) 1335 { 1336 const char *cstr = NULL; 1337 Address format_addr; 1338 bool calculate_format_addr_function_offset = false; 1339 // Set reg_kind and reg_num to invalid values 1340 RegisterKind reg_kind = kNumRegisterKinds; 1341 uint32_t reg_num = LLDB_INVALID_REGNUM; 1342 FileSpec format_file_spec; 1343 const RegisterInfo *reg_info = NULL; 1344 RegisterContext *reg_ctx = NULL; 1345 bool do_deref_pointer = false; 1346 ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 1347 ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; 1348 1349 // Each variable must set success to true below... 1350 bool var_success = false; 1351 switch (var_name_begin[0]) 1352 { 1353 case '*': 1354 case 'v': 1355 case 's': 1356 { 1357 if (!valobj) 1358 break; 1359 1360 if (log) 1361 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1362 1363 // check for *var and *svar 1364 if (*var_name_begin == '*') 1365 { 1366 do_deref_pointer = true; 1367 var_name_begin++; 1368 } 1369 1370 if (log) 1371 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1372 1373 if (*var_name_begin == 's') 1374 { 1375 if (!valobj->IsSynthetic()) 1376 valobj = valobj->GetSyntheticValue().get(); 1377 if (!valobj) 1378 break; 1379 var_name_begin++; 1380 } 1381 1382 if (log) 1383 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1384 1385 // should be a 'v' by now 1386 if (*var_name_begin != 'v') 1387 break; 1388 1389 if (log) 1390 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); 1391 1392 ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? 1393 ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); 1394 ValueObject::GetValueForExpressionPathOptions options; 1395 options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); 1396 ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; 1397 ValueObject* target = NULL; 1398 Format custom_format = eFormatInvalid; 1399 const char* var_name_final = NULL; 1400 const char* var_name_final_if_array_range = NULL; 1401 const char* close_bracket_position = NULL; 1402 int64_t index_lower = -1; 1403 int64_t index_higher = -1; 1404 bool is_array_range = false; 1405 const char* first_unparsed; 1406 bool was_plain_var = false; 1407 bool was_var_format = false; 1408 bool was_var_indexed = false; 1409 1410 if (!valobj) break; 1411 // simplest case ${var}, just print valobj's value 1412 if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0) 1413 { 1414 was_plain_var = true; 1415 target = valobj; 1416 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1417 } 1418 else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0) 1419 { 1420 was_var_format = true; 1421 // this is a variable with some custom format applied to it 1422 const char* percent_position; 1423 target = valobj; 1424 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1425 ScanFormatDescriptor (var_name_begin, 1426 var_name_end, 1427 &var_name_final, 1428 &percent_position, 1429 &custom_format, 1430 &val_obj_display); 1431 } 1432 // this is ${var.something} or multiple .something nested 1433 else if (::strncmp (var_name_begin, "var", strlen("var")) == 0) 1434 { 1435 if (::strncmp(var_name_begin, "var[", strlen("var[")) == 0) 1436 was_var_indexed = true; 1437 const char* percent_position; 1438 ScanFormatDescriptor (var_name_begin, 1439 var_name_end, 1440 &var_name_final, 1441 &percent_position, 1442 &custom_format, 1443 &val_obj_display); 1444 1445 const char* open_bracket_position; 1446 const char* separator_position; 1447 ScanBracketedRange (var_name_begin, 1448 var_name_end, 1449 var_name_final, 1450 &open_bracket_position, 1451 &separator_position, 1452 &close_bracket_position, 1453 &var_name_final_if_array_range, 1454 &index_lower, 1455 &index_higher); 1456 1457 Error error; 1458 1459 std::auto_ptr<char> expr_path(new char[var_name_final-var_name_begin-1]); 1460 ::memset(expr_path.get(), 0, var_name_final-var_name_begin-1); 1461 memcpy(expr_path.get(), var_name_begin+3,var_name_final-var_name_begin-3); 1462 1463 if (log) 1464 log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.get()); 1465 1466 target = valobj->GetValueForExpressionPath(expr_path.get(), 1467 &first_unparsed, 1468 &reason_to_stop, 1469 &final_value_type, 1470 options, 1471 &what_next).get(); 1472 1473 if (!target) 1474 { 1475 if (log) 1476 log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," 1477 " final_value_type %d", 1478 first_unparsed, reason_to_stop, final_value_type); 1479 break; 1480 } 1481 else 1482 { 1483 if (log) 1484 log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," 1485 " final_value_type %d", 1486 first_unparsed, reason_to_stop, final_value_type); 1487 } 1488 } 1489 else 1490 break; 1491 1492 is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || 1493 final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); 1494 1495 do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); 1496 1497 if (do_deref_pointer && !is_array_range) 1498 { 1499 // I have not deref-ed yet, let's do it 1500 // this happens when we are not going through GetValueForVariableExpressionPath 1501 // to get to the target ValueObject 1502 Error error; 1503 target = target->Dereference(error).get(); 1504 if (error.Fail()) 1505 { 1506 if (log) 1507 log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ 1508 break; 1509 } 1510 do_deref_pointer = false; 1511 } 1512 1513 // <rdar://problem/11338654> 1514 // we do not want to use the summary for a bitfield of type T:n 1515 // if we were originally dealing with just a T - that would get 1516 // us into an endless recursion 1517 if (target->IsBitfield() && was_var_indexed) 1518 { 1519 // TODO: check for a (T:n)-specific summary - we should still obey that 1520 StreamString bitfield_name; 1521 bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); 1522 lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); 1523 if (!DataVisualization::GetSummaryForType(type_sp)) 1524 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; 1525 } 1526 1527 // TODO use flags for these 1528 bool is_array = ClangASTContext::IsArrayType(target->GetClangType()); 1529 bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType()); 1530 bool is_aggregate = ClangASTContext::IsAggregateType(target->GetClangType()); 1531 1532 if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions 1533 { 1534 StreamString str_temp; 1535 if (log) 1536 log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); 1537 1538 if (target->HasSpecialPrintableRepresentation(val_obj_display, 1539 custom_format)) 1540 { 1541 // try to use the special cases 1542 var_success = target->DumpPrintableRepresentation(str_temp, 1543 val_obj_display, 1544 custom_format); 1545 if (log) 1546 log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't"); 1547 1548 // should not happen 1549 if (!var_success) 1550 s << "<invalid usage of pointer value as object>"; 1551 else 1552 s << str_temp.GetData(); 1553 var_success = true; 1554 break; 1555 } 1556 else 1557 { 1558 if (was_plain_var) // if ${var} 1559 { 1560 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1561 } 1562 else if (is_pointer) // if pointer, value is the address stored 1563 { 1564 target->DumpPrintableRepresentation (s, 1565 val_obj_display, 1566 custom_format, 1567 ValueObject::ePrintableRepresentationSpecialCasesDisable); 1568 } 1569 else 1570 { 1571 s << "<invalid usage of pointer value as object>"; 1572 } 1573 var_success = true; 1574 break; 1575 } 1576 } 1577 1578 // if directly trying to print ${var}, and this is an aggregate, display a nice 1579 // type @ location message 1580 if (is_aggregate && was_plain_var) 1581 { 1582 s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); 1583 var_success = true; 1584 break; 1585 } 1586 1587 // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it 1588 if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) 1589 { 1590 s << "<invalid use of aggregate type>"; 1591 var_success = true; 1592 break; 1593 } 1594 1595 if (!is_array_range) 1596 { 1597 if (log) 1598 log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); 1599 var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1600 } 1601 else 1602 { 1603 if (log) 1604 log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); 1605 if (!is_array && !is_pointer) 1606 break; 1607 if (log) 1608 log->Printf("[Debugger::FormatPrompt] handle as array"); 1609 const char* special_directions = NULL; 1610 StreamString special_directions_writer; 1611 if (close_bracket_position && (var_name_end-close_bracket_position > 1)) 1612 { 1613 ConstString additional_data; 1614 additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); 1615 special_directions_writer.Printf("${%svar%s}", 1616 do_deref_pointer ? "*" : "", 1617 additional_data.GetCString()); 1618 special_directions = special_directions_writer.GetData(); 1619 } 1620 1621 // let us display items index_lower thru index_higher of this array 1622 s.PutChar('['); 1623 var_success = true; 1624 1625 if (index_higher < 0) 1626 index_higher = valobj->GetNumChildren() - 1; 1627 1628 uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 1629 1630 for (;index_lower<=index_higher;index_lower++) 1631 { 1632 ValueObject* item = ExpandIndexedExpression (target, 1633 index_lower, 1634 exe_ctx->GetFramePtr(), 1635 false).get(); 1636 1637 if (!item) 1638 { 1639 if (log) 1640 log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %lld", index_lower); 1641 } 1642 else 1643 { 1644 if (log) 1645 log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions); 1646 } 1647 1648 if (!special_directions) 1649 var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); 1650 else 1651 var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item); 1652 1653 if (--max_num_children == 0) 1654 { 1655 s.PutCString(", ..."); 1656 break; 1657 } 1658 1659 if (index_lower < index_higher) 1660 s.PutChar(','); 1661 } 1662 s.PutChar(']'); 1663 } 1664 } 1665 break; 1666 case 'a': 1667 if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0) 1668 { 1669 if (addr && addr->IsValid()) 1670 { 1671 var_success = true; 1672 format_addr = *addr; 1673 } 1674 } 1675 else if (::strncmp (var_name_begin, "ansi.", strlen("ansi.")) == 0) 1676 { 1677 var_success = true; 1678 var_name_begin += strlen("ansi."); // Skip the "ansi." 1679 if (::strncmp (var_name_begin, "fg.", strlen("fg.")) == 0) 1680 { 1681 var_name_begin += strlen("fg."); // Skip the "fg." 1682 if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0) 1683 { 1684 s.Printf ("%s%s%s", 1685 lldb_utility::ansi::k_escape_start, 1686 lldb_utility::ansi::k_fg_black, 1687 lldb_utility::ansi::k_escape_end); 1688 } 1689 else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0) 1690 { 1691 s.Printf ("%s%s%s", 1692 lldb_utility::ansi::k_escape_start, 1693 lldb_utility::ansi::k_fg_red, 1694 lldb_utility::ansi::k_escape_end); 1695 } 1696 else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0) 1697 { 1698 s.Printf ("%s%s%s", 1699 lldb_utility::ansi::k_escape_start, 1700 lldb_utility::ansi::k_fg_green, 1701 lldb_utility::ansi::k_escape_end); 1702 } 1703 else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0) 1704 { 1705 s.Printf ("%s%s%s", 1706 lldb_utility::ansi::k_escape_start, 1707 lldb_utility::ansi::k_fg_yellow, 1708 lldb_utility::ansi::k_escape_end); 1709 } 1710 else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0) 1711 { 1712 s.Printf ("%s%s%s", 1713 lldb_utility::ansi::k_escape_start, 1714 lldb_utility::ansi::k_fg_blue, 1715 lldb_utility::ansi::k_escape_end); 1716 } 1717 else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0) 1718 { 1719 s.Printf ("%s%s%s", 1720 lldb_utility::ansi::k_escape_start, 1721 lldb_utility::ansi::k_fg_purple, 1722 lldb_utility::ansi::k_escape_end); 1723 } 1724 else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0) 1725 { 1726 s.Printf ("%s%s%s", 1727 lldb_utility::ansi::k_escape_start, 1728 lldb_utility::ansi::k_fg_cyan, 1729 lldb_utility::ansi::k_escape_end); 1730 } 1731 else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0) 1732 { 1733 s.Printf ("%s%s%s", 1734 lldb_utility::ansi::k_escape_start, 1735 lldb_utility::ansi::k_fg_white, 1736 lldb_utility::ansi::k_escape_end); 1737 } 1738 else 1739 { 1740 var_success = false; 1741 } 1742 } 1743 else if (::strncmp (var_name_begin, "bg.", strlen("bg.")) == 0) 1744 { 1745 var_name_begin += strlen("bg."); // Skip the "bg." 1746 if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0) 1747 { 1748 s.Printf ("%s%s%s", 1749 lldb_utility::ansi::k_escape_start, 1750 lldb_utility::ansi::k_bg_black, 1751 lldb_utility::ansi::k_escape_end); 1752 } 1753 else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0) 1754 { 1755 s.Printf ("%s%s%s", 1756 lldb_utility::ansi::k_escape_start, 1757 lldb_utility::ansi::k_bg_red, 1758 lldb_utility::ansi::k_escape_end); 1759 } 1760 else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0) 1761 { 1762 s.Printf ("%s%s%s", 1763 lldb_utility::ansi::k_escape_start, 1764 lldb_utility::ansi::k_bg_green, 1765 lldb_utility::ansi::k_escape_end); 1766 } 1767 else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0) 1768 { 1769 s.Printf ("%s%s%s", 1770 lldb_utility::ansi::k_escape_start, 1771 lldb_utility::ansi::k_bg_yellow, 1772 lldb_utility::ansi::k_escape_end); 1773 } 1774 else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0) 1775 { 1776 s.Printf ("%s%s%s", 1777 lldb_utility::ansi::k_escape_start, 1778 lldb_utility::ansi::k_bg_blue, 1779 lldb_utility::ansi::k_escape_end); 1780 } 1781 else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0) 1782 { 1783 s.Printf ("%s%s%s", 1784 lldb_utility::ansi::k_escape_start, 1785 lldb_utility::ansi::k_bg_purple, 1786 lldb_utility::ansi::k_escape_end); 1787 } 1788 else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0) 1789 { 1790 s.Printf ("%s%s%s", 1791 lldb_utility::ansi::k_escape_start, 1792 lldb_utility::ansi::k_bg_cyan, 1793 lldb_utility::ansi::k_escape_end); 1794 } 1795 else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0) 1796 { 1797 s.Printf ("%s%s%s", 1798 lldb_utility::ansi::k_escape_start, 1799 lldb_utility::ansi::k_bg_white, 1800 lldb_utility::ansi::k_escape_end); 1801 } 1802 else 1803 { 1804 var_success = false; 1805 } 1806 } 1807 else if (::strncmp (var_name_begin, "normal}", strlen ("normal}")) == 0) 1808 { 1809 s.Printf ("%s%s%s", 1810 lldb_utility::ansi::k_escape_start, 1811 lldb_utility::ansi::k_ctrl_normal, 1812 lldb_utility::ansi::k_escape_end); 1813 } 1814 else if (::strncmp (var_name_begin, "bold}", strlen("bold}")) == 0) 1815 { 1816 s.Printf ("%s%s%s", 1817 lldb_utility::ansi::k_escape_start, 1818 lldb_utility::ansi::k_ctrl_bold, 1819 lldb_utility::ansi::k_escape_end); 1820 } 1821 else if (::strncmp (var_name_begin, "faint}", strlen("faint}")) == 0) 1822 { 1823 s.Printf ("%s%s%s", 1824 lldb_utility::ansi::k_escape_start, 1825 lldb_utility::ansi::k_ctrl_faint, 1826 lldb_utility::ansi::k_escape_end); 1827 } 1828 else if (::strncmp (var_name_begin, "italic}", strlen("italic}")) == 0) 1829 { 1830 s.Printf ("%s%s%s", 1831 lldb_utility::ansi::k_escape_start, 1832 lldb_utility::ansi::k_ctrl_italic, 1833 lldb_utility::ansi::k_escape_end); 1834 } 1835 else if (::strncmp (var_name_begin, "underline}", strlen("underline}")) == 0) 1836 { 1837 s.Printf ("%s%s%s", 1838 lldb_utility::ansi::k_escape_start, 1839 lldb_utility::ansi::k_ctrl_underline, 1840 lldb_utility::ansi::k_escape_end); 1841 } 1842 else if (::strncmp (var_name_begin, "slow-blink}", strlen("slow-blink}")) == 0) 1843 { 1844 s.Printf ("%s%s%s", 1845 lldb_utility::ansi::k_escape_start, 1846 lldb_utility::ansi::k_ctrl_slow_blink, 1847 lldb_utility::ansi::k_escape_end); 1848 } 1849 else if (::strncmp (var_name_begin, "fast-blink}", strlen("fast-blink}")) == 0) 1850 { 1851 s.Printf ("%s%s%s", 1852 lldb_utility::ansi::k_escape_start, 1853 lldb_utility::ansi::k_ctrl_fast_blink, 1854 lldb_utility::ansi::k_escape_end); 1855 } 1856 else if (::strncmp (var_name_begin, "negative}", strlen("negative}")) == 0) 1857 { 1858 s.Printf ("%s%s%s", 1859 lldb_utility::ansi::k_escape_start, 1860 lldb_utility::ansi::k_ctrl_negative, 1861 lldb_utility::ansi::k_escape_end); 1862 } 1863 else if (::strncmp (var_name_begin, "conceal}", strlen("conceal}")) == 0) 1864 { 1865 s.Printf ("%s%s%s", 1866 lldb_utility::ansi::k_escape_start, 1867 lldb_utility::ansi::k_ctrl_conceal, 1868 lldb_utility::ansi::k_escape_end); 1869 1870 } 1871 else if (::strncmp (var_name_begin, "crossed-out}", strlen("crossed-out}")) == 0) 1872 { 1873 s.Printf ("%s%s%s", 1874 lldb_utility::ansi::k_escape_start, 1875 lldb_utility::ansi::k_ctrl_crossed_out, 1876 lldb_utility::ansi::k_escape_end); 1877 } 1878 else 1879 { 1880 var_success = false; 1881 } 1882 } 1883 break; 1884 1885 case 'p': 1886 if (::strncmp (var_name_begin, "process.", strlen("process.")) == 0) 1887 { 1888 if (exe_ctx) 1889 { 1890 Process *process = exe_ctx->GetProcessPtr(); 1891 if (process) 1892 { 1893 var_name_begin += ::strlen ("process."); 1894 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 1895 { 1896 s.Printf("%llu", process->GetID()); 1897 var_success = true; 1898 } 1899 else if ((::strncmp (var_name_begin, "name}", strlen("name}")) == 0) || 1900 (::strncmp (var_name_begin, "file.basename}", strlen("file.basename}")) == 0) || 1901 (::strncmp (var_name_begin, "file.fullpath}", strlen("file.fullpath}")) == 0)) 1902 { 1903 Module *exe_module = process->GetTarget().GetExecutableModulePointer(); 1904 if (exe_module) 1905 { 1906 if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') 1907 { 1908 format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); 1909 var_success = format_file_spec; 1910 } 1911 else 1912 { 1913 format_file_spec = exe_module->GetFileSpec(); 1914 var_success = format_file_spec; 1915 } 1916 } 1917 } 1918 } 1919 } 1920 } 1921 break; 1922 1923 case 't': 1924 if (::strncmp (var_name_begin, "thread.", strlen("thread.")) == 0) 1925 { 1926 if (exe_ctx) 1927 { 1928 Thread *thread = exe_ctx->GetThreadPtr(); 1929 if (thread) 1930 { 1931 var_name_begin += ::strlen ("thread."); 1932 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 1933 { 1934 s.Printf("0x%4.4llx", thread->GetID()); 1935 var_success = true; 1936 } 1937 else if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) 1938 { 1939 s.Printf("%u", thread->GetIndexID()); 1940 var_success = true; 1941 } 1942 else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) 1943 { 1944 cstr = thread->GetName(); 1945 var_success = cstr && cstr[0]; 1946 if (var_success) 1947 s.PutCString(cstr); 1948 } 1949 else if (::strncmp (var_name_begin, "queue}", strlen("queue}")) == 0) 1950 { 1951 cstr = thread->GetQueueName(); 1952 var_success = cstr && cstr[0]; 1953 if (var_success) 1954 s.PutCString(cstr); 1955 } 1956 else if (::strncmp (var_name_begin, "stop-reason}", strlen("stop-reason}")) == 0) 1957 { 1958 StopInfoSP stop_info_sp = thread->GetStopInfo (); 1959 if (stop_info_sp && stop_info_sp->IsValid()) 1960 { 1961 cstr = stop_info_sp->GetDescription(); 1962 if (cstr && cstr[0]) 1963 { 1964 s.PutCString(cstr); 1965 var_success = true; 1966 } 1967 } 1968 } 1969 else if (::strncmp (var_name_begin, "return-value}", strlen("return-value}")) == 0) 1970 { 1971 StopInfoSP stop_info_sp = thread->GetStopInfo (); 1972 if (stop_info_sp && stop_info_sp->IsValid()) 1973 { 1974 ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); 1975 if (return_valobj_sp) 1976 { 1977 ValueObject::DumpValueObjectOptions dump_options; 1978 ValueObject::DumpValueObject (s, return_valobj_sp.get(), dump_options); 1979 var_success = true; 1980 } 1981 } 1982 } 1983 } 1984 } 1985 } 1986 else if (::strncmp (var_name_begin, "target.", strlen("target.")) == 0) 1987 { 1988 // TODO: hookup properties 1989 // if (!target_properties_sp) 1990 // { 1991 // Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 1992 // if (target) 1993 // target_properties_sp = target->GetProperties(); 1994 // } 1995 // 1996 // if (target_properties_sp) 1997 // { 1998 // var_name_begin += ::strlen ("target."); 1999 // const char *end_property = strchr(var_name_begin, '}'); 2000 // if (end_property) 2001 // { 2002 // ConstString property_name(var_name_begin, end_property - var_name_begin); 2003 // std::string property_value (target_properties_sp->GetPropertyValue(property_name)); 2004 // if (!property_value.empty()) 2005 // { 2006 // s.PutCString (property_value.c_str()); 2007 // var_success = true; 2008 // } 2009 // } 2010 // } 2011 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2012 if (target) 2013 { 2014 var_name_begin += ::strlen ("target."); 2015 if (::strncmp (var_name_begin, "arch}", strlen("arch}")) == 0) 2016 { 2017 ArchSpec arch (target->GetArchitecture ()); 2018 if (arch.IsValid()) 2019 { 2020 s.PutCString (arch.GetArchitectureName()); 2021 var_success = true; 2022 } 2023 } 2024 } 2025 } 2026 break; 2027 2028 2029 case 'm': 2030 if (::strncmp (var_name_begin, "module.", strlen("module.")) == 0) 2031 { 2032 if (sc && sc->module_sp.get()) 2033 { 2034 Module *module = sc->module_sp.get(); 2035 var_name_begin += ::strlen ("module."); 2036 2037 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 2038 { 2039 if (module->GetFileSpec()) 2040 { 2041 var_name_begin += ::strlen ("file."); 2042 2043 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 2044 { 2045 format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); 2046 var_success = format_file_spec; 2047 } 2048 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 2049 { 2050 format_file_spec = module->GetFileSpec(); 2051 var_success = format_file_spec; 2052 } 2053 } 2054 } 2055 } 2056 } 2057 break; 2058 2059 2060 case 'f': 2061 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 2062 { 2063 if (sc && sc->comp_unit != NULL) 2064 { 2065 var_name_begin += ::strlen ("file."); 2066 2067 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 2068 { 2069 format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); 2070 var_success = format_file_spec; 2071 } 2072 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 2073 { 2074 format_file_spec = *sc->comp_unit; 2075 var_success = format_file_spec; 2076 } 2077 } 2078 } 2079 else if (::strncmp (var_name_begin, "frame.", strlen("frame.")) == 0) 2080 { 2081 if (exe_ctx) 2082 { 2083 StackFrame *frame = exe_ctx->GetFramePtr(); 2084 if (frame) 2085 { 2086 var_name_begin += ::strlen ("frame."); 2087 if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) 2088 { 2089 s.Printf("%u", frame->GetFrameIndex()); 2090 var_success = true; 2091 } 2092 else if (::strncmp (var_name_begin, "pc}", strlen("pc}")) == 0) 2093 { 2094 reg_kind = eRegisterKindGeneric; 2095 reg_num = LLDB_REGNUM_GENERIC_PC; 2096 var_success = true; 2097 } 2098 else if (::strncmp (var_name_begin, "sp}", strlen("sp}")) == 0) 2099 { 2100 reg_kind = eRegisterKindGeneric; 2101 reg_num = LLDB_REGNUM_GENERIC_SP; 2102 var_success = true; 2103 } 2104 else if (::strncmp (var_name_begin, "fp}", strlen("fp}")) == 0) 2105 { 2106 reg_kind = eRegisterKindGeneric; 2107 reg_num = LLDB_REGNUM_GENERIC_FP; 2108 var_success = true; 2109 } 2110 else if (::strncmp (var_name_begin, "flags}", strlen("flags}")) == 0) 2111 { 2112 reg_kind = eRegisterKindGeneric; 2113 reg_num = LLDB_REGNUM_GENERIC_FLAGS; 2114 var_success = true; 2115 } 2116 else if (::strncmp (var_name_begin, "reg.", strlen ("reg.")) == 0) 2117 { 2118 reg_ctx = frame->GetRegisterContext().get(); 2119 if (reg_ctx) 2120 { 2121 var_name_begin += ::strlen ("reg."); 2122 if (var_name_begin < var_name_end) 2123 { 2124 std::string reg_name (var_name_begin, var_name_end); 2125 reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); 2126 if (reg_info) 2127 var_success = true; 2128 } 2129 } 2130 } 2131 } 2132 } 2133 } 2134 else if (::strncmp (var_name_begin, "function.", strlen("function.")) == 0) 2135 { 2136 if (sc && (sc->function != NULL || sc->symbol != NULL)) 2137 { 2138 var_name_begin += ::strlen ("function."); 2139 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 2140 { 2141 if (sc->function) 2142 s.Printf("function{0x%8.8llx}", sc->function->GetID()); 2143 else 2144 s.Printf("symbol[%u]", sc->symbol->GetID()); 2145 2146 var_success = true; 2147 } 2148 else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) 2149 { 2150 if (sc->function) 2151 cstr = sc->function->GetName().AsCString (NULL); 2152 else if (sc->symbol) 2153 cstr = sc->symbol->GetName().AsCString (NULL); 2154 if (cstr) 2155 { 2156 s.PutCString(cstr); 2157 2158 if (sc->block) 2159 { 2160 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2161 if (inline_block) 2162 { 2163 const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 2164 if (inline_info) 2165 { 2166 s.PutCString(" [inlined] "); 2167 inline_info->GetName().Dump(&s); 2168 } 2169 } 2170 } 2171 var_success = true; 2172 } 2173 } 2174 else if (::strncmp (var_name_begin, "name-with-args}", strlen("name-with-args}")) == 0) 2175 { 2176 // Print the function name with arguments in it 2177 2178 if (sc->function) 2179 { 2180 var_success = true; 2181 ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; 2182 cstr = sc->function->GetName().AsCString (NULL); 2183 if (cstr) 2184 { 2185 const InlineFunctionInfo *inline_info = NULL; 2186 VariableListSP variable_list_sp; 2187 bool get_function_vars = true; 2188 if (sc->block) 2189 { 2190 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2191 2192 if (inline_block) 2193 { 2194 get_function_vars = false; 2195 inline_info = sc->block->GetInlinedFunctionInfo(); 2196 if (inline_info) 2197 variable_list_sp = inline_block->GetBlockVariableList (true); 2198 } 2199 } 2200 2201 if (get_function_vars) 2202 { 2203 variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); 2204 } 2205 2206 if (inline_info) 2207 { 2208 s.PutCString (cstr); 2209 s.PutCString (" [inlined] "); 2210 cstr = inline_info->GetName().GetCString(); 2211 } 2212 2213 VariableList args; 2214 if (variable_list_sp) 2215 { 2216 const size_t num_variables = variable_list_sp->GetSize(); 2217 for (size_t var_idx = 0; var_idx < num_variables; ++var_idx) 2218 { 2219 VariableSP var_sp (variable_list_sp->GetVariableAtIndex(var_idx)); 2220 if (var_sp->GetScope() == eValueTypeVariableArgument) 2221 args.AddVariable (var_sp); 2222 } 2223 2224 } 2225 if (args.GetSize() > 0) 2226 { 2227 const char *open_paren = strchr (cstr, '('); 2228 const char *close_paren = NULL; 2229 if (open_paren) 2230 close_paren = strchr (open_paren, ')'); 2231 2232 if (open_paren) 2233 s.Write(cstr, open_paren - cstr + 1); 2234 else 2235 { 2236 s.PutCString (cstr); 2237 s.PutChar ('('); 2238 } 2239 const size_t num_args = args.GetSize(); 2240 for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) 2241 { 2242 VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); 2243 ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); 2244 const char *var_name = var_value_sp->GetName().GetCString(); 2245 const char *var_value = var_value_sp->GetValueAsCString(); 2246 if (var_value_sp->GetError().Success()) 2247 { 2248 if (arg_idx > 0) 2249 s.PutCString (", "); 2250 s.Printf ("%s=%s", var_name, var_value); 2251 } 2252 } 2253 2254 if (close_paren) 2255 s.PutCString (close_paren); 2256 else 2257 s.PutChar(')'); 2258 2259 } 2260 else 2261 { 2262 s.PutCString(cstr); 2263 } 2264 } 2265 } 2266 else if (sc->symbol) 2267 { 2268 cstr = sc->symbol->GetName().AsCString (NULL); 2269 if (cstr) 2270 { 2271 s.PutCString(cstr); 2272 var_success = true; 2273 } 2274 } 2275 } 2276 else if (::strncmp (var_name_begin, "addr-offset}", strlen("addr-offset}")) == 0) 2277 { 2278 var_success = addr != NULL; 2279 if (var_success) 2280 { 2281 format_addr = *addr; 2282 calculate_format_addr_function_offset = true; 2283 } 2284 } 2285 else if (::strncmp (var_name_begin, "line-offset}", strlen("line-offset}")) == 0) 2286 { 2287 var_success = sc->line_entry.range.GetBaseAddress().IsValid(); 2288 if (var_success) 2289 { 2290 format_addr = sc->line_entry.range.GetBaseAddress(); 2291 calculate_format_addr_function_offset = true; 2292 } 2293 } 2294 else if (::strncmp (var_name_begin, "pc-offset}", strlen("pc-offset}")) == 0) 2295 { 2296 StackFrame *frame = exe_ctx->GetFramePtr(); 2297 var_success = frame != NULL; 2298 if (var_success) 2299 { 2300 format_addr = frame->GetFrameCodeAddress(); 2301 calculate_format_addr_function_offset = true; 2302 } 2303 } 2304 } 2305 } 2306 break; 2307 2308 case 'l': 2309 if (::strncmp (var_name_begin, "line.", strlen("line.")) == 0) 2310 { 2311 if (sc && sc->line_entry.IsValid()) 2312 { 2313 var_name_begin += ::strlen ("line."); 2314 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 2315 { 2316 var_name_begin += ::strlen ("file."); 2317 2318 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 2319 { 2320 format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); 2321 var_success = format_file_spec; 2322 } 2323 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 2324 { 2325 format_file_spec = sc->line_entry.file; 2326 var_success = format_file_spec; 2327 } 2328 } 2329 else if (::strncmp (var_name_begin, "number}", strlen("number}")) == 0) 2330 { 2331 var_success = true; 2332 s.Printf("%u", sc->line_entry.line); 2333 } 2334 else if ((::strncmp (var_name_begin, "start-addr}", strlen("start-addr}")) == 0) || 2335 (::strncmp (var_name_begin, "end-addr}", strlen("end-addr}")) == 0)) 2336 { 2337 var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); 2338 if (var_success) 2339 { 2340 format_addr = sc->line_entry.range.GetBaseAddress(); 2341 if (var_name_begin[0] == 'e') 2342 format_addr.Slide (sc->line_entry.range.GetByteSize()); 2343 } 2344 } 2345 } 2346 } 2347 break; 2348 } 2349 2350 if (var_success) 2351 { 2352 // If format addr is valid, then we need to print an address 2353 if (reg_num != LLDB_INVALID_REGNUM) 2354 { 2355 StackFrame *frame = exe_ctx->GetFramePtr(); 2356 // We have a register value to display... 2357 if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) 2358 { 2359 format_addr = frame->GetFrameCodeAddress(); 2360 } 2361 else 2362 { 2363 if (reg_ctx == NULL) 2364 reg_ctx = frame->GetRegisterContext().get(); 2365 2366 if (reg_ctx) 2367 { 2368 if (reg_kind != kNumRegisterKinds) 2369 reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 2370 reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); 2371 var_success = reg_info != NULL; 2372 } 2373 } 2374 } 2375 2376 if (reg_info != NULL) 2377 { 2378 RegisterValue reg_value; 2379 var_success = reg_ctx->ReadRegister (reg_info, reg_value); 2380 if (var_success) 2381 { 2382 reg_value.Dump(&s, reg_info, false, false, eFormatDefault); 2383 } 2384 } 2385 2386 if (format_file_spec) 2387 { 2388 s << format_file_spec; 2389 } 2390 2391 // If format addr is valid, then we need to print an address 2392 if (format_addr.IsValid()) 2393 { 2394 var_success = false; 2395 2396 if (calculate_format_addr_function_offset) 2397 { 2398 Address func_addr; 2399 2400 if (sc) 2401 { 2402 if (sc->function) 2403 { 2404 func_addr = sc->function->GetAddressRange().GetBaseAddress(); 2405 if (sc->block) 2406 { 2407 // Check to make sure we aren't in an inline 2408 // function. If we are, use the inline block 2409 // range that contains "format_addr" since 2410 // blocks can be discontiguous. 2411 Block *inline_block = sc->block->GetContainingInlinedBlock (); 2412 AddressRange inline_range; 2413 if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 2414 func_addr = inline_range.GetBaseAddress(); 2415 } 2416 } 2417 else if (sc->symbol && sc->symbol->ValueIsAddress()) 2418 func_addr = sc->symbol->GetAddress(); 2419 } 2420 2421 if (func_addr.IsValid()) 2422 { 2423 if (func_addr.GetSection() == format_addr.GetSection()) 2424 { 2425 addr_t func_file_addr = func_addr.GetFileAddress(); 2426 addr_t addr_file_addr = format_addr.GetFileAddress(); 2427 if (addr_file_addr > func_file_addr) 2428 s.Printf(" + %llu", addr_file_addr - func_file_addr); 2429 else if (addr_file_addr < func_file_addr) 2430 s.Printf(" - %llu", func_file_addr - addr_file_addr); 2431 var_success = true; 2432 } 2433 else 2434 { 2435 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2436 if (target) 2437 { 2438 addr_t func_load_addr = func_addr.GetLoadAddress (target); 2439 addr_t addr_load_addr = format_addr.GetLoadAddress (target); 2440 if (addr_load_addr > func_load_addr) 2441 s.Printf(" + %llu", addr_load_addr - func_load_addr); 2442 else if (addr_load_addr < func_load_addr) 2443 s.Printf(" - %llu", func_load_addr - addr_load_addr); 2444 var_success = true; 2445 } 2446 } 2447 } 2448 } 2449 else 2450 { 2451 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 2452 addr_t vaddr = LLDB_INVALID_ADDRESS; 2453 if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 2454 vaddr = format_addr.GetLoadAddress (target); 2455 if (vaddr == LLDB_INVALID_ADDRESS) 2456 vaddr = format_addr.GetFileAddress (); 2457 2458 if (vaddr != LLDB_INVALID_ADDRESS) 2459 { 2460 int addr_width = target->GetArchitecture().GetAddressByteSize() * 2; 2461 if (addr_width == 0) 2462 addr_width = 16; 2463 s.Printf("0x%*.*llx", addr_width, addr_width, vaddr); 2464 var_success = true; 2465 } 2466 } 2467 } 2468 } 2469 2470 if (var_success == false) 2471 success = false; 2472 } 2473 p = var_name_end; 2474 } 2475 else 2476 break; 2477 } 2478 else 2479 { 2480 // We got a dollar sign with no '{' after it, it must just be a dollar sign 2481 s.PutChar(*p); 2482 } 2483 } 2484 else if (*p == '\\') 2485 { 2486 ++p; // skip the slash 2487 switch (*p) 2488 { 2489 case 'a': s.PutChar ('\a'); break; 2490 case 'b': s.PutChar ('\b'); break; 2491 case 'f': s.PutChar ('\f'); break; 2492 case 'n': s.PutChar ('\n'); break; 2493 case 'r': s.PutChar ('\r'); break; 2494 case 't': s.PutChar ('\t'); break; 2495 case 'v': s.PutChar ('\v'); break; 2496 case '\'': s.PutChar ('\''); break; 2497 case '\\': s.PutChar ('\\'); break; 2498 case '0': 2499 // 1 to 3 octal chars 2500 { 2501 // Make a string that can hold onto the initial zero char, 2502 // up to 3 octal digits, and a terminating NULL. 2503 char oct_str[5] = { 0, 0, 0, 0, 0 }; 2504 2505 int i; 2506 for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) 2507 oct_str[i] = p[i]; 2508 2509 // We don't want to consume the last octal character since 2510 // the main for loop will do this for us, so we advance p by 2511 // one less than i (even if i is zero) 2512 p += i - 1; 2513 unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 2514 if (octal_value <= UINT8_MAX) 2515 { 2516 char octal_char = octal_value; 2517 s.Write (&octal_char, 1); 2518 } 2519 } 2520 break; 2521 2522 case 'x': 2523 // hex number in the format 2524 if (isxdigit(p[1])) 2525 { 2526 ++p; // Skip the 'x' 2527 2528 // Make a string that can hold onto two hex chars plus a 2529 // NULL terminator 2530 char hex_str[3] = { 0,0,0 }; 2531 hex_str[0] = *p; 2532 if (isxdigit(p[1])) 2533 { 2534 ++p; // Skip the first of the two hex chars 2535 hex_str[1] = *p; 2536 } 2537 2538 unsigned long hex_value = strtoul (hex_str, NULL, 16); 2539 if (hex_value <= UINT8_MAX) 2540 s.PutChar (hex_value); 2541 } 2542 else 2543 { 2544 s.PutChar('x'); 2545 } 2546 break; 2547 2548 default: 2549 // Just desensitize any other character by just printing what 2550 // came after the '\' 2551 s << *p; 2552 break; 2553 2554 } 2555 2556 } 2557 } 2558 if (end) 2559 *end = p; 2560 return success; 2561 } 2562 2563 void 2564 Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) 2565 { 2566 // For simplicity's sake, I am not going to deal with how to close down any 2567 // open logging streams, I just redirect everything from here on out to the 2568 // callback. 2569 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); 2570 } 2571 2572 bool 2573 Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream) 2574 { 2575 Log::Callbacks log_callbacks; 2576 2577 StreamSP log_stream_sp; 2578 if (m_log_callback_stream_sp) 2579 { 2580 log_stream_sp = m_log_callback_stream_sp; 2581 // For now when using the callback mode you always get thread & timestamp. 2582 log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 2583 } 2584 else if (log_file == NULL || *log_file == '\0') 2585 { 2586 log_stream_sp.reset(new StreamFile(GetOutputFile().GetDescriptor(), false)); 2587 } 2588 else 2589 { 2590 LogStreamMap::iterator pos = m_log_streams.find(log_file); 2591 if (pos == m_log_streams.end()) 2592 { 2593 log_stream_sp.reset (new StreamFile (log_file)); 2594 m_log_streams[log_file] = log_stream_sp; 2595 } 2596 else 2597 log_stream_sp = pos->second; 2598 } 2599 assert (log_stream_sp.get()); 2600 2601 if (log_options == 0) 2602 log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 2603 2604 if (Log::GetLogChannelCallbacks (channel, log_callbacks)) 2605 { 2606 log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream); 2607 return true; 2608 } 2609 else 2610 { 2611 LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel)); 2612 if (log_channel_sp) 2613 { 2614 if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories)) 2615 { 2616 return true; 2617 } 2618 else 2619 { 2620 error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2621 return false; 2622 } 2623 } 2624 else 2625 { 2626 error_stream.Printf ("Invalid log channel '%s'.\n", channel); 2627 return false; 2628 } 2629 } 2630 return false; 2631 } 2632 2633