implement attach and launch
This commit is contained in:
115
tools/edbg.cpp
115
tools/edbg.cpp
@@ -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();
|
||||
}
|
||||
Reference in New Issue
Block a user