< C++ .Net Early Stage 14 | Main | C++ .Net System Prog. 2 >


 

 

Early Stages of the C++ .Net 15

(Managed Extensions for C++)

 

 

In this module we will see the C++ .Net from the system programming and to be familiar with the command line tools that available in the VC++ 2003/2005. It is a very long story here. The code snippets (if any) used in this module are for Visual C++ .Net 2003 and if compiled using Visual C++ .Net 2005 you need to use the /clr:oldSyntax option. The following are the topics available in this page

 

  1. Systems Programming

  2. Assemblies

  3. Portable Executable Files

----------Next-----------------

  1. Metadata Directory

  2. Reading Metadata

  3. Assembly Format

  4. Version

  5. Culture

  6. Assembly Strong Name

  7. Assembly Configuration

  8. Configuration Files

  9. Application Settings

  10. Diagnostic Switches

  11. Remoting

  12. Startup

  13. Configuration Section Handlers

  14. Writing to Configuration Files

  15. Per-User Configuration Files

  16. Versioning and Fusion

  17. Private Assemblies

  18. Shared Assemblies

  19. PreJITted Assemblies

  20. Locating Assemblies

  21. Publisher Policy Files

  22. Security

  23. Code Access Security

  24. Role-Based Security

  25. Verifiable Code

  26. Unmanaged .NET Services API

  27. Enumerating Managed Processes

  28. Getting Information About the Garbage Collector

  29. Hosting the .NET Runtime

  30. Initializing the Runtime

  31. Summary

 

Systems Programming

 

Microsoft Visual C++ .NET is the .NET systems programming language. C++ gives you the facility to do things that are not possible to do in other languages supported by the .NET Framework. If you are the sort of person who wants complete control, Visual C++ .NET is the language for you. In this module we will go into more depth about how .NET works and how you can configure it for your code. The systems concepts of how assemblies are implemented and how to get information about the types that are implemented in assemblies will be explored. Then we will see how assemblies are configured and how you can get configuration information. We will try to learn how code access security protects your code and the implications of writing assemblies in C++ on code access security and we will see the unmanaged API for accessing the runtime and explain how you can use it.

 

Assemblies

 

Assemblies are the units of deployment, versioning, and security in .NET, and in this module, we will cover each of these issues. Assemblies can be made up of more than one file, but all code will be contained in the Microsoft Portable Executable (PE) files. Assemblies have to contain metadata (which is vital to how .NET works), and each code file in an assembly will have metadata. One file in the assembly will have information about all the other files in the metadata in a section named the manifest. This file, the one that contains the manifest, is your central point for investigating how assemblies work and the information that they contain.

 

Portable Executable Files

 

Code that executes on Windows is stored in a file format known as portable executable (PE), which is an extension of the Common Object File Format (COFF). The PE file format is shown in Figure 1.

 

The Portable Executable, PE file format

 

Figure 1: The PE file format

 

 

 

 

A PE file consists of headers containing flags about the file and sections that contain code and data. For historical reasons, all PE files have an MS-DOS header that has a small amount of x86 code that will run under MS-DOS and print out the message “This program cannot be run in DOS mode”. The MS-DOS header can be identified by the two bytes MZ (These are the initials of Mark Zbikowski, one of the original architects of MS-DOS ) at the beginning of the file. The four bytes at location 0x3c within the MS-DOS header are the offset of the PE header from the beginning of the file.

The PE header is made up of two structures, the COFF header and the PE header, and starts with a 4-byte signature, which is PE followed by 2 NULL bytes. The 20-byte COFF header contains information about the type of the machine that the file should be run on, the time and date that the file was created, and the characteristics of the file, which indicate things such as whether the file is a DLL or an EXE. The COFF header also gives the number of sections that are in the PE file. The PE header immediately follows the COFF header, and the size of the PE header is a field in the COFF header. The PE header contains information about:

 

  1. The version of the linker that was used,

  2. The size of the code and data sections,

  3. The versions of the target operating systems and subsystems, and

  4. Various other flags.

 

The PE header is 96 bytes followed by the data directory. (The size in the COFF header is the size of the fixed fields plus the size of the data directory.) The data directory contains sixteen 8-byte entries (although the data directory can obtain a different number of entries, current tools generate only 16 entries), where each entry is a relative virtual address (RVA) of the relevant table and the size of the table. An RVA is the location of the item when the file is loaded in memory relative to the load address of the file. You can find the DUMPBIN program in the bin folder of your VC++ compiler shown below (VC++ .Net 2003 and VC++ .Net 2005 Express Edition on Windows XP SP2 machine).

 

