OpenWrt: Remote Debugging C/C++ Programs Using GDB

谨以此文献给Hoowa同志,江湖人称“火神”。 —— 题记


Introduction

为调试Linux机器上的C/C++程序,我们通常使用GDB. 但要调试那些在路由器上跑的C/C++程序,GDB还能胜任么?毕竟,我们又不能直接把源码搁到路由器上编译,在Linux机器上编的话还牵扯到交叉编译(Cross Compiling)。

答案是Yes. 在本文中,我就将给大家介绍如何搭建GDB调试环境,如何调试一个比Hello world复杂那么一点点的C程序的方法。

由于我使用的是OpenWrt 14.07 (Barrier Breaker),因此,也假设你也使用的这个版本并对如何编译ipk软件包有一定的了解。Barrier Breaker的官方仓库在这儿:

Compiling GDB Tools

在make menuconfig的时候启用GDB

以及gdbserver

Solution to the “Remote ‘g’ packet reply is too long” problem

在你编译之前呢,我这儿有一个免费的patch送给你,可以避免你以后遇到像下面这样儿式的问题:

700-fix-remote-g-packet-reply-too-long.patch

编译toolchain中的gdb和package中的gdbserver

  • 将700-fix-remote-g-packet-reply-too-long.patch搁到toolchain/gdb/patches/目录下

这时候, 你如果ls一下大约可以看到这些:

  • 编译gdb工具链

  • 编译准备安装到OpenWRT上的gdbserver

将gdbserver扔到路由器上并安装上

路由器上opkg怎么update,怎么装ipk包不用我说了吧?

Add debugging to a package

A more complex Hello world in C

File Listings

  • 文件清单列表如下:

hello/src/hello.c

hello/src/mytest.h

hello/src/mytest.c

hello/src/Makefile

hello/Makefile

Methods for adding debugging to a package

  • 法1: Add CFLAGS to package Makefile and recompile it. # 推荐

正如上面hello/Makefile文件做的那样,为hello软件包的Makefile添加CFLAGS。并重新编译

  • 法2: Recompile the package with CONFIG_DEBUG set # 设置CONFIG_DEBUG=y来编包

  • 法3: Enable debug info in menuconfig #在全局编译构造环境中启用调试开关

这法2和法3是OpenWrt官方wiki上(http://wiki.openwrt.org/doc/devel/gdb )提到的方法,没试验过。

请将编译好的带调试信息的hello软件包扔到路由器上安装。

Starting GDB

Start gdbserver on target (router)

路由器(IP为192.168.1.1)的9000端口上跑gdbserver

Start gdb on host (in compiling tree)

宿主系统(Host System,比如我的是Ubuntu最近的某个版本)上跑gdb

Now gdb shell is up. Set breakpoints, start program, backtrace etc.

这样gdb shell就起来了。设置断点, 启动程序,查看堆栈,就跟以前一样。

Tips

  • The output of hello got printed to the ROUTER console, rather than the Host system terminal.

注意,hello包的输出是打印到路由器的控制台(console/terminal)上的,而非宿主系统上。

  • Always try to use “target remote 192.168.1.1:9000” on Host System

In the gdb shell on the Host system, please always use “target remote 192.168.1.1:9000” to reconnect when the Router process brought up by gdbserver exits and then restarts, as in this way, your previous settings of breakpoints, watchpoints are reserved.

当路由器上gdbserver带起的进程退出后重新带起的时候,请不要直接将宿主系统上的gdb shell退出重进。在原gdb shell中使用”target remote 192.168.1.1:9000″即可,这样做的好处是,你原先关于断点、监测点的设定都会保留住。