Am Dienstag, den 18.12.2018, 09:03 -0700 schrieb Jeff Law: > On 12/18/18 8:32 AM, Jakub Jelinek wrote: > > On Tue, Dec 18, 2018 at 10:23:46AM -0500, Paul Koning wrote: > > > > > > > > > > On Dec 17, 2018, at 2:23 PM, Szabolcs Nagy <szabolcs.n...@arm.com> > > > > wrote: > > > > > > > > On 17/12/2018 18:22, Uecker, Martin wrote: > > > > > > > > > > > > ... > > > > > > > > > > So a thread_local static variable for storing the static > > > > > chain? > > > > > > > > something like that, but the more i think about it the > > > > harder it seems: the call site of the nested function > > > > may not be under control of the nested function writer, > > > > in particular the nested function may be called on a > > > > different thread, and extern library apis are unlikely > > > > to provide guarantees about this, so in general if a > > > > nested function escapes into an extern library then > > > > this cannot be relied on, which limits my original > > > > idea again to cases where there is no escape (which i > > > > think is not that useful). > > > > > > I'm not sure I understand "escape" of a nested function pointer. > > > > > > Your description makes it sound like you're talking about a function > > > being called by someone > > > who has been given the pointer, from outside the scope of the function. > > > That sounds like an > > > illegal operation, exactly as it would be if you attempted to reference > > > an automatic variable > > > via a pointer from outside the scope of that variable. > > > > > > Did I misunderstand? > > > > The most common case is when you pass a call to a nested function > > to some function that has a function pointer argument, e.g. qsort. > > This is well defined with GNU nested functions, but the function that calls > > the callback (qsort in this case) doesn't know it is a call to a nested > > function. > > Right. This is the classic example and highlights the ABI concerns. If > we use the low bit to distinguish between a normal function pointer and > a pointer to a descriptor and qsort doesn't know about it, then we lose. > > One way around this is to make *all* function pointers be some kind of > descriptor and route all indirect calls through a resolver. THen you > need either linker hackery or special code to compare function pointers > to preserve ISO C behavior.
If it has to work with existing code and without the restrictions discussed above then you have to create a pointer to a new code address for each nested functions. One possibility which comes to mind would be a shadow stack which is executable (and might contain pre-allocated trampolines). Best, Martin > Note that if you have a nested function and take its address, then go > out of scope of the containing function, then that function pointer is > no longer valid -- which makes perfect sense if you think about it. THe > trampoline was on the stack and if you go out of scope of the containing > function, then that stack frame is invalid and you also don't have a > suitable frame chain to pass to the nested function either. > > > Jeff