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.

Reply via email to