找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 4586|回复: 2

用户层栈回溯+获得源码地址与行号

[复制链接]

6

主题

123

回帖

0

精华

初来乍到

积分
5392
发表于 2018-6-20 14:01:44 | 显示全部楼层 |阅读模式
步骤:

RtlCaptureContext----->填充到STACKFRAME结构----------------->循环调用StackWalk64---->SymFromAddr获得符号--------->SymGetLineFromAddr64获得源码地址与行号




        const UINT max_name_length = 256;        // Max length of symbols' name.

        CONTEXT context;                        // Store register addresses.
        STACKFRAME64 stackframe;                // Call stack.
        HANDLE process, thread;                        // Handle to current process & thread.
                                                // Generally it can be subsitituted with 0xFFFFFFFF & 0xFFFFFFFE.
        PSYMBOL_INFO symbol;                        // Debugging symbol's information.
        IMAGEHLP_LINE64 source_info;                // Source information (file name & line number)
        DWORD displacement;                        // Source line displacement.

        // Initialize PSYMBOL_INFO structure.
        // Allocate a properly-sized block.
        symbol = (PSYMBOL_INFO)malloc(sizeof(SYMBOL_INFO) + (max_name_length - 1) * sizeof(TCHAR));       
        memset(symbol, 0, sizeof(SYMBOL_INFO) + (max_name_length - 1) * sizeof(TCHAR));
        symbol->SizeOfStruct = sizeof(SYMBOL_INFO);        // SizeOfStruct *MUST BE* set to sizeof(SYMBOL_INFO).
        symbol->MaxNameLen = max_name_length;

        // Initialize IMAGEHLP_LINE64 structure.
        memset(&source_info, 0, sizeof(IMAGEHLP_LINE64));
        source_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
       
        // Initialize STACKFRAME64 structure.
        RtlCaptureContext(&context);                        // Get context.
        memset(&stackframe, 0, sizeof(STACKFRAME64));
        stackframe.AddrPC.Offset = context.Eip;                // Fill in register addresses (EIP, ESP, EBP).
        stackframe.AddrPC.Mode = AddrModeFlat;
        stackframe.AddrStack.Offset = context.Esp;
        stackframe.AddrStack.Mode = AddrModeFlat;
        stackframe.AddrFrame.Offset = context.Ebp;
        stackframe.AddrFrame.Mode = AddrModeFlat;

        process = GetCurrentProcess();        // Get current process & thread.
        thread = GetCurrentThread();

        // Initialize dbghelp library.
        if(!SymInitialize(process, NULL, TRUE))
                return ;

        _putts(__T("Call stack: \n\n"));

        // Enumerate call stack frame.
        while(StackWalk64(IMAGE_FILE_MACHINE_I386, process, thread, &stackframe,
                &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
        {
                if(stackframe.AddrFrame.Offset == 0)        // End reaches.
                        break;
               
                if(SymFromAddr(process, stackframe.AddrPC.Offset, NULL, symbol))// Get symbol.
                        _tprintf(__T(" > %s\n"), symbol->Name);

                if(SymGetLineFromAddr64(process, stackframe.AddrPC.Offset,
                        &displacement, &source_info)) {                                // Get source information.
                                _tprintf(__T("\t[%s:%d] at addr 0x%08LX\n"),
                                        source_info.FileName,
                                        source_info.LineNumber,
                                        stackframe.AddrPC.Offset);
                } else {
                        if(GetLastError() == 0x1E7) {                // If err_code == 0x1e7, no symbol was found.
                                _tprintf(__T("\tNo debug symbol loaded for this function.\n"));
                        }
                }
        }

        SymCleanup(process);        // Clean up and exit.
        free(symbol);

857

主题

2632

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36130
发表于 2018-6-28 15:56:33 | 显示全部楼层
很好,值得学习。

28

主题

116

回帖

0

精华

铜牌会员

积分
273
发表于 2018-7-5 06:15:00 | 显示全部楼层
本帖最后由 gfw 于 2018-7-5 06:19 编辑

正需要呢 感谢YOUBADBAD
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表