ある種類のプラットフォーム (ARM や x86 など) で使用可能なオブジェクト ファイルを別の種類のプラットフォームに移植する必要がある場合があります。ソース コードが利用可能であれば、ターゲット プラットフォームで再コンパイルできるため、作業は比較的簡単です。しかし、ソース コードが入手できず、オブジェクト ファイルを別のプラットフォームに移植する必要がある場合はどうすればよいでしょうか。 Linux を使用している場合は、コマンド objcopy が必要な処理を正確に実行します。この記事では、いくつかの例を通して、このコマンドの基本的な使い方を学びます。
私は x86_64 タイプのプラットフォームでしか作業していないため、このチュートリアルでは、このコマンドのプラットフォームに依存しない機能について説明します。
このコマンドの構文は次のとおりです:
objcopy [options] infile [outfile]...
「options」と「outfile」は必須の引数ではありませんが、それぞれに意味があることに注意してください。
例
1.オブジェクト ファイルをソースから宛先にコピーするだけ
次の例を考えてみましょう:
$ objcopy test new_test $
したがって、上記のコマンドは「test」を新しいファイル「new_test」にコピーします。この場合、「test」は同じプラットフォームでコンパイルされているため、出力「new_test」は変わらないことに注意してください。
また、バイナリ ファイルを逆アセンブルしてオブジェクト ファイルの詳細を取得したい場合は、前述のように objdump コマンドを使用する必要があります。
2.新しいファイル名を指定せずにオブジェクト ファイルをコピーします
上記の例では、コピーされたファイルは、コマンドのオプションと共に提供されたため、「new_test」という名前が付けられました。ただし、宛先ファイル名が指定されていない場合、objcopy コマンドは元のファイルをコピーされたファイルに置き換えます。
次の例を考えてみましょう:
$ stat test File: `test' Size: 8498 Blocks: 24 IO Block: 4096 regular file Device: 805h/2053d Inode: 1442357 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 1000/himanshu) Gid: ( 1001/ family) Access: 2012-08-31 21:25:54.828808055 +0530 Modify: 2012-08-31 21:25:50.498614487 +0530 Change: 2012-08-31 21:25:50.498614487 +0530 $ objcopy test $ stat test File: `test' Size: 8498 Blocks: 24 IO Block: 4096 regular file Device: 805h/2053d Inode: 1459714 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 1000/himanshu) Gid: ( 1001/ family) Access: 2012-08-31 21:30:04.108833244 +0530 Modify: 2012-08-31 21:30:04.108833244 +0530 Change: 2012-08-31 21:30:04.108833244 +0530
したがって、オブジェクト ファイル「test」の統計は、objcopy によって完全に新しいファイルとして作成されたため、完全に変更されたことがわかります。
3. -j オプションを使用して特定のセクションのみをコピー
ソース オブジェクト ファイルから宛先オブジェクト ファイルに 1 つのセクションのみをコピーする場合は、-j オプションを使用します。
次の例を考えてみましょう:
$ objcopy -j.interp test new_test $
上記のコマンドは、実際には .interp セクションのみを空の new_test ファイルにコピーします。
確認した場合:
$ objdump -s new_test new_test: file format elf64-x86-64 Contents of section .interp: 400238 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux- 400248 7838362d 36342e73 6f2e3200 x86-64.so.2.
したがって、このファイルには .interp セクション (「test」からコピーしたもの) のみが含まれていることがわかります。
4. -R オプションを使用して、コピーしたファイルから特定のセクションのみを削除します
このオプションにより、objdump コマンドは、このオプションと共に指定されたセクションを除いて、完全なソース ファイルをコピーできます。
次の例を考えてみましょう:
$ objcopy -R.interp test new_test
確認した場合:
$ objdump -s -j.interp new_test new_test: file format elf64-x86-64
したがって、新しいファイル「new_test」には .interp セクションがないことがわかります。
5. -p オプションを使用してアクセス日と変更日を保持
このコマンドとともに -p オプションを使用すると、コピーされたファイルのアクセス日と変更日を保存できます (ソースと同じに保つことができます)。
次の例を考えてみましょう:
$ objcopy -p test new_tst
上記のコマンドは、アクセスと変更の日時を保持します。
確認した場合:
$ $ stat test File: `test' Size: 8498 Blocks: 24 IO Block: 4096 regular file Device: 805h/2053d Inode: 1459714 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 1000/himanshu) Gid: ( 1001/ family) Access: 2012-08-31 21:32:32.458629723 +0530 Modify: 2012-08-31 21:30:04.108833244 +0530 Change: 2012-08-31 21:30:04.108833244 +0530 $ stat new_tst File: `new_tst' Size: 8498 Blocks: 24 IO Block: 4096 regular file Device: 805h/2053d Inode: 1442650 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 1000/himanshu) Gid: ( 1001/ family) Access: 2012-08-31 21:32:32.000000000 +0530 Modify: 2012-08-31 21:30:04.000000000 +0530 Change: 2012-08-31 21:42:25.938657423 +0530
したがって、アクセスと変更日時の両方が保持されていることがわかります。
6. –weaken オプションを使用して、すべてのグローバル シンボルを weak に変更します
これは、リンカーに -R オプションを使用して他のオブジェクト ファイルとリンクできるオブジェクト ファイルを構築する際に役立ちます。
次の例を考えてみましょう:
$ readelf -s new_test Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 65 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000400238 0 SECTION LOCAL DEFAULT 1 2: 0000000000400254 0 SECTION LOCAL DEFAULT 2 3: 0000000000400274 0 SECTION LOCAL DEFAULT 3 4: 0000000000400298 0 SECTION LOCAL DEFAULT 4 .. 27: 0000000000000000 0 SECTION LOCAL DEFAULT 27 28: 000000000040046c 0 FUNC LOCAL DEFAULT 14 call_gmon_start 29: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c .. 49: 0000000000400550 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini 50: 0000000000400440 0 FUNC GLOBAL DEFAULT 14 _start 51: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 52: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses 53: 0000000000400628 0 FUNC GLOBAL DEFAULT 15 _fini 54: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_ 55: 0000000000400638 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used .. $ objcopy --weaken test new_test $ readelf -s new_test Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 65 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000400238 0 SECTION LOCAL DEFAULT 1 2: 0000000000400254 0 SECTION LOCAL DEFAULT 2 3: 0000000000400274 0 SECTION LOCAL DEFAULT 3 4: 0000000000400298 0 SECTION LOCAL DEFAULT 4 .. 28: 000000000040046c 0 FUNC LOCAL DEFAULT 14 call_gmon_start 29: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 30: 0000000000600e18 0 OBJECT LOCAL DEFAULT 19 __CTOR_LIST__ 31: 0000000000600e28 0 OBJECT LOCAL DEFAULT 20 __DTOR_LIST__ 32: 0000000000600e38 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__ ... 49: 0000000000400550 2 FUNC WEAK DEFAULT 14 __libc_csu_fini 50: 0000000000400440 0 FUNC WEAK DEFAULT 14 _start 51: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 52: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses 53: 0000000000400628 0 FUNC WEAK DEFAULT 15 _fini 54: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_ 55: 0000000000400638 4 OBJECT WEAK DEFAULT 16 _IO_stdin_used 56: 0000000000601010 0 NOTYPE WEAK DEFAULT 25 __data_start .. $
したがって、-weaken フラグを指定して objcopy コマンドを実行すると、すべての GLOBAL シンボルが WEAK に変換されたことがわかります。
7. –prefix-symbols オプションを使用して文字列でシンボルをプレフィックスします
シンボル名の前に文字列「TGS」を付ける必要がある次の例を考えてみましょう:
$ objcopy --prefix-symbols="TGS" test new_test $ readelf -s new_test Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 65 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000400238 0 SECTION LOCAL DEFAULT 1 2: 0000000000400254 0 SECTION LOCAL DEFAULT 2 3: 0000000000400274 0 SECTION LOCAL DEFAULT 3 4: 0000000000400298 0 SECTION LOCAL DEFAULT 4 ... 28: 000000000040046c 0 FUNC LOCAL DEFAULT 14 TGScall_gmon_start 29: 0000000000000000 0 FILE LOCAL DEFAULT ABS TGScrtstuff.c 30: 0000000000600e18 0 OBJECT LOCAL DEFAULT 19 TGS__CTOR_LIST__ 31: 0000000000600e28 0 OBJECT LOCAL DEFAULT 20 TGS__DTOR_LIST__ 32: 0000000000600e38 0 OBJECT LOCAL DEFAULT 21 TGS__JCR_LIST__ 33: 0000000000400490 0 FUNC LOCAL DEFAULT 14 TGS__do_global_dtors_aux ...
したがって、「TGS」がシンボル名の前に付いていることがわかります。
8. –strip-symbols オプションを使用して特定のシンボルを取り除く
一部のシンボルを削除する必要がある場合は、オプション –strip-symbols をファイル名とともに使用できます。このファイル名には、削除するシンボル名が含まれています (各行に 1 つ)。
次の例では、「call_gmon_start」シンボル名がファイル (symbolname) で指定されているため削除されます。
$ readelf -s new_test Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 65 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000400238 0 SECTION LOCAL DEFAULT 1 2: 0000000000400254 0 SECTION LOCAL DEFAULT 2 3: 0000000000400274 0 SECTION LOCAL DEFAULT 3 4: 0000000000400298 0 SECTION LOCAL DEFAULT 4 ..... 28: 000000000040046c 0 FUNC LOCAL DEFAULT 14 call_gmon_start 29: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 30: 0000000000600e18 0 OBJECT LOCAL DEFAULT 19 __CTOR_LIST__ 31: 0000000000600e28 0 OBJECT LOCAL DEFAULT 20 __DTOR_LIST__ 32: 0000000000600e38 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__ 33: 0000000000400490 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux ... $ objcopy --strip-symbols=symbolname test new_test $ readelf -s new_test Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 64 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000400238 0 SECTION LOCAL DEFAULT 1 2: 0000000000400254 0 SECTION LOCAL DEFAULT 2 3: 0000000000400274 0 SECTION LOCAL DEFAULT 3 4: 0000000000400298 0 SECTION LOCAL DEFAULT 4 ... 26: 0000000000601020 0 SECTION LOCAL DEFAULT 26 27: 0000000000000000 0 SECTION LOCAL DEFAULT 27 28: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 29: 0000000000600e18 0 OBJECT LOCAL DEFAULT 19 __CTOR_LIST__ 30: 0000000000600e28 0 OBJECT LOCAL DEFAULT 20 __DTOR_LIST__ 31: 0000000000600e38 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__ 32: 0000000000400490 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux ...
これで、シンボル「call_gmon_start」が正常に取り除かれたことがわかります。
9. –prefix-sections オプションを使用して、セクション名の前に文字列を付けます
次の例を考えてみましょう:
$ objcopy --prefix-sections="TGS" test new_test $ readelf -s new_test readelf: Error: no .dynamic section in the dynamic segment Symbol table 'TGS.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND ... ... ...
したがって、セクション名には、提供された文字列 TGS がプレフィックスとして付けられていることがわかります。
10. –keep-file-symbols オプションを使用してソース ファイル名のシンボルを保持
–strip-debug シンボル (ファイル名を指定するシンボルとともに多くのデバッグ関連のシンボルを削除する) を使用するときはいつでも、ソース ファイル名のシンボルを保持する必要が生じた場合は、–keep-file-symbols を使用できます。
次の例を考えてみましょう:
$ objcopy --strip-debug test new_test $ readelf -s new_test Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 62 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 000000000040046c 0 FUNC LOCAL DEFAULT 14 call_gmon_start 2: 0000000000600e18 0 OBJECT LOCAL DEFAULT 19 __CTOR_LIST__ 3: 0000000000600e28 0 OBJECT LOCAL DEFAULT 20 __DTOR_LIST__ 4: 0000000000600e38 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__ ... 10: 00000000004006e8 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__ 11: 0000000000600e38 0 OBJECT LOCAL DEFAULT 21 __JCR_END__ 12: 00000000004005f0 0 FUNC LOCAL DEFAULT 14 __do_global_ctors_aux 13: 0000000000600fe8 0 OBJECT LOCAL HIDDEN 24 _GLOBAL_OFFSET_TABLE_ 14: 0000000000600e14 0 NOTYPE LOCAL HIDDEN 19 __init_array_end 15: 0000000000600e14 0 NOTYPE LOCAL HIDDEN 19 __init_array_start ... $ objcopy --strip-debug --keep-file-symbols test new_test $ readelf -s new_test Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 65 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 000000000040046c 0 FUNC LOCAL DEFAULT 14 call_gmon_start 2: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 3: 0000000000600e18 0 OBJECT LOCAL DEFAULT 19 __CTOR_LIST__ 4: 0000000000600e28 0 OBJECT LOCAL DEFAULT 20 __DTOR_LIST__ ... 12: 00000000004006e8 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__ 13: 0000000000600e38 0 OBJECT LOCAL DEFAULT 21 __JCR_END__ 14: 00000000004005f0 0 FUNC LOCAL DEFAULT 14 __do_global_ctors_aux 15: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c 16: 0000000000600fe8 0 OBJECT LOCAL HIDDEN 24 _GLOBAL_OFFSET_TABLE_ 17: 0000000000600e14 0 NOTYPE LOCAL HIDDEN 19 __init_array_end 18: 0000000000600e14 0 NOTYPE LOCAL HIDDEN 19 __init_array_start ...
上記の例では、最初に objcopy が –strip-debug オプションで実行され、(他の多くのシンボルと共に) ソース ファイル (test.c) 名を示すシンボルが取り除かれました。次に、-keep-file-symbols オプションを指定して objcopy コマンドを再実行し、ソース ファイル名のシンボルが取り除かれていないことを確認しました (太字部分)。