[x86/Linux] Set Establisher Frame Pointer as Caller SP (dotnet/coreclr#9264)
authorJonghyun Park <parjong@gmail.com>
Thu, 2 Feb 2017 16:12:07 +0000 (01:12 +0900)
committerJan Kotas <jkotas@microsoft.com>
Thu, 2 Feb 2017 16:12:07 +0000 (08:12 -0800)
Commit migrated from https://github.com/dotnet/coreclr/commit/cfca38899b29d609266c108a69cc828a5791a300

docs/coreclr/botr/clr-abi.md
src/coreclr/src/unwinder/i386/unwinder_i386.cpp

index b100ee9..6719522 100644 (file)
@@ -285,7 +285,7 @@ The PSPSym is a pointer-sized local variable in the frame of the main function a
 
 The VM uses the PSPSym to find other locals it cares about (such as the generics context in a funclet frame). The JIT uses it to re-establish the frame pointer register, so that the frame pointer is the same value in a funclet as it is in the main function body.
 
-When a funclet is called, it is passed the *Establisher Frame Pointer*. For AMD64 this is true for all funclets and it is passed as the first argument in RCX, but for ARM and ARM64 this is only true for first pass funclets (currently just filters) and it is passed as the second argument in R1. The Establisher Frame Pointer is a stack pointer of an interesting "parent" frame in the exception processing system. For the CLR, it points either to the main function frame or a dynamically enclosing funclet frame from the same function, for the funclet being invoked. The value of the Establisher Frame Pointer is Initial-SP on AMD64, Caller-SP on ARM and ARM64.
+When a funclet is called, it is passed the *Establisher Frame Pointer*. For AMD64 this is true for all funclets and it is passed as the first argument in RCX, but for ARM and ARM64 this is only true for first pass funclets (currently just filters) and it is passed as the second argument in R1. The Establisher Frame Pointer is a stack pointer of an interesting "parent" frame in the exception processing system. For the CLR, it points either to the main function frame or a dynamically enclosing funclet frame from the same function, for the funclet being invoked. The value of the Establisher Frame Pointer is Initial-SP on AMD64, Caller-SP on x86, ARM, and ARM64.
 
 Using the establisher frame, the funclet wants to load the value of the PSPSym. Since we don't know if the Establisher Frame is from the main function or a funclet, we design the main function and funclet frame layouts to place the PSPSym at an identical, small, constant offset from the Establisher Frame in each case. (This is also required because we only report a single offset to the PSPSym in the GC information, and that offset must be valid for the main function and all of its funclets). Then, the funclet uses this known offset to compute the PSPSym address and read its value. From this, it can compute the value of the frame pointer (which is a constant offset from the PSPSym value) and set the frame register to be the same as the parent function. Also, the funclet writes the value of the PSPSym to its own frame's PSPSym. This "copying" of the PSPSym happens for every funclet invocation, in particular, for every nested funclet invocation.
 
index b506c61..ca9e28e 100644 (file)
@@ -67,7 +67,6 @@ OOPStackUnwinderX86::VirtualUnwind(
     __deref_opt_out_opt PEXCEPTION_ROUTINE *HandlerRoutine
     )
 {
-    *EstablisherFrame = ContextRecord->Esp;
     if (HandlerRoutine != NULL)
     {
         *HandlerRoutine = NULL;
@@ -108,6 +107,10 @@ OOPStackUnwinderX86::VirtualUnwind(
     ContextRecord->Esp = rd.SP;
     ContextRecord->Eip = rd.ControlPC;
 
+    // For x86, the value of Establisher Frame Pointer is Caller SP
+    //
+    // (Please refers to CLR ABI for details)
+    *EstablisherFrame = ContextRecord->Esp;
     return S_OK;
 }