Linux 64 command line parameters in Assembly

前端 未结 3 1062
既然无缘
既然无缘 2020-12-19 07:55

This description is valid for Linux 32 bit: When a Linux program begins, all pointers to command-line arguments are stored on the stack. The number of arguments is stored at

相关标签:
3条回答
  • 2020-12-19 08:10

    It looks like section 3.4 Process Initialization, and specifically figure 3.9, in the already mentioned System V AMD64 ABI describes precisely what you want to know.

    0 讨论(0)
  • 2020-12-19 08:23

    Despite the accepted answer being more than sufficient, I would like to give an explicit answer, as there are some other answers which might confuse.

    Most important (for more information see examples below): in x86-64 the command line arguments are passed via stack:

    (%rsp) -> number of arguments
    8(%rsp) -> address of the name of the executable
    16(%rsp) -> address of the first command line argument (if exists)
    ... so on ...
    

    It is different from the function parameter passing in x86-64, which uses %rdi, %rsi and so on.

    One more thing: one should not deduce the behavior from reverse engineering of the C main-function. C runtime provides the entry point _start, wraps the command line arguments and calls main as a common function. To see it, let's consider the following example.

    No C runtime/GCC with -nostdlib

    Let's check this simple x86-64 assembler program, which do nothing but returns 42:

    .section .text
    .globl _start
    _start:   
        movq $60, %rax #60 -> exit
        movq $42, %rdi #return 42
        syscall #run kernel 
    

    We build it with:

    as --64 exit64.s -o exit64.o
    ld -m elf_x86_64 exit64.o -o exit64
    

    or with

    gcc -nostdlib exit64.s -o exit64
    

    run in gdb with

    ./exit64 first second third
    

    and stop at the breakpoint at _start. Let's check the registers:

    (gdb) info registers
    ...
    rsi            0x0  0
    rdi            0x0  0
    ...
    

    Nothing there. What about the stack?

    (gdb) x/5g $sp
    0x7fffffffde40: 4   140737488347650
    0x7fffffffde50: 140737488347711 140737488347717
    0x7fffffffde60: 140737488347724
    

    So the first element on the stack is 4 - the expected argc. The next 4 values look a lot like pointers. Let's look at the second pointer:

    (gdb) print (char[5])*(140737488347711)
    $1 = "first"
    

    As expected it is the first command line argument.

    So there is experimental evidence, that the command line arguments are passed via stack in x86-64. However only by reading the ABI (as the accepted answer suggested) we can be sure, that this is really the case.

    With C runtime

    We have to change the program slightly, renaming _start into main, because the entry point _start is provided by the C runtime.

    .section .text
    .globl main
    main:   
        movq $60, %rax #60 -> exit
        movq $42, %rdi #return 42
        syscall #run kernel 
    

    We build it with (C runtime is used per default):

    gcc exit64gcc.s -o exit64gcc
    

    run in gdb with

    ./exit64gcc first second third
    

    and stop at the breakpoint at main. What is at the stack?

    (gdb) x/5g $sp
    0x7fffffffdd58: 0x00007ffff7a36f45  0x0000000000000000
    0x7fffffffdd68: 0x00007fffffffde38  0x0000000400000000
    0x7fffffffdd78: 0x00000000004004ed
    

    It does not look familiar. And registers?

    (gdb) info registers
    ...
    rsi            0x7fffffffde38   140737488346680
    rdi            0x4  4
    ...
    

    We can see that rdi contains the argc value. But if we now inspect the pointer in rsi strange things happen:

    (gdb) print (char[5])*($rsi)
    $1 =  "\211\307???"
    

    But wait, the second argument of the main function in C is not char *, but char ** also:

    (gdb) print (unsigned long long [4])*($rsi)
    $8 = {140737488347644, 140737488347708, 140737488347714, 140737488347721}
    (gdb) print (char[5])*(140737488347708)
    $9 = "first"
    

    And now we found our arguments, which are passed via registers as it would be for a normal function in x86-64.

    Conclusion: As we can see, the is a difference concerning passing of command line arguments between code using C runtime and code which doesn't.

    0 讨论(0)
  • 2020-12-19 08:28

    I do believe what you need to do is check out the x86-64 ABI. Specifically, I think you need to look at section 3.2.3 Parameter Passing.

    0 讨论(0)
提交回复
热议问题