Skip to content

Commit

Permalink
util: add debug utility
Browse files Browse the repository at this point in the history
  • Loading branch information
DHrpcs3 committed Nov 24, 2024
1 parent 84026f1 commit 2d407fb
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
1 change: 1 addition & 0 deletions rx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ find_package(Git)


add_library(${PROJECT_NAME} OBJECT
src/debug.cpp
src/die.cpp
src/hexdump.cpp
src/mem.cpp
Expand Down
9 changes: 9 additions & 0 deletions rx/include/rx/debug.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

namespace rx {
bool isDebuggerPresent();
void waitForDebugger();
void runDebugger();
void breakpoint();
void breakpointIfDebugging();
} // namespace rx
101 changes: 101 additions & 0 deletions rx/src/debug.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include "debug.hpp"
#include <fstream>
#include <list>
#include <print>
#include <thread>
#include <vector>

#ifdef __GNUC__
#include <linux/limits.h>
#include <sys/ptrace.h>
#include <unistd.h>

bool rx::isDebuggerPresent() {
std::ifstream in("/proc/self/status");
std::string line;
while (std::getline(in, line)) {
const std::string_view tracerPrefix = "TracerPid:\t";

if (!line.starts_with(tracerPrefix)) {
continue;
}

std::string_view tracer = line;
tracer.remove_prefix(tracerPrefix.size());

if (tracer.size() == 1 && tracer[0] == '0')
return false;

return true;
}

return false;
}

void rx::waitForDebugger() {
if (isDebuggerPresent()) {
return;
}

std::println(stderr, "waiting for debugger, pid {}", ::getpid());

while (!isDebuggerPresent()) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}

std::println(stderr, "debugger was attached");
std::this_thread::sleep_for(std::chrono::seconds(3));
breakpoint();
}

void rx::runDebugger() {
int pid = ::getpid();
char path[PATH_MAX];
::readlink("/proc/self/exe", path, sizeof(path));
if (fork()) {
std::this_thread::sleep_for(std::chrono::seconds(1));
waitForDebugger();
return;
}

auto pidString = std::to_string(pid);
const char *gdbPath = "/usr/bin/gdb";

std::list<std::string> storage;
std::vector<const char *> argv;
argv.push_back(gdbPath);
argv.push_back(path);
argv.push_back(pidString.c_str());
argv.push_back("-iex");
argv.push_back("set pagination off");
argv.push_back("-ex");
argv.push_back("handle SIGSYS nostop noprint");
argv.push_back("-ex");
argv.push_back("handle SIGUSR1 nostop noprint");
// TODO: collect elfs
// argv.push_back("-ex");
// argv.push_back("add-symbol-file <path to elf> 0x400000");
argv.push_back(nullptr);

execv(gdbPath, (char **)argv.data());
}

#else
bool rx::isDebuggerPresent() { return false; }
void rx::waitForDebugger() {}
void rx::runDebugger() {}
#endif

void rx::breakpoint() {
#if __has_builtin(__builtin_debugtrap)
__builtin_debugtrap();
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
__asm__ volatile("int3");
#endif
}

void rx::breakpointIfDebugging() {
if (isDebuggerPresent()) {
breakpoint();
}
}

0 comments on commit 2d407fb

Please sign in to comment.