I have a statically compiled test binary compiled as :-

$ cat > test.c
int main() {
mprotect(0x8048000, 0x100, 0x7);
$ gcc -o test test.c -static

I use the strace.so pintool and get the following output:-

0xb77c0419: 122(0xbfa1a72a, 0xb77c0000, 0x0, 0x0, 0x8049630, 0xbfa1a6ec)returns: 0x0
0xb77c0419: 45(0x0, 0x840, 0x27, 0xd40, 0x28, 0xbfa1a868)returns: 0x9fda000
0xb77c0419: 45(0x9fdad40, 0x840, 0x9fda000, 0x9fdad40, 0x28, 0xbfa1a868)returns: 0x9fdad40
0x80493b9: 243(0xbfa1a8c0, 0x0, 0x4, 0x4, 0x28, 0x40)returns: 0x0
0xb77c0419: 45(0x9ffbd40, 0x21000, 0x21000, 0x9ffbd40, 0x0, 0xbfa1a728)returns: 0x9ffbd40
0xb77c0419: 45(0x9ffc000, 0x2c0, 0x21000, 0x9ffc000, 0x0, 0xbfa1a728)returns: 0x9ffc000
0xb77c0419: 197(0x1, 0xbfa1a210, 0xbfa1a210, 0x2000, 0x2000, 0xbfa1a1b8)returns: 0x0
0xb77c0419: 192(0x0, 0x1000, 0x3, 0x22, 0xffffffff, 0xbfa1a1cc)returns: 0xb60b6000
0xb77c0419: 125(0x8048000, 0x100, 0x7, 0x0, 0x8049630, 0xbfa1a8d8)returns: 0x0
0xb77c0419: 4(0x1, 0xb60b6000, 0x4, 0x80ef6a0, 0x4, 0xbfa1a778)returns: 0x4
0xb77c0419: 252(0x0, 0x0, 0x80f0d04, 0x0, 0x80ef06c, 0xbfa1a8ac)#eof

We can see that the addresses shown at the left(the IP) have repeating values. Also they don't seem to be addresses in the text segment. I'd like to be able to view the addresses at which the system calls are made.

Why does this happen? The code for the strace pintool can be found here.

[EDIT] Checking in gdb I understand that this happens because the call goes via a common "int 0x80" instruction. As a result, multiple system calls seem to be made from the same address. Hence, it seems like I'd have to read the 4 bytes from the top of the stack to find out which instruction is trying to make the system call. Are there any better ways to do this?


On modern Linux systems, a syscall stub (vdso) is used to invoke the actual syscall. This is done so that the application binary does not need to know anything about the host CPU, and what mechanism is best or fastest for the CPU.

This can be seen from within GDB or via ldd.

ldd /bin/bash
    linux-vdso.so.1 =>  (0x00007fff07fc3000)
    libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f65e336e000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f65e316a000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f65e2da3000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f65e35b6000)

You can easily dump out the instruction being executed with Pin via printing the return value of INS_Disassemble. You should see that it's actually a syscall instruction or similar.

Regarding the best mechanism for determining the source of a call to the VDSO, checking the top of the stack at a routine entry will give you its return address. This will be a few bytes after the call instruction. Additionally, you'd have to whitelist the explicit address which is in the vdso, as not all int 0x80 instructions will be immediately after a call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy