According to the System V ABI for x86, esp
should be pointing at argc
when entering main
. However, I've seen many binaries where argc
instead is retrieved from esp + 4
, or esp + 8
. Is this correct, or am I missing something? Also, why do these offset differ?
-
some of your comments were deleted for violating the code of conduct. Please review it.– julian ♦Apr 13, 2020 at 1:10
-
1Consider that "main" is not always the program's entry point. There may be initialisation routines added at compile time before. If this happens, then the init procedure calls "main", pushing argc on the stack. After the call, [ESP] will point to the return address and [ESP+4] will contain argc. At the beginnig of main, a PUSH EBP will move ESP another 4 bytes back, now [ESP+8]=argc.– YotamzApr 13, 2020 at 12:00
-
@Yotamz yes, I figured that much. In that case, neither _start nor main have esp pointing at argc, so neither comply with what the ABI says, correct?– MartinApr 14, 2020 at 13:46
1 Answer
I think your confusion stems from the fact that quoted part of the spec is talking about the process entry point which is a different concept from the C main
function. The main
is called by the C library startup code so it will follow the standard calling sequence rather than "Initial process stack layout". For 386, it means that argc
will be the first value passed on the stack after the return address, and argv
will be the second. I.e. at the beginning of main
, the layout will look like this
| |
+----------------+
| argv | <-- esp+8
+----------------+
| argc | <-- esp+4
+----------------+
| return address | <-- esp
+----------------+
If the compiler decides to use the frame pointer, then argc
will be typically accessed as [ebp+8]
due to the extra 4 bytes taken by the saved ebp
.