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はglibcのglibc/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_SYSCALL
はINTERNAL_SYSCALL
を呼んでいる。
このINTERNAL_SYSCALL
の中でint $0x80
が呼ばれていて、割り込みしているのがわかる。
movl %1, %%eax
で 1番目のオペランドを%eaxに入れるということなので(参考:
GCCのインラインアセンブラの書き方 for x86 - OSのようなもの)、これで"i": (__NR_##name)
が%eaxに入り、execve
システムコールが実行される。あとはdefine
されている変数を見ていくと、%ebx
, %ecx
, %edx
にそれぞれ引数を入れている。
これからexecve
システムコールを把握していくわけだけど疲れたのでここまで。
メモ
- asmのcallsysというのはこれのことかなぁ
- registerについて
- 高速に処理しろということらしい
- C言語/データ型と変数 - Wikibooks
- volatileについて
- 最適化するなということらしい
- inline assembly
- __NR_execve