13

我想链接原始二进制数据。我想把它放在一个特定的地址,或者让它链接到我在代码中定义的符号(例如 char* mydata)。因为它不是一个 obj 文件,所以我不能简单地将它链接进去。

类似的帖子(包含带有 GNU ld 链接器脚本的二进制文件)建议使用带有-B bfdarch选项的 objcopy。objcopy 以“架构 bfdarch 未知”响应。

另一个答案建议将对象转换为自定义 LD 脚本,然后将其包含在主 LD 脚本中。在这一点上,我还不如只使用 C 包含文件(这是我现在正在做的)所以我宁愿不这样做。

我可以使用 objcopy 来完成此操作,还是有其他方法?

4

3 回答 3

20

以下示例适用于我:

$ dd if=/dev/urandom of=binblob bs=1024k count=1
$ objcopy -I binary -O elf32-little binblob binblob.o
$ file binblob.o
binblob.o: ELF 32-bit LSB relocatable, no machine, version 1 (SYSV), not stripped
$ nm  -S -t d binblob.o
0000000001048576 D _binary_binblob_end
0000000001048576 A _binary_binblob_size
0000000000000000 D _binary_binblob_start

即不需要为二进制数据指定 BFD 拱门(它只对代码有用/必要)。只需说“输入是二进制”和“输出是……”,它就会为您创建文件。由于纯二进制数据不是特定于体系结构的,您只需要告诉它输出是32位elf32-...(( ,例如在 SPARC/m68k 上)。elf64-......-little...-big

编辑: 澄清选项objcopy

  • -O ...选项控件 的使用:
    • 位宽(ELF 文件是 32 位还是 64 位)
    • 字节序(ELF 文件是 LSB 还是 MSB)
  • -B ...选项的使用控制 ELF 文件将请求的体系结构

必须指定 the-O ...-B ...是可选的。一个小例子可以很好地说明这种差异:

$ objcopy -I 二进制 -O elf64-x86-64 foobar foobar.o
$ 文件 foobar.o
foob​​ar.o:ELF 64 位 LSB 可重定位,无机器,版本 1 (SYSV),未剥离

$ objcopy -I 二进制 -O elf64-x86-64 -B i386 foobar foobar.o
$ 文件 foobar.o
foob​​ar.o:ELF 64 位 LSB 可重定位,AMD x86-64,版本 1 (SYSV),未剥离

即只是输出格式说明符elf64-x86-64不会将生成的二进制文件绑定到特定的体系结构(这就是为什么fileno machine)。用法 if-B i386这样做 - 在这种情况下,你被告知这是 now AMD x86-64

这同样适用于 ARM。-O elf32-littlevs.-O elf32-littlearm -B arm是在前一种情况下,你最终ELF 32-bit LSB relocatable, no machine, ...会在后一种情况下得到一段时间,它将是一个ELF 32-bit LSB relocatable, ARM....

这里也有一些相互依赖。您必须使用-O elf{32|64}-<arch>(不是通用的elf{32|64}-{little|big})输出选项才能进行-B ...识别。

请参阅objcopy --infobinutils 可以处理的 ELF 格式/BFD 类型列表。

2021 年 7 月 15 日编辑:所以我尝试了一点“使用”:

#include <stdio.h>

extern unsigned char _binary_binblob_start[];

int main(int argc, char **argv)
{
    for (int i = 0; i < 1024; i++) {
        printf("%02X ", _binary_binblob_start[i]);
        if ((i+1) % 60 == 0)
            printf("\n");
    }
return 0;
}

如果我制作那个“本地拱门”,我只能与 binblob 建立这个链接。否则它会给出下面指出的@chen3feng 错误。

似乎应该可以通过https://stackoverflow.com/a/7779766/512360gcc提供链接器选项- 但如果我逐字尝试,我会得到:

$ gcc use-binblob.c -Wl,-b -Wl,elf64-little binblob.o
/usr/bin/ld: skipping incompatible /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/libgcc.a when searching for -lgcc
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: skipping incompatible /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../lib64/libgcc_s.so.1 when searching for libgcc_s.so.1
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libgcc_s.so.1 when searching for libgcc_s.so.1
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 when searching for libgcc_s.so.1
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libgcc_s.so.1 when searching for libgcc_s.so.1
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 when searching for libgcc_s.so.1
/usr/bin/ld: skipping incompatible /usr/local/lib64/libgcc_s.so.1 when searching for libgcc_s.so.1
/usr/bin/ld: cannot find libgcc_s.so.1
/usr/bin/ld: skipping incompatible /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/libgcc.a when searching for -lgcc
/usr/bin/ld: cannot find -lgcc
collect2: error: ld returned 1 exit status

或者,转动 args,

$ gcc -Wl,-b -Wl,elf64-little binblob.o use-binblob.c
/usr/bin/ld: /tmp/cczASyDb.o: Relocations in generic ELF (EM: 62)
/usr/bin/ld: /tmp/cczASyDb.o: Relocations in generic ELF (EM: 62)
/usr/bin/ld: /tmp/cczASyDb.o: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status

如果我去“纯二进制”,这给出:

$ gcc use-binblob.c -Wl,-b -Wl,binary binblob
/usr/bin/ld: /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/libgcc.a:(.data+0x0): multiple definition of '_binary__usr_local_lib_gcc_x86_64_linux_gnu_10_2_0_libgcc_a_start'; /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/libgcc.a:(.data+0x0): first defined here
/usr/bin/ld: /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/libgcc.a:(.data+0x9445f6): multiple definition of '_binary__usr_local_lib_gcc_x86_64_linux_gnu_10_2_0_libgcc_a_end'; /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/libgcc.a:(.data+0x9445f6): first defined here
/usr/bin/ld: /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../lib64/libgcc_s.so:(.data+0x0): multiple definition of '_binary__usr_local_lib_gcc_x86_64_linux_gnu_10_2_0_____________lib64_libgcc_s_so_start'; /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../lib64/libgcc_s.so:(.data+0x0): first defined here
/usr/bin/ld: /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../lib64/libgcc_s.so:(.data+0x84): multiple definition of '_binary__usr_local_lib_gcc_x86_64_linux_gnu_10_2_0_____________lib64_libgcc_s_so_end'; /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../lib64/libgcc_s.so:(.data+0x84): first defined here
/usr/bin/ld: /lib/x86_64-linux-gnu/Scrt1.o: in function '_start': (.text+0x16): undefined reference to '__libc_csu_fini'
/usr/bin/ld: (.text+0x1d): undefined reference to '__libc_csu_init'
/usr/bin/ld: (.text+0x2a): undefined reference to '__libc_start_main'
/usr/bin/ld: /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/crtbeginS.o: in function 'deregister_tm_clones': crtstuff.c:(.text+0xa): undefined reference to '__TMC_END__'
/usr/bin/ld: /usr/local/lib/gcc/x86_64-linux-gnu/10.2.0/crtbeginS.o: in function 'register_tm_clones': crtstuff.c:(.text+0x3a): undefined reference to '__TMC_END__'
/usr/bin/ld: /tmp/ccF1Pxfc.o: in function `main': use-binblob.c:(.text+0x3a): undefined reference to 'printf'
/usr/bin/ld: use-binblob.c:(.text+0x6f): undefined reference to 'putchar'
/usr/bin/ld: a.out: hidden symbol '__TMC_END__' isn't defined
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status

缺少对后者的引用_binary_binblob_start是正常的,但其余的是与 libc 中的链接和基本运行时相关的错误;我目前不知道如何解决这个问题。应该可以通过链接器映射文件,通过声明目标(文件)特定选项,但在撰写本文时我还没有弄清楚如何。

于 2013-06-24T08:39:43.660 回答
5

另一种方法可能是使用xxd

xxd -i your_data your_data.c

在文件中,您将获得两个符号unsigned char your_data[]unsigned int your_data_len. 第一个将是一个包含您的数据的巨大数组,第二个将是该数组的长度。

编译创建的 C 文件可能需要一些时间,因此如果您使用的是构建系统/Makefile,请正确处理它,避免不必要的重新编译。

xxd应该是您的 Linux 发行版的vim( vim-common) 包的一部分。

于 2013-06-24T07:35:12.677 回答
1

一种快速的方法是将数据放入其自己的 .c 文件(.c 而不是 .h)中,使其本身成为 .o,然后在链接描述文件中定义特定的内存空间和节条目该 .o 文件并将其放在您想要的任何位置。

MEMORY
{
...
BOB : ORIGIN = 0x123400, length = 0x200
...
}
SECTIONS
{
...
TED : { mydata.o } > BOB
...
}
于 2013-06-23T23:29:26.077 回答