【问题标题】:How to wrap variadic functions using LD_PRELOAD?如何使用 LD_PRELOAD 包装可变参数函数?
【发布时间】:2019-01-08 14:49:57
【问题描述】:

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

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

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

【问题讨论】:

    标签: c variadic-functions dynamic-linking ld-preload dlsym


    【解决方案1】:

    我认为您的问题与 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)
    

    【讨论】:

    • 我不能要求创建者创建一个 vfoo() 函数......但我想要做的是获取 va_list 的值,将它们存储到一个字符串数组并传递它......该方法似乎确实有效,但由于参数数量不正确而导致错误...您能否建议我是否可以使用此解决方案,对这种可变参数函数的经验很少。
    • 可能有一些依赖于平台/编译器的“解决方案”,但您应该首先描述上下文(操作系统、CPU、编译器等)
    • 我可能没听懂你想说什么...在这种情况下上下文应该无关紧要
    • 在刚刚出现的源代码中找到了函数 vfoo() 并使用它,我能够得到我的解决方案......非常感谢!
    • libffi 应该能够做到这一点,并且分布/安装相当广泛。
    【解决方案2】:

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

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

    va_args 背后的基本概念是在循环中使用控制变量,通常是printf 样式的格式字符串,可以对其进行解析以决定何时退出调用帧构建循环。在您的情况下 ankit,您需要在构建va_list 时采用某种形式“在调用框架中放置另一个参数”。基本上是 va_start va_arg... va_end。

    再一次,最好用代码解释,手册页有一个很好的例子。

    【讨论】:

    • va_arg 函数希望您知道va_list 中提取哪些类型。
    【解决方案3】:

    给定

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

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

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

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

    如果你无法深入了解这一点,你就会迷失方向。在 C 中,没有通用的“内置”方式来收集传递的可变参数的数量和类型。

    【讨论】:

    • 对,我确实有来自 f... 的参数类型的信息,现在如何进一步进行?
    • 使用对va_arg 的连续调用从va_list 中提取值,这是对va_start 的初始调用给你的。
    猜你喜欢
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多