00001
00002
00003 #ifndef _GSYMLOOKUP_H_
00004 #define _GSYMLOOKUP_H_
00005
00006 #ifdef WIN32
00007 #include "ImageHlp.h"
00008 #include <direct.h>
00009 #include <stdio.h>
00010 #undef _T
00011 #include <tchar.h>
00012
00013 #if _MSC_VER < 1300
00014 typedef DWORD DWORD_PTR;
00015 #define __w64
00016 #endif
00017
00018 #ifdef _UNICODE
00019 #define TCHAR_FORMAT "%S"
00020 #else
00021 #define TCHAR_FORMAT "%s"
00022 #endif
00023
00024 typedef BOOL (__stdcall *SYMINITIALIZEPROC)( HANDLE, LPSTR, BOOL );
00025 typedef BOOL (__stdcall *SYMCLEANUPPROC)( HANDLE );
00026
00027 typedef BOOL (__stdcall * STACKWALKPROC)
00028 ( DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID,
00029 PREAD_PROCESS_MEMORY_ROUTINE,PFUNCTION_TABLE_ACCESS_ROUTINE,
00030 PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE );
00031
00032 typedef LPVOID (__stdcall *SYMFUNCTIONTABLEACCESSPROC)( HANDLE, DWORD );
00033
00034 typedef DWORD (__stdcall *SYMGETMODULEBASEPROC)( HANDLE, DWORD );
00035
00036 typedef BOOL (__stdcall *SYMGETSYMFROMADDRPROC)
00037 ( HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL );
00038
00039 typedef BOOL (__stdcall *proc_SymGetLineFromAddr)( HANDLE hProcess,
00040 DWORD dwAddr,
00041 PDWORD pdwDisplacement,
00042 PIMAGEHLP_LINE Line);
00043
00044 typedef DWORD (__stdcall *proc_SymGetOptions)(VOID);
00045 typedef DWORD (__stdcall *proc_SymSetOptions)(DWORD SymOptions);
00046
00048 class GSymLookup
00049 {
00050 HMODULE DbgHelp;
00051 HANDLE hProcess;
00052
00053 SYMINITIALIZEPROC SymInitialize;
00054 SYMCLEANUPPROC SymCleanup;
00055 STACKWALKPROC StackWalk;
00056 SYMFUNCTIONTABLEACCESSPROC SymFunctionTableAccess;
00057 SYMGETMODULEBASEPROC SymGetModuleBase;
00058 SYMGETSYMFROMADDRPROC SymGetSymFromAddr;
00059 proc_SymGetLineFromAddr SymGetLineFromAddr;
00060 proc_SymGetOptions SymGetOptions;
00061 proc_SymSetOptions SymSetOptions;
00062
00063 bool InitOk;
00064
00065 public:
00066 typedef __w64 unsigned Addr;
00067
00068 GSymLookup()
00069 {
00070 hProcess = GetCurrentProcess();
00071 InitOk = 0;
00072 DbgHelp = LoadLibrary(_T("dbghelp.dll"));
00073 if (DbgHelp)
00074 {
00075 SymInitialize = (SYMINITIALIZEPROC) GetProcAddress(DbgHelp, "SymInitialize");
00076 SymCleanup = (SYMCLEANUPPROC) GetProcAddress(DbgHelp, "SymCleanup");
00077 StackWalk = (STACKWALKPROC) GetProcAddress(DbgHelp, "StackWalk");
00078 SymFunctionTableAccess = (SYMFUNCTIONTABLEACCESSPROC) GetProcAddress(DbgHelp, "SymFunctionTableAccess");
00079 SymGetModuleBase = (SYMGETMODULEBASEPROC) GetProcAddress(DbgHelp, "SymGetModuleBase");
00080 SymGetSymFromAddr = (SYMGETSYMFROMADDRPROC) GetProcAddress(DbgHelp, "SymGetSymFromAddr");
00081 SymGetLineFromAddr = (proc_SymGetLineFromAddr) GetProcAddress(DbgHelp, "SymGetLineFromAddr");
00082 SymGetOptions = (proc_SymGetOptions) GetProcAddress(DbgHelp, "SymGetOptions");
00083 SymSetOptions = (proc_SymSetOptions) GetProcAddress(DbgHelp, "SymSetOptions");
00084
00085 DWORD dwOpts = SymGetOptions();
00086 DWORD Set = SymSetOptions(dwOpts | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST);
00087
00088 char s[256];
00089 _getcwd(s, sizeof(s));
00090
00091 char *path = getenv("path");
00092 int pathlen = (int)strlen(path);
00093
00094 int len = pathlen + (int)strlen(s) + 256;
00095 char *all = (char*)malloc(len);
00096 if (all)
00097 {
00098 #if _MSC_VER >= 1300
00099 strcpy_s(all, len, path);
00100 #else
00101 strcpy(all, path);
00102 #endif
00103
00104 if (all[strlen(all)-1] != ';')
00105 {
00106 #if _MSC_VER >= 1300
00107 strcat_s(all, len, ";");
00108 #else
00109 strcat(all, ";");
00110 #endif
00111 }
00112
00113 #ifdef _DEBUG
00114 char *Mode = "Debug";
00115 #else
00116 char *Mode = "Release";
00117 #endif
00118
00119 #if _MSC_VER >= 1300
00120 sprintf_s(all+strlen(all), len-strlen(all), "%s\\%s", s, Mode);
00121 #else
00122 sprintf(all+strlen(all), "%s\\%s", s, Mode);
00123 #endif
00124
00125 InitOk = SymInitialize(hProcess, all, true) != 0;
00126 free(all);
00127 }
00128 }
00129 }
00130
00131 ~GSymLookup()
00132 {
00133 if (DbgHelp)
00134 {
00135 SymCleanup(hProcess);
00136 FreeLibrary(DbgHelp);
00137 }
00138 }
00139
00140 bool GetStatus()
00141 {
00142 return InitOk;
00143 }
00144
00147 bool Lookup
00148 (
00150 char *buf,
00152 int buffer_len,
00154 Addr *Ip,
00156 int IpLen
00157 )
00158 {
00159 if (!buf || buffer_len < 1 || !Ip || IpLen < 1)
00160 return false;
00161
00162 #if _MSC_VER >= 1300
00163 #define Sprintf sprintf_s
00164 #else
00165 #define Sprintf snprintf
00166 #endif
00167
00168 bool Status = true;
00169 char *buf_end = buf + buffer_len;
00170 for (int i=0; i<IpLen; i++)
00171 {
00172 MEMORY_BASIC_INFORMATION mbi;
00173 VirtualQuery((void*)Ip[i], &mbi, sizeof(mbi));
00174 HINSTANCE Pid = (HINSTANCE)mbi.AllocationBase;
00175
00176 TCHAR module[256] = _T("");
00177 if (GetModuleFileName(Pid, module, sizeof(module)))
00178 {
00179 BYTE symbolBuffer[ sizeof(IMAGEHLP_SYMBOL) + 512 ];
00180 PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
00181 DWORD symDisplacement = 0;
00182 IMAGEHLP_LINE Line;
00183
00184
00185 DWORD_PTR Offset = (DWORD_PTR)Ip[i] - (DWORD_PTR)Pid;
00186
00187 pSymbol->SizeOfStruct = sizeof(symbolBuffer);
00188 pSymbol->MaxNameLength = 512;
00189 memset(&Line, 0, sizeof(Line));
00190 Line.SizeOfStruct = sizeof(Line);
00191
00192 TCHAR *mod = _tcsrchr(module, '\\');
00193 if (mod) mod++;
00194 else mod = module;
00195
00196 bool found_addr = false;
00197 if (SymGetSymFromAddr(hProcess, (DWORD_PTR)Ip[i], &symDisplacement, pSymbol))
00198 {
00199 if (SymGetLineFromAddr(hProcess, (DWORD_PTR)Ip[i], &symDisplacement, &Line))
00200 {
00201 int Ch = Sprintf(buf, buf_end-buf, "%08.8x: "TCHAR_FORMAT", %s:%i", Ip[i], mod, Line.FileName, Line.LineNumber);
00202 if (Ch > 0)
00203 buf += Ch;
00204 else
00205 Status = false;
00206 found_addr = true;
00207 }
00208 else if (pSymbol->Name[0] != '$')
00209 {
00210 int Ch = Sprintf(buf, buf_end-buf, "%08.8x: "TCHAR_FORMAT ", %s+0x%x", Ip[i], mod, pSymbol->Name, symDisplacement);
00211 if (Ch > 0)
00212 buf += Ch;
00213 else
00214 Status = false;
00215 found_addr = true;
00216 }
00217 }
00218
00219 if (!found_addr)
00220 {
00221 int Ch = Sprintf(buf, buf_end-buf, "%08.8x: "TCHAR_FORMAT, Ip[i], mod);
00222 if (Ch > 0)
00223 buf += Ch;
00224 else
00225 Status = false;
00226 }
00227 }
00228 else
00229 {
00230 int Ch = Sprintf(buf, buf_end-buf, "%08.8x: unknown module", Ip[i]);
00231 if (Ch > 0)
00232 buf += Ch;
00233 else
00234 Status = false;
00235 }
00236
00237 int Ch = Sprintf(buf, buf_end-buf, "\r\n");
00238 if (Ch > 0)
00239 buf += Ch;
00240 }
00241
00242 return Status;
00243 }
00244
00245 int BackTrace(long Eip, long Ebp, Addr *addr, int len)
00246 {
00247 if (!addr || len < 1)
00248 return 0;
00249
00250 int i = 0;
00251
00252
00253 Addr RegEbp = Ebp;
00254 if (!Ebp)
00255 {
00256 memset(addr, 0, sizeof(Addr) * len);
00257 #ifdef _MSC_VER
00258
00259 _asm {
00260 mov eax, ebp
00261 mov RegEbp, eax
00262 }
00263 #else
00264
00265 asm("movl %%ebp, %%eax;"
00266 "movl %%eax, %0;"
00267 :"=r"(RegEbp)
00268 :
00269 :"%eax"
00270 );
00271 #endif
00272 }
00273
00274 if (Eip)
00275 addr[i++] = Eip;
00276
00277 for (; i<len; i++)
00278 {
00279 if ((RegEbp & 3) != 0 ||
00280 IsBadReadPtr( (void*)RegEbp, 8 ))
00281 break;
00282
00283
00284 addr[i] = (Addr) *((uint8**)RegEbp + 1);
00285 RegEbp = *(Addr*)RegEbp;
00286 }
00287
00288 return i;
00289 }
00290 };
00291 #endif
00292
00293 #endif