Reputation: 11996
I'm running a 64-bit Debian 4.7.2-5 Linux system, using glibc-2.13-1. While I was searching for the assembly code of some function calls in libc.a
I came across this:
file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <sync>:
0: b9 a2 00 00 00 mov eax,0xa2
5: 0f 05 syscall
7: 48 3d 01 f0 ff ff cmp rax,0xfffffffffffff001
d: 0f 83 00 00 00 00 jae 13 <sync+0x13>
13: c3 ret
I'm a bit confused on what this is doing. What is the point of mov eax,0xa2
and why isn't the rax
register being used if this is a 64-bit machine (how does syscall know what system call to make)? In short: what do these 5 lines of code do?
Upvotes: 2
Views: 910
Reputation: 25318
0xa2 is the syscall number. The kernel uses it to decide what actual function to perform, since the syscall
instruction itself does not contain any information.
As for rax
, it does get used. To continue the tradition started in old days, the eax
is an alias to the low 32 bits of rax
. However, there is one not very well-known quirk of x64 architecture: whenever you modify that low 32-bit part, the top 32-bits get zeroed. So, in fact mov eax, 0xa2
is equivalent to mov rax, 0xa2
, except its encoding is shorter. NASM, or as -O2
, will even do that optimization for you.
The last three instructions perform the error handling. In case %rax
is between -1 and -4095, it means the syscall returned an error, for any Linux system call. Here's how it looks in the original source:
cmpq $-4095, %rax /* Check %rax for error. */
jae __syscall_error /* Branch forward if it failed. */
ret /* Return to caller. */
You see wrong target for the jae
because you're disassembling a relocatable object, and the relocatable fields have been set to 0 since they will be patched at the final link time.
To see the relocation targets, add -r
switch to objdump
command line:
0000000000000000 <sync>:
0: b8 a2 00 00 00 mov $0xa2,%eax
5: 0f 05 syscall
7: 48 3d 01 f0 ff ff cmp $0xfffffffffffff001,%rax
d: 0f 83 00 00 00 00 jae 13 <sync+0x13>
f: R_X86_64_PC32 __syscall_error-0x4
13: c3 retq
You can see that the bytes at offset f
will be patched so that jump goes to __syscall_error
.
Read https://cs.lmu.edu/~ray/notes/syscalls/ for more info on syscalls.
Also The Definitive Guide to Linux System Calls blog article.
Upvotes: 5
Reputation: 10580
mov eax,0xa2
is sufficient to set the entire rax
, because modifying 32-bit general registers such as eax
zeroes always the top 32 bits of the corresponding 64-bit register (in this case rax
).
Syscall number a2
is sync
, see /usr/src/linux/usr/include/asm/unistd_64.h
for the list of Linux x86-64 syscalls (replace /usr/src/linux/
with the directory where you have your Linux source installed).
As a whole, these lines open a file defined already before these instructions, then compare the return value of syscall
(in rax
) with 0xfffffffffffff001
, and then there something a bit strange: 0f 83 00 00 00 00
jae 13
is a conditional jump to the next instruction, that would be reached anyway.
Upvotes: 1