your feedback send to: debugger@fyzor.com     
C++ debugger
Navigator
Main
Screenshots
Docs
Download
Sources
Plugins
API
History
Legend
Contacts
Links
Mail
Search
Search Site With Google
Надежный хостинг по доступным ценам!

Plug-ins

You can attach your own DLL-modules (plug-ins) to the debugger. This could be useful in two cases:

  1. When you want to extend functionality of the debugger to meet your specific needs.

  2. When you have a compiler that generates executable modules in one of those formats that are not supported by the current format loaders of the debugger. So you may decide to read appropriate documentation and write it by yourself.

Attachment

Plug-ins are attached to the debugger through four exported functions:
PLUGIN_Init
necessarily
It is called when the module is just loaded. Besides, presence of this function serves as a mark by which debugger distinguishes a general DLL module from its own plug-ins.
PLUGIN_Shutdown It is called just before the module is unloaded from the process memory of debugger. In this function you must free any resources that were allocated previously.
PLUGIN_Prop Called from the plug-ins control dialog in the debugger. Could be used to change some internal options of the plug-in. All these options we recommend you to save into the registry.
PLUGIN_LoadDebugInfoUsed to load symbolic debug information from each module being loaded into debugged process. The function must return TRUE, if the symbols have been successfully loaded.

In your plug-ins you can call any service functions that are declared in file zdapi.h. Copy of this file you can find in the plug-in control dialog box of the debugger. More details about these service functions read here.

Order of plug-ins loading

All plug-ins must reside in one directory, that is sepcified in plug-in control dialog opened by pressing ALT+F5 key.

The following algorithm is used to load plug-ins after the debugger is loaded itself: the debugger opens plug-ins directory and sequentially loads each*.dll module found there. If such a DLL exports PLUGIN_Init function, then it assumed to be a plug-in for the debugger and so left in memory. Otherwise it is unloaded and no function from it called at all.

There is one case when plug-ins can be reloaded - it happens when the path of plug-ins is changed. In this case all plug-ins are unloaded, and then loaded again from the new path.

Using plug-ins

An example of working plug-in module with its source file in C you can download here. But here we'll describe shortly only the basic principle. It is very simple: the first function that is called in your module is PLUGIN_Init (), which can be used to initialize your global variables. There you also can setup plug-in's title that debugger uses as the comment text in plug-in control dialog box. This string can include a short description of formats supported by the plug-in or just module's general purpose.

Farther, when debugger detects a new DLL module in debugged process, it temporary maps this module into its own memory space and gives a chance to each plug-in to parse file's contents and extract debugging information. Debugger calls the function PLUGIN_LoadDebugInfofor for each plug-in until one of them returns TRUE that signals that symbols have been loaded normally. If all of such functions return FALSE, then the debugging format is assumed to be unknown and becomes inaccessible.

The function that is called by debugger to load symbols is declared as following:

BOOL PLUGIN_LoadDebugInfo(BYTE*FileRoot, BYTE*DebugRoot);

When called, parameter #FileRoot points to the memory where the module's file is mapped.

Pay special attention, that this pointer doesn't point to the address in the debuggee's process, but instead to the memory where a copy of the executable module is mapped. Being an executable part of the program, the module itself always resides in the context of debugged program, and its sections usually shifted upper relative to their positions in file. By these two reasons it is more convenient to extract symbols from a copy of the module mapped into debugger's memory space, and not from module itself.

Parameter #DebugRoot points to the address where expected to be a debug section. This parameter is passed only for convenience, and can be easily calculated from the first parameter and knowing standard format of executable header which comes here.

Executable file format

If you want to write a symbol loader for some unknown debug information, then, possibly, you will find useful the following short description of the executable format itself. This can be in rare cases when by some reasons debug information is kept in unusual place of an executable file. In most other cases you can safely use #DebugRoot that points to the debug section.

In the following table we describe the structure of the standard executable *.exe or *.dll file. All potentially useful fields are in bold font. Other detailed information can be taken from MSDN, and all structures declared in winnt.h.

Data typeNameUseful content
IMAGE_DOS_HEADER DosHeader Points to NT header
a space of variable length...
DWORD Signature 'PE'
IMAGE_FILE_HEADER FileHeader Number of sections and module characteristics
IMAGE_OPTIONAL_HEADER32 OptionalHeader Entry point, image base, sizes, version and others
IMAGE_DATA_DIRECTORY Export Exported symbols
IMAGE_DATA_DIRECTORY Import Imported symbols
IMAGE_DATA_DIRECTORY Resource Dialogs, images and so on
IMAGE_DATA_DIRECTORY Exception Exception Directory
IMAGE_DATA_DIRECTORY Security Security Directory
IMAGE_DATA_DIRECTORY BaseReloc Base Relocation Table
IMAGE_DATA_DIRECTORY Debug Pointer to debug symbols
IMAGE_DATA_DIRECTORY Copyright/Architecture Architecture Specific Data
IMAGE_DATA_DIRECTORY GlobalPtr RVA of GP
IMAGE_DATA_DIRECTORY TLS TLS Directory
IMAGE_DATA_DIRECTORY LoadConfig Load Configuration Directory
IMAGE_DATA_DIRECTORY BoundImport Bound Import Directory in headers
IMAGE_DATA_DIRECTORY IAT Import Address Table
IMAGE_DATA_DIRECTORY DelayImport Delay Load Import Descriptors
IMAGE_DATA_DIRECTORY COM_Descriptor COM Runtime descriptor
a space of variable length...
IMAGE_SECTION_HEADER Sections [] Sections of different data, including section of code (usually one). Each section has the name of no more than eight characters length

Note: all sections of executable module usually shifted down to the beginning of the file. This is done by removing page-aligned spaces between them. But when the module is loaded by the system, these sections are aligned on page boundaries.

By this reason some members in the header have VA (virtual address) prefix, meaning that the value is referencing the address in the process's (virtual) memory and not in file's (physical) memory. To calculate the physical address for such a value we need to subtract #delta from it:

delta = section->VirtualAddress - section->PointerToRawData

Where #section - is the section where the VirtualAddress resides. To find this section write a special function FindSectionByVA, that scans all sections comparing their ranges with desired address.

Все исходные файлы и рабочий DLL-модуль вы можете скачать из этого архива. Для того, чтобы его увидел и загрузил отладчик, файл sample.dll следует переместить в текущую директорию плагинов.

All your plug-in modules must be placed into plug-ins directory, otherwise debugger will not find them.

Project and site author: Sapunov Vladimir
(c) Copyright 2005-2008