43 #define NCBI_USE_ERRCODE_X Corelib_Stack
49 #define lenof(a) (sizeof(a) / sizeof((a)[0]))
50 #define MAXNAMELEN 1024
51 #define IMGSYMLEN (sizeof IMAGEHLP_SYMBOL)
52 #define TTBUFLEN 65535
69 #define MAX_MODULE_NAME32 255
70 #define TH32CS_SNAPMODULE 0x00000008
94 typedef HANDLE (__stdcall *FCreateToolhelp32Snapshot)(
WORD dwFlags,
104 FCreateToolhelp32Snapshot CreateToolhelp32Snapshot;
109 const char *dllname[] = {
115 const char* libname = dllname[0];
116 unique_ptr<CDll> dll;
120 CreateToolhelp32Snapshot =
121 dll->GetEntryPoint_Func(
"CreateToolhelp32Snapshot",
122 &CreateToolhelp32Snapshot);
124 dll->GetEntryPoint_Func(
"Module32First", &Module32First);
126 dll->GetEntryPoint_Func(
"Module32Next", &Module32Next);
128 if (CreateToolhelp32Snapshot && Module32First && Module32Next) {
133 if ( !CreateToolhelp32Snapshot ) {
135 "toolhelp32 functions not available");
139 if (handle == (
HANDLE) -1) {
141 "failed to create toolhelp32 snapshot");
146 bool done = !Module32First(handle, &me) ?
true :
false;
154 modules.push_back(e);
156 done = !Module32Next(handle, &me) ?
true :
false;
161 return modules.size() != 0;
163 catch (exception& e) {
164 ERR_POST_X(1,
Error <<
"Error retrieving toolhelp32 symbols: " << e.what());
198 typedef DWORD (__stdcall *FGetModuleBaseNameA)(
HANDLE hProcess,
203 typedef BOOL (__stdcall *FGetModuleInformation)(
HANDLE hProcess,
210 FGetModuleBaseNameA GetModuleBaseNameA;
211 FGetModuleInformation GetModuleInformation;
218 &EnumProcessModules);
219 GetModuleFileNameExA =
221 &GetModuleFileNameExA);
224 &GetModuleBaseNameA);
225 GetModuleInformation =
227 &GetModuleInformation);
229 if ( !EnumProcessModules ||
230 !GetModuleFileNameExA ||
231 !GetModuleBaseNameA ||
232 !GetModuleInformation ) {
236 vector<HMODULE> modules;
237 modules.resize(4096);
241 if ( !EnumProcessModules(hProcess,
243 modules.size()*
sizeof(HMODULE),
246 "EnumProcessModules() failed");
249 if ( needed > modules.size() *
sizeof(HMODULE)) {
251 string(
"More than ") +
256 needed /=
sizeof(HMODULE);
257 for (
size_t i = 0;
i < needed; ++
i) {
261 GetModuleInformation(hProcess, modules[
i], &mi,
sizeof(mi));
270 GetModuleFileNameExA(hProcess, modules[
i], tt,
sizeof(tt));
275 GetModuleBaseNameA(hProcess, modules[
i], tt,
sizeof(tt));
283 catch (exception& e) {
322 HANDLE curr_proc = GetCurrentProcess();
328 if (GetModuleFileNameA(0,
const_cast<char*
>(
tmp.data()),
330 string::size_type pos =
tmp.find_last_of(
"\\/");
331 if (pos != string::npos) {
334 search_path =
tmp +
';' + search_path;
337 const char* ptr = getenv(
"_NT_SYMBOL_PATH");
340 search_path =
tmp +
';' + search_path;
342 ptr = getenv(
"_NT_ALTERNATE_SYMBOL_PATH");
345 search_path =
tmp +
';' + search_path;
347 ptr = getenv(
"SYSTEMROOT");
350 search_path =
tmp +
';' + search_path;
354 if ( !SymInitialize(curr_proc,
355 const_cast<char*
>(search_path.c_str()),
361 DWORD symOptions = SymGetOptions();
362 symOptions |= SYMOPT_LOAD_LINES;
363 symOptions &= ~SYMOPT_UNDNAME;
364 SymSetOptions(symOptions);
369 catch (exception& e) {
375 <<
"Unknown error initializing symbols for stack trace.");
382 SymCleanup(GetCurrentProcess());
389 DWORD pid = GetCurrentProcessId();
403 DWORD module_addr = SymLoadModule(
proc, 0,
404 const_cast<char*
>(it->imageName.c_str()),
405 const_cast<char*
>(it->moduleName.c_str()),
406 it->baseAddress, it->size);
407 if ( !module_addr ) {
411 _TRACE(
"Loaded symbols from " << it->moduleName);
437 #define GET_CURRENT_CONTEXT(c, contextFlags) \
439 memset(&c, 0, sizeof(CONTEXT)); \
440 c.ContextFlags = contextFlags; \
443 __asm mov c.Eip, eax \
444 __asm mov c.Ebp, ebp \
445 __asm mov c.Esp, esp \
449 #pragma warning( push )
450 #pragma warning( disable : 4748)
454 HANDLE curr_proc = GetCurrentProcess();
455 HANDLE thread = GetCurrentThread();
458 DWORD img_type = IMAGE_FILE_MACHINE_I386;
466 memset(&s, 0,
sizeof s);
467 s.AddrPC.Offset = c.Eip;
468 s.AddrPC.Mode = AddrModeFlat;
469 s.AddrFrame.Offset = c.Ebp;
470 s.AddrFrame.Mode = AddrModeFlat;
471 s.AddrStack.Offset = c.Esp;
472 s.AddrStack.Mode = AddrModeFlat;
476 for (
size_t frame = 0; frame <= max_depth; ++frame) {
478 if ( !StackWalk(img_type, curr_proc, thread, &s, &c,
NULL,
479 SymFunctionTableAccess,
490 if ( !s.AddrPC.Offset ) {
497 catch (exception& e) {
505 #pragma warning( pop )
521 HANDLE curr_proc = GetCurrentProcess();
523 IMAGEHLP_SYMBOL *pSym =
NULL;
542 sf_info.func =
"<cannot get function name for this address>";
544 if ( !SymGetSymFromAddr(curr_proc,
548 stack.push_back(sf_info);
558 UnDecorateSymbolName(pSym->Name, undFullName,
561 sf_info.func = undFullName;
564 if (SymGetLineFromAddr(curr_proc,
568 sf_info.file =
Line.FileName;
569 sf_info.line =
Line.LineNumber;
571 _TRACE(
"failed to get line number for " << sf_info.func);
575 if ( !SymGetModuleInfo(curr_proc,
581 sf_info.module =
Module.ModuleName;
582 sf_info.module +=
"[";
583 sf_info.module +=
Module.ImageName;
584 sf_info.module +=
"]";
587 stack.push_back(sf_info);
590 catch (exception& e) {
backward::StackTrace TStack
void Expand(CStackTrace::TStack &stack)
vector< TStackFrame > TStack
list< SStackFrameInfo > TStack
static unsigned int s_GetStackTraceMaxDepth(void)
set< string > TLoadedModules
iterator_bool insert(const value_type &val)
const_iterator find(const key_type &key) const
const_iterator end() const
parent_type::const_iterator const_iterator
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
TFunc GetEntryPoint_Func(const string &name, TFunc *func)
Get DLLs entry point (function).
void Error(CExceptionArgs_Base &args)
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
static string GetCwd(void)
Get the current working directory.
#define END_NCBI_SCOPE
End previously defined NCBI scope.
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
static string SizetToString(size_t value, TNumToStringFlags flags=0, int base=10)
Convert size_t to string.
#define HANDLE
An abstraction for a file handle.
Definition of all error codes used in corelib (xncbi.lib).
BOOL(WINAPI * FModule32Next)(HANDLE hSnapshot, LPMODULEENTRY32_A lpme)
BOOL(WINAPI * FEnumProcessModules)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded)
DWORD(WINAPI * FGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize)
BOOL(WINAPI * FModule32First)(HANDLE hSnapshot, LPMODULEENTRY32_A lpme)
Static variables safety - create on demand, destroy on application termination.
struct _MODULEINFO MODULEINFO
vector< SModuleEntry > TModules
static bool s_FillModuleListPSAPI(TModules &mods, DWORD pid, HANDLE hProcess)
MODULEENTRY32 * LPMODULEENTRY32
static bool s_FillModuleListTH32(TModules &modules, DWORD pid)
MODULEENTRY32 * PMODULEENTRY32
#define TH32CS_SNAPMODULE
static CSafeStatic< CSymbolGuard > s_SymbolGuard
#define GET_CURRENT_CONTEXT(c, contextFlags)
static bool s_FillModuleList(TModules &modules, DWORD pid, HANDLE hProcess)
struct _MODULEINFO * LPMODULEINFO
struct tagMODULEENTRY32 MODULEENTRY32
TModules::iterator ModuleListIter
#define MAX_MODULE_NAME32
Define class Dll and for Portable DLL handling.
Structure for holding stack trace data.