I was using this solution to retrieve method names from an unmanaged C++ library, the solution uses SymEnumerateSymbols64
function but MSDN says here that applications must use SymEnumSymbols
instead, so I've found this other solution, but when I've tried to adapt and translate the C# code into VB.NET code the SYMBOL_INFO.Name
property only contains the first letter of the method name.
Where is the problem and how I can fix it?.
I think that the problem could be the declaration inside the structure:
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=1024I)>
Public Name As String
...But if I remove the marshalling, the application just closes itself without any kind of exception.
This is the full code:
<DllImport("dbghelp.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function SymInitialize(
ByVal hProcess As IntPtr,
ByVal UserSearchPath As String,
<MarshalAs(UnmanagedType.Bool)> ByVal fInvadeProcess As Boolean
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("dbghelp.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function SymCleanup(
ByVal hProcess As IntPtr
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("dbghelp.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function SymLoadModuleEx(
ByVal hProcess As IntPtr,
ByVal hFile As IntPtr,
ByVal ImageName As String,
ByVal ModuleName As String,
ByVal BaseOfDll As Long,
ByVal DllSize As Integer,
ByVal Data As IntPtr,
ByVal Flags As SymLoadModuleFlags
) As ULong
End Function
<DllImport("dbghelp.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function SymEnumSymbols(
ByVal hProcess As IntPtr,
ByVal BaseOfDll As ULong,
ByVal Mask As String,
ByVal EnumSymbolsCallback As SymEnumSymbolsProc,
ByVal UserContext As IntPtr
) As Boolean ' As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Public Delegate Function SymEnumSymbolsProc(
ByRef pSymInfo As SYMBOL_INFO,
ByVal SymbolSize As UInteger,
ByVal UserContext As IntPtr
) As Boolean
<StructLayout(LayoutKind.Sequential)>
Public Structure SYMBOL_INFO
Public SizeOfStruct As UInteger
Public TypeIndex As UInteger
Public Reserved1 As ULong
Public Reserved2 As ULong
Public Reserved3 As UInteger
Public Size As UInteger
Public ModBase As ULong
Public Flags As SymFlag
Public Value As ULong
Public Address As ULong
Public Register As UInteger
Public Scope As UInteger
Public Tag As SymTagEnum
Public NameLen As Integer
Public MaxNameLen As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=1024)>
Public Name As String
End Structure
<FlagsAttribute>
Public Enum SymFlag As UInteger
VALUEPRESENT = &H1
REGISTER = &H8
REGREL = &H10
FRAMEREL = &H20
PARAMETER = &H40
LOCAL = &H80
CONSTANT = &H100
EXPORT = &H200
FORWARDER = &H400
[FUNCTION] = &H800
VIRTUAL = &H1000
THUNK = &H2000
TLSREL = &H4000
End Enum
<FlagsAttribute>
Public Enum SymTagEnum As UInteger
Null
Exe
Compiland
CompilandDetails
CompilandEnv
[Function]
Block
Data
Annotation
Label
PublicSymbol
UDT
[Enum]
FunctionType
PointerType
ArrayType
BaseType
Typedef
BaseClass
[Friend]
FunctionArgType
FuncDebugStart
FuncDebugEnd
UsingNamespace
VTableShape
VTable
[Custom]
Thunk
CustomType
ManagedType
Dimension
End Enum
<Description("Enum used as 'Flags' parameter of 'SymLoadModuleEx' function")>
<FlagsAttribute()>
Public Enum SymLoadModuleFlags As Integer
Module_And_Symbols = &H0I
Only_Module = &H4I
Virtual = &H1I
End Enum
Public Shared Function EnumSyms(ByRef pSymInfo As SYMBOL_INFO,
ByVal SymbolSize As UInteger,
ByVal UserContext As IntPtr) As Boolean
' Debug.WriteLine(pSymInfo.Name)
Debug.WriteLine(pSymInfo.Address & " " & SymbolSize & " " & pSymInfo.Name)
Return True
End Function
And this is a real example usage:
Private Sub Test() Handles MyBase.Shown
Dim hCurrentProcess As IntPtr = Process.GetCurrentProcess().Handle
Dim baseOfDll As ULong
Dim status As Boolean
' Initialize sym.
' Please read the remarks on MSDN for the hProcess
' parameter.
status = SymInitialize(hCurrentProcess, Nothing, False)
If status = False Then
MsgBox("Failed to initialize sym.")
Exit Sub
End If
' Load dll.
baseOfDll = SymLoadModuleEx(hCurrentProcess,
IntPtr.Zero,
"C:\Users\Administrador\Desktop\x64.dll",
Nothing,
0,
0,
IntPtr.Zero,
SymLoadModuleFlags.Module_And_Symbols)
If baseOfDll = 0 Then
MsgBox("Failed to load module.")
SymCleanup(hCurrentProcess)
Exit Sub
End If
' Enumerate symbols. For every symbol the
' callback method EnumSyms is called.
If Not SymEnumSymbols(hCurrentProcess,
baseOfDll,
"*",
AddressOf EnumSyms,
IntPtr.Zero
) Then
MsgBox("Failed to enum symbols.")
End If
' Cleanup.
SymCleanup(hCurrentProcess)
End Sub