This is the mail archive of the
mailing list for the GDB project.
How does gdb handle syscall restarting on Linux?
- From: Scott Long <smxlong at gmail dot com>
- To: gdb at sourceware dot org
- Date: Wed, 25 Mar 2009 17:05:02 -0700
- Subject: How does gdb handle syscall restarting on Linux?
I'm developing a lightweight process control library for Linux,
essentially a wrapper around ptrace() but with the ability to inject
code into processes for instrumentation ("attach and profile"
functionality). I've hit an issue which I'm sure gdb must also
encounter, and was wondering how gdb deals with it.
I've already perused the gdb source, but can't find the relevant code.
What I am observing is that I attach to a process, wait for it to
stop, poke some code into memory as well as a stack frame, twiddle ESP
and EIP, then restart the process.
The symptom is that the process attempts to execute from an EIP value
which is 2 less than the value I set it to. In this case, this EIP
value points to an invalid address, and the inferior process crashes
when I attempt to restart it.
What I believe has happened is that the SIGSTOP which was delivered
when I attached, interrupted a system call in the inferior process.
The kernel is now trying to restart this system call by adjusting EIP
by -2 (the size of an "int 0x80" instruction).
How can I detect this situation, and more importantly, how do I handle
it? A few thoughts have occurred to me.
1. I could check if the current EIP is somewhere in the vDSO region,
and if so, assume that I've interrupted a system call. Restart the
process and try again, until I'm not in the vDSO any more.
2. Similar to 1, but "keep on trucking" by adding 2 to my EIP value to
account for the -2 the kernel will set -- then adjust the original EIP
by -2 as if the kernel had done it.
3. Ignore the issue, and place a pad page full of NOP instructions
immediately prior to the injected code. Now it doesn't matter than EIP
is off, it will just follow the NOPs until it hits the real code.
My concern is that I don't want to damage process semantics by doing
something invalid, like causing a system call or a signal to silently
It seems like gdb MUST be able to deal with this. If there is code in
gdb which does this, I'd love to have a pointer to it, to avoid
wasting anybody's time here.