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