Where, and why, should the pointer to the x64 framework indicate? (Windows x64 ABI)

I read a long catalog of very good articles on Windows x64 ABI. A very minor aspect of these articles is the description of the frame pointer. The general point is that since the rules of the Windows x64 call stack are so strict, a special frame pointer is usually not needed, although it is optional.

The only exception that I have constantly noted is when alloca() used to dynamically allocate memory on the stack. To perform functions, obviously, a frame pointer is required. For example, to quote from the Microsoft documentation on "Stack Allocation" (italics and highlighted by me):

If space is allocated dynamically (alloca) in a function, then a non-volatile register should be used as the frame pointer to mark the base of the fixed part stack and this register should be saved and initialized in the prolog. Note that when using alloca, calls to the same called party from the same caller can have different home addresses for their register settings.

For this, the Microsoft x64 ABI alloca() documentation smoothly adds:

_alloca is required for 16-byte alignment, and an optional frame pointer is required.

First of all, why should it be used? I assume that an exception is thrown for the call stack, but I have not yet found a satisfactory explanation.

The next question is: where should it indicate? The first of the two quotes above says that "should" be used to denote the base " fixed part of the stack." What is the "fixed portion of the stack"? I get the impression that this term means in this frame a range of addresses that contains (higher addresses for lower ones):

  • Caller’s return address (if you consider it to be part of the current function frame);
  • addresses to which non-volatile registers were saved using the prolog function; and
  • addresses where local variables are stored.

Again, I did not find a satisfactory definition for this "fixed part". The Stack Allocation page that I linked to above contains the diagram below along with the words "if used, the stack pointer will usually point here":

enter image description here

This very wonderful blog post is equally vague, including a diagram in which the frame pointer "points somewhere here", where "here" are addresses for stored non-volatile registers and local users.

The final bit of criticism comes from a Microsoft MSDN article entitled "Dynamic Structure of the Parameter Stack Area" , which contains only this:

If a frame pointer is used, there is an option to dynamically create an area of ​​the parameter stack. This is not currently running on the x64 compiler.

What does "generally" mean? Where is "somewhere here"? Which option is there? Is there a rule? Who cares?

Or, tl; dr: What the name asks. Any response containing an annotated assembly is gratefully accepted.

+8
c assembly windows 64bit calling-convention
source share
2 answers

The diagram clearly shows that the frame pointer points to the bottom of the fixed portion of the local stack frame. The "fixed part" is the part whose size does not change and whose location is fixed relative to the pointer to the initial stack. The diagram shows "Local variables and stored non-volatile registers." [one]

The exact location of the frame pointer does not matter for the operating system, because from a theoretical and theoretical point of view, local variables are indistinguishable from the memory allocated by alloca immediately after entering the function.

 void function1() { int a; int *b = (int*)alloca(sizeof(int)); ... } void function2() { int& a = *(int*)alloca(sizeof(int)); int *b = (int*)alloca(sizeof(int)); ... } 

The operating system cannot distinguish between these two functions. They store a on the stack directly under non-volatile registers.

This equivalence explains why the chart says “generally.” In practice, compilers point it where it is indicated, but theoretically they can point it anywhere inside the local frame if the distance from the frame pointer to the return address is constant.

The function should inform the operating system in which the frame pointer so that the stack can be unwound during exception handling. Without this information, it would be impossible to go through the stack because the frame has a variable size.

[1] You can do this from the fact that the text indicates that the frame pointer points to the "base of the fixed part of the stack", and the diagram says: "The frame pointer will usually point here," and this indicates the base of local variables and saving non-volatile registers. Assuming that the text and the diagram are consistent, this means that the fixed part of the stack matches local variables and preserves non-volatile registers. This is the same conclusion that you make every day without even realizing it. For example, if the story says

Sally called her brother. "Billy, where are you?"

You can conclude that Billy is Sally's brother.

+7
source share

alloca intended for use with a size available only at runtime. Thus, it will change the stack pointer to an amount that is not known at compile time. You can usually address your local variables and arguments on the stack relative to the stack pointer because of the fixed layout, but alloca messes, which therefore requires another stable register. This frame pointer can point anywhere if you know the relation to a fixed area.

The frame pointer is also convenient when it comes time to free alloca memory, because you can simply restore the stack pointer to a known location without worrying about how the stack pointer has changed.

I do not think that ABI requires a frame pointer as such, or it must be rbp or that it must point to a specific place (disclaimer: I do not use windows).

+1
source share

All Articles