Все функции, которые нужно перенаправить, находятся в своем собственном модуле компиляции.
У компоновщика есть опция «--wrap», которая заменяет все ссылки на символ «xxx» на «__wrap_xxx», а сам символ на «__real_xxx». Он используется для помещения функции-обертки в качестве «перехватчика» между вызовом и функцией.
Но с помощью этой опции вы можете делать все что угодно с этими символами в вашем скрипте компоновщика. Вам просто нужно определить "__wrap_xxx" с символом, чтобы ссылки были разрешаемыми.
В зависимости от ваших потребностей вы также можете написать фиктивную функцию с именем "__wrap_xxx ()", которая даже не вызывает "__real_xxx ()». Или вы можете поместить «__real_xxx» в таблицу векторов, или ... все, что вы можете придумать.
Все перенаправляемые функции не являются статичными («глобальными»), исправляя непосредственные значения
Я просмотрел ответы на другой вопрос ОП, опубликованный в комментарии. Это дало мне идею ослабить рассматриваемые символы и переопределить их значением с помощью компоновщика.
Этот пример может дать вам некоторое представление. Я тестировал в Linux, в котором рандомизация размещения адресного пространства , поэтому все адреса смещены от случайной базы. Но для целевой системы ОП она должна работать как положено.
foo1.c
Из-за произвольных значений для перенаправленных адресов функции не могут быть вызваны. Но программа может распечатать их адреса.
#include <stdio.h>
void foo1(void) {
}
extern void bar1(void);
int main(void) {
printf("%p\n", main);
printf("%p\n", foo1);
printf("%p\n", bar1);
return 0;
}
bar1.c
void bar1(void) {
}
wrapper.ld
Это первая альтернатива, которая дает компоновщику адреса для использования, дополнительный скрипт компоновщика. Второй см. Ниже. Стандартный скрипт компоновщика будет дополнен, нет необходимости копировать и исправлять его. Из-за простой структуры это, вероятно, самый простой способ предоставить много перенаправленных адресов, которые можно легко автоматизировать.
foo1 = 0x1000;
bar1 = 0x2000;
Примечание. Это не C! Это синтаксис «сценария компоновщика», который очень похож.
Как я построил и протестировал
Эта последовательность команд может быть автоматизирована и отсортирована для вашегосимпатия. В частности, вызовы objcopy
могут быть выполнены с помощью некоторого цикла по списку.
gcc -c -ffunction-sections foo1.c
objcopy --weaken-symbol=foo1 foo1.o foo2.o
gcc -c -ffunction-sections bar1.c
objcopy --weaken-symbol=bar1 bar1.o bar2.o
gcc foo1.o bar1.o -o original
echo original
./original
gcc foo2.o bar2.o -o weakened
echo weakened
./weakened
gcc foo2.o bar2.o wrapper.ld -o redirected
echo redirected
./redirected
Вместо дополнительного сценария компоновщика определения символов также могут быть даны в командной строке. Это упомянутая вторая альтернатива.
gcc foo2.o bar2.o -Wl,--defsym=foo1=0x1000 -Wl,--defsym=bar1=0x2000 -o redirected
Кстати, компоновщик понимает @file
для чтения всех аргументов из файла file
. Таким образом, размер команды компоновщика не ограничен.
Все перенаправляемые функции нестатичны («глобальны»), перезаписываются новыми функциями
Вместо предоставления непосредственных значенийВы можете, конечно, просто предоставить свои альтернативные функции. Это работает как выше, но вместо дополнительного сценария компоновщика или определения символов вы пишете исходный файл.
wrapper.c
Да, верно, имена равнына имена оригиналов! Поскольку мы сделали символы исходных функций слабыми , мы не получим сообщение об ошибке от компоновщика, когда он перезаписывает ссылки адресами новых функций.
void foo1(void) {
}
void bar1(void) {
}
Buildперенаправленная программа, подобная этой (показаны только новые команды):
gcc -c -ffunction-sections wrapper.c
gcc foo2.o bar2.o wrapper.o -o redirected
Функция для перенаправления: static
Ну, в зависимости от вашей целевой архитектуры это, вероятно, будет невозможно. Это из-за записи перемещения ссылки. Это будет своего рода родственник, говорящий компоновщику разрешить с помощью смещения в разделе функции вместо разрешения по символу функции.
Я не исследовал это далее.