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/lldb-private.h" 11 #include "lldb/Core/ConnectionFileDescriptor.h" 12 #include "lldb/Core/Debugger.h" 13 #include "lldb/Core/InputReader.h" 14 #include "lldb/Core/State.h" 15 #include "lldb/Core/StreamString.h" 16 #include "lldb/Core/Timer.h" 17 #include "lldb/Interpreter/CommandInterpreter.h" 18 #include "lldb/Target/TargetList.h" 19 #include "lldb/Target/Process.h" 20 #include "lldb/Target/RegisterContext.h" 21 #include "lldb/Target/StopInfo.h" 22 #include "lldb/Target/Thread.h" 23 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 29 static uint32_t g_shared_debugger_refcount = 0; 30 static lldb::user_id_t g_unique_id = 1; 31 32 #pragma mark Static Functions 33 34 static Mutex & 35 GetDebuggerListMutex () 36 { 37 static Mutex g_mutex(Mutex::eMutexTypeRecursive); 38 return g_mutex; 39 } 40 41 typedef std::vector<DebuggerSP> DebuggerList; 42 43 static DebuggerList & 44 GetDebuggerList() 45 { 46 // hide the static debugger list inside a singleton accessor to avoid 47 // global init contructors 48 static DebuggerList g_list; 49 return g_list; 50 } 51 52 53 #pragma mark Debugger 54 55 UserSettingsControllerSP & 56 Debugger::GetSettingsController () 57 { 58 static UserSettingsControllerSP g_settings_controller; 59 return g_settings_controller; 60 } 61 62 int 63 Debugger::TestDebuggerRefCount () 64 { 65 return g_shared_debugger_refcount; 66 } 67 68 void 69 Debugger::Initialize () 70 { 71 if (g_shared_debugger_refcount == 0) 72 { 73 UserSettingsControllerSP &usc = GetSettingsController(); 74 usc.reset (new SettingsController); 75 UserSettingsController::InitializeSettingsController (usc, 76 SettingsController::global_settings_table, 77 SettingsController::instance_settings_table); 78 lldb_private::Initialize(); 79 } 80 g_shared_debugger_refcount++; 81 82 } 83 84 void 85 Debugger::Terminate () 86 { 87 if (g_shared_debugger_refcount > 0) 88 { 89 g_shared_debugger_refcount--; 90 if (g_shared_debugger_refcount == 0) 91 { 92 lldb_private::WillTerminate(); 93 lldb_private::Terminate(); 94 UserSettingsControllerSP &usc = GetSettingsController(); 95 UserSettingsController::FinalizeSettingsController (usc); 96 usc.reset(); 97 98 // Clear our master list of debugger objects 99 Mutex::Locker locker (GetDebuggerListMutex ()); 100 GetDebuggerList().clear(); 101 } 102 } 103 } 104 105 DebuggerSP 106 Debugger::CreateInstance () 107 { 108 DebuggerSP debugger_sp (new Debugger); 109 // Scope for locker 110 { 111 Mutex::Locker locker (GetDebuggerListMutex ()); 112 GetDebuggerList().push_back(debugger_sp); 113 } 114 return debugger_sp; 115 } 116 117 void 118 Debugger::Destroy (lldb::DebuggerSP &debugger_sp) 119 { 120 if (debugger_sp.get() == NULL) 121 return; 122 123 Mutex::Locker locker (GetDebuggerListMutex ()); 124 DebuggerList &debugger_list = GetDebuggerList (); 125 DebuggerList::iterator pos, end = debugger_list.end(); 126 for (pos = debugger_list.begin (); pos != end; ++pos) 127 { 128 if ((*pos).get() == debugger_sp.get()) 129 { 130 debugger_list.erase (pos); 131 return; 132 } 133 } 134 135 } 136 137 lldb::DebuggerSP 138 Debugger::GetSP () 139 { 140 lldb::DebuggerSP debugger_sp; 141 142 Mutex::Locker locker (GetDebuggerListMutex ()); 143 DebuggerList &debugger_list = GetDebuggerList(); 144 DebuggerList::iterator pos, end = debugger_list.end(); 145 for (pos = debugger_list.begin(); pos != end; ++pos) 146 { 147 if ((*pos).get() == this) 148 { 149 debugger_sp = *pos; 150 break; 151 } 152 } 153 return debugger_sp; 154 } 155 156 lldb::DebuggerSP 157 Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name) 158 { 159 lldb::DebuggerSP debugger_sp; 160 161 Mutex::Locker locker (GetDebuggerListMutex ()); 162 DebuggerList &debugger_list = GetDebuggerList(); 163 DebuggerList::iterator pos, end = debugger_list.end(); 164 165 for (pos = debugger_list.begin(); pos != end; ++pos) 166 { 167 if ((*pos).get()->m_instance_name == instance_name) 168 { 169 debugger_sp = *pos; 170 break; 171 } 172 } 173 return debugger_sp; 174 } 175 176 TargetSP 177 Debugger::FindTargetWithProcessID (lldb::pid_t pid) 178 { 179 lldb::TargetSP target_sp; 180 Mutex::Locker locker (GetDebuggerListMutex ()); 181 DebuggerList &debugger_list = GetDebuggerList(); 182 DebuggerList::iterator pos, end = debugger_list.end(); 183 for (pos = debugger_list.begin(); pos != end; ++pos) 184 { 185 target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid); 186 if (target_sp) 187 break; 188 } 189 return target_sp; 190 } 191 192 193 Debugger::Debugger () : 194 UserID (g_unique_id++), 195 DebuggerInstanceSettings (*GetSettingsController()), 196 m_input_comm("debugger.input"), 197 m_input_file (), 198 m_output_file (), 199 m_error_file (), 200 m_target_list (), 201 m_listener ("lldb.Debugger"), 202 m_source_manager (), 203 m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)), 204 m_exe_ctx (), 205 m_input_readers (), 206 m_input_reader_data () 207 { 208 m_input_comm.SetCloseOnEOF(false); 209 m_command_interpreter_ap->Initialize (); 210 } 211 212 Debugger::~Debugger () 213 { 214 CleanUpInputReaders(); 215 int num_targets = m_target_list.GetNumTargets(); 216 for (int i = 0; i < num_targets; i++) 217 { 218 ProcessSP process_sp (m_target_list.GetTargetAtIndex (i)->GetProcessSP()); 219 if (process_sp) 220 process_sp->Destroy(); 221 } 222 DisconnectInput(); 223 } 224 225 226 bool 227 Debugger::GetAsyncExecution () 228 { 229 return !m_command_interpreter_ap->GetSynchronous(); 230 } 231 232 void 233 Debugger::SetAsyncExecution (bool async_execution) 234 { 235 m_command_interpreter_ap->SetSynchronous (!async_execution); 236 } 237 238 void 239 Debugger::DisconnectInput() 240 { 241 m_input_comm.Clear (); 242 } 243 244 void 245 Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) 246 { 247 m_input_file.SetFileHandle (fh, tranfer_ownership); 248 if (m_input_file.GetFileHandle() == NULL) 249 m_input_file.SetFileHandle (stdin, false); 250 251 // Disconnect from any old connection if we had one 252 m_input_comm.Disconnect (); 253 m_input_comm.SetConnection (new ConnectionFileDescriptor (::fileno (GetInputFileHandle()), true)); 254 m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this); 255 256 Error error; 257 if (m_input_comm.StartReadThread (&error) == false) 258 { 259 FILE *err_fh = GetErrorFileHandle(); 260 if (err_fh) 261 { 262 ::fprintf (err_fh, "error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error"); 263 exit(1); 264 } 265 } 266 267 } 268 269 FILE * 270 Debugger::GetInputFileHandle () 271 { 272 return m_input_file.GetFileHandle(); 273 } 274 275 276 void 277 Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership) 278 { 279 m_output_file.SetFileHandle (fh, tranfer_ownership); 280 if (m_output_file.GetFileHandle() == NULL) 281 m_output_file.SetFileHandle (stdin, false); 282 283 GetCommandInterpreter().GetScriptInterpreter()->ResetOutputFileHandle (fh); 284 } 285 286 FILE * 287 Debugger::GetOutputFileHandle () 288 { 289 return m_output_file.GetFileHandle(); 290 } 291 292 void 293 Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) 294 { 295 m_error_file.SetFileHandle (fh, tranfer_ownership); 296 if (m_error_file.GetFileHandle() == NULL) 297 m_error_file.SetFileHandle (stdin, false); 298 } 299 300 301 FILE * 302 Debugger::GetErrorFileHandle () 303 { 304 return m_error_file.GetFileHandle(); 305 } 306 307 CommandInterpreter & 308 Debugger::GetCommandInterpreter () 309 { 310 assert (m_command_interpreter_ap.get()); 311 return *m_command_interpreter_ap; 312 } 313 314 Listener & 315 Debugger::GetListener () 316 { 317 return m_listener; 318 } 319 320 321 TargetSP 322 Debugger::GetSelectedTarget () 323 { 324 return m_target_list.GetSelectedTarget (); 325 } 326 327 ExecutionContext 328 Debugger::GetSelectedExecutionContext () 329 { 330 ExecutionContext exe_ctx; 331 exe_ctx.Clear(); 332 333 lldb::TargetSP target_sp = GetSelectedTarget(); 334 exe_ctx.target = target_sp.get(); 335 336 if (target_sp) 337 { 338 exe_ctx.process = target_sp->GetProcessSP().get(); 339 if (exe_ctx.process && exe_ctx.process->IsRunning() == false) 340 { 341 exe_ctx.thread = exe_ctx.process->GetThreadList().GetSelectedThread().get(); 342 if (exe_ctx.thread == NULL) 343 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 344 if (exe_ctx.thread) 345 { 346 exe_ctx.frame = exe_ctx.thread->GetSelectedFrame().get(); 347 if (exe_ctx.frame == NULL) 348 exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex (0).get(); 349 } 350 } 351 } 352 return exe_ctx; 353 354 } 355 356 SourceManager & 357 Debugger::GetSourceManager () 358 { 359 return m_source_manager; 360 } 361 362 363 TargetList& 364 Debugger::GetTargetList () 365 { 366 return m_target_list; 367 } 368 369 void 370 Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len) 371 { 372 if (bytes_len > 0) 373 ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len); 374 else 375 ((Debugger *)baton)->DispatchInputEndOfFile (); 376 } 377 378 379 void 380 Debugger::DispatchInput (const char *bytes, size_t bytes_len) 381 { 382 if (bytes == NULL || bytes_len == 0) 383 return; 384 385 WriteToDefaultReader (bytes, bytes_len); 386 } 387 388 void 389 Debugger::DispatchInputInterrupt () 390 { 391 m_input_reader_data.clear(); 392 393 if (!m_input_readers.empty()) 394 { 395 while (CheckIfTopInputReaderIsDone ()) ; 396 397 InputReaderSP reader_sp(m_input_readers.top()); 398 if (reader_sp) 399 reader_sp->Notify (eInputReaderInterrupt); 400 401 while (CheckIfTopInputReaderIsDone ()) ; 402 } 403 } 404 405 void 406 Debugger::DispatchInputEndOfFile () 407 { 408 m_input_reader_data.clear(); 409 410 if (!m_input_readers.empty()) 411 { 412 while (CheckIfTopInputReaderIsDone ()) ; 413 414 InputReaderSP reader_sp(m_input_readers.top()); 415 if (reader_sp) 416 reader_sp->Notify (eInputReaderEndOfFile); 417 418 while (CheckIfTopInputReaderIsDone ()) ; 419 } 420 } 421 422 void 423 Debugger::CleanUpInputReaders () 424 { 425 m_input_reader_data.clear(); 426 427 while (m_input_readers.size() > 1) 428 { 429 while (CheckIfTopInputReaderIsDone ()) ; 430 431 InputReaderSP reader_sp (m_input_readers.top()); 432 if (reader_sp) 433 { 434 reader_sp->Notify (eInputReaderEndOfFile); 435 reader_sp->SetIsDone (true); 436 } 437 } 438 } 439 440 void 441 Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len) 442 { 443 if (bytes && bytes_len) 444 m_input_reader_data.append (bytes, bytes_len); 445 446 if (m_input_reader_data.empty()) 447 return; 448 449 while (!m_input_readers.empty() && !m_input_reader_data.empty()) 450 { 451 while (CheckIfTopInputReaderIsDone ()) 452 /* Do nothing. */; 453 454 // Get the input reader from the top of the stack 455 InputReaderSP reader_sp(m_input_readers.top()); 456 457 if (!reader_sp) 458 break; 459 460 size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(), 461 m_input_reader_data.size()); 462 if (bytes_handled) 463 { 464 m_input_reader_data.erase (0, bytes_handled); 465 } 466 else 467 { 468 // No bytes were handled, we might not have reached our 469 // granularity, just return and wait for more data 470 break; 471 } 472 } 473 474 // Flush out any input readers that are donesvn 475 while (CheckIfTopInputReaderIsDone ()) 476 /* Do nothing. */; 477 478 } 479 480 void 481 Debugger::PushInputReader (const InputReaderSP& reader_sp) 482 { 483 if (!reader_sp) 484 return; 485 if (!m_input_readers.empty()) 486 { 487 // Deactivate the old top reader 488 InputReaderSP top_reader_sp (m_input_readers.top()); 489 if (top_reader_sp) 490 top_reader_sp->Notify (eInputReaderDeactivate); 491 } 492 m_input_readers.push (reader_sp); 493 reader_sp->Notify (eInputReaderActivate); 494 ActivateInputReader (reader_sp); 495 } 496 497 bool 498 Debugger::PopInputReader (const lldb::InputReaderSP& pop_reader_sp) 499 { 500 bool result = false; 501 502 // The reader on the stop of the stack is done, so let the next 503 // read on the stack referesh its prompt and if there is one... 504 if (!m_input_readers.empty()) 505 { 506 InputReaderSP reader_sp(m_input_readers.top()); 507 508 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get()) 509 { 510 m_input_readers.pop (); 511 reader_sp->Notify (eInputReaderDeactivate); 512 reader_sp->Notify (eInputReaderDone); 513 result = true; 514 515 if (!m_input_readers.empty()) 516 { 517 reader_sp = m_input_readers.top(); 518 if (reader_sp) 519 { 520 ActivateInputReader (reader_sp); 521 reader_sp->Notify (eInputReaderReactivate); 522 } 523 } 524 } 525 } 526 return result; 527 } 528 529 bool 530 Debugger::CheckIfTopInputReaderIsDone () 531 { 532 bool result = false; 533 if (!m_input_readers.empty()) 534 { 535 InputReaderSP reader_sp(m_input_readers.top()); 536 537 if (reader_sp && reader_sp->IsDone()) 538 { 539 result = true; 540 PopInputReader (reader_sp); 541 } 542 } 543 return result; 544 } 545 546 void 547 Debugger::ActivateInputReader (const InputReaderSP &reader_sp) 548 { 549 FILE *in_fh = GetInputFileHandle(); 550 551 if (in_fh) 552 { 553 struct termios in_fh_termios; 554 int in_fd = fileno (in_fh); 555 if (::tcgetattr(in_fd, &in_fh_termios) == 0) 556 { 557 if (reader_sp->GetEcho()) 558 in_fh_termios.c_lflag |= ECHO; // Turn on echoing 559 else 560 in_fh_termios.c_lflag &= ~ECHO; // Turn off echoing 561 562 switch (reader_sp->GetGranularity()) 563 { 564 case eInputReaderGranularityByte: 565 case eInputReaderGranularityWord: 566 in_fh_termios.c_lflag &= ~ICANON; // Get one char at a time 567 break; 568 569 case eInputReaderGranularityLine: 570 case eInputReaderGranularityAll: 571 in_fh_termios.c_lflag |= ICANON; // Get lines at a time 572 break; 573 574 default: 575 break; 576 } 577 ::tcsetattr (in_fd, TCSANOW, &in_fh_termios); 578 } 579 } 580 } 581 582 void 583 Debugger::UpdateExecutionContext (ExecutionContext *override_context) 584 { 585 m_exe_ctx.Clear(); 586 587 if (override_context != NULL) 588 { 589 m_exe_ctx.target = override_context->target; 590 m_exe_ctx.process = override_context->process; 591 m_exe_ctx.thread = override_context->thread; 592 m_exe_ctx.frame = override_context->frame; 593 } 594 else 595 { 596 TargetSP target_sp (GetSelectedTarget()); 597 if (target_sp) 598 { 599 m_exe_ctx.target = target_sp.get(); 600 m_exe_ctx.process = target_sp->GetProcessSP().get(); 601 if (m_exe_ctx.process && m_exe_ctx.process->IsAlive() && !m_exe_ctx.process->IsRunning()) 602 { 603 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetSelectedThread().get(); 604 if (m_exe_ctx.thread == NULL) 605 { 606 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 607 // If we didn't have a selected thread, select one here. 608 if (m_exe_ctx.thread != NULL) 609 m_exe_ctx.process->GetThreadList().SetSelectedThreadByID(m_exe_ctx.thread->GetID()); 610 } 611 if (m_exe_ctx.thread) 612 { 613 m_exe_ctx.frame = m_exe_ctx.thread->GetSelectedFrame().get(); 614 if (m_exe_ctx.frame == NULL) 615 { 616 m_exe_ctx.frame = m_exe_ctx.thread->GetStackFrameAtIndex (0).get(); 617 // If we didn't have a selected frame select one here. 618 if (m_exe_ctx.frame != NULL) 619 m_exe_ctx.thread->SetSelectedFrame(m_exe_ctx.frame); 620 } 621 } 622 } 623 } 624 } 625 } 626 627 DebuggerSP 628 Debugger::FindDebuggerWithID (lldb::user_id_t id) 629 { 630 lldb::DebuggerSP debugger_sp; 631 632 Mutex::Locker locker (GetDebuggerListMutex ()); 633 DebuggerList &debugger_list = GetDebuggerList(); 634 DebuggerList::iterator pos, end = debugger_list.end(); 635 for (pos = debugger_list.begin(); pos != end; ++pos) 636 { 637 if ((*pos).get()->GetID() == id) 638 { 639 debugger_sp = *pos; 640 break; 641 } 642 } 643 return debugger_sp; 644 } 645 646 static void 647 TestPromptFormats (StackFrame *frame) 648 { 649 if (frame == NULL) 650 return; 651 652 StreamString s; 653 const char *prompt_format = 654 "{addr = '${addr}'\n}" 655 "{process.id = '${process.id}'\n}" 656 "{process.name = '${process.name}'\n}" 657 "{process.file.basename = '${process.file.basename}'\n}" 658 "{process.file.fullpath = '${process.file.fullpath}'\n}" 659 "{thread.id = '${thread.id}'\n}" 660 "{thread.index = '${thread.index}'\n}" 661 "{thread.name = '${thread.name}'\n}" 662 "{thread.queue = '${thread.queue}'\n}" 663 "{thread.stop-reason = '${thread.stop-reason}'\n}" 664 "{target.arch = '${target.arch}'\n}" 665 "{module.file.basename = '${module.file.basename}'\n}" 666 "{module.file.fullpath = '${module.file.fullpath}'\n}" 667 "{file.basename = '${file.basename}'\n}" 668 "{file.fullpath = '${file.fullpath}'\n}" 669 "{frame.index = '${frame.index}'\n}" 670 "{frame.pc = '${frame.pc}'\n}" 671 "{frame.sp = '${frame.sp}'\n}" 672 "{frame.fp = '${frame.fp}'\n}" 673 "{frame.flags = '${frame.flags}'\n}" 674 "{frame.reg.rdi = '${frame.reg.rdi}'\n}" 675 "{frame.reg.rip = '${frame.reg.rip}'\n}" 676 "{frame.reg.rsp = '${frame.reg.rsp}'\n}" 677 "{frame.reg.rbp = '${frame.reg.rbp}'\n}" 678 "{frame.reg.rflags = '${frame.reg.rflags}'\n}" 679 "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}" 680 "{frame.reg.carp = '${frame.reg.carp}'\n}" 681 "{function.id = '${function.id}'\n}" 682 "{function.name = '${function.name}'\n}" 683 "{function.addr-offset = '${function.addr-offset}'\n}" 684 "{function.line-offset = '${function.line-offset}'\n}" 685 "{function.pc-offset = '${function.pc-offset}'\n}" 686 "{line.file.basename = '${line.file.basename}'\n}" 687 "{line.file.fullpath = '${line.file.fullpath}'\n}" 688 "{line.number = '${line.number}'\n}" 689 "{line.start-addr = '${line.start-addr}'\n}" 690 "{line.end-addr = '${line.end-addr}'\n}" 691 ; 692 693 SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything)); 694 ExecutionContext exe_ctx; 695 frame->CalculateExecutionContext(exe_ctx); 696 const char *end = NULL; 697 if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, &end)) 698 { 699 printf("%s\n", s.GetData()); 700 } 701 else 702 { 703 printf ("error: at '%s'\n", end); 704 printf ("what we got: %s\n", s.GetData()); 705 } 706 } 707 708 bool 709 Debugger::FormatPrompt 710 ( 711 const char *format, 712 const SymbolContext *sc, 713 const ExecutionContext *exe_ctx, 714 const Address *addr, 715 Stream &s, 716 const char **end 717 ) 718 { 719 bool success = true; 720 const char *p; 721 for (p = format; *p != '\0'; ++p) 722 { 723 size_t non_special_chars = ::strcspn (p, "${}\\"); 724 if (non_special_chars > 0) 725 { 726 if (success) 727 s.Write (p, non_special_chars); 728 p += non_special_chars; 729 } 730 731 if (*p == '\0') 732 { 733 break; 734 } 735 else if (*p == '{') 736 { 737 // Start a new scope that must have everything it needs if it is to 738 // to make it into the final output stream "s". If you want to make 739 // a format that only prints out the function or symbol name if there 740 // is one in the symbol context you can use: 741 // "{function =${function.name}}" 742 // The first '{' starts a new scope that end with the matching '}' at 743 // the end of the string. The contents "function =${function.name}" 744 // will then be evaluated and only be output if there is a function 745 // or symbol with a valid name. 746 StreamString sub_strm; 747 748 ++p; // Skip the '{' 749 750 if (FormatPrompt (p, sc, exe_ctx, addr, sub_strm, &p)) 751 { 752 // The stream had all it needed 753 s.Write(sub_strm.GetData(), sub_strm.GetSize()); 754 } 755 if (*p != '}') 756 { 757 success = false; 758 break; 759 } 760 } 761 else if (*p == '}') 762 { 763 // End of a enclosing scope 764 break; 765 } 766 else if (*p == '$') 767 { 768 // We have a prompt variable to print 769 ++p; 770 if (*p == '{') 771 { 772 ++p; 773 const char *var_name_begin = p; 774 const char *var_name_end = ::strchr (p, '}'); 775 776 if (var_name_end && var_name_begin < var_name_end) 777 { 778 // if we have already failed to parse, skip this variable 779 if (success) 780 { 781 const char *cstr = NULL; 782 Address format_addr; 783 bool calculate_format_addr_function_offset = false; 784 // Set reg_kind and reg_num to invalid values 785 RegisterKind reg_kind = kNumRegisterKinds; 786 uint32_t reg_num = LLDB_INVALID_REGNUM; 787 FileSpec format_file_spec; 788 const lldb::RegisterInfo *reg_info = NULL; 789 RegisterContext *reg_ctx = NULL; 790 791 // Each variable must set success to true below... 792 bool var_success = false; 793 switch (var_name_begin[0]) 794 { 795 case 'a': 796 if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0) 797 { 798 if (addr && addr->IsValid()) 799 { 800 var_success = true; 801 format_addr = *addr; 802 } 803 } 804 break; 805 806 case 'p': 807 if (::strncmp (var_name_begin, "process.", strlen("process.")) == 0) 808 { 809 if (exe_ctx && exe_ctx->process != NULL) 810 { 811 var_name_begin += ::strlen ("process."); 812 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 813 { 814 s.Printf("%i", exe_ctx->process->GetID()); 815 var_success = true; 816 } 817 else if ((::strncmp (var_name_begin, "name}", strlen("name}")) == 0) || 818 (::strncmp (var_name_begin, "file.basename}", strlen("file.basename}")) == 0) || 819 (::strncmp (var_name_begin, "file.fullpath}", strlen("file.fullpath}")) == 0)) 820 { 821 ModuleSP exe_module_sp (exe_ctx->process->GetTarget().GetExecutableModule()); 822 if (exe_module_sp) 823 { 824 if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') 825 { 826 format_file_spec.GetFilename() = exe_module_sp->GetFileSpec().GetFilename(); 827 var_success = format_file_spec; 828 } 829 else 830 { 831 format_file_spec = exe_module_sp->GetFileSpec(); 832 var_success = format_file_spec; 833 } 834 } 835 } 836 } 837 } 838 break; 839 840 case 't': 841 if (::strncmp (var_name_begin, "thread.", strlen("thread.")) == 0) 842 { 843 if (exe_ctx && exe_ctx->thread) 844 { 845 var_name_begin += ::strlen ("thread."); 846 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 847 { 848 s.Printf("0x%4.4x", exe_ctx->thread->GetID()); 849 var_success = true; 850 } 851 else if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) 852 { 853 s.Printf("%u", exe_ctx->thread->GetIndexID()); 854 var_success = true; 855 } 856 else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) 857 { 858 cstr = exe_ctx->thread->GetName(); 859 var_success = cstr && cstr[0]; 860 if (var_success) 861 s.PutCString(cstr); 862 } 863 else if (::strncmp (var_name_begin, "queue}", strlen("queue}")) == 0) 864 { 865 cstr = exe_ctx->thread->GetQueueName(); 866 var_success = cstr && cstr[0]; 867 if (var_success) 868 s.PutCString(cstr); 869 } 870 else if (::strncmp (var_name_begin, "stop-reason}", strlen("stop-reason}")) == 0) 871 { 872 StopInfoSP stop_info_sp = exe_ctx->thread->GetStopInfo (); 873 if (stop_info_sp) 874 { 875 cstr = stop_info_sp->GetDescription(); 876 if (cstr && cstr[0]) 877 { 878 s.PutCString(cstr); 879 var_success = true; 880 } 881 } 882 } 883 } 884 } 885 else if (::strncmp (var_name_begin, "target.", strlen("target.")) == 0) 886 { 887 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 888 if (target) 889 { 890 var_name_begin += ::strlen ("target."); 891 if (::strncmp (var_name_begin, "arch}", strlen("arch}")) == 0) 892 { 893 ArchSpec arch (target->GetArchitecture ()); 894 if (arch.IsValid()) 895 { 896 s.PutCString (arch.AsCString()); 897 var_success = true; 898 } 899 } 900 } 901 } 902 break; 903 904 905 case 'm': 906 if (::strncmp (var_name_begin, "module.", strlen("module.")) == 0) 907 { 908 if (sc && sc->module_sp.get()) 909 { 910 Module *module = sc->module_sp.get(); 911 var_name_begin += ::strlen ("module."); 912 913 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 914 { 915 if (module->GetFileSpec()) 916 { 917 var_name_begin += ::strlen ("file."); 918 919 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 920 { 921 format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); 922 var_success = format_file_spec; 923 } 924 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 925 { 926 format_file_spec = module->GetFileSpec(); 927 var_success = format_file_spec; 928 } 929 } 930 } 931 } 932 } 933 break; 934 935 936 case 'f': 937 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 938 { 939 if (sc && sc->comp_unit != NULL) 940 { 941 var_name_begin += ::strlen ("file."); 942 943 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 944 { 945 format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); 946 var_success = format_file_spec; 947 } 948 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 949 { 950 format_file_spec = *sc->comp_unit; 951 var_success = format_file_spec; 952 } 953 } 954 } 955 else if (::strncmp (var_name_begin, "frame.", strlen("frame.")) == 0) 956 { 957 if (exe_ctx && exe_ctx->frame) 958 { 959 var_name_begin += ::strlen ("frame."); 960 if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0) 961 { 962 s.Printf("%u", exe_ctx->frame->GetFrameIndex()); 963 var_success = true; 964 } 965 else if (::strncmp (var_name_begin, "pc}", strlen("pc}")) == 0) 966 { 967 reg_kind = eRegisterKindGeneric; 968 reg_num = LLDB_REGNUM_GENERIC_PC; 969 var_success = true; 970 } 971 else if (::strncmp (var_name_begin, "sp}", strlen("sp}")) == 0) 972 { 973 reg_kind = eRegisterKindGeneric; 974 reg_num = LLDB_REGNUM_GENERIC_SP; 975 var_success = true; 976 } 977 else if (::strncmp (var_name_begin, "fp}", strlen("fp}")) == 0) 978 { 979 reg_kind = eRegisterKindGeneric; 980 reg_num = LLDB_REGNUM_GENERIC_FP; 981 var_success = true; 982 } 983 else if (::strncmp (var_name_begin, "flags}", strlen("flags}")) == 0) 984 { 985 reg_kind = eRegisterKindGeneric; 986 reg_num = LLDB_REGNUM_GENERIC_FLAGS; 987 var_success = true; 988 } 989 else if (::strncmp (var_name_begin, "reg.", strlen ("reg.")) == 0) 990 { 991 reg_ctx = exe_ctx->frame->GetRegisterContext().get(); 992 if (reg_ctx) 993 { 994 var_name_begin += ::strlen ("reg."); 995 if (var_name_begin < var_name_end) 996 { 997 std::string reg_name (var_name_begin, var_name_end); 998 reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); 999 if (reg_info) 1000 var_success = true; 1001 } 1002 } 1003 } 1004 } 1005 } 1006 else if (::strncmp (var_name_begin, "function.", strlen("function.")) == 0) 1007 { 1008 if (sc && (sc->function != NULL || sc->symbol != NULL)) 1009 { 1010 var_name_begin += ::strlen ("function."); 1011 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0) 1012 { 1013 if (sc->function) 1014 s.Printf("function{0x%8.8x}", sc->function->GetID()); 1015 else 1016 s.Printf("symbol[%u]", sc->symbol->GetID()); 1017 1018 var_success = true; 1019 } 1020 else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0) 1021 { 1022 if (sc->function) 1023 cstr = sc->function->GetName().AsCString (NULL); 1024 else if (sc->symbol) 1025 cstr = sc->symbol->GetName().AsCString (NULL); 1026 if (cstr) 1027 { 1028 s.PutCString(cstr); 1029 1030 if (sc->block) 1031 { 1032 Block *inline_block = sc->block->GetContainingInlinedBlock (); 1033 if (inline_block) 1034 { 1035 const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); 1036 if (inline_info) 1037 { 1038 s.PutCString(" [inlined] "); 1039 inline_info->GetName().Dump(&s); 1040 } 1041 } 1042 } 1043 var_success = true; 1044 } 1045 } 1046 else if (::strncmp (var_name_begin, "addr-offset}", strlen("addr-offset}")) == 0) 1047 { 1048 var_success = addr != NULL; 1049 if (var_success) 1050 { 1051 format_addr = *addr; 1052 calculate_format_addr_function_offset = true; 1053 } 1054 } 1055 else if (::strncmp (var_name_begin, "line-offset}", strlen("line-offset}")) == 0) 1056 { 1057 var_success = sc->line_entry.range.GetBaseAddress().IsValid(); 1058 if (var_success) 1059 { 1060 format_addr = sc->line_entry.range.GetBaseAddress(); 1061 calculate_format_addr_function_offset = true; 1062 } 1063 } 1064 else if (::strncmp (var_name_begin, "pc-offset}", strlen("pc-offset}")) == 0) 1065 { 1066 var_success = exe_ctx->frame; 1067 if (var_success) 1068 { 1069 format_addr = exe_ctx->frame->GetFrameCodeAddress(); 1070 calculate_format_addr_function_offset = true; 1071 } 1072 } 1073 } 1074 } 1075 break; 1076 1077 case 'l': 1078 if (::strncmp (var_name_begin, "line.", strlen("line.")) == 0) 1079 { 1080 if (sc && sc->line_entry.IsValid()) 1081 { 1082 var_name_begin += ::strlen ("line."); 1083 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0) 1084 { 1085 var_name_begin += ::strlen ("file."); 1086 1087 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0) 1088 { 1089 format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); 1090 var_success = format_file_spec; 1091 } 1092 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0) 1093 { 1094 format_file_spec = sc->line_entry.file; 1095 var_success = format_file_spec; 1096 } 1097 } 1098 else if (::strncmp (var_name_begin, "number}", strlen("number}")) == 0) 1099 { 1100 var_success = true; 1101 s.Printf("%u", sc->line_entry.line); 1102 } 1103 else if ((::strncmp (var_name_begin, "start-addr}", strlen("start-addr}")) == 0) || 1104 (::strncmp (var_name_begin, "end-addr}", strlen("end-addr}")) == 0)) 1105 { 1106 var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); 1107 if (var_success) 1108 { 1109 format_addr = sc->line_entry.range.GetBaseAddress(); 1110 if (var_name_begin[0] == 'e') 1111 format_addr.Slide (sc->line_entry.range.GetByteSize()); 1112 } 1113 } 1114 } 1115 } 1116 break; 1117 } 1118 1119 if (var_success) 1120 { 1121 // If format addr is valid, then we need to print an address 1122 if (reg_num != LLDB_INVALID_REGNUM) 1123 { 1124 // We have a register value to display... 1125 if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) 1126 { 1127 format_addr = exe_ctx->frame->GetFrameCodeAddress(); 1128 } 1129 else 1130 { 1131 if (reg_ctx == NULL) 1132 reg_ctx = exe_ctx->frame->GetRegisterContext().get(); 1133 1134 if (reg_ctx) 1135 { 1136 if (reg_kind != kNumRegisterKinds) 1137 reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); 1138 reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); 1139 var_success = reg_info != NULL; 1140 } 1141 } 1142 } 1143 1144 if (reg_info != NULL) 1145 { 1146 DataExtractor reg_data; 1147 var_success = reg_ctx->ReadRegisterBytes (reg_info->kinds[eRegisterKindLLDB], reg_data); 1148 { 1149 reg_data.Dump(&s, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); 1150 } 1151 } 1152 1153 if (format_file_spec) 1154 { 1155 s << format_file_spec; 1156 } 1157 1158 // If format addr is valid, then we need to print an address 1159 if (format_addr.IsValid()) 1160 { 1161 var_success = false; 1162 1163 if (calculate_format_addr_function_offset) 1164 { 1165 Address func_addr; 1166 1167 if (sc) 1168 { 1169 if (sc->function) 1170 { 1171 func_addr = sc->function->GetAddressRange().GetBaseAddress(); 1172 if (sc->block) 1173 { 1174 // Check to make sure we aren't in an inline 1175 // function. If we are, use the inline block 1176 // range that contains "format_addr" since 1177 // blocks can be discontiguous. 1178 Block *inline_block = sc->block->GetContainingInlinedBlock (); 1179 AddressRange inline_range; 1180 if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) 1181 func_addr = inline_range.GetBaseAddress(); 1182 } 1183 } 1184 else if (sc->symbol && sc->symbol->GetAddressRangePtr()) 1185 func_addr = sc->symbol->GetAddressRangePtr()->GetBaseAddress(); 1186 } 1187 1188 if (func_addr.IsValid()) 1189 { 1190 if (func_addr.GetSection() == format_addr.GetSection()) 1191 { 1192 addr_t func_file_addr = func_addr.GetFileAddress(); 1193 addr_t addr_file_addr = format_addr.GetFileAddress(); 1194 if (addr_file_addr > func_file_addr) 1195 s.Printf(" + %llu", addr_file_addr - func_file_addr); 1196 else if (addr_file_addr < func_file_addr) 1197 s.Printf(" - %llu", func_file_addr - addr_file_addr); 1198 var_success = true; 1199 } 1200 else 1201 { 1202 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 1203 if (target) 1204 { 1205 addr_t func_load_addr = func_addr.GetLoadAddress (target); 1206 addr_t addr_load_addr = format_addr.GetLoadAddress (target); 1207 if (addr_load_addr > func_load_addr) 1208 s.Printf(" + %llu", addr_load_addr - func_load_addr); 1209 else if (addr_load_addr < func_load_addr) 1210 s.Printf(" - %llu", func_load_addr - addr_load_addr); 1211 var_success = true; 1212 } 1213 } 1214 } 1215 } 1216 else 1217 { 1218 Target *target = Target::GetTargetFromContexts (exe_ctx, sc); 1219 addr_t vaddr = LLDB_INVALID_ADDRESS; 1220 if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) 1221 vaddr = format_addr.GetLoadAddress (target); 1222 if (vaddr == LLDB_INVALID_ADDRESS) 1223 vaddr = format_addr.GetFileAddress (); 1224 1225 if (vaddr != LLDB_INVALID_ADDRESS) 1226 { 1227 int addr_width = 0; 1228 if (exe_ctx && exe_ctx->process) 1229 addr_width = exe_ctx->process->GetAddressByteSize() * 2; 1230 if (addr_width == 0) 1231 addr_width = 16; 1232 s.Printf("0x%*.*llx", addr_width, addr_width, vaddr); 1233 var_success = true; 1234 } 1235 } 1236 } 1237 } 1238 1239 if (var_success == false) 1240 success = false; 1241 } 1242 p = var_name_end; 1243 } 1244 else 1245 break; 1246 } 1247 else 1248 { 1249 // We got a dollar sign with no '{' after it, it must just be a dollar sign 1250 s.PutChar(*p); 1251 } 1252 } 1253 else if (*p == '\\') 1254 { 1255 ++p; // skip the slash 1256 switch (*p) 1257 { 1258 case 'a': s.PutChar ('\a'); break; 1259 case 'b': s.PutChar ('\b'); break; 1260 case 'f': s.PutChar ('\f'); break; 1261 case 'n': s.PutChar ('\n'); break; 1262 case 'r': s.PutChar ('\r'); break; 1263 case 't': s.PutChar ('\t'); break; 1264 case 'v': s.PutChar ('\v'); break; 1265 case '\'': s.PutChar ('\''); break; 1266 case '\\': s.PutChar ('\\'); break; 1267 case '0': 1268 // 1 to 3 octal chars 1269 { 1270 // Make a string that can hold onto the initial zero char, 1271 // up to 3 octal digits, and a terminating NULL. 1272 char oct_str[5] = { 0, 0, 0, 0, 0 }; 1273 1274 int i; 1275 for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) 1276 oct_str[i] = p[i]; 1277 1278 // We don't want to consume the last octal character since 1279 // the main for loop will do this for us, so we advance p by 1280 // one less than i (even if i is zero) 1281 p += i - 1; 1282 unsigned long octal_value = ::strtoul (oct_str, NULL, 8); 1283 if (octal_value <= UINT8_MAX) 1284 { 1285 char octal_char = octal_value; 1286 s.Write (&octal_char, 1); 1287 } 1288 } 1289 break; 1290 1291 case 'x': 1292 // hex number in the format 1293 if (isxdigit(p[1])) 1294 { 1295 ++p; // Skip the 'x' 1296 1297 // Make a string that can hold onto two hex chars plus a 1298 // NULL terminator 1299 char hex_str[3] = { 0,0,0 }; 1300 hex_str[0] = *p; 1301 if (isxdigit(p[1])) 1302 { 1303 ++p; // Skip the first of the two hex chars 1304 hex_str[1] = *p; 1305 } 1306 1307 unsigned long hex_value = strtoul (hex_str, NULL, 16); 1308 if (hex_value <= UINT8_MAX) 1309 s.PutChar (hex_value); 1310 } 1311 else 1312 { 1313 s.PutChar('x'); 1314 } 1315 break; 1316 1317 default: 1318 // Just desensitize any other character by just printing what 1319 // came after the '\' 1320 s << *p; 1321 break; 1322 1323 } 1324 1325 } 1326 } 1327 if (end) 1328 *end = p; 1329 return success; 1330 } 1331 1332 #pragma mark Debugger::SettingsController 1333 1334 //-------------------------------------------------- 1335 // class Debugger::SettingsController 1336 //-------------------------------------------------- 1337 1338 Debugger::SettingsController::SettingsController () : 1339 UserSettingsController ("", lldb::UserSettingsControllerSP()) 1340 { 1341 m_default_settings.reset (new DebuggerInstanceSettings (*this, false, 1342 InstanceSettings::GetDefaultName().AsCString())); 1343 } 1344 1345 Debugger::SettingsController::~SettingsController () 1346 { 1347 } 1348 1349 1350 lldb::InstanceSettingsSP 1351 Debugger::SettingsController::CreateInstanceSettings (const char *instance_name) 1352 { 1353 DebuggerInstanceSettings *new_settings = new DebuggerInstanceSettings (*GetSettingsController(), 1354 false, instance_name); 1355 lldb::InstanceSettingsSP new_settings_sp (new_settings); 1356 return new_settings_sp; 1357 } 1358 1359 #pragma mark DebuggerInstanceSettings 1360 //-------------------------------------------------- 1361 // class DebuggerInstanceSettings 1362 //-------------------------------------------------- 1363 1364 DebuggerInstanceSettings::DebuggerInstanceSettings 1365 ( 1366 UserSettingsController &owner, 1367 bool live_instance, 1368 const char *name 1369 ) : 1370 InstanceSettings (owner, name ? name : InstanceSettings::InvalidName().AsCString(), live_instance), 1371 m_term_width (80), 1372 m_prompt (), 1373 m_frame_format (), 1374 m_thread_format (), 1375 m_script_lang (), 1376 m_use_external_editor (false), 1377 m_auto_confirm_on (false) 1378 { 1379 // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called 1380 // until the vtables for DebuggerInstanceSettings are properly set up, i.e. AFTER all the initializers. 1381 // For this reason it has to be called here, rather than in the initializer or in the parent constructor. 1382 // The same is true of CreateInstanceName(). 1383 1384 if (GetInstanceName() == InstanceSettings::InvalidName()) 1385 { 1386 ChangeInstanceName (std::string (CreateInstanceName().AsCString())); 1387 m_owner.RegisterInstanceSettings (this); 1388 } 1389 1390 if (live_instance) 1391 { 1392 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name); 1393 CopyInstanceSettings (pending_settings, false); 1394 } 1395 } 1396 1397 DebuggerInstanceSettings::DebuggerInstanceSettings (const DebuggerInstanceSettings &rhs) : 1398 InstanceSettings (*Debugger::GetSettingsController(), CreateInstanceName ().AsCString()), 1399 m_prompt (rhs.m_prompt), 1400 m_frame_format (rhs.m_frame_format), 1401 m_thread_format (rhs.m_thread_format), 1402 m_script_lang (rhs.m_script_lang), 1403 m_use_external_editor (rhs.m_use_external_editor), 1404 m_auto_confirm_on(rhs.m_auto_confirm_on) 1405 { 1406 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name); 1407 CopyInstanceSettings (pending_settings, false); 1408 m_owner.RemovePendingSettings (m_instance_name); 1409 } 1410 1411 DebuggerInstanceSettings::~DebuggerInstanceSettings () 1412 { 1413 } 1414 1415 DebuggerInstanceSettings& 1416 DebuggerInstanceSettings::operator= (const DebuggerInstanceSettings &rhs) 1417 { 1418 if (this != &rhs) 1419 { 1420 m_term_width = rhs.m_term_width; 1421 m_prompt = rhs.m_prompt; 1422 m_frame_format = rhs.m_frame_format; 1423 m_thread_format = rhs.m_thread_format; 1424 m_script_lang = rhs.m_script_lang; 1425 m_use_external_editor = rhs.m_use_external_editor; 1426 m_auto_confirm_on = rhs.m_auto_confirm_on; 1427 } 1428 1429 return *this; 1430 } 1431 1432 bool 1433 DebuggerInstanceSettings::ValidTermWidthValue (const char *value, Error err) 1434 { 1435 bool valid = false; 1436 1437 // Verify we have a value string. 1438 if (value == NULL || value[0] == '\0') 1439 { 1440 err.SetErrorString ("Missing value. Can't set terminal width without a value.\n"); 1441 } 1442 else 1443 { 1444 char *end = NULL; 1445 const uint32_t width = ::strtoul (value, &end, 0); 1446 1447 if (end && end[0] == '\0') 1448 { 1449 if (width >= 10 && width <= 1024) 1450 valid = true; 1451 else 1452 err.SetErrorString ("Invalid term-width value; value must be between 10 and 1024.\n"); 1453 } 1454 else 1455 err.SetErrorStringWithFormat ("'%s' is not a valid unsigned integer string.\n", value); 1456 } 1457 1458 return valid; 1459 } 1460 1461 1462 void 1463 DebuggerInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name, 1464 const char *index_value, 1465 const char *value, 1466 const ConstString &instance_name, 1467 const SettingEntry &entry, 1468 lldb::VarSetOperationType op, 1469 Error &err, 1470 bool pending) 1471 { 1472 1473 if (var_name == TermWidthVarName()) 1474 { 1475 if (ValidTermWidthValue (value, err)) 1476 { 1477 m_term_width = ::strtoul (value, NULL, 0); 1478 } 1479 } 1480 else if (var_name == PromptVarName()) 1481 { 1482 UserSettingsController::UpdateStringVariable (op, m_prompt, value, err); 1483 if (!pending) 1484 { 1485 // 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to 1486 // strip off the brackets before passing it to BroadcastPromptChange. 1487 1488 std::string tmp_instance_name (instance_name.AsCString()); 1489 if ((tmp_instance_name[0] == '[') 1490 && (tmp_instance_name[instance_name.GetLength() - 1] == ']')) 1491 tmp_instance_name = tmp_instance_name.substr (1, instance_name.GetLength() - 2); 1492 ConstString new_name (tmp_instance_name.c_str()); 1493 1494 BroadcastPromptChange (new_name, m_prompt.c_str()); 1495 } 1496 } 1497 else if (var_name == GetFrameFormatName()) 1498 { 1499 UserSettingsController::UpdateStringVariable (op, m_frame_format, value, err); 1500 } 1501 else if (var_name == GetThreadFormatName()) 1502 { 1503 UserSettingsController::UpdateStringVariable (op, m_thread_format, value, err); 1504 } 1505 else if (var_name == ScriptLangVarName()) 1506 { 1507 bool success; 1508 m_script_lang = Args::StringToScriptLanguage (value, eScriptLanguageDefault, 1509 &success); 1510 } 1511 else if (var_name == UseExternalEditorVarName ()) 1512 { 1513 UserSettingsController::UpdateBooleanVariable (op, m_use_external_editor, value, err); 1514 } 1515 else if (var_name == AutoConfirmName ()) 1516 { 1517 UserSettingsController::UpdateBooleanVariable (op, m_auto_confirm_on, value, err); 1518 } 1519 } 1520 1521 bool 1522 DebuggerInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry, 1523 const ConstString &var_name, 1524 StringList &value, 1525 Error *err) 1526 { 1527 if (var_name == PromptVarName()) 1528 { 1529 value.AppendString (m_prompt.c_str(), m_prompt.size()); 1530 1531 } 1532 else if (var_name == ScriptLangVarName()) 1533 { 1534 value.AppendString (ScriptInterpreter::LanguageToString (m_script_lang).c_str()); 1535 } 1536 else if (var_name == TermWidthVarName()) 1537 { 1538 StreamString width_str; 1539 width_str.Printf ("%d", m_term_width); 1540 value.AppendString (width_str.GetData()); 1541 } 1542 else if (var_name == GetFrameFormatName ()) 1543 { 1544 value.AppendString(m_frame_format.c_str(), m_frame_format.size()); 1545 } 1546 else if (var_name == GetThreadFormatName ()) 1547 { 1548 value.AppendString(m_thread_format.c_str(), m_thread_format.size()); 1549 } 1550 else if (var_name == UseExternalEditorVarName()) 1551 { 1552 if (m_use_external_editor) 1553 value.AppendString ("true"); 1554 else 1555 value.AppendString ("false"); 1556 } 1557 else if (var_name == AutoConfirmName()) 1558 { 1559 if (m_auto_confirm_on) 1560 value.AppendString ("true"); 1561 else 1562 value.AppendString ("false"); 1563 } 1564 else 1565 { 1566 if (err) 1567 err->SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString()); 1568 return false; 1569 } 1570 return true; 1571 } 1572 1573 void 1574 DebuggerInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings, 1575 bool pending) 1576 { 1577 if (new_settings.get() == NULL) 1578 return; 1579 1580 DebuggerInstanceSettings *new_debugger_settings = (DebuggerInstanceSettings *) new_settings.get(); 1581 1582 m_prompt = new_debugger_settings->m_prompt; 1583 if (!pending) 1584 { 1585 // 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to 1586 // strip off the brackets before passing it to BroadcastPromptChange. 1587 1588 std::string tmp_instance_name (m_instance_name.AsCString()); 1589 if ((tmp_instance_name[0] == '[') 1590 && (tmp_instance_name[m_instance_name.GetLength() - 1] == ']')) 1591 tmp_instance_name = tmp_instance_name.substr (1, m_instance_name.GetLength() - 2); 1592 ConstString new_name (tmp_instance_name.c_str()); 1593 1594 BroadcastPromptChange (new_name, m_prompt.c_str()); 1595 } 1596 m_frame_format = new_debugger_settings->m_frame_format; 1597 m_thread_format = new_debugger_settings->m_thread_format; 1598 m_term_width = new_debugger_settings->m_term_width; 1599 m_script_lang = new_debugger_settings->m_script_lang; 1600 m_use_external_editor = new_debugger_settings->m_use_external_editor; 1601 m_auto_confirm_on = new_debugger_settings->m_auto_confirm_on; 1602 } 1603 1604 1605 bool 1606 DebuggerInstanceSettings::BroadcastPromptChange (const ConstString &instance_name, const char *new_prompt) 1607 { 1608 std::string tmp_prompt; 1609 1610 if (new_prompt != NULL) 1611 { 1612 tmp_prompt = new_prompt ; 1613 int len = tmp_prompt.size(); 1614 if (len > 1 1615 && (tmp_prompt[0] == '\'' || tmp_prompt[0] == '"') 1616 && (tmp_prompt[len-1] == tmp_prompt[0])) 1617 { 1618 tmp_prompt = tmp_prompt.substr(1,len-2); 1619 } 1620 len = tmp_prompt.size(); 1621 if (tmp_prompt[len-1] != ' ') 1622 tmp_prompt.append(" "); 1623 } 1624 EventSP new_event_sp; 1625 new_event_sp.reset (new Event(CommandInterpreter::eBroadcastBitResetPrompt, 1626 new EventDataBytes (tmp_prompt.c_str()))); 1627 1628 if (instance_name.GetLength() != 0) 1629 { 1630 // Set prompt for a particular instance. 1631 Debugger *dbg = Debugger::FindDebuggerWithInstanceName (instance_name).get(); 1632 if (dbg != NULL) 1633 { 1634 dbg->GetCommandInterpreter().BroadcastEvent (new_event_sp); 1635 } 1636 } 1637 1638 return true; 1639 } 1640 1641 const ConstString 1642 DebuggerInstanceSettings::CreateInstanceName () 1643 { 1644 static int instance_count = 1; 1645 StreamString sstr; 1646 1647 sstr.Printf ("debugger_%d", instance_count); 1648 ++instance_count; 1649 1650 const ConstString ret_val (sstr.GetData()); 1651 1652 return ret_val; 1653 } 1654 1655 const ConstString & 1656 DebuggerInstanceSettings::PromptVarName () 1657 { 1658 static ConstString prompt_var_name ("prompt"); 1659 1660 return prompt_var_name; 1661 } 1662 1663 const ConstString & 1664 DebuggerInstanceSettings::GetFrameFormatName () 1665 { 1666 static ConstString prompt_var_name ("frame-format"); 1667 1668 return prompt_var_name; 1669 } 1670 1671 const ConstString & 1672 DebuggerInstanceSettings::GetThreadFormatName () 1673 { 1674 static ConstString prompt_var_name ("thread-format"); 1675 1676 return prompt_var_name; 1677 } 1678 1679 const ConstString & 1680 DebuggerInstanceSettings::ScriptLangVarName () 1681 { 1682 static ConstString script_lang_var_name ("script-lang"); 1683 1684 return script_lang_var_name; 1685 } 1686 1687 const ConstString & 1688 DebuggerInstanceSettings::TermWidthVarName () 1689 { 1690 static ConstString term_width_var_name ("term-width"); 1691 1692 return term_width_var_name; 1693 } 1694 1695 const ConstString & 1696 DebuggerInstanceSettings::UseExternalEditorVarName () 1697 { 1698 static ConstString use_external_editor_var_name ("use-external-editor"); 1699 1700 return use_external_editor_var_name; 1701 } 1702 1703 const ConstString & 1704 DebuggerInstanceSettings::AutoConfirmName () 1705 { 1706 static ConstString use_external_editor_var_name ("auto-confirm"); 1707 1708 return use_external_editor_var_name; 1709 } 1710 1711 //-------------------------------------------------- 1712 // SettingsController Variable Tables 1713 //-------------------------------------------------- 1714 1715 1716 SettingEntry 1717 Debugger::SettingsController::global_settings_table[] = 1718 { 1719 //{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"}, 1720 // The Debugger level global table should always be empty; all Debugger settable variables should be instance 1721 // variables. 1722 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL } 1723 }; 1724 1725 #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name}${function.pc-offset}}}" 1726 #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" 1727 1728 #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\ 1729 "{, ${frame.pc}}"\ 1730 MODULE_WITH_FUNC\ 1731 FILE_AND_LINE\ 1732 "{, stop reason = ${thread.stop-reason}}"\ 1733 "\\n" 1734 1735 //#define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\ 1736 // "{, ${frame.pc}}"\ 1737 // MODULE_WITH_FUNC\ 1738 // FILE_AND_LINE\ 1739 // "{, stop reason = ${thread.stop-reason}}"\ 1740 // "{, name = ${thread.name}}"\ 1741 // "{, queue = ${thread.queue}}"\ 1742 // "\\n" 1743 1744 #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ 1745 MODULE_WITH_FUNC\ 1746 FILE_AND_LINE\ 1747 "\\n" 1748 1749 SettingEntry 1750 Debugger::SettingsController::instance_settings_table[] = 1751 { 1752 // NAME Setting variable type Default Enum Init'd Hidden Help 1753 // ======================= ======================= ====================== ==== ====== ====== ====================== 1754 { "frame-format", eSetVarTypeString, DEFAULT_FRAME_FORMAT, NULL, false, false, "The default frame format string to use when displaying thread information." }, 1755 { "prompt", eSetVarTypeString, "(lldb) ", NULL, false, false, "The debugger command line prompt displayed for the user." }, 1756 { "script-lang", eSetVarTypeString, "python", NULL, false, false, "The script language to be used for evaluating user-written scripts." }, 1757 { "term-width", eSetVarTypeInt, "80" , NULL, false, false, "The maximum number of columns to use for displaying text." }, 1758 { "thread-format", eSetVarTypeString, DEFAULT_THREAD_FORMAT, NULL, false, false, "The default thread format string to use when displaying thread information." }, 1759 { "use-external-editor", eSetVarTypeBoolean, "false", NULL, false, false, "Whether to use an external editor or not." }, 1760 { "auto-confirm", eSetVarTypeBoolean, "false", NULL, false, false, "If true all confirmation prompts will receive their default reply." }, 1761 { NULL, eSetVarTypeNone, NULL, NULL, false, false, NULL } 1762 }; 1763