//==========================================
// Matt Pietrek
// Microsoft Systems Journal, August 1997
// FILE: EZPE.CPP
//==========================================
#include <windows.h>
#include <stdio.h>
#include <imagehlp.h>
//=============================================================================
// Macros to make formatted output of numerous data structure fields easier
//=============================================================================
#define DISPLAY_COLUMNS "35"
#define DisplayPtrField( ptr, field, fmt ) \
printf( "%-" DISPLAY_COLUMNS fmt, #field, ptr->field );
#define DisplayPtrFieldD( ptr, field ) DisplayPtrField( ptr, field, "s%08X\n" )
#define DisplayPtrFieldW( ptr, field ) DisplayPtrField( ptr, field, "s%04X\n" )
#define DisplayPtrFieldStr(ptr,field ) DisplayPtrField( ptr, field, "s%s\n" )
#define DisplayPtrVersionFields( name, ptr, field1, field2 ) \
printf("%-" DISPLAY_COLUMNS "s%u.%02u\n", name,ptr->field1,ptr->field2);
#define DisplayField( struct, field, fmt ) \
printf( "%-" DISPLAY_COLUMNS fmt, #field, struct.field );
#define DisplayFieldD( struct, field ) DisplayField( struct, field, "s%08X\n")
#define DisplayFieldW( struct, field ) DisplayField( struct, field, "s%04X\n")
#define DisplayFieldStr(struct,field ) DisplayField( struct, field, "s%s\n")
#define DisplayDataDir( ptr, x ) \
printf( "%-" DISPLAY_COLUMNS "sAddress: %08X Size: %08X\n", \
#x, ptr->DataDirectory[x].VirtualAddress, ptr->DataDirectory[x].Size );
//=============================================================================
// Prototypes for helper functions
//=============================================================================
BOOL CALLBACK EnumSymbolsCallback( LPSTR, ULONG, ULONG, PVOID );
void ShowImageFileHeaders( PIMAGE_NT_HEADERS pNTHdrs );
void ShowSectionHeaders( PIMAGE_SECTION_HEADER pSectionHdr, DWORD cSections );
void StartNewDisplaySection( PSTR pszSectionName );
BOOL ParseCommandLine(int argc, char * argv[], PSTR pszFilename, PSTR pszPath);
void ShowSymbols( PSTR pszFilename, PSTR pszPath );
//=============================================================================
// Global variables
//=============================================================================
BOOL g_fDecoratedNames = FALSE;
BOOL g_fShowSymbols = TRUE;
char g_szHelp[] =
"EZPE - August 1997 Microsoft Systems Journal, by Matt Pietrek\n"
"Syntax: EZPE [options] <filename>\n"
" -d Decorated C++ names\n"
" -n No symbol display\n";
//=============================================================================
// Main program - First display info about the executable, then shows symbols
//=============================================================================
int main( int argc, char * argv[] )
{
char szFilename[MAX_PATH];
char szPath[MAX_PATH];
if ( !ParseCommandLine(argc, argv, szFilename, szPath) )
{
printf( g_szHelp );
return 1;
}
printf( "Display of file %s\n", szFilename );
LOADED_IMAGE li;
if ( MapAndLoad( szFilename, 0, &li, FALSE, TRUE) )
{
StartNewDisplaySection( " LOADED_IMAGE" );
DisplayFieldStr( li, ModuleName )
DisplayFieldD( li, hFile )
DisplayFieldD( li, MappedAddress )
DisplayFieldD( li, FileHeader )
DisplayFieldD( li, LastRvaSection )
DisplayFieldD( li, NumberOfSections )
DisplayFieldD( li, Sections )
DisplayFieldD( li, Characteristics )
DisplayFieldD( li, fSystemImage )
DisplayFieldD( li, fDOSImage )
DisplayFieldD( li, Links )
DisplayFieldD( li, SizeOfImage )
StartNewDisplaySection( "PE File Headers (LOADED_IMAGE.FileHeader)" );
ShowImageFileHeaders( li.FileHeader );
StartNewDisplaySection( "Section Headers (LOADED_IMAGE.Sections)" );
ShowSectionHeaders( li.Sections, li.NumberOfSections );
}
else
{
printf( "MapAndLoad failed - exiting\n" );
return 1;
}
UnMapAndLoad( &li );
if ( g_fShowSymbols )
ShowSymbols( szFilename, szPath );
return 0;
}
#define MY_PROCESS_HANDLE 0
//=============================================================================
// Loads a symbol table and enumerates the symbols in it
//=============================================================================
void ShowSymbols( PSTR pszFilename, PSTR pszPath )
{
PIMAGE_DEBUG_INFORMATION pidi;
//
// First, see if there's any debug information worth displaying. If
// this functions succeeds, the PE file, and its debug information
// is memory mapped in.
//
pidi = MapDebugInformation( 0, pszFilename, "", 0 );
if ( pidi )
{
StartNewDisplaySection( "IMAGE_DEBUG_INFORMATION" );
DisplayPtrFieldD( pidi, Size )
DisplayPtrFieldD( pidi, MappedBase )
DisplayPtrFieldW( pidi, Machine )
DisplayPtrFieldW( pidi, Characteristics )
DisplayPtrFieldD( pidi, CheckSum )
DisplayPtrFieldD( pidi, ImageBase )
DisplayPtrFieldD( pidi, SizeOfImage )
DisplayPtrFieldD( pidi, NumberOfSections )
DisplayPtrFieldD( pidi, Sections )
DisplayPtrFieldD( pidi, ExportedNamesSize )
DisplayPtrFieldD( pidi, ExportedNames )
DisplayPtrFieldD( pidi, NumberOfFunctionTableEntries )
DisplayPtrFieldD( pidi, FunctionTableEntries )
DisplayPtrFieldD( pidi, LowestFunctionStartingAddress )
DisplayPtrFieldD( pidi, HighestFunctionEndingAddress )
DisplayPtrFieldD( pidi, NumberOfFpoTableEntries )
DisplayPtrFieldD( pidi, FpoTableEntries )
DisplayPtrFieldD( pidi, SizeOfCoffSymbols )
DisplayPtrFieldD( pidi, CoffSymbols )
DisplayPtrFieldD( pidi, SizeOfCodeViewSymbols )
DisplayPtrFieldD( pidi, CodeViewSymbols )
DisplayPtrFieldStr( pidi, ImageFilePath )
DisplayPtrFieldStr( pidi, ImageFileName )
DisplayPtrFieldStr( pidi, DebugFilePath )
DisplayPtrFieldD( pidi, TimeDateStamp )
DisplayPtrFieldD( pidi, RomImage )
DisplayPtrFieldD( pidi, DebugDirectory )
DisplayPtrFieldD( pidi, NumberOfDebugDirectories )
}
else
{
printf( "MapDebugInformation failed - exiting\n" );
return;
}
//
// Init symbol handler for "process" (in our case, "0" is the process)
//
if ( !SymInitialize( MY_PROCESS_HANDLE, pszPath, FALSE ) )
{
printf( "MapDebugInformation failed - exiting\n" );
return;
}
//
// If the command line specified "decorated" names (-d), set the symbol
// options before loading the symbol table below.
//
if ( g_fDecoratedNames )
{
DWORD symOptions = SymGetOptions();
symOptions &= ~SYMOPT_UNDNAME; // Turn off the SYMOPT_UNDNAME flag
SymSetOptions( symOptions );
}
//
// Load the symbol table for the specified file. A "MappedAddress" from
// MapAndLoad, or a "MappedBase" from MapDebugInformation is needed as
// parameter 5.
//
if ( !SymLoadModule( MY_PROCESS_HANDLE, 0, pszFilename, 0,
(DWORD)pidi->MappedBase, 0 ) )
{
printf( "SymLoadModuleFailed\n" );
return;
}
IMAGEHLP_MODULE im = { sizeof(im) };
if ( SymGetModuleInfo( MY_PROCESS_HANDLE, (DWORD)pidi->MappedBase, &im ) )
{
StartNewDisplaySection( "IMAGEHLP_MODULE" );
// DisplayFieldD( im, SizeOfStruct ); // Not worth showing
// DisplayFieldD( im, BaseOfImage );
// DisplayFieldD( im, ImageSize );
// DisplayFieldD( im, TimeDateStamp );
DisplayFieldD( im, CheckSum );
DisplayFieldD( im, NumSyms );
DisplayFieldD( im, SymType );
PSTR pszSymType;
switch( im.SymType )
{
case SymNone: pszSymType = "SymNone"; break;
case SymCoff: pszSymType = "SymCoff"; break;
case SymCv: pszSymType = "SymCv"; break;
case SymPdb: pszSymType = "SymPdb"; break;
case SymExport: pszSymType = "SymExport"; break;
case SymDeferred: pszSymType = "SymDeferred"; break;
default: pszSymType = "?";
}
printf( "%-" DISPLAY_COLUMNS "s%s\n", " ", pszSymType );
DisplayFieldStr( im, ModuleName );
DisplayFieldStr( im, ImageName );
DisplayFieldStr( im, LoadedImageName );
}
StartNewDisplaySection( "Symbols" );
printf( " RVA Name\n" );
printf( "-------- ----\n" );
//
// Kick off the symbol enumeration. The EnumSymbolsCallback function
// is called once for each symbol.
//
SymEnumerateSymbols( 0, (DWORD)pidi->MappedBase, EnumSymbolsCallback,
pidi->MappedBase );
SymUnloadModule( 0, (DWORD)pidi->MappedBase ); // Undo SymLoadModule
SymCleanup( 0 ); // Undo the SymInitialize
UnmapDebugInformation( pidi ); // Close the PE file and debug info mapping
}
//=============================================================================
// Callback function for use by the SymEnumerateSymbols API
//=============================================================================
BOOL CALLBACK EnumSymbolsCallback(
LPSTR SymbolName,
ULONG SymbolAddress,
ULONG SymbolSize,
PVOID UserContext )
{
// User Context is whatever was passed to SymEnumerateSymbols. Here,
// we passed the mapped address of the executable. This allows us
// to convert the symbol addresses we get into RVAs, below.
DWORD mappedBase = (DWORD)UserContext;
// print out the RVA, and the symbol name passed to us.
printf( "%08X %s\n", SymbolAddress - mappedBase, SymbolName );
//
// If "decorated" names were specified, and if the name is "decorated,"
// undecorate it so that a human readable version can be displayed.
//
if ( g_fDecoratedNames && ('?' == *SymbolName) )
{
char szUndecoratedName[0x400]; // Make symbol name buffers for the
char szDecoratedName[0x400]; // decorated & undecorated versions
// Make a copy of the original SymbolName, so that we can modify it
lstrcpy( szDecoratedName, SymbolName );
PSTR pEnd = szDecoratedName + lstrlen( szDecoratedName );
// Strip everything off the end until we reach a 'Z'
while ( (pEnd > szDecoratedName) && (*pEnd != 'Z') )
*pEnd-- = 0;
// Call the IMAGEHLP function to undecorate the name
if ( 0 != UnDecorateSymbolName( szDecoratedName, szUndecoratedName,
sizeof(szUndecoratedName),
UNDNAME_COMPLETE |
UNDNAME_32_BIT_DECODE ) )
{
// End the output line with the undecorated name
printf( " %s\n", szUndecoratedName );
}
}
return TRUE;
}
//=============================================================================
// Shows the contents of a PE header. Called by main()
//=============================================================================
void ShowImageFileHeaders( PIMAGE_NT_HEADERS pNTHdrs )
{
PIMAGE_FILE_HEADER pImageFileHeader = &pNTHdrs->FileHeader;
DisplayPtrFieldW( pImageFileHeader, Machine )
DisplayPtrFieldW( pImageFileHeader, NumberOfSections )
DisplayPtrFieldD( pImageFileHeader, TimeDateStamp )
DisplayPtrFieldD( pImageFileHeader, PointerToSymbolTable )
DisplayPtrFieldD( pImageFileHeader, NumberOfSymbols )
DisplayPtrFieldW( pImageFileHeader, SizeOfOptionalHeader )
DisplayPtrFieldW( pImageFileHeader, Characteristics )
PIMAGE_OPTIONAL_HEADER pImageOptHeader = &pNTHdrs->OptionalHeader;
DisplayPtrFieldW( pImageOptHeader, Magic )
DisplayPtrVersionFields("LinkerVersion", pImageOptHeader,
MajorLinkerVersion, MinorLinkerVersion );
DisplayPtrFieldD( pImageOptHeader, SizeOfCode )
DisplayPtrFieldD( pImageOptHeader, SizeOfInitializedData )
DisplayPtrFieldD( pImageOptHeader, SizeOfUninitializedData )
DisplayPtrFieldD( pImageOptHeader, AddressOfEntryPoint )
DisplayPtrFieldD( pImageOptHeader, BaseOfCode )
DisplayPtrFieldD( pImageOptHeader, BaseOfData )
DisplayPtrFieldD( pImageOptHeader, ImageBase )
DisplayPtrFieldD( pImageOptHeader, SectionAlignment )
DisplayPtrFieldD( pImageOptHeader, FileAlignment )
DisplayPtrVersionFields("OperatingSystemVersion", pImageOptHeader,
MajorOperatingSystemVersion,
MinorOperatingSystemVersion )
DisplayPtrVersionFields("ImageVersion", pImageOptHeader, MajorImageVersion,
MinorImageVersion )
DisplayPtrVersionFields("SubsystemVersion", pImageOptHeader,
MajorSubsystemVersion,
MinorSubsystemVersion )
DisplayPtrFieldD( pImageOptHeader, Win32VersionValue )
DisplayPtrFieldD( pImageOptHeader, SizeOfImage )
DisplayPtrFieldD( pImageOptHeader, SizeOfHeaders )
DisplayPtrFieldD( pImageOptHeader, CheckSum )
DisplayPtrFieldW( pImageOptHeader, Subsystem )
DisplayPtrFieldW( pImageOptHeader, DllCharacteristics )
DisplayPtrFieldD( pImageOptHeader, SizeOfStackReserve )
DisplayPtrFieldD( pImageOptHeader, SizeOfStackCommit )
DisplayPtrFieldD( pImageOptHeader, SizeOfHeapReserve )
DisplayPtrFieldD( pImageOptHeader, SizeOfHeapCommit )
DisplayPtrFieldD( pImageOptHeader, LoaderFlags )
DisplayPtrFieldD( pImageOptHeader, NumberOfRvaAndSizes )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_EXPORT )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_IMPORT )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_RESOURCE )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_EXCEPTION )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_SECURITY )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_BASERELOC )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_DEBUG )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_COPYRIGHT )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_GLOBALPTR )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_TLS )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT )
DisplayDataDir( pImageOptHeader, IMAGE_DIRECTORY_ENTRY_IAT )
}
//=============================================================================
// Enumerates through a section table and displays basic info for each section
//=============================================================================
void ShowSectionHeaders( PIMAGE_SECTION_HEADER pSectionHdr, DWORD cSections )
{
printf( " # Name Address VirtSize RawSize\n" );
printf( "-- -------- -------- -------- --------\n" );
for ( unsigned i=1; i <= cSections; i++, pSectionHdr++ )
{
printf( "%2u %8.8s %08X %08X %08x\n", i, pSectionHdr->Name,
pSectionHdr->VirtualAddress, pSectionHdr->Misc.VirtualSize,
pSectionHdr->SizeOfRawData );
}
}
//=============================================================================
// Helper function used to provide consistent delimitation of output sections
//=============================================================================
void StartNewDisplaySection( PSTR pszSectionName )
{
printf( "\n==== %s ====\n", pszSectionName );
}
//=============================================================================
// Called by main() to extract any command-line arguments, as well as the
// filename to be used. Also attempts to come up with a complete path to
// the directory containing the named executable. Returns this value in the
// pszPath param buffer.
//=============================================================================
BOOL ParseCommandLine( int argc, char * argv[], PSTR pszFilename, PSTR pszPath )
{
if ( argc < 2 )
return FALSE;
BOOL fSawFilename = FALSE;
for ( int i = 1; i < argc; i++ )
{
PSTR pszArg = argv[i];
if ( *pszArg == '-' ) // Is the first character a '-' ?
{
*pszArg++;
if ( (*pszArg=='d') || (*pszArg=='D') ) // allow "d" or "D"
g_fDecoratedNames = TRUE; // set global flag
else if ( (*pszArg=='n') || (*pszArg=='N') ) // allow "n" or "N"
g_fShowSymbols = FALSE; // set global flag
}
else
{
if ( fSawFilename ) // We should only get here once
return FALSE;
PSTR pszFilenamePart;
if (GetFullPathName( argv[i], MAX_PATH, pszPath, &pszFilenamePart))
{
// Truncate the filename portion off the path
if ( pszFilenamePart )
*pszFilenamePart = 0;
// Copy the input argument to the passed in filename buffer
lstrcpy( pszFilename, argv[i] );
fSawFilename = TRUE;
}
else // GetFullPathName failed. Ooops!
return FALSE;
}
}
return fSawFilename;
}
Figure 2 EZPE Output
ezpe.mak
Ezpe.out
Display of file EZPE.EXE
==== LOADED_IMAGE ====
ModuleName EZPE.EXE
hFile FFFFFFFF
MappedAddress 008B0000
FileHeader 008B0080
LastRvaSection 008B0178
NumberOfSections 00000004
Sections 008B0178
Characteristics 0000010B
fSystemImage 00000000
fDOSImage 00000000
Links 0012FFA4
SizeOfImage 00003E00
==== PE File Headers (LOADED_IMAGE.FileHeader) ====
Machine 014C
NumberOfSections 0004
TimeDateStamp 336CF53B
PointerToSymbolTable 00000000
NumberOfSymbols 00000000
SizeOfOptionalHeader 00E0
Characteristics 010B
Magic 010B
LinkerVersion 5.00
SizeOfCode 00002200
SizeOfInitializedData 00001800
SizeOfUninitializedData 00000000
AddressOfEntryPoint 00001E59
BaseOfCode 00001000
BaseOfData 00004000
ImageBase 00400000
SectionAlignment 00001000
FileAlignment 00000200
OperatingSystemVersion 4.00
ImageVersion 0.00
SubsystemVersion 4.00
Win32VersionValue 00000000
SizeOfImage 00007000
SizeOfHeaders 00000400
CheckSum 00000000
Subsystem 0003
DllCharacteristics 0000
SizeOfStackReserve 00100000
SizeOfStackCommit 00001000
SizeOfHeapReserve 00100000
SizeOfHeapCommit 00001000
LoaderFlags 00000000
NumberOfRvaAndSizes 00000010
IMAGE_DIRECTORY_ENTRY_EXPORT Address: 00000000 Size: 00000000
IMAGE_DIRECTORY_ENTRY_IMPORT Address: 00006000 Size: 00000050
IMAGE_DIRECTORY_ENTRY_RESOURCE Address: 00000000 Size: 00000000
IMAGE_DIRECTORY_ENTRY_EXCEPTION Address: 00000000 Size: 00000000
IMAGE_DIRECTORY_ENTRY_SECURITY Address: 00000000 Size: 00000000
IMAGE_DIRECTORY_ENTRY_BASERELOC Address: 00000000 Size: 00000000
IMAGE_DIRECTORY_ENTRY_DEBUG Address: 00004000 Size: 00000054
IMAGE_DIRECTORY_ENTRY_COPYRIGHT Address: 00000000 Size: 00000000
IMAGE_DIRECTORY_ENTRY_GLOBALPTR Address: 00000000 Size: 00000000
IMAGE_DIRECTORY_ENTRY_TLS Address: 00000000 Size: 00000000
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG Address: 00000000 Size: 00000000
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT Address: 00000000 Size: 00000000
IMAGE_DIRECTORY_ENTRY_IAT Address: 0000613C Size: 000000EC
==== Section Headers (LOADED_IMAGE.Sections) ====
# Name Address VirtSize RawSize
-- -------- -------- -------- --------
1 .text 00001000 0000206F 00002200
2 .rdata 00004000 00000164 00000200
3 .data 00005000 00000E53 00000c00
4 .idata 00006000 000004FC 00000600
==== IMAGE_DEBUG_INFORMATION ====
Size 0000012C
MappedBase 008B0000
Machine 014C
Characteristics 010B
CheckSum 00000000
ImageBase 00400000
SizeOfImage 00007000
NumberOfSections 00000004
Sections 008B0178
ExportedNamesSize 00000000
ExportedNames 00000000
NumberOfFunctionTableEntries 00000000
FunctionTableEntries 00000000
LowestFunctionStartingAddress 00000000
HighestFunctionEndingAddress 00000000
NumberOfFpoTableEntries 00000005
FpoTableEntries 008AE72C
SizeOfCoffSymbols 00000000
CoffSymbols 00000000
SizeOfCodeViewSymbols 00000029
CodeViewSymbols 008AE780
ImageFilePath E:\column\col47\EZPE.EXE
ImageFileName EZPE.EXE
DebugFilePath E:\column\col47\EZPE.EXE
TimeDateStamp 336CF53B
RomImage 00000000
DebugDirectory 008B2600
NumberOfDebugDirectories 00000003
==== IMAGEHLP_MODULE ====
CheckSum 00000000
NumSyms 00000000
SymType 00000003
SymPdb
ModuleName EZPE
ImageName EZPE.EXE
LoadedImageName E:\column\col47\EZPE.EXE
==== Symbols ====
RVA Name
-------- ----
000061BC _imp__ExitProcess
00001834 ShowImageFileHeaders
0000616C _imp__UnDecorateSymbolName
00001F92 UnmapDebugInformation
00001FEC GetStdHandle
00001F8C MapAndLoad
00006014 _IMPORT_DESCRIPTOR_IMAGEHLP
00001E14 printf
000061A8 _imp__lstrlenA
00001F80 wvsprintfA
00001D5F ParseCommandLine
00001E76 _ConvertCommandLineToArgcArgv
00005A78 g_szHelp
000061F8 _imp__wvsprintfA
0000614C _imp__UnmapDebugInformation
00001FE0 GetFullPathNameA
00006154 _imp__SymUnloadModule
000061C8 KERNEL32_NULL_THUNK_DATA
00006148 _imp__MapAndLoad
00001FDA lstrcpyA
000061B0 _imp__GetCommandLineA
00001F86 UnMapAndLoad
00001FA4 SymEnumerateSymbols
00005BE0 _ppszArgv
00005A70 g_fShowSymbols
00001FAA SymGetModuleInfo
00001292 ShowSymbols
0000613C _imp__MapDebugInformation
000061FC USER32_NULL_THUNK_DATA
00001D4A StartNewDisplaySection
00001046 main
00001FBC SymGetOptions
0000615C _imp__SymGetModuleInfo
00006140 _imp__SymInitialize
00006144 _imp__UnMapAndLoad
00002004 GetCommandLineA
000061C4 _imp__GetProcessHeap
000061A4 _imp__GetFullPathNameA
00006170 IMAGEHLP_NULL_THUNK_DATA
00006164 _imp__SymSetOptions
00005BC0 g_fDecoratedNames
00006160 _imp__SymLoadModule
00001FC8 MapDebugInformation
00001F9E SymUnloadModule
00006000 _IMPORT_DESCRIPTOR_USER32
00001FF8 HeapAlloc
00006158 _imp__SymEnumerateSymbols
00001F98 SymCleanup
00001FE6 WriteFile
000061AC _imp__lstrcpyA
00001767 EnumSymbolsCallback
00006150 _imp__SymCleanup
000061B8 _imp__GetStdHandle
00001FD4 lstrlenA
00001FB6 SymSetOptions
00006168 _imp__SymGetOptions
00001FFE GetProcessHeap
000061B4 _imp__WriteFile
00006028 _IMPORT_DESCRIPTOR_KERNEL32
00001E59 mainCRTStartup
00001FF2 ExitProcess
000061C0 _imp__HeapAlloc
00001FCE UnDecorateSymbolName
00001CEE ShowSectionHeaders
00001FC2 SymInitialize
00001FB0 SymLoadModule
0000603C _NULL_IMPORT_DESCRIPTOR