【问题标题】:How to link object files into a raw binary file with gcc/ld?如何使用 gcc/ld 将目标文件链接到原始二进制文件?
【发布时间】:2019-10-16 16:35:08
【问题描述】:

2019 年 12 月 2 日更新:

我在使用 m68k-elf 工具链时遇到了问题。我想做的是像这样翻译一个简单的68k汇编文件source.s

    .text 
    move.w %d0,%d1

进入一个目标文件,然后使用链接器脚本memmap.ldscript

MEMORY 
{
    ROM1 (rx) : ORIGIN = 0x00, LENGTH = 16
    ROM2 (rx) : ORIGIN = 0x10, LENGTH = 16
}

SECTIONS 
{
    .text : 
    {
       *(.text)
    } >ROM2
}

OUTPUT_FORMAT(binary)

将此目标文件链接到原始二进制文件。最终文件应如下所示(在十六进制编辑器中查看):

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00

如果我这样构建它

m68k-elf-as -o source.o source.s 
m68k-elf-ld -T memmap.ldscript -o final.rom source.o 

那么final.rom只包含:

30 01

所以节的代码被放置在 0x00 而不是 0x05。

我需要“原始”机器代码来刻录到 E(E)PROM。但我想使用链接器和链接器脚本能够将多个源文件中的部分组装成目标文件,然后将它们链接到一个最终的 ROM 中,其中部分位置由链接器脚本控制。 m68k-elf 可以吗?

【问题讨论】:

  • 我认为这相当于在链接后执行 objcopy 步骤(其中包含该二进制行)。 gnu 将根据链接中的最低地址构建 rom 文件,因此如果您说 .text 从 0x05 开始,文件的第一个字节将是地址 0x05 的字节。如果你想填充它并制作一个内存图像样式的二进制文件,那么你需要将填充放在程序集中 .byte 0,0,0,0,0 并将地址设为 0x00。
  • 如果您链接到 elf 或类似的东西,那么您将使用 objdump 或 readelf 或其他方式在正确的偏移量处看到您的指令,但是当您转换为二进制时,它将使用链接中的最低地址进行转换(0x05) 作为第一个字节。我的意思是,如果你制作了 .text 0x1000 和 .data 0x200,那么 objcopy -O 二进制文件的第一个字节就是 0x200 字节。如果你做了 .text 0x100 和 .data 0x200 那么第一个字节 0x100 地址等等。
  • ld --oformat=binary 有帮助吗?

标签: assembly ld 68000


【解决方案1】:

您需要通过创建包含一些内容的输出部分来强制链接器发出 ROM1 区域。 manual says

在输出节中分配空间的其他链接脚本指令也将创建输出节。即使分配没有创造空间,分配也会点,除了'。 = 0','。 = 。 + 0','。 =符号','。 = 。 + 符号'和'。 = ALIGN (. != 0, expr, 1)' 当 ‘sym’ 是脚本中定义的值 0 的绝对符号时。这允许您使用“.”强制输出一个空部分。 = .'.

所以这应该有效:

MEMORY 
{
    ROM1 (rx) : ORIGIN = 0x00, LENGTH = 16
    ROM2 (rx) : ORIGIN = 0x10, LENGTH = 16
}

SECTIONS
{
    .dummy :
    {
       . = ORIGIN(ROM1) + LENGTH(ROM1);
    } >ROM1

    .text : 
    {
       *(.text)
       . = ORIGIN(ROM2) + LENGTH(ROM2);
    } >ROM2
}

OUTPUT_FORMAT(binary)

但是,至少在我的 binutils 版本 2.33.1 中,它没有。 .=. 也不起作用。如果您只需要该区域进行填充,则可以向其中发送一些数据,例如通过 BYTE(0) 指令并且有效:

MEMORY 
{
    ROM1 (rx) : ORIGIN = 0x00, LENGTH = 16
    ROM2 (rx) : ORIGIN = 0x10, LENGTH = 16
}

SECTIONS
{
    .dummy :
    {
       BYTE(0);
       . = ORIGIN(ROM1) + LENGTH(ROM1);
    } >ROM1

    .text : 
    {
       *(.text)
       . = ORIGIN(ROM2) + LENGTH(ROM2);
    } >ROM2
}

OUTPUT_FORMAT(binary)

如果您确实有 ROM1 的一些内容,那么当然只需为其创建输入部分,但请确保它始终存在,否则链接器将删除它。奇怪的是,即使是零大小的部分也可以。

【讨论】:

  • 对不起,我的回复晚了,我快速检查了一下,它有效,谢谢!我完全误解了点运算符,我认为它仅用于符号分配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-13
  • 2012-12-19
  • 2012-10-15
  • 1970-01-01
  • 2019-07-31
  • 2011-08-05
  • 2011-08-24
相关资源
最近更新 更多