2011年4月14日
falcnvrtを64bitビルド
せっかく64bit環境な訳だし64bit版を作るべくVC2010EE+WindowsSDK7.1環境で設定してビルドをポチっと。
出るわ出るわwarningの山。
ただsize_tが64bit値になっているせいで出ているのが大半で後はDWORD_PTR系程度で簡単にビルド完了。
UNICODEも有効にしてたけどもともとTCHARベースで開発してたおかげでこれまた問題なし。
とりあえず簡単な動作テストはクリアして拍子抜け・・・
デバッグ関数
ただ一つだけ懸念していたのがデバッグ関数。
イース6とフェルガナのconfig.exeから画像抽出するのにデバッグ関数使っていたのが案の定ダメ。
ブレークポイントに引っかからずに起動してしまう。
64bitプロセスから32bitプロセスをデバッグ起動してすんなりいく訳は無いわな。
IMAGE_NT_HEADERS
まず IMAGE_NT_HEADERS の ImageBase を利用していたのだが32bit仕様だと
typedef struct _IMAGE_OPTIONAL_HEADER { // ~略~ DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; DWORD ImageBase; DWORD SectionAlignment; // ~略~ } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
なのが64bit仕様だと
typedef struct _IMAGE_OPTIONAL_HEADER64 { // ~略~ DWORD AddressOfEntryPoint; DWORD BaseOfCode; ULONGLONG ImageBase; DWORD SectionAlignment; // ~略~ } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
となってて ImageBase が BaseOfData とくっついてULONGLONGに・・・
IMAGE_OPTIONAL_HEADER を IMAGE_OPTIONAL_HEADER32 と明示的に宣言するようにしてこの問題は解決。
Get/SetThreadContext
しかしまだブレークポイントで止まらない。
色々調べてると64bitアプリから32bitアプリ(WOW64で動作)のものに対しては、
SetThreadContextじゃなくWow64SetThreadContextを使えばいいらしい?(日本語の情報が無い・・・)
そこでブレークポイント設定関数を
BOOL SetBreakPoint32(HANDLE hThread, DWORD dwAddress) { CONTEXT ctx = { CONTEXT_DEBUG_REGISTERS }; GetThreadContext( hThread, &ctx ); ctx.Dr0 = dwAddress; ctx.Dr7 |= 0x00000001; return SetThreadContext( hThread, &ctx ); }
BOOL SetBreakPoint64(HANDLE hThread, DWORD dwAddress) { WOW64_CONTEXT ctx = { WOW64_CONTEXT_DEBUG_REGISTERS }; Wow64GetThreadContext( hThread, &ctx ); ctx.Dr0 = dwAddress; ctx.Dr7 |= 0x00000001; return Wow64SetThreadContext( hThread, &ctx ); }
として#ifdef _WIN64で切り替えて使うように変更。
ビルドして試してみると無事ブレークポイントで止まるように!
完成
これで一応falcnvrtの64bit版は完成。
公開はどうしようかな。
あとがき
ただWow64SetThreadContextって対応OSがVista以降なんだけどXP64bit版はどうするんだ?
XPの64bit版も32bitアプリはWOW64で動作のはずだけどこのAPI使えないよなぁ。
~~DISCUSSION~~