home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

C言語系/memos/VC++/10, "/NODEFAULTLIB"使用時の注意

C言語系/memos/VC++/10, "/NODEFAULTLIB"使用時の注意

C言語系 / memos / VC++ / 10, " / NODEFAULTLIB"使用時の注意
id: 694 所有者: msakamoto-sf    作成日: 2010-07-04 15:13:42
カテゴリ: C言語 Windows 

"/NODEFAULTLIB"リンカオプションを使うと、標準CRTをリンクしないようになる。
サイズの小さいEXEやDLL、あるいは標準以外のCRTを使いたい場合にこのオプションを使うことになるが、 C言語系/memos/VC++/09, スタック破壊の検出・防止("/GS", "/RTC", "/GZ") で取りあげたように "/GS" オプションがデフォルトで有効になっている為、Cookie値関連のシンボルが解決出来ずリンカエラーになる場合がある。

対象:Visual C++ 2008 Express Edition, Windows XP SP3 (Japanese)

> cl
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.
> link
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

dll.c:

#include <windows.h>
 
int __declspec(dllexport) funcA(int a, int b) { return a + b + funcB(a, b); }
int funcB(int a, int b) { return a * b; }
 
/*
int mycpy(const char *src)
{
    char buf[20];
    int i = 0;
    for (i = 0; i < 20; i++, src++) {
        buf[i] = *src;
    }
    return i;
}
*/
 
BOOL WINAPI DllMain(
        HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved)
{
    switch (dwReason) {
        case DLL_PROCESS_ATTACH:
            MessageBox(NULL, "DLL_PROCESS_ATTACH", "dll", MB_OK);
            break;
        case DLL_PROCESS_DETACH:
            MessageBox(NULL, "DLL_PROCESS_DETACH", "dll", MB_OK);
            break;
    }
    return TRUE;
}

main.c:

#include <windows.h>
 
int __declspec(dllimport) funcA(int a, int b);
 
/*
int mycpy(const char *src)
{
    char buf[20];
    int i = 0;
    for (i = 0; i < 20; i++, src++) {
        buf[i] = *src;
    }
    return i;
}
*/
 
int WINAPI WinMain(
        HINSTANCE hInst, 
        HINSTANCE hPrevInst, 
        LPSTR lpCmdLine, 
        int nCmdShow)
{
    int a = funcA(2, 3);
    MessageBox(NULL, "WinMain", "main", MB_OK);
    return 0;
}

この時点ではまだ"/GS"によるスタック保護の対象となる"mycpy()"関数がコメントアウトされている為、Cookie値チェックのコードは埋め込まれない。

コンパイル:

> cl dll.c /LD user32.lib /link /entry:DllMain /nodefaultlib
> cl main.c user32.lib dll.lib /link /entry:WinMain /nodefaultlib

ところが、コメントマークを外して"mycpy()"関数を有効にすると、Cookie値チェックのコードが埋め込まれそれにより__security_cookie, __security_check_cookieへの参照が埋め込まれる。しかし標準CRTが"/nodefaultlib"オプションによりリンクされない為、参照が解決出来ずリンカエラーとなる。

dllの場合:

dll.obj : error LNK2019: 未解決の外部シンボル ___security_cookie が関数 _mycpy で参照されました。
dll.obj : error LNK2019: 未解決の外部シンボル @__security_check_cookie@4 が関数 _mycpy で参照されました。
dll.dll : fatal error LNK1120: 外部参照 2 が未解決です。

exeの場合:

main.obj : error LNK2019: 未解決の外部シンボル ___security_cookie が関数 _mycpy で参照されました。
main.obj : error LNK2019: 未解決の外部シンボル @__security_check_cookie@4 が関数 _mycpy で参照されました。
main.exe : fatal error LNK1120: 外部参照 2 が未解決です。

もしも自分のコードに自信があれば、"/GS-"オプションを指定する。これによりCookie値チェック関連のコードが挿入されず、リンカエラーも消える。

コンパイル:

> cl dll.c /GS- /LD user32.lib /link /entry:DllMain /nodefaultlib
> cl /GS- main.c user32.lib dll.lib /link /entry:WinMain /nodefaultlib

ただし "/GS" によるスタック破壊のチェックが使えなくなる為、そのセキュリティ上のデメリットを考慮して"/GS-"オプションを指定する。

参考:

  • Visual C++ 6. 0 でプロジェクトをビルドすると、"エラー LNK2001 未解決の外部シンボル"__chkesp エラー メッセージが表示されます。
  • Visual C++の小技


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2010-07-04 15:31:54
md5:e6136f4609176dc9000403aa74c57d99
sha1:5e8ae772cd846550c3755000d9e43cff046c8c8c
コメント
コメントを投稿するにはログインして下さい。