Section 7.4. glibc Debugging Support


7.4. glibc Debugging Support

The usual way to examine a back trace of a program is to use an external debugger such as GDB. Sometimes, however, it is useful to obtain back-trace information from within a running program for logging or debugging purposes. The GNU glibc provides support that enables the developer to produce back-trace printouts from within the application.

Example 7-4 shows how to use backtrace inside a signal handler and outside a signal handler. The API prototypes for back trace are declared in the header file execinfo.h and should be included in the application.

Example 7-4. Code Listing of sample_backtrace.c

1 #include <execinfo.h> 2 #include <stdio.h> 3 #include <signal.h> 4 5 void handler() 6 { 7   int i; 8   void *trace[128]; 9   int tr_size; 10   char **strings; 11 12   printf("\n########## start backtrace ##########\n\n"); 13   tr_size = backtrace(trace, sizeof(trace) / sizeof(void *)); 14   strings = backtrace_symbols(trace, tr_size); 15   printf("Number of elements in backtrace: %d\n", tr_size); 16   for (i = 0; i < tr_size; i++) { 17     printf("%s\n", strings[i]); 18   } 19   printf("\n########## end backtrace ##########\n"); 20 21   free(strings); 22 } 23 24 h() 25 { 26 #ifdef _handler_ 27   abort(); 28 #else 29   handler(); 30 #endif 31 } 32 33 void g() 34 { 35   h(); 36 } 37 38 void foo() 39 { 40   g(); 41 } 42 43 int main(int argc, char **argv) 44 { 45   struct sigaction sigact; 46 47    sigact.sa_sigaction = handler; 48    sigemptyset(&sigact.sa_mask); 49    sigact.sa_flags = SA_SIGINFO; 50    sigaction(SIGSEGV, &sigact, NULL); 51    sigaction(SIGABRT, &sigact, NULL); 52 53    foo(); 54 } 

Compile the code listing sample_backtrace.c with the _handler_ macro defined to simulate an application program that aborts in the middle of its run:

$ gcc sample_backtrace.c -o sample_backtrace -g -rdynamic -D_handler_ $./sample_backtrace ########## start backtrace ########## Number of elements in backtrace: 9 ./main1(handler+0x2d) [0x8048829] [0xffffe440] /lib/tls/libc.so.6(abort+0x129) [0x40051f79] ./main1(g+0) [0x80488d2] ./main1(g+0xb) [0x80488dd] ./main1(foo+0xb) [0x80488ea] ./main1(main+0x6a) [0x8048956] /lib/tls/libc.so.6(__libc_start_main+0xe0) [0x4003e500] ./main1 [0x8048761] ########## end backtrace ########## Aborted 


In the preceding example, back-trace information is produced through the abort signal handler routine called handler(). The same method can be implemented for other signals caught by the application.

In the following, Example 7-4 is compiled without the _handler_ macro defined. In this example, the handler() function is called explicitly by the application to produce a back-trace printout. This method can be used to create back-trace information at certain points of the application for debugging or monitoring reasons.

$ gcc sample_backtrace.c -o sample_backtrace -g -rdynamic $ ./sample_backtrace ########## start backtrace ########## Number of elements in backtrace: 7 ./main1(handler+0x2d) [0x80487f9] ./main1(h+0xb) [0x80488a2] ./main1(g+0xb) [0x80488af] ./main1(foo+0xb) [0x80488bc] ./main1(main+0x6a) [0x8048928] /lib/tls/libc.so.6(__libc_start_main+0xe0) [0x4003e500] ./main1 [0x8048731] ########## end backtrace ########## 


When compiling, notice that the rdynamic flag is used. The rdynamic flag is passed on to the linker to force inclusion of global symbol tables in the final executable.




UNIX to Linux Porting. A Comprehensive Reference
UNIX to Linux Porting: A Comprehensive Reference
ISBN: 0131871099
EAN: 2147483647
Year: 2004
Pages: 175

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net