问题
I am trying to write my own _start function using inline assembly. But when I try to read argc and argv from stack (%rsp and %rsp + 8) I get wrong values. I don't know what I am doing wrong.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <syscall.h>
int main(int argc, char *argv[]) {
printf("%d\n", argc);
printf("%s\n", argv[0]);
printf("got here\n");
return 0;
}
void _start() {
__asm__(
"xor %rbp, %rbp;"
"movl (%rsp), %edi;"
"lea 8(%rsp), %rsi;"
"xor %rax, %rax;"
"call main"
...
Terminal:
$ gcc test.c -nostartfiles
$ ./a.out one two three
0
Segmentation fault (core dumped)
$
Any idea where my fault could be ? I am using a Ubuntu 20.04 VM
回答1:
This looks correct for a minimal _start:
but you put it inside a non-naked
C function. Compiler-generated code will run, e.g. push %rbp
/ mov %rsp, %rbp
, before execution enters before the asm statement. To see this, look at gcc -S
output, or single-step in a debugger such as GDB.
Put your asm statement at global scope (like in How Get arguments value using inline assembly in C without Glibc?) or use __attribute__((naked))
on your _start()
. Note that _start
isn't really a function
As a rule, never use GNU C Basic asm statements in a non-naked function. Although you might get this to work with -O3
because that would imply -fomit-frame-pointer
so the stack would still be pointing at argc and argv when your code ran.
A dynamically linked executable on GNU/Linux will run libc startup code from dynamic linker hooks, so you actually can use printf
from _start
without manually calling those init functions. Unlike if this was statically linked.
However, your main
tries to return to your _start
, but you don't show _start
calling exit
. You should call exit
instead of making an _exit system call directly, to make sure stdio buffers get flushed even if output is redirected to a file (making stdout full buffered). Falling off the end of _start
would be bad, crashing or getting into an infinite loop depending on what execution falls in to.
来源:https://stackoverflow.com/questions/65169694/linux-getting-terminal-arguments-from-start-not-working-with-inline-assembly-in