如何在 C 中包装现有函数
How to wrap existing function in C
我正在尝试包装现有函数。
以下代码完美运行。
#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改变了main函数。我的目标是包装 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
包装的临时文件未打印。请指导我包装函数温度。
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
如果您可以将要覆盖的函数与调用它的函数分开,则 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();
}
然后您可以在另一个单元文件中覆盖它。非常有用的单位 testing/mocking:
#include <stdio.h>
#include "hello.h"
/* overrides */
void world(void)
{
printf("world from main.c\n");
}
int main(void)
{
hello();
return 0;
}
我正在尝试包装现有函数。
以下代码完美运行。
#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改变了main函数。我的目标是包装 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
包装的临时文件未打印。请指导我包装函数温度。
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
如果您可以将要覆盖的函数与调用它的函数分开,则 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();
}
然后您可以在另一个单元文件中覆盖它。非常有用的单位 testing/mocking:
#include <stdio.h>
#include "hello.h"
/* overrides */
void world(void)
{
printf("world from main.c\n");
}
int main(void)
{
hello();
return 0;
}