此篇文章是用来记录一下,本人对于交叉编译链的下载及学习,期间也参考了很多优秀的博客(已在下面附上了相关的博客链接)只是为了记录一下,要是觉得被冒犯到了,请联系我删除谢谢。

arm-linux-gcc、gdb+gdbserver

​ 在嵌入式系统开发中,用户经常通过使用交叉编译巩实现远程调试。采用远程调试的主要原因是:大多是的嵌入式平台不太适合进行本地调试,在很多嵌入式平台上内存等资源受限,并且附带调试信息的可执行程序往往超过几兆字节大小。使用交叉编译,可以减轻嵌入式平台相应的负担。

1、gdb和gdbserver是什么

1.1 gdb

​ gdb是GNU开源组织发布的一个强大的Linux下的程序调试工具。

1.2 gdbserver

​ gdb调试器提供了两种不同的远程调试方法,即gdbserver方式和stub(插桩)方式。gdbserver本身体积很小,能够在具有很小内存的目标系统上独立运行,因此很适合嵌入式的开发,而stub比较适合于调试Bootloader和内核等系统程序。但是,gdbserver要求宿主机和目标系统采用统一系列的操作系统,而stub没有这种限制,甚至,目标系统可以没有操作系统 。stu方式需要通过链接器把调试代理和要调试程序链接成一个可执行的应用程序文件。而且stub需要修改异常处理和驱动程序等。

2、gdb+gdbserver调试嵌入式平台上的Linux程序

​ 目前而言,嵌入式Linux系统中,主要有三种远程调试方法,分别适用于不同场合的调试工作:用ROM Monitor调试目标机程序、用KGDB调试系统内核和用gdbserver调试用户空间程序。这三种调试方法的区别主要在于,目标机远程调试stub 的存在形式的不同,而其设计思路和实现方法则是大致相同的。而我们最常用的是调试应用程序,就是采用gdb+gdbserver的方式进行调试。

gdbserver是在目标系统(板子)上运行,gdb则是在宿主机(本地)上运行。gdb和gdbserver之间可以通过串行线或者TCP/IP网络连接进行通信。采用的通信协议是标准的gdb远程串行协议(RSP)。

2.1 编译交叉工具链(arm-linux-gdb)

2.1.1 下载安装包

​ [官网下载]http://ftp.gnu.org/gnu/gdb/)

2.1.2 生成Makefile
tar -zvxf gdb-7.8.tar.gz
cd gdb-7.8 
./configure -target=arm-linux [-prefix=(自己想要放的位置)]

-prefix是用来指定生成的路径的,一般好方便自己管理。编译成功之后,如果没有自己选定位置的话,就可以在/usr/local看到生成的四个文件夹,分别是:bin include lib share。(当然,如果你想放到自己创建的文件内好管理的话,使用了-prefix指定了位置,同样可以在对应的位置看到这几个文件。)

2.1.3 编译
sudo make
sudo make install

注意:此处可能出现:configure:error:no termcap library found的错误

原因:系统没有安装termcap库

解决办法:安装termcap库

  1. termcap库下载

  2. 安装

    tar -zvxf termcap-1.3.1.tar.gz
    cd termcap-1.3.1
    ./configure --build="i686-pc-linux-gnu" --host="arm-linux-gnu" --target="arm-linux-gnu" -prefix=$HOME/install
    make
    make install
    

    这样在$HOME/install目录下就会生成一个libtermcap.a的库文件,这个目录是在上述命令中使用–prefix参数指定的。

  3. 将生成的库文件复制到默认库目录(/usr/lib等)中。

回到对应的目录,重新编译即可。
​因为有时有些问题是访问权限不够,所以,编译时,加上了sudo。

​根据自己的第一步,是否指定位置:编译成功之后,如果没有自己选定位置的话,就可以在/usr/local看到生成的四个文件夹,分别是:bin include lib share。(当然,如果你想放到自己创建的文件内好管理的话,使用了-prefix指定了位置,同样可以在对应的位置看到这几个文件。)可以查看,bin文件下面是否有:arm-linux-gdb和arm-linux-run。前者是宿主机上运行的gdb调试器,后者是用于在宿主机上运行armulator仿真器,把程序的运行结果显示出来。

2.1.4 设置环境变量

​ 1. 分别在在/etc/profile中和~/.bashrc中将bin的路径放进去

​ 2. source一下,使其生效,这样随便在那个地方都可以使用arm-linux-gdb了。

2.2 编译gdbserver

​ gdbserver是在目标系统上运行的,但是要先在本地的电脑上生成可执行程序:gdbserver。然后再将其拷贝到目标系统里面。

