1
0
Fork 0

DBG: fix call stack on x64

This commit is contained in:
pxf_god 2019-10-06 07:26:29 +08:00 committed by Duncan Ogilvie
parent 31443c2c78
commit 2952170189
3 changed files with 59 additions and 1 deletions

View File

@ -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
}

View File

@ -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;

View File

@ -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))
{