如何使用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
字段引用正确的“地址”。
答案 0 :(得分:15)
litb建议使用--defsym symbol=address
确实有效,但是当您有几十个这样的实例要映射时,这有点麻烦。但是,--just-symbols=symbolfile
只是诀窍。我花了一段时间才找到symbolfile
的语法,即
symbolname1 = address;
symbolname2 = address;
...
似乎需要空格,否则ld
报告file format not recognized; treating as linker script
。
答案 1 :(得分:8)
尝试
--defsym symbol=expression
与此相同:
gcc -Wl,--defsym,foobar=0x76543210 file.c
在你的代码中使foobar成为一个外部声明:
extern struct FooBar foobar;
这看起来很有希望。但是,做这样的事情是个坏主意(除非你真的知道你做了什么)。你为什么需要它?
答案 2 :(得分:1)
我会给你热门提示...... GNU LD可以做到这一点(假设系统库不需要你想要的地址)。您只需构建自己的链接描述文件,而不是使用编译器的自动生成链接器脚本。阅读ld的手册页。此外,当您涉及GLIBC时,为复杂的软件构建链接描述文件也不是一件容易的事。