root/trunk/ElephantDebugApi/edbgfunctions.cpp

Revision 5, 6.9 kB (checked in by qbert, 3 years ago)

Initial ( and last :( ) commit

Line 
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 }
Note: See TracBrowser for help on using the browser.