我正在尝试包装现有的功能。
下面的代码是完美的工作。
#include<stdio.h>
int __real_main();
int __wrap_main()
{
printf("Wrapped main\n");
return __real_main();
}
int main()
{
printf("main\n");
return 0;
}
命令:
gcc main.c -Wl,-wrap,main
输出:
Wrapped main
main
所以我用temp改变了主要功能。我的目标是包装temp()函数。
以下是代码
temp.c
#include<stdio.h>
int temp();
int __real_temp();
int __wrap_temp()
{
printf("Wrapped temp\n");
return __real_temp();
}
int temp()
{
printf("temp\n");
return 0;
}
int main()
{
temp();
return 0;
}
命令:
gcc temp.c -Wl,-wrap,temp
输出:
temp
包裹的温度不打印。请引导我包装funciton temp。
答案 0 :(得分:6)
ld的联机帮助页说:
--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.
此处的关键字未定义。
如果将定义temp
放在与使用它的代码相同的翻译单元中,则在使用它的代码中不会定义它。
您需要拆分代码定义和使用它的代码:
#!/bin/sh
cat > user.c <<'EOF'
#include<stdio.h>
int temp(void);
int __real_temp(void);
int __wrap_temp()
{
printf("Wrapped temp\n");
return __real_temp();
}
int main()
{
temp();
return 0;
}
EOF
cat > temp.c <<'EOF'
#include<stdio.h>
int temp()
{
printf("temp\n");
return 0;
}
EOF
gcc user.c -Wl,-wrap,temp temp.c # OK
./a.out
将构建拆分为两个单独的编译可能会更清楚:
$ gcc -c user.c
$ gcc -c temp.c
$ nm user.o temp.o
temp.o:
U puts
0000000000000000 T temp
user.o:
0000000000000015 T main
U puts
U __real_temp
U temp
0000000000000000 T __wrap_temp
由于temp
中user.c
未定义,因此链接器可以对其执行__real_
/ __wrap_
魔术。
$ gcc user.o temp.o -Wl,-wrap=temp
$ ./a.out
Wrapped temp
temp
答案 1 :(得分:4)
如果您可以从要调用它的函数中拆分要覆盖的函数,PSCocik提出的答案效果很好。但是,如果要将被调用者和调用者保持在同一源文件中,--wrap
选项将不起作用。
相反,您可以在实施被调用者之前使用__attribute__((weak))
,以便让某人重新实现它而不会让GCC对多个定义大喊大叫。
例如,假设您要在以下 hello.c 代码单元中模拟world
函数。您可以添加属性以便能够覆盖它。
#include "hello.h"
#include <stdio.h>
__attribute__((weak))
void world(void)
{
printf("world from lib\n");
}
void hello(void)
{
printf("hello\n");
world();
}
然后您可以在另一个单元文件中覆盖它。对于单元测试/模拟非常有用:
#include <stdio.h>
#include "hello.h"
/* overrides */
void world(void)
{
printf("world from main.c"\n);
}
void main(void)
{
hello();
return 0;
}