【问题标题】:How to wrap functions with the `--wrap` option correctly?如何使用 `--wrap` 选项正确包装函数?
【发布时间】:2018-03-08 17:11:13
【问题描述】:

gcc 6.3 的手册页说:

--wrap=symbol
           Use a wrapper function for symbol.  Any undefined reference to
           symbol will be resolved to "__wrap_symbol".  Any undefined
           reference to "__real_symbol" will be resolved to symbol.
           ...
           If you link other code with this file using --wrap malloc, then all
           calls to "malloc" will call the function "__wrap_malloc" instead.
           The call to "__real_malloc" in "__wrap_malloc" will call the real
           "malloc" function.

所以我创建了一个简单的例子:

#include <stdio.h>

int foo() {
    printf("foo\n");
    return 0;
}

int __wrap_foo() {
    printf("wrap foo\n");
    return 0;
}

int main () {
    printf("foo:");foo();
    printf("wrapfoo:");__wrap_foo();
    printf("realfoo:");__real_foo();
    return 0;
}

并编译它:

gcc main.c -Wl,--wrap=foo -o main

这给了我一个警告:

main.c:18:21: warning: implicit declaration of function ‘__real_foo’ [-Wimplicit-function-declaration]
  printf("realfoo:");__real_foo();
                     ^~~~~~~~~~

进展顺利。现在我建议这样的输出:

foo:wrap foo
wrapfoo:wrap foo
realfoo:foo

相反,我得到了这个:

foo:foo
wrapfoo:wrap foo
realfoo:foo

我希望事情很清楚。我对警告感到困惑。通常__real 函数应该由链接器链接到foo()。此外,对foo() 的调用应链接到__wrap_foo。但输出显示,foo() 正在被执行。

如何正确使用--wrap

【问题讨论】:

  • 它确实有效。但是因为您只有一个翻译单元,并且存在foo,所以对foo 的调用不是对foo未定义引用
  • 好吧,我不明白。上面示例的输出对我来说似乎是错误的。 foo() 应该输出"wrap foo"!我做错了什么?
  • 您忽略了“未定义的引用”要求
  • 哇哦,就是这样! ...现在要撰写完整的答案...
  • 个人意见:--wrap这个东西的正确使用方法一点也不。当您只需要链接某些没有源代码的库并且您必须做这样可怕的事情才能使其工作时,这是一个可怕的解决方法。当您没有其他选择时(包括与图书馆供应商交谈,然后与您的老板交谈并威胁要退出,如果您必须继续使用需要像这样的黑客攻击的不良图书馆),这是挽救您理智的最后努力.

标签: c++ c gcc gcc-warning linker-flags


【解决方案1】:

正如 StoryTeller 告诉我的,我忽略了上面已经发布的“未定义参考”要求:

... 任何对符号的未定义引用都将被解析为“__wrap_symbol”。任何对“__real_symbol”的未定义引用都将被解析为符号。

为了使用--wrap 选项,我重新排列了我的代码示例,如下所示:

main.c:

#include <stdio.h>
extern int foo();
extern int __real_foo();

int __wrap_foo() {
    printf("wrap foo\n");
    return 0;
}

int main () {
    printf("foo:");foo();
    printf("wrapfoo:");__wrap_foo();
    printf("realfoo:");__real_foo();
    return 0;
}

foo.c:

#include <stdio.h>
int foo() {
    printf("foo\n");
    return 0;
}

然后编译:

gcc main.c foo.c -Wl,--wrap=foo -o main

运行./main后的惊人输出:

foo:wrap foo
wrapfoo:wrap foo
realfoo:foo

诀窍是(如果我错了,请纠正我)foo()__real_foo() 的引用在编译时没有定义。 I.E. 他们有**未定义的引用”,这是链接器将 foo() 链接到 __wrap_foo()__real_foo()foo() 的要求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多