mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-16 21:42:43 +00:00
* build: clear 2 warnings - cast the NSTextField the class check already proved
mainframe_text_field is NSTextField* and was assigned a bare NSView*, which
Clang reports as -Wincompatible-pointer-types. Both assignments sit inside
if ([viewObject class] == [NSTextField self]), so the runtime type is already
guaranteed, and the line above the second one casts the same variable the same
way to call setTextColor. macOS only, since nothing else compiles this file.
* build: clear 6 warning categories from the clang-cl inventory
-Wmissing-braces (9). Aggregates whose first member is itself an aggregate.
GUID's fourth member is BYTE[8], so the trailing eight bytes take their own
braces. The others were reaching for zero-initialization with {0} and say {}
now. bbs_3mf's backup Task ends in an anonymous union, which needs braces of
its own; those braces initialize the union's first member rather than the one
named at the call site, so the RemoveBackup site says so in a comment.
-Wmacro-redefined (11). SendMultiMachinePage.hpp defines five names that
Preferences.hpp, PresetBundleDialog.hpp, ExportPresetBundleDialog.hpp and
TroubleshootDialog.hpp also define with different values, so the value in
force depended on include order. All nine of this file's DESIGN_ macros take
the SEND_ prefix it already uses for its own macros, values unchanged, so a
DESIGN_ name added elsewhere later cannot collide with it again. They read as
one page-local palette, a 900 to 400 gray ramp plus sizes, so the four with
no current readers stay: dropping them would leave gaps in a named scale. test_marchingsquares.cpp defines NOMINMAX,
which libslic3r already passes as a PUBLIC compile definition, so it takes
the #ifndef guard the other suites use.
-Wbraced-scalar-init (3). Two PushStyleVar calls resolve to the float
overload, so the braces were initializing a scalar. ConfigOptionFloatsNullable
already takes an initializer_list, so the inner braces did the same thing.
-Wmicrosoft-goto (2). Both gotos in copy_file_gui jump forward over the
initialization of size, dwRead and dwWrite, which only MSVC accepts. Those
declarations move up to join the others at the top of the function.
-Wunused-private-field (3). Every use of ColourPicker's m_clrData and
m_picker_widget is behind !defined(__linux__), so on Linux they are written
and never read; the members now carry the same guard. ParamsPanel's
m_size_move is read nowhere. Tab has its own, which is the one Tab.cpp uses.
-Wnonportable-include-path (2). BaseException.h asked for "stackwalker.h"
and the file on disk is StackWalker.h.
550 lines
16 KiB
C++
550 lines
16 KiB
C++
#include "StackWalker.h"
|
|
#include <strsafe.h>
|
|
//#include <atlconv.h>
|
|
#include <dbghelp.h>
|
|
#pragma comment(lib, "version.lib")
|
|
#pragma comment( lib, "dbghelp.lib" )
|
|
|
|
CStackWalker::CStackWalker(HANDLE hProcess, WORD wPID, LPCTSTR lpSymbolPath):
|
|
m_hProcess(hProcess),
|
|
m_wPID(wPID),
|
|
m_bSymbolLoaded(FALSE),
|
|
m_lpszSymbolPath(NULL)
|
|
{
|
|
if (NULL != lpSymbolPath)
|
|
{
|
|
size_t dwLength = 0;
|
|
StringCchLength(lpSymbolPath, MAX_SYMBOL_PATH, &dwLength);
|
|
m_lpszSymbolPath = new TCHAR[dwLength + 1];
|
|
ZeroMemory(m_lpszSymbolPath, sizeof(TCHAR) * (dwLength + 1));
|
|
StringCchCopy(m_lpszSymbolPath, dwLength, lpSymbolPath);
|
|
}
|
|
|
|
}
|
|
|
|
CStackWalker::~CStackWalker(void)
|
|
{
|
|
if (NULL != m_lpszSymbolPath)
|
|
{
|
|
delete[] m_lpszSymbolPath;
|
|
}
|
|
|
|
if (m_bSymbolLoaded)
|
|
{
|
|
SymCleanup(m_hProcess);
|
|
}
|
|
}
|
|
|
|
BOOL CStackWalker::LoadSymbol()
|
|
{
|
|
//USES_CONVERSION;
|
|
//只加载一次
|
|
if(m_bSymbolLoaded)
|
|
{
|
|
return m_bSymbolLoaded;
|
|
}
|
|
|
|
if (NULL != m_lpszSymbolPath)
|
|
{
|
|
|
|
m_bSymbolLoaded = SymInitialize(m_hProcess, textconv_helper::T2A_(m_lpszSymbolPath), FALSE);
|
|
return m_bSymbolLoaded;
|
|
}
|
|
|
|
//添加当前程序路径
|
|
TCHAR szSymbolPath[MAX_SYMBOL_PATH] = _T("");
|
|
StringCchCopy(szSymbolPath, MAX_SYMBOL_PATH, _T(".;"));
|
|
|
|
//添加程序所在目录
|
|
TCHAR szTemp[MAX_PATH] = _T("");
|
|
if (GetCurrentDirectory(MAX_PATH, szTemp) > 0)
|
|
{
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
|
|
}
|
|
|
|
//添加程序主模块所在路径
|
|
ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
|
|
if (GetModuleFileName(NULL, szTemp, MAX_PATH) > 0)
|
|
{
|
|
size_t sLength = 0;
|
|
StringCchLength(szTemp, MAX_PATH, &sLength);
|
|
for (int i = sLength; i >= 0; i--)
|
|
{
|
|
if (szTemp[i] == _T('\\') || szTemp[i] == _T('/') || szTemp[i] == _T(':'))
|
|
{
|
|
szTemp[i] = _T('\0');
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
|
|
|
|
ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
|
|
if (GetEnvironmentVariable(_T("_NT_SYMBOL_PATH"), szTemp, MAX_PATH) > 0)
|
|
{
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
|
|
}
|
|
|
|
ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
|
|
if (GetEnvironmentVariable(_T("_NT_ALTERNATE_SYMBOL_PATH"), szTemp, MAX_PATH) > 0)
|
|
{
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
|
|
}
|
|
|
|
ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
|
|
if (GetEnvironmentVariable(_T("SYSTEMROOT"), szTemp, MAX_PATH) > 0)
|
|
{
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
|
|
// also add the "system32"-directory:
|
|
StringCchCat(szTemp, MAX_PATH, _T("\\system32"));
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T(";"));
|
|
}
|
|
|
|
ZeroMemory(szTemp, MAX_PATH * sizeof(TCHAR));
|
|
if (GetEnvironmentVariable(_T("SYSTEMDRIVE"), szTemp, MAX_PATH) > 0)
|
|
{
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T("SRV*"));
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, szTemp);
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T("\\websymbols"));
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T("*http://msdl.microsoft.com/download/symbols;"));
|
|
}
|
|
else
|
|
{
|
|
StringCchCat(szSymbolPath, MAX_SYMBOL_PATH, _T("SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols;"));
|
|
}
|
|
|
|
size_t sLength = 0;
|
|
StringCchLength(szSymbolPath, MAX_SYMBOL_PATH, &sLength);
|
|
if (sLength > 0)
|
|
{
|
|
m_lpszSymbolPath = new TCHAR[sLength + 1];
|
|
ZeroMemory(m_lpszSymbolPath, sizeof(TCHAR) * (sLength + 1));
|
|
StringCchCopy(m_lpszSymbolPath, sLength, szSymbolPath);
|
|
}
|
|
|
|
if (NULL != m_lpszSymbolPath)
|
|
{
|
|
m_bSymbolLoaded = SymInitialize(m_hProcess, textconv_helper::T2A_(m_lpszSymbolPath), TRUE); //这里设置为TRUE,让它在初始化符号表的同时加载符号表
|
|
}
|
|
|
|
DWORD symOptions = SymGetOptions();
|
|
symOptions |= SYMOPT_LOAD_LINES;
|
|
symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
|
|
symOptions |= SYMOPT_DEBUG;
|
|
SymSetOptions(symOptions);
|
|
|
|
return m_bSymbolLoaded;
|
|
}
|
|
|
|
LPMODULE_INFO CStackWalker::GetLoadModules()
|
|
{
|
|
LPMODULE_INFO pHead = GetModulesTH32();
|
|
if (NULL == pHead)
|
|
{
|
|
pHead = GetModulesPSAPI();
|
|
}
|
|
|
|
return pHead;
|
|
}
|
|
|
|
void CStackWalker::FreeModuleInformations(LPMODULE_INFO pmi)
|
|
{
|
|
LPMODULE_INFO head = pmi;
|
|
while (NULL != head)
|
|
{
|
|
pmi = pmi->pNext;
|
|
delete head;
|
|
head = pmi;
|
|
}
|
|
}
|
|
|
|
LPMODULE_INFO CStackWalker::GetModulesTH32()
|
|
{
|
|
//这里为了防止加载Toolhelp.dll 影响最终结果,所以采用动态加载的方式
|
|
LPMODULE_INFO pHead = NULL;
|
|
LPMODULE_INFO pTail = pHead;
|
|
|
|
typedef HANDLE (WINAPI *pfnCreateToolhelp32Snapshot)(DWORD dwFlags, DWORD th32ProcessID);
|
|
typedef BOOL (WINAPI *pfnModule32First)(HANDLE hSnapshot, LPMODULEENTRY32 lpme );
|
|
typedef BOOL (WINAPI *pfnModule32Next)(HANDLE hSnapshot, LPMODULEENTRY32 lpme );
|
|
|
|
const TCHAR* dllname[] = {_T("kernel32.dll"), _T("tlhelp32.dll")};
|
|
HINSTANCE hToolhelp = NULL;
|
|
|
|
pfnCreateToolhelp32Snapshot CreateToolhelp32Snapshot = NULL;
|
|
pfnModule32First Module32First = NULL;
|
|
pfnModule32Next Module32Next = NULL;
|
|
|
|
HANDLE hSnap;
|
|
MODULEENTRY32 me;
|
|
me.dwSize = sizeof(me);
|
|
BOOL keepGoing;
|
|
size_t i;
|
|
|
|
for (i = 0; i < (sizeof(dllname) / sizeof(dllname[0])); i++)
|
|
{
|
|
hToolhelp = LoadLibrary(dllname[i]);
|
|
if (hToolhelp == NULL)
|
|
continue;
|
|
CreateToolhelp32Snapshot = (pfnCreateToolhelp32Snapshot)GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot");
|
|
#ifdef UNICODE
|
|
Module32First = (pfnModule32First)GetProcAddress(hToolhelp, "Module32FirstW");
|
|
Module32Next = (pfnModule32Next)GetProcAddress(hToolhelp, "Module32NextW");
|
|
#else
|
|
Module32First = (pfnModule32First)GetProcAddress(hToolhelp, "Module32FirstA");
|
|
Module32Next = (pfnModule32Next)GetProcAddress(hToolhelp, "Module32NextA");
|
|
#endif
|
|
|
|
if ((CreateToolhelp32Snapshot != NULL) && (Module32First != NULL) && (Module32Next != NULL))
|
|
break;
|
|
|
|
FreeLibrary(hToolhelp);
|
|
hToolhelp = NULL;
|
|
}
|
|
|
|
if (hToolhelp == NULL)
|
|
return pHead;
|
|
|
|
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, m_wPID);
|
|
|
|
if (hSnap == INVALID_HANDLE_VALUE)
|
|
{
|
|
FreeLibrary(hToolhelp);
|
|
return pHead;
|
|
}
|
|
|
|
keepGoing = Module32First(hSnap, &me);
|
|
|
|
while (keepGoing)
|
|
{
|
|
LPMODULE_INFO pmi = new MODULE_INFO;
|
|
ZeroMemory(pmi, sizeof(MODULE_INFO));
|
|
|
|
pmi->dwModSize = me.modBaseSize;
|
|
pmi->ModuleAddress = (DWORD64)me.modBaseAddr;
|
|
StringCchCopy(pmi->szModuleName, MAX_MODULE_NAME32, me.szModule);
|
|
StringCchCopy(pmi->szModulePath, MAX_PATH, me.szExePath);
|
|
GetModuleInformation(pmi);
|
|
if (pHead == NULL)
|
|
{
|
|
pHead = pmi;
|
|
pTail = pHead;
|
|
}else
|
|
{
|
|
pTail->pNext = pmi;
|
|
pTail = pmi;
|
|
}
|
|
|
|
keepGoing = Module32Next(hSnap, &me);
|
|
}
|
|
|
|
CloseHandle(hSnap);
|
|
FreeLibrary(hToolhelp);
|
|
return pHead;
|
|
}
|
|
|
|
LPMODULE_INFO CStackWalker::GetModulesPSAPI()
|
|
{
|
|
LPMODULE_INFO pHead = NULL;
|
|
LPMODULE_INFO pTail = pHead;
|
|
typedef BOOL(WINAPI *pfnEnumProcessModules)(HANDLE hProcess, HMODULE * lphModule, DWORD cb,LPDWORD lpcbNeeded);
|
|
typedef DWORD(WINAPI *pfnGetModuleFileNameEx)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
|
|
typedef DWORD(WINAPI *pfnGetModuleBaseName)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
|
|
typedef BOOL(WINAPI *pfnGetModuleInformation)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize);
|
|
|
|
HINSTANCE hPsapi;
|
|
pfnEnumProcessModules EnumProcessModules = NULL;
|
|
pfnGetModuleFileNameEx GetModuleFileNameEx = NULL;
|
|
pfnGetModuleBaseName GetModuleBaseName = NULL;
|
|
pfnGetModuleInformation GetModuleInformation = NULL;
|
|
|
|
DWORD i;
|
|
//ModuleEntry e;
|
|
DWORD cbNeeded;
|
|
MODULEINFO mi;
|
|
HMODULE* hMods = NULL;
|
|
TCHAR szModuleName[MAX_MODULE_NAME32 + 1] = _T("");
|
|
TCHAR szModulePath[MAX_PATH] = _T("");
|
|
|
|
hPsapi = LoadLibrary(_T("psapi.dll"));
|
|
if (hPsapi == NULL)
|
|
{
|
|
return pHead;
|
|
}
|
|
|
|
EnumProcessModules = (pfnEnumProcessModules)GetProcAddress(hPsapi, "EnumProcessModules");
|
|
#ifdef UNICODE
|
|
GetModuleFileNameEx = (pfnGetModuleFileNameEx)GetProcAddress(hPsapi, "GetModuleFileNameExW");
|
|
GetModuleBaseName = (pfnGetModuleBaseName)GetProcAddress(hPsapi, "GetModuleBaseNameW");
|
|
#else
|
|
GetModuleFileNameEx = (pfnGetModuleFileNameEx)GetProcAddress(hPsapi, "GetModuleFileNameExA");
|
|
GetModuleBaseName = (pfnGetModuleBaseName)GetProcAddress(hPsapi, "GetModuleBaseNameA");
|
|
#endif
|
|
GetModuleInformation = (pfnGetModuleInformation)GetProcAddress(hPsapi, "GetModuleInformation");
|
|
if ((EnumProcessModules == NULL) || (GetModuleFileNameEx == NULL) || (GetModuleBaseName == NULL) || (GetModuleInformation == NULL))
|
|
{
|
|
FreeLibrary(hPsapi);
|
|
return pHead;
|
|
}
|
|
|
|
EnumProcessModules(m_hProcess, hMods, 0, &cbNeeded);
|
|
hMods = new HMODULE[cbNeeded / sizeof(HMODULE)];
|
|
ASSERT(NULL != hMods);
|
|
ZeroMemory(hMods, cbNeeded);
|
|
|
|
if (!EnumProcessModules(m_hProcess, hMods, cbNeeded, &cbNeeded))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
for (i = 0; i < cbNeeded / sizeof(HMODULE); i++)
|
|
{
|
|
GetModuleInformation(m_hProcess, hMods[i], &mi, sizeof(mi));
|
|
GetModuleFileNameEx(m_hProcess, hMods[i], szModulePath, MAX_PATH);
|
|
GetModuleBaseName(m_hProcess, hMods[i], szModuleName, MAX_MODULE_NAME32);
|
|
LPMODULE_INFO pmi = new MODULE_INFO;
|
|
ZeroMemory(pmi, sizeof(MODULE_INFO));
|
|
pmi->dwModSize = mi.SizeOfImage;
|
|
pmi->ModuleAddress = (DWORD64)mi.lpBaseOfDll;
|
|
StringCchCopy(pmi->szModuleName, MAX_MODULE_NAME32, szModuleName);
|
|
StringCchCopy(pmi->szModulePath, MAX_PATH, szModulePath);
|
|
this->GetModuleInformation(pmi);
|
|
if (pHead == NULL)
|
|
{
|
|
pHead = pmi;
|
|
pTail = pHead;
|
|
}else
|
|
{
|
|
pTail->pNext = pmi;
|
|
pTail = pmi;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (hPsapi != NULL)
|
|
{
|
|
FreeLibrary(hPsapi);
|
|
}
|
|
if (hMods != NULL)
|
|
{
|
|
delete[] hMods;
|
|
}
|
|
|
|
return pHead;
|
|
}
|
|
|
|
void CStackWalker::OutputString(LPCTSTR lpszFormat, ...)
|
|
{
|
|
TCHAR szBuf[1024] = _T("");
|
|
va_list args;
|
|
va_start(args, lpszFormat);
|
|
_vsntprintf_s(szBuf, 1024, lpszFormat, args);
|
|
va_end(args);
|
|
|
|
OutputDebugString(szBuf);
|
|
}
|
|
|
|
void CStackWalker::GetModuleInformation(LPMODULE_INFO pmi)
|
|
{
|
|
//USES_CONVERSION;
|
|
IMAGEHLP_MODULE64 im = {0};
|
|
im.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
|
|
|
|
VS_FIXEDFILEINFO* pvfi = NULL;
|
|
DWORD dwHandle = 0;
|
|
DWORD dwInfoSize = 0;
|
|
dwInfoSize = GetFileVersionInfoSize(pmi->szModulePath, &dwHandle);
|
|
|
|
if (dwInfoSize > 0)
|
|
{
|
|
byte *lpData = new byte[dwInfoSize];
|
|
ZeroMemory(lpData, dwInfoSize * sizeof(byte));
|
|
|
|
if (GetFileVersionInfo(pmi->szModulePath, dwHandle, dwInfoSize, lpData) > 0 )
|
|
{
|
|
TCHAR szBlock[] = _T("\\");
|
|
UINT len;
|
|
if (VerQueryValue(lpData, szBlock, (LPVOID*)&pvfi, &len))
|
|
{
|
|
WORD v1 = HIWORD(pvfi->dwFileVersionMS);
|
|
WORD v2 = LOWORD(pvfi->dwFileVersionMS);
|
|
WORD v3 = HIWORD(pvfi->dwFileVersionLS);
|
|
WORD v4 = LOWORD(pvfi->dwFileVersionLS);
|
|
_stprintf_s(pmi->szVersion, MAX_VERSION_LENGTH, _T("%d.%d.%d.%d"), v1, v2, v3, v4);
|
|
}
|
|
}
|
|
|
|
delete[] lpData;
|
|
}
|
|
|
|
SymGetModuleInfo64(m_hProcess, pmi->ModuleAddress, &im);
|
|
StringCchCopy(pmi->szSymbolPath, MAX_PATH, textconv_helper::A2T_(im.LoadedPdbName));
|
|
}
|
|
|
|
LPSTACKINFO CStackWalker::StackWalker(HANDLE hThread, const CONTEXT* context)
|
|
{
|
|
//USES_CONVERSION;
|
|
//加载符号表
|
|
LoadSymbol();
|
|
|
|
LPSTACKINFO pHead = NULL;
|
|
LPSTACKINFO pTail = pHead;
|
|
|
|
//获取当前线程的上下文环境
|
|
CONTEXT c = {0};
|
|
if (context == NULL)
|
|
{
|
|
#if _WIN32_WINNT <= 0x0501
|
|
if (hThread == GetCurrentThread())
|
|
#else
|
|
if (GetThreadId(hThread) == GetCurrentThreadId())
|
|
#endif
|
|
{
|
|
GET_CURRENT_THREAD_CONTEXT(c, CONTEXT_FULL);
|
|
}
|
|
else
|
|
{
|
|
//如果不是当前线程,需要停止目标线程,以便取出正确的堆栈信息
|
|
SuspendThread(hThread);
|
|
memset(&c, 0, sizeof(CONTEXT));
|
|
c.ContextFlags = CONTEXT_FULL;
|
|
if (GetThreadContext(hThread, &c) == FALSE)
|
|
{
|
|
ResumeThread(hThread);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
c = *context;
|
|
|
|
STACKFRAME64 sf = {};
|
|
DWORD imageType;
|
|
|
|
//intel X86
|
|
#ifdef _M_IX86
|
|
imageType = IMAGE_FILE_MACHINE_I386;
|
|
sf.AddrPC.Offset = c.Eip;
|
|
sf.AddrPC.Mode = AddrModeFlat;
|
|
sf.AddrFrame.Offset = c.Ebp;
|
|
sf.AddrFrame.Mode = AddrModeFlat;
|
|
sf.AddrStack.Offset = c.Esp;
|
|
sf.AddrStack.Mode = AddrModeFlat;
|
|
// AMD
|
|
#elif _M_X64
|
|
imageType = IMAGE_FILE_MACHINE_AMD64;
|
|
sf.AddrPC.Offset = c.Rip;
|
|
sf.AddrPC.Mode = AddrModeFlat;
|
|
sf.AddrFrame.Offset = c.Rsp;
|
|
sf.AddrFrame.Mode = AddrModeFlat;
|
|
sf.AddrStack.Offset = c.Rsp;
|
|
sf.AddrStack.Mode = AddrModeFlat;
|
|
////intel Itanium(安腾)
|
|
#elif _M_IA64
|
|
imageType = IMAGE_FILE_MACHINE_IA64;
|
|
sf.AddrPC.Offset = c.StIIP;
|
|
sf.AddrPC.Mode = AddrModeFlat;
|
|
sf.AddrFrame.Offset = c.IntSp;
|
|
sf.AddrFrame.Mode = AddrModeFlat;
|
|
sf.AddrBStore.Offset = c.RsBSP;
|
|
sf.AddrBStore.Mode = AddrModeFlat;
|
|
sf.AddrStack.Offset = c.IntSp;
|
|
sf.AddrStack.Mode = AddrModeFlat;
|
|
// ARM64
|
|
#elif defined(_M_ARM64)
|
|
imageType = IMAGE_FILE_MACHINE_ARM64;
|
|
sf.AddrPC.Offset = c.Pc;
|
|
sf.AddrPC.Mode = AddrModeFlat;
|
|
sf.AddrFrame.Offset = c.Fp;
|
|
sf.AddrFrame.Mode = AddrModeFlat;
|
|
sf.AddrStack.Offset = c.Sp;
|
|
sf.AddrStack.Mode = AddrModeFlat;
|
|
#else
|
|
#error "Platform not supported!"
|
|
#endif
|
|
|
|
|
|
DWORD64 dwDisplayment = 0;
|
|
PIMAGEHLP_SYMBOL64 pSym = (PIMAGEHLP_SYMBOL64)new BYTE[sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN];
|
|
PIMAGEHLP_LINE64 pLine = new IMAGEHLP_LINE64;
|
|
while (StackWalk64(imageType, m_hProcess, hThread, &sf, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
|
|
{
|
|
ZeroMemory(pSym, sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN);
|
|
ZeroMemory(pLine, sizeof(IMAGEHLP_LINE64));
|
|
|
|
pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
|
pSym->MaxNameLength = STACKWALK_MAX_NAMELEN;
|
|
pLine->SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
|
|
|
LPSTACKINFO pCallStack = new STACKINFO;
|
|
ZeroMemory(pCallStack, sizeof(STACKINFO));
|
|
pCallStack->szFncAddr = sf.AddrPC.Offset;
|
|
if (sf.AddrPC.Offset != 0)
|
|
{
|
|
if(SymGetSymFromAddr64(m_hProcess, sf.AddrPC.Offset, &dwDisplayment, pSym))
|
|
{
|
|
char szName[STACKWALK_MAX_NAMELEN] = "";
|
|
StringCchCopy(pCallStack->szFncName, STACKWALK_MAX_NAMELEN, textconv_helper::A2T_(pSym->Name));
|
|
UnDecorateSymbolName(pSym->Name, szName, STACKWALK_MAX_NAMELEN, UNDNAME_COMPLETE);
|
|
StringCchCopy(pCallStack->undFullName, STACKWALK_MAX_NAMELEN, textconv_helper::A2T_(szName));
|
|
ZeroMemory(szName, STACKWALK_MAX_NAMELEN * sizeof(char));
|
|
UnDecorateSymbolName(pSym->Name, szName, STACKWALK_MAX_NAMELEN, UNDNAME_NAME_ONLY);
|
|
StringCchCopy(pCallStack->undName, STACKWALK_MAX_NAMELEN, textconv_helper::A2T_(szName));
|
|
}else
|
|
{
|
|
//调用错误一般是487(地址无效或者没有访问的权限、在符号表中未找到指定地址的相关信息)
|
|
//this->OutputString(_T("Call SymGetSymFromAddr64 ,Address %08x Error:%08x\n"), sf.AddrPC.Offset, GetLastError());
|
|
|
|
StringCchCopy(pCallStack->undFullName, STACKWALK_MAX_NAMELEN, textconv_helper::A2T_("Unknown"));
|
|
}
|
|
|
|
if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset, (DWORD*)&dwDisplayment, pLine))
|
|
{
|
|
StringCchCopy(pCallStack->szFileName, MAX_PATH, textconv_helper::A2T_(pLine->FileName));
|
|
pCallStack->uFileNum = pLine->LineNumber;
|
|
}else
|
|
{
|
|
//this->OutputString(_T("Call SymGetLineFromAddr64 ,Address %08x Error:%08x\n"), sf.AddrPC.Offset, GetLastError());
|
|
|
|
StringCchCopy(pCallStack->szFileName, MAX_PATH, textconv_helper::A2T_("Unknown file"));
|
|
pCallStack->uFileNum = -1;
|
|
}
|
|
|
|
//这里为了将获取函数信息失败的情况与正常的情况一起输出,防止用户在查看时出现误解
|
|
this->OutputString(_T("%08llx:%s [%s][%ld]\n"), pCallStack->szFncAddr, pCallStack->undFullName, pCallStack->szFileName, pCallStack->uFileNum);
|
|
if (NULL == pHead)
|
|
{
|
|
pHead = pCallStack;
|
|
pTail = pHead;
|
|
}else
|
|
{
|
|
pTail->pNext = pCallStack;
|
|
pTail = pCallStack;
|
|
}
|
|
}
|
|
}
|
|
|
|
delete[] pSym;
|
|
delete pLine;
|
|
|
|
return pHead;
|
|
}
|
|
|
|
void CStackWalker::FreeStackInformations(LPSTACKINFO psi)
|
|
{
|
|
LPSTACKINFO head = psi;
|
|
while (NULL != head)
|
|
{
|
|
psi = psi->pNext;
|
|
delete head;
|
|
head = psi;
|
|
}
|
|
|
|
} |