On Wed, Nov 18, 2020 at 02:59:29PM +0100, Florian Weimer wrote: > * Peter Zijlstra: > > > I think that as long as the function is completely empty (it never > > touches any of the arguments) this should work in practise. > > > > That is: > > > > void tp_nop_func(void) { } > > > > can be used as an argument to any function pointer that has a void > > return. In fact, I already do that, grep for __static_call_nop(). > > You can pass it as a function parameter, but in general, you cannot > call the function with a different prototype. Even trivial > differences such as variadic vs non-variadic prototypes matter. I don't think any tracepoint uses variadic argument. > The default Linux calling conventions are all of the cdecl family, > where the caller pops the argument off the stack. You didn't quote > enough to context to tell whether other calling conventions matter in > your case. This is strictly in-kernel, and I think we're all cdecl, of which the important part is caller-cleanup. The function compiles to: RET so whatever the arguments are is irrelevant. > > I'm not sure what the LLVM-CFI crud makes of it, but that's their > > problem. > > LTO can cause problems as well, particularly with whole-program > optimization. I don't think LTO can de-virtualize a dynamic array of function pointers, so there's very little risk. That said, the __static_call_nop case, where everything is inlined, is compiled sub-optimally for both LLVM and GCC.