/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* main.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: thrieg +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/11 04:07:30 by thrieg #+# #+# */ /* Updated: 2025/12/11 23:25:15 by thrieg ### ########.fr */ /* */ /* ************************************************************************** */ #include "../includes/ft_strace.h" int main_loop(size_t binary_type, pid_t pid) { int in_syscall = 0; while (1) { // Ask kernel to run until next syscall or signal if (ptrace(PTRACE_SYSCALL, pid, 0, 0) == -1) break; int status; if (waitpid(pid, &status, 0) == -1) break; if (WIFEXITED(status)) { // child exited normally printf("+++ exited with %d +++\n", WEXITSTATUS(status)); break; } if (WIFSIGNALED(status)) { // killed by a signal printf("+++ killed by %s +++\n", strsignal(WTERMSIG(status))); break; } if (!WIFSTOPPED(status)) continue; int sig = WSTOPSIG(status); if (sig == (SIGTRAP | 0x80)) { // syscall-enter or syscall-exit if (!in_syscall) { // ENTRY read_regs_and_print_entry(pid, binary_type); in_syscall = 1; } else { // EXIT read_regs_and_print_exit(pid, binary_type); in_syscall = 0; } } else { // A real signal: print it print_signal(pid, sig); // pass down the signal to the actual program if (ptrace(PTRACE_SYSCALL, pid, 0, sig) == -1) break; //waitpid(pid, &status, 0); } } return (EXIT_SUCCESS); } int main(int argc, char **argv) { if (argc < 2) { dprintf(2, "usage: %s ...\n", argv[0]); return (EXIT_FAILURE); } //determine if this file is an executable, and if so, 64 or 32 bits ssize_t binary_bits = binary_type(argv[1]); if (binary_bits < 0) { if (binary_bits == -1) { dprintf(2, "couldn't read that file, make sure you have the read and execute permissions on %s\n", argv[1]); } else if (binary_bits == -2) { dprintf(2, "%s is not a supported binary\n", argv[1]); } return (EXIT_FAILURE); } pid_t pid = fork(); if (pid == 0) { execvp(argv[1], argv + 1); perror("execvp"); return (EXIT_FAILURE); } else { // 1) Seize the child if (ptrace(PTRACE_SEIZE, pid, 0, 0) == -1) perror("PTRACE_SEIZE"); // 2) Interrupt it to force a stop if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) == -1) perror("PTRACE_INTERRUPT"); // 3) Wait for it to stop int status; waitpid(pid, &status, 0); // 4) Set options long opts = PTRACE_O_TRACESYSGOOD; ptrace(PTRACE_SETOPTIONS, pid, 0, opts); // 5) Enter main trace loop return (main_loop((size_t)binary_bits, pid)); } return (EXIT_SUCCESS); }