Added line preview

Author Mitja Felicijan <mitja.felicijan@gmail.com> 2026-01-16 11:02:28 +0100
Committer Mitja Felicijan <mitja.felicijan@gmail.com> 2026-01-16 11:02:28 +0100
Commit 4537fa8fa96915b7b907579bcb2b3f84b2322160 (patch)
-rw-r--r-- tdbg.cpp 55
1 files changed, 53 insertions, 2 deletions
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;
...