DUMPBIN executable locations

 

Figure 2: DUMPBIN locations

 

The values in the PE header can be viewed with the DUMPBIN tool using the /headers switch. For the testing purpose, using VC++ .Net 2005 EE, create CLR Console Application project named Meta1 as shown below. This is a classic Hello World program sample.

 

CLR new console application project window

 

Figure 3

 

Next, run Visual Studio 2005 Command Prompt. So we can use Visual Studio Tools directly at command prompt.

 

Invoking the Visual Studio 2005 Command Prompt

 

Figure 4

 

Try running the DUMPBIN tool.

 

Dumpbin command options

 

Figure 5

 

 

 

 

The following example shows the DUMPBIN /headers command against our sample program Meta1.exe.

F:\vc2005project\Meta1\debug>dumpbin /headers Meta1.exe

Microsoft (R) COFF/PE Dumper Version 8.00.50727.42

Copyright (C) Microsoft Corporation.  All rights reserved.

 

Dump of file Meta1.exe

 

PE signature found

 

File Type: EXECUTABLE IMAGE

 

FILE HEADER VALUES

             14C machine (x86)

               5 number of sections

        45C73B69 time date stamp Mon Feb 05 22:12:57 2007

               0 file pointer to symbol table

               0 number of symbols

              E0 size of optional header

             102 characteristics

                   Executable

                   32 bit word machine

 

OPTIONAL HEADER VALUES

             10B magic # (PE32)

            8.00 linker version

            2200 size of code

            6A00 size of initialized data

               0 size of uninitialized data

            2F04 entry point (00402F04) __CorExeMain@0

            1000 base of code

            4000 base of data

          400000 image base (00400000 to 0040CFFF)

            1000 section alignment

             200 file alignment

            4.00 operating system version

            0.00 image version

            4.00 subsystem version

               0 Win32 version

            D000 size of image

             400 size of headers

           17F64 checksum

               3 subsystem (Windows CUI)

               0 DLL characteristics

          100000 size of stack reserve

            1000 size of stack commit

          100000 size of heap reserve

            1000 size of heap commit

               0 loader flags

              10 number of directories

               0 [       0] RVA [size] of Export Directory

            9454 [      64] RVA [size] of Import Directory

            B000 [     6A4] RVA [size] of Resource Directory

               0 [       0] RVA [size] of Exception Directory

               0 [       0] RVA [size] of Certificates Directory

            C000 [     258] RVA [size] of Base Relocation Directory

            4130 [      1C] RVA [size] of Debug Directory

               0 [       0] RVA [size] of Architecture Directory

               0 [       0] RVA [size] of Global Pointer Directory

               0 [       0] RVA [size] of Thread Storage Directory

            43B0 [      40] RVA [size] of Load Configuration Directory

               0 [       0] RVA [size] of Bound Import Directory

            4000 [      D4] RVA [size] of Import Address Table Directory

               0 [       0] RVA [size] of Delay Import Directory

            414C [      48] RVA [size] of COM Descriptor Directory

               0 [       0] RVA [size] of Reserved Directory

 

SECTION HEADER #1

   .text name

    2066 virtual size

    1000 virtual address (00401000 to 00403065)

    2200 size of raw data

     400 file pointer to raw data (00000400 to 000025FF)

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

60000020 flags

         Code

         Execute Read

 

SECTION HEADER #2

  .rdata name

    5AB0 virtual size

    4000 virtual address (00404000 to 00409AAF)

    5C00 size of raw data

    2600 file pointer to raw data (00002600 to 000081FF)

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

40000040 flags

         Initialized Data

         Read Only

 

  Debug Directories

 

        Time Type       Size      RVA  Pointer

    -------- ------ -------- -------- --------

    45C73B69 cv        3F 00009168     7768    Format: RSDS, {0709F0EC-FACB-4

13A-9A5A-EDA64266A7EF}, 13, f:\vc2005project\Meta1\debug\Meta1.pdb

 

SECTION HEADER #3

   .data name

     6BC virtual size

    A000 virtual address (0040A000 to 0040A6BB)

     200 size of raw data

    8200 file pointer to raw data (00008200 to 000083FF)

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

C0000040 flags

         Initialized Data

         Read Write

 

SECTION HEADER #4

   .rsrc name

     6A4 virtual size

    B000 virtual address (0040B000 to 0040B6A3)

     800 size of raw data

    8400 file pointer to raw data (00008400 to 00008BFF)

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

40000040 flags

         Initialized Data

         Read Only

 

