您的位置:首页 > 其它

playing with ptrace(Part I) 之四 --- Single-Stepping

2012-06-22 17:29 507 查看
文章出处:http://www.linuxjournal.com/article/6100?page=0,2

Nov 01, 2002 By Pradeep Padala

in

SysAdmin

ptrace提供了在子进程中进行单步调试的功能。通过调用ptrace(PTRACE_SINGLESTEP,..)就可以通知内核在子进程执行每一条指令时,都对其进行暂停,并将控制权交给父进程。下面的例子展示了当系统调用发生时如何读取正在执行的指令的方法。我写了一个小例子以便你能够理解到底发生了什么,而不是纠缠于libc产生的调用中。

下面是dummy1.s的程序清单。它是用汇编语言写的,使用gcc -o dummy1 dummy1.s来进行编译:

.data
hello:
.string "hello world\n"
.globl  main
main:
movl    $4, %eax
movl    $2, %ebx
movl    $hello, %ecx
movl    $12, %edx
int     $0x80
movl    $1, %eax
xorl    %ebx, %ebx
int     $0x80
ret

单步调试的例程如下:

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/user.h>
#include <sys/syscall.h>
int main()
{   pid_t child;
const int long_size = sizeof(long);
child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl("./dummy1", "dummy1", NULL);
}
else {
int status;
union u {
long val;
char chars[long_size];
}data;
struct user_regs_struct regs;
int start = 0;
long ins;
while(1) {
wait(&status);
if(WIFEXITED(status))
break;
ptrace(PTRACE_GETREGS,
child, NULL, ®s);
if(start == 1) {
ins = ptrace(PTRACE_PEEKTEXT,
child, regs.eip,
NULL);
printf("EIP: %lx Instruction "
"executed: %lx\n",
regs.eip, ins);
}
if(regs.orig_eax == SYS_write) {
start = 1;
ptrace(PTRACE_SINGLESTEP, child,
NULL, NULL);
}
else
ptrace(PTRACE_SYSCALL, child,
NULL, NULL);
}
}
return 0;
}


程序输出如下:

hello world
EIP: 8049478 Instruction executed: 80cddb31
EIP: 804947c Instruction executed: c3

你可以通过查阅Inter的手册来了解具体指令的含义。使用单步实现更复杂的功能,如设置断点等,则需要更加仔细的设计和更加复杂的代码实现。

在Part II中,我们将看到断点是怎样被插入到程序中的以及如何向一个正在运行中的程序中诸如代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: