Backtrace

Differences between revisions 34 and 41 (spanning 7 versions)
Revision 34 as of 2009-03-05 18:18:39
Size: 5674
Editor: 168
Comment: Apport can now be enabled manually to get traces
Revision 41 as of 2022-12-20 22:15:16
Size: 6286
Editor: sergiodj
Comment: Add information regarding debuginfod
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
A backtrace shows a listing of which program functions are still active.  Since functions are nested when they are called, the program must record where it left one function, to jump into an inner one.  It does this on the stack, which we dump for the backtrace.
= Introduction =

A backtrace shows a listing of which program functions are still active. Since functions are nested when they are called, the program must record where it left one function, to jump into an inner one. It does this on the stack, which we dump for the backtrace.
Line 7: Line 10:
When using KDE the KDE Crash Handler will intercept debugging information. However, it is possible to disable the KDE Crash Handler when you are launching an application by passing the --nocrashhandler argument to the application. For example, 'kget --nocrashhandler' instead of 'kget'. = Prepare your environment to gather a backtrace =
Line 9: Line 12:
Please also note that since '''Ubuntu Jaunty 9.04''', the Apport automated retracing tool can be enabled manually, in order to get traces for a specific crash. This is the recommended way to get traces from bug reporters, avoiding them the need for complex manipulations. See [[https://wiki.ubuntu.com/Apport#How%20to%20enable%20apport|How to enable apport]] to find out how you can do so. By default, a program called [[https://wiki.ubuntu.com/Apport|apport]] is enabled and running, which preempts gdb. However, to gather a backtrace manually, apport needs to be disabled first. One may do this via a terminal: {{{
sudo nano /etc/default/apport }}}
Line 11: Line 15:
= Generation =
<<Anchor(generation)>>
Please ensure you have packages with debug symbols installed. You can do this by following the instructions at DebuggingProgramCrash.
and change: {{{
enabled=1 }}}
Line 15: Line 18:
 1. Make sure the GNU Debugger is installed. {{{
sudo apt-get install gdb
}}}
 1. Start the program under control of `gdb`: {{{
gdb <program> 2>&1 | tee gdb-<program>.txt
(gdb) handle SIG33 pass nostop noprint
(gdb) set pagination 0
(gdb) run <arguments, if any>
}}} (If the program must run as root, use {{{sudo gdb}}} instead of just {{{gdb}}} above.)
 1. The program will start. Perform any actions necessary to reproduce the crash. If the program hangs but doesn't crash you can press ctrl+c in gdb while the program is frozen and then continue with the next step.
 1. Retrieve a backtrace: {{{
(gdb) backtrace full
(gdb) info registers
(gdb) thread apply all backtrace
(gdb) quit
}}}
 1. Attach the complete output from GDB, contained in gdb-<program>.txt, in your bug report. You will find the file in your home directory /home/<username>/.
to: {{{
enabled=0 }}}

save, close, and restart.

== Kubuntu ==

When using KDE, the KDE Crash Handler will intercept debugging information. However, it is possible to disable the KDE Crash Handler when you are launching an application by passing the --nocrashhandler argument to the application. For example, running the program from a terminal via: {{{
kget --nocrashhandler
Line 36: Line 31:
mono --debug /usr/lib/f-spot/f-spot.exe mono --debug /usr/lib/f-spot/f-spot.exe }}}

