111 lines
3 KiB
C
111 lines
3 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* main.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: jhalford <jack@crans.org> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2017/04/22 14:10:24 by jhalford #+# #+# */
|
|
/* Updated: 2017/04/23 18:18:41 by jhalford ### ########.fr */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include "strace.h"
|
|
|
|
extern char **environ;
|
|
|
|
extern t_syscall g_syscalls[];
|
|
|
|
#define LOAD_PARAMS(params, regs) do { \
|
|
memcpy(params + 0, ®s->rdi, 8); \
|
|
memcpy(params + 1, ®s->rsi, 8); \
|
|
memcpy(params + 2, ®s->rdx, 8); \
|
|
memcpy(params + 3, ®s->rcx, 8); \
|
|
memcpy(params + 4, ®s->r8, 8); \
|
|
memcpy(params + 5, ®s->r9, 8); \
|
|
} while (0)
|
|
|
|
void print_syscall_params(t_syscall syscall, struct user_regs_struct *regs)
|
|
{
|
|
enum e_param type;
|
|
unsigned long long params[7];
|
|
|
|
LOAD_PARAMS(params, regs);
|
|
for (int i = 0; syscall.params[i]; i++) {
|
|
type = syscall.params[i];
|
|
if (i != 0)
|
|
printf(", ");
|
|
if (type == PARAM_NUMBER)
|
|
printf("%d", (int)params[i]);
|
|
if (type == PARAM_STRING)
|
|
{
|
|
if (params[i] == 0)
|
|
printf("NULL");
|
|
/* else */
|
|
/* printf("\"%s\"", (char *)params[i]); */
|
|
}
|
|
if (type == PARAM_ADDR)
|
|
{
|
|
if (params[i] == 0)
|
|
printf("NULL");
|
|
else
|
|
printf("%#llx", params[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void print_syscall_ret(unsigned long long ret)
|
|
{
|
|
printf(") = ");
|
|
if ((signed long long)ret < 0)
|
|
printf("-1 (errno %lld)", -ret);
|
|
else if (ret >> 16)
|
|
printf("%#llx", ret);
|
|
else
|
|
printf("%lld", ret);
|
|
printf("\n");
|
|
}
|
|
|
|
int main(int ac, char **av)
|
|
{
|
|
int child;
|
|
int status;
|
|
unsigned long old;
|
|
struct user_regs_struct regs;
|
|
|
|
(void)ac;
|
|
if ((child = fork()) == 0) {
|
|
/* ptrace(PTRACE_TRACEME, child, 0, 0); */
|
|
raise(SIGSTOP);
|
|
execve(av[1], av + 1, environ);
|
|
}
|
|
ptrace(PTRACE_SEIZE, child, 0, (void*)(PTRACE_O_TRACESYSGOOD));
|
|
ptrace(PTRACE_INTERRUPT, child, 0, 0);
|
|
wait(&status);
|
|
/* ptrace(PTRACE_SETOPTIONS, child, NULL, PTRACE_O_TRACEEXEC); */
|
|
while (1) {
|
|
ptrace(PTRACE_SYSCALL, child, NULL, NULL);
|
|
waitpid(child, &status, 0);
|
|
if (WIFEXITED(status))
|
|
{
|
|
if (old != 0)
|
|
printf(") = ?\n+++ exited with %d +++\n", WEXITSTATUS(status));
|
|
break ;
|
|
}
|
|
else if (!(WIFSTOPPED(status) && WSTOPSIG(status) & 0x80))
|
|
continue ;
|
|
|
|
ptrace(PTRACE_GETREGS, child, NULL, ®s);
|
|
if (old != regs.rip) {
|
|
printf("%s(", g_syscalls[regs.orig_rax].name);
|
|
print_syscall_params(g_syscalls[regs.orig_rax], ®s);
|
|
old = regs.rip;
|
|
}
|
|
else
|
|
{
|
|
print_syscall_ret(regs.rax);
|
|
old = 0;
|
|
}
|
|
}
|
|
return (0);
|
|
}
|