Есть ли способ переопределить функции со статической областью видимости в объектном модуле?
Если я начну с чего-то подобного, то модуль с глобальным символом «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 являются глобальными символами и доступны извне модуля. Все идет нормально.
Но что, если я хочу вставить свою собственную функцию поверх «база», а «бар» будет вызывать мою вставленную «баз»?
Есть ли способ сделать это?
Опция --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(), была обернута, но bar по-прежнему вызывает локальную базу, а не обернутую базу.
Есть ли способ заставить бар называть завернутый баз?
Даже если требуется изменить объектный код, чтобы возиться с адресами вызовов функций, если это можно сделать автоматически, этого может быть достаточно, но в этом случае он должен работать как минимум на i386 и x86_64.
-- Стив