Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap variadic functions using LD_PRELOAD?

I have to perform dynamic linking on a variadic function of following format:

int foo(char *args, const char *f, ...)

Here the number of arguments are variable. What I want to achieve is that I want to pass the obtained arguments to the original function which I am resolving using dlsym. If I do not pass all the arguments I keep getting segmentation fault. Thanks in advance.

like image 788
ankit jain Avatar asked Aug 01 '18 06:08

ankit jain


People also ask

How do you access Variadic arguments?

To access variadic arguments, we must include the <stdarg. h> header.

Is printf variadic function?

Variadic functions are functions (e.g. printf) which take a variable number of arguments.

Can variadic methods take any number of parameters?

A variadic function allows you to accept any arbitrary number of arguments in a function.


2 Answers

I think your problem is not related to LD_PRELOAD or dlopen/dlsym: you simply want to call a variadic function from a variadic function, eg:

int printf (const char *fmt, ...) {
    return fprintf (stdout, fmt, my_variadic_parameters);
}

As far as I know, it is not possible, but in carefully designed libraries (which is obviously a minority of them), every variadic function has a counterpart that uses va_list parameter, like printf and vprintf, fprintf and vfprintf:

int printf (const char *fmt, ...) {
    va_list ap;
    int retval;

    va_start (ap, fmt);
    retval= vfprintf (stdout, fmt, ap);
    va_end (ap);
    return retval;
}

int vmyprintf (const char *fmt, va_list pap) {
    va_list ap;
    int retval;

    va_copy (ap, pap);
    retval= vfprintf (stdout, fmt, ap);
    va_end (ap);
    return retval;
}

So you should ask the creator of 'foo' to create a 'vfoo':

int vfoo (char *args, const char *f, va_list v)
like image 176
Lorinczy Zsigmond Avatar answered Oct 18 '22 10:10

Lorinczy Zsigmond


Have a look at man va_start, there is a nicely concise example in that man page.

You can treat the dlsym symbol address just you would any other function pointer.

The basic concept behind va_args, is using a control variable in a loop, usually a printf style format string that can be parsed to decide when to exit the call frame building loop. In your case ankit, you need to have some form "is there another argument to place in the call frame" as you build up a va_list. Basically va_start va_arg... va_end.

Again, best explained in code, and the man page has a nice example.

like image 44
Brian Tiffin Avatar answered Oct 18 '22 09:10

Brian Tiffin