NFCallStackImp::callstack_ptr NFCallStackImp::generate(const void* pContext) { if (!m_bInitialized) { _initialize(); } CONTEXT Context; if (pContext != NULL) { ::memcpy_s(&Context, sizeof(CONTEXT), pContext, sizeof(CONTEXT)); } else { ::ZeroMemory(&Context, sizeof(Context)); Context.ContextFlags = CONTEXT_FULL; __asm { call FakeFuncCall FakeFuncCall: pop eax mov Context.Eip, eax mov Context.Ebp, ebp mov Context.Esp, esp } } static const int gc_iMaxStackDepth = 512; QWORD aryStack[gc_iMaxStackDepth] = {0}; // 由于_stackwalk内部使用SEH 因此不能在其内部使用C++类 _stackwalk(aryStack, gc_iMaxStackDepth, &Context); callstack_ptr spCallStack(new NFCallStack()); for (int i = 0; i < gc_iMaxStackDepth && aryStack[i] != 0; ++i) { func_name name = _getfuncname(aryStack[i]); spCallStack->mspImp->m_lstFunc.push_back(name); } return spCallStack; }
list<stack_line_info> get_stack_list(size_t maxDepth, size_t offset, bool module, bool symbolName) { assert(maxDepth <= 32); QWORD trace[33]; CONTEXT context; ::ZeroMemory(&context, sizeof(context)); context.ContextFlags = CONTEXT_FULL; #ifdef _WIN64 get_bp_sp_ip((void**)&context.Rbp, (void**)&context.Rsp, (void**)&context.Rip); #else get_bp_sp_ip((void**)&context.Ebp, (void**)&context.Esp, (void**)&context.Eip); #endif size_t depths = _stackwalk(trace, maxDepth+1, &context); list<stack_line_info> imageList; HANDLE hProcess = ::GetCurrentProcess(); for (size_t i = 1 + offset; i < depths; i++) { stack_line_info stackResult; { DWORD symbolDisplacement = 0; IMAGEHLP_LINE64 imageHelpLine; imageHelpLine.SizeOfStruct = sizeof(imageHelpLine); if (::SymGetLineFromAddr64(hProcess, trace[i], &symbolDisplacement, &imageHelpLine)) { stackResult.file = string(imageHelpLine.FileName, check_file_name(imageHelpLine.FileName)); memset(imageHelpLine.FileName, 0, stackResult.file.size() + 1); stackResult.line = (int)imageHelpLine.LineNumber; } else { stackResult.line = -1; } } if (symbolName) { static const int maxNameLength = 1024; char symbolBf[sizeof(IMAGEHLP_SYMBOL64)+maxNameLength] = { 0 }; PIMAGEHLP_SYMBOL64 symbol; DWORD64 symbolDisplacement64 = 0; symbol = (PIMAGEHLP_SYMBOL64)symbolBf; symbol->SizeOfStruct = sizeof(symbolBf); symbol->MaxNameLength = maxNameLength; if (::SymGetSymFromAddr64( hProcess, trace[i], &symbolDisplacement64, symbol) ) { stackResult.symbolName = symbol->Name; } else { stackResult.symbolName = "unknow..."; } } if (module) { IMAGEHLP_MODULE64 imageHelpModule; imageHelpModule.SizeOfStruct = sizeof(imageHelpModule); if (::SymGetModuleInfo64(hProcess, trace[i], &imageHelpModule)) { stackResult.module = string(imageHelpModule.ImageName, check_file_name(imageHelpModule.ImageName)); memset(imageHelpModule.ImageName, 0, stackResult.module.size() + 1); } } imageList.push_back(std::move(stackResult)); } return std::move(imageList); }