如何使用GNU ld将(某些)符号链接到特定的固定地址,以便二进制文件在Linux(x86)中仍可正常执行? 这些符号将不会被访问,但是他们的地址是重要的。
例如,我会有以下结构:
struct FooBar { Register32 field_1; Register32 field_2; //... }; struct FooBar foobar;
我想链接foobar
地址0x76543210,但正常链接标准库和应用程序的其余部分。 然后,应用程序将使用foobar的地址,但不会引用它后面的(可能不存在的)内存。
这个请求的基本原理是可以在两个平台上使用同一个源代码:在本地平台上, Register32
可以简单地是一个volatile uint32_t
,但是在Linux Register32
是一个与uint32_t
相同大小的C ++对象,例如operator=
,然后它将使用该对象的地址,并向具有该地址(和数据)的通信框架发送请求以在远程硬件上执行实际的访问。 链接器将因此确保结构的Register32
字段引用正确的“地址”。
由litb使用--defsym symbol=address
确实有效,但是当你有几十个这样的实例映射时,这有点麻烦。 不过, --just-symbols=symbolfile
只是个窍门。 我花了一段时间才找出symbolfile
的语法
symbolname1 = address; symbolname2 = address; ...
空格似乎是必需的,否则ld
报告file format not recognized; treating as linker script
file format not recognized; treating as linker script
。
尝试一下
--defsym symbol=expression
就像这样:
gcc -Wl,--defsym,foobar=0x76543210 file.c
并在你的代码foobar外部声明:
extern struct FooBar foobar;
这看起来很有希望 然而,做这样的事情是一个坏主意(除非你真的知道你在做什么)。 你为什么需要它?
我会给你热门的提示… GNU LD可以做到这一点(假设系统库不需要你想要的地址)。 你只需要建立你自己的链接脚本,而不是使用编译器的自动生成的脚本。 阅读ld的手册页。 而且,当您涉及GLIBC时,为复杂的软件构建链接脚本也不是一件容易的事情。