桌面Windows操作系统具有“StackWalk64”功能,Jochen Kalmbach将a library for decoding the call stack置于人类可读的东西之上。
我需要一个类似的工具,但对于Windows CE。 WinCE有一个函数来获取调用堆栈GetThreadCallStack,但是一旦我有原始返回地址,我该如何
PS。如果它对任何人有帮助,我还发现OS-agnostic code用于遍历ARM调用堆栈。显然,可靠的确很难!
答案 0 :(得分:4)
好吧,我想出了一半。您需要致电GetThreadCallStack
...
CallSnapshot frames[100];
HANDLE hThread = GetCurrentThread();
SetLastError(ERROR_SUCCESS);
int funcCount = GetThreadCallStack(hThread, 100, frames, STACKSNAP_RETURN_FRAMES_ON_ERROR, 0);
bool success = GetLastError() == ERROR_SUCCESS;
但由于某种原因,它的头文件未包含在Windows CE SDK中。因此,您需要手动声明它:
extern "C" {
typedef struct _CallSnapshot {
DWORD dwReturnAddr;
} CallSnapshot;
typedef struct _CallSnapshotEx {
DWORD dwReturnAddr;
DWORD dwFramePtr;
DWORD dwCurProc;
DWORD dwParams[4];
} CallSnapshotEx;
ULONG GetThreadCallStack (HANDLE hThrd, ULONG dwMaxFrames, LPVOID lpFrames, DWORD dwFlags, DWORD dwSkip);
ULONG GetCallStackSnapshot (ULONG dwMaxFrames, CallSnapshot lpFrames[], DWORD dwFlags, DWORD dwSkip);
#define STACKSNAP_FAIL_IF_INCOMPLETE 1
#define STACKSNAP_EXTENDED_INFO 2
#define STACKSNAP_INPROC_ONLY 4
#define STACKSNAP_RETURN_FRAMES_ON_ERROR 8
}
然后解码调用堆栈,您必须(1)找出每个返回地址的模块(EXE或DLL),以及(2)找出该模块中的函数。
我问another question about getting the module from a code address;理论上,可以将地图文件解析为figure out which function (in that module) the address belongs to(感谢链接的ctacke)。
答案 1 :(得分:3)
我也使用GetThreadCallStack,效果很好。一般来说,wince是最糟糕的平台,在调试方面具有最差的工具。关于doctorwatson的msdn上的所有BS都需要成为合作伙伴或使用平台构建器。那些需要在发布应用程序的运行时解决崩溃源的常规开发人员呢?!在数字时代和计算机时,这些"酷"地图文件的技巧听起来相当迟钝;这种任务非常适合计算机。 在wince上获取调用堆栈的唯一方法是GetThreadCallStack。与操作系统无关的代码"原始海报提到的不适用于wince。对于作者来说,使用他的编译器/ os / cpu组合工作已经足够好了,但它对wince没有用处(特别是它不能处理恢复PC寄存器的LDR指令)。我浪费了一些时间来使代码工作,总的来说我决定跳过它并浪费一大堆:那种代码必须由操作系统或编译器制造商编写,很难让它适用于所有人可能的生成代码类型。
对于那些拒绝使用地图文件的所有内容的人,我可以推荐一种可以帮助您避免该步骤的工具。 John Robbins的CrashFinder.exe可以为你做那部分。 此外,当您从GetThreadCallStack获取callstack时,清除最顶层字节的打印地址:
unsigned addr = addr1 & 0x00ffffff;
然后,在崩溃查找器中,您需要打开wince应用程序的exe文件,您可以查询地址,如果地址在您的应用程序中,它将显示功能名称。通常,如果在winapi内部发生崩溃,我需要从callstack手动输入每个地址,直到找到我应用程序中的最后一个地址。
答案 2 :(得分:2)
这些文章都讨论了将地址转换为源代码中的一行代码,可能会有所帮助: