Generating the stack traces in the C++ code
-
Thursday, August 16, 2012 3:11 PM
Hi ther,
I am trying to generate a stack trace using StackWalk64 function. I did get an example, illustrating how to use it at http://code-freeze.blogspot.com/2012_01_01_archive.html.
In example, you can see, author is using boost C++ libraries, for debugging purpose. I am not using boost c++ libraries, so I modified the code accordingly. I am not able to get the stack trace as I see it while debugging. Following is my code
#include <windows.h> #include <DbgHelp.h> #include <stdio.h> #include <conio.h> #include <string> #include <iostream> #include <sstream> class sym_handler { public: static sym_handler& get_instance() { static sym_handler instance; return instance; } std::string get_symbol_info(DWORD64 addr) { char tmp[1024]; std::stringstream ss; DWORD64 displacement64; DWORD displacement; char symbol_buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>(symbol_buffer); symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->MaxNameLen = 255; IMAGEHLP_LINE64 line; line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); //ss << boost::format("[0x%08X] ") % addr; sprintf(tmp, "%i", addr); ss << tmp; if (m_initialized) { if (SymFromAddr(GetCurrentProcess(), addr, &displacement64, symbol)) { ss << symbol->Name; if (SymGetLineFromAddr64(GetCurrentProcess(), addr, &displacement, &line)) { //ss << (boost::format(" (%s:%d)") % line.FileName % line.LineNumber).str(); sprintf(tmp, "File Name: %s, line No: %d"); ss << tmp; } } else{ DWORD err = GetLastError(); } } return ss.str(); } void capture_stack_trace(CONTEXT* context, DWORD64* frame_ptrs, size_t count, size_t skip) { if (m_initialized) { CONTEXT current_context; if (!context) { RtlCaptureContext(¤t_context); context = ¤t_context; } DWORD machine_type; STACKFRAME64 frame; ZeroMemory(&frame, sizeof(frame)); frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Mode = AddrModeFlat; #ifdef _M_X64 frame.AddrPC.Offset = context->Rip; frame.AddrFrame.Offset = context->Rbp; frame.AddrStack.Offset = context->Rsp; machine_type = IMAGE_FILE_MACHINE_AMD64; #else frame.AddrPC.Offset = context->Eip; frame.AddrPC.Offset = context->Ebp; frame.AddrPC.Offset = context->Esp; machine_type = IMAGE_FILE_MACHINE_I386; #endif for (size_t i = 0; i < count + skip; i++) { if (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), &frame, context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { if (i >= skip) { frame_ptrs[i - skip] = frame.AddrPC.Offset; } } else { break; } } } } private: sym_handler() { m_initialized = SymInitialize(GetCurrentProcess(), NULL, TRUE) == TRUE; } ~sym_handler() { if (m_initialized) { SymCleanup(GetCurrentProcess()); m_initialized = false; } } bool m_initialized; }; class stack_trace { public: stack_trace(CONTEXT* context, size_t skip) { ZeroMemory(m_frame_ptrs, sizeof(m_frame_ptrs)); sym_handler::get_instance().capture_stack_trace(context, m_frame_ptrs, max_frame_ptrs, skip); } std::string to_string() const { std::stringstream ss; for (size_t i = 0; i < max_frame_ptrs && m_frame_ptrs[i]; ++i) { ss << sym_handler::get_instance().get_symbol_info(m_frame_ptrs[i]) << "\n"; } return ss.str(); } private: static const size_t max_frame_ptrs = 16; DWORD64 m_frame_ptrs[max_frame_ptrs]; }; inline std::string to_string(const stack_trace& trace) { return trace.to_string(); } void foo2(){ stack_trace *sttrace = new stack_trace(NULL, 0); std::cout << sttrace->to_string(); MessageBoxA(NULL, sttrace->to_string().c_str(), "Stack Trace", 0); OutputDebugStringA(sttrace->to_string().c_str()); } void foo1(){ foo2(); } void foo(int x) { foo1(); } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { foo(-1); }
My queries can be,
1) Is the code correct!! can there be any modification to get the correct stack trace
2) Is there any other way or an example to do this?? If there please lead me to it
3) Are there any debugger options to be set, or some settings to be done?
Dhanyawaad (Thanks)
- Edited by Optimus22 Thursday, August 16, 2012 3:15 PM
All Replies
-
Monday, August 20, 2012 7:09 AMModerator
I think you can just use this http://jpassing.com/2008/03/12/walking-the-stack-of-the-current-thread/ ,
you can use it directly, it is not using others library.
Mike Zhang[MSFT]
MSDN Community Support | Feedback to us
- Marked As Answer by Mike Dos ZhangMicrosoft Contingent Staff, Moderator Wednesday, August 22, 2012 4:35 AM

