|
|
![]() |
|
||
|
|
|||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||
| Visual Basic System Services MapDebugInformation: Obtain Debugging Info for an Image |
||
| Posted: | Saturday January 15, 2000 | |
| Updated: | Monday December 26, 2011 | |
| Applies to: | VB4-32, VB5, VB6 | |
| Developed with: | VB6, Windows NT4 | |
| OS restrictions: | Requires Imagehlp.dll | |
| Author: | Dev Ashish, VBnet - Randy Birch | |
| Prerequisites |
| Imagehlp.dll. Available as a redistributable for Windows 95. |
|
|
Those
who've used Microsoft's Dependency Walker (depends.exe) are familiar with the listing of exported functions / methods from DLL's. This code,
originally authored by Dev Ashish for use under MS Access, has been graciously
provided to VBnet by Dev. Using the MapDebugInformation API this code allows you to select any DLL (or any other file for that
matter) in order to see the names of any methods that might be exported by the file. Note that not all files export methods. And in
Windows parlance an executable file is an 'image' ... and an executable file can be either an exe or a dll
The MSDN offers the following explanation of imagehlp's MapDebugInformation API in a 1997 Under the Hood article by Matt Pietrek. Slightly paraphrased here to make sense taken out of context (from the entire article), it covers significantly more details than this demo shows, is included for its completeness (and to spark ideas). MapDebugInformation maps the executable file into memory, then figures out what the best type of symbol information is as well as some basic information about that symbol table. 'Best' means best - it turns out that an executable can be built with more than one type of debug information. For example, an executable can have both CodeView (PDB) information and a COFF symbol table. IMAGEHLP knows how to read both formats, as well as a few others, and knows which one is optimal for your executable. Once finished with the file, MapDebugInformation needs to be cleaned up by calling UnmapDebugInformation. Because in C the symbols for an executable may be in a file other than the executable itself (a debug file), the MapDebugInformation API can take a parameter specifying the symbol search path, if such a file was available. Besides mapping and loading the executable and its symbols (if present), the MapDebugInformation API returns a pointer to an IMAGE_DEBUG_INFORMATION structure. This structure contains many more fields than a LOADED_IMAGE structure (used with MapandLood), although nearly every field in the LOADED_IMAGE structure can be found in the IMAGE_DEBUG_INFORMATION structure. For example, the MappedBase field contains the address where the executable was mapped, and is the same as the MappedAddress field in a LOADED_IMAGE structure. Similarly, the Sections field is a pointer to the executable’s section table, and so forth. More useful information found in the IMAGE_DEBUG_INFORMATION structure includes the preferred load address (the ImageBase field), and the size of the executable in memory (the SizeOfImage field). There are also pointers to the table of names for the exported functions, as well as the executable’s time/date stamp DWORD. The meaning of some fields in the IMAGE_DEBUG_INFORMATION structure isn’t so obvious, like the pointers to Function and FPO tables. The Function table is data used by the structured exception handling code on the Alpha and MIPS platforms (it’s not encountered with Intel-based executables). FPO information is seen only on the Intel platform; it helps debuggers walk the call stack in the absence of standard EBP register stack frames. Finally, the IMAGE_DEBUG_INFORMATION has a variety of fields that indicate if CodeView and COFF information are present, and if so, where. There’s even a pointer to the debug directory. This is the data structure in the PE file that tells you what types of debug information are present and where. The MapDebugInformation API does a good job of extracting this information and presenting it in the IMAGE_DEBUG_INFORMATION structure. Still, if you’re so inclined, you can go straight to the same raw data that IMAGEHLP uses to generate the IMAGE_DEBUG_INFORMATION structure. Remember though, the whole advantage of using IMAGEHLP is to avoid such low-level grunginess. |
| BAS Module Code |
| None. |
|
|
| Form Code |
|
|
| To a form, add a command button, label, listbox and common dialog control. Use the default names and add the following code: |
|
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const INVALID_HANDLE_VALUE = -1
Private Const OPEN_EXISTING = 3
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Const MAX_PATH As Long = 260
Private Type IMAGE_DEBUG_INFORMATION
List As Long
Size As Long
MappedBase As Long
Machine As Long
Characteristics As Long
CheckSum As Long
ImageBase As Long
SizeOfImage As Long
NumberOfSections As Long
Sections As Long 'pointer to a IMAGE_SECTION_HEADER type
ExportedNamesSize As Long
ExportedNames As Long
NumberOfFunctionTableEntries As Long
FunctionTableEntries As Long 'pointer to a IMAGE_FUNCTION_ENTRY type
LowestFunctionStartingAddress As Long
HighestFunctionEndingAddress As Long
NumberOfFpoTableEntries As Long
FpoTableEntries As Long
SizeOfCoffSymbols As Long
CoffSymbols As Long 'pointer to the COFF symbol table
SizeOfCodeViewSymbols As Long
CodeViewSymbols As Long
ImageFilePath As Long
ImageFileName As Long
DebugFilePath As Long
TimeDateStamp As Long
RomImage As Long
DebugDirectory As Long 'pointer to a IMAGE_DEBUG_DIRECTORY type
NumberOfDebugDirectories As Long
OriginalFunctionTableBaseAddress As Long
Reserved0 As Long
Reserved1 As Long
Reserved2 As Long
End Type
Private Declare Function MapDebugInformation Lib "ImageHlp.dll" _
(ByVal FileHandle As Long, _
ByVal FileName As String, _
ByVal SymbolPath As String, _
ByVal ImageBase As Long) _
As Long
Private Declare Function UnmapDebugInformation Lib "imagehlp.dll" _
(ByVal DebugInfo As Long) As Long
Private Declare Function CreateFile Lib "kernel32" _
Alias "CreateFileA" _
(ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, _
ByVal lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) _
As Long
Private Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" _
Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)
Private Function GetFileImageInformation(sDLLName As String) As String
On Local Error GoTo fileExport_error
Dim IMGDBG As IMAGE_DEBUG_INFORMATION
Dim hFile As Long
Dim ptrDbg As Long
Dim strOut As String
Const ERR_GENERIC = vbObjectError + 5555
'obtain a handle to the specified file
hFile = CreateFile(sDLLName, GENERIC_READ, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, _
0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0&)
'if the handle is invalid, raise an
'error to properly clean up and exit
If hFile = INVALID_HANDLE_VALUE Then
Err.Raise ERR_GENERIC
End If
'obtain a pointer to the image debug
'info in the passed file
ptrDbg = MapDebugInformation(hFile, sDLLName, vbNullString, 0&)
'if the handle is invalid, raise an
'error to properly clean up and exit
If ptrDbg = 0 Then
Err.Raise ERR_GENERIC
End If
'fill the UDT with the image debug info
Call CopyMemory(IMGDBG, ByVal ptrDbg, Len(IMGDBG))
'pad a string sufficiently large enough to
'receive the string of exported functions
'and copy the functions into the string.
With IMGDBG
strOut = String$(.ExportedNamesSize, vbNullChar)
Call CopyMemory(ByVal strOut, ByVal .ExportedNames, .ExportedNamesSize)
End With
'if the calls above are successful, and the
'file has exported methods, return the string
'consisting of a series of null-terminated
'strings naming all the functions exported
'from the image
GetFileImageInformation = strOut
fileExport_exit:
Call UnmapDebugInformation(ptrDbg)
Call CloseHandle(hFile)
On Error GoTo 0
Exit Function
fileExport_error:
GetFileImageInformation = vbNullString
Resume fileExport_exit
End Function
Private Sub Command1_Click()
Dim sExports As String
Dim tmp As String
On Local Error GoTo enumdata_error
'set up the common dialog
With CommonDialog1
.Flags = cdlOFNExplorer Or cdlOFNPathMustExist
.CancelError = True
.Filter = "DLL's (*.dll)|*.dll|OCX's (*.ocx)|*.ocx|All Files (*.*)|*.*"
'get the file
.ShowOpen
'double check
If Len(.FileName) > 0 Then
'set up the form
List1.Clear
Label1.Caption = LCase$(.FileName)
'retrieve the exported functions
sExports = GetFileImageInformation(.FileName)
'double check
If Len(sExports) > 0 Then
'remove an item from the string
'returned and add to the list
Do While Len(sExports) > 0
List1.AddItem StripNulls(sExports)
Loop
End If 'If Len(sExports)
End If 'If .FileName
End With 'With CDlg1
enumdata_exit:
Exit Sub
enumdata_error:
Label1.Caption = Err.Description
Resume enumdata_exit
End Sub
Private Function StripNulls(startstr As String) As String
Dim pos As Long
pos = InStr(startstr, Chr$(0))
If pos Then
StripNulls = Mid$(startstr, 1, pos - 1)
startstr = Mid$(startstr, pos + 1, Len(startstr))
End If
End Function |
| Comments |
| Try experimenting with the other attributes. Of particular interest might be the Checksum member of the UDT. |
|
|
|
|
|
|||||
|
|||||
|
|
|||||
|
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |
![]() |