#navi_header|C言語系| "/NODEFAULTLIB"リンカオプションを使うと、標準CRTをリンクしないようになる。 サイズの小さいEXEやDLL、あるいは標準以外のCRTを使いたい場合にこのオプションを使うことになるが、 [[693]] で取りあげたように "/GS" オプションがデフォルトで有効になっている為、Cookie値関連のシンボルが解決出来ずリンカエラーになる場合がある。 #more|| 対象: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: #code|c|> #include 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: #code|c|> #include 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 エラー メッセージが表示されます。 -- http://support.microsoft.com/kb/191669 - Visual C++の小技 -- http://hp.vector.co.jp/authors/VA000092/win32/vc-tech.html -- VC6の記事になるが、"CRTをぜんぜん使わないDLL"の項で、スタックチェック用の"_chkesp"の実体を手動で用意することで参照を解決する手法が載っている。 #navi_footer|C言語系|