如何使用 LD_PRELOAD 包装可变参数函数?

How to wrap variadic functions using LD_PRELOAD?

我必须对以下格式的可变参数函数执行动态链接:

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

这里参数的数量是可变的。 我想要实现的是,我想将获得的参数传递给我正在使用 dlsym 解析的原始函数。 如果我没有传递所有参数,我就会不断收到分段错误。 提前致谢。

我认为您的问题与 LD_PRELOAD 或 dlopen/dlsym 无关:您只是想从可变参数函数调用可变参数函数,例如:

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

据我所知,这是不可能的,但在精心设计的库中(这显然是其中的少数),每个可变参数函数都有一个使用 va_list 参数的对应函数,例如 printf 和 vprintf , fprintf 和 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;
}

所以你应该请 'foo' 的创建者创建一个 'vfoo':

int vfoo (char *args, const char *f, va_list v)

看看 man va_start,该手册页中有一个非常简洁的示例。

您可以像处理任何其他函数指针一样处理 dlsym 符号地址。

va_args 背后的基本概念是在循环中使用控制变量,通常是 printf 样式的格式字符串,可以对其进行解析以决定何时退出调用框架构建循环。在你的例子中,当你建立一个 va_list 时,你需要有某种形式 "is there another argument to place in the call frame"。基本上 va_start va_arg... va_end.

同样,最好在代码中进行解释,手册页中有一个很好的示例。

给出

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

argsf 提供的信息应该告诉您调用者作为可变参数传递了多少种类型的参数。

如何提供此信息取决于 foo 的实施,因此请参阅 foo() 文档。

一个很好的例子是 printf(const char * format, ...); 所有作为可变参数接收的信息都可以从第一个参数解析,非可变格式 - "string"。

如果你不能洞察这一点,你就迷路了。在 C 中,没有 泛型,"built-in" 方法来收集传递的可变参数的数量和类型。