Ptrace provides the ptrace_singlestep command to implement single-step debugging for sub-processes. During one-step debugging, the kernel blocks each command executed in the sub-process and then gives control to the parent process. The parent process can view the sub-process variables and register values, complete program debugging.
The following is a program compiled by sink that finds the maximum number from three numbers. File Name: find_maxnum.s
1. section. data 2 var1: 3. long 23 4 var2: 5. long 46 6 var3: 7. long 89 8. section. text 9. global main 10 main: 11 movl (var1), % ECx 12 CMPL (var2), % ECx 13 JG find_maxnum; // JG, B indicates that B> = A redirects to 14 movl (var2), % ECx 15 find_maxnum: 16 CMPL (var3), % ECx 17 JG exit_func 18 movl (var3), % ECx 19 exit_func: 20 movl $4, % eax; execute the write call (system call number is 4) 21 movl % ECx, % EBX 22 int $0x80 23 movl $1, % eax; execute exit Call (system call number: 1) 24 movl $0, % EBX 25 int $0x80 26
The above program was written in at&t's assembly language, which is different from Intel's. Find the maximum number from the three numbers, 46, and 89, and store the result in EBX storage.
Use gcc-O find_maxnum find_maxnum.s for compilation.
The tracing program is as follows. The file name is ptrace_singlestep.c.
#include<sys/ptrace.h>#include<sys/types.h>#include<sys/wait.h>#include<unistd.h>#include<asm/user.h>#include<sys/syscall.h>int main(){pid_t child;int status;int start=0;struct user_regs_struct regs;child=fork();if(-1==child) printf("fork error/n");else if(0==child) { ptrace(PTRACE_TRACEME,child,NULL,NULL); execl("./find_maxnum","find_maxnum",NULL); }else { while(1) { wait(&status); if(WIFEXITED(status)) break;ptrace(PTRACE_GETREGS,child,NULL,®s);if(1==start){printf("ebx register value =%ld/n",regs.ebx);printf("eip:excuted instruction pointer %lx/n",regs.eip);}if(regs.orig_eax==SYS_write){start=1;ptrace(PTRACE_SINGLESTEP,child,NULL,NULL);} else ptrace(PTRACE_SYSCALL,child,NULL,NULL); } }return 0;}
In a sub-process, run the ptrace_traceme command to identify the sub-process to be tracked. After executing the execl function, the parent process starts tracing after receiving the sub-process system call.
Use gcc-O ptrace_singlestep ptrace_singlestep.c
After the./ptrace_singlestep command is executed, the output result is:
EBX register value = 89
EIP: excuted instruction pointer
804835f
EBX register value = 89
EIP: excuted instruction pointer 8048364
EBX register value = 0
EIP: excuted instruction pointer 804836b
The value of EBX in the third row is 0, which is set to 0 in the exit function.
We can see that the parent process ptrace_singlestep implements the single-step tracking of the child process find_maxnum, and views the value of the sub-process EBX register, that is, the maximum of the three.