ウィンビー国際的アイドル化計画
Download
Report
Transcript ウィンビー国際的アイドル化計画
オペレーティングシステム発表資料
Win32 on BeOS
プラットフォームの違いとは?
CPUの違い
APIの違い
実行形式の違い
エミュレーション可能だが、パ
フォーマンスは落ちる
仕様がわかっていれば互換
APIを用意する事で解決
直接実行するにはOSのサ
ポートが必要だが、間接的に
実行するならアプリケーション
でのサポートで十分
実装ポリシー
やった事
PE(COFF)ローダの実装
膨大なWin32 APIを(必要なとこだけ)実装
gccの移植と改変(DirectXとCOM)
メモリ再配置不能問題の対処
動作例
実行形式
メモリ空間
プログラムコード
初期化値付きデータ
未初期化データ
・プログラムのサイズ、場所
・初期化データのサイズ、場所
・未初期化データのサイズ
・再配置情報
・共有ライブラリ情報
.
.
.
実行ファイル
スタック
ヘッダ情報
カーネル領域
プログラムコード
初期値データ
共有ライブラリ
プログラム
プログラム側の処理としてはDLL関数呼び出しは、
ExternLib[func_number](args);
といった処理と等価になっている。
0x08000000[0]();
0x08000000
0x10000000
0x10000240
0x10000614
.
.
ExternLibという関数テーブルは、プログラムロード
時にOSによって適切な値が設定される。
関数テーブル
0x10000000
共有ライブラリ
再配置情報
再配置情報
アプリケーション
.
mov ax, 0x80403f00
.
.
call 0x80402024
.
補正
アプリケーション
.
mov ax, 0x00403f00
.
.
call 0x00402024
.
プロセスの生成
fork→exec系
create process系
親
fork
親
子
exec
CreateProcess
子
アプリケーションの間接実行
直接実行(OS)
(Kernel)
読み込み・解釈
リソース割り当て
(User)
間接実行(ユーザー)
(Kernel)
(中継プロセスの)
起動要求
読み込み・解釈
起動
(User)
起動要求
(中継プロセスの)
(中継プロセスの)
リソース割り当て
起動
(Win32プロセスの)
読み込み・解釈
リソース割り当て
リソース要求
(Win32プロセスの)
起動
Windows/BeOSのメモリ配置
Windows
HAL
各種プール・キャッシュ・エントリ
メモリマップドファイル
BeOS
0xFFFFFFFF
共有ライブラリ
カ
ー
ネ
ル
領
域
0xEC000000
実行イメージ
0xA0000000
ユ
ー
ザ
ー
領
域
カーネル
0x80000000
ユ
ー
ザ
ー
領
域
実行イメージ・共有ライブラリ
0x30000000
0x10000000
0x00000000
カ
実行ファイル・共有ライブラリのキャッシュ ー
ネ
ル
領
域
物理メモリ
カーネル
Windowsに置ける標準的な実行イメージ配置場所にBeOSではカーネルが存在してい
る!!
再配置が必要不可欠
動的再配置(1) - 仮配置
実際の配置場所
再配置情報がない場合には、必ず仮
定されたアドレスへ配置する必要があ
るのだが、それは不可能なので、とり
あえず必要な補正は行えないが、別の
アドレスへ配置する。
(本来の配置場所)
実行イメージ
動的再配置(2) - クラッシュ
.
.
call 0x00402024
.
.
.
.
巻き戻し・再実行
解析・修正
クラッシュ
アドレス
補正処理
.
.
call 0x80402024
.
.
.
.
動的再配置(3) - 予測
下の例のように、単純に問題個所だけ補正していた
のでは解決できない場合が多々ある!
char buffer[1024];
char *p;
for (p = buffer; p != &buffer[1024]; p++) *p = 0;
1. 最初の「*p = 0」で、不正なアドレスへのアクセスが発生。「p」の指すアドレスが補正される。
2. この状態では「&buffer[1024]」という値は補正前の値になっている。
3. 終了条件に一致せず、永遠にメモリを「0」で埋め尽くす。
4. スタックの破壊。この状態からはもはや復帰不能。
問題個所周辺のプログラム・データの流れについて、
十分な解析・予測の上で補正する必要があり、これ
を自動的に完全動作させるのは不可能。
おまけ(1)
CoffError
Coff::SetSignal
(void)
{
CoffError rc = COFF_ERR_UNKNOWN;
struct sigaction sa;
sa.sa_handler = (__signal_func_ptr)CoffSigSegv;
sa.sa_mask = 0;
sa.sa_flags = 0;
sa.sa_userdata = (void *)this;
struct sigaction old;
if (0 == sigaction(SIGSEGV, &sa, &old)) {
old_sigsegv = old.sa_handler;
rc = COFF_ERR_OK;
}
return rc;
}
おまけ(2)
.section
.text
.p2align
.global
.type
CoffSigSegv:
pushl
movl
subl
movl
movl
movl
lea
pushl
movl
pushl
movl
pushl
movl
pushl
call
movl
movl
movl
movl
popl
ret
nop
.Lfel:
.size
.rodata
2
CoffSigSegv
main, @function
%ebp
%esp, %ebp
$0x0c, %esp
%ebx, -0x04(%ebp)
%esi, -0x08(%ebp)
%edi, -0x0c(%ebp)
-0x0c(%ebp), %eax
%eax
0x10(%ebp), %eax
%eax
0x0c(%ebp), %eax
%eax
0x08(%ebp), %eax
%eax
SigSegv__4CoffiP4CoffP5vregsP8_xxxregs
-0x04(%ebp),%ebx
-0x08(%ebp),%esi
-0x0c(%ebp),%edi
%ebp, %esp
%ebp
CoffSigSegv,.Lfel - main
おまけ(3)
void
Coff::SigSegv
(int no, Coff *obj, vregs *regs, xxxregs *xregs)
{
obj->mSigSegv(regs, xregs);
}