Reputation: 2101
I'm attaching to a process with ptrace(PTRACE_ATTACH...) while it is in a syscall (like nanosleep()). I can use PTRACE_GETREGS to get the register contents, and eip is at expected location (in __kernel_vsyscall). However, eax and orig_eax registers have unexpected contents: eax usually contains -516, and orig_eax is usually 0.
This is the test program I used (taken from http://www.linuxjournal.com/article/6210 and slightly modified):
#include <stdlib.h>
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
int main(int argc, char *argv[])
{
pid_t traced_process;
struct user_regs_struct regs;
long ins;
if(argc != 2) {
printf("Usage: %s <pid to be traced>\n",
argv[0]);
exit(1);
}
traced_process = atoi(argv[1]);
ptrace(PTRACE_ATTACH, traced_process,
NULL, NULL);
wait(NULL);
ptrace(PTRACE_GETREGS, traced_process,
NULL, ®s);
printf("eax: %lx (%d); orig_eax: %lx\n",
regs.eax, (int)regs.eax, regs.orig_eax);
ins = ptrace(PTRACE_PEEKTEXT, traced_process,
regs.eip, NULL);
printf("EIP: %lx Instruction executed: %lx\n",
regs.eip, ins);
ptrace(PTRACE_DETACH, traced_process,
NULL, NULL);
return 0;
}
Output when attaching to a "sleep 10000" command running in another terminal:
eax: fffffdfc (-516); orig_eax: 0
EIP: b7711424 Instruction executed: c3595a5d
What does the value in eax mean? Why doesn't orig_eax contain the original syscall number (like 162)? And how do I actually get the system call number in this case?
Also, why does gdb correctly shows "162" for "print $orig_eax"?
Btw. this is on Ubuntu 12.04, with kernel 3.2.0:
which sleep
: "/bin/sleep: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x0965431bde4d183eaa2fa3e3989098ce46b92129, stripped".So it's a 32-bit PAE kernel and 32-bit Ubuntu installation on 64-bit CPU.
Upvotes: 3
Views: 1890
Reputation: 349
When the sleeping process is stopped by ptrace(PTRACE_ATTACH), The tracer process can get the registers(user_regs_struct) information. The system call number is 162, which is the sys_nanosleep, the eax=-516 indicates return value of this interrupted syscall.
Upvotes: 0
Reputation: 11
When you attached to the process, a signal was sent to the process which interrupted any syscalls in progress. Most syscalls just return -EINTR if this happens and expect the userspace code to restart them if wanted. There are other syscalls which can automatically restart themselves, but that's a bigger topic.
In the case of some syscalls, of which nanosleep() is one, the process has already slept for part of the specified time, so instead of restarting from the beginning you want to sleep for just the remaining time. To achieve this, each thread has a "restart block" in kernel space. When the syscall is interrupted, it fills in the restart block, and returns -516 (ERESTART_RESTARTBLOCK). The kernel treats this return code specially: it rewinds the pc to before the syscall and changes the syscall number to "restart_syscall" (0 on your architecture). When the process is restarted, it will apparently call restart_syscall which uses the restart block to figure out what to do.
This restarting is intended to be normally invisible to the user but ptrace is one way to spot it. However I don't know GDB manages to get the right value for orig_eax.
Upvotes: 1
Reputation: 213375
This is on Ubuntu 12.04, with kernel 3.2.0
This doesn't uniquely identify your system. What processor?
My crystal ball tells me that sleep
you are invoking is a 64-bit program, while your tracer program is not. Or vice versa.
Upvotes: 0