Ptrace read errno value in child process

Viewed 313

How does strace get errno from failed system calls in the process it traces?

For example, if I do strace ls, strace displays the symbolic errno value (e.g. ENOENT) when a call fails. I know that strace uses ptrace under the hood.

If I am using ptrace to trace a processes system calls, how can I read the value of errno in the traced process?

More specifically, how do I get the address of errno in the child process, so that I can read it using PTRACE_PEEKDATA or process_vm_readv?

Thanks

1 Answers

Following the system call, you'll need to get the registers, specifically rax. If the system call failed then the value for rax will be a high number such as 0xFFFFFFFFFFFFFFF4. errno is calculated by negating this number like so:

-0xFFFFFFFFFFFFFFF4 = 0xFFFFFFFFFFFFFFFF - 0xFFFFFFFFFFFFFFF4 + 1 = 0xC = 12

Once you have errno, you can look it up in errno.h. The location is a bit different on different systems; if you're having trouble finding it you can run echo "#include <errno.h>" | gcc -E -, which will print out the location. In this example the error is ENOMEM.

Related