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