On Mon, 16 Dec 2024, Florian Weimer via Gcc wrote:
> I would like to provide a facility to create wrapper functions without
> lots of argument shuffling. To achieve that, the wrapping function and
> the wrapped function should have the same prototype. There will be a
> trampoline that puts additional data somewhere (possibly including the
> address of the wrapped function, but that interpretation is up to the
> wrapping function) and then transfers control to the wrapper function
> with an indirect jump (tail call).
>
> For signal safety, I think the hidden argument needs to be in a register
> (instead of, say, thread-local storage). Most System V ABI variants
> seem to reserve a register for use by the dynamic linker, or for the
> static chain pointer of nested functions.
>
> Is there a way to reuse either register for this purpose and assign it
> to a local variable reliably at the start of the wrapper function
> implementation?
Not in a way that will work with LLVM, I'm afraid, and with GCC
you'll have to shield wrappers from LTO:
register void *r10 asm("r10");
void f(int, int);
void f_wrap(int a, int b)
{
r10 = f;
f(a, b);
}
LLVM refuses to translate this. With GCC you must compile with -ffixed-r10,
otherwise r10 is not reserved, and GCC will warn:
warning: call-clobbered register used for global register variable
1 | register void *r10 asm("r10");
| ^~~:
This is the only approach I'm aware of, apart of generating wrappers
in asm (speaking of, is there some reason that wouldn't work for you?).
HTH
Alexander