Skip to content

Remote debugging with gdbserver

Frans de Jonge edited this page Jun 21, 2020 · 17 revisions

Making a debug build

First of all, you need to make a debug build. The easiest way is to use the kodev script in front with a --debug flag, for example:

kodev release --debug pocketbook

Alternatively you can use:

make KODEBUG=1

Disable stripping in koreader-base

Edit koreader-base/Makefile. Find the following lines and comment them as below:

#ifndef EMULATE_READER
#       $(STRIP) --strip-unneeded \
#               $(OUTPUT_DIR)/extr \
#               $(OUTPUT_DIR)/sdcv \
#               $(LUAJIT) \
#               $(OUTPUT_DIR)/libs/*.so*
#endif

koreader-base building settings

Edit koreader-base/Makefile.defs. Look for the following line and comment it as below:

#BASE_CFLAGS:=-O2 -ffast-math -pipe -fomit-frame-pointer

And uncomment the following line:

BASE_CFLAGS:=-O0 -g

For kindles with gdb 6.6 buildin, which only reads DWARF2, -gdwarf-2should also be used.

LuaJIT building settings

Edit koreader-base/luajit-2.0/src/Makefile. Look for and uncomment the following lines:

CCDEBUG= -g

For kindles, -gdwarf-2 should be added to avoid Dwarf error.

XCFLAGS+= -DLUAJIT_USE_GDBJIT
XCFLAGS+= -DLUA_USE_APICHECK
XCFLAGS+= -DLUA_USE_ASSERT

The LUA_USE_APICHECK and LUA_USE_ASSERT are not really needed for our purpose (using remote gdb), but they are often useful for debugging koreader-base.

You may also want to enable Valgrind support, although for this to be useful we still would need to build a valgrind package able to run in the Kindle or in the Kobo (currently not done yet).

XCFLAGS+= -DLUAJIT_USE_VALGRIND

IMPORTANT NOTICE

Most of this applies to the old buildsystem, since the move to CMake, things have changed a bit. Raw braindump incoming:

  • -Og is nice if the GCC version handles it
  • libpng fails to link w/ -g3, use -g
  • We don't have the luajit tree from a clean checkout with the new CMake stuff, so just add CCDEBUG=\"-g\" XCFLAGS=\"-DLUAJIT_USE_GDBJIT -DLUA_USE_APICHECK -DLUA_USE_ASSERT\" after TARGET_FLAGS in thirdparty/luajit/CMakeLists.txt
  • Disable stripping by simply passing STRIP=true to make
  • Kill some stray hardcoded -O3... sed -e 's/-O3//g' -i third.Makefile thirdparty/libk2pdfopt/CMakeLists.txt && sed -e 's/-DCMAKE_BUILD_TYPE=Release/-DCMAKE_BUILD_TYPE=Debug/g' -i third.Makefile && sed -e 's/-DNDEBUG=1//' -i thirdparty/kpvcrlib/CMakeLists.txt

Build it

Build KOReader as usual. For the Kindle:

make customupdate

Or for the Kobo:

make TARGET_DEVICE=KOBO koboupdate

Running in your device

Installing gdbserver

The Kindle comes with gdbserver pre-installed, at least on FW 5.x, so you don't need to install any additional software in the device.

However, if your device is a Kobo, or a Kindle with a previous FW that does not come with gdbserver, you can download a Debian package and extract the executable.

You can extract the executable as follows:

ar x gdbserver_*.deb
tar zxvf data.tar.gz ./usr/bin/gdbserver

Setting up gdbserver

Edit the shell script koreader.sh or koreader_kobo.sh present in your device. Look for the line which calls reader.lua:

./reader.lua "$@" 2> crash.log

Prefix the line with gdbserver :2345 ./luajit ./koreader-base . You might also want to remove 2> crash.log if you are launching KOReader from a ssh session. For example:

gdbserver :2345 ./luajit ./koreader-base ./reader.lua "$@"

For kindles, Add this line to the Iptables part.

iptables -A INPUT -i wlan0 -p tcp --dport 2345 -j ACCEPT

Now launch KOReader. It will wait for your computer to connect to gdbserver before proceeding.

Debugging from your computer

Suppose the IP address of your device is 192.168.15.244 (which is the default IP address for Kindle with USBNet). Change if your device has another address.

Go to the directory where you built KOReader and do a cd koreader-arm-*/koreader. Start gdb-multiarch. In the (gdb) prompt, inform the architecture, load the symbols, and connect to your device:

set gnutarget elf32-littlearm
file luajit
target remote 192.168.15.244:2345

Now set any breakpoints you might want to set, then issue the continue command to start running.

Workaround for debugging shared libraries

If you need to set any breakpoints in code outside the main luajit executable, a little trick is needed. For some reason, when using this kind of remote debugging, gdb currently only loads symbols from the libraries if you instruct do to it after the program is already running. So, after you issued continue in gdb prompt, interrupt execution (pressing the keys Ctrl+C in gdb-multiarch, not in the device), and enter the following command:

set solib-search-path libs

Then, symbols from the shared libraries should be loaded.