Thursday, 25 February 2016

assembly - Process command line in Linux 64 bit




I have problems accessing the process command line from Linux 64 bit Assembly program. To reproduce this with minimal code, I made this 32-bit program which prints first 5 characters of the program name:




.section .text

.globl _start
_start:
movl %esp, %ebp


movl $4, %eax # write
movl $1, %ebx # stdout
movl 4(%ebp), %ecx # program name address (argv[0])
movl $5, %edx # hard-coded length
int $0x80

movl $1, %eax
movl $0, %ebx
int $0x80



This program is working. When I translate it to 64 bit and run in Linux 64, it doesn't print anything:




.section .text

.globl _start
_start:
movq %rsp, %rbp


movq $4, %rax
movq $1, %rbx
movq 8(%rbp), %rcx # program name address ?
movq $5, %rdx
int $0x80

movq $1, %rax
movq $0, %rbx
int $0x80



Where is my mistake?


Answer



You are loading the correct address into %rcx.



int 0x80 then invokes the 32-bit syscall interface. That truncates the address to 32 bits, which makes it incorrect. (If you use a debugger and set a breakpoint just after the first int 0x80, you will see that it returns with -14 in %eax, which is -EFAULT.)



The second syscall, exit, works OK because the truncation to 32 bits doesn't do any harm in that case.







If you want to pass a 64-bit address to a system call, you will have to use the 64-bit syscall interface:




  • use syscall, not int 0x80;

  • different registers are used: see here;

  • the system call numbers are different as well: see here.




Here is a working version of your code:



.section .text

.globl _start
_start:
movq %rsp, %rbp

movq $1, %rax
movq $1, %rdi

movq 8(%rbp), %rsi # program name address ?
movq $5, %rdx
syscall

movq $60, %rax
movq $0, %rdi
syscall

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...