12

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 Answers 2

13

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!

Sign up to request clarification or add additional context in comments.

4 Comments

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, out of curiosity why would you do this instead of using the portable calls exit() and write()? Isn't this just asking for trouble?
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 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.
3

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?? 

3 Comments

Hmm, is this register information wrong? Is rdi for arg1 as OP suggests?
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.
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!