Jump to content
Eternal Lands Official Forums
Sign in to follow this  
Wytter

Crashcourse in debugging

Recommended Posts

Hey all,

 

This note on debugging methods is primarially targetted at GNU/Linux and *BSD users but should also work for Windows users who use a Cygwin environment (if you don't know what it is, this doesn't apply to you at all).

 

The pre-requirements for helping debugging the EL client is:

 

*) The latest CVS client

- If you run into an error, try doing a new checkout and see if the problem persists. If it's still there, it will most likely be a bug and if you are not able to see a bug report describing the error you're experiencing on these forums, you should report it.

 

*) The GCC compiler or similiar capable of compiling with debugging flags.

- For GCC you only need to add the -ggdb keyword to the compiler flags. The default target in the Makefile.linux and Makefile.bsd already use these keywords.

 

*) The GDB (The GNU Project Debugger) or similiar

- http://www.gnu.org/software/gdb/gdb.html

 

If you run into an error and you're willing to help us more than just reporting the bug, you can help us fix it by using a debugger and learning some simple commands. This small crashcourse should be able to give you the info you need to debug the EL client and give us sufficient information to find the source of the error.

 

Keywords:

Debugging: Debugging is the concept of finding and resolving bugs/crashes etc.

Backtrace: Through a backtrace we can obtain information of what happened before the crash. Through this, we can see what happened prior to the crash and where the crash happened.

 

Step 1:

Compile the client with the default flags:

make clean
make -f Makefile.linux

 

Step 2:

Open the client in the GDB debugger:

gdb el.x86.linux.bin

 

Here's how the console should be looking:

bjorn@darkhelmet elc $ gdb el.x86.linux.bin
GNU gdb 6.2.1
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) 

 

Step 3:

Let's run the beast.

To run the client, you just need to write "run". If you wish to run the game with some command line arguments, you should put these after "run".

(gdb) run <arguments>

 

You should see the following window:

 

Starting program: /home/bjorn/elsrc/dev/elc/el.x86.linux.bin
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
[Thread debugging using libthread_db enabled]
[New Thread 182915818272 (LWP 2867)]
[New Thread 1082128736 (LWP 2870)]
[New Thread 1090517344 (LWP 2871)]
[Thread 1090517344 (zombie) exited]

 

Step 4:

Shit! The client crashed. But where and how?

If the client crashes the window will not close, however you will get info that an error has occured. In this case I made a mistake on purpose (tried accessing a NULL-pointer) and caused the client to crash. You'll see something similiar to the following:

 

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 182915818272 (LWP 2867)]
0x000000000043a436 in HandleEvent (event=0x7fbffff2d0) at events.c:46
46              actors_list[200]->x_pos=0;
(gdb)

Of course the location of the error will not be the same - the main idea is just that you remember to copy the lines "Program recieved signal ..." to (gdb) (the debugger console).

 

 

Step 5 (Optional):

Getting variables values

Now, the first thing you'd do to check what could cause this to happen would be trying to get the value of the variable that caused the crash.

(gdb) print actors_list[200]
$1 = (actor *) 0x0
(gdb)

Oh, so we tried accessing a NULL-pointer - that'll explain the error :icon13:

If you do not know how to do this or if this step confuses you due to lack of programming experience, you can jump to the backtrace.

 

Step 6:

The backtrace

Now, in most cases the error will not be that obvious, and we'd need a backtrace to figure out what happened. To get a backtrace do the following:

 

(gdb) backtrace
#0  0x000000000043a436 in HandleEvent (event=0x7fbffff2d0) at events.c:46
#1  0x000000000044de05 in start_rendering () at main.c:48
#2  0x000000000044e106 in main (argc=1, argv=0x7fbffff3f8) at main.c:149
(gdb)

 

It'll simply show the latest function calls, and that can be used to locate the error. We would also prefer if you could attach a "backtrace full", which holds more information about what happened in the last miliseconds before the crash.

 

----

 

There's a more thorough guide here:

http://www.delorie.com/gnu/docs/gdb/gdb_toc.html

 

If you want a debugging GUI, I will recommend the DDD debugger:

http://www.gnu.org/software/ddd

 

----

 

Now, this was a short introduction to debugging. If you have any questions or additions, feel free to post below.

Share this post


Link to post
Share on other sites

Addition to step 4: if you don't want to look up the source, you can use the "list" command to show the adjacing code lines or other portions of the source:

 

list
41      {
42              int done = 0;
43              Uint32 key = 0;
44              Uint32 flags = 0;
45
46              if (event->type == SDL_NOEVENT) return 0;
47
48              mod_key_status = SDL_GetModState();
49
50              if (mod_key_status & KMOD_SHIFT) shift_on = 1;
(gdb) list 41
36                      }
37              }
38      }
39
40      int HandleEvent (SDL_Event *event)
41      {
42              int done = 0;
43              Uint32 key = 0;
44              Uint32 flags = 0;
45
(gdb) bt
#0  HandleEvent (event=0xbfffed40) at events.c:46
#1  0x0807c56e in start_rendering () at main.c:91
#2  0x0807c813 in main (argc=1, argv=0x1) at main.c:213
(gdb) list main.c:91
86                              SDL_Event event;
87
88                              // handle SDL events
89                              while( SDL_PollEvent( &event ) )
90                                      {
91                                              done = HandleEvent(&event);
92                                      }
93
94                              //advance the clock
95                              cur_time = SDL_GetTicks();

 

With regards

Lachesis

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×