Welcome, Guest!

Here are some links you may find helpful

How to setup GDB debugging in Linux with Redream

Cooljerk

Well-known member
Original poster
Jun 8, 2019
47
53
18
AGName
The Perfect K
I took a peak in the "60 fps codes" topic here just a moment ago and noticed a line about "the absence of an emulator with debugging options." Redream used to have a built in gdb debugger but it was stripped out ages ago. Despite this, you CAN use redream with GDB to debug dreamcast applications, pretty easily too:

First thing, make sure you are using the same version of dcload-ip and dctool-ip. I actually struggled for a couple of years to get gdb debugging going due to what I assume was somehow a version mismatch on my end, until @SiZiOUS released his latest versions of dctool-ip and dcload-ip within the last yearish. Building both tools from source form his latest versions solved the version mismatch problem I was running into and everything went smooth from there.

The version mismatch error I was receiving manifested in two ways. First, the actual dcload-ip idle screen was green, not blue as many people reported, which should have actually tipped me off that it was an old version. Second, even though I could transmit and load elf files from the dreamcast through through the mismatched versions of dcload-ip and dctool-ip, gdb itself would crash. You could tell this was happening, because anytime I used the gdb_init() function call in my program, the program would hang. By moving the call around a series of printfs, I could tell it was that specific function that would make my program hang. What is supposed to happen is that, when you call that function, it should print out "waiting for gdb connection..." or something similar. With a version mismatch, that statement never printed out and I was never able to advance, the entire command prompt would just hang.

After matching the versions by building the tools myself from Siz's latest source, connecting gdb to the dreamcast was a snap. Once your program says "waiting for gdb..." in the terminal, open up another terminal window and launch sh-elf-gdb. You also need to build sh-elf-gdb, you can do so by downloading the gdb source here:


and building using the following options (ignore the version number in this example):

Code:
   /home/linus> cd build/gdb
   /home/linus/build/gdb> ../../gdb-6.6/configure --target=sh-elf --prefix=/home/linus/sh1
   /home/linus/build/gdb> make
   /home/linus/build/gdb> make install

Alternatively, the dc-chain folder in KOS has a makefile to build and install sh-elf-gdb for you. Navigate to the dc-chain folder in your KOS director and

Code:
make gdb

Once you launch sh-elf-gdb, you connect to your Dreamcast by using the command:

Code:
target remote :2159

That tells GDB that you want to debug a remote application on the network, which is communicating through localhost:2159. You don't actually need to write the localhost bit, hence the ":2159" in the command. That'll connect GDB to your dreamcast. However, since this is a remote application, GDB won't have any of the debug symbols loaded, so you need to do that manually. To do that, use the command

Code:
file <path_to_ef>

to load the debug symbols from your program. The "path to elf" is the local path on your PC that you submitted to your dreamcast via dcload/dctool. Make sure your source is built with the -g command flag to preserve debug symbols. Another quibble I ran into is that the cross compiler KOS uses expects the -g command to be the very first argument. So if your argument list for kos-cc is like "-W -O2 blah" you need to make sure that the -g command comes at the very front of all other commands. Similarly, when you launch dctool-ip, make sure the -g command is the very first argument sent. I dunno if this weirdness regarding the placement of the -g command in my arguments list is a quirk of my particular setup, but just a tip.

Once you load the debug symbols by loading the elf into gdb, you can use it like any other session of gdb. I have noticed, however, if you don't properly exit your dreamcast title (i.e. if you turn off your dreamcast while it's running the program, instead of implementing a quit key into your program) that the port gdb uses, :2159, remains connected for a long while unless you manually kill it, and dctool-ip similarly stays running. to kill it, use the command

Code:
sudo netstat -ap | grep :2159

in a terminal to list the pid of the program connected to that port. It'll usually bd dctool itself. Note the pid of the program, and use the command

Code:
sudo kill <pid>

to end the use of that port. If you don't do this, when you next try to launch your program, as soon as "waiting for gdb..." appears, it'll report a gdb buffer overflow error and crash.

This isn't a problem, however, if you properly exit your program. That is done by letting your main function return. I do this by calling out to a looping function which is gated by a global static variable, and changing that variable breaks the loop, which returns to main, which itself returns. If you do that, once your program ends, dcload-ip will blank the screen and idle until you send another elf across dctool-ip. Similarly, if your program actually crashes and you still have gdb connected, you can send the quit command (q) from gdb and it'll ask if you want to terminate your debugging session. Doing so will cause your dreamcast to soft reboot and go back to dcload-ip, freeing the port. Exiting your program in either of these ways saves you the hassle of having the use netstat and kill the port.

Similar to the above, redream in linux offers a non-documented --serial command line option. If you use this, it'll emulate a serial link from redream. In this example, rather than using dcload-ip and dctool-ip, you use dcload-ser and dctool-ser to foster the connection. The gist of it all is that the --serial command needs to be pointed at a serial device in linux, usually /dev/tty0 or something. Instead, we use a program called socat to create a virtual serial link between two aribtrary files in linux and route redream to that.

I have a script which does everything for me, that I'll paste snippets from to explain how to do this. Major thanks to inolen, the author of redream, for the advice on using socat to create terminal output in the first place:

Code:
socat pty,raw,echo=0,link=/home/gabe/tty0 pty,raw,echo=0,link=/home/gabe/tty1> /dev/null 2>&1 &

This command creates a simulated serial link between the arbitrarily created files /home/gabe/tty0 and /home/gabe/tty1. The stuff on the right, if you're unfamiliar, is some stuff to manage output of the script.

Code:
/home/gabe/redream/redream --serial=/home/gabe/tty0 /home/gabe/Projects/DreamcastFramework/dcload2.cdi> /dev/null 2>&1 &

I launch redream with the secret --serial function and point it to my ~/tty0 file and also send my dcload executable.

Code:
sleep 15

xfce4-terminal -e "/home/gabe/dc-load-ip/dcload-ip-master/host-src/tool/dc-tool-ser -g -t $HOME/tty1 -x /home/gabe/Projects/DreamcastFramework/DreamcastFramework/program.elf"

I sleep a bit in my script to give redream time to boot and wait in the dcload idle screen, then I open a new terminal window and launch dc-tool-ser from it. The command argument list includes the -g flag I mentioned earlier (again, first in the argument list) then a -t command to target ~/tty1 as the connection point, then I use the -x flag to automatically send my program elf.

Code:
sleep 8

socat pty,link=/home/gabe/tty0,raw tcp:localhost:2159 &

I sleep again a bit to give dc-tool and dc-load some time to send the elf and launch it, then I use socat to set up a virtual link between the file ~/tty0 and the tcp localhost port 2159.

To make sure you get conceptually what's happening here, we have redream, which is using a file called tty0 as a link to it's emulated serial port. That file tty0 is using a program socat to simulate a serial connection with another file called tty1. dctool-ser is pointing to tty1 like it's a mount point for a real serial connection on your PC and transmitting data through it. We then use socat again to create a second virtual link between tty0 and our localhost tcp port :2159, which is the port gdb uses to communicate.

Once that's done, we can connect sh-elf-gdb to our tty0 file and we're good to go:

Code:
sh-elf-gdb -ex "target remote /home/gabe/tty0" "/home/gabe/Projects/DreamcastFramework/DreamcastFramework/program.elf"

this is a combined command to launch sh-elf-gdb to automatically remote connect to tty0, and also to automatically load my elf file for debug symbols.

All said and done:
D_fGHp1XkAAbUdJ


Happy debugging!
 

Make a donation