将符号链接到Linux上的固定地址

如何使用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时,为复杂的软件构建链接脚本也不是一件容易的事情。