6.4. The .idata Section

All image files that import symbols, including virtually all .EXE files, have an .idata section. A typical file layout for the import information follows:

Directory Table
Null Directory Entry

DLL1 Import Lookup Table
Null

DLL2 Import Lookup Table
Null

DLL3 Import Lookup Table
Null

Hint-Name Table

Figure 3. Typical Import Section Layout

6.4.1. Import Directory Table

The import information begins with the Import Directory Table, which describes the remainder of the import information. The Import Directory Table contains address information that is used to resolve fix-up references to the entry points within a DLL image. The Import Directory Table consists of an array of Import Directory Entries, one entry for each DLL the image references. The last directory entry is empty (filled with null values), which indicates the end of the directory table.

Each Import Directory entry has the following format:

Offset Size Field Description
0 4 Import Lookup Table RVA (Characteristics) Relative virtual address of the Import Lookup Table; this table contains a name or ordinal for each import. (The name “Characteristics” is used in WINNT.H but is no longer descriptive of this field.)
4 4 Time/Date Stamp Set to zero until bound; then this field is set to the time/data stamp of the DLL.
8 4 Fowarder Chain Index of first forwarder reference.
12 4 Name RVA Address of ASCII string containing the DLL name. This address is relative to the image base.
16 4 Import Address Table RVA (Thunk Table) Relative virtual address of the Import Address Table: this table is identical in contents to the Import Lookup Table until the image is bound.

6.4.2. Import Lookup Table

An Import Lookup Table is an array of 32-bit numbers for PE32, 64-bit for PE32+. Each entry uses the bit-field format described below, in which bit 31 (63) is the most significant bit. The collection of these entries describes all imports from the image to a given DLL. The last entry is set to zero (NULL) to indicate end of the table.

Bit(s) Size Bit Field Description
31 / 63 1 Ordinal/Name Flag If bit is set, import by ordinal. Otherwise, import by name. Bit is masked as 0x80000000 for PE32, 0x8000000000000000 for PE32+.
30 – 0 / 62 – 0 31 / 63 Ordinal Number Ordinal/Name Flag is 1: import by ordinal. This field is a 31-bit (63-bit) ordinal number.
30 – 0 / 62 – 0 31 / 63 Hint/Name Table RVA Ordinal/Name Flag is 0: import by name. This field is a 31-bit (63-bit) address of a Hint/Name Table entry, relative to image base.

In a PE32 image, the lower 31 bits can be masked as 0x7FFFFFFF. In either case, the resulting number is a 32-bit integer or pointer in which the high bit is always zero (zero extension to 32 bits). Similarly for a PE32+ image, the lower 63 bits can be masked as 0x7FFFFFFFFFFFFFFF.

6.4.3. Hint/Name Table

One Hint/Name Table suffices for the entire import section. Each entry in the Hint/Name Table has the following format:

Offset Size Field Description
0 2 Hint Index into the Export Name Pointer Table. A match is attempted first with this value. If it fails, a binary search is performed on the DLL’s Export Name Pointer Table.
2 variable Name ASCII string containing name to import. This is the string that must be matched to the public name in the DLL. This string is case sensitive and terminated by a null byte.
* 0 or 1 Pad A trailing zero pad byte appears after the trailing null byte, if necessary, to align the next entry on an even boundary.

6.4.4. Import Address Table

The structure and content of the Import Address Table are identical to that of the Import Lookup Table, until the file is bound. During binding, the entries in the Import Address Table are overwritten with the 32-bit (or 64-bit for PE32+) addresses of the symbols being imported: these addresses are the actual memory addresses of the symbols themselves (although technically, they are still called “virtual addresses”). The processing of binding is typically performed by the loader.