Two blog posts that implement backtrce by themselves

Source: Internet
Author: User

Stack backtrace in Linux)

Today, we have encountered such a requirement that the call stack can be printed out when an exception is thrown in the dynamic link library. I searched Google and found some clues.

My file directory is as follows: the current directory is main. cpp and test/

Under test is a. h, A. cpp (defines a class), backtrace. H, backtrace. cpp

 

Step 1: print the call stack. The backtrace function is implemented as follows:

Backtrace. cpp

# Include "backtrace. H"

# Include <unistd. h>
# Include <stdio. h>
# Include <execinfo. h>
# Include <stdlib. h>
# Include <string. h>
Void backtrace ()
{
Const int maxlevel = 200;
Void * buffer [maxlevel];
Int level = backtrace (buffer, maxlevel );
Const int size = 1024;
Char cmd [size] = "addr2line-C-f-e ";

// Let prog point to the end of "cmd"
Char * prog = cmd + strlen (CMD );

Int r = readlink ("/proc/self/EXE", prog, sizeof (CMD)-(prog-cmd)-1 );

File * fp = popen (CMD, "W ");
If (! FP)
{
Perror ("popen ");
Return;
}
For (INT I = 0; I <level; ++ I)
{
Fprintf (FP, "% P/N", buffer [I]);
}
Fclose (FP );
}

Main. cpp

Include <stdio. h>
# Include "A. H"
# Include "backtrace. H"
Void Foo (INT, char *)
{
Backtrace ();
}
Void bar (double)
{
Foo (0, null );
}

Int main ()
{
Bar (0.0 );
//;
Return 0;
}

Compile as follows. Pay attention to the-G and-rdynamic parameters.

[Charlie @ localhost so] $ g ++-g-rdynamic-itest main. cpp test/backtrace. cpp
[Charlie @ localhost so] $./A. Out
Backtrace ()
/Home/Charlie/workspace/SO/test/backtrace. cpp: 12
Foo (INT, char *)
/Home/Charlie/workspace/SO/Main. cpp: 7
Bar (double)
/Home/Charlie/workspace/SO/Main. cpp: 11
Main
/Home/Charlie/workspace/SO/Main. cpp: 17
??
?? : 0
_ Start
?? : 0
From the above output, we can see that the call stack is correctly printed, including the function name, code file: number of rows

Below ?? Indicates that the code file name cannot be obtained and may be filtered if necessary.

Step 2: print the call stack in the dynamic link library.

A. cpp

# Include "A. H"
# Include "backtrace. H"
# Include <stdio. h>

A: ()
{
Printf ("A: A/N ");
Backtrace ();
}

Related Changes in Main. cpp are as follows:

Int main ()
{
// Bar (0.0 );
A;
Return 0;
}

Compile and generate a Dynamic Link Library:

[Charlie @ localhost test] $ g ++-g-rdynamic-o liba. So-shared a. cpp backtrace. cpp

[Charlie @ localhost so] $ g ++-g-rdynamic-ltest-itest-La main. cpp

[Charlie @ localhost so] $./A. Out
A:
??
?? : 0
??
?? : 0
Main
/Home/Charlie/workspace/SO/Main. cpp: 7
??
?? : 0
_ Start
?? : 0

Unfortunately, only the main function can output the file name and number of rows. Dynamic Link Library cannot be typed out.

Dynamic library does not work. How about static library? Intuition should be a line, because it is similar to the direct compilation link.

CD to test,

[Charlie @ localhost test] $ g ++-g-rdynamic-C backtrace. cpp A. cpp

Compile and generate the. o file, and then use AR to compress it into the. A file.
[Charlie @ localhost test] $ ar-rc liba. a. o backtrace. o
[Charlie @ localhost test] $ CD ..
[Charlie @ localhost so] $ g ++-g-rdynamic-itest main. cpp test/LIBA.
[Charlie @ localhost so] $./A. Out
A:
Backtrace ()
/Home/Charlie/workspace/SO/test/backtrace. cpp: 12
A
/Home/Charlie/workspace/SO/test/a. cpp: 9
Main
/Home/Charlie/workspace/SO/Main. cpp: 17
??
?? : 0
_ Start
?? : 0
This execution really got the expected results and printed the stack information correctly.

 

Conclusion: With the help of the addr2line command, backtrace can be used to display the function call stack information at runtime. This method is effective for static connections and does not work for dynamic libraries (not available for the moment ).

 

 

Certificate -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// ///////

 

Get function call stack-_ builtin_frame_address2007-09-17

GCC provides two built-in functions for obtaining the return address and Framework address in the function call stack at runtime.

If glibc 2.1 or later is used, you can use the backtrace () function. For more information, see <execinfo. h>. Other systems may have different technical support.

Built-in Function: void * __builtin_return_address (unsigned int level)

Built-in Function: void * __builtin_frame_address (unsigned int level)

Example

#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <ucontext.h>
#include <dlfcn.h>
#include <execinfo.h>

void showBacktrace()
{
        void * ret = __builtin_return_address(1);
        printf("ret address [%x]/n", ret);
        void * caller = __builtin_frame_address(0);
        printf("call address [%x]/n", caller);
#ifdef __cplusplus
         Dl_info dlinfo;

        void *ip = ret;
        if(!dladdr(ip, &dlinfo)) {
                perror("addr not found/n");
                return;
        }

        const char *symname = dlinfo.dli_sname;
        int f = 0;
        fprintf(stderr, "% 2d: %p %s+%u (%s)/n",
                        ++f,
                         ip,
                         symname, 0,
// (unsigned)(ip - dlinfo.dli_saddr),

                         dlinfo.dli_fname);
#endif
}

int MyFunc_A()
{
         showBacktrace();
        return 10;
}

int MyFunc_B()
{
        return MyFunc_A();
}

int main()
{
         MyFunc_B();
        return 0;
}

$ G ++ T. cpp-rdynamic-LDL-o t
$./T
RET Address [80488ff]
Call Address [bfffb938]
1: 0x80488ff _ z8myfunc_bv + 0 (./t)

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.