views:

1117

answers:

2

Hi,

Why does this print garbage instead of exiting my program gracefully? I use system calls this way on BSD, and I wonder what would I need to make it work in Linux.

int
main(int argc, char **argv)
{
    __asm ("movq $1,%rax; movq $0,%rdi; syscall"); /* exit(0) ? */
    return 0;
}

Thanks.

+2  A: 

Syscall 1 is exit on i386 but write on x86-64 I believe.

EDIT: this seems inaccurate: According to the web, which does not seem to have too much information about x86-64 Linux assembly this seems to be the expected register setup before the syscall instruction.

 rax  system call number
 rbx  arg0
 rcx  return address from syscall
 rdx  arg2
 rsi  arg3
 rdi  arg4
 r8   arg5
 r9   arg1    (expected by gcc in %rcx)
 r10-r15  should be saved/restored by C code
 rbp  dito What is dito??
Sean A.O. Harney
Hmm, is this register information wrong? Is rdi for arg1 as OP suggests?
Sean A.O. Harney
Yes. The order is rdi,rsi,rdx,... like in regular functions with the syscall number going to rax. This might have been true for the first Linux x86_64 versions that maybe copied the i386 abi, but I don't know for sure. Anyways in this case a bad value for arg1, etc. couldn't have possibly caused the problem as exit will always succeed and terminate the process.
jbcreix
Yes, I was pretty sure the main issue was due to it using NR_write instead of NR_exit, but thought that the argument might be off also!
Sean A.O. Harney
+11  A: 

Why does this print garbage instead of exiting my program gracefully?

Per CESA-2009-001, "Syscall 1 is exit on i386 but write on x86_64".

what would I need to make it work in Linux

Use the syscall ordinals from the current unistd_64.h

Hope this helps!

Marsh Ray
thank you! this is it. I don't know why they had to change it though. So BSD uses the traditional numbers while Linux 64 has changed them. This means I cannot reuse my code though :(
jbcreix
@jbcreix, out of curiosity *why* would you do this instead of using the portable calls `exit()` and `write()`? Isn't this just asking for trouble?
RBerteig
The portable calls need linking to glibc or other C libraries. This way I can implement only the functions I need the way I need and independent from the OS. Of course static linking would achieve a similar result, but then there are licensing issues with GPL code.
jbcreix
@jbcreix It looks like they changed them to conform to some common ABI. The definitions for i386 were in "entry.S", for x64 it's "unistd_64.h".@RBerteig Sometimes one just needs a challenge. Like writing an executable without linking to anything! It can also be a useful technique in security applications and exploit code.
Marsh Ray