|
diff --git a/tdbg.cpp b/tdbg.cpp
|
| ... |
| 17 |
|
17 |
|
| 18 |
using namespace lldb; |
18 |
using namespace lldb; |
| 19 |
|
19 |
|
| 20 |
const int LOG_WINDOW_HEIGHT = 10; |
20 |
struct LayoutConfig { |
| 21 |
const int STATUS_WINDOW_HEIGHT = 1; |
21 |
int log_height = 10; |
| 22 |
const int BREAKPOINTS_WINDOW_HEIGHT = 10; |
22 |
int status_height = 1; |
| 23 |
const int SIDEBAR_WIDTH = 50; |
23 |
int breakpoints_height = 10; |
|
|
24 |
int sidebar_width = 50; |
|
|
25 |
} layout_config; |
| 24 |
|
26 |
|
| 25 |
// https://unicodeplus.com |
27 |
// https://unicodeplus.com |
| 26 |
const uint32_t SCROLLBAR_THUMB = 0x2593; // Dark shade |
28 |
const uint32_t SCROLLBAR_THUMB = 0x2593; // Dark shade |
| ... |
| 165 |
char type_char = get_type_char(val.GetType()); |
167 |
char type_char = get_type_char(val.GetType()); |
| 166 |
std::string prefix = std::string("(") + type_char + ") "; |
168 |
std::string prefix = std::string("(") + type_char + ") "; |
| 167 |
|
169 |
|
|
|
170 |
std::string val_str = val.GetValue() ? val.GetValue() : ""; |
|
|
171 |
std::string summary_str = val.GetSummary() ? val.GetSummary() : ""; |
| 168 |
std::string value; |
172 |
std::string value; |
|
|
173 |
|
| 169 |
if (!val.IsValid()) value = "(invalid)"; |
174 |
if (!val.IsValid()) value = "(invalid)"; |
| 170 |
else if (val.GetValue()) value = val.GetValue(); |
175 |
else { |
| 171 |
else if (val.GetSummary()) value = val.GetSummary(); |
176 |
if (!val_str.empty() && !summary_str.empty()) value = val_str + " " + summary_str; |
|
|
177 |
else if (!val_str.empty()) value = val_str; |
|
|
178 |
else if (!summary_str.empty()) value = summary_str; |
|
|
179 |
} |
| 172 |
|
180 |
|
| 173 |
std::string indent_str(indent * 2, ' '); |
181 |
std::string indent_str(indent * 2, ' '); |
| 174 |
std::string content = original_name; |
182 |
std::string content = original_name; |
| ... |
| 198 |
std::string name = name_override.empty() ? (val.GetName() ? val.GetName() : "") : name_override; |
206 |
std::string name = name_override.empty() ? (val.GetName() ? val.GetName() : "") : name_override; |
| 199 |
char type_char = get_type_char(val.GetType()); |
207 |
char type_char = get_type_char(val.GetType()); |
| 200 |
|
208 |
|
|
|
209 |
std::string val_str = val.GetValue() ? val.GetValue() : ""; |
|
|
210 |
std::string summary_str = val.GetSummary() ? val.GetSummary() : ""; |
| 201 |
std::string value; |
211 |
std::string value; |
|
|
212 |
|
| 202 |
if (!val.IsValid()) value = "(invalid)"; |
213 |
if (!val.IsValid()) value = "(invalid)"; |
| 203 |
else if (val.GetValue()) value = val.GetValue(); |
214 |
else { |
| 204 |
else if (val.GetSummary()) value = val.GetSummary(); |
215 |
if (!val_str.empty() && !summary_str.empty()) value = val_str + " " + summary_str; |
|
|
216 |
else if (!val_str.empty()) value = val_str; |
|
|
217 |
else if (!summary_str.empty()) value = summary_str; |
|
|
218 |
} |
| 205 |
|
219 |
|
| 206 |
std::string indent_str(indent * 2, ' '); |
220 |
std::string indent_str(indent * 2, ' '); |
| 207 |
std::string line = get_timestamp() + " " + indent_str + "(" + type_char + ") " + name; |
221 |
std::string line = get_timestamp() + " " + indent_str + "(" + type_char + ") " + name; |
| ... |
| 588 |
} |
602 |
} |
| 589 |
|
603 |
|
| 590 |
int main(int argc, char** argv) { |
604 |
int main(int argc, char** argv) { |
| 591 |
if (argc < 2) { |
605 |
std::vector<std::string> target_env; |
| 592 |
std::cerr << "Usage: " << argv[0] << " <target_executable>\n"; |
606 |
std::vector<std::string> debuggee_args; |
|
|
607 |
std::string target_path; |
|
|
608 |
|
|
|
609 |
for (int i = 1; i < argc; ++i) { |
|
|
610 |
std::string arg = argv[i]; |
|
|
611 |
if (arg == "-e" && i + 1 < argc) { |
|
|
612 |
target_env.push_back(argv[++i]); |
|
|
613 |
} else if (arg == "--") { |
|
|
614 |
for (int j = i + 1; j < argc; ++j) { |
|
|
615 |
debuggee_args.push_back(argv[j]); |
|
|
616 |
} |
|
|
617 |
break; |
|
|
618 |
} else if (target_path.empty()) { |
|
|
619 |
target_path = arg; |
|
|
620 |
} else { |
|
|
621 |
debuggee_args.push_back(arg); |
|
|
622 |
} |
|
|
623 |
} |
|
|
624 |
|
|
|
625 |
if (target_path.empty()) { |
|
|
626 |
std::cerr << "Usage: " << argv[0] << " [-e KEY=VALUE] ... <target_executable> [-- arg1 arg2 ...]\n"; |
| 593 |
return 1; |
627 |
return 1; |
| 594 |
} |
628 |
} |
| 595 |
|
629 |
|
| ... |
| 599 |
close(log_fd); |
633 |
close(log_fd); |
| 600 |
} |
634 |
} |
| 601 |
|
635 |
|
| 602 |
const char* target_path = argv[1]; |
|
|
| 603 |
|
|
|
| 604 |
LLDBGuard lldb_guard; |
636 |
LLDBGuard lldb_guard; |
| 605 |
SBDebugger debugger = SBDebugger::Create(); |
637 |
SBDebugger debugger = SBDebugger::Create(); |
| 606 |
debugger.SetAsync(false); |
638 |
debugger.SetAsync(false); |
| 607 |
|
639 |
|
| 608 |
SBTarget target = debugger.CreateTarget(target_path); |
640 |
SBTarget target = debugger.CreateTarget(target_path.c_str()); |
| 609 |
if (!target.IsValid()) { |
641 |
if (!target.IsValid()) { |
| 610 |
std::cerr << "Failed to create target for " << target_path << "\n"; |
642 |
std::cerr << "Failed to create target for " << target_path << "\n"; |
| 611 |
return 1; |
643 |
return 1; |
| ... |
| 635 |
|
667 |
|
| 636 |
int width = tb_width(); |
668 |
int width = tb_width(); |
| 637 |
int height = tb_height(); |
669 |
int height = tb_height(); |
| 638 |
int main_window_height = height - LOG_WINDOW_HEIGHT - STATUS_WINDOW_HEIGHT; |
670 |
int main_window_height = height - layout_config.log_height - layout_config.status_height; |
| 639 |
int split_x = width - SIDEBAR_WIDTH; |
671 |
int split_x = width - layout_config.sidebar_width; |
| 640 |
int locals_window_height = main_window_height - BREAKPOINTS_WINDOW_HEIGHT; |
672 |
int locals_window_height = main_window_height - layout_config.breakpoints_height; |
| 641 |
|
673 |
|
| 642 |
SBFrame frame; |
674 |
SBFrame frame; |
| 643 |
if (process.IsValid() && process.GetState() != eStateExited) { |
675 |
if (process.IsValid() && process.GetState() != eStateExited) { |
| ... |
| 672 |
} |
704 |
} |
| 673 |
|
705 |
|
| 674 |
draw_source_view(frame, 0, 0, split_x, main_window_height, source_cache, source_scroll_offset); |
706 |
draw_source_view(frame, 0, 0, split_x, main_window_height, source_cache, source_scroll_offset); |
| 675 |
draw_variables_view(frame, split_x, 0, SIDEBAR_WIDTH, locals_window_height, locals_scroll_offset); |
707 |
draw_variables_view(frame, split_x, 0, layout_config.sidebar_width, locals_window_height, locals_scroll_offset); |
| 676 |
draw_breakpoints_view(target, split_x, locals_window_height, SIDEBAR_WIDTH, BREAKPOINTS_WINDOW_HEIGHT); |
708 |
draw_breakpoints_view(target, split_x, locals_window_height, layout_config.sidebar_width, layout_config.breakpoints_height); |
| 677 |
draw_log_view(0, main_window_height, width, LOG_WINDOW_HEIGHT, log_buffer, mode, input_buffer, log_scroll_offset); |
709 |
draw_log_view(0, main_window_height, width, layout_config.log_height, log_buffer, mode, input_buffer, log_scroll_offset); |
| 678 |
draw_status_bar(process, mode, width, height); |
710 |
draw_status_bar(process, mode, width, height); |
| 679 |
|
711 |
|
| 680 |
tb_present(); |
712 |
tb_present(); |
| ... |
| 696 |
} |
728 |
} |
| 697 |
} |
729 |
} |
| 698 |
log_msg(log_buffer, "Launching..."); |
730 |
log_msg(log_buffer, "Launching..."); |
| 699 |
process = target.LaunchSimple(nullptr, nullptr, "."); |
731 |
|
| 700 |
if (!process.IsValid()) log_msg(log_buffer, "Launch failed"); |
732 |
std::vector<const char*> launch_argv; |
| 701 |
else log_msg(log_buffer, "Launched"); |
733 |
launch_argv.push_back(target_path.c_str()); |
|
|
734 |
for (const auto& arg : debuggee_args) { |
|
|
735 |
launch_argv.push_back(arg.c_str()); |
|
|
736 |
} |
|
|
737 |
launch_argv.push_back(nullptr); |
|
|
738 |
|
|
|
739 |
std::vector<const char*> launch_env; |
|
|
740 |
for (const auto& env : target_env) { |
|
|
741 |
launch_env.push_back(env.c_str()); |
|
|
742 |
} |
|
|
743 |
launch_env.push_back(nullptr); |
|
|
744 |
|
|
|
745 |
SBLaunchInfo launch_info(launch_argv.data()); |
|
|
746 |
launch_info.SetEnvironmentEntries(launch_env.data(), true); |
|
|
747 |
launch_info.SetWorkingDirectory("."); |
|
|
748 |
|
|
|
749 |
SBError error; |
|
|
750 |
process = target.Launch(launch_info, error); |
|
|
751 |
|
|
|
752 |
if (!process.IsValid() || error.Fail()) { |
|
|
753 |
std::string err_msg = "Launch failed"; |
|
|
754 |
if (error.GetCString()) { |
|
|
755 |
err_msg += ": "; |
|
|
756 |
err_msg += error.GetCString(); |
|
|
757 |
} |
|
|
758 |
log_msg(log_buffer, err_msg); |
|
|
759 |
} else { |
|
|
760 |
log_msg(log_buffer, "Launched"); |
|
|
761 |
} |
| 702 |
} else { |
762 |
} else { |
| 703 |
log_msg(log_buffer, "Already running"); |
763 |
log_msg(log_buffer, "Already running"); |
| 704 |
} |
764 |
} |
| ... |
| 719 |
case 's': if (thread.IsValid()) thread.StepInto(); break; |
779 |
case 's': if (thread.IsValid()) thread.StepInto(); break; |
| 720 |
case 'o': if (thread.IsValid()) thread.StepOut(); break; |
780 |
case 'o': if (thread.IsValid()) thread.StepOut(); break; |
| 721 |
case 'c': process.Continue(); break; |
781 |
case 'c': process.Continue(); break; |
|
|
782 |
case '<': layout_config.sidebar_width = std::min(width - 20, layout_config.sidebar_width + 2); break; |
|
|
783 |
case '>': layout_config.sidebar_width = std::max(20, layout_config.sidebar_width - 2); break; |
|
|
784 |
} |
|
|
785 |
} else { |
|
|
786 |
switch (ev.ch) { |
|
|
787 |
case '<': layout_config.sidebar_width = std::min(width - 20, layout_config.sidebar_width + 2); break; |
|
|
788 |
case '>': layout_config.sidebar_width = std::max(20, layout_config.sidebar_width - 2); break; |
| 722 |
} |
789 |
} |
| 723 |
} |
790 |
} |
| 724 |
} |
791 |
} |
| ... |
| 762 |
} |
829 |
} |
| 763 |
} |
830 |
} |
| 764 |
} else if (ev.type == TB_EVENT_MOUSE) { |
831 |
} else if (ev.type == TB_EVENT_MOUSE) { |
| 765 |
int main_window_height = tb_height() - LOG_WINDOW_HEIGHT - STATUS_WINDOW_HEIGHT; |
832 |
int main_window_height = tb_height() - layout_config.log_height - layout_config.status_height; |
| 766 |
|
833 |
|
| 767 |
// Log window scrolling |
834 |
// Log window scrolling |
| 768 |
int log_start_y = main_window_height; |
835 |
int log_start_y = main_window_height; |
| 769 |
int log_end_y = tb_height() - STATUS_WINDOW_HEIGHT; |
836 |
int log_end_y = tb_height() - layout_config.status_height; |
| 770 |
if (ev.y >= log_start_y && ev.y < log_end_y) { |
837 |
if (ev.y >= log_start_y && ev.y < log_end_y) { |
| 771 |
if (ev.key == TB_KEY_MOUSE_WHEEL_UP) { |
838 |
if (ev.key == TB_KEY_MOUSE_WHEEL_UP) { |
| 772 |
int max_scroll = std::max(0, (int)log_buffer.size() - (LOG_WINDOW_HEIGHT - 2)); |
839 |
int max_scroll = std::max(0, (int)log_buffer.size() - (layout_config.log_height - 2)); |
| 773 |
if (log_scroll_offset < max_scroll) { |
840 |
if (log_scroll_offset < max_scroll) { |
| 774 |
log_scroll_offset++; |
841 |
log_scroll_offset++; |
| 775 |
} |
842 |
} |
| ... |
| 808 |
} |
875 |
} |
| 809 |
|
876 |
|
| 810 |
// Locals window scrolling |
877 |
// Locals window scrolling |
| 811 |
int split_x = tb_width() - SIDEBAR_WIDTH; |
878 |
int split_x = tb_width() - layout_config.sidebar_width; |
| 812 |
int locals_window_height = main_window_height - BREAKPOINTS_WINDOW_HEIGHT; |
879 |
int locals_window_height = main_window_height - layout_config.breakpoints_height; |
| 813 |
if (ev.x >= split_x && ev.y < locals_window_height) { |
880 |
if (ev.x >= split_x && ev.y < locals_window_height) { |
| 814 |
std::vector<VarLine> lines; |
881 |
std::vector<VarLine> lines; |
| 815 |
if (frame.IsValid()) { |
882 |
if (frame.IsValid()) { |
| 816 |
SBValueList vars = frame.GetVariables(true, true, false, true); |
883 |
SBValueList vars = frame.GetVariables(true, true, false, true); |
| 817 |
for (uint32_t i = 0; i < vars.GetSize(); ++i) { |
884 |
for (uint32_t i = 0; i < vars.GetSize(); ++i) { |
| 818 |
collect_variables_recursive(vars.GetValueAtIndex(i), 0, lines, SIDEBAR_WIDTH - 2); |
885 |
collect_variables_recursive(vars.GetValueAtIndex(i), 0, lines, layout_config.sidebar_width - 2); |
| 819 |
} |
886 |
} |
| 820 |
} |
887 |
} |
| 821 |
int max_scroll = std::max(0, (int)lines.size() - (locals_window_height - 2)); |
888 |
int max_scroll = std::max(0, (int)lines.size() - (locals_window_height - 2)); |
| ... |