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.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
ankit jain
  • 350
  • 2
  • 12

3 Answers3

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)
Lorinczy Zsigmond
  • 1,749
  • 1
  • 14
  • 21
  • 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. – ankit jain Aug 01 '18 at 07:59
  • There might be some platform-/compiler-dependent "solution", but you should describe the context first (OS, CPU, compiler, etc) – Lorinczy Zsigmond Aug 01 '18 at 08:17
  • I probably didn't get what you want to say... context should not matter in this case – ankit jain Aug 01 '18 at 08:56
  • This (very platform-dependent) library seems to do what you whish: http://www.dyncall.org/ – Lorinczy Zsigmond Aug 01 '18 at 08:56
  • 2
    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! – ankit jain Aug 01 '18 at 10:34
  • 1
    libffi should be able to do this and is fairly widely distributed/installed. – R.. GitHub STOP HELPING ICE Aug 01 '18 at 13:42
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.

Brian Tiffin
  • 3,978
  • 1
  • 24
  • 34
  • 1
    The `va_arg` function expects that you *know* which types to pull from the `va_list`. – alk Aug 01 '18 at 08:51
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.

alk
  • 69,737
  • 10
  • 105
  • 255
  • Right, I do have the information for type of arguments from f... now how to proceed further? – ankit jain Aug 01 '18 at 08:56
  • Use successive calls to `va_arg` to pull the values from the `va_list` that an initial call to `va_start` gave you. – alk Aug 01 '18 at 08:58