Arm 如何解码Windows CE调用堆栈?

Arm 如何解码Windows CE调用堆栈?,arm,windows-ce,decode,callstack,Arm,Windows Ce,Decode,Callstack,桌面Windows操作系统有一个“StackWalk64”功能,Jochen Kalmbach在该功能的基础上制作了一些人类可读的东西 我需要一个类似的工具,但用于Windows CE。WinCE有一个获取调用堆栈的功能,但是一旦我有了原始的返回地址,我该怎么做呢 从每个程序计数器确定模块(DLL或EXE) 使用my.map或.pdb文件确定包含地址的函数 如果这对任何人都有帮助的话,我还发现了一种方法,可以在ARM调用堆栈中行走。显然,这真的很难做到可靠 这些文章都讨论了如何在源代码中将地址转

桌面Windows操作系统有一个“StackWalk64”功能,Jochen Kalmbach在该功能的基础上制作了一些人类可读的东西

我需要一个类似的工具,但用于Windows CE。WinCE有一个获取调用堆栈的功能,但是一旦我有了原始的返回地址,我该怎么做呢

  • 从每个程序计数器确定模块(DLL或EXE)
  • 使用my.map或.pdb文件确定包含地址的函数

  • 如果这对任何人都有帮助的话,我还发现了一种方法,可以在ARM调用堆栈中行走。显然,这真的很难做到可靠

    这些文章都讨论了如何在源代码中将地址转换为一行代码,可能会有所帮助:


      • 好吧,我算出了一半。您需要调用
        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)计算出该模块中的函数


        我问;从理论上讲,可以将映射文件解析为(感谢ctacke提供的链接)。

        我也使用GetThreadCallStack,它工作得非常好。通常,在调试时,wince是最差的平台,工具也最差。msdn上关于doctorwatson的所有BS都需要成为合作伙伴或使用platform builder。那些需要在发布应用程序运行时解决崩溃源的普通开发人员呢?!在数字时代和计算机时代,这些带有地图文件的“酷”把戏听起来相当迟钝;这种任务非常适合计算机。 在wince上获取调用堆栈的唯一方法是GetThreadCallStack。原始海报中提到的“操作系统不可知代码”在wince上不起作用。这对作者来说已经足够好了,可以让它与编译器/os/cpu组合使用,但它对wince不起作用(特别是,它不处理恢复PC寄存器的LDR指令)。我浪费了一些时间使代码正常工作,一般来说,我决定跳过它,这是一堆浪费:这种代码必须由操作系统或编译器制造商编写,很难使它完美地适用于所有可能生成的代码类型

        对于那些拒绝使用所有这些乱七八糟的地图文件的人,我可以推荐一个工具来帮助你避免这一步。约翰·罗宾斯可以帮你演那个角色。 另外,当您从GetThreadCallStack获取callstack时,打印清除了最顶端字节的地址:

        unsigned addr = addr1 & 0x00ffffff;
        

        然后,在crash finder中,你需要打开wince应用程序的exe文件,你可以查询地址,如果地址在你的应用程序中,它会显示你的函数名。通常,如果winapi内部某个地方发生崩溃,我需要手动输入callstack中的每个地址,直到找到我应用程序中的最后一个地址。

        你说它是“最差的平台,最差的工具”,这真是太好笑了!您使用过多少其他嵌入式平台和工具集?显然,它比嵌入式平台好。我指的是大多数桌面或移动开发人员使用的常规平台和目标。我将它与我使用的linux/gcc组合进行比较,gcc有一些函数可以在不使用黑魔法的情况下获取调用堆栈跟踪和函数名。在windows上,至少ms具有正常功能,允许您执行大部分操作。在wince中,即使在连接调试器时点击dataabort,有时回溯会出错,或者如果在运行breakall时使用breakall,也不会得到任何回溯。我没有使用过任何其他嵌入式操作系统,但与桌面Windows或Linux相比,wince可用的工具要少得多(Linux的嵌入式版本不能使用桌面Linux上的大多数可用工具吗?)我为WinCE编写了高性能代码,但仍然没有找到一个合适的分析器(Monte Carlo分析器似乎需要platform builder,而且无论如何也不捕获调用堆栈)。我还发现了一个完整的回溯解决方案(使用规定的方法)