Fix Win32 stack traces issue due to invalid search path for debug symbols

#457
This commit is contained in:
Wojtek Figat
2021-04-23 16:35:18 +02:00
parent 826581cb77
commit d36a36d439

View File

@@ -38,7 +38,7 @@ namespace
CriticalSection SymLocker; CriticalSection SymLocker;
bool SymInitialized = false; bool SymInitialized = false;
bool SymModulesDirty = true; bool SymModulesDirty = true;
char* SymPath = nullptr; Array<String> SymbolsPath;
#endif #endif
} }
@@ -617,9 +617,8 @@ void WindowsPlatform::Exit()
{ {
SymInitialized = false; SymInitialized = false;
SymCleanup(GetCurrentProcess()); SymCleanup(GetCurrentProcess());
free(SymPath);
SymPath = nullptr;
} }
SymbolsPath.Resize(0);
SymLocker.Unlock(); SymLocker.Unlock();
#endif #endif
@@ -1116,7 +1115,13 @@ void* WindowsPlatform::LoadLibrary(const Char* filename)
#if CRASH_LOG_ENABLE #if CRASH_LOG_ENABLE
// Refresh modules info during next stack trace collecting to have valid debug symbols information // Refresh modules info during next stack trace collecting to have valid debug symbols information
SymLocker.Lock(); SymLocker.Lock();
SymModulesDirty = true; const auto folder = StringUtils::GetDirectoryName(filename);
if (!SymbolsPath.Contains(folder))
SymbolsPath.Add(folder);
if (SymInitialized)
{
SymModulesDirty = true;
}
SymLocker.Unlock(); SymLocker.Unlock();
#endif #endif
@@ -1137,80 +1142,43 @@ Array<PlatformBase::StackFrame> WindowsPlatform::GetStackFrames(int32 skipCount,
SymInitialized = true; SymInitialized = true;
// Build search path // Build search path
const size_t nSymPathLen = 4096; String symbolSearchPath;
SymPath = (char*)malloc(nSymPathLen); TCHAR ModulePath[MAX_PATH] = { 0 };
SymPath[0] = 0; if (::GetModuleFileName(::GetModuleHandle(nullptr), ModulePath, MAX_PATH))
strcat_s(SymPath, nSymPathLen, ".;");
const size_t nTempLen = 1024;
char szTemp[nTempLen];
// Current directory path
if (GetCurrentDirectoryA(nTempLen, szTemp) > 0)
{ {
szTemp[nTempLen - 1] = 0; symbolSearchPath += StringUtils::GetDirectoryName(ModulePath);
strcat_s(SymPath, nSymPathLen, szTemp); symbolSearchPath += ";";
strcat_s(SymPath, nSymPathLen, ";");
} }
for (auto& path : SymbolsPath)
// Main module path
if (GetModuleFileNameA(nullptr, szTemp, nTempLen) > 0)
{ {
szTemp[nTempLen - 1] = 0; symbolSearchPath += path;
for (char* p = (szTemp + strlen(szTemp) - 1); p >= szTemp; --p) symbolSearchPath += ";";
{
// Locate the rightmost path separator
if ((*p == '\\') || (*p == '/') || (*p == ':'))
{
*p = 0;
break;
}
}
if (strlen(szTemp) > 0)
{
strcat_s(SymPath, nSymPathLen, szTemp);
strcat_s(SymPath, nSymPathLen, ";");
}
} }
String _NT_SYMBOL_PATH;
// System symbols paths if (!Platform::GetEnvironmentVariable(TEXT("_NT_SYMBOL_PATH"), _NT_SYMBOL_PATH))
if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", szTemp, nTempLen) > 0)
{ {
szTemp[nTempLen - 1] = 0; symbolSearchPath += _NT_SYMBOL_PATH;
strcat_s(SymPath, nSymPathLen, szTemp); symbolSearchPath += ";";
strcat_s(SymPath, nSymPathLen, ";");
} }
if (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", szTemp, nTempLen) > 0) symbolSearchPath += Platform::GetWorkingDirectory();
{ symbolSearchPath += ";";
szTemp[nTempLen - 1] = 0;
strcat_s(SymPath, nSymPathLen, szTemp);
strcat_s(SymPath, nSymPathLen, ";");
}
if (GetEnvironmentVariableA("SYSTEMROOT", szTemp, nTempLen) > 0)
{
szTemp[nTempLen - 1] = 0;
strcat_s(SymPath, nSymPathLen, szTemp);
strcat_s(SymPath, nSymPathLen, ";");
strcat_s(szTemp, nTempLen, "\\system32");
strcat_s(SymPath, nSymPathLen, szTemp);
strcat_s(SymPath, nSymPathLen, ";");
}
SymInitialize(process, SymPath, FALSE);
DWORD options = SymGetOptions(); DWORD options = SymGetOptions();
options |= SYMOPT_LOAD_LINES; options |= SYMOPT_LOAD_LINES;
options |= SYMOPT_FAIL_CRITICAL_ERRORS; options |= SYMOPT_FAIL_CRITICAL_ERRORS;
options |= SYMOPT_DEFERRED_LOADS;
options |= SYMOPT_EXACT_SYMBOLS;
SymSetOptions(options); SymSetOptions(options);
SymInitializeW(process, *symbolSearchPath, TRUE);
} }
// Load modules // Refresh modules if needed
if (SymModulesDirty) if (SymModulesDirty)
{ {
SymModulesDirty = false; SymModulesDirty = false;
GetModuleListPSAPI(process); SymRefreshModuleList(process);
} }
SymRefreshModuleList(process);
// Capture the context if missing // Capture the context if missing
/*EXCEPTION_POINTERS exceptionPointers; /*EXCEPTION_POINTERS exceptionPointers;