Let strace almost work on NetBSD/amd64
This commit is contained in:
parent
278ca235c6
commit
0863570941
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
|
|
||||||
/* types */
|
/* types */
|
||||||
typedef long ptrace_data_t; /* XXX really is int */
|
typedef int ptrace_data_t;
|
||||||
struct user
|
struct user
|
||||||
{
|
{
|
||||||
struct reg regs;
|
struct reg regs;
|
||||||
|
@ -35,8 +35,7 @@ struct user
|
||||||
|
|
||||||
/* constants */
|
/* constants */
|
||||||
# if defined(__amd64__)
|
# if defined(__amd64__)
|
||||||
# define _REG32_EAX 11 /* XXX or #define _KERNEL */
|
# define orig_rax regs[_REG_RAX]
|
||||||
# define orig_eax regs[_REG32_EAX]
|
|
||||||
# elif defined(__i386__)
|
# elif defined(__i386__)
|
||||||
# define orig_eax r_eax
|
# define orig_eax r_eax
|
||||||
# endif
|
# endif
|
||||||
|
|
107
src/strace.c
107
src/strace.c
|
@ -27,9 +27,22 @@
|
||||||
|
|
||||||
|
|
||||||
/* strace */
|
/* strace */
|
||||||
|
/* private */
|
||||||
|
/* prototypes */
|
||||||
|
static int _strace(char * argv[]);
|
||||||
|
|
||||||
static int _strace_error(char const * message, int ret);
|
static int _strace_error(char const * message, int ret);
|
||||||
static int _strace_parent(pid_t pid);
|
static int _strace_parent(pid_t pid);
|
||||||
|
|
||||||
|
static int _strace_handle(pid_t pid, int res);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static void _strace_regs_print(struct reg * regs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
/* strace */
|
||||||
static int _strace(char * argv[])
|
static int _strace(char * argv[])
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
@ -41,13 +54,16 @@ static int _strace(char * argv[])
|
||||||
return _strace_error("fork", 1);
|
return _strace_error("fork", 1);
|
||||||
if(pid == 0)
|
if(pid == 0)
|
||||||
{
|
{
|
||||||
ptrace(PT_TRACE_ME, -1, NULL, (ptrace_data_t)NULL);
|
/* child */
|
||||||
|
ptrace(PT_TRACE_ME, -1, NULL, (ptrace_data_t)0);
|
||||||
execvp(argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
return _strace_error(argv[0], 1);
|
return _strace_error(argv[0], 1);
|
||||||
}
|
}
|
||||||
return _strace_parent(pid);
|
return _strace_parent(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* strace_error */
|
||||||
static int _strace_error(char const * message, int ret)
|
static int _strace_error(char const * message, int ret)
|
||||||
{
|
{
|
||||||
fputs("strace: ", stderr);
|
fputs("strace: ", stderr);
|
||||||
|
@ -55,48 +71,97 @@ static int _strace_error(char const * message, int ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _handle(pid_t pid, int res);
|
|
||||||
|
/* strace_parent */
|
||||||
static int _strace_parent(pid_t pid)
|
static int _strace_parent(pid_t pid)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
waitpid(pid, &status, 0);
|
if(waitpid(pid, &status, 0) == -1)
|
||||||
if(_handle(pid, status) != 0)
|
return -_strace_error("waitpid", 1);
|
||||||
|
if(_strace_handle(pid, status) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _handle(pid_t pid, int status)
|
|
||||||
{
|
|
||||||
struct user context;
|
|
||||||
int size = sizeof(stracecall) / sizeof(*stracecall);
|
|
||||||
|
|
||||||
|
/* strace_handle */
|
||||||
|
static void _handle_trap_before(pid_t pid);
|
||||||
|
static void _handle_trap_after(pid_t pid);
|
||||||
|
|
||||||
|
static int _strace_handle(pid_t pid, int status)
|
||||||
|
{
|
||||||
if(!WIFSTOPPED(status))
|
if(!WIFSTOPPED(status))
|
||||||
return -1;
|
return -1;
|
||||||
switch(WSTOPSIG(status))
|
switch(WSTOPSIG(status))
|
||||||
{
|
{
|
||||||
case SIGTRAP:
|
case SIGTRAP:
|
||||||
ptrace(PT_GETREGS, pid, NULL,
|
/* examine the system call */
|
||||||
(ptrace_data_t)&context);
|
_handle_trap_before(pid);
|
||||||
if(context.regs.orig_eax >= 0
|
/* execute the system call */
|
||||||
&& context.regs.orig_eax < size)
|
ptrace(PT_SYSCALL, pid, (caddr_t)1, (ptrace_data_t)0);
|
||||||
fprintf(stderr, "%s();\n", stracecall[
|
/* examine the return value and data */
|
||||||
context.regs.orig_eax]);
|
_handle_trap_after(pid);
|
||||||
else
|
/* wait until the next syscall */
|
||||||
fprintf(stderr, "%ld\n", context.regs.orig_eax);
|
ptrace(PT_SYSCALL, pid, (caddr_t)1, (ptrace_data_t)0);
|
||||||
ptrace(PT_SYSCALL, pid, NULL, (ptrace_data_t)NULL);
|
|
||||||
wait(0);
|
|
||||||
ptrace(PT_SYSCALL, pid, NULL, (ptrace_data_t)NULL);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ptrace(PT_CONTINUE, pid, NULL, WSTOPSIG(status));
|
ptrace(PT_CONTINUE, pid, (caddr_t)1, WSTOPSIG(status));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _handle_trap_before(pid_t pid)
|
||||||
|
{
|
||||||
|
struct user context;
|
||||||
|
int size = sizeof(stracecall) / sizeof(*stracecall);
|
||||||
|
|
||||||
|
ptrace(PT_GETREGS, pid, &context, 0);
|
||||||
|
#ifdef DEBUG
|
||||||
|
_strace_regs_print(&context.regs);
|
||||||
|
#endif
|
||||||
|
#if defined(__amd64__)
|
||||||
|
if(context.regs.orig_rax >= 0 && context.regs.orig_rax < size)
|
||||||
|
fprintf(stderr, "%s();", stracecall[context.regs.orig_rax]);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%ld", context.regs.orig_rax);
|
||||||
|
#elif defined(__i386__)
|
||||||
|
if(context.regs.orig_eax >= 0 && context.regs.orig_eax < size)
|
||||||
|
fprintf(stderr, "%s();", stracecall[context.regs.orig_eax]);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%ld", context.regs.orig_eax);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _handle_trap_after(pid_t pid)
|
||||||
|
{
|
||||||
|
struct user context;
|
||||||
|
|
||||||
|
ptrace(PT_GETREGS, pid, &context, 0);
|
||||||
|
#ifdef DEBUG
|
||||||
|
_strace_regs_print(&context.regs);
|
||||||
|
#endif
|
||||||
|
#if defined(__amd64__)
|
||||||
|
fprintf(stderr, " => %ld\n", context.regs.orig_rax);
|
||||||
|
#elif defined(__i386__)
|
||||||
|
fprintf(stderr, " => %ld\n", context.regs.orig_eax);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
/* strace_regs_print */
|
||||||
|
static void _strace_regs_print(struct reg * regs)
|
||||||
|
{
|
||||||
|
#if defined(__amd64__)
|
||||||
|
fprintf(stderr, "rax: 0x%016lx\n", regs->orig_rax);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* usage */
|
/* usage */
|
||||||
static int _usage(void)
|
static int _usage(void)
|
||||||
|
@ -117,7 +182,7 @@ int main(int argc, char * argv[])
|
||||||
default:
|
default:
|
||||||
return _usage();
|
return _usage();
|
||||||
}
|
}
|
||||||
if(argc - optind <= 1)
|
if(argc - optind < 1)
|
||||||
return _usage();
|
return _usage();
|
||||||
return (_strace(&argv[optind]) == 0) ? 0 : 2;
|
return (_strace(&argv[optind]) == 0) ? 0 : 2;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user