重命名功能而不更改其引用 [英] Rename a function without changing its references

查看:82
本文介绍了重命名功能而不更改其引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有-ffunction-sections选项的gcc编译的目标文件.我可以访问源文件,但不允许修改它.

I have an object file compiled using gcc with -ffunction-sections option. I have access to the source file but iam not allowed to modify it.

file.c
void foo(void)
{
    bar();
}
void bar(void)
{
    abc();
}

我要达到的目的是使对bar的所有引用都采用一个绝对地址(我将在链接器脚本中分配),而bar将被链接器放置在其他地址上.

What iam trying to achieve is to make all the references to bar take an absolute address(which I'll assign in the linker script) whereas bar will be placed at some other address by the linker.

一个可能的解决方案是将bar重命名为file_bar而不更改foo()中对bar的调用.我尝试使用objcopy -redefine-syms,但似乎甚至重命名了对bar的调用.

A possible solution is to rename bar to file_bar without changing the call to bar inside foo(). I tried using objcopy -redefine-syms but it seems to rename even the calls to bar.

busybee提供的解决方案可以解决问题,除非这些功能位于同一编译单元中. foo1.c

Solution provided by busybee solves the problem unless the functions are in the same compilation unit. foo1.c

#include <stdio.h>
extern void bar1();
void foo1(){
printf("foo1\n");
}
int main(){
printf("main\n");
foo1();
bar1();
}

bar1.c

#include <stdio.h>
void bar1(){
printf("bar1\n");
}

wrapper.c

wrapper.c

#include <stdio.h>
void __wrap_foo1(){
printf("wrap_foo1\n");
}
void __wrap_bar1(){
printf("wrap_bar1\n");
}

现在

$ gcc -c -ffunction-sections foo1.c bar1.c wrapper.c
$ gcc -Wl,--wrap=foo1 -Wl,--wrap=bar1 -o output foo1.o bar1.o wrapper.o
$ ./output
main
foo1
wrap_bar1

推荐答案

所有要重定向的函数都在其自己的编译单元中

链接器具有选项"--wrap",该选项将对符号"xxx"的所有引用替换为"__wrap_xxx",并将符号本身替换为"__real_xxx".它用于在调用和函数之间放置包装函数,作为拦截器".

All functions to be redirected are in their own compilation unit

The linker has the option "--wrap" that replaces all references to the symbol "xxx" by "__wrap_xxx" and the symbol itself by "__real_xxx". It is used to put a wrapper function as an "interceptor" in between call and function.

但是,使用此选项,您可以对链接脚本中的这些符号进行任何操作.您只需要用符号定义"__wrap_xxx",以便引用可以解析.

But with this option you can do whatever you like with those symbols in your linker script. You just need to define "__wrap_xxx" with a symbol so that the references are resolvable.

根据您的需要,您还可以编写一个甚至不调用"__real_xxx()"的伪函数"__wrap_xxx()".或者,您可以在向量表中放置"__real_xxx",或者...无论您想到什么.

Depending on your needs you can also write a dummy function named "__wrap_xxx()" that does not even call "__real_xxx()". Or you can place "__real_xxx" in a vector table, or... whatever you can think of.

我查看了

I looked through the answers of the other question the OP posted in a comment. This gave me the idea to weaken the symbols in question and to override them with a value by the linker.

此示例可能会给您一些启示.我在具有地址空间布局随机化的Linux上进行了测试,因此所有地址都偏离了随机基数.但是对于OP的目标系统,它应该可以按预期工作.

This example might give you some insight. I tested in on Linux which has address space layout randomization so all addresses are offsets from a random base. But for the OP's target system it should work as expected.

foo1.c

由于重定向地址具有任意值,因此无法调用函数.但是该程序可以打印其地址.

Because of arbitrary values for the redirected addresses the functions can't be called. But the program can print their addresses.

#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

这是第一种为链接程序提供要使用的地址的方法,即一个附加的链接程序脚本.对于第二个,请参见下文.标准链接描述文件将在此处进行扩展,无需复制和打补丁.由于结构简单,这可能是提供许多可以自动实现的重定向地址的最简单方法.

This is the first alternative to give the linker the addresses to be used, an additional linker script. For the second one see below. The standard linker script will be augmented here, there is no need to copy and patch it. Because of the simple structure this is probably the most simple way to provide many redirected addresses which can be easily automated.

foo1 = 0x1000;
bar1 = 0x2000;

注意:这不是C!正是链接程序脚本"语法非常相似.

我如何构建和测试

此命令序列可以自动进行排序,并可以根据您的喜好进行排序.尤其是objcopy的调用可以通过对列表的某些循环来完成.

This command sequence can be automated and sorted for your liking. Especially the calls of objcopy could be done by some loop over a list.

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

也可以在命令行上给出符号定义,而不是附加的链接描述文件.这是上述第二种选择.

Instead of an additional linker script the symbol definitions can be given on the command line, too. This is the mentioned second alternative.

gcc foo2.o bar2.o -Wl,--defsym=foo1=0x1000 -Wl,--defsym=bar1=0x2000 -o redirected

顺便说一句,链接器理解@file可以从文件file中读取所有自变量.因此,链接器命令的大小没有限制.

BTW, the linker understands @file to read all arguments from the file file. So there's "no limit" on the size of the linker command.

除了提供即时值外,您当然还可以提供替代功能.这与上面的工作原理相同,但是您无需编写其他链接程序脚本或符号定义,而是编写源文件.

Instead of providing immediate values you can of course just provide your alternative functions. This works like above but instead of the additional linker script or symbol definitions you write a source file.

wrapper.c

是的,没错,名字等于原件的名字!因为我们将原始函数的符号设置为 weak ,所以当链接器用新函数的地址覆盖引用时,链接器不会收到任何错误消息.

Yes, that's right, the names are equal to the names of the originals! Because we made the symbols of the original functions weak, we'll get no error message from the linker when it overwrites the references with the addresses of the new functions.

void foo1(void) {
}

void bar1(void) {
}

构建这样的重定向程序(仅显示新命令):

Build the redirected program like this (only new commands shown):

gcc -c -ffunction-sections wrapper.c

gcc foo2.o bar2.o wrapper.o -o redirected

要重定向的功能是static

好吧,根据您的目标体系结构,可能将无法实现.这是因为引用的重定位条目.这将是一种相对的关系,它告诉链接器通过对函数部分的偏移进行解析,而不是通过函数的符号进行解析.

A function to be redirected is static

Well, depending on your target architecture it will probably not be possible. This is because of the relocation entry of the reference. It will be some kind of relative, telling the linker to resolve by an offset into the section of the function instead to resolve by the symbol of the function.

我没有对此做进一步的调查.

I didn't investigate this further.

这篇关于重命名功能而不更改其引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