The PE Reader panel serves for the analysis of module relationships in the profiled application. When loading a project, PE Reader analyzes the modules linked to the application at load-time, builds a tree-like structure of these modules and displays detailed information about each module.
PE Reader works both with Windows and .NET executables. It does not require the application be compiled with debug information. It simply analyzes the application code and helps you --
- Determine what modules are required for the running application.
- Determine defective files.
- Determine what functions each module imports and exports.
- Examine detailed information about the functions that are used by the application: entry points, function addresses in a module, etc.
- Examine detailed information about the modules that are used by the application: operating system version, module version, image file type, debug info existence, entry point, image base address, processor type, etc.
- Determine whether a function belongs to a module, etc.
To display the PE Reader panel, do any of the following:
Select PE Reader from the View > AQTime Profile Windows > Other menu.
Select PE Reader from the Assistant panel.
PE Reader scans all application modules recursively beginning with the main module. If a module, say a dynamic link library, imports some functions from another dynamic link library, PE Reader analyzes the latter and displays it as a child node of the “parent” DLL in the module tree. The recursion continues until all the used modules are processed.
To add a module displayed in the module tree to the current AQTime project, right-click that module and choose Add Module to Project from the context menu.
There can be several versions of the module that can be loaded by the parent executable. The version to be loaded is specified by the manifest of that parent executable. Since AQTime does not “know” which module will be loaded, it displays the version that best matches the specified version.
Below is a description of possible module’s icons:
|Defective or unavailable module. PE Reader uses this icon if the module cannot be executed or if it is absent.|
|Note:||A combination of marks is possible. For instance, the icon means the module is delay-loaded and unavailable.|
To update the module tree, select Reload Modules Tree from PE Reader toolbar or from the context menu. The refresh is necessary, for example, if initially an imported module was absent, but then it was created (that is, it became available).
Information about each module is shown on the following tabbed pages:
Routine Information - Holds tables of imported and exported functions.
PE Information - Displays information about headers and sections of the module selected in the module tree.
Manifest - Displays information from the manifest that describes the module selected in the module tree.
Modules - Displays a list of modules that are linked to the profiled executable at load-time.
The rest of this topic provides detailed information on the tabbed pages.
Routine Information Page
The Routine Information page of the PE Reader panel displays two lists of functions: the lower list, Exported Routines, holds functions exported by the module currently selected in the module tree; the upper list, Imported Routines, holds functions that are called by the "parent" module from the selected module.
|Entry Point||Routine’s address in the module. For imported routines, this address includes the module’s base address that is specified in the module’s header. For exported routines, this address does not include the module’s base address.|
|Hint||Hint value of a routine. This value is a function index in the array of functions exported by a module. The system uses this value for rapid search of a function in the module.|
|Ordinal||Holds the routine’s ordinal number. The Ordinal column of the Imported Routines table may hold the "N/A" value that means the routine is imported by name.|
|Offset to Address||This column is in the Imported Routines list only. It holds the offset of the routine’s address in the import address table of the "parent" module. The import address table (IAT) is used to call a routine kept in another module. When an executable (EXE or DLL) calls a routine stored in another module, control does not go directly to the desired routine. Instead, it goes to an instruction like
|Routine||Name of the routine. The Routine name of the Imported Routines table may hold the "N/A" value that means that the function is imported by ordinal number. The routine name may be decorated or undecorated according to the state of the Undecorate routine names toolbar item.|
Both Exported Routines and Imported Routines tables can be arranged at your desire: you can change the column sizes, remove columns from or add them to the tables, sort records on any column, etc. See Arranging Columns, Lines and Panels. You can also search for information in the tables using the incremental search mechanism.
To view the source code of a routine shown in the Exported or Imported Routines list, double-click this routine and then switch to the Editor panel. Note that you will be able to view the routine’s source code only if the module holding the routine matches the following requirements:
It must be included in the current AQTime project (if the module does not belong to the project, AQTime will ask you to add it there).
It must be compiled with debug information (see How AQTime Profilers Use Metadata and Debug Information).
To view the binary code of a routine, double-click this routine in the Exported Routines or Imported Routines list and switch to the Disassembler panel. Note that you will be able to view the binary code only if the module holding the routine is included in the current AQTime project. If the module was compiled without debug information, the panel may show more assembler instructions than the routine’s binary code actually contains. This happens because without debug info it is impossible to determine the exact size of the routine’s binary code, so AQTime has to resort to its own algorithm, which is less accurate than debug info (the algorithm may report that the routine contains more binary instructions than it actually has).
PE Information Page
This page displays detailed information about the headers and sections of the module that is currently selected in the modules tree.
The header of a module consists of several parts (or several headers). They hold detailed information about the module. All the modules have the following headers:
|DOS Header||The header that existed in all DOS executable applications plus the field that indicates the offset of PE Header.|
|PE Header||Holds information about the processor type, the number of application sections, and the date of file creation and file attributes.|
|Optional Header||Holds specific information used by the operating system, for example, the version number of the required operating system, control sum, image base address, etc.|
For more information about the structure and contents of PE Headers, see MSDN Library (online version is available at http://msdn.microsoft.com).
Sections are "segments" of code or data within an executable. In general, a file can include any section with an arbitrary name and purpose, but some sections, for example, debug or rsrc, have specific meaning. For detailed information, see MSDN Library.
For each section, PE Reader displays the following information:
- Virtual address of a section in the process address space.
- Relative size of the section body.
- The offset of the section body in a file.
- Section attributes.
The Manifest page displays information stored in the manifest of the selected module. A manifest describes and uniquely identifies its module as well as provides information on the dependence of the module on other assemblies. For each dependent assembly referenced by the module, for which the manifest was created, this information contains the assembly name, version, type, and so on. Manifest information allows the module to bind to the appropriate version of a helper module at run time if there are several versions of this helper module.
With the Manifest tabbed page, you can easily view the contents of the selected module’s manifest (if any) and learn the exact versions of the modules on which the selected module depends.
|Note:||The Manifest page displays information only if the manifest is embedded as a resource into the module file. If the selected module does not contain an embedded manifest (if the manifest was created as a stand-alone file or was not generated at all), the Manifest page is empty.|
If the manifest information is successfully obtained from the selected module, the Manifest resource ID box of the Manifest tabbed page displays the resource identifier used for searching for the manifest information in other resources included in the module.
Manifest information is stored in the XML format. For a complete description of the XML schema used by manifests, see the MSDN Library (its online version is available at http://msdn.microsoft.com). By default, the Manifest page displays the XML data of the module manifest in a tree-like structure in a table:
The table has the following columns:
|Name||Contains the hierarchy of the manifest’s XML elements and their attributes. Each element in the tree of XML elements shown in this column has an appropriate icon:
|Value||Contains the values of appropriate XML elements and attributes listed in the Name column.|
Furthermore, if you want to view the contents of a manifest as text, you can right-click the table in the Manifest page and select View as Text from the context menu. The page will display the contents of the manifest as text by using the XML markup. To return to the tree-like view, right-click the text on the page and select View as Tree from the context menu.
The Modules page displays the modules that are linked to the profiled executable at load-time (that is, the module’s functions are encapsulated by the executable). Use this page to quickly view a list of modules necessary for application execution. For each module, the following information is available:
|Module||Name of the module.|
|File Size||Size of the module in bytes.|
|File Version and Product Version||These fields are added by your compiler. They specify the full version numbers of the module and of the entire application (product). These versions include the build number.|
|Image Version||The version of the executable file.|
|Link Time Stamp||Date and time of file creation. Do not confuse them with the date and time file attributes. Link Time Stamp is the date and time of file creation that are specified in the executable header. These values are written there by the linker.|
|Machine||The machine (CPU) type. The module can be run on the specified machine only or on a system that emulates it.|
|OS Version||The version of the required operating system.|
|Path||Path to the module.|
|Preferred Address||The preferred address for loading the module in memory.|
|Subsystem||The subsystem, which is required to run the module: Windows GUI, console subsystem, Posix character subsystem, device driver, etc.|
|Subsystem Version||The version of the subsystem is required to run the module.|
The Modules table can be arranged at your desire: you can change the column sizes, sort records on any column, etc. For more information on this, see Arranging Columns, Lines and Panels. You can also search for information in the table using the incremental search feature. To select a module in the module tree and view its parent and child modules, right-click the desired module and select Show Imported Modules from the context menu.
The PE Reader panel may work slowly after installation of certain Windows 10 updates.