项目需要,交叉编译本地版gdb 6.5
预读
首先明确configure的三个参数:
–build : 运行交叉编译器的环境
–host : 编译出的可执行文件的执行环境
–target : 编译出的可执行文件执行后能产生的文件的执行环境
所有值默认都等于–build,–build默认为本机环境,–target默认为–host
比如 在gcc源码目录:
$ ./configure CC=arm-linux-gcc –build=i686-pc-linux –host=arm-linux –target=mips
在intel pc上编译产生arm上运行的gcc,在arm平台运用产生的gcc编译mips上执行的程序
0. 嵌入式应用gdb调试
嵌入式应用gdb调试主要有两种方法:
PC端调试
这是主流方法,进入gdb目录,交叉编译时./configure 重要参数
--build=i686-pc-linux
--host=i686-pc-linux
--target=arm-linux
交叉编译产生的arm-linux-gdb在PC端运行
进入gdbserver目录,交叉编译./configure 时重要参数:
--build=i686-pc-linux
--host=arm-linux
--target=arm-linux
交叉编译产生的gdbserver放在arm设备上
过程:调试时,arm设备上打开gdbserver,附加至应用程序进程,在PC端通过arm-linux-gdb设置端口连接gdbserver调试。整个过程两者间通信类似于CS架构通信
arm-linux-gdb功能有限,一般可采用PC端的gdb代替之进行调试;另外PC和设备之间需要至少一种方式通信,串口与网络皆可,关于gdbserver通过串口调试方法,可自行搜索;由于作者所用设备只能通过串口调试,且串口有其他调试信息输出,故不采用此方式。
设备本地gdb调试
交叉编译时./configure 的重要参数
CC=arm-linux-gcc
--build=i686-pc-linux
--host=arm-linux
--target=arm-linux
过程:交叉编译产生arm设备上运行的gdb,直接在arm设备上运行gdb,调试应用程序。
本文主要讨论此种方法。
1. 交叉编译本地版gdb
交叉编译gdb时,与PC端的arm-linux-gcc的版本是相关的,过低版本的arm-linux-gcc不能交叉编译版本太高的gdb,本机的编译环境如下:
arm-linux-gcc:4.3.2
gdb-src :6.5
libncurses :5.6
arm-linux : 2.6.34
下载:
由于gdb依赖于termcap库,现在这个库可以通过ncurses来代替,所以先交叉编译产生libncurses,我选择的5.6版本
交叉编译ncurses
解压
$ tar zxvf ncurses-5.6.tar.gz
$ cd ncurses-5.6
配置环境
$ CC=arm-linux-gcc ./configure --build=i686-pc-linux --host=arm-linux --prefix=$HOME/arm/ncurses --without-ada --enable-termcap --with-shared
以上产生Makefile,其中./configure 参数含义:
CC=arm-linux-gcc 使用arm-linux-gcc交叉编译器
–prefix=$HOME/arm/ncurses 将生成ncurses的相关文件安装在$HOME/arm/ncurses目录下
–without-ada 不编译ada库
–enable-termcap 支持termcap,这个很重要
–with-shared 以动态库形式封装libncurses
make
$ make
make install
$ make install
然后在$HOME/arm/ncurses看到如下文件:
ncurses/ ├── bin │ ├── captoinfo -> tic │ ├── clear │ ├── infocmp │ ├── infotocap -> tic │ ├── ncurses5-config │ ├── reset -> tset │ ├── tack │ ├── tic │ ├── toe │ ├── tput │ └── tset ├── include │ └── ncurses ├── lib │ ├── libform.a │ ├── libform_g.a │ ├── libform.so -> libform.so.5 │ ├── libform.so.5 -> libform.so.5.6 │ ├── libform.so.5.6 │ ├── libmenu.a │ ├── libmenu_g.a │ ├── libmenu.so -> libmenu.so.5 │ ├── libmenu.so.5 -> libmenu.so.5.6 │ ├── libmenu.so.5.6 │ ├── libncurses.a │ ├── libncurses++.a │ ├── libncurses_g.a │ ├── libncurses.so -> libncurses.so.5 │ ├── libncurses.so.5 -> libncurses.so.5.6 │ ├── libncurses.so.5.6 │ ├── libpanel.a │ ├── libpanel_g.a │ ├── libpanel.so -> libpanel.so.5 │ ├── libpanel.so.5 -> libpanel.so.5.6 │ ├── libpanel.so.5.6 │ └── terminfo -> ../share/terminfo ├── man │ ├── man1 │ ├── man3 │ ├── man5 │ └── man7 └── share ├── tabset └── terminfo
编译gdb
./configure
$ CC='arm-linux-gcc' LDFLAGS=-L$HOME/arm/ncurses/lib CPPFLAGS=-I$HOME/arm/ncurses/include ./configure --build=i686-pc-linux --host=arm-linux --target=arm-linux --enable-shared --prefix=$HOME/arm/gdb --without-x --disable-gdbtk --disable-tui
参数含义:
libncurses 路径
LDFLAGS=-L$HOME/arm/ncurses/lib
CPPFLAGS=-I$HOME/arm/ncurses/include
–enable-shared 动态编译
–prefix=$HOME/arm/gdb 安装目录
–without-x 取消x windows 支持
–disable-gdbtk 取消gdbtk,应该也是图形界面相关的
–disable-tui 取消tui 界面
这点要说明一下,CC LDFLAGS CPPFLAGS这些编译参数本是放到./configure后的,但是当我放到./configure后提示错误:configure: error: can only configure for one host and one target at a time
,应该是configure的nonopt变量设置问题,我只好放到了前面,其实到后面会发现其是不起作用的。
以上生成Makefile
make
$ make
然后出现几个问题;
- no termcap library found
明明添加了ncurses的库路径为什么不行?它既然是找libtermcap,给它在$HOME/arm/ncurses/lib下建个指向libncurses.so的软连接
$ ln -s $HOME/arm/ncurses/lib/libncurses.so $HOME/arm/ncurses/lib/libtermcap.so
结果仍然提示上述错误。
这应该是configure时配置的FLAGS不起作用;
因此将上面的make修正为
$ make LDFLAGS=-L$HOME/arm/ncurses/lib CPPFLAGS=-I$HOME/arm/ncurses/include
编译顺利进行
- gdb/gdb_curses.h头文件错误
将代码修改为如下:
#if defined (HAVE_NCURSES_H) #include#elif defined (HAVE_CURSESX_H) #include #elif defined (HAVE_CURSES_H) #include #endif #if defined (HAVE_TERM_H) #include #else /* On MinGW, a real termcap library is usually not present. Stub versions of the termcap functions will be built from win32-termcap.c. Readline provides its own extern declarations when there's no termcap.h; do the same here for the termcap functions used in GDB. */ extern int tgetnum (const char *); #endif
编译通过
make install
$ make install
安装后在$HOME/arm/gdb目录下会看到bin等目录,其下有 gdb gdbserver run三个文件,表示安装成功。
刚生成的gdb有10M左右,嵌入式设备Flash不大,可以将其strip下,减下肥
$ arm-linux-strip gdb
此时gdb只有2M多了
放置gdb
将$HOME/arm/gdb/bin/gdb 拷贝至设备/usr/bin目录,将$HOME/arm/ncurses/libncurse.so,libtermcap.so拷贝至设备/usr/lib目录即可
< 完 >