从现有二进制文件中导入符号到链接器脚本中

huangapple go评论82阅读模式
英文:

Import symbols from an existing binary in a linker script

问题

我正在为一个带有闪存和RAM的微处理器创建一个二进制文件。常规的构建过程使用链接脚本来声明不同部分应该放在哪里,还会将参数导出到代码中,比如RAM的哪一部分可以用作堆。

为了更好地进行开发和更新,我想在二进制文件的开头添加一个自定义引导加载程序。然而,这导致需要在主二进制文件的链接脚本中添加“魔术常量”。例如,二进制文件不能再从闪存的开头开始,而只能在几千字节后开始,这取决于引导加载程序的代码大小。此外,我还想从主二进制文件中引用引导加载程序的一些闪存区域。

作为一种基本方法,我想能够从现有的(.elf)二进制文件中加载符号,以在链接脚本中使用,而不包含来自其他二进制文件的任何有效负载数据,但似乎不可能实现这一点。

因此,在链接之后,我希望有两个二进制文件:

  • bootloader.elf(使用闪存0x10000000 - 0x1004a000)
  • application.elf(使用闪存0x1004a000 - 0x10080000并引用bootloader.elf中的其他符号)

这是否可能在不在application.elf的链接脚本中硬编码地址(并且需要在引导加载程序中更改内容时更改它们)的情况下实现?

INPUT链接脚本命令只接受目标文件,所以该命令不太有用,我也找不到其他有用的命令。

总的来说,感觉我在尝试用错误的工具解决这个问题。

英文:

I am creating a binary for a microprocessor with flash and ram. The regular build process uses a linker script to declare where different sections should go and also exports parameters to the code, like which part of the ram can be used for heap.

For better development and updatability I want to add a custom bootloader at the beginning of the binary. However this leads to the need to add "magic constants" to the linker script of the main binary. E.g. the binary cannot start at the beginning of the flash anymore, but only a few kilobytes later, depending on the codesize of the bootloader. Additionally I want to reference some flash regions of the bootloader from the main binary.

As a primitive, I would like to be able to load symbols from an existing (.elf-)binary for usage in a linker script without including any payload data from the other binary, but that does not seem to be possible.

So after linking I would like to have 2 binaries:

  • bootloader.elf (uses flash 0x10000000 - 0x1004a000)
  • application.elf (uses flash 0x1004a000 - 0x10080000 and references other symbols in bootloader.elf)

Is this possible without hardcoding the addresses inside the linker script for application.elf (and needing to change them whenever I change something in the bootloader)?

The INPUT linker-script command only accepts object files, so that command is not useful, and I can't find any other useful command there.

In general, it feels like I'm trying to solve this problem with the wrong tools.

答案1

得分: 1

> 作为一个原始操作,我希望能够从现有的(.elf)二进制文件中加载符号以供链接器脚本使用,而不包括来自其他二进制文件的任何有效负载数据,但这似乎是不可能的。

我会采取以下方式处理这个问题:

  1. 链接 bootloader.elf
  2. 运行 readelf bootloader.elf 以提取符号地址、大小等信息。
  3. 将这些信息提供给Perl、Python或其他语言中的一个简单生成器,该生成器将编写一个新的 application.lds 链接器脚本。
  4. 使用新生成的脚本来链接 application.elf

这一切都可以在您的 Makefile 中完成。

附言:如果从 bootloader.elf 中提取所有相关信息变得麻烦,可以编写一个简单的 C 程序来完成这个任务(例如,使用 libelf 来实际解析 bootloader.elf)。然后,该程序可以直接输出 application.lds

英文:

> As a primitive, I would like to be able to load symbols from an existing (.elf-)binary for usage in a linker script without including any payload data from the other binary, but that does not seem to be possible.

The way I would approach this is:

  1. Link bootloader.elf
  2. Run readelf bootloader.elf to extract symbol addresses, size, etc.
  3. Feed this info into a trivial generator in Perl, Python, whatever, which will write a new application.lds linker script
  4. Use the newly generated script to link application.elf.

All within your Makefile.

P.S. If extracting all the relevant info from bootloader.elf proves bothersome, write a simple C program to do that (using e.g. libelf to actually parse bootloader.elf). That program can then spit out the application.lds directly).

答案2

得分: 0

ld提供了一种选项,可以仅加载二进制文件的符号,以便在链接过程中引用它们(感谢 @michael-petch 指出这个选项):

-R 文件名
--just-symbols=文件名
  从文件名中读取符号名称及其地址,但不重新定位它,也不包含在输出中。

具体来说,可以使用 -r 创建中间链接器文件,如下所示:

ld -r --just-symbols=bootloader.elf -o bootloader-interface.elf \
  --retain-symbols-file to-export.txt

这将创建一个中间的 ELF 文件 bootloader-interface.elf,其中只包含在 to-export.txt 中列出的符号,不包含任何符号的内容,然后在链接过程中像任何其他源文件一样使用该 ELF 文件。

在链接器脚本中,可以将该文件引入链接过程中:

INPUT(path/to/bootloader-interface.elf);

然后,所有导出的符号都可以在链接器脚本中用于 application.elf,并且在 application 的目标文件中也可以相应地引用这些符号。

英文:

ld offers an option to load just the symbols of a binary to be able to reference them during linkage (thanks to @michael-petch for pointing me to this option):

-R filename
--just-symbols=filename
  Read symbol names and their addresses from filename, but do not relocate it
  or include it in the output.

Concretely, using -r to create intermediate linker files, one can use:

ld -r --just-symbols=bootloader.elf -o bootloader-interface.elf \
  --retain-symbols-file to-export.txt

to create an intermediate elf-file bootloader-interface.elf, that only contains the symbols listed in to-export.txt and does not contain any contents for the symbols, and then use that elf-file just like any other source during linkage.

In a linker script this file can be brought into the linkage with:

INPUT(path/to/bootloader-interface.elf);

Then all exported symbols can be used inside the linker script for application.elf and also consequently referenced from the object files for application.

huangapple
  • 本文由 发表于 2023年7月17日 20:34:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76704497.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定