= Generation =
<<Anchor(generation)>>
 1. If you are on Ubuntu Jammy (22.04) or later, you do '''not''' need to worry about installing debug symbol packages anymore. The Ubuntu project maintains a [[https://debuginfod.ubuntu.com|Debuginfod]] server, and GDB and other debuginfo-consumer applications support it out of the box. For more information about it, please refer to [[https://ubuntu.com/server/docs/service-debuginfod|this page]]. Otherwise, if you are on an older Ubuntu release (pre-Jammy), please ensure you have packages with debug symbols installed. You can do this by following the instructions at DebuggingProgramCrash.
 1. Make sure the GNU Debugger is installed. {{{
sudo apt-get install gdb }}}
 1. Start the program under control of `gdb` via a terminal (some programs run as root, so one would use {{{sudo gdb}}} instead of just {{{gdb}}} below): {{{
gdb <program> 2>&1 | tee ~/gdb-<program>.txt
(gdb) handle SIG33 pass nostop noprint
(gdb) set pagination 0
(gdb) run <arguments, if any>
Line 38: Line 44:
 1. The program will start. Perform any actions necessary to reproduce the crash. If the program hangs but doesn't crash you can press ctrl+c in gdb while the program is frozen and then continue with the next step.
 1. Retrieve a backtrace: {{{
(gdb) backtrace full
(gdb) info registers
(gdb) x/16i $pc
(gdb) thread apply all backtrace
(gdb) quit }}}
 1. Attach the complete output from GDB, contained in gdb-<program>.txt, in your bug report. You will find the file in your home directory /home/<username>/.
Line 41: Line 55:
You can ask GDB to attach to a program that's already running.  This is useful for debugging things that start up, but crash when you perform a particular task. You can ask GDB to attach to a program that's already running. This is useful for debugging things that start up, but crash when you perform a particular task.
Line 43: Line 57:
 1. Make sure the GNU Debugger is installed.  {{{
sudo apt-get install gdb
}}}
 1. Make sure the GNU Debugger is installed. {{{
sudo apt-get install gdb }}}
Line 48: Line 61:
pidof <program>
}}}
pidof <program> }}}
Line 51: Line 63:
 1. Start `gdb`: {{{  1. Start `gdb` (some programs run as root, so one would use {{{sudo gdb}}} instead of just {{{gdb}}} below): {{{
Line 55: Line 67:
(gdb) attach <PID>
}}} (If the program is running as root, use {{{sudo gdb}}} instead of just {{{gdb}}} above.)
(gdb) attach <PID> }}}
Line 59: Line 70:
(gdb) continue
}}}
(gdb) continue }}}
Line 62: Line 72:
 1. The program will continue running.  Perform any actions necessary to reproduce the crash. If the program hangs but doesn't crash you can press ctrl+c in gdb while the program is frozen and then continue with the next step.  1. The program will continue running. Perform any actions necessary to reproduce the crash. If the program hangs but doesn't crash you can press ctrl+c in gdb while the program is frozen and then continue with the next step.
Line 67: Line 77:
(gdb) x/16i $pc
Line 68: Line 79:
(gdb) quit
}}}
(gdb) quit }}}
Line 75: Line 85:
(gdb) set logging on
}}}
(gdb) set logging on }}}
Line 80: Line 89:
You are also able to retrace a core file if you have one produced. (I believe these are disabled by default) You are also able to retrace a core file if you have one produced (I believe these are disabled by default).
Line 83: Line 92:
 gdb -c <corefile> 2>&1 | tee gdb-<program>.txt
}}}
 gdb -c <corefile> 2>&1 | tee gdb-<program>.txt }}}
Line 89: Line 97:
(gdb) x/16i $pc
Line 90: Line 99:
(gdb) quit
}}}
(gdb) quit }}}
Line 96: Line 104:
Line 101: Line 110:
Line 103: Line 111:
  * make it executable

