【问题标题】:Calculating number of variable arguments for clone function计算克隆函数的变量参数数量
【发布时间】:2012-06-25 14:50:51
【问题描述】:

我正在尝试 LD_PRELOAD linux 的 clone 函数。在我的 LD_PRELOADed 版本中,我需要在调用原始 clone 函数之前记录输入参数。但是,问题在于 clone 采用可变数量的参数。它是这样声明的。

int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...
/* pid_t *pid, struct user_desc *tls, pid_t *ctid */ );

现在要将这些参数传递给原始 clone 函数,我必须知道传入的参数数量。我该怎么做?

【问题讨论】:

  • 你还碰巧有那个 LD_PRELOAD 代码(或者至少有一些骨架)吗?因为我试图做同样的事情并且也被 clone() varags 卡住了。根据 va_* 的实现,重新考虑接受的答案,我认为它只会吃掉堆栈上的(随机)数据。调用者必须始终告诉被调用者要使用多少(参数数量、终止符、格式字符串或……)。

标签: c linux gcc x86-64 variadic-functions


【解决方案1】:

使用va_* 函数,这些是处理变量参数列表时的方法。

这是man page,最后还包含一个示例。

【讨论】:

    【解决方案2】:

    如果有 NULL 终止符,您可以调用 va_arg,但它不会返回 NULL

    【讨论】:

      【解决方案3】:

      对此的正确答案是:你不能计算变量参数函数中的参数数量。

      但是,对于clone 函数,您可以通过查看flags 参数假设参数的数量,因为某些标志需要某些额外的参数。

      CLONE_PARENT_SETTID 标志为例,在manual page 中声明:

      将子线程 ID 存储在父子内存中的 ptid 位置。 (在 Linux 2.5.32-2.5.48 中有一个标志 CLONE_SETTID 可以做到这一点。)

      所以如果设置了这个标志,那么你知道ptid 参数应该存在,你可以使用va_* 函数来获取它。

      但是,无法验证用户是否确实传递了参数,这意味着如果用户没有传递参数,那么事情可能会出现严重错误。

      【讨论】:

      • 因此,如果设置了 CLONE_PARENT_SETTID,您可以假设 ptid 并吃掉一个参数,如果 CLONE_SETTLS 您还可以期待 tls 并从堆栈中读取 2 个参数,如果设置了 CLONE_CHILD_CLEARTID 或 CLONE_CHILD_SETTID,您可以期待 3 个参数?这个 clone() 太骇人听闻了。
      【解决方案4】:

      man page 是这样描述原型的:

      int clone(int (*fn)(void *), void *child_stack, int flags,
                void *arg, ... /* pid_t *ptid, struct user_desc *tls, pid_t *" ctid ");
      

      注意:我在tlspid_t 之间添加了一个逗号,我认为手册页中存在拼写错误。

      然后讨论ptidctid 的论点。所以我会继续检查文档,对于那些定义了这些额外参数的情况,这就是如何从va_list 中读取它们。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-13
        • 2014-06-28
        • 1970-01-01
        • 2011-05-24
        • 2020-07-06
        • 1970-01-01
        • 2016-03-12
        • 2017-10-16
        相关资源
        最近更新 更多