2.2.1 生成Makefile

还是在上面gdb源代码解压目录下的gdb/gdbserver目录下包含了编译gdbserver所需要的所有东西。

cd gdb-7.8/gdb/gdbserver
chmod +x configure
./configure --host=arm-linux --target=arm-linux

其中,–host=arm-linux 运行环境 (交叉编译成arm)宿主机的,–target是板子上的。

2.2.2 编译

​ 1、这一步,需要下载安装好arm-linux-gcc。

arm-linux-gcc安装步骤:

拓展:

  1. 解压tar.bz2是用
tar -jvxf xxxxx.tar.bz2
  1. 解压tar.gz
tar -zvxf xxxxx.tar.gz
  1. 解压.zip
unzip xxxx.zip

参考链接

​ 2、编译

sudo make CC=arm-linux-gcc
arm-linux-strip gdbserver /*去掉各种调试信息,减小gdbserver的大小*/

遇到的问题:

1、这一步可能还会出现问题:/bin/bash:arm-linux-gcc not found。这就说明arm-linux-gcc的环境变量没有设置好。需要在/etc/profile里面重新添加环境变量,上述链接中说的很清楚了。我这边出现的问题是,source之后,就会自动进入到root用户下,在root用户下,执行就不会有问题。但是当我回到自己的用户名下时,会报错,显示:/bin/bash:arm-linux-gcc not found。但是在自己的用户名下又可以正常使用arm-linux-gcc及其他的命令。(等我在root用户下执行完之后,回到自己的用户下,又可以执行了)这个不知道是为什么。有知道的还希望不吝赐教。

2、也可能会遇到:

linux-arm-low.c:272:1: error: conflicting types for ‘ps_get_thread_area’
 ps_get_thread_area (const struct ps_prochandle *ph,
 ^~~~~~~~~~~~~~~~~~
In file included from gdb_proc_service.h:30:0,
                 from linux-low.h:24,
                 from linux-arm-low.c:20:
/opt/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/proc_service.h:72:17: note: previous declaration of ‘ps_get_thread_area’ was here
 extern ps_err_e ps_get_thread_area (struct ps_prochandle *

原因:重定义了

解决办法

3、可能会有: Makefile:recipe for target xxx failed。这个主要的错可能是在上面。先排除上面的主要的错误,再看这个。遇到错先定位到错误的位置,不要着急!

3、远程调试

3.1 可执行文件下到板子

​ 将上一步生成的可执行程序gdbserve放到板子里

3.2 宿主机编译可执行文件

​ 宿主机需要编译两份可执行文件(如果目标机上的可执行文件是需要不带调试信息的程序的话。),一份放在自己这,一份要放到目 标机上。编译文件时记得带上-g参数,生成具有调试信息的可执行文件。这是放在宿主中的可执行文件

arm-linux-gcc -g test.c -o test

​ 当然如果目标板子的内存不是很大的话,也可以将生成的可执行文件test_strip去掉各种调试信息之后再放到板子上面(当然在目标机端也是可以直接使用附带调试信息的程序)。然后将该程序拷到目标板上。

arm-linux-strip test_strip

3.3 在目标板上启动gdbserver

./gdbserver 192.168.xxx.xxx:端口号 test_strip

​ 其中192.168.xxx.xxx是宿主机的IP地址,gdbserver启动一个子进程test_strip

3.4 在宿主机上启动arm-linux-gdb

arm-linux-gdb test

之后会进入与gdb调试相同的界面。(前面的那个gdb是进去调试界面本来就有的,是不需要手动输入的.)通过symbol-file读入符号表,其参数是附带调试信息的可执行程序,即test。

(gdb)target remote 192.168.xxx.xx:端口号
(gdb)symbol-file test

接下来就可以进行调试了,但是要注意:这和本地调试还是不同的。在远程时,不需要使用run启动程序运行,用continue执行下一步。因为目标板上已经启动了被调试的程序运行。现在目标机的该进程的进程被gdbserver阻塞,以等待来自宿主机的调试指令。

4、参考链接

gdb+gdbserver远程调试技术(一)——调试环境搭建

gdb+gdbserver远程调试环境搭建及调试

Logo

「智能机器人开发者大赛」官方平台,致力于为开发者和参赛选手提供赛事技术指导、行业标准解读及团队实战案例解析;聚焦智能机器人开发全栈技术闭环,助力开发者攻克技术瓶颈,促进软硬件集成、场景应用及商业化落地的深度研讨。 加入智能机器人开发者社区iRobot Developer,与全球极客并肩突破技术边界,定义机器人开发的未来范式!

更多推荐