|
diff --git a/tdbg.cpp b/tdbg.cpp
|
| ... |
| 4 |
#include <string> |
4 |
#include <string> |
| 5 |
#include <thread> |
5 |
#include <thread> |
| 6 |
#include <chrono> |
6 |
#include <chrono> |
|
|
7 |
#include <fstream> |
|
|
8 |
#include <vector> |
| 7 |
|
9 |
|
| 8 |
using namespace lldb; |
10 |
using namespace lldb; |
| 9 |
|
11 |
|
| ... |
| 40 |
} |
42 |
} |
| 41 |
} |
43 |
} |
| 42 |
|
44 |
|
| 43 |
|
|
|
| 44 |
void print_backtrace(SBThread &thread) { |
45 |
void print_backtrace(SBThread &thread) { |
| 45 |
int num_frames = thread.GetNumFrames(); |
46 |
int num_frames = thread.GetNumFrames(); |
| 46 |
for (int i = 0; i < num_frames; ++i) { |
47 |
for (int i = 0; i < num_frames; ++i) { |
| ... |
| 50 |
} |
51 |
} |
| 51 |
} |
52 |
} |
| 52 |
|
53 |
|
|
|
54 |
void print_source_line(const std::string& filepath, int line_number) { |
|
|
55 |
std::ifstream file(filepath); |
|
|
56 |
if (!file.is_open()) { |
|
|
57 |
// std::cerr << "Could not open source file: " << filepath << "\n"; |
|
|
58 |
return; |
|
|
59 |
} |
|
|
60 |
|
|
|
61 |
std::string line; |
|
|
62 |
int current_line = 1; |
|
|
63 |
while (std::getline(file, line)) { |
|
|
64 |
if (current_line >= line_number - 3 && current_line <= line_number + 3) { |
|
|
65 |
std::cout << (current_line == line_number ? " -> " : " ") |
|
|
66 |
<< current_line << ": " << line << "\n"; |
|
|
67 |
} |
|
|
68 |
if (current_line > line_number + 3) break; |
|
|
69 |
current_line++; |
|
|
70 |
} |
|
|
71 |
} |
|
|
72 |
|
| 53 |
int main(int argc, char** argv) { |
73 |
int main(int argc, char** argv) { |
| 54 |
if (argc < 2) { |
74 |
if (argc < 2) { |
| 55 |
std::cerr << "Usage: " << argv[0] << " <target_executable>\n"; |
75 |
std::cerr << "Usage: " << argv[0] << " <target_executable>\n"; |
| ... |
| 83 |
SBListener listener = debugger.GetListener(); |
103 |
SBListener listener = debugger.GetListener(); |
| 84 |
SBEvent event; |
104 |
SBEvent event; |
| 85 |
|
105 |
|
|
|
106 |
std::string last_cmd; |
|
|
107 |
|
| 86 |
while (true) { |
108 |
while (true) { |
| 87 |
// Wait for events from LLDB. |
109 |
// Wait for events from LLDB. |
| 88 |
if (listener.WaitForEvent(1, event)) { |
110 |
if (listener.WaitForEvent(1, event)) { |
| ... |
| 97 |
std::cout << "Stopped at function: " << frame.GetFunctionName() |
119 |
std::cout << "Stopped at function: " << frame.GetFunctionName() |
| 98 |
<< ", line: " << frame.GetLineEntry().GetLine() << "\n"; |
120 |
<< ", line: " << frame.GetLineEntry().GetLine() << "\n"; |
| 99 |
|
121 |
|
|
|
122 |
SBFileSpec line_entry = frame.GetLineEntry().GetFileSpec(); |
|
|
123 |
if (line_entry.IsValid()) { |
|
|
124 |
// Directory and Filename might be null if not debug info |
|
|
125 |
const char* dirname = line_entry.GetDirectory(); |
|
|
126 |
const char* filename = line_entry.GetFilename(); |
|
|
127 |
if (filename) { |
|
|
128 |
std::string fullpath; |
|
|
129 |
if (dirname) { |
|
|
130 |
fullpath = std::string(dirname) + "/" + std::string(filename); |
|
|
131 |
} else { |
|
|
132 |
fullpath = std::string(filename); |
|
|
133 |
} |
|
|
134 |
print_source_line(fullpath, frame.GetLineEntry().GetLine()); |
|
|
135 |
} |
|
|
136 |
} |
|
|
137 |
|
| 100 |
// REPL loop for user commands. |
138 |
// REPL loop for user commands. |
| 101 |
std::string cmd; |
139 |
std::string cmd; |
|
|
140 |
|
| 102 |
while (true) { |
141 |
while (true) { |
| 103 |
std::cout << "(tdbg) "; |
142 |
std::cout << "(tdbg) "; |
| 104 |
std::getline(std::cin, cmd); |
143 |
std::getline(std::cin, cmd); |
|
|
144 |
|
|
|
145 |
if (cmd.empty()) { |
|
|
146 |
if (last_cmd.empty()) { |
|
|
147 |
continue; |
|
|
148 |
} |
|
|
149 |
cmd = last_cmd; |
|
|
150 |
} else { |
|
|
151 |
last_cmd = cmd; |
|
|
152 |
} |
|
|
153 |
|
| 105 |
if (cmd == "c") { |
154 |
if (cmd == "c") { |
| 106 |
process.Continue(); |
155 |
process.Continue(); |
| 107 |
break; // exit REPL, wait for next stop |
156 |
break; // exit REPL, wait for next stop |
| ... |
| 115 |
print_backtrace(thread); |
164 |
print_backtrace(thread); |
| 116 |
} else if (cmd == "v") { |
165 |
} else if (cmd == "v") { |
| 117 |
print_variables(frame); |
166 |
print_variables(frame); |
|
|
167 |
} else if (cmd == "h") { |
|
|
168 |
std::cout << "Commands: c=continue, s=step in, n=step over, bt=backtrace, v=variables, q=quit, h=help\n"; |
| 118 |
} else if (cmd == "q") { |
169 |
} else if (cmd == "q") { |
| 119 |
process.Kill(); |
170 |
process.Kill(); |
| 120 |
goto cleanup; |
171 |
goto cleanup; |
| 121 |
} else { |
172 |
} else { |
| 122 |
std::cout << "Commands: c=continue, s=step in, n=step over, bt=backtrace, v=variables, q=quit\n"; |
173 |
std::cout << "Unknown command. Type 'h' for help.\n"; |
| 123 |
} |
174 |
} |
| 124 |
} |
175 |
} |
| 125 |
break; |
176 |
break; |
| ... |