Difference between revisions of "Debugging"

From WiiBrew
Jump to navigation Jump to search
(Initial information about remote debugging on gdb, still very basic)
 
(Added a bit more helpful info, and moved debugging tips from programming tips)
Line 1: Line 1:
 
==Remote Debugging with GDB==
 
==Remote Debugging with GDB==
devkitPro comes with gdb, the gnu debugger, which has been configured to allow remote debugging over the [[USB Gecko]].  You compile a stub of code into your wii program and run the debugger on your pc.  Firstly initialise the link with:
+
devkitPro comes with gdb, the gnu debugger, which has been configured to allow remote debugging over the USB Gecko.  You compile a stub of code into your wii program and run the debugger on your pc.  Firstly include the code which establishes the connection:
  
#include <debug.h>
+
    #include <debug.h>
  
DEBUG_Init(GDBSTUB_DEVICE_USB, 1);
+
    DEBUG_Init(GDBSTUB_DEVICE_USB, 1);
  
 
You can then manually insert breakpoint into your code with the line:
 
You can then manually insert breakpoint into your code with the line:
  
_break();
+
_break();
  
Your wii code must be linked with the option -ldb, included before other libraries such as -logc.
+
Your wii code must be compiled with the option -g linked with the option -ldb, included before other libraries such as -logc.
  
 
Start your wii code using normal means such as the homebrew channel.  Start gdb by typing:
 
Start your wii code using normal means such as the homebrew channel.  Start gdb by typing:
  
powerpc-gekko-gdb
+
powerpc-gekko-gdb
  
 
At the gdb command prompt, type:
 
At the gdb command prompt, type:
  
target remote /dev/ttyUSB0
+
target remote /dev/ttyUSB0
  
You can then continue running the program by typing "cont"
+
Tell gdb where to find symbol information by typing
 +
 
 +
symbol-file /path/to/elf/on/pc
 +
 
 +
You can then insert other break points manually by typing for example (assuming you are in the same directory as the source file):
 +
break sourcefile.c:linenum
 +
 
 +
You can then continue running the program by typing:
 +
 
 +
cont
 +
 
 +
Examine the value of variables by typing
 +
 
 +
print variablename
 +
 
 +
==Diagnosing crashes==
 +
When faced with a crash in your Homebrew, often you'll see a code dump with an address and some machine code.  Here's my trick to track that back to a line of C++ code.
 +
 
 +
For example if your homebrew game crashes it might show something like this:
 +
 
 +
    CODE DUMP:
 +
   
 +
    800084ac:  809F0020 2F840000 ...
 +
    800084bc:  ...
 +
    800084cc:  ...
 +
 
 +
The 800084ac is the memory address in hex of where the crash occurred.  809F0020 is the machine code for the offending instruction.
 +
 
 +
*Step 1:
 +
In your makefile change the CXXFLAGS line to the following:
 +
  CXXFLAGS = -save-temps -Xassembler -aln=$@.lst $(CFLAGS)
 +
The "-save-temps" will save the assembly language file, which can be interesting.
 +
The "-Xassembler -aln=$@.lst" creates a list file which contains the assembly and the machine code.
 +
Now recompile your entire project.
 +
Note, this just affects C++ code.
 +
 
 +
*Step 2:
 +
Look at the map file that was built.  The mapfile is on by default in the Wii template makefile. Typically it's in the build subdirectory and called something.map.  Look in that mapfile for the nearest memory address that doesn't go over the one found in the CODE DUMP.  Here is an example:
 +
    0x80008464                ShooterView::Render(BibGraphicsDevice&)
 +
This tells me that the crash was 72 bytes into the ShooterView::Render() function.  Now to find the line number in Render()
 +
 
 +
*Step 3:
 +
Look at the list file for the relevant function.  Here's an example:
 +
 
 +
    473              .globl _ZN11ShooterView6RenderER17BibGraphicsDevice
 +
    474              .type _ZN11ShooterView6RenderER17BibGraphicsDevice, @function
 +
    475              _ZN11ShooterView6RenderER17BibGraphicsDevice:
 +
    476              .LFB1465:
 +
    477              .loc 1 158 0
 +
    478              .LVL20:
 +
    479 02d0 9421FF00 stwu 1,-256(1)
 +
 
 +
