[PATCH] D105968: [libunwind][CET] Support exception handling stack unwind in CET environment

xiongji90 via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 2 01:39:12 PDT 2021


xiongji90 added inline comments.


================
Comment at: libunwind/src/UnwindLevel1.c:47
+#if !defined(_LIBUNWIND_CET_ENABLED)
+#define __unw_phase2_resume(cursor, fn) __unw_resume((cursor))
+#elif _LIBUNWIND_CET_ENABLED == 1
----------------
compnerd wrote:
> xiongji90 wrote:
> > compnerd wrote:
> > > Why does this have to be a macro?  Can we just define the function instead?
> > Hi, @compnerd 
> > In previous version, I defined a function the code looks like following:
> > void __unw_phase2_resume(cursor, fn) {
> > __LIBUNWIND_POP_CET_SSP(...);
> > ....
> > ....
> > __asm__ volatile(....)
> > }
> > The stack layout looks like following if compiler doesn't do any optimization to __unw_phase2_resume:
> > _____________________
> > .....user functions
> > ______________________
> > __cxx_throw
> > _______________________
> > _Unwind_RaiseException
> > _______________________
> > unwind_phase2
> > _______________________
> > __unw_phase2_resume
> > ________________________
> > 
> > Under such circumstances, the stack frame for __unw_phase2_resume will be skipped too and we must adjust CET shadow stack for it.
> > However, as we can see, the __unw_phase2_resume will never return. I am afraid compiler may directly jump to this function instead of "call" it. If so, there will be no stack frame for __unw_phase2_resume and if compiler uses "jmp" to jump to it instead of calling it, we mustn't adjust CET shadow stack for it.
> > In our source code, we can't know whether compiler will do such optimization and we can't decide whether we should adjust CET shadow stack for __unw_phase2_resume. So I used macro here to avoid this problem.
> > I used inline asm to jump to __libunwind_Registers_x86_64_jumpto for the same purpose.
> > Thanks very much.
> I wonder if we can get away with some combination of `noinline`, and pragmas for `no-optimize-sibling-calls`.
Hi, @compnerd 
I think using combination of following:
1. using __attribute__((noinline)) to decorate target functions
2. building source file containing target functions with -fno-optimize-sibling-calls
can help us to get away with the issue mentioned above. I only found gcc/clang compiling options for "-fno-optimize-sibling-calls" and didn't find corresponding pragma or attribute, so if we choose to use "-fno-optimize-sibling-calls", tail call optimization for other functions will be disabled too which seems to be overshooting.
And if choosing the combination of "noinline" and "-fno-optimize-sibling-calls", we are relying on gcc/clang's implementation which is a implicit dependency, using macro here should be safe to all compilers.

Thanks very much.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D105968/new/

https://reviews.llvm.org/D105968



More information about the llvm-commits mailing list