From 9f269b41dffa7e1bc67147c1e54212dff318d654 Mon Sep 17 00:00:00 2001 From: diekmann Date: Fri, 11 Aug 2017 12:17:23 +0200 Subject: [PATCH] Improved picture of stack layout * Added dots around envp and argv since those are arrays of pointers. While argc and NULL are just 8B, argv and envp are of variable size, usually more than 8B. The dots visualize this. * In the first image, moved rsp to point to argc. This is the initial stack and register layout at the beginning of _start. Only after libc popped the top of the stack into rsi, rsp will point to beginning of argv. (*) (*) I verified this by writing my own _start implementation: https://github.com/diekmann/x86_64-dump-startup-stack/blob/039ac7c03c4001f0cba4082b4eaf1bdbd2cfefd4/start.asm#L61 --- Misc/program_startup.md | 16 ++++++++++++---- contributors.md | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Misc/program_startup.md b/Misc/program_startup.md index e787ca5..5f680db 100644 --- a/Misc/program_startup.md +++ b/Misc/program_startup.md @@ -280,19 +280,23 @@ STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **), It takes the address of the `main` function of a program, `argc` and `argv`. `init` and `fini` functions are constructor and destructor of the program. The `rtld_fini` is the termination function which will be called after the program will be exited to terminate and free its dynamic section. The last parameter of the `__libc_start_main` is a pointer to the stack of the program. Before we can call the `__libc_start_main` function, all of these parameters must be prepared and passed to it. Let's return to the [sysdeps/x86_64/start.S](https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86_64/start.S;h=f1b961f5ba2d6a1ebffee0005f43123c4352fbf4;hb=HEAD) assembly file and continue to see what happens before the `__libc_start_main` function will be called from there. -We can get all the arguments we need for `__libc_start_main` function from the stack. As `_start` is called, our stack looks like: +We can get all the arguments we need for `__libc_start_main` function from the stack. At the very beginning, when `_start` is called, our stack looks like: ``` +-----------------+ | NULL | +-----------------+ +| ... | | envp | +| ... | +-----------------+ | NULL | +------------------ -| argv | <- rsp +| ... | +| argv | +| ... | +------------------ -| argc | +| argc | <- rsp +-----------------+ ``` @@ -302,11 +306,15 @@ After we cleared `ebp` register and saved the address of the termination functio +-----------------+ | NULL | +-----------------+ +| ... | | envp | +| ... | +-----------------+ | NULL | +------------------ -| argv | <- rsp +| ... | +| argv | +| ... | <- rsp +-----------------+ ``` diff --git a/contributors.md b/contributors.md index f1da0e7..3e3bd2f 100644 --- a/contributors.md +++ b/contributors.md @@ -107,3 +107,4 @@ Thank you to all contributors: * [Stéphan Gorget](https://github.com/phantez) * [Adrian Reyes](https://github.com/int3rrupt) * [JB Cayrou](https://github.com/jbcayrou) +* [Cornelius Diekmann](https://github.com/diekmann)