Producing Verifiable Components with Managed Extensions for C++
In Visual Studio .NET 2003, you can generate verifiable components built with Managed Extensions for C++.
Currently, the compiler does not generate any warnings if you include nonverifiable constructs in source code.
The following guidelines will help you author components that can be compiled into a verifiable component:
- Only fully managed constructs (not unmanaged classes, unmanaged pointers, and unmanaged arrays) are used
- Global variables are not used.
- CRT functions are not used and no links are made to unmanaged libraries.
- A verifiable function may not declare, create, or manipulate any object of unmanaged class type (including simple PODs).
- A verifiable function may not declare, create, or manipulate any unmanaged pointer.
- A verifiable function shall not contain a static_cast for down-casting (the compiler changes C-style casts to __try_cast in this case). static_cast between primitive types, like a single into a double, or a Byte into an Int16, is verifiable.
- A verifiable function shall not contain a reinterpret_cast (or any C-style cast equivalent).
- A verifiable function shall perform no arithmetic on a interior __gc* (byref) pointer. It may only assign to it and dereference it.
- A verifiable function shall only throw or catch pointers to __gc classes (hence value types must be boxed before throwing).
- A verifiable function may only call verifiable functions (such that calls to the CRT are not allowed, include AtEntry/AtExit, and so global constructors are disallowed).
- The type of a verifiable data member shall be primitive type, verifiable value class type, or a pointer to verifiable gc class type.
- A verifiable class may only consist of verifiable member functions, and verifiable data members.
- A verifiable class may not use LayoutKind::Explicit.
- If building an .exe, a main function cannot declare any parameters; use System::Environment::GetCommandLineArgs.
- Do not use compiler optimizations.
Also, the following keywords cannot be used in verifiable code:
- unmanaged and pack pragmas
- naked and align __declspec modifiers
- __asm
- __based
- __nogc
- __try and __except
Compiling a Verifiable Managed Extensions Assembly
This section discusses how to get the Visual C++ compiler to produce a verifiable assembly.
- Include the following in one of the source files to be compiled:
#ifdef __cplusplus extern "C" { #endif int _fltused=1; void _cdecl _check_commonlanguageruntime_version(){} #ifdef __cplusplus } #endif // An empty data section causes verifier to complain
_check_commonlanguageruntime_version is a CRT internal function to determine the version of the common language runtime. In a pure MSIL image (no native code), you need to override the CRT default behavior, which only allows an image to run on version 1.1 (or later) of the runtime.
- Specify /clr:initialAppDomain /Od to generate MSIL and disable compiler optimizations
- Suppress SkipVerification by adding the following attribute to one of your source code files:
using namespace System::Security::Permissions; [assembly:SecurityPermissionAttribute( SecurityAction::RequestMinimum, SkipVerification=false)];
- Specify linker options /link /dll /noentry /fixed:no /opt:ref, which specify linking to a DLL, a empty main entry point, to generate a relocation section, and remove unused references. Use /entry:main to build an exe.
- Run SetILOnly.exe on your component. See SetILOnly to access the source code to build this .exe.
- Use PEVerify to validate if the output image is verifiable.
When building from the development environments, you may want to use a custom build step or build event to run SetILOnly or PEVerify. For more information, see Understanding Custom Build Steps and Build Events.