我尝试了这段代码(来自http://www.linuxjournal.com/article/6100?page=0,1):
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/syscall.h>
int main()
{ pid_t child;
long orig_eax, rax;
long params[3];
int status;
int insyscall = 0;
struct user_regs_struct regs;
child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl("/bin/ls", "ls", NULL);
}
else {
while(1) {
wait(&status);
if(WIFEXITED(status))
break;
orig_eax = ptrace(PTRACE_PEEKUSER,
child, 8 * ORIG_RAX,
NULL);
if(orig_eax == SYS_write) {
if(insyscall == 0) {
/* Syscall entry */
insyscall = 1;
ptrace(PTRACE_GETREGS, child,
NULL, ®s);
printf("Write called with "
"%ld, %ld, %ld\n",
regs.rdi, regs.rsi,
regs.rdx);
}
else { /* Syscall exit */
rax = ptrace(PTRACE_PEEKUSER,
child, 8 * RAX,
NULL);
printf("Write returned "
"with %ld\n", rax);
insyscall = 0;
}
}
ptrace(PTRACE_SYSCALL, child,
NULL, NULL);
}
}
return 0;
}
这很有效。寄存器rdi获得似乎正确的值。关键是我有一个其他代码返回我的空寄存器,我找不到原因。这是:
void father_part(pid_t pid)
{
int status;
int rax;
wait4(pid, &status, 0, 0);
while (!WIFEXITED(status))
{
rax = ptrace(PTRACE_PEEKUSER, pid, ORIG_RAX * 8, NULL);
if (rax > 0)
{
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, pid, 0, ®s);
printf("%x\n", regs.rdi); // Here rdi is always NULL
}
ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
wait4(pid, &status, 0, 0);
}
}
void child_part(char **av)
{
ptrace(PTRACE_TRACEME, 0, 0, 0);
if (execvp(av[1], &av[1]) == -1)
perror(av[1]);
exit(0);
}
void trace_proc(char **av)
{
pid_t pid;
pid = fork();
if (pid == 0)
child_part(av);
else
father_part(pid);
}
int main(int ac, char **av)
{
if (ac == 2)
trace_proc(av);
return (0);
}
有人能找到第二个代码的错误吗?