#include #include #include #include #include #include #include #include #include #include #include "libedbg/error.hpp" #include "libedbg/process.hpp" namespace { std::vector split(const std::string_view str, char delimiter) { std::vector 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(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& 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 attach(const int argc, const char **argv) { if (argc == 3 && argv[1] == std::string_view("-p")) { const auto pid = static_cast(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& 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"; } }