SECTION HEADER #5

  .reloc name

     29A virtual size

    C000 virtual address (0040C000 to 0040C299)

     400 size of raw data

    8C00 file pointer to raw data (00008C00 to 00008FFF)

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

42000040 flags

         Initialized Data

         Discardable

         Read Only

 

  Summary

 

        1000 .data

        6000 .rdata

        1000 .reloc

        1000 .rsrc

        3000 .text

 

F:\vc2005project\Meta1\debug>

 

 

 

 

This tool is just a stub for the linker with the /dump switch. DUMPBIN calls the COFF header file header values, and it calls the PE header optional header values.

The current version of DUMPBIN also describes the fifteenth data directory as the COM descriptor directory; however, this description is likely an artifact from the various names that were used for .NET before the current name was chosen. The ECMA specification calls the fifteenth data directory the CLI header, and confusingly, you can obtain this information with the /clrheader switch to DUMPBIN as shown below.

F:\vc2005project\Meta1\debug>dir

 Volume in drive F is hd0c

 Volume Serial Number is 98DB-52B1

 

 Directory of F:\vc2005project\Meta1\debug

 

02/05/2007  10:12 PM    <DIR>          .

02/05/2007  10:12 PM    <DIR>          ..

02/05/2007  10:10 PM                23 inputfile.txt

02/05/2007  10:12 PM            36,864 Meta1.exe

02/05/2007  10:12 PM                 0 Meta1.ilk

02/05/2007  10:12 PM           306,176 Meta1.pdb

02/05/2007  10:11 PM                25 outputfile.txt

               5 File(s)        343,088 bytes

               2 Dir(s)   8,525,717,504 bytes free

 

F:\vc2005project\Meta1\debug>DUMPBIN /CLRHEADER Meta1.exe

Microsoft (R) COFF/PE Dumper Version 8.00.50727.42

Copyright (C) Microsoft Corporation.  All rights reserved.

 

Dump of file Meta1.exe

 

File Type: EXECUTABLE IMAGE

 

  clr Header:

 

              48 cb

            2.05 runtime version

            43F8 [    4D70] RVA [size] of MetaData Directory

               0 flags

         6000047 entry point token

               0 [       0] RVA [size] of Resources Directory

               0 [       0] RVA [size] of StrongNameSignature Directory

               0 [       0] RVA [size] of CodeManagerTable Directory

            91A8 [     230] RVA [size] of VTableFixups Directory

               0 [       0] RVA [size] of ExportAddressTableJumps Directory

               0 [       0] RVA [size] of ManagedNativeHeader Directory

 

  Summary

 

        1000 .data

        6000 .rdata

        1000 .reloc

        1000 .rsrc

        3000 .text

 

F:\vc2005project\Meta1\debug>

The CLI header gives the RVA for the managed resources and the metadata directory. The managed resource directory holds the resources that you have added to your assembly through the linker /assemblyresource switch. The CLI header also gives the minimum version of the runtime required to run the assembly, but curiously, this version is given as 2.0x. The reason for this odd versioning may be is that .NET was known as COM+ 2.0 during the early part of its development. Immediately after the PE header is a section table that has 40 bytes for each entry. (The COFF header gives the total number of sections). Section is the name of a part of the PE file that can contain either code or data. The section table indicates the name of the section, its size and position in the PE file, and whether the section contains code or data. If the section contains code, the entry in the section header indicates whether the code is readable or writable. Sections in PE files will be located at linker determined alignments. At run time, sections are always loaded at page boundaries. This combination of read/write characteristics and the fact that they are loaded at page boundaries implies that the main purpose of a section is to provide the basic information required by the Win32 virtual memory APIs.

Section names generated by Microsoft compilers always start with a period, but if you define your own sections with #pragma data_seg (for example, to declare a shared data section), you can use any name you want. Section names have a maximum of eight characters, and names longer than this will be truncated. Furthermore, they are not necessarily NULL terminated: the entry in the section table is exactly 8 bytes. The DUMPBIN /headers switch gives this information for each section. The PE header also gives the address of the entry point of the PE file. This code is simply a JMP to either the _CorExeMain or _CorDllMain function exported from mscoree.dll.

 

The mscoree.dll file location

 

Figure 6

 

This DLL is statically imported by all .NET modules and is the only .NET file that is copied to your machine’s system directory. mscoree.dll is a shim DLL that forwards calls to the appropriate .NET system DLL (mscorwks.dll or mscorsvr.dll). All that described here is true of executable and library assemblies and of .NET module files.

 

 

Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7 | Part 8

 

 


< C++ .Net Early Stage 14 | Main | C++ .Net System Prog. 2 >