Linuxでは、実行可能ファイル形式はELF形式であり、問題の解決に役立つ「秘密」をより深く理解するのに役立つコマンドがいくつかあります。
サンプルプログラム
サンプルプログラムは次のとおりです。
//hello.c
#include<stdio.h>
int main(int argc,char *argv[])
{
printf("hello shouwangxiansheng\n");
return 0 ;
}
hello実行可能ファイルをコンパイルして取得します。
$ gcc -o hello hello.c
ファイルタイプを表示
fileコマンドを使用して、ファイルタイプを表示できます。
$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=8f1de0f59bdfe9aaff85ade6898173aa436b296a, not stripped
結果から、ELF実行可能ファイルであり、ダイナミックリンクを備えた64ビットプログラムであることがわかります。最後に削除されていないのは、シンボルテーブル情報またはデバッグ情報を保持していることも示しています。
実行可能ファイルでない場合、その情報は何ですか?例えば:
$ file hello.c
hello.c: C source, UTF-8 Unicode text
ELFヘッダーを表示する
以下に示すように、readelfはELFファイルを表示するために使用されます。
$ readelf -h hello
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
それがEXECであり、ファイルを実行でき、リトルエンディアンプログラムがX86-64で実行されていることがわかります。このファイルヘッダーの情報は、クロスコンパイル時にも非常に役立ちます。たとえば、x86マシンでpowerpc実行可能ファイルをクロスコンパイルすると、認識されず、powerpcで実行できません。readelfを使用して、Machineフィールドが正しくコンパイルされていないかどうかを確認することをお勧めします。
ELFファイルで文字列を見つけます
たとえば、ファイルにバージョン番号または特別な文字列を書き込む場合、stringsコマンドを使用してそれを検索できます。
$ strings hello|grep shouwang
hello shouwangxiansheng
ELFファイルの各セグメントのサイズを表示する
$ size hello
text data bss dec hex filename
1210 552 8 1770 6ea hello
ここでは、コードセグメントとデータセグメントが占める量を確認できます。また、必要に応じてコードを最適化して、ディスク領域の使用量を減らすことができます。
リンクされたダイナミックライブラリを表示する
実行中にダイナミックライブラリが見つかりませんか?リンクしているライブラリを見てみませんか。
$ ldd hello
linux-vdso.so.1 => (0x00007ffd16386000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f507e083000)
/lib64/ld-linux-x86-64.so.2 (0x00007f507e44d000)
リンクしているダイナミックライブラリは/lib/x86_64-linux-gnu/libc.so.6であり、ファイルが存在しない場合、実行時にエラーが発生することがわかります。ここでは、「ダイナミックライブラリの作成と使用」も参照できます。
シンボルテーブルを見る
新しく追加された関数またはグローバル変数がコンパイルされているのだろうか?シンボルテーブルに何かがあるかどうかを確認する方法(シンボルテーブルが削除されていない場合):
$ nm hello |grep main #符号表中查找main函数
U __libc_start_main@@GLIBC_2.2.5
0000000000400526 T main
見つからないか、先頭にUがあり、アドレスがない場合は、この関数がelfファイルで定義されていないことを意味します。これは、リンクに問題がある場合に役立ちます。
ELFファイルのスリミング
ファイルをチェックしたところ、シンボルテーブル情報が含まれているため、削除されていない単語が表示されました。ファイルを削除すると、バイナリファイルは小さくなりますが、内部のシンボルテーブル情報は小さくなります。そうではありません。、問題の場所に影響します。
$ ls -lh hello #瘦身前
-rwxrwxr-x 1 root root 8.4K
$ strip hello
$ ls -lh hello #瘦身后
-rwxrwxr-x 1 root root 6.2K
ご覧のとおり、減量後はバイナリファイルが小さくなります。実行可能ファイルが大きいほど、スリミング効果がより明確になります。もちろん、これはプログラムの通常の動作には影響しませんが、デバッグと問題の場所にのみ影響しますので、ご安心ください。
この時点でシンボルテーブルを見てください。
$ nm hello
nm: hello: no symbols
ファイルのチェックサムを印刷する
転送プロセス中にバイナリファイルが破損しているか、同じバージョンであるかどうかにかかわらず、チェックサムとブロック数を確認してください。
$ sum hello
33513 7
もちろん、次のものも使用できます。
$ md5sum hello
521efed706c3b485dd3b5e96e48b138a hello
md5値を比較します。
総括する
ELFファイルは、適切に使用されている限り、豊富な情報を隠します。これは、問題をより適切に開発または特定するのに役立ちます。