ELF検出に限定したい場合は、自分のELFヘッダーを読むことができ/proc/$PID/exe
ます。ファイルの5バイト目が1の場合、32ビットのバイナリです。2の場合、64ビットです。追加された健全性チェックの場合:
- 最初の5バイトが
0x7f, "ELF", 1
:の場合、32ビットELFバイナリです。
- 最初の5バイトが
0x7f, "ELF", 2
:の場合、それは64ビットELFバイナリです。
- それ以外の場合:決定的ではありません。
を使用することもできますがobjdump
、それによりlibmagic
依存関係が取り除かれ、依存関係に置き換えられますlibelf
。
別の方法:/proc/$PID/auxv
ファイルを解析することもできます。によるとproc(5)
:
これには、実行時にプロセスに渡されるELFインタープリター情報の内容が含まれます。形式は、1つの符号なしの長いIDと各エントリの1つの符号なしの長い値です。最後のエントリには2つのゼロが含まれています。
unsigned long
キーの意味はにあります/usr/include/linux/auxvec.h
。あなたが欲しいAT_PLATFORM
、それは0x00000f
。そのことを引用しないでくださいchar *
が、プラットフォームの文字列の説明を取得するために、値はとして解釈されるべきであると思われます。
このStackOverflowの質問が役立つ場合があります。
さらに別の方法:man ld
実行可能ファイルに関する情報をダンプするように動的リンカー()に指示できます。デコードされたAUXV構造を標準出力に出力します。警告:これはハックですが、動作します。
LD_SHOW_AUXV=1 ldd /proc/$SOME_PID/exe | grep AT_PLATFORM | tail -1
次のように表示されます。
AT_PLATFORM: x86_64
32ビットバイナリで試してみましたが、i686
代わりに入手しました。
仕組み:LD_SHOW_AUXV=1
実行可能ファイルを実行する前に、デコードされたAUXV構造をダンプするようにダイナミックリンカーに指示します。人生を面白くすることが本当に好きでない限り、実際に実行ファイルを実行することは避けたいと思うでしょう。main()
関数を実際に呼び出さずにロードして動的にリンクする1つの方法は、実行ldd(1)
することです。欠点LD_SHOW_AUXV
はシェルによって有効になっているため、サブシェル、、ldd
およびターゲットバイナリのAUXV構造のダンプを取得できます。私たちはそうgrep
AT_PLATFORMための、唯一の最後の行を保持します。
auxvの解析:(auxv
ダイナミックローダーに依存せずに)自分で構造を解析する場合、少し難問があります:auxv
構造はそれが記述するプロセスのルールに従うsizeof(unsigned long)
ため、32ビットプロセスでは4、64 では8になりますビットプロセス。私たちはこの仕事をすることができます。これが32ビットシステムで機能するには、すべてのキーコードが0xffffffff
以下である必要があります。64ビットシステムでは、最上位の32ビットはゼロになります。Intelマシンはリトルエンディアンなので、これらの32ビットはメモリ内の最下位ビットに従います。
そのため、必要なことは次のとおりです。
1. Read 16 bytes from the `auxv` file.
2. Is this the end of the file?
3. Then it's a 64-bit process.
4. Done.
5. Is buf[4], buf[5], buf[6] or buf[7] non-zero?
6. Then it's a 32-bit process.
7. Done.
8. Go to 1.
マップファイルの解析:これはGillesによって提案されましたが、うまくいきませんでした。これが変更されたバージョンです。/proc/$PID/maps
ファイルの読み取りに依存しています。ファイルに64ビットアドレスがリストされている場合、プロセスは64ビットです。それ以外の場合、32ビットです。問題は、カーネルが4つのグループの16進アドレスから先行ゼロを取り除くことで出力を単純化するため、長さのハックがうまく機能しないことです。awk
救助へ:
if ! [ -e /proc/$pid/maps ]; then
echo "No such process"
else
case $(awk </proc/$pid/maps -- 'END { print substr($1, 0, 9); }') in
*-) echo "32 bit process";;
*[0-9A-Fa-f]) echo "64 bit process";;
*) echo "Insufficient permissions.";;
esac
fi
これは、プロセスの最後のメモリマップの開始アドレスをチェックすることで機能します。それらはのようにリストされています12345678-deadbeef
。したがって、プロセスが32ビットの場合、そのアドレスは8桁の16進数であり、9番目はハイフンになります。64ビットの場合、最高アドレスはそれより長くなります。9番目の文字は16進数です。
注意してください:最初と最後のメソッド以外はすべて、Linuxカーネル2.6.0以降が必要auxv
です。ファイルは以前は存在していなかったからです。
/proc/[pid]/auxv
:「ELFインタプリタ情報は、実行時にプロセスに渡されたフォーマット一つのunsigned long IDプラス各エントリに対して1つの符号なしlong値です。」(man proc
)。