Borland C++ Compiler での、コンパイラ/リンカオプションやライブラリなどの早見表、および C言語系/memos/BCC/01, Win32のEXE,LIB,DLL開発入門(C言語) では取りあげなかったミニTipsなど。
対象:
> bcc32 Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland (...) > ilink32 Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland (...)
以下のFAQ掲載のスタートアップモジュール/インポートライブラリ、および C言語系/memos/BCC/01, Win32のEXE,LIB,DLL開発入門(C言語) で取りあげたいくつかのコマンドラインオプションをまとめておく。
ターゲットを指定するには、次の3つのオプションのいずれかを指定する。
-W : GUIアプリケーション -WC : コンソールアプリケーション -WD : DLL
以下のオプションは、他のオプションと組み合わせて使用出来る。
-WM : マルチスレッド -WU : UNICODE対応 -WR : ダイナミックRTLを使用
※W付はワイド文字版
| C0X32(W).OBJ | 32ビットコンソールモード用EXEスタートアップモジュール |
| C0W32(W).OBJ | GUI .EXE用スタートアップモジュール |
| C0D32(W).OBJ | DLLスタートアップモジュール |
| C0D32X.OBJ | DLLスタートアップモジュール(例外処理なし) |
| FILEINFO.OBJ | オープンしているファイルハンドル情報を子プロセスへ渡すときに使う |
| GP.OBJ | 例外処理発生時にレジスタダンプを印刷する |
| WILDARGS.OBJ | ワイルドカード引数を評価 |
| CW32.LIB | シングルスレッドのRTL |
| CW32I.LIB | シングルスレッドのRTL(CC3250.DLL)用 ImportLIB |
| CW32MT.LIB | マルチスレッドのRTL |
| CW32MTI.LIB | マルチスレッドのRTL(CC3250MT.DLL)用 ImportLib |
| DXEXTRA.LIB | DirectX用スタティックLib |
| IMPORT32.LIB | APIのインポートライブラリ |
| INET.LIB | MS Internet DLL用ImportLib |
| NOEH32.LIB | 例外処理を除外するためのライブラリ |
| OLE2W32.LIB | 32ビットOLE 2.0API用Import Lib |
| OLEAUT32.LIB | 32ビットOLE 2.0API用Import Lib |
| UUID.LIB | Direct3D、DirectDraw、シェルエクステンションなどのためのGUIDライブラリ |
| WININET.LIB | WININET.LIB用ImportLib |
| WS2_32.LIB | 32ビットWinSock 2.0用ImportLib |
・コンソールアプリ:
スタートアップモジュール : C0X32.OBJ ライブラリ: CW32.LIB + IMPORT32.LIB
・GUIアプリ:
スタートアップモジュール : C0W32.OBJ ライブラリ: CW32.LIB + IMPORT32.LIB
・ランタイムライブラリをDLLとしてリンクする場合は、CW32.LIBではなくCW32I.LIBをリンクする。
CW32I.LIB をリンク → CC3250.DLL が必要(BINディレクトリ中に存在) CW32MTI.LIB をリンク → CC3250MT.DLL が必要(同上)
※いずれも32bitGUIアプリ対応
・マルチスレッド用のライブラリ(CW32MT.LIB/CW32MTI.LIB)はBCC32.EXEでの
-WM
オプション指定時に使う。
・NOEH32.LIBを指定して例外処理を扱わないようにすることで、BCCで作成するアプリケーションの実行ファイルのサイズを節約することが可能。ただしC++の入出力クラスなど例外処理が必要な場合は無効。
C言語系/memos/BCC/01, Win32のEXE,LIB,DLL開発入門(C言語) の複数ファイル分割の項から再掲:
ILINK32 [@respfile][options] startup myobjs, [exe], [mapfile], [libraries], [deffile], [resfile]
"options"では、/c (シンボルで大文字と小文字を区別)オプションを忘れずに指定すること。
またターゲット指定のオプションを以下に簡単にまとめる。
| /aa | 32 ビット Windows アプリケーションを構築する |
| /ad | 32 ビット Windows デバイスドライバを構築する |
| /ap | 32 ビット Windows コンソールアプリケーションを構築する |
| /Tpd | Windows の .DLL ファイルをターゲットにする |
| /Tpe | Windows の .EXE ファイルをターゲットにする |
Visual C++ 2008 のC++コンパイラが生成するインポートライブラリはCOFF (Common Object File Format)というファイル形式になっている。一方Borland C++ Compilerが生成するOBJ, LIBファイルは(Relocatable) OMF (Object Module Format)というファイル形式になっている。
この違いが問題となってくるのは、Visual C++ で生成したインポートライブラリをBorland C++ Compilerでリンクする場合である。
Visual C++ → xxyy.dll (PE: Porable Executable ファイル)
xxyy.lib (COFF)
↓
BCC32/ILINK32 client.obj (OMF) → このままではCOFF形式のLIBをOMF形式のOBJとリンク出来ない!
ここで登場するのが Borland C++ Compiler に含まれている COFF2OMF.EXE である。
まずCOFF形式のインポートライブラリをリンクしようとすると、エラーとなってしまうことを確認する。
> dir foobar_usedll_cui.c libdllfoobarbaz.dll ... VC++2008で生成したDLL libdllfoobarbaz.lib ... 同上のインポートライブラリ(COFF形式) > bcc32 -c foobar_usedll_cui.c > bcc32 -WC foobar_usedll_cui.obj libdllfoobarbaz.lib Error: 'C:\IN_VITRO\C\BCCTEST03\LIBDLLFOOBARBAZ.LIB' contains invalid OMF record, type 0x21 (possibly COFF)
(foobar_usedll_cui.cおよびlibdllfoobarbaz.dllのソースは省略)
COFF2OMFを使って、OMF形式のインポートライブラリ "libdllfoobarbaz_omf.lib" に変換してリンク&実行:
> COFF2OMF libdllfoobarbaz.lib libdllfoobarbaz_omf.lib > bcc32 -WC foobar_usedll_cui.obj libdllfoobarbaz_omf.lib > foobar_usedll_cui.exe foo(2, 3) = 5 bar(2, 3) = 6
DLL側とアプリ側とで呼び出し規約を一致させる必要がある点に注意すること。これがずれてしまうと、スタックのクリーンアップがずれてしまい異常終了の原因になる。
呼び出し規約に応じてシンボル名の修飾が入るが、COFF2OMFでは"-lib"オプションで修飾名の調整を行える。
"-lib:ms" : MS C++ の名前の変形(name mangling)のあるエントリを許可(デフォルト: no) "-lib:st" : MS stdcall の変形にエリアスを使うかわりに名前を標準化する "-lib:ca" : MS cdecl エリアス使用を行わない(デフォルトはエリアシングする)
呼び出し規約が一致しなくとも、"-lib"オプションを調整することで「無理矢理」リンクに成功させることも出来るが、当然、異常終了の原因となる。
呼び出し規約の不一致による異常終了は、アセンブラのレベルでデバッグをしないと発見が難しい。重ね重ね注意が必要である。
アセンブラコードを出力するには、"-S"オプションを使う。
bar.c:
int bar(int a, int b) {
return a * b;
}
アセンブラファイルは拡張子が".asm"で出力される。
> bcc32 -S bar.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland bar.c:
bar.asm:
.386p
(...)
_bar proc near
?live1@0:
;
; int bar(int a, int b) {
;
push ebp
mov ebp,esp
;
; return a * b;
;
@1:
mov eax,dword ptr [ebp+8]
imul dword ptr [ebp+12]
;
; }
;
@3:
@2:
pop ebp
ret
_bar endp
_TEXT ends
public _bar
?debug D "bar.c" 15447 27147
end
これをコンパイルするにはTASM32が必要らしい。
例えばOllyDbgのLoaddllはアセンブラで書かれており、TASM32でコンパイルされる。(*1)
EXE or DLLファイルのヘッダー情報をダンプ
tdump -e xxxx.exe tdump -e xxxx.dll
エクスポートの一覧をダンプ
tdump -ee xxxx.exe tdump -ee xxxx.dll
インポート一覧をダンプ
tdump -em xxxx.exe
インポートしたモジュール一覧をダンプ
tdump -em. xxxx.exe
COFF形式のOBJ, LIBファイルをダンプ
tdump -C xxxx.obj tdump -C xxxx.lib