使用GCC ARM工具链链接任意数据

nwo49xxi  于 2023-08-06  发布在  其他
关注(0)|答案(3)|浏览(122)

我想连接原始二进制数据。我想把它放在一个特定的地址,或者让它链接到我在代码中定义的一个符号(例如char* mydata)。因为它不是一个obj文件,我不能简单地链接它。
一个类似的帖子(Include binary file with GNU ld linker script)建议使用带有-B bfdarch选项的objcopy。objcopy响应“archictecture bfdarch unknown”。
还有一个答案建议将对象转换为自定义LD脚本,然后将其包含在主LD脚本中。在这一点上,我可能只是使用一个C包含文件(这是我现在正在做的),所以我宁愿不这样做。
我可以使用objcopy来完成这个任务吗?或者还有其他方法?

7qhs6swi

7qhs6swi1#

下面的示例适用于我:

$ 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-...)还是64位(elf64-...),以及它是低位序/ LSB(...-little,如ARM/x86上的)还是高位序/ MSB(...-big,如在SPARC/m68 k上)。

**编辑:**关于objcopy选项得说明:

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

您 * 必须 * 指定-O ...,但-B ...是可选的。以下是一个很好的例子来说明这种区别:

$ objcopy -I binary -O elf64-x86-64 foobar foobar.o
$ file foobar.o
foobar.o: ELF 64-bit LSB relocatable, no machine, version 1 (SYSV), not stripped

$ objcopy -I binary -O elf64-x86-64 -B i386 foobar foobar.o
$ file foobar.o
foobar.o: ELF 64-bit LSB relocatable, AMD x86-64, version 1 (SYSV), not stripped


也就是说,只有输出格式说明符elf64-x86-64不会将生成的二进制文件绑定到特定的体系结构(这就是file显示为no machine的原因)。如果-B i386这样做的话,那么它的用法就是AMD x86-64
这同样适用于ARM; -O elf32-little-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 ...被辨识。
有关binutils可以处理的ELF格式/ BFD类型的列表,请参见objcopy --info
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


或者,将参数反过来,

$ 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和基本运行时中的链接相关的错误;我目前不知道如何解决此问题。这应该可以通过链接器Map文件,通过声明目标(文件)特定的选项来实现,但在撰写本文时,我还没有弄清楚如何实现。

dba5bblo

dba5bblo2#

另一种方法可能是使用xxd

xxd -i your_data your_data.c

字符串
在文件中,您将得到两个符号unsigned char your_data[]unsigned int your_data_len。第一个将是一个包含您的数据的巨大数组,第二个将是该数组的长度。
编译已创建的C文件可能需要时间,因此如果您使用构建系统/ Makefile,请正确处理它,以避免不必要的重新编译。
xxd应该是Linux发行版的vimvim-common)包的一部分。

ryevplcw

ryevplcw3#

一个快速的方法是将数据放在它自己的.c文件(.c不是.h)中,这样它就变成了一个.o,然后在链接器脚本中,你可以为这个.o文件定义一个特定的内存空间和节条目,并把它放在你想要的任何地方。

MEMORY
{
...
BOB : ORIGIN = 0x123400, length = 0x200
...
}
SECTIONS
{
...
TED : { mydata.o } > BOB
...
}

字符串

相关问题