有没有办法在对象模块中覆盖具有静态范围的函数?
如果我从这样的东西开始,具有全局符号“foo”的模块是一个调用局部符号“bar”的函数,它调用局部符号“baz”
[scameron@localhost ~]$ cat foo.c
#include <stdio.h>
static void baz(void)
{
printf("baz\n");
}
static void bar(void)
{
printf("bar\n");
baz();
}
void foo(void)
{
printf("foo\n");
bar();
}
[scameron@localhost ~]$ gcc -g -c foo.c
[scameron@localhost ~]$ objdump -x foo.o | egrep 'foo|bar|baz'
foo.o: file format elf32-i386
foo.o
00000000 l df *ABS* 00000000 foo.c
00000000 l F .text 00000014 baz
00000014 l F .text 00000019 bar
0000002d g F .text 00000019 foo
它有一个全局变量“foo”和两个局部变量“bar”和“baz”。
假设我想写一些练习 bar 和 baz 的单元测试,我可以这样做:
[scameron@localhost ~]$ cat barbaz
bar
baz
[scameron@localhost ~]$ objcopy --globalize-symbols=barbaz foo.o foo2.o
[scameron@localhost ~]$ objdump -x foo2.o | egrep 'foo|bar|baz'
foo2.o: file format elf32-i386
foo2.o
00000000 l df *ABS* 00000000 foo.c
00000000 g F .text 00000014 baz
00000014 g F .text 00000019 bar
0000002d g F .text 00000019 foo
[scameron@localhost ~]$
现在 bar 和 baz 是全局符号,可以从模块外部访问。到目前为止,一切都很好。
但是如果我想在“baz”之上插入我自己的函数,并让“bar”调用我插入的“baz”怎么办?
有没有办法做到这一点?
--wrap 选项似乎没有这样做......
[scameron@localhost ~]$ cat ibaz.c
#include <stdio.h>
extern void foo();
extern void bar();
void __wrap_baz()
{
printf("wrapped baz\n");
}
int main(int argc, char *argv[])
{
foo();
baz();
}
[scameron@localhost ~]$ gcc -o ibaz ibaz.c foo2.o -Xlinker --wrap -Xlinker baz
[scameron@localhost ~]$ ./ibaz
foo
bar
baz
wrapped baz
[scameron@localhost ~]$
从 main() 调用的 baz 被包装了,但 bar 仍然调用本地 baz 而不是包装的 baz。
有没有办法让 bar 调用包装好的 baz?
即使它需要修改目标代码以修改函数调用的地址,如果可以以自动化方式完成,那可能就足够了,但在这种情况下,它至少需要在 i386 和 x86_64 上工作。
——史蒂夫