使用GNU ld链接脚本包含二进制文件

31

我有一个可用的链接脚本。我想添加另一个数据节,其内容直接从文件中提取(ld 不应解析它并提取节等)。我该怎么做?

OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
SECTIONS
{
  .text 0x100000 : {
    *(.multiboot)
    *(.text)
    *(.code)
    *(.rodata*)
  }
  .data : {
    *(.data)
  }
  .bss : {
    *(.bss)
  }
  kernel_end = .;
  roottask_start = .;
  .data : {

    HERE I WANT TO INCLUDE THE ENTIRE CONTENTS OF ANOTHER (BINARY) FILE

  }
  roottask_end = .;
}

GCC:https://dev59.com/questions/qm445IYBdhLWcg3wapzF - Ciro Santilli OurBigBook.com
4个回答

24
你可以尝试使用objcopy将其转换为普通对象,然后像引用普通对象一样在链接脚本中引用它的符号。从objcopy手册页面上来看:

-B bfdarch   --binary-architecture=bfdarch   在将原始二进制输入文件转换为对象文件时非常有用。在这种情况下,输出体系结构可以设置为bfdarch。如果输入文件具有已知的bfdarch,则会忽略此选项。您可以通过引用转换过程创建的特殊符号来访问此二进制数据。这些符号称为_binary_objfile_start_binary_objfile_end_binary_objfile_size。例如,您可以将图片文件转换为对象文件,然后使用这些符号在代码中访问它。

...其中objfile将被扩展为输入对象文件的名称。

另请参阅--rename-section选项。


3
“bfdarch”文本并非字面意思(也不需要它)。如需了解更多,请参见使用gcc arm工具链链接任意数据 - artless noise

19

您可以将原始文件放入汇编程序的单独部分,然后在链接器脚本中包含这个部分。

首先,您需要创建模板.S文件,例如:

.section .rawdata
.incbin "blob1.raw"

...并修改链接脚本以按您喜欢的方式包含此部分:

.data : {

    *(.rawdata*)

}

您还可以在这里查看一些关于 .S 模板的更详细信息。


7
另一种只使用链接器的方法是使用TARGETINPUT命令。 TARGET(binary) INPUT (./DATA.bin) INPUT (./CODE.bin) #如果需要,可以在此添加更多二进制文件
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
SECTIONS { .text 0x100000 : { *(.multiboot) *(.text) *(.code) ./CODE.bin *(.rodata*) } .data : { *(.data) } .bss : { *(.bss) } kernel_end = .; roottask_start = .; .data : {
./DATA.bin } roottask_end = .; }
此外,您可能需要在二进制输入周围添加对齐节。

这可能在ARM架构上无法工作。请参见:https://lists.gnu.org/archive/html/bug-gnu-utils/2001-05/msg00258.html - artless noise

7
另一种解决方案是使用 BYTE 函数生成第二个链接器脚本,并使用 INCLUDE 指令将其包含在前面的链接器脚本中。您可以使用以下方法从二进制文件中使用 hexdump 生成脚本:
cat ramelfs | hexdump -v -e '"BYTE(0x" 1/1 "%02X" ")\n"' > ramelfs.ld

然后按以下方式包含它:
SECTIONS {
    .text : {

        /* ... */

        kramelfs = .;
        INCLUDE "ramelfs.ld" ;
        kramelfs_end = .;

       /* ... */
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接