The function names are mangled because this is C++ code.  See http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B
 +
The address of the first instruction of Render() is at 02d0.  This is also line 158 in the file (".loc 1 158 0").  To find the error location, just look at 0x2d0 + 72 = 0x318.  See below:
 +
 
 +
                                .loc 1 168 0
 +
    528 0314 809F0020 lwz 4,32(31)
 +
    529 0318 2F840000 cmpwi 7,4,0
 +
 
 +
This shows machine address 0x318 has the proper machine code and the nearest .loc statement says the problem is at line 168 of the ShooterView.cpp.
 +
For more info on the assembler output see the manual here:  http://sourceware.org/binutils/docs-2.18/as/index.html

Revision as of 09:48, 28 June 2008

Remote Debugging with GDB

devkitPro comes with gdb, the gnu debugger, which has been configured to allow remote debugging over the USB Gecko. You compile a stub of code into your wii program and run the debugger on your pc. Firstly include the code which establishes the connection:

   #include <debug.h>
   DEBUG_Init(GDBSTUB_DEVICE_USB, 1);

You can then manually insert breakpoint into your code with the line:

_break();

Your wii code must be compiled with the option -g linked with the option -ldb, included before other libraries such as -logc.

Start your wii code using normal means such as the homebrew channel. Start gdb by typing:

powerpc-gekko-gdb

At the gdb command prompt, type:

target remote /dev/ttyUSB0

Tell gdb where to find symbol information by typing

symbol-file /path/to/elf/on/pc

You can then insert other break points manually by typing for example (assuming you are in the same directory as the source file):

break sourcefile.c:linenum 

You can then continue running the program by typing:

cont

Examine the value of variables by typing

print variablename

Diagnosing crashes

When faced with a crash in your Homebrew, often you'll see a code dump with an address and some machine code. Here's my trick to track that back to a line of C++ code.

For example if your homebrew game crashes it might show something like this:

    CODE DUMP:
    
    800084ac:   809F0020 2F840000 ...
    800084bc:   ...
    800084cc:   ...

The 800084ac is the memory address in hex of where the crash occurred. 809F0020 is the machine code for the offending instruction.

  • Step 1:

In your makefile change the CXXFLAGS line to the following:

  CXXFLAGS = -save-temps -Xassembler -aln=$@.lst $(CFLAGS)

The "-save-temps" will save the assembly language file, which can be interesting. The "-Xassembler -aln=$@.lst" creates a list file which contains the assembly and the machine code. Now recompile your entire project. Note, this just affects C++ code.

  • Step 2:

Look at the map file that was built. The mapfile is on by default in the Wii template makefile. Typically it's in the build subdirectory and called something.map. Look in that mapfile for the nearest memory address that doesn't go over the one found in the CODE DUMP. Here is an example:

    0x80008464                ShooterView::Render(BibGraphicsDevice&)

This tells me that the crash was 72 bytes into the ShooterView::Render() function. Now to find the line number in Render()

  • Step 3:

Look at the list file for the relevant function. Here's an example:

   473              		.globl _ZN11ShooterView6RenderER17BibGraphicsDevice
   474              		.type	_ZN11ShooterView6RenderER17BibGraphicsDevice, @function
   475              	_ZN11ShooterView6RenderER17BibGraphicsDevice:
   476              	.LFB1465:
   477              		.loc 1 158 0
   478              	.LVL20:
   479 02d0 9421FF00 		stwu 1,-256(1)

The function names are mangled because this is C++ code. See http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B The address of the first instruction of Render() is at 02d0. This is also line 158 in the file (".loc 1 158 0"). To find the error location, just look at 0x2d0 + 72 = 0x318. See below:

                               .loc 1 168 0
   528 0314 809F0020 		lwz 4,32(31)
   529 0318 2F840000 		cmpwi 7,4,0

This shows machine address 0x318 has the proper machine code and the nearest .loc statement says the problem is at line 168 of the ShooterView.cpp. For more info on the assembler output see the manual here: http://sourceware.org/binutils/docs-2.18/as/index.html