From 391030ed94b6698a60d644cc6355982ad0bb25a9 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 3fb8183..8e7012e 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 2c813c2..2ec22a6 100644 --- a/contributors.md +++ b/contributors.md @@ -107,3 +107,4 @@ * [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)