http://www.cnblogs.com/opc521/archive/2010/04/08/1707060.html
-
获得函数调用堆栈地址
WinCE下可以通过函数GetCallStackSnapshot()来获得函数调用堆栈地址。该函数在pkfuncs.h中定义。
文件路径:
c:\Program Files\Windows CE Tools\wce600\PanelViewPlus SDK\Include\X86\pkfuncs.h
函数定义:
ULONG GetCallStackSnapshot (ULONG dwMaxFrames, CallSnapshot lpFrames[], DWORD dwFlags, DWORD dwSkip);
dwMaxFrames: 最大堆栈的个数
lpFrames: 返回堆栈的数组
其中 CallSnapshot定义:
typedef struct _CallSnapshot {
DWORD dwReturnAddr;
} CallSnapshot;
dwReturnAddr 为函数返回地址, 通过该地址结合map文件就可以找到调用的函数名。
例子:
#define MAX_FRAME_COUNT 10
CallSnapshot lpFrames[MAX_FRAME_COUNT];
int nRet = GetCallStackSnapshot(MAX_FRAME_COUNT, lpFrames, 0, 1);
-
MAP 文件
MAP 文件是程序的全局符号、源文件和代码行号信息的唯一的文本表示方法,它可以在任何地方、任何时候使用,不需要有额外的程序进行支持。 MAP文件可以在Visual Studio中设置,在编译工程的时候产生:

