13

生のバイナリデータにリンクしたい。特定のアドレスに配置するか、コードで定義したシンボル (char* mydata など) にリンクさせたいと考えています。objファイルではないので、単純にリンクすることはできません。

同様の投稿 ( GNU ld リンカー スクリプトにバイナリ ファイルを含める) では、オプションで objcopy を使用することが提案されてい-B bfdarchます。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 アーキテクチャを指定する必要はありません(これは、コードにのみ有用/必要です)。「入力はバイナリです」、「出力は...」と言うだけで、ファイルが作成されます。elf32-...純粋なバイナリ データはアーキテクチャ固有ではないため、出力が 32 ビット ( ) か 64 ビット ( elf64-...) か、およびそれがリトル エンディアン/LSB ( ...-littleARM/x86 のように) かビッグ エンディアン/MSBかだけを伝える必要があります。( ...-big、たとえば SPARC/m68k の場合)。

編集: オプションの説明objcopy

  • -O ...オプション コントロール の使用法:
    • ビット幅 (ELF ファイルが 32 ビットか 64 ビットか)
    • エンディアン (ELF ファイルが LSB か MSB か)
  • オプションの使用法は-B ...、ELF ファイルが要求するアーキテクチャを制御します

を指定する必要があります-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特定のアーキテクチャに結び付けられません (そのため、と表示されます)。if の使用法はそうです - その場合、これは now であると言われます。fileno machine-B i386AMD x86-64

同じことが ARM にも当てはまります。-O elf32-littlevs.-O elf32-littlearm -B arm前者の場合は、後者の場合は a ELF 32-bit LSB relocatable, no machine, ...while になるということ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;
}

その「ローカルアーチ」を作成した場合にのみ、ビンブロブとのリンクを作成できます。それ以外の場合、@ 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 と基本的なランタイムのリンクに関連するエラーです。現在、これを解決する方法がわかりません。ターゲット(ファイル)固有のオプションを宣言することにより、リンカーマップファイルを介して可能になるはずですが、これを書いている時点ではまだ方法がわかりません。

于 2013-06-24T08:39:43.660 に答える
5

別のアプローチは、xxdを使用することです。

xxd -i your_data your_data.c

ファイルには、2 つのシンボルunsigned char your_data[]unsigned int your_data_len. 1 つ目はデータを含む巨大な配列になり、2 つ目はその配列の長さになります。

作成された C ファイルのコンパイルには時間がかかる場合があるため、ビルド システム / Makefile を使用している場合は、不必要な再コンパイルを避けて適切に処理してください。

xxdvimLinux ディストリビューションの( vim-common) パッケージの一部である必要があります。

于 2013-06-24T07:35:12.677 に答える
1

これを行う簡単な方法は、データを独自の .c ファイル (.h ではなく .c) に入れて、それ自体が .o になるようにし、リンカー スクリプトで特定のメモリ空間とセクション エントリを定義できるようにすることです。その .o ファイルを任意の場所に配置します。

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