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