mirror of
https://github.com/reactos/reactos.git
synced 2025-05-28 13:38:19 +00:00
PE symbol dumper. It's not finished, functions don't work and the type output doesn't always look 100% correct. But it does it's job. You need dbghelp.dll and symsrv.dll from windbg.
svn path=/trunk/; revision=35346
This commit is contained in:
parent
39775880e5
commit
e9f18efcfc
3 changed files with 998 additions and 0 deletions
|
@ -20,6 +20,10 @@
|
|||
<xi:include href="syscalldump/syscalldump.rbuild" />
|
||||
</directory>
|
||||
|
||||
<directory name="symdump">
|
||||
<xi:include href="symdump/symdump.rbuild" />
|
||||
</directory>
|
||||
|
||||
<directory name="vgafontedit">
|
||||
<xi:include href="vgafontedit/vgafontedit.rbuild" />
|
||||
</directory>
|
||||
|
|
985
rosapps/applications/devutils/symdump/symdump.c
Normal file
985
rosapps/applications/devutils/symdump/symdump.c
Normal file
|
@ -0,0 +1,985 @@
|
|||
/*
|
||||
* PE symbol dumper
|
||||
*
|
||||
* symdump.c
|
||||
*
|
||||
* Copyright (c) 2008 Timo Kreuzer <timo <dot> kreuzer <at> reactos <dot> org>
|
||||
*
|
||||
* This program is released under the terms of the GNU GPL.
|
||||
*
|
||||
* TODO:
|
||||
* - fix GDILoObjType
|
||||
* - fix UDTKind1
|
||||
* - include the correct headers for some stuff
|
||||
* - fix unions like LARGE_INTEGER
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#define _WINVER 0x501
|
||||
#include <windows.h>
|
||||
#include <shlwapi.h>
|
||||
#include <dbghelp.h>
|
||||
|
||||
HANDLE hCurrentProcess;
|
||||
BOOL g_bShowPos = 0;
|
||||
|
||||
#define MAX_SYMBOL_NAME 1024
|
||||
|
||||
#define CV_CALL_NEAR_C 0x00
|
||||
#define CV_CALL_FAR_C 0x01
|
||||
#define CV_CALL_NEAR_PASCAL 0x02
|
||||
#define CV_CALL_FAR_PASCAL 0x03
|
||||
#define CV_CALL_NEAR_FAST 0x04
|
||||
#define CV_CALL_FAR_FAST 0x05
|
||||
#define CV_CALL_SKIPPED 0x06
|
||||
#define CV_CALL_NEAR_STD 0x07
|
||||
#define CV_CALL_FAR_STD 0x08
|
||||
#define CV_CALL_NEAR_SYS 0x09
|
||||
#define CV_CALL_FAR_SYS 0x0a
|
||||
#define CV_CALL_THISCALL 0x0b
|
||||
#define CV_CALL_MIPSCALL 0x0c
|
||||
#define CV_CALL_GENERIC 0x0d
|
||||
#define CV_CALL_ALPHACALL 0x0e
|
||||
#define CV_CALL_PPCCALL 0x0f
|
||||
#define CV_CALL_SHCALL 0x10
|
||||
#define CV_CALL_ARMCALL 0x11
|
||||
#define CV_CALL_AM33CALL 0x12
|
||||
#define CV_CALL_TRICALL 0x13
|
||||
#define CV_CALL_SH5CALL 0x14
|
||||
#define CV_CALL_M32RCALL 0x15
|
||||
|
||||
enum SymTagEnum
|
||||
{
|
||||
SymTagNull,
|
||||
SymTagExe,
|
||||
SymTagCompiland,
|
||||
SymTagCompilandDetails,
|
||||
SymTagCompilandEnv,
|
||||
SymTagFunction,
|
||||
SymTagBlock,
|
||||
SymTagData,
|
||||
SymTagAnnotation,
|
||||
SymTagLabel,
|
||||
SymTagPublicSymbol,
|
||||
SymTagUDT,
|
||||
SymTagEnum,
|
||||
SymTagFunctionType,
|
||||
SymTagPointerType,
|
||||
SymTagArrayType,
|
||||
SymTagBaseType,
|
||||
SymTagTypedef,
|
||||
SymTagBaseClass,
|
||||
SymTagFriend,
|
||||
SymTagFunctionArgType,
|
||||
SymTagFuncDebugStart,
|
||||
SymTagFuncDebugEnd,
|
||||
SymTagUsingNamespace,
|
||||
SymTagVTableShape,
|
||||
SymTagVTable,
|
||||
SymTagCustom,
|
||||
SymTagThunk,
|
||||
SymTagCustomType,
|
||||
SymTagManagedType,
|
||||
SymTagDimension,
|
||||
SymTagMax
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
UDTKind_Struct = 0,
|
||||
UDTKind_Class = 1, /* ? */
|
||||
UDTKind_Union = 2,
|
||||
};
|
||||
|
||||
enum BasicType
|
||||
{
|
||||
btNoType = 0,
|
||||
btVoid = 1,
|
||||
btChar = 2,
|
||||
btWChar = 3,
|
||||
btInt = 6,
|
||||
btUInt = 7,
|
||||
btFloat = 8,
|
||||
btBCD = 9,
|
||||
btBool = 10,
|
||||
btLong = 13,
|
||||
btULong = 14,
|
||||
btCurrency = 25,
|
||||
btDate = 26,
|
||||
btVariant = 27,
|
||||
btComplex = 28,
|
||||
btBit = 29,
|
||||
btBSTR = 30,
|
||||
btHresult = 31
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HANDLE hProcess;
|
||||
DWORD64 dwModuleBase;
|
||||
LPSTR pszSymbolName;
|
||||
BOOL bType;
|
||||
} ENUMINFO, *PENUMINFO;
|
||||
|
||||
VOID DumpType(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers);
|
||||
|
||||
CHAR *SymTagString[] =
|
||||
{
|
||||
"SymTagNull",
|
||||
"SymTagExe",
|
||||
"SymTagCompiland",
|
||||
"SymTagCompilandDetails",
|
||||
"SymTagCompilandEnv",
|
||||
"SymTagFunction",
|
||||
"SymTagBlock",
|
||||
"SymTagData",
|
||||
"SymTagAnnotation",
|
||||
"SymTagLabel",
|
||||
"SymTagPublicSymbol",
|
||||
"SymTagUDT",
|
||||
"SymTagEnum",
|
||||
"SymTagFunctionType",
|
||||
"SymTagPointerType",
|
||||
"SymTagArrayType",
|
||||
"SymTagBaseType",
|
||||
"SymTagTypedef",
|
||||
"SymTagBaseClass",
|
||||
"SymTagFriend",
|
||||
"SymTagFunctionArgType",
|
||||
"SymTagFuncDebugStart",
|
||||
"SymTagFuncDebugEnd",
|
||||
"SymTagUsingNamespace",
|
||||
"SymTagVTableShape",
|
||||
"SymTagVTable",
|
||||
"SymTagCustom",
|
||||
"SymTagThunk",
|
||||
"SymTagCustomType",
|
||||
"SymTagManagedType",
|
||||
"SymTagDimension",
|
||||
"SymTagMax"
|
||||
};
|
||||
|
||||
void
|
||||
IndentPrint(INT ind)
|
||||
{
|
||||
INT i;
|
||||
for (i = 0; i < ind; i++)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
#define printfi \
|
||||
IndentPrint(indent); printf
|
||||
|
||||
VOID
|
||||
PrintUsage()
|
||||
{
|
||||
printf("Syntax:\n\n");
|
||||
printf("dumpsym <file> [-sp=<symbolpath>] [-p] [<symname>]\n\n");
|
||||
printf("<file> The PE file you want to dump the symbols of\n");
|
||||
printf("-sp=<symbolpath> Path to your symbol files.\n");
|
||||
printf(" Default is MS symbol server.\n");
|
||||
printf("-p Enable struct positions.\n");
|
||||
printf("<symname> A name of a Symbol, you want to dump\n");
|
||||
printf(" Default is all symbols.\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
BOOL InitDbgHelp(HANDLE hProcess, LPSTR pszSymbolPath)
|
||||
{
|
||||
if (!SymInitialize(hProcess, 0, FALSE))
|
||||
return FALSE;
|
||||
|
||||
SymSetOptions(SymGetOptions() | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS);
|
||||
SymSetOptions(SymGetOptions() & (~SYMOPT_DEFERRED_LOADS));
|
||||
SymSetSearchPath(hProcess, pszSymbolPath);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
DumpBaseType(DWORD dwTypeIndex, PENUMINFO pei, INT indent)
|
||||
{
|
||||
ULONG64 ulSize;
|
||||
DWORD dwBaseType;
|
||||
|
||||
SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_LENGTH, &ulSize);
|
||||
SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_BASETYPE, &dwBaseType);
|
||||
|
||||
switch (dwBaseType)
|
||||
{
|
||||
case btVoid:
|
||||
printfi("VOID");
|
||||
return;
|
||||
case btChar:
|
||||
printfi("CHAR");
|
||||
return;
|
||||
case btWChar:
|
||||
printfi("WCHAR");
|
||||
return;
|
||||
case btInt:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 1:
|
||||
printfi("CHAR");
|
||||
return;
|
||||
case 2:
|
||||
printfi("SHORT");
|
||||
return;
|
||||
case 4:
|
||||
printfi("INT");
|
||||
return;
|
||||
case 8:
|
||||
printfi("INT64");
|
||||
return;
|
||||
default:
|
||||
printfi("INT%ld", (ULONG)ulSize * 8);
|
||||
return;
|
||||
}
|
||||
case btUInt:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 1:
|
||||
printfi("UCHAR");
|
||||
return;
|
||||
case 2:
|
||||
printfi("USHORT");
|
||||
return;
|
||||
case 4:
|
||||
printfi("UINT");
|
||||
return;
|
||||
case 8:
|
||||
printfi("UINT64");
|
||||
return;
|
||||
default:
|
||||
printfi("UINT%ld", (ULONG)ulSize * 8);
|
||||
return;
|
||||
}
|
||||
case btFloat:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 4:
|
||||
printfi("FLOAT");
|
||||
return;
|
||||
case 8:
|
||||
printfi("DOUBLE");
|
||||
return;
|
||||
default:
|
||||
printfi("FLOAT%ld", (ULONG)ulSize * 8);
|
||||
return;
|
||||
}
|
||||
case btBCD:
|
||||
printfi("BCD%ld", (ULONG)ulSize * 8);
|
||||
return;
|
||||
case btBool:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 1:
|
||||
printfi("BOOLEAN");
|
||||
return;
|
||||
case 4:
|
||||
printfi("BOOL");
|
||||
return;
|
||||
default:
|
||||
printfi("BOOL%ld", (ULONG)ulSize * 8);
|
||||
return;
|
||||
}
|
||||
case btLong:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 1:
|
||||
printfi("CHAR");
|
||||
return;
|
||||
case 2:
|
||||
printfi("SHORT");
|
||||
return;
|
||||
case 4:
|
||||
printfi("LONG");
|
||||
return;
|
||||
case 8:
|
||||
printfi("LONGLONG");
|
||||
return;
|
||||
default:
|
||||
printfi("LONG%ld", (ULONG)ulSize * 8);
|
||||
return;
|
||||
}
|
||||
case btULong:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 1:
|
||||
printfi("UCHAR");
|
||||
return;
|
||||
case 2:
|
||||
printfi("USHORT");
|
||||
return;
|
||||
case 4:
|
||||
printfi("ULONG");
|
||||
return;
|
||||
case 8:
|
||||
printfi("ULONGLONG");
|
||||
return;
|
||||
default:
|
||||
printfi("ULONG%ld", (ULONG)ulSize * 8);
|
||||
return;
|
||||
}
|
||||
case btCurrency:
|
||||
case btDate:
|
||||
case btVariant:
|
||||
case btComplex:
|
||||
case btBit:
|
||||
case btBSTR:
|
||||
printfi("UNSUP_%ld_%ld", dwBaseType, (ULONG)ulSize);
|
||||
return;
|
||||
case btHresult:
|
||||
if (ulSize == 4)
|
||||
{
|
||||
printfi("HRESULT");
|
||||
return;
|
||||
}
|
||||
printfi("HRESULT%ld", (ULONG)ulSize);
|
||||
return;
|
||||
}
|
||||
|
||||
printfi("UNKNBASETYPE");
|
||||
}
|
||||
|
||||
VOID
|
||||
DumpArray(DWORD dwTypeIndex, PENUMINFO pei, INT indent)
|
||||
{
|
||||
DWORD dwTypeId;
|
||||
|
||||
SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_TYPE, &dwTypeId);
|
||||
DumpType(dwTypeId, pei, indent, FALSE);
|
||||
}
|
||||
|
||||
VOID
|
||||
DumpPointer(DWORD dwTypeIndex, PENUMINFO pei, INT indent)
|
||||
{
|
||||
DWORD dwRefTypeId;
|
||||
DWORD dwTag = 0;
|
||||
ULONG64 ulSize;
|
||||
DWORD dwBaseType;
|
||||
|
||||
SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_TYPE, &dwRefTypeId);
|
||||
SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwRefTypeId, TI_GET_BASETYPE, &dwBaseType);
|
||||
SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwRefTypeId, TI_GET_LENGTH, &ulSize);
|
||||
SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwRefTypeId, TI_GET_SYMTAG, &dwTag);
|
||||
|
||||
if (dwTag == SymTagFunctionType)
|
||||
{
|
||||
printfi("PPROC");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dwBaseType)
|
||||
{
|
||||
case btVoid:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 0:
|
||||
printfi("PVOID");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case btChar:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 1:
|
||||
printfi("PCHAR");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case btWChar:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 2:
|
||||
printfi("PWCHAR");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case btInt:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 4:
|
||||
printfi("PINT");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case btUInt:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 4:
|
||||
printfi("PUINT");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case btFloat:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 4:
|
||||
printfi("PFLOAT");
|
||||
return;
|
||||
case 8:
|
||||
printfi("PDOUBLE");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case btBCD:
|
||||
break;
|
||||
case btBool:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 1:
|
||||
printfi("PBOOLEAN");
|
||||
return;
|
||||
case 4:
|
||||
printfi("PBOOL");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case btLong:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 4:
|
||||
printfi("PLONG");
|
||||
return;
|
||||
case 8:
|
||||
printfi("PLONGLONG");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case btULong:
|
||||
switch (ulSize)
|
||||
{
|
||||
case 4:
|
||||
printfi("PULONG");
|
||||
return;
|
||||
case 8:
|
||||
printfi("PULONGLONG");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case btCurrency:
|
||||
case btDate:
|
||||
case btVariant:
|
||||
case btComplex:
|
||||
case btBit:
|
||||
case btBSTR:
|
||||
case btHresult:
|
||||
break;
|
||||
}
|
||||
|
||||
DumpType(dwRefTypeId, pei, indent, FALSE);
|
||||
printf("*");
|
||||
}
|
||||
|
||||
VOID
|
||||
PrintVariant(VARIANT *v)
|
||||
{
|
||||
// printf("<vt%d>", v->n1.n2.vt);
|
||||
switch (v->n1.n2.vt)
|
||||
{
|
||||
case VT_I1:
|
||||
printf("%d", (INT)v->n1.n2.n3.cVal);
|
||||
break;
|
||||
case VT_UI1:
|
||||
printf("0x%x", (UINT)v->n1.n2.n3.cVal);
|
||||
break;
|
||||
case VT_I2:
|
||||
printf("%d", (UINT)v->n1.n2.n3.iVal);
|
||||
break;
|
||||
case VT_UI2:
|
||||
printf("0x%x", (UINT)v->n1.n2.n3.iVal);
|
||||
break;
|
||||
case VT_INT:
|
||||
case VT_I4:
|
||||
printf("%d", (UINT)v->n1.n2.n3.lVal);
|
||||
break;
|
||||
case VT_UINT:
|
||||
case VT_UI4:
|
||||
printf("0x%x", (UINT)v->n1.n2.n3.lVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
IsUnnamed(WCHAR *pszName)
|
||||
{
|
||||
if ((StrStrW(pszName, L"__unnamed") != NULL) ||
|
||||
(StrStrW(pszName, L"<unnamed-tag>") != NULL))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
DumpEnum(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers)
|
||||
{
|
||||
DWORD64 dwModuleBase = pei->dwModuleBase;
|
||||
HANDLE hProcess = pei->hProcess;
|
||||
INT i;
|
||||
DWORD dwUDTKind;
|
||||
WCHAR *pszName, *pszNameX;
|
||||
struct
|
||||
{
|
||||
TI_FINDCHILDREN_PARAMS tfp;
|
||||
ULONG TypeIds[200];
|
||||
} tfpex;
|
||||
VARIANT v;
|
||||
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_SYMNAME, &pszNameX);
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_UDTKIND, &dwUDTKind);
|
||||
pszName = pszNameX;
|
||||
if (IsUnnamed(pszName))
|
||||
{
|
||||
if (bMembers)
|
||||
{
|
||||
LocalFree(pszNameX);
|
||||
return;
|
||||
}
|
||||
bMembers = TRUE;
|
||||
pszName = L"";
|
||||
}
|
||||
printfi("enum %ls", pszName);
|
||||
LocalFree(pszNameX);
|
||||
|
||||
if (bMembers)
|
||||
{
|
||||
printf(" /* %03x */", 0);
|
||||
printfi("\n{\n");
|
||||
|
||||
/* Get the children */
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &tfpex.tfp.Count);
|
||||
|
||||
tfpex.tfp.Start = 0;
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_FINDCHILDREN, &tfpex.tfp);
|
||||
|
||||
for (i = 0; i < tfpex.tfp.Count; i++)
|
||||
{
|
||||
pszName = L"";
|
||||
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_SYMNAME, &pszName);
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_VALUE, &v);
|
||||
|
||||
indent++;
|
||||
printfi("%ls = ", pszName);
|
||||
PrintVariant(&v);
|
||||
printf(",\n");
|
||||
indent--;
|
||||
|
||||
LocalFree(pszName);
|
||||
}
|
||||
printfi("}");
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
DumpUDT(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers)
|
||||
{
|
||||
DWORD64 dwModuleBase = pei->dwModuleBase;
|
||||
HANDLE hProcess = pei->hProcess;
|
||||
INT i;
|
||||
DWORD dwUDTKind;
|
||||
WCHAR *pszName, *pszNameX;
|
||||
struct
|
||||
{
|
||||
TI_FINDCHILDREN_PARAMS tfp;
|
||||
ULONG TypeIds[200];
|
||||
} tfpex;
|
||||
|
||||
DWORD dwDataKind;
|
||||
DWORD dwTypeId;
|
||||
DWORD dwCount;
|
||||
WCHAR *pszTypeName;
|
||||
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_SYMNAME, &pszNameX);
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_UDTKIND, &dwUDTKind);
|
||||
|
||||
pszName = pszNameX;
|
||||
if (IsUnnamed(pszName))
|
||||
{
|
||||
if (bMembers)
|
||||
{
|
||||
LocalFree(pszNameX);
|
||||
return;
|
||||
}
|
||||
bMembers = TRUE;
|
||||
pszName = L"";
|
||||
}
|
||||
if (dwUDTKind == UDTKind_Struct)
|
||||
{
|
||||
printfi("struct %ls", pszName);
|
||||
}
|
||||
else if (dwUDTKind == UDTKind_Union)
|
||||
{
|
||||
printfi("union %ls", pszName);
|
||||
}
|
||||
else
|
||||
{
|
||||
printfi("UTDKind%ld %ls", dwUDTKind, pszName);
|
||||
}
|
||||
LocalFree(pszNameX);
|
||||
|
||||
if (bMembers)
|
||||
{
|
||||
ULONG64 ulLength;
|
||||
|
||||
printf("\n");
|
||||
printfi("{\n");
|
||||
|
||||
/* Get the children */
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &tfpex.tfp.Count);
|
||||
|
||||
tfpex.tfp.Start = 0;
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_FINDCHILDREN, &tfpex.tfp);
|
||||
|
||||
for (i = 0; i < tfpex.tfp.Count; i++)
|
||||
{
|
||||
DWORD dwChildTag;
|
||||
DWORD dwOffset;
|
||||
|
||||
pszName = L"";
|
||||
pszTypeName = L"";
|
||||
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_SYMNAME, &pszName);
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_DATAKIND, &dwDataKind);
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_TYPE, &dwTypeId);
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_OFFSET, &dwOffset);
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeId, TI_GET_SYMTAG, &dwChildTag);
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeId, TI_GET_LENGTH, &ulLength);
|
||||
|
||||
printf(" /* %03lx */", dwOffset);
|
||||
DumpType(dwTypeId, pei, indent + 1, FALSE);
|
||||
printf(" %ls", pszName);
|
||||
if (dwChildTag == SymTagArrayType)
|
||||
{
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeId, TI_GET_COUNT, &dwCount);
|
||||
printf("[%ld]", dwCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwCurrentBitPos;
|
||||
DWORD dwNextBitPos;
|
||||
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i], TI_GET_BITPOSITION, &dwCurrentBitPos);
|
||||
if (i < tfpex.tfp.Count - 1)
|
||||
{
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, tfpex.tfp.ChildId[i+1], TI_GET_BITPOSITION, &dwNextBitPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
dwNextBitPos = 0;
|
||||
}
|
||||
|
||||
if (dwNextBitPos == 0 && dwCurrentBitPos != 0)
|
||||
{
|
||||
dwNextBitPos = ulLength * 8;
|
||||
}
|
||||
|
||||
if (dwNextBitPos != dwCurrentBitPos)
|
||||
{
|
||||
printf(":%ld", dwNextBitPos - dwCurrentBitPos);
|
||||
}
|
||||
}
|
||||
printf(";\n");
|
||||
LocalFree(pszName);
|
||||
}
|
||||
printfi("}");
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
DumpType(DWORD dwTypeIndex, PENUMINFO pei, INT indent, BOOL bMembers)
|
||||
{
|
||||
HANDLE hProcess = pei->hProcess;
|
||||
DWORD64 dwModuleBase = pei->dwModuleBase;
|
||||
DWORD dwTag = 0;
|
||||
|
||||
SymGetTypeInfo(hProcess, dwModuleBase, dwTypeIndex, TI_GET_SYMTAG, &dwTag);
|
||||
|
||||
switch (dwTag)
|
||||
{
|
||||
case SymTagEnum:
|
||||
DumpEnum(dwTypeIndex, pei, indent, bMembers);
|
||||
break;
|
||||
|
||||
case SymTagUDT:
|
||||
DumpUDT(dwTypeIndex, pei, indent, bMembers);
|
||||
break;
|
||||
|
||||
case SymTagPointerType:
|
||||
DumpPointer(dwTypeIndex, pei, indent);
|
||||
break;
|
||||
|
||||
case SymTagBaseType:
|
||||
DumpBaseType(dwTypeIndex, pei, indent);
|
||||
break;
|
||||
|
||||
case SymTagArrayType:
|
||||
DumpArray(dwTypeIndex, pei, indent);
|
||||
break;
|
||||
|
||||
case SymTagFunctionType:
|
||||
printfi("function");
|
||||
break;
|
||||
|
||||
default:
|
||||
printfi("typeTag%ld", dwTag);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
DumpCV(DWORD dwTypeIndex, PENUMINFO pei)
|
||||
{
|
||||
DWORD cv = 0x20;
|
||||
|
||||
SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, dwTypeIndex, TI_GET_CALLING_CONVENTION, &cv);
|
||||
switch (cv)
|
||||
{
|
||||
case CV_CALL_NEAR_C:
|
||||
printf("CDECL");
|
||||
return;
|
||||
case CV_CALL_FAR_C:
|
||||
printf("FAR CDECL");
|
||||
return;
|
||||
case CV_CALL_NEAR_PASCAL:
|
||||
printf("PASCAL");
|
||||
return;
|
||||
case CV_CALL_FAR_PASCAL:
|
||||
printf("FAR PASCAL");
|
||||
return;
|
||||
case CV_CALL_NEAR_FAST:
|
||||
printf("FASTCALL");
|
||||
return;
|
||||
case CV_CALL_FAR_FAST:
|
||||
printf("FAR FASTCALL");
|
||||
return;
|
||||
case CV_CALL_SKIPPED:
|
||||
printf("SKIPPED");
|
||||
return;
|
||||
case CV_CALL_NEAR_STD:
|
||||
printf("STDCALL");
|
||||
return;
|
||||
case CV_CALL_FAR_STD:
|
||||
printf("FAR STDCALL");
|
||||
return;
|
||||
case CV_CALL_NEAR_SYS:
|
||||
case CV_CALL_FAR_SYS:
|
||||
case CV_CALL_THISCALL:
|
||||
printf("THISCALL");
|
||||
return;
|
||||
case CV_CALL_MIPSCALL:
|
||||
printf("MIPSCALL");
|
||||
return;
|
||||
case CV_CALL_GENERIC:
|
||||
case CV_CALL_ALPHACALL:
|
||||
case CV_CALL_PPCCALL:
|
||||
case CV_CALL_SHCALL:
|
||||
case CV_CALL_ARMCALL:
|
||||
case CV_CALL_AM33CALL:
|
||||
case CV_CALL_TRICALL:
|
||||
case CV_CALL_SH5CALL:
|
||||
case CV_CALL_M32RCALL:
|
||||
default:
|
||||
printf("UNKNOWNCV");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOL CALLBACK
|
||||
EnumParamsProc(
|
||||
PSYMBOL_INFO pSymInfo,
|
||||
ULONG SymbolSize,
|
||||
PVOID UserContext)
|
||||
{
|
||||
printf("x, ");
|
||||
(*(INT*)UserContext)++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
DumpParams(PSYMBOL_INFO pSymInfo, PENUMINFO pei)
|
||||
{
|
||||
IMAGEHLP_STACK_FRAME sf;
|
||||
BOOL bRet;
|
||||
|
||||
sf.InstructionOffset = pSymInfo->Address;
|
||||
|
||||
printf("(");
|
||||
bRet = SymSetContext(pei->hProcess, &sf, 0);
|
||||
|
||||
if (!bRet)
|
||||
{
|
||||
printf("\nError: SymSetContext() failed. Error code: %lu \n", GetLastError());
|
||||
return;
|
||||
}
|
||||
printf("Address == 0x%x, ReturnOffset = 0x%x", (UINT)pSymInfo->Address, (UINT)sf.ReturnOffset);
|
||||
|
||||
// Enumerate local variables
|
||||
|
||||
INT NumLocals = 0; // the number of local variables found
|
||||
|
||||
bRet = SymEnumSymbols(pei->hProcess, 0, 0, EnumParamsProc, &NumLocals);
|
||||
|
||||
if (!bRet)
|
||||
{
|
||||
// printf("Error: SymEnumSymbols() failed. Error code: %lu \n", GetLastError());
|
||||
printf("?)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (NumLocals == 0)
|
||||
{
|
||||
// printf("The function does not have parameters and local variables.\n");
|
||||
printf("void)");
|
||||
}
|
||||
|
||||
printf(")");
|
||||
}
|
||||
|
||||
VOID
|
||||
DumpFunction(PSYMBOL_INFO pSymInfo, PENUMINFO pei)
|
||||
{
|
||||
DWORD dwTypeId;
|
||||
|
||||
//printf("Name=%s, Size=%ld, TypeId=0x%ld\n", pSymInfo->Name, pSymInfo->Size, pSymInfo->TypeIndex);
|
||||
|
||||
SymGetTypeInfo(pei->hProcess, pei->dwModuleBase, pSymInfo->TypeIndex, TI_GET_TYPEID, &dwTypeId);
|
||||
|
||||
// DumpCV(pSymInfo->TypeIndex, pei);
|
||||
// printf("\n");
|
||||
// DumpType(pSymInfo->TypeIndex, pei, 0, FALSE);
|
||||
printf("%s", pSymInfo->Name);
|
||||
DumpParams(pSymInfo, pei);
|
||||
}
|
||||
|
||||
BOOL CALLBACK
|
||||
EnumSymbolsProc(
|
||||
PSYMBOL_INFO pSymInfo,
|
||||
ULONG SymbolSize,
|
||||
PVOID UserContext)
|
||||
{
|
||||
PENUMINFO pei = (PENUMINFO)UserContext;
|
||||
|
||||
if ((pei->pszSymbolName == NULL) ||
|
||||
(strstr(pSymInfo->Name, pei->pszSymbolName) != 0))
|
||||
{
|
||||
if (pei->bType)
|
||||
{
|
||||
DumpType(pSymInfo->TypeIndex, pei, 0, TRUE);
|
||||
printf("\n\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (pSymInfo->Flags & SYMFLAG_FUNCTION)
|
||||
{
|
||||
// DumpFunction(pSymInfo, pei);
|
||||
// printf("\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
HANDLE hProcess;
|
||||
CHAR szFullFileName[MAX_PATH+1];
|
||||
DWORD64 dwModuleBase;
|
||||
BOOL bRet;
|
||||
LPSTR pszSymbolPath, pszSymbolName;
|
||||
INT i;
|
||||
ENUMINFO enuminfo;
|
||||
|
||||
printf("PE symbol dumper\n");
|
||||
printf("Copyright (c) Timo Kreuzer 2008\n\n");
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
PrintUsage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the full path name of the PE file from first argument */
|
||||
GetFullPathName(argv[1], MAX_PATH, szFullFileName, NULL);
|
||||
|
||||
/* Default Symbol Name (all) */
|
||||
pszSymbolName = NULL;
|
||||
|
||||
/* Default to ms symbol server */
|
||||
pszSymbolPath = "srv**symbols*http://msdl.microsoft.com/download/symbols";
|
||||
|
||||
/* Check other command line arguments */
|
||||
for (i = 2; i < argc; i++)
|
||||
{
|
||||
if (*argv[i] == '-')
|
||||
{
|
||||
if (strncmp(argv[i], "-sp=", 4) == 0)
|
||||
{
|
||||
pszSymbolPath = argv[i] + 4;
|
||||
}
|
||||
else if (strcmp(argv[i], "-p") == 0)
|
||||
{
|
||||
g_bShowPos = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid argument: %s\n", argv[i]);
|
||||
PrintUsage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pszSymbolName = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
hProcess = GetCurrentProcess();
|
||||
|
||||
printf("Trying to get symbols from: %s\n", pszSymbolPath);
|
||||
|
||||
if (!InitDbgHelp(hProcess, pszSymbolPath))
|
||||
{
|
||||
printf("SymInitialize() failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
printf("Loading symbols for %s, please wait...\n", szFullFileName);
|
||||
dwModuleBase = SymLoadModule64(hProcess, 0, szFullFileName, 0, 0, 0);
|
||||
if (dwModuleBase == 0)
|
||||
{
|
||||
printf("SymLoadModule64() failed: %ld\n", GetLastError());
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
printf("\nSymbols:\n");
|
||||
enuminfo.hProcess = hProcess;
|
||||
enuminfo.pszSymbolName = pszSymbolName;
|
||||
enuminfo.bType = FALSE;
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
bRet = SymEnumSymbols(hProcess, dwModuleBase, NULL, EnumSymbolsProc, &enuminfo);
|
||||
if (!bRet)
|
||||
{
|
||||
printf("SymEnumSymbols failed: %ld\n", GetLastError());
|
||||
}
|
||||
|
||||
printf("\nTypes:\n");
|
||||
enuminfo.bType = TRUE;
|
||||
enuminfo.dwModuleBase = dwModuleBase;
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
bRet = SymEnumTypes(hProcess, dwModuleBase, EnumSymbolsProc, &enuminfo);
|
||||
if (!bRet)
|
||||
{
|
||||
printf("SymEnumTypes failed: %ld\n", GetLastError());
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
return 0;
|
||||
}
|
9
rosapps/applications/devutils/symdump/symdump.rbuild
Normal file
9
rosapps/applications/devutils/symdump/symdump.rbuild
Normal file
|
@ -0,0 +1,9 @@
|
|||
<module name="symdump" type="win32cui" installbase="system32" installname="symdump.exe">
|
||||
<include base="gdihv">.</include>
|
||||
<define name="_WIN32_IE">0x0501</define>
|
||||
<define name="_WIN32_WINNT">0x0501</define>
|
||||
<library>dbghelp</library>
|
||||
<library>shlwapi</library>
|
||||
<library>kernel32</library>
|
||||
<file>symdump.c</file>
|
||||
</module>
|
Loading…
Reference in a new issue