https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66960
Bug ID: 66960 Summary: Add a builtin to get the address of the current stack frame Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: hjl.tools at gmail dot com Target Milestone: --- The initial i386 stack layout is: environ 4*argc + 4 + %esp 0 4 bytes envp 8 + 4*argc + %esp N * 4 bytes 0 4 + 4*argc + %esp 4 bytes argv %esp + 4 4*argc bytes argc %esp 4 bytes To get argc, argv and environ in C, we can use --- extern char **environ; extern void exit (int status); extern int main (int argc, char **argv, char **envp); void _start (void) { void *argc_p = __builtin_frame_address (0) + 4; char **argv = (char **) (argc_p + 4); int argc = *(int *) argc_p; int status; environ = argv + argc + 1; status = main (argc, argv, environ); exit (status); } --- With -O2 -m32 -miamcu, we generate _start: pushl %ebp movl %esp, %ebp movl 4(%ebp), %eax leal 8(%ebp), %edx leal 4(%edx,%eax,4), %ecx movl %ecx, environ call main call exit .size _start, .-_start %ebp is used since __builtin_frame_address always keeps the frame pointer. With a new builtin, __builtin_current_frame, which returns the top of the stack frame, we can use --- extern char **environ; extern void exit (int status); extern int main (int argc, char **argv, char **envp); void _start (void) { void *argc_p = __builtin_current_frame (); char **argv = (char **) (argc_p + 4); int argc = *(int *) argc_p; int status; environ = argv + argc + 1; status = main (argc, argv, environ); exit (status); } --- and generate _start: movl (%esp), %eax leal 4(%esp), %edx leal 8(%esp,%eax,4), %ecx movl %ecx, environ call main call exit .size _start, .-_start We can avoid using %ebp. __builtin_current_frame may not be the best name. We can use __builtin_stack_top, __builtin_top_of_stack, which gives us the stack address when the function is called.