How to get a stack trace for C++ using gcc with line number information?

后端 未结 14 2046
长发绾君心
长发绾君心 2020-11-27 09:54

We use stack traces in proprietary assert like macro to catch developer mistakes - when error is caught, stack trace is printed.

I find gcc\'s pair

14条回答
  •  囚心锁ツ
    2020-11-27 10:43

    I suppose line numbers are related to current eip value, right?

    SOLUTION 1:
    Then you can use something like GetThreadContext(), except that you're working on linux. I googled around a bit and found something similar, ptrace():

    The ptrace() system call provides a means by which a parent process may observe and control the execution of another process, and examine and change its core image and registers. [...] The parent can initiate a trace by calling fork(2) and having the resulting child do a PTRACE_TRACEME, followed (typically) by an exec(3). Alternatively, the parent may commence trace of an existing process using PTRACE_ATTACH.

    Now I was thinking, you can do a 'main' program which checks for signals that are sent to its child, the real program you're working on. after fork() it call waitid():

    All of these system calls are used to wait for state changes in a child of the calling process, and obtain information about the child whose state has changed.

    and if a SIGSEGV (or something similar) is caught call ptrace() to obtain eip's value.

    PS: I've never used these system calls (well, actually, I've never seen them before ;) so I don't know if it's possible neither can help you. At least I hope these links are useful. ;)

    SOLUTION 2: The first solution is quite complicated, right? I came up with a much simpler one: using signal() catch the signals you are interested in and call a simple function that reads the eip value stored in the stack:

    ...
    signal(SIGSEGV, sig_handler);
    ...
    
    void sig_handler(int signum)
    {
        int eip_value;
    
        asm {
            push eax;
            mov eax, [ebp - 4]
            mov eip_value, eax
            pop eax
        }
    
        // now you have the address of the
        // **next** instruction after the
        // SIGSEGV was received
    }
    

    That asm syntax is Borland's one, just adapt it to GAS. ;)

提交回复
热议问题