生成的MAP文件可以指定名称,如不指定则为工程名字,扩展名为.map。
打开map文件可以看到为如下格式:
TestClient
Timestamp is 4bbbf1e9 (Wed Apr 07 10:46:01 2010)
Preferred load address is 00400000
Start Length Name Class
0001:00000000 00001182H .text CODE
0001:00001190 000000b3H .text$x CODE
0001:00001250 0000005eH .text$yc CODE
0001:000012b0 0000001bH .text$yd CODE
0002:00000000 00000324H .idata$5 DATA
0002:00000324 00000004H .CRT$XCA DATA
0002:00000328 00000004H .CRT$XCAA DATA
0002:0000032c 00000004H .CRT$XCL DATA
0002:00000330 00000008H .CRT$XCU DATA
0002:00000338 00000004H .CRT$XCZ DATA
0002:0000033c 00000004H .CRT$XIA DATA
0002:00000340 00000004H .CRT$XIAA DATA
0002:00000344 00000004H .CRT$XIY DATA
0002:00000348 00000004H .CRT$XIZ DATA
0002:00000350 00000640H .rdata DATA
0002:00000990 0000005aH .rdata$debug DATA
0002:000009ec 000002fcH .rdata$r DATA
0002:00000cf0 00000014H .rdata$sxdata DATA
0002:00000d04 00000004H .rtc$IAA DATA
0002:00000d08 00000004H .rtc$IZZ DATA
0002:00000d0c 00000004H .rtc$TAA DATA
0002:00000d10 00000004H .rtc$TZZ DATA
0002:00000d18 00000154H .xdata$x DATA
0002:00000e6c 00000000H ATL$__a DATA
0002:00000e6c 00000000H ATL$__z DATA
0002:00000e6c 00000064H .idata$2 DATA
0002:00000ed0 00000014H .idata$3 DATA
0002:00000ee4 00000324H .idata$4 DATA
0002:00001208 000003e8H .idata$6 DATA
0002:000015f0 00000000H .edata DATA
0003:00000000 00000131H .data DATA
0003:00000138 000004a4H .bss DATA
0004:00000000 000003e8H .rsrc$01 DATA
0004:000003f0 00010e08H .rsrc$02 DATA
Address Publics by Value Rva+Base Lib:Object
0000:00000005 ___safe_se_handler_count 00000005 <absolute>
0000:00000000 ___ImageBase 00400000 <linker-defined>
0001:00000000 ?GetMessageMap@CTestClientApp@@MBEPBUAFX_MSGMAP@@XZ 00401000 f TestClient.obj
0001:00000010 ??_ECTestClientApp@@UAEPAXI@Z 00401010 f i CIL library: CIL module
0001:00000010 ??_GCTestClientApp@@UAEPAXI@Z 00401010 f i TestClient.obj
0001:00000030 ?InitInstance@CTestClientApp@@UAEHXZ 00401030 f TestClient.obj
0001:000000f0 ?PreLoadState@CWinAppEx@@MAEXXZ 004010f0 f i TestClient.obj
0001:000000f0 ?PreSaveState@CWinAppEx@@MAEXXZ 004010f0 f i TestClient.obj
0001:000000f0 ?SaveCustomState@CWinAppEx@@MAEXXZ 004010f0 f i TestClient.obj
0001:000000f0 ?AssertValid@CObject@@UBEXXZ 004010f0 f i TestClient.obj
0001:000000f0 ?LoadCustomState@CWinAppEx@@MAEXXZ 004010f0 f i TestClient.obj
0001:00000100 ?OnWorkspaceIdle@CWinAppEx@@UAEHPAVCWnd@@@Z 00401100 f i TestClient.obj
0001:00000110 ?DoDataExchange@CTestClientDlg@@MAEXPAVCDataExchange@@@Z 00401110 f i TestClientDlg.obj
0001:00000110 ?DoDataExchange@CAboutDlg@@MAEXPAVCDataExchange@@@Z 00401110 f i TestClientDlg.obj
0001:00000110 ?Dump@CObject@@UBEXAAVCDumpContext@@@Z 00401110 f i TestClient.obj
0001:00000110 ?Serialize@CObject@@UAEXAAVCArchive@@@Z 00401110 f i TestClient.obj
0001:00000120 ??1CTestClientDlg@@UAE@XZ 00401120 f i TestClient.obj
0001:00000120 ??1CAboutDlg@@UAE@XZ 00401120 f i TestClientDlg.obj
0001:00000130 ?GetMessageMap@CAboutDlg@@MBEPBUAFX_MSGMAP@@XZ 00401130 f TestClientDlg.obj
0001:00000140 ??0CTestClientDlg@@QAE@PAVCWnd@@@Z 00401140 f TestClientDlg.obj
0001:000001c0 ??_GCAboutDlg@@UAEPAXI@Z 004011c0 f i TestClientDlg.obj
0001:000001c0 ??_ECTestClientDlg@@UAEPAXI@Z 004011c0 f i CIL library: CIL module
0001:000001c0 ??_ECAboutDlg@@UAEPAXI@Z 004011c0 f i CIL library: CIL module
0001:000001c0 ??_GCTestClientDlg@@UAEPAXI@Z 004011c0 f i TestClientDlg.obj
0001:000001e0 ?GetMessageMap@CTestClientDlg@@MBEPBUAFX_MSGMAP@@XZ 004011e0 f TestClientDlg.obj
0001:000001f0 ?OnInitDialog@CTestClientDlg@@MAEHXZ 004011f0 f TestClientDlg.obj
0001:000002d0 ?OnSysCommand@CTestClientDlg@@IAEXIJ@Z 004012d0 f TestClientDlg.obj
0001:00000370 ?OnPaint@CTestClientDlg@@IAEXXZ 00401370 f TestClientDlg.obj
0001:00000440 ?OnQueryDragIcon@CTestClientDlg@@IAEPAUHICON__@@XZ 00401440 f TestClientDlg.obj
0001:00000450 ?OnBnClickedButton1@CTestClientDlg@@QAEXXZ 00401450 f TestClientDlg.obj
… …
(其他部分省略)
最后一行,可以看到函数名(OnBnClickedButton1),类名(CTestClientDlg),后面是地址(00401450),最后是cpp编译出来的obj文件名。
在第一部分我们已经通过GetCallStackSnapshot()获得函数的返回地址,根据这个地址到map文件中查找相等或者比它小的第一个地址处的函数名就是当前调用的函数。
微软提供开源代码mapfile.c用来方便的读取map文件:
www.totalembedded.com/open_source/objtool/objtool/mapfile.c
其中函数
PSTR MapfileLookupAddress(
IN PCWSTR wszModuleName,
IN DWORD dwAddress, DWORD* pdwResult);