implement attach and launch

This commit is contained in:
2025-11-17 08:07:40 -08:00
parent 8e1842d412
commit 22f031c268
12 changed files with 327 additions and 39 deletions

View File

@@ -1,5 +1,114 @@
#include <libedbg/libedbg.hpp>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string.h>
#include <string>
#include <string_view>
#include <unistd.h>
#include <vector>
#include <editline/readline.h>
#include <sys/wait.h>
#include "libedbg/error.hpp"
#include "libedbg/process.hpp"
namespace {
std::vector<std::string> split(const std::string_view str, char delimiter) {
std::vector<std::string> out{};
std::stringstream ss{std::string{str}};
std::string item;
while (std::getline(ss, item, delimiter)) {
out.push_back(item);
}
return out;
}
bool is_prefix(std::string_view str, std::string_view of) {
if (str.size() < of.size()) {
return false;
}
return std::equal(str.begin(), str.end(), of.begin());
}
void print_stop_reason(const edbg::process& process, edbg::stop_reason reason) {
std::cout << "Process " << process.pid() << ' ';
switch (reason.reason) {
case edbg::process_state::exited:
std::cout << "exited with status " << static_cast<int>(reason.info);
break;
case edbg::process_state::terminated:
std::cout << "terminated with signal " << sigabbrev_np(reason.info);
case edbg::process_state::stopped:
std::cout << "stopped with signal " << sigabbrev_np(reason.info);
default: ;
}
std::cout << std::endl;
}
void handle_command(const std::unique_ptr<edbg::process>& process, const std::string_view line) {
const auto args = split(line, ' ');
const auto& command = args[0];
if (is_prefix(command, "continue")) {
process->resume();
const auto reason = process->wait_on_signal();
print_stop_reason(*process, reason);
} else {
std::cerr << "Unknown command: " << command << "\n";
}
}
std::unique_ptr<edbg::process> attach(const int argc, const char **argv) {
if (argc == 3 && argv[1] == std::string_view("-p")) {
const auto pid = static_cast<pid_t>(std::strtol(argv[2], nullptr, 10));
return edbg::process::attach(pid);
}
const char *program_path = argv[1];
return edbg::process::launch(program_path);
}
void main_loop(std::unique_ptr<edbg::process>& process) {
char *line = nullptr;
while ((line = readline("edbg> ")) != nullptr) {
std::string line_str;
if (line == std::string_view("")) {
free(line);
if (history_length > 0) {
line_str = history_list()[history_length - 1]->line;
}
} else {
line_str = line;
add_history(line_str.c_str());
free(line);
}
if (!line_str.empty()) {
try {
handle_command(process, line_str);
} catch (const edbg::error& err) {
std::cout << err.what() << "\n";
}
}
}
}
}
int main(const int argc, const char **argv) {
if (argc == 1) {
std::cerr << "No arguments given\n";
return -1;
}
try {
auto process = attach(argc, argv);
main_loop(process);
} catch (const edbg::error& err) {
std::cout << err.what() << "\n";
}
int main() {
edbg::hello();
}