Coins Java - i386での例外処理

i386アーキテクチャ上での例外処理

[Coins Java - 例外処理]

gcc内部でのレジスタの扱い

各レジスタに割り振られるレジスタ番号は、以下の表のようになっている。

番号 レジスタ名 備考
0 %eax
1 %ecx
2 %edx
3 %ebx
4 %esp スタックポインタ
5 %ebp フレームポインタ
6 %esi
7 %edi
8 %eip 擬似レジスタ。プログラムカウンタ
9 %eflags
10 %trapno 擬似レジスタ。
11 %st(0)
12 %st(1)
13 %st(2)
14 %st(3)
15 %st(4)
16 %st(5)
17 %st(6)
18 %st(7)

prologue処理

基本的には、以下のようなプログラムになっている。

// callerのフレームポインタを退避
pushl  %ebp
// calleeのフレームポインタを設定
movl   %esp, %ebp

フレームの形状

以下のような形状をしている。

ただし、この形状になるのは、Prologue処理終了後である。

関数が呼び出されると、メモリアドレスの高いほうから順にリターンアドレス、呼び出しフレームのフレームポインタを格納し、関数で使用される自動変数領域を確保する。例外処理で使用される情報は、主にリターンアドレスとフレームポインタである。

CIEの形状

基本的な部分の解説はCIEにまわすとして、アーキテクチャ依存する部分のみを記述する。

要素 備考
code align 1
data align -4 スタックフレームの構造
return address column 8 %eipのレジスタ番号が8であるため

また、CIEが持つCFAは以下のようになっていた。

// CFAの定義
// i386では %esp が 4 番のレジスタで、関数呼び出し直後は %esp+4 がフレームの先頭になるため
def_cfa 4 4 (0x0c 0x04 0x04)
// 復帰すべきレジスタの登録
// i386では 8番のレジスタがプログラムカウンタである。
// この命令は、先ほど設定した data align の影響を受け、-4倍される。
// CFAの先頭から-4バイトずらした位置にはリターンアドレスが格納されているため、
// フレームの巻き戻しを行う際にはこのアドレスをPCに書きもどしてやる必要がある。
offset 8 1

FDEの形状

基本的な部分の解説はFDEにまわすとして、アーキテクチャ依存する部分のみを記述する。FDECIEのような設定は無く、CFAから始まる。

// PCの移動
// 開始直後に %ebp を退避し、 %esp がずれてしまうため、[[CFA|Coins Java - CFA]]の先頭アドレスもずれてしまう。
// このアドレスがずれる直後までPCを移動する。
// もし、PCがここに達していない場合は、これ以降のインストラクションは考慮しない。
advance_loc4 (%ebpを退避させた直後のアドレス - メソッドの開始位置)
// CFAの再定義
// %espがずれてしまったため、フレームの先頭位置を調整する。
// スタックにプッシュした際に、%espが4バイト加算されるのだから、オフセットを4バイトずらしてやればよい
def_cfa_offset 8
// 復帰すべきレジスタの登録
// フレームの巻き戻しを行う際に%ebpを復帰させる必要がある。
// %ebpのレジスタ番号は5番で、フレームの先頭から2つ目にプッシュしたのでそれを指定する。
// ちなみに、フレームの先頭から1つ目のデータはリターンアドレスである。
offset 5 2
// PCの移動
// 次のステップでは、この関数内でのフレームポインタを設定する。
advance_loc4 ((movl %esp, %ebp)を行ったアドレス - %ebpを退避させた直後のアドレス)
// CFAの再定義
// 今までは%espを起点にCFAを設定していたが、%espは今後、頻繁に変更される可能性があるため、
// %ebp(フレームポインタ)を起点に使用することになる。
// このオペレーションでは、起点以降のオフセット(= 8)は変化しない
def_cfa_register 5
// これ以降は解析中
// デバッグ用の情報か、GC用の情報かも知れず
; advance_loc4 .LCFI0-.LFB26
; fs->pc += (.LCFI3-.LCFI1) * fs->code_align
.byte  0x4
.long  .LCFI3-.LCFI1
args_size 16
context->args_size = 16
.byte  0x2e
.uleb128  0x10

キャッチ時の状態

次のレジスタにキャッチ時の情報が格納されている。

レジスタ名 情報
%eax unwindHeader
%edx ar_filter

Copyright (C) 2002-2006 s.arakawa