| 1 |
#include "edbgfunctions.h" |
|---|
| 2 |
#include <stdio.h> |
|---|
| 3 |
|
|---|
| 4 |
#define IMAGE_SECOND_HEADER_OFFSET (15 * sizeof(ULONG)) // relative to file beginning |
|---|
| 5 |
#define IMAGE_BASE_OFFSET (13 * sizeof(DWORD)) // relative to PE header base |
|---|
| 6 |
#define IMAGE_EXPORT_TABLE_RVA_OFFSET (30 * sizeof(DWORD)) // relative to PE header base |
|---|
| 7 |
#define IMAGE_NAME_RVA_OFFSET 12 |
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
int ReadDebugString( HANDLE hProcess, OUTPUT_DEBUG_STRING_INFO odsi ,LPCSTR str ) { |
|---|
| 11 |
DWORD br; |
|---|
| 12 |
ReadProcessMemory( hProcess, |
|---|
| 13 |
(LPVOID) odsi.lpDebugStringData, |
|---|
| 14 |
(LPVOID)str, odsi.nDebugStringLength, &br); |
|---|
| 15 |
|
|---|
| 16 |
return br; |
|---|
| 17 |
} |
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
DWORD GetModuleFileNameFromHeader( HANDLE hProcess, HANDLE hFile, DWORD BaseOfDll, |
|---|
| 22 |
char* lpszPath, DWORD cchPath ) |
|---|
| 23 |
{ |
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
WORD DosSignature; |
|---|
| 27 |
DWORD NtSignature; |
|---|
| 28 |
DWORD dwNumberOfBytesRead = 0; |
|---|
| 29 |
DWORD PeHeader, ImageBase, ExportTableRVA, NameRVA; |
|---|
| 30 |
|
|---|
| 31 |
//-- verify that the handle is not NULL |
|---|
| 32 |
|
|---|
| 33 |
if( !hFile ) |
|---|
| 34 |
{ |
|---|
| 35 |
strcpy( lpszPath, "Invalid File Handle"); |
|---|
| 36 |
return( 0 ); |
|---|
| 37 |
} |
|---|
| 38 |
|
|---|
| 39 |
//-- verify that the handle is for a disk file |
|---|
| 40 |
if( GetFileType(hFile) != FILE_TYPE_DISK ) |
|---|
| 41 |
{ |
|---|
| 42 |
strcpy( lpszPath, "Invalid File Type"); |
|---|
| 43 |
return( 0 ); |
|---|
| 44 |
} |
|---|
| 45 |
|
|---|
| 46 |
//-- Extract the filename from the EXE header |
|---|
| 47 |
SetFilePointer( hFile, 0L, NULL, FILE_BEGIN ); |
|---|
| 48 |
|
|---|
| 49 |
ReadFile( hFile, &DosSignature, sizeof(DosSignature), &dwNumberOfBytesRead, |
|---|
| 50 |
(LPOVERLAPPED) NULL); |
|---|
| 51 |
|
|---|
| 52 |
//-- verify DOS signature found |
|---|
| 53 |
if( DosSignature != IMAGE_DOS_SIGNATURE ) |
|---|
| 54 |
{ |
|---|
| 55 |
sprintf( lpszPath, "Bad MZ Signature: 0x%x" , DosSignature ); |
|---|
| 56 |
return( 0 ); |
|---|
| 57 |
} |
|---|
| 58 |
|
|---|
| 59 |
SetFilePointer( hFile, IMAGE_SECOND_HEADER_OFFSET, (LPLONG) NULL, |
|---|
| 60 |
FILE_BEGIN ); |
|---|
| 61 |
ReadFile( hFile, &PeHeader, sizeof(PeHeader), &dwNumberOfBytesRead, |
|---|
| 62 |
(LPOVERLAPPED) NULL ); |
|---|
| 63 |
SetFilePointer( hFile, PeHeader, (LPLONG) NULL, FILE_BEGIN ); |
|---|
| 64 |
ReadFile( hFile, &NtSignature, sizeof(NtSignature), &dwNumberOfBytesRead, |
|---|
| 65 |
(LPOVERLAPPED) NULL); |
|---|
| 66 |
|
|---|
| 67 |
//-- verify Windows NT (PE) signature found |
|---|
| 68 |
|
|---|
| 69 |
if( NtSignature != IMAGE_NT_SIGNATURE ) |
|---|
| 70 |
{ |
|---|
| 71 |
wsprintf( lpszPath, TEXT( "Bad PE Signature: 0x%x" ), DosSignature ); |
|---|
| 72 |
return( 0 ); |
|---|
| 73 |
} |
|---|
| 74 |
|
|---|
| 75 |
SetFilePointer( hFile, PeHeader + IMAGE_BASE_OFFSET, (LPLONG) NULL, |
|---|
| 76 |
FILE_BEGIN ); |
|---|
| 77 |
ReadFile( hFile, &ImageBase, sizeof(ImageBase), &dwNumberOfBytesRead, |
|---|
| 78 |
(LPOVERLAPPED) NULL); |
|---|
| 79 |
SetFilePointer( hFile, PeHeader + IMAGE_EXPORT_TABLE_RVA_OFFSET, |
|---|
| 80 |
(LPLONG) NULL, FILE_BEGIN ); |
|---|
| 81 |
ReadFile( hFile, &ExportTableRVA, sizeof(ExportTableRVA), |
|---|
| 82 |
&dwNumberOfBytesRead, (LPOVERLAPPED) NULL); |
|---|
| 83 |
|
|---|
| 84 |
//-- now read from the virtual address space in the process |
|---|
| 85 |
ReadProcessMemory( hProcess, |
|---|
| 86 |
(LPVOID) (BaseOfDll + ExportTableRVA + (DWORD) IMAGE_NAME_RVA_OFFSET), |
|---|
| 87 |
&NameRVA, sizeof(NameRVA), &dwNumberOfBytesRead ); |
|---|
| 88 |
|
|---|
| 89 |
|
|---|
| 90 |
strcpy( lpszPath, TEXT("Empty!") ); |
|---|
| 91 |
|
|---|
| 92 |
if( !ReadProcessMemory( hProcess, |
|---|
| 93 |
(LPVOID) (BaseOfDll + NameRVA), |
|---|
| 94 |
lpszPath, cchPath, &dwNumberOfBytesRead ) ) |
|---|
| 95 |
|
|---|
| 96 |
|
|---|
| 97 |
|
|---|
| 98 |
|
|---|
| 99 |
strcpy( lpszPath, TEXT("Access Denied!") ); |
|---|
| 100 |
|
|---|
| 101 |
return( dwNumberOfBytesRead ); |
|---|
| 102 |
} |
|---|
| 103 |
|
|---|
| 104 |
vector<BackTraceData> StackBackTrace(HANDLE hProcess, HANDLE hThread , PCONTEXT _pContext ) |
|---|
| 105 |
|
|---|
| 106 |
{ |
|---|
| 107 |
|
|---|
| 108 |
PCONTEXT pContext = _pContext; |
|---|
| 109 |
DWORD dwMachineType = 0; |
|---|
| 110 |
// Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag |
|---|
| 111 |
|
|---|
| 112 |
STACKFRAME sf; |
|---|
| 113 |
memset( &sf, 0, sizeof(sf) ); |
|---|
| 114 |
|
|---|
| 115 |
#ifdef _M_IX86 |
|---|
| 116 |
// Initialize the STACKFRAME structure for the first call. This is only |
|---|
| 117 |
// necessary for Intel CPUs, and isn't mentioned in the documentation. |
|---|
| 118 |
sf.AddrPC.Offset = pContext->Eip; |
|---|
| 119 |
sf.AddrPC.Mode = AddrModeFlat; |
|---|
| 120 |
sf.AddrStack.Offset = pContext->Esp; |
|---|
| 121 |
sf.AddrStack.Mode = AddrModeFlat; |
|---|
| 122 |
sf.AddrFrame.Offset = pContext->Ebp; |
|---|
| 123 |
sf.AddrFrame.Mode = AddrModeFlat; |
|---|
| 124 |
|
|---|
| 125 |
dwMachineType = IMAGE_FILE_MACHINE_I386; |
|---|
| 126 |
#endif |
|---|
| 127 |
|
|---|
| 128 |
vector<BackTraceData> ret; |
|---|
| 129 |
BackTraceData item; |
|---|
| 130 |
|
|---|
| 131 |
while ( 1 ) |
|---|
| 132 |
{ |
|---|
| 133 |
// Get the next stack frame |
|---|
| 134 |
if ( ! StackWalk( dwMachineType, |
|---|
| 135 |
hProcess, |
|---|
| 136 |
hThread, |
|---|
| 137 |
&sf, |
|---|
| 138 |
pContext, |
|---|
| 139 |
0, |
|---|
| 140 |
SymFunctionTableAccess, |
|---|
| 141 |
SymGetModuleBase, |
|---|
| 142 |
0 ) ) |
|---|
| 143 |
break; |
|---|
| 144 |
|
|---|
| 145 |
if ( 0 == sf.AddrFrame.Offset ) // Basic sanity check to make sure |
|---|
| 146 |
break; // the frame is OK. Bail if not. |
|---|
| 147 |
|
|---|
| 148 |
|
|---|
| 149 |
|
|---|
| 150 |
// Get the name of the function for this stack frame entry |
|---|
| 151 |
BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + 1024 ]; |
|---|
| 152 |
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer; |
|---|
| 153 |
pSymbol->SizeOfStruct = sizeof(symbolBuffer); |
|---|
| 154 |
pSymbol->MaxNameLen = 1024; |
|---|
| 155 |
|
|---|
| 156 |
DWORD64 symDisplacement = 0; // Displacement of the input address, |
|---|
| 157 |
// relative to the start of the symbol |
|---|
| 158 |
|
|---|
| 159 |
if ( SymFromAddr(m_hProcess,sf.AddrPC.Offset,&symDisplacement,pSymbol)) |
|---|
| 160 |
{ |
|---|
| 161 |
item.symName = pSymbol->Name; |
|---|
| 162 |
// _tprintf( _T("%hs+%I64X"), pSymbol->Name, symDisplacement ); |
|---|
| 163 |
|
|---|
| 164 |
} |
|---|
| 165 |
else // No symbol found. Print out the logical address instead. |
|---|
| 166 |
{ |
|---|
| 167 |
TCHAR szModule[MAX_PATH] = _T(""); |
|---|
| 168 |
DWORD section = 0, offset = 0; |
|---|
| 169 |
|
|---|
| 170 |
GetLogicalAddress( (PVOID)sf.AddrPC.Offset, |
|---|
| 171 |
szModule, sizeof(szModule), section, offset ); |
|---|
| 172 |
|
|---|
| 173 |
//_tprintf( _T("%04X:%08X %s"), section, offset, szModule ); |
|---|
| 174 |
} |
|---|
| 175 |
|
|---|
| 176 |
// Get the source line for this stack frame entry |
|---|
| 177 |
IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) }; |
|---|
| 178 |
DWORD dwLineDisplacement; |
|---|
| 179 |
if ( SymGetLineFromAddr( m_hProcess, sf.AddrPC.Offset, |
|---|
| 180 |
&dwLineDisplacement, &lineInfo ) ) |
|---|
| 181 |
{ |
|---|
| 182 |
item.fileName = lineInfo.FileName; |
|---|
| 183 |
item.lineNumber = lineInfo.LineNumber; |
|---|
| 184 |
|
|---|
| 185 |
//_tprintf(_T(" %s line %u"),lineInfo.FileName,lineInfo.LineNumber); |
|---|
| 186 |
} |
|---|
| 187 |
|
|---|
| 188 |
//_tprintf( _T("\r\n") ); |
|---|
| 189 |
|
|---|
| 190 |
|
|---|
| 191 |
// Use SymSetContext to get just the locals/params for this frame |
|---|
| 192 |
IMAGEHLP_STACK_FRAME imagehlpStackFrame; |
|---|
| 193 |
imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset; |
|---|
| 194 |
SymSetContext( m_hProcess, &imagehlpStackFrame, 0 ); |
|---|
| 195 |
|
|---|
| 196 |
// Enumerate the locals/parameters |
|---|
| 197 |
SymEnumSymbols( m_hProcess, 0, 0, EnumerateSymbolsCallback, &sf ); |
|---|
| 198 |
|
|---|
| 199 |
//_tprintf( _T("\r\n") ); |
|---|
| 200 |
|
|---|
| 201 |
} |
|---|
| 202 |
|
|---|
| 203 |
} |
|---|
| 204 |
|
|---|
| 205 |
|
|---|
| 206 |
BOOL CALLBACK |
|---|
| 207 |
EnumerateSymbolsCallback( |
|---|
| 208 |
PSYMBOL_INFO pSymInfo, |
|---|
| 209 |
ULONG SymbolSize, |
|---|
| 210 |
PVOID UserContext ) |
|---|
| 211 |
{ |
|---|
| 212 |
|
|---|
| 213 |
char szBuffer[2048]; |
|---|
| 214 |
|
|---|
| 215 |
__try |
|---|
| 216 |
{ |
|---|
| 217 |
if ( FormatSymbolValue( pSymInfo, (STACKFRAME*)UserContext, |
|---|
| 218 |
szBuffer, sizeof(szBuffer) ) ) |
|---|
| 219 |
_tprintf( _T("\t%s\r\n"), szBuffer ); |
|---|
| 220 |
} |
|---|
| 221 |
__except( 1 ) |
|---|
| 222 |
{ |
|---|
| 223 |
_tprintf( _T("punting on symbol %s\r\n"), pSymInfo->Name ); |
|---|
| 224 |
} |
|---|
| 225 |
|
|---|
| 226 |
return TRUE; |
|---|
| 227 |
} |
|---|