On 2018-11-18 14:37:09, Andrew Fish wrote:
> 
> 
> > On Nov 18, 2018, at 4:07 AM, Liu Yu <pedroa....@outlook.com> wrote:
> > 
> > sorry your  path can't fix this issue.   if this path just turn off 
> > optimization option within sec.c not global project.
> > 
> > I have tested different version GCC such as (GCC4,8, GCC5.x, GCC7.x)  
> > and all of them can duplicate this issue  (Ubuntu 16.04, 16.10,18.04 )
> > 
> > I have traced this issue on my hand.
> > 
> > you can see Dispatcher.c (MdeModulePkg/Pei/DIspatcher/) Line 792:
> > 
> > 
> > 790      if (StackOffsetPositive) {
> > 791       SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID 
> > *)SecCoreData + StackOffset);
> > 792      Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + 
> > StackOffset);
> > 793     } else {
> > 794      ..........
> > 795      ..........
> > 796    }
> > 
> >  790 --792 disassembly code
> > 
> >  0x10200f2ca <PeiCheckAndSwitchStack+1030>:    test %r14b,%r14b
> >  0x10200f2cd <PeiCheckAndSwitchStack+1033>:    je 0x10200f2df 
> > <PeiCheckAndSwitchStack+1051>
> >  0x10200f2cf <PeiCheckAndSwitchStack+1035>:    mov 0x38(%rsp),%rax
> >  0x10200f2d4 <PeiCheckAndSwitchStack+1040>:    lea 0x0(%rbp,%rax,1),%r14
> >  0x10200f2d9 <PeiCheckAndSwitchStack+1045>:    lea (%rbx,%rax,1),%rbp
> > 
> >  we can see Private value have been stored in %rbp  (rbp register be 
> > used as general register )   so when call 
> > TemporaryRamSupportPpi->TemporaryRamMigration()
> > 
> 
> The calling conventions define RBP as non-volatile must be preserved
> by callee. Using RBP as the frame pointer is optional.

This is kind of a mess. I think the definition of
EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI is really to blame. It probably
should not have been spec'd as 'change stack and return'. Instead, it
should have been given a new function pointer to switch-stack and call
into.

By returning with a switched stack, we don't really know what the
returning code could do with regard to the stack. For example, it
could have saved the stack value on the stack and then pop it into a
register and somehow switch the stack back to the old stack. It seems
unlikely, but I don't think anything prevents it.

Additionally, there is the issue of rbp/ebp being used as a frame
pointer. This can lead to some variables being used from the temp ram
location after we return from TemporaryRamMigration. (Assuming rbp/ebp
is not adjusted to point to the new stack.)

So, is it safe to adjust rbp? Unknown. It may not be if rbp is not
used as a frame pointer. Is it safe to *not* adjust rbp and
potentially allow the old temp ram stack to be used? Unknown.

Now, if TemporaryRamMigration received a new function to call into, we
can safely assume that the new stack transition would proceed as
expected without having to worry if a compiler is using rbp/ebp as a
framepointer or not.

Another advantage could have been that something like the BasePkg
SwitchStack function could have been used, hopefully preventing people
from trying to write error prone assembly code for
TemporaryRamMigration.

-Jordan

> Is it possible the assembly coder is assuming RBP is a frame
> pointer? That would imply for gcc/clang the correct answer would be
> to have compiler flags force frame pointer usage?
> 
> Assuming -O 0 does something seems like we are matching an
> implementation at a given point in time. I'd rather force the frame
> pointer usage (that is optional in the ABI) if that fixes the RBP
> usage assumption. I guess the other option would be to have
> different assembler if the compiler is using frame pointers or not.
> and I don't think we have that concept.
> 
> Given this is the common frame pointer pattern:
> 
>         pushq   %rbp
>         movq    %rsp, %rbp
> ...
>         popq    %rbp
>         retq
> 
> It follows the calling convention rules even if the frame pointer is
> not in general use. Thus it only seems like you would hit issues
> when you move the stack around.
> 
> Thanks,
> 
> Andrew Fish
> 
> PS Xcode clang always emits the frame pointer. 
> 
> > this function would modify rbp value because it treat rbp as "stack base 
> > address ".
> > 
> > 816     MigrateMemoryPages (Private, TRUE);
> > 
> > // Private pointer point to other address, so this function would get a 
> > NULL pointer that result in segment fault
> > 
> > I think we can turn off optimization options like this.
> > 
> > 1. modify  EmulatorPkg.dsc
> > 
> >       MdeModulePkg/Core/Pei/PeiMain.inf {
> >          <BuildOptions>
> >           GCC:*_*_*_CC_FLAGS = -O0
> >   }
> > 
> > Reference GCC Manual description:
> > 
> >   -O also turns on -fomit-frame-pointer on machines where doing so does 
> > not interfere with debugging.
> > 
> > 
> > 
> > 在 2018/11/18 下午5:27, Jordan Justen 写道:
> >> On 2018-11-17 20:51:11, Liu Yu wrote:
> >>> OS: Ubuntu
> >>> 
> >>> Toolchain:GCC48
> >> I don't have gcc-4.8, so I couldn't reproduce the issue, but I wonder
> >> if this branch can fix the issue for you?
> >> 
> >> https://github.com/jljusten/edk2/tree/emulator-temp-ram
> >> 
> >> You can fetch this branch locally to a branch named `test` with a
> >> command like this:
> >> 
> >> $ git fetch --no-tags https://github.com/jljusten/edk2.git 
> >> emulator-temp-ram:test
> >> 
> >> Then checkout the `test` branch to try it.
> >> 
> >> First, there is some patches to cleanup Sec, but then I added a patch:
> >> 
> >> 53a432e149 "EmulatorPkg/Sec: Disable optimizations for 
> >> TemporaryRamMigration function"
> >> 
> >> Which I hope might help in your case.
> >> 
> >> -Jordan
> >> 
> >>> Issue Description :
> >>> 
> >>>   Program received signal SIGSEGV, Segmentation fault.
> >>>    at 
> >>> /home/pedroa/workspace/orign/edkcrb/MdeModulePkg/Core/Pei/Memory/MemoryServices.c:129
> >>> 129      Private->MemoryPages.Size = (UINTN) 
> >>> (Private->HobList.HandoffInformationTable->EfiMemoryTop -
> >>> 
> >>> 
> >>> if the GCC optimization option is used not -O0 so the "rbp" register will 
> >>> be used as "general register"
> >>> 
> >>> in the SecTemporaryRamSupport function as below, this function will 
> >>> modify the rbp (as general register not stack base address pointer)value 
> >>> that result in program crash.
> >>> 
> >>> ASM_PFX(SecTemporaryRamSupport):
> >>>   // Adjust callers %rbp to account for stack move
> >>>   subq    %rdx, %rbp     // Calc offset of %rbp in Temp Memory
> >>>   addq    %r8,  %rbp     // add in permanent base to offset
> >>> 
> >>> _______________________________________________
> >>> edk2-devel mailing list
> >>> edk2-devel@lists.01.org
> >>> https://lists.01.org/mailman/listinfo/edk2-devel
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to