How to wrap variadic functions using LD_PRELOAD?
Asked Answered
C

3

6

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.

Cocainize answered 1/8, 2018 at 6:8 Comment(0)
B
4

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)
Blackandwhite answered 1/8, 2018 at 7:14 Comment(6)
I cannot ask the creator to create a vfoo() function... but what I am trying to do is take the values of va_list, store them to a string array and pass it forward... the approach does seem to work but gives errors due to improper number of arguments... Can you suggest if I can with this solution, have little experience this variadic functions.Cocainize
There might be some platform-/compiler-dependent "solution", but you should describe the context first (OS, CPU, compiler, etc)Blackandwhite
I probably didn't get what you want to say... context should not matter in this caseCocainize
This (very platform-dependent) library seems to do what you whish: dyncall.orgBlackandwhite
Found the function vfoo() in the source which was just present there and using that, I was able to get my solution... Thanks a lot!Cocainize
libffi should be able to do this and is fairly widely distributed/installed.Idonah
R
1

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.

Redskin answered 1/8, 2018 at 7:16 Comment(1)
The va_arg function expects that you know which types to pull from the va_list.Butyrate
B
0

Given

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

the information provided by either args or f ought to tell you how many parameters of which type had been passed by the caller as variadic arguments.

How this info is provided depends on foo's implementation, so see foo() documentation.

A nice example to this is printf(const char * format, ...); All info of what is received as variadic arguments shall be parseable from the 1st parameter, the non-variadic format-"string".

If you fail to gain insight in this, you are lost. In C there is no generic, "built-in" way to gather the number and types of variadic arguments passed.

Butyrate answered 1/8, 2018 at 8:45 Comment(2)
Right, I do have the information for type of arguments from f... now how to proceed further?Cocainize
Use successive calls to va_arg to pull the values from the va_list that an initial call to va_start gave you.Butyrate

© 2022 - 2024 — McMap. All rights reserved.