{{{
  * make it executable {{{
Line 107: Line 113:
Line 127: Line 132:

Line 144: Line 147:
    -ex 'x/16i $pc' \
Line 148: Line 152:

Debugging Central

This page is part of the debugging series — pages with debugging details for a variety of Ubuntu packages.

Introduction

A backtrace shows a listing of which program functions are still active. Since functions are nested when they are called, the program must record where it left one function, to jump into an inner one. It does this on the stack, which we dump for the backtrace.

By getting a backtrace at the point of a bug, a developer may be able to isolate where that bug is, because it will narrow down to the function, or even the line, that caused the erroneous behaviour.

Prepare your environment to gather a backtrace

By default, a program called apport is enabled and running, which preempts gdb. However, to gather a backtrace manually, apport needs to be disabled first. One may do this via a terminal:

sudo nano /etc/default/apport 

and change:

enabled=1 

to:

enabled=0 

save, close, and restart.

Kubuntu

When using KDE, the KDE Crash Handler will intercept debugging information. However, it is possible to disable the KDE Crash Handler when you are launching an application by passing the --nocrashhandler argument to the application. For example, running the program from a terminal via:

kget --nocrashhandler

= Applications using Mono =

To obtain a backtrace from a Mono application such as Beagle or F-Spot, use Mono's {{{--debug

option, e.g.

mono --debug /usr/lib/f-spot/f-spot.exe 

Generation

  1. If you are on Ubuntu Jammy (22.04) or later, you do not need to worry about installing debug symbol packages anymore. The Ubuntu project maintains a Debuginfod server, and GDB and other debuginfo-consumer applications support it out of the box. For more information about it, please refer to this page. Otherwise, if you are on an older Ubuntu release (pre-Jammy), please ensure you have packages with debug symbols installed. You can do this by following the instructions at DebuggingProgramCrash.

  2. Make sure the GNU Debugger is installed.

    sudo apt-get install gdb 
  3. Start the program under control of gdb via a terminal (some programs run as root, so one would use sudo gdb instead of just gdb below):

    gdb <program> 2>&1 | tee ~/gdb-<program>.txt
    (gdb) handle SIG33 pass nostop noprint
    (gdb) set pagination 0
    (gdb) run <arguments, if any>
  4. The program will start. Perform any actions necessary to reproduce the crash. If the program hangs but doesn't crash you can press ctrl+c in gdb while the program is frozen and then continue with the next step.
  5. Retrieve a backtrace:

    (gdb) backtrace full
    (gdb) info registers
    (gdb) x/16i $pc
    (gdb) thread apply all backtrace
    (gdb) quit 
  6. Attach the complete output from GDB, contained in gdb-<program>.txt, in your bug report. You will find the file in your home directory /home/<username>/.

Already running programs

You can ask GDB to attach to a program that's already running. This is useful for debugging things that start up, but crash when you perform a particular task.

  1. Make sure the GNU Debugger is installed.

    sudo apt-get install gdb 
  2. Find the process ID of <program>:

    pidof <program> 
  3. Start gdb (some programs run as root, so one would use sudo gdb instead of just gdb below):

    gdb 2>&1 | tee gdb-<program>.txt
    (gdb) handle SIG33 pass nostop noprint
    (gdb) set pagination 0
    (gdb) attach <PID> 
  4. Continue the <program>:

    (gdb) continue 
  5. The program will continue running. Perform any actions necessary to reproduce the crash. If the program hangs but doesn't crash you can press ctrl+c in gdb while the program is frozen and then continue with the next step.
  6. Retrieve a backtrace:

    (gdb) backtrace full
    (gdb) info registers
    (gdb) x/16i $pc
    (gdb) thread apply all backtrace
    (gdb) quit 
  7. Attach the complete output from GDB, contained in gdb-<program>.txt, in your bug report.

Note that you can also set logging to a file like this:

(gdb) set logging file gdb-<program>.txt
(gdb) set logging on 

Core Files

You are also able to retrace a core file if you have one produced (I believe these are disabled by default).

  1. Load the core file into the debugger

     gdb -c <corefile> 2>&1 | tee gdb-<program>.txt 
  2. Retrieve a backtrace of the crash:

    (gdb) backtrace full
    (gdb) info registers
    (gdb) x/16i $pc
    (gdb) thread apply all backtrace
    (gdb) quit 
  3. Attach the complete output from GDB, contained in gdb-<program>.txt, in your bug report. You will find the file in your home directory /home/<username>/.

Other resources

Summary in script form

You can automate backtrace collection as described above using this Bourne shell script:

  • save it somewhere in your $PATH
  • make it executable

    #---------------------------------------------------------------------
    usage() {
        cat<<EOF
    Usage: ${0} program_name [program_args]
    
    Trace a given program using gdb.
    
    EOF
    }
    
    log() {
        echo "${*}" 1>&2
    }
    
    die() {
        usage
        log 'error:' ${*}'.'
        exit 1
    }
    #---------------------------------------------------------------------
    test "x${*}" = "x" && die 'no process given'
    
    LOG="/tmp/gdb-`basename ${1}`.txt"
    log "outputting trace to '${LOG}'"
    
    exec gdb -batch-silent \
        -ex 'set logging overwrite on' \
        -ex "set logging file ${LOG}" \
        -ex 'set logging on' \
        -ex 'handle SIG33 pass nostop noprint' \
        -ex 'set pagination 0' \
        -ex 'run' \
        -ex 'backtrace full' \
        -ex 'info registers' \
        -ex 'x/16i $pc' \
        -ex 'thread apply all backtrace' \
        -ex 'quit' \
        --args ${*} \
        < /dev/null


CategoryBugSquad CategoryDebugging

Backtrace (last edited 2022-12-20 22:15:16 by sergiodj)