DBG: fix call stack on x64
This commit is contained in:
parent
31443c2c78
commit
2952170189
|
@ -635,6 +635,34 @@ static void ReadDebugDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
static void ReadExceptionDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
|
||||
{
|
||||
// Clear runtime functions
|
||||
Info.runtimeFunctions.clear();
|
||||
|
||||
// Get address and size of exception directory
|
||||
ULONG totalBytes;
|
||||
auto baseRuntimeFunctions = (PRUNTIME_FUNCTION)RtlImageDirectoryEntryToData((PVOID)FileMapVA,
|
||||
FALSE,
|
||||
IMAGE_DIRECTORY_ENTRY_EXCEPTION,
|
||||
&totalBytes);
|
||||
if(baseRuntimeFunctions == nullptr || totalBytes == 0 ||
|
||||
(ULONG_PTR)baseRuntimeFunctions + totalBytes > FileMapVA + Info.loadedSize || // Check if baseRuntimeFunctions fits into the mapped area
|
||||
(ULONG_PTR)baseRuntimeFunctions + totalBytes < (ULONG_PTR)baseRuntimeFunctions) // Check for ULONG_PTR wraparound (e.g. when totalBytes == 0xfffff000)
|
||||
return;
|
||||
|
||||
Info.runtimeFunctions.resize(totalBytes / sizeof(RUNTIME_FUNCTION));
|
||||
for(size_t i = 0; i < Info.runtimeFunctions.size(); i++)
|
||||
Info.runtimeFunctions[i] = baseRuntimeFunctions[i];
|
||||
|
||||
std::stable_sort(Info.runtimeFunctions.begin(), Info.runtimeFunctions.end(), [](const RUNTIME_FUNCTION & a, const RUNTIME_FUNCTION & b)
|
||||
{
|
||||
return std::tie(a.BeginAddress, a.EndAddress) < std::tie(b.BeginAddress, b.EndAddress);
|
||||
});
|
||||
}
|
||||
#endif // _WIN64
|
||||
|
||||
static bool GetUnsafeModuleInfoImpl(MODINFO & Info, ULONG_PTR FileMapVA, void(*func)(MODINFO &, ULONG_PTR), const char* name)
|
||||
{
|
||||
__try
|
||||
|
@ -723,6 +751,9 @@ void GetModuleInfo(MODINFO & Info, ULONG_PTR FileMapVA)
|
|||
GetUnsafeModuleInfo(ReadTlsCallbacks);
|
||||
GetUnsafeModuleInfo(ReadBaseRelocationTable);
|
||||
GetUnsafeModuleInfo(ReadDebugDirectory);
|
||||
#ifdef _WIN64
|
||||
GetUnsafeModuleInfo(ReadExceptionDirectory);
|
||||
#endif // _WIN64
|
||||
#undef GetUnsafeModuleInfo
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,9 @@ struct MODINFO
|
|||
std::vector<MODSECTIONINFO> sections;
|
||||
std::vector<MODRELOCATIONINFO> relocations;
|
||||
std::vector<duint> tlsCallbacks;
|
||||
#if _WIN64
|
||||
std::vector<RUNTIME_FUNCTION> runtimeFunctions; //sorted by (begin, end)
|
||||
#endif // _WIN64
|
||||
|
||||
MODEXPORT entrySymbol;
|
||||
|
||||
|
|
|
@ -153,6 +153,30 @@ static BOOL CALLBACK StackReadProcessMemoryProc64(HANDLE hProcess, DWORD64 lpBas
|
|||
return false;
|
||||
}
|
||||
|
||||
static PVOID CALLBACK StackSymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
// https://github.com/dotnet/coreclr/blob/master/src/unwinder/amd64/dbs_stack_x64.cpp
|
||||
MODINFO* info = ModInfoFromAddr(AddrBase);
|
||||
if(!info)
|
||||
return nullptr;
|
||||
|
||||
DWORD rva = DWORD(AddrBase - info->base);
|
||||
RUNTIME_FUNCTION needle;
|
||||
needle.BeginAddress = rva;
|
||||
needle.EndAddress = rva;
|
||||
needle.UnwindData = 0;
|
||||
auto found = binary_find(info->runtimeFunctions.begin(), info->runtimeFunctions.end(), needle, [](const RUNTIME_FUNCTION & a, const RUNTIME_FUNCTION & b)
|
||||
{
|
||||
return a.EndAddress < b.BeginAddress;
|
||||
});
|
||||
if(found != info->runtimeFunctions.end())
|
||||
return &found->BeginAddress;
|
||||
#endif // _WIN64
|
||||
|
||||
return SymFunctionTableAccess64(hProcess, AddrBase);
|
||||
}
|
||||
|
||||
static DWORD64 CALLBACK StackGetModuleBaseProc64(HANDLE hProcess, DWORD64 Address)
|
||||
{
|
||||
return (DWORD64)ModBaseFromAddr((duint)Address);
|
||||
|
@ -308,7 +332,7 @@ void stackgetcallstack(duint csp, std::vector<CALLSTACKENTRY> & callstackVector,
|
|||
&frame,
|
||||
&context,
|
||||
StackReadProcessMemoryProc64,
|
||||
SymFunctionTableAccess64,
|
||||
StackSymFunctionTableAccess64,
|
||||
StackGetModuleBaseProc64,
|
||||
StackTranslateAddressProc64))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue