Debugging: Difference between revisions

From miki
Jump to navigation Jump to search
Line 19: Line 19:
Object and executables need to build with '''<tt>gcc -g -rdynamic</tt>'''!
Object and executables need to build with '''<tt>gcc -g -rdynamic</tt>'''!
<source lang="bash">
<source lang="bash">
gcc -O0 -g -rdynamic main.c -o myprogram
gcc -o0 -g -rdynamic main.c -o myprogram
</source>
</source>


Line 28: Line 28:
#include <signal.h>
#include <signal.h>
#include <stdlib.h>
#include <stdlib.h>



void handler(int sig) {
void handler(int sig) {
Line 34: Line 33:
int size;
int size;


// get void*'s for all entries on the stack
size = backtrace(array, 10); // get void*'s for all entries on the stack
size = backtrace(array, 10);


// print out all the frames to stderr
fprintf(stderr, "Error: signal %d:\n", sig); // print out all the frames to stderr
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, 2);
backtrace_symbols_fd(array, size, 2);
exit(1);
exit(1);
Line 44: Line 41:


void baz() {
void baz() {
int *foo = (int*)-1; // make a bad pointer
int *foo = (int*)-1; // make a bad pointer
printf("%d\n", *foo); // causes segfault
printf("%d\n", *foo); // causes segfault
}
}


void bar() { baz(); }
void bar() { baz(); }
void foo() { bar(); }
void foo() { bar(); }



int main(int argc, char **argv) {
int main(int argc, char **argv) {
signal(SIGSEGV, handler); // install our handler
signal(SIGSEGV, handler); // install our handler
foo(); // this will call foo, bar, and baz. baz segfaults.
foo(); // this will call foo, bar, and baz. baz segfaults.
return 0;
return 0;
}
}
Line 82: Line 78:


* Using <tt>backtrace</tt>:
* Using <tt>backtrace</tt>:
{{pl2|
{{hidden|<tt>main.c</tt>
([{{#filelink: main.c}} download])|{{#fileanchor: main.c}}
<source lang="c">
<source lang="c">
#ifndef _GNU_SOURCE
#ifndef _GNU_SOURCE
Line 192: Line 191:
exit(EXIT_SUCCESS);
exit(EXIT_SUCCESS);
}
}
</source>|headerstyle=background:#ccccff;text-align:left;}} }}
</source>


* Demangling symbols in C++ by calling <tt>__cxa_demangle</tt> (like is done in tool <tt>c++filt</tt>):
* Demangling symbols in C++ by calling <tt>__cxa_demangle</tt> (like is done in tool <tt>c++filt</tt>):
{{pl2|
{{hidden|<tt>main.c</tt>
([{{#filelink: main.c}} download])|{{#fileanchor: main.c}}
<source lang="cpp">
<source lang="cpp">
void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext)
void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext)
Line 277: Line 279:
exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
}
</source>|headerstyle=background:#ccccff;text-align:left;}} }}
</source>


=== Getting function name from its address ===
=== Getting function name from its address ===

Revision as of 17:49, 30 September 2011

This is a general page on debugging tools, techniques, tips, etc.

Linux tools

addr2line

See addr2line page.

gdb

See gdb page.

C/C++ - Debugging with gcc

backtrace, backtrace_symbols, backtrace_symbols_fd

See manual page, or gcc manual.

int     backtrace            (void **      buffer, int size)
char ** backtrace_symbols    (void *const *buffer, int size)
void    backtrace_symbols_fd (void *const *buffer, int size, int fd)

Object and executables need to build with gcc -g -rdynamic!

gcc -o0 -g -rdynamic main.c -o myprogram

Short example:

#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>

void handler(int sig) {
  void *array[10];
  int size;

  size = backtrace(array, 10);                  // get void*'s for all entries on the stack

  fprintf(stderr, "Error: signal %d:\n", sig);  // print out all the frames to stderr
  backtrace_symbols_fd(array, size, 2);
  exit(1);
}

void baz() {
  int *foo = (int*)-1;                          // make a bad pointer
  printf("%d\n", *foo);                         // causes segfault
}

void bar() { baz(); }
void foo() { bar(); }

int main(int argc, char **argv) {
  signal(SIGSEGV, handler);                     // install our handler
  foo();                                        // this will call foo, bar, and baz.  baz segfaults.
  return 0;
}

It can also be used to print the symbol name of any function of which we know the address (a bit like SymFromAddr on windows):

#include <stdio.h>
#include <execinfo.h>

void foo(void) {
    printf("foo\n");
}

int main(int argc, char *argv[]) {
    void    *funptr = &foo;

    backtrace_symbols_fd(&funptr, 1, 1);

    return 0;
}


A very extensive answer on StackOverflow:

  • Using backtrace:
  • Demangling symbols in C++ by calling __cxa_demangle (like is done in tool c++filt):

Getting function name from its address

The following program show how to use the backtrace_symbols function to get the name of a function given its address. The program must be compiled with gcc options -g -rdynamic:

gcc -g -rdynamic -o0 main.c -o symfromaddr

libunwind (non-gnu)