Examining Libraries with EXEHDR

Both program files and dynamic link library files are in the New Executable format. You can get some sense of the workings of dynamic linking by running the EXEHDR program (included with Microsoft C 6) with the -v (verbose) parameter on the various files included with Windows and seeing what type of information the files contain. EXEHDR divides its output into five main sections, in this order:

The old MS-DOS .EXE header information

The New Executable format header information

A list of the code and data segments in the module

The exported functions of the module

Relocation information for each segment

Some of this information won't be present for resource-only library modules (such as the .FON files). You'll notice that the first line of the second section begins with either ”Module,“ indicating a program module, or ”Library,“ indicating a dynamic link library.

If you run EXEHDR on KERNEL.EXE, USER.EXE, or GDI.EXE, you'll find that many of the names of the exported functions (the fourth section of the output) are familiar. These are the functions that the library makes available for other modules to call. Each exported function has an ”ordinal number“ associated with it. This is simply a positive number in the ”ord“ column of the EXEHDR output.

Both program modules and library modules can call functions that are exported from other library modules. To the module that makes the call, the function is said to be ”imported.“ These imported functions show up in the last section of the EXEHDR display as relocation items, generally in the form of the library module name followed by a period and the ordinal number of the function.

When Windows loads a program into memory for execution, it must resolve the calls that the program makes to imported functions. If the library module containing these functions has not yet been loaded into memory, Windows loads at least the data segment and one code segment into memory and calls a short initialization routine in the library module. Windows also creates ”reload thunks“ (a topic discussed in Chapter 7) for the exported functions in the library. The calls in the program to external functions can then be resolved by inserting the addresses of the reload thunks in the code segment of the program.

The second section of the EXEHDR output points up some differences between programs and libraries. Windows programs have a line that reads:

Data: NOSHARED

This means that new data segments are created for each instance of the program. Because a single instance of a Windows library is shared by all programs that need it, this line is different for Windows libraries. It can be either:

Data: SHARED

or:

Data: NONE

depending on whether the library has one data segment or none.

A Windows program must have at least one data segment (called the automatic data segment), because this data segment contains the program's stack. In the EXEHDR output of a program file, you'll see an indication of the stack size (”Extra Stack Allocation“). However, a library module doesn't have its own stack, and thus EXEHDR won't show this line. A dynamic link library always uses the stack of the program that calls the functions in the library. The absence of a stack for the library module has some significant implications that I'll cover later in this chapter.

Because each Windows program has its own stack, Windows must switch between stacks when switching from one program to another. A stack's presence in a program identifies the program as a distinct process that can receive messages from Windows. A library module is not a process and does not receive messages. When a program calls a function in a library module, no task switch takes place. To Windows, the program making the call to the library is still running even though code in the library is being executed.