【问题标题】:Linking symbols to fixed addresses on Linux在 Linux 上将符号链接到固定地址
【发布时间】:2010-10-04 11:04:04
【问题描述】:

如何使用 GNU ld 将(一些)符号链接到特定的固定地址,以便二进制文件仍然可以在 Linux (x86) 中正常执行?不会对这些符号进行任何访问,但它们的地址很重要。

例如,我有以下结构:

struct FooBar {
    Register32 field_1;
    Register32 field_2;
    //...
};

struct FooBar foobar;

我想将foobar 链接到地址0x76543210,但要正常链接标准库和应用程序的其余部分。然后应用程序将使用 foobar 的地址,但不会引用它后面的(可能不存在的)内存。

这个请求的基本原理是这个相同的源可以在两个平台上使用:在本机平台上,Register32 可以简单地是一个volatile uint32_t,但在 Linux 上,Register32 是一个具有相同大小的 C++ 对象作为uint32_t 定义例如operator=,然后它将使用对象的地址并向具有该地址(和数据)的通信框架发送请求,以执行对远程硬件的实际访问。因此,链接器将确保结构的 Register32 字段引用正确的“地址”。

【问题讨论】:

  • 为什么你可能想要这样做?
  • 在受内存保护的操作系统上,没有理由这样做。
  • 在硬件位于已知特定地址的嵌入式系统中经常需要这种东西。但是,0x76543210 不太可能是这样的地址。 ;-) ld 也不是用于此类事情的最友好的链接器。从链接描述文件中定义符号的语法很有帮助。
  • OP 的意图似乎不仅仅是访问位于特定地址的硬件。使用 GCC,类似“struct FooBar foobar = (struct FooBar)0x76543210”之类的内容应该是促进硬件访问的直接方式。

标签: linux gcc linker gnu ld


【解决方案1】:

litb 使用--defsym symbol=address 的建议确实有效,但是当您要映射几十个这样的实例时会有点麻烦。然而,--just-symbols=symbolfile 就可以解决问题。我花了一段时间才弄明白symbolfile的语法是

symbolname1 = address;
symbolname2 = address;
...

这些空格似乎是必需的,否则ld 会报告file format not recognized; treating as linker script

【讨论】:

    【解决方案2】:

    试试看

    --defsym symbol=expression
    

    和这个一样:

    gcc -Wl,--defsym,foobar=0x76543210 file.c
    

    并在您的代码中使 foobar 成为外部声明:

    extern struct FooBar foobar;
    

    这看起来很有希望。然而,做这样的事情是个坏主意(除非你真的知道你在做什么)。为什么需要它?

    【讨论】:

      【解决方案3】:

      我会给你一个热门提示... GNU LD 可以做到这一点(假设系统库不需要你想要的地址)。您只需要构建自己的链接器脚本,而不是使用编译器自动生成的。阅读 ld 的手册页。此外,当您也涉及 GLIBC 时,为复杂的软件构建链接器脚本并非易事。

      【讨论】:

      • ld 文档不是很有用,至少只有几个小时的研究。我尝试调整编译器的默认链接器脚本,但是当我注意到即使使用(未经编辑的)提取的默认脚本也不会链接时放弃了(虽然它当然可以在没有链接器脚本的情况下链接)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-03
      • 2011-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 2012-08-23
      相关资源
      最近更新 更多