Linux Users: Basic GDB

Discussion in 'Mac and Linux' started by atomicinf, June 15, 2013.

  1. atomicinf

    atomicinf New Member

    Likes Received:
    Uber was nice enough to include debug symbols in its Linux build. That means you can use GDB to generate some details if you run into a crash, to help Uber find and fix problems more easily - even though we don't have the source code.

    (Note that all ` in this guide, indicating commands to enter into the terminal, are not part of said commands and should not be entered into the terminal.)

    Getting GDB

    On Ubuntu, you can just type `sudo apt-get install gdb`. On Fedora/Red Hat, `sudo yum install gdb` should accomplish the same task. Other distributions have their own package managers.

    Running PA in GDB

    Open a command prompt and navigate to your PA directory. This is probably '~/.local/share/Steam/SteamApps/common/Planetary Annihilation', if you installed through Steam.

    Then, run `gdb PA`.

    You'll see something like this:
    GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
    Copyright (C) 2012 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-linux-gnu".
    For bug reporting instructions, please see:
    Reading symbols from /home/[YOURUSERNAME]/.local/share/Steam/SteamApps/common/Planetary Annihilation/PA...done.
    The (gdb) bit is the GDB prompt, where you enter commands into the debugger.

    To start PA running under GDB's supervision, just enter `run`.


    This is an alpha, so things like segmentation faults are to be expected. If PA crashes for any reason, GDB will freeze it and spit out something like the following

    Program received signal SIGSEGV, Segmentation fault.
    ClientGame::dispatch (this=0xc0b750, raw_event=...)
        at /home/jenkins/jobs/Planetary_Annihilation_Linux64/workspace/pa/live/client/client_main.cpp:831
    831	/home/jenkins/jobs/Planetary_Annihilation_Linux64/workspace/pa/live/client/client_main.cpp: No such file or directory.
    and give you a GDB prompt. To get a backtrace (list of function calls that got you here), just enter `backtrace`. You'll see something like this:

    #0  ClientGame::dispatch (this=0xc0b750, raw_event=...)
        at /home/jenkins/jobs/Planetary_Annihilation_Linux64/workspace/pa/live/client/client_main.cpp:831
    #1  0x000000000059bbb3 in crom::LinuxPlatform::dispatchEvents (this=0xc09810)
        at /home/jenkins/jobs/Planetary_Annihilation_Linux64/workspace/pa/live/engine/game/linux_platform.cpp:411
    #2  0x000000000040aca7 in main (argc=<optimized out>, argv=<optimized out>)
        at /home/jenkins/jobs/Planetary_Annihilation_Linux64/workspace/pa/live/engine/game/linux_game_main.cpp:101
    Each one of these numbered lines represents a 'frame', or context associated with a function call. You're in frame 0 by default, but can jump around frames by typing e.g. `frame 1`. Switching frames is especially useful if the crash happens somewhere that's not in fact Uber's code - for instance, in a 3rd party library. Crashes in 3rd party libraries might be being caused by Uber's code forgetting to do something.

    You can inspect function arguments in the current frame by using the `print` directive followed by any symbol name. For instance, in this example, if I'm in frame 0, `print raw_event` yields

    $2 = (const crom::UIEvent &) @0x7fffffffdf20: {eventType = 4, 
      inputSource = 1 '\001', inputIndex = 0 '\000', data = {85, 0}}
    We could also try to `print this`, which yields the less than helpful

    $3 = (ClientGame * const) 0xc0b750
    but notice the * in the parentheses? That tells us we can do `print *this` to hopefully get more information - a lot more:

    $4 = {<crom::Game> = {<crom::UIEventDispatcher> = {
          _vptr.UIEventDispatcher = 0x724cf0}, mPlatform = 0xc09810, 
        mLoaderThreadPool = {<zu::noncopyable> = {<No data fields>}, ptr = 
        0xc0aaa0, dtor = {<No data fields>}}, 
        mResourceSystem = {<zu::noncopyable> = {<No data fields>}, ptr = 0xc0bdd0, 
          dtor = {<No data fields>}}, 
        mMaterialLibrary = {<zu::noncopyable> = {<No data fields>}, ptr = 
        0xc0be80, dtor = {<No data fields>}}, 
        mRenderer = {<zu::noncopyable> = {<No data fields>}, ptr = 0x135f3f0, 
          dtor = {<No data fields>}}, ...
    But what are we really doing with all this? We're trying to give Uber a window into the exact state of PA at the moment of crash, so they know what to look for - and hopefully fix in time for the next build.

    We can restart PA by typing `run` again, or quit GDB by typing `quit`. Notice that quitting GDB kills PA.


    Pressing Ctrl-C in the GDB window stops PA in its tracks and gives you a debug prompt:

    Program received signal SIGINT, Interrupt.
    0x00007ffff5d03313 in __GI___poll (fds=<optimized out>, nfds=<optimized out>, 
        timeout=<optimized out>) at ../sysdeps/unix/sysv/linux/poll.c:87
    87	../sysdeps/unix/sysv/linux/poll.c: No such file or directory.
    We can then inspect things as if a segfault occurred, or type `continue` to continue the program flow as if nothing had happened.

    I take no responsibility for anything that happens should you try to deliberately interrupt PA mid-game.


    Anything you want to add? Post it here! Include a use case, preferably one PA-related.
  2. ImperialXT

    ImperialXT New Member

    Likes Received:
    Can a mod sticky this so that people see it first when they open up this sub forum.
  3. mcodl

    mcodl Member

    Likes Received:
    Thanks for this post atomicinf. I'll make sure to install it.

    EDIT: It was already installed for some reason. Possibly because of mono and some other developer stuff I have on my Linux laptop.

Share This Page