使用 GCC ARM 工具链链接任意数据 [英] linking arbitrary data using GCC ARM toolchain

查看:24
本文介绍了使用 GCC ARM 工具链链接任意数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to link in raw binary data. I'd like to either put it at a particular address, or have it link to a symbol (char* mydata, for instance) I have defined in code. Since it's not an obj file, I can't simply link it in.

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

A similar post (Include binary file with GNU ld linker script) suggests using objcopy with the -B bfdarch option. objcopy responds with "archictecture bfdarch unknown".

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

Yet another answer suggests transforming the object into a custom LD script and then include that from the main LD script. At this point, I may as well just be using a C include file (which is what I am doing Now) so I'd rather not do that.

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

Can I use objcopy to accomplish this, or is there another way?

推荐答案

以下示例适用于我:

$ 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-...)code>),以及它是小端/LSB(...-little,如在 ARM/x86 上)还是大端/MSB(...-big,例如在 SPARC/m68k 上).

I.e. no need to specify the BFD arch for binary data (it's only useful / necessary for code). Just say "the input is binary", and "the output is ...", and it'll create you the file. Since pure binary data isn't architecture-specific, all you need to tell it is whether the output is 32bit (elf32-...) or 64bit (elf64-...), and whether it's little endian / LSB (...-little, as on ARM/x86) or big endian / MSB (...-big, as e.g. on SPARC/m68k).

objcopy 的选项说明:

  • -O ... 选项的使用控制:
    • 位宽(ELF 文件是 32 位还是 64 位)
    • 字节序(ELF 文件是 LSB 还是 MSB)

    必须指定 -O ...-B ... 是可选的.用一个小例子来最好地说明差异:

    You have to specifiy the -O ... but the -B ... is optional. The difference is best illustrated by a little example:

    $ 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 不会将生成的二进制文件绑定到特定的架构(这就是为什么 fileno machine).用法 if -B i386 这样做 - 在这种情况下,你被告知这是现在 AMD x86-64.

    I.e. just the output format specifier elf64-x86-64 doesn't tie the generated binary to a specific architecture (that's why file says no machine). The usage if -B i386 does so - and in that case, you're told this is now AMD x86-64.

    这同样适用于 ARM;-O elf32-little-O elf32-littlearm -B arm 是在前一种情况下,您最终会得到一个 ELF 32 位 LSB 可重定位,没有机器,... 而在后者中,它将是一个 ELF 32 位 LSB 可重定位,ARM....

    The same would apply to ARM; -O elf32-little vs. -O elf32-littlearm -B arm is that in the former case, you end up with a ELF 32-bit LSB relocatable, no machine, ... while in the latter, it'll be an ELF 32-bit LSB relocatable, ARM....

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

    There's some interdependency here as well; you have to use -O elf{32|64}-<arch> (not the generic elf{32|64}-{little|big}) output option to be able to make -B ... recognized.

    有关您的 binutils 可以处理的 ELF 格式/BFD 类型列表,请参阅 objcopy --info.

    See objcopy --info for the list of ELF formats / BFD types that your binutils can deal with.

    编辑 2021 年 7 月 15 日:所以我尝试了一些使用":

    Edit 15/Jul/2021: So I tried a little "use":

    #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 在下面指出的错误.

    I can only make this link with the binblob if I make that "local arch". Else it gives the error @chen3feng points out below.

    似乎应该可以根据 https://stackoverflow 提供要传递的 gcc 链接器选项.com/a/7779766/512360 - 但如果我逐字逐句地尝试,我得到:

    It appears it should be possible giving gcc linker options to pass, per https://stackoverflow.com/a/7779766/512360 - but if I try that verbatim, I get:

    $ 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
    

    如果我选择纯二进制",这会给出:

    and if I go "pure binary", this gives:

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

    The missing reference to _binary_binblob_start is expected from the latter alright, but the remainder are errors related to linking in libc and the basic runtime; I do not currently know how to resolve this. It should be possible via linker mapfiles, by declaring target (file-) specific options, but as of this writing I have not yet figured out how.

    这篇关于使用 GCC ARM 工具链链接任意数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