diff --git a/src/tracer.cpp b/src/tracer.cpp index e73cecc..391b134 100644 --- a/src/tracer.cpp +++ b/src/tracer.cpp @@ -53,3 +53,65 @@ void Tracer::handle_watchpoint_hit(pid_t pid, uint64_t address) { std::cout << std::format("Variable accessed at RIP: 0x{:x}", regs.rip) << std::endl; } + +void Tracer::watch_variable(const std::string &exec_path, uint64_t address, size_t size) { + pid_t pid = fork(); + + if (pid == 0) { + // Child process: execute the target binary + ptrace(PTRACE_TRACEME, 0, 0, 0); + execl(exec_path.c_str(), exec_path.c_str(), nullptr); + std::cerr << "Error: Failed to execute " << exec_path << std::endl; + exit(1); + } else if (pid > 0) { + // Parent process: set up watchpoint and monitor + int status; + waitpid(pid, &status, 0); + + if (!WIFSTOPPED(status)) { + std::cerr << "Error: Child process not stopped" << std::endl; + return; + } + + // Set up hardware watchpoint + setup_hardware_watchpoint(pid, address, size); + + // Continue execution and monitor for watchpoint hits + ptrace(PTRACE_CONT, pid, 0, 0); + + while (true) { + waitpid(pid, &status, 0); + + if (WIFEXITED(status)) { + std::cout << "Process exited with status " << WEXITSTATUS(status) + << std::endl; + break; + } + + if (WIFSTOPPED(status)) { + int sig = WSTOPSIG(status); + + if (sig == SIGTRAP) { + // Check if it's a watchpoint hit + uint64_t dr6 = ptrace(PTRACE_PEEKUSER, pid, + offsetof(struct user, u_debugreg[6]), 0); + + if (dr6 & 0x1) { // DR0 triggered + handle_watchpoint_hit(pid, address); + + // Clear DR6 + ptrace(PTRACE_POKEUSER, pid, + offsetof(struct user, u_debugreg[6]), 0); + } + + ptrace(PTRACE_CONT, pid, 0, 0); + } else { + // Forward other signals + ptrace(PTRACE_CONT, pid, 0, sig); + } + } + } + } else { + std::cerr << "Error: fork() failed" << std::endl; + } +}