6

When a syscall returns, I get the syscall return value in %eax, however on entry I am getting -38, which is 0xFFFFFFDA in hex. This is for both write/read. What is this number? Can it be used to safely differentiate an entry from an exit?

ofosho
  • 433
  • 1
  • 5
  • 15
  • 1
    Can you explain what you mean by "on entry"? – Mr. Shickadance Mar 31 '11 at 18:34
  • @Mr. Shickadance, As I understand it, there are two parts to a sys_call. When it is made/sent to the kernel, which I am referring to as entry, and when the kernel finishes and it returns, which I refer to as exit. So entry/exit would be entering/leaving kernel space. – ofosho Mar 31 '11 at 18:46
  • After entering kernel space, kernel code is run. Your code after the syscall will only run after the kernel returns (exits). – ughoavgfhw Mar 31 '11 at 18:51
  • @ughoavgfhw, I am using ptrace to follow an appplication. So as the call is made (or entering) I am inspecting the %eax, and it is -38. When the call returns (or exits) I am checking the %eax again and getting a file descriptor, or useful error. I just want to know what the %eax is when the call is given to the kernel, and I read it. There is a reason the kernel saves orig_eax, I want to know what happens to %eax after save that results in -38, but I cannot seem to find that anywhere. – ofosho Mar 31 '11 at 18:56
  • I reproduce this with `ptrace GETREGS`. The right way to get the system call number seems to be to use `PTRACE_PEEKUSER` + `ORIG_EAX`: https://github.com/nelhage/ministrace/blob/for-blog/ministrace.c – Ciro Santilli OurBigBook.com Aug 08 '15 at 12:09

2 Answers2

7

The -38 in eax on syscall entry is apparently ENOSYS (Function not implemented), and is put there by syscall_trace_entry in arch/x86/kernel/entry_32.S. I suppose it's safe to assume that it will always be there on syscall entry, however it can also be there on syscall exit, if the syscall returns ENOSYS.

Personally, I have always just kept track of whether I'm in syscall entry or exit when using ptrace, although I have seen some code relying on the ENOSYS too. (I'm assuming you're using ptrace) I guess that won't work if the process happens to be inside a syscall when you attach to it, but I have been lucky enough to not bump into that problem.

I took a quick look at strace sources, and I guess it keeps track of the state too, since there was a comment saying "We are attaching to an already running process. Try to figure out the state of the process in syscalls, to handle the first event well." and slightly after that it said "The process is asleep in the middle of a syscall. Fake the syscall entry event.".

In short, the value can't be safely used to differentiate an entry from an exit. That said, I'm not sure that tracking it manually is the best method, since I haven't really got any source which would definitely tell you to use that technique, sorry. :)

Aleksi Torhamo
  • 6,452
  • 2
  • 34
  • 44
  • "syscall_trace_entry in arch/x86/kernel/entry_32.S" That's what I needed. Thanks! – ofosho Mar 31 '11 at 20:37
  • It can definitely be `-ENOSYS` on exit - checking the source shows that many syscalls can return this. – caf Apr 01 '11 at 06:13
  • @caf Thanks, I totally missed that. I was somehow confusing syscall entry with exit when I was thinking about it, thinking that you'd need to do a syscall with ENOSYS as the syscall number to achieve it, and that it depended on whether the invalid syscall would be dropped before getting to ptrace. I've updated the answer. – Aleksi Torhamo Apr 01 '11 at 10:29
0

I still not get when you get the -38 in eax, but when doing a syscall eax contains a number that defines the syscall (in a 2.6 Kernel you can have a look at arch/x86/include/asm/unistd_64.h to see the numbers for each call).

So the sequence is the following:

  1. your programm
  2. set eax to syscall (dep on call, also some other regs)
  3. init syscall (via int 0x80)
  4. result of syscall in eax
  5. your programm again

Maybe your question is not so formulated, but if you are not writing kernel code/driver the easiest way to tell, wether you are before syscall entry or after syscall exit is: TRUE when you are in your code ;-). The entry/exit itself happen (more or less) instant in one instruction, so either you are in the syscall (then you would know because it must be some kernel code or the blocking call) or you are not (almost everytime when you debug your code).

flolo
  • 15,148
  • 4
  • 32
  • 57
  • 1
    the comments should clarify the question. I chose an answer. Thanks for the help though, much appreciated! – ofosho Mar 31 '11 at 20:39