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

Reply via email to