Answered Generating the stack traces in the C++ code

  • Thursday, August 16, 2012 3:11 PM
     
      Has Code

    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(&current_context);  
                    context = &current_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