Figure 2 IMAGE_DATA_DIRECTORY Values
Value
|
Description
|
IMAGE_DIRECTORY_ENTRY_EXPORT
|
Points to the exports (an IMAGE_EXPORT_DIRECTORY structure).
|
IMAGE_DIRECTORY_ENTRY_IMPORT
|
Points to the imports (an array of IMAGE_IMPORT_DESCRIPTOR structures).
|
IMAGE_DIRECTORY_ENTRY_RESOURCE
|
Points to the resources (an IMAGE_RESOURCE_DIRECTORY structure.
|
IMAGE_DIRECTORY_ENTRY_EXCEPTION
|
Points to the exception handler table (an array of IMAGE_RUNTIME_FUNCTION_ENTRY structures). CPU-specific and for table-based exception handling. Used on every CPU except the x86.
|
IMAGE_DIRECTORY_ENTRY_SECURITY
|
Points to a list of WIN_CERTIFICATE structures, defined in WinTrust.H. Not mapped into memory as part of the image. Therefore, the VirtualAddress field is a file offset, rather than an RVA.
|
IMAGE_DIRECTORY_ENTRY_BASERELOC
|
Points to the base relocation information.
|
IMAGE_DIRECTORY_ENTRY_DEBUG
|
Points to an array of IMAGE_DEBUG_DIRECTORY structures, each describing some debug information for the image. Early Borland linkers set the Size field of this IMAGE_DATA_DIRECTORY entry to the number of structures, rather than the size in bytes. To get the number of IMAGE_DEBUG_DIRECTORYs, divide the Size field by the size of an IMAGE_DEBUG_DIRECTORY.
|
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
|
Points to architecture-specific data, which is an array of IMAGE_ARCHITECTURE_HEADER structures. Not used for x86 or IA-64, but appears to have been used for DEC/Compaq Alpha.
|
IMAGE_DIRECTORY_ENTRY_GLOBALPTR
|
The VirtualAddress field is the RVA to be used as the global pointer (gp) on certain architectures. Not used on x86, but is used on IA-64. The Size field isn't used. See the November 2000 Under The Hood column for more information on the IA-64 gp.
|
IMAGE_DIRECTORY_ENTRY_TLS
|
Points to the Thread Local Storage initialization section.
|
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
|
Points to an IMAGE_LOAD_CONFIG_DIRECTORY structure. The information in an IMAGE_LOAD_CONFIG_DIRECTORY is specific to Windows NT, Windows 2000, and Windows XP (for example, the GlobalFlag value). To put this structure in your executable, you need to define a global structure with the name __load_config_used, and of type IMAGE_LOAD_CONFIG_DIRECTORY. For non-x86 architectures, the symbol name needs to be _load_config_used (with a single underscore). If you do try to include an IMAGE_LOAD_CONFIG_DIRECTORY, it can be tricky to get the name right in your C++ code. The symbol name that the linker sees must be exactly: __load_config_used (with two underscores). The C++ compiler adds an underscore to global symbols. In addition, it decorates global symbols with type information. So, to get everything right, in your C++ code, you'd have something like this: extern "C"
IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {...}
|
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
|
Points to an array of IMAGE_BOUND_IMPORT_DESCRIPTORs, one for each DLL that this image has bound against. The timestamps in the array entries allow the loader to quickly determine whether the binding is fresh. If stale, the loader ignores the binding information and resolves the imported APIs normally.
|
IMAGE_DIRECTORY_ENTRY_IAT
|
Points to the beginning of the first Import Address Table (IAT). The IATs for each imported DLL appear sequentially in memory. The Size field indicates the total size of all the IATs. The loader uses this address and size to temporarily mark the IATs as read-write during import resolution.
|
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
|
Points to the delayload information, which is an array of CImgDelayDescr structures, defined in DELAYIMP.H from Visual C++. Delayloaded DLLs aren't loaded until the first call to an API in them occurs. It's important to note that Windows has no implicit knowledge of delay loading DLLs. The delayload feature is completely implemented by the linker and runtime library.
|
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
|
This value has been renamed to IMAGE_DIRECTORY_ENTRY_COMHEADER in more recent updates to the system header files. It points to the top-level information for .NET information in the executable, including metadata. This information is in the form of an IMAGE_COR20_HEADER structure.
|
Figure 3 IMAGE_FILE_HEADER
Size
|
Field
|
Description
|
WORD
|
Machine
|
The target CPU for this executable. Common values are: IMAGE_FILE_MACHINE_I386 0x014c // Intel 386
IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64
|
WORD
|
NumberOfSections
|
Indicates how many sections are in the section table. The section table immediately follows the IMAGE_NT_HEADERS.
|
DWORD
|
TimeDateStamp
|
Indicates the time when the file was created. This value is the number of seconds since January 1, 1970, Greenwich Mean Time (GMT). This value is a more accurate indicator of when the file was created than is the file system date/time. An easy way to translate this value into a human-readable string is with the _ctime function (which is time-zone-sensitive!). Another useful function for working with this field is gmtime.
|
DWORD
|
PointerToSymbolTable
|
The file offset of the COFF symbol table, described in section 5.4 of the Microsoft specification. COFF symbol tables are relatively rare in PE files, as newer debug formats have taken over. Prior to Visual Studio .NET, a COFF symbol table could be created by specifying the linker switch /DEBUGTYPE:COFF. COFF symbol tables are almost always found in OBJ files. Set to 0 if no symbol table is present.
|
DWORD
|
NumberOfSymbols
|
Number of symbols in the COFF symbol table, if present. COFF symbols are a fixed size structure, and this field is needed to find the end of the COFF symbols. Immediately following the COFF symbols is a string table used to hold longer symbol names.
|
WORD
|
SizeOfOptionalHeader
|
The size of the optional data that follows the IMAGE_FILE_HEADER. In PE files, this data is the IMAGE_OPTIONAL_HEADER. This size is different depending on whether it's a 32 or 64-bit file. For 32-bit PE files, this field is usually 224. For 64-bit PE32+ files, it's usually 240. However, these sizes are just minimum values, and larger values could appear.
|
WORD
|
Characteristics
|
A set of bit flags indicating attributes of the file. Valid values of these flags are the IMAGE_FILE_xxx values defined in WINNT.H. Some of the more common values include those listed in Figure 4.
|
Figure 4 IMAGE_FILE_XXX
Value
|
Description
|
IMAGE_FILE_RELOCS_STRIPPED
|
Relocation information stripped from a file.
|
IMAGE_FILE_EXECUTABLE_IMAGE
|
The file is executable.
|
IMAGE_FILE_AGGRESIVE_WS_TRIM
|
Lets the OS aggressively trim the working set.
|
IMAGE_FILE_LARGE_ADDRESS_AWARE
|
The application can handle addresses greater than two gigabytes.
|
IMAGE_FILE_32BIT_MACHINE
|
This requires a 32-bit word machine.
|
IMAGE_FILE_DEBUG_STRIPPED
|
Debug information is stripped to a .DBG file.
|
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
|
If the image is on removable media, copy to and run from the swap file.
|
IMAGE_FILE_NET_RUN_FROM_SWAP
|
If the image is on a network, copy to and run from the swap file.
|
IMAGE_FILE_DLL
|
The file is a DLL.
|
IMAGE_FILE_UP_SYSTEM_ONLY
|
The file should only be run on single-processor machines.
|
Figure 5 IMAGE_OPTIONAL_HEADER
Size
|
Structure Member
|
Description
|
WORD
|
Magic
|
A signature WORD, identifying what type of header this is. The two most common values are IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b and IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b.
|
BYTE
|
MajorLinkerVersion
|
The major version of the linker used to build this executable. For PE files from the Microsoft linker, this version number corresponds to the Visual Studio version number (for example, version 6 for Visual Studio 6.0).
|
BYTE
|
MinorLinkerVersion
|
The minor version of the linker used to build this executable.
|
DWORD
|
SizeOfCode
|
The combined total size of all sections with the IMAGE_SCN_CNT_CODE attribute.
|
DWORD
|
SizeOfInitializedData
|
The combined size of all initialized data sections.
|
DWORD
|
SizeOfUninitializedData
|
The size of all sections with the uninitialized data attributes. This field will often be 0, since the linker can append uninitialized data to the end of regular data sections.
|
DWORD
|
AddressOfEntryPoint
|
The RVA of the first code byte in the file that will be executed. For DLLs, this entrypoint is called during process initialization and shutdown and during thread creations/destructions. In most executables, this address doesn't directly point to main, WinMain, or DllMain. Rather, it points to runtime library code that calls the aforementioned functions. This field can be set to 0 in DLLs, and none of the previous notifications will be received. The linker /NOENTRY switch sets this field to 0.
|
DWORD
|
BaseOfCode
|
The RVA of the first byte of code when loaded in memory.
|
DWORD
|
BaseOfData
|
Theoretically, the RVA of the first byte of data when loaded into memory. However, the values for this field are inconsistent with different versions of the Microsoft linker. This field is not present in 64-bit executables.
|
DWORD
|
ImageBase
|
The preferred load address of this file in memory. The loader attempts to load the PE file at this address if possible (that is, if nothing else currently occupies that memory, it's aligned properly and at a legal address, and so on). If the executable loads at this address, the loader can skip the step of applying base relocations (described in Part 2 of this article). For EXEs, the default ImageBase is 0x400000. For DLLs, it's 0x10000000. The ImageBase can be set at link time with the /BASE switch, or later with the REBASE utility.
|
DWORD
|
SectionAlignment
|
The alignment of sections when loaded into memory. The alignment must be greater or equal to the file alignment field (mentioned next). The default alignment is the page size of the target CPU. For user mode executables to run under Windows 9x or Windows Me, the minimum alignment size is a page (4KB). This field can be set with the linker /ALIGN switch.
|
DWORD
|
FileAlignment
|
The alignment of sections within the PE file. For x86 executables, this value is usually either 0x200 or 0x1000. The default has changed with different versions of the Microsoft linker. This value must be a power of 2, and if the SectionAlignment is less than the CPU's page size, this field must match the SectionAlignment. The linker switch /OPT:WIN98 sets the file alignment on x86 executables to 0x1000, while /OPT:NOWIN98 sets the alignment to 0x200.
|
WORD
|
MajorOperatingSystemVersion
|
The major version number of the required operating system. With the advent of so many versions of Windows, this field has effectively become irrelevant.
|
WORD
|
MinorOperatingSystemVersion
|
The minor version number of the required OS.
|
WORD
|
MajorImageVersion
|
The major version number of this file. Unused by the system and can be 0. It can be set with the linker /VERSION switch.
|
WORD
|
MinorImageVersion
|
The minor version number of this file.
|
WORD
|
MajorSubsystemVersion
|
The major version of the operating subsystem needed for this executable. At one time, it was used to indicate that the newer Windows 95 or Windows NT 4.0 user interface was required, as opposed to older versions of the Windows NT interface. Today, because of the proliferation of the various versions of Windows, this field is effectively unused by the system and is typically set to the value 4. Set with the linker /SUBSYSTEM switch.
|
WORD
|
MinorSubsystemVersion
|
The minor version of the operating subsystem needed for this executable.
|
DWORD
|
Win32VersionValue
|
Another field that never took off. Typically set to 0.
|
DWORD
|
SizeOfImage
|
SizeOfImage contains the RVA that would be assigned to the section following the last section if it existed. This is effectively the amount of memory that the system needs to reserve when loading this file into memory. This field must be a multiple of the section alignment.
|
DWORD
|
SizeOfHeaders
|
The combined size of the MS-DOS header, PE headers, and section table. All of these items will occur before any code or data sections in the PE file. The value of this field is rounded up to a multiple of the file alignment.
|
DWORD
|
CheckSum
|
The checksum of the image. The CheckSumMappedFile API in IMAGEHLP.DLL can calculate this value. Checksums are required for kernel-mode drivers and some system DLLs. Otherwise, this field can be 0. The checksum is placed in the file when the /RELEASE linker switch is used.
|
WORD
|
Subsystem
|
An enum value indicating what subsystem (user interface type) the executable expects. This field is only important for EXEs. Important values include: IMAGE_SUBSYSTEM_NATIVE // Image doesn't require a subsystem
IMAGE_SUBSYSTEM_WINDOWS_GUI // Use the Windows GUI
IMAGE_SUBSYSTEM_WINDOWS_CUI // Run as a console mode application
// When run, the OS creates a console
// window for it, and provides stdin,
// stdout, and stderr file handles
|
WORD
|
DllCharacteristics
|
Flags indicating characteristics of this DLL. These correspond to the IMAGE_DLLCHARACTERISTICS_xxx fields #defines. Current values are:
IMAGE_DLLCHARACTERISTICS_NO_BIND
// Do not bind this image
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
// Driver uses WDM model
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
// When the terminal server loads
// an application that is not
// Terminal- Services-aware, it
// also loads a DLL that contains
// compatibility code
|
DWORD
|
SizeOfStackReserve
|
In EXE files, the maximum size the initial thread in the process can grow to. This is 1MB by default. Not all this memory is committed initially.
|
DWORD
|
SizeOfStackCommit
|
In EXE files, the amount of memory initially committed to the stack. By default, this field is 4KB.
|
DWORD
|
SizeOfHeapReserve
|
In EXE files, the initial reserved size of the default process heap. This is 1MB by default. In current versions of Windows, however, the heap can grow beyond this size without intervention by the user.
|
DWORD
|
SizeOfHeapCommit
|
In EXE files, the size of memory committed to the heap. By default, this is 4KB.
|
DWORD
|
LoaderFlags
|
This is obsolete.
|
DWORD
|
NumberOfRvaAndSizes
|
At the end of the IMAGE_NT_HEADERS structure is an array of IMAGE_DATA_DIRECTORY structures. This field contains the number of entries in the array. This field has been 16 since the earliest releases of Windows NT.
|
IMAGE_
|
DataDirectory[16]
|
An array of IMAGE_DATA_DIRECTORY structures. Each structure contains the RVA and size of some important part of the executable (for instance, imports, exports, resources).
|
Figure 6 The IMAGE_SECTION_HEADER
Size
|
Field
|
Description
|
BYTE
|
Name[8]
|
The ASCII name of the section. A section name is not guaranteed to be null-terminated. If you specify a section name longer than eight characters, the linker truncates it to eight characters in the executable. A mechanism exists for allowing longer section names in OBJ files. Section names often start with a period, but this is not a requirement. Section names with a $ in the name get special treatment from the linker. Sections with identical names prior to the $ character are merged. The characters following the $ provide an alphabetic ordering for how the merged sections appear in the final section. There's quite a bit more to the subject of sections with $ in the name and how they're combined, but the details are outside the scope of this article
|
DWORD
|
Misc.VirtualSize
|
Indicates the actual, used size of the section. This field may be larger or smaller than the SizeOfRawData field. If the VirtualSize is larger, the SizeOfRawData field is the size of the initialized data from the executable, and the remaining bytes up to the VirtualSize should be zero-padded. This field is set to 0 in OBJ files.
|
DWORD
|
VirtualAddress
|
In executables, indicates the RVA where the section begins in memory. Should be set to 0 in OBJs.
|
DWORD
|
SizeOfRawData
|
The size (in bytes) of data stored for the section in the executable or OBJ. For executables, this must be a multiple of the file alignment given in the PE header. If set to 0, the section is uninitialized data.
|
DWORD
|
PointerToRawData
|
The file offset where the data for the section begins. For executables, this value must be a multiple of the file alignment given in the PE header.
|
DWORD
|
PointerToRelocations
|
The file offset of relocations for this section. This is only used in OBJs and set to zero for executables. In OBJs, it points to an array of IMAGE_RELOCATION structures if non-zero.
|
DWORD
|
PointerToLinenumbers
|
The file offset for COFF-style line numbers for this section. Points to an array of IMAGE_LINENUMBER structures if non-zero. Only used when COFF line numbers are emitted.
|
WORD
|
NumberOfRelocations
|
The number of relocations pointed to by the PointerToRelocations field. Should be 0 in executables.
|
WORD
|
NumberOfLinenumbers
|
The number of line numbers pointed to by the NumberOfRelocations field. Only used when COFF line numbers are emitted.
|
DWORD
|
Characteristics
|
Flags OR'ed together, indicating the attributes of this section. Many of these flags can be set with the linker's /SECTION option. Common values include those listed in Figure 7.
|
Figure 7 Flags
Value
|
Description
|
IMAGE_SCN_CNT_CODE
|
The section contains code.
|
IMAGE_SCN_MEM_EXECUTE
|
The section is executable.
|
IMAGE_SCN_CNT_INITIALIZED_DATA
|
The section contains initialized data.
|
IMAGE_SCN_CNT_UNINITIALIZED_DATA
|
The section contains uninitialized data.
|
IMAGE_SCN_MEM_DISCARDABLE
|
The section can be discarded from the final executable. Used to hold information for the linker's use, including the .debug$ sections.
|
IMAGE_SCN_MEM_NOT_PAGED
|
The section is not pageable, so it should always be physically present in memory. Often used for kernel-mode drivers.
|
IMAGE_SCN_MEM_SHARED
|
The physical pages containing this section's data will be shared between all processes that have this executable loaded. Thus, every process will see the exact same values for data in this section. Useful for making global variables shared between all instances of a process. To make a section shared, use the /section:name,S linker switch.
|
IMAGE_SCN_MEM_READ
|
The section is readable. Almost always set.
|
IMAGE_SCN_MEM_WRITE
|
The section is writeable.
|
IMAGE_SCN_LNK_INFO
|
The section contains information for use by the linker. Only exists in OBJs.
|
IMAGE_SCN_LNK_REMOVE
|
The section contents will not become part of the image. This only appears in OBJ files.
|
IMAGE_SCN_LNK_COMDAT
|
The section contents is communal data (comdat). Communal data is data (or code) that can be defined in multiple OBJs. The linker will select one copy to include in the executable. Comdats are vital for support of C++ template functions and function-level linking. Comdat sections only appear in OBJ files.
|
IMAGE_SCN_ALIGN_XBYTES
|
The alignment of this section's data in the resultant executable. There are a variety of these values ( _4BYTES, _8BYTES, _16BYTES, and so on). The default, if not specified, is 16 bytes. These flags will only be set in OBJ files.
|
|