ELFがどう実行されるか調べる

コンパイラつくろー - エンジニアですよ!で書いたようにコンパイラを作っている。

フロントエンドもさることながらバックエンドの難しさは自分の理解できる範囲を余裕で超えている。

気になることを調べながら地道に進めていく。

ELFヘッダーについて調べつつ、bashなどのshellからどうELF形式のファイルが実行されるのか調べようと思った。

フォーマットはここを読みつつだが、実際に実行されるところを追うという点では、

ここがかなり参考になった。Binary Hacksかなり欲しくなった。

bashで./helloとかする場合どういう処理がされるかを追ってみる。

helloはこれ

bashをbuildしてgdbで実行の流れを追ってみたんだけど、if (pid ==0) を待つようなところで延々とループになって止まってしまう。 当たり前かもしれないけどよくわかってない。straceをattachしてみたら延々と同じことを繰り返している。。

仕方ないので追うのは諦めるが、bashのexecute_cmd.cのexecute_disk_commandが呼ばれていることはわかる。

そして止まってしまう4914行目のifの中を確認すると、最後に

exit (shell_execve (command, args, export_env));

としてshell_execveを呼び出しているのがわかる。このなかでexecveを呼んでいる。

execveはglibcglibc/sysdeps/unix/sysv/linux/execve.cに定義されている

int
__execve (file, argv, envp)
     const char *file;
     char *const argv[];
     char *const envp[];
{
  return INLINE_SYSCALL (execve, 3, file, argv, envp);
}
weak_alias (__execve, execve)

systemcall呼んでるのであろうことがわかる。

INLINE_SYSCALLINTERNAL_SYSCALLを呼んでいる。

このINTERNAL_SYSCALLの中でint $0x80が呼ばれていて、割り込みしているのがわかる。

movl %1, %%eaxで 1番目のオペランドを%eaxに入れるということなので(参考: GCCのインラインアセンブラの書き方 for x86 - OSのようなもの)、これで"i": (__NR_##name)が%eaxに入り、execveシステムコールが実行される。あとはdefineされている変数を見ていくと、%ebx, %ecx, %edxにそれぞれ引数を入れている。

これからexecveシステムコールを把握していくわけだけど疲れたのでここまで。

メモ