交叉编译问题记录-嵌入式环境下 GDB 的使用方法

本文为做者原创,转载请注明出处:http://www.javashuo.com/article/p-txwprthd-bz.htmlhtml

本文以嵌入式 Linux 环境下的 gdb 使用为例,记录交叉编译过程当中一个比较关键的问题:configure 过程当中 --build, --host, --target 参数的区别。python

1. 交叉编译

交叉编译是指在一种平台上编译出运行于另外一种平台的程序。这里的平台,涉及硬件和软件两个部分,硬件平台指 CPU 架构,软件平台指操做系统。交叉编译主要针对嵌入式领域,由于嵌入式系统资源受限,没有办法在嵌入式平台上运行一套编译环境,所以须要在其余性能更强劲的平台上借助交叉编译工具链来制做可在嵌入式平台上运行的程序。linux

交叉编译与普通编译基本步骤同样:shell

[1] configure
在编译前进行配置。若是 --host 参数与 --build 参数不一样,则是交叉编译。不然就是普通编译。架构

[2] make
编译。根据上一步 configure 配置生成的参数,调用相应的编译工具链编译生成目标程序。工具

[3] make install
安装。将 make 生成的目标程序安装到指定目录。若是不运行 make install,手动拷贝到指定目录也可。性能

1.1 --build --host --target

看一下 configure 步骤中 --build、--host 和 --target 三个参数的定义,下面在 gdb 源码目录运行 './configure --help'ui

./configure --help
System types:
  --build=BUILD     configure for building on BUILD [guessed]
  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
  --target=TARGET   configure for building compilers for TARGET [HOST]

源码通过编译生成可执行程序。根据执行编译操做的平台、可执行程序的运行平台、可执行的程序的处理平台,能够将编译操做分为多种类型,对应的三个配置参数以下:this

--build:运行编译工具链的平台,也就是正在执行编译操做的平台。若是未指定此参数,则经过 config.guess 猜想获得。一般都不指定此参数。操作系统

--host:可执行程序将运行的平台。若是未指定此参数,则和 --build 相同。若是 --host 和 --build 不一样,是交叉编译;不然是普通编译。

--target:可执行程序将处理的平台。若是未指定此参数,则和 --host 相同。通常来讲,程序运行在什么平台,处理的就是什么平台,此参数值和 --host 参数相同,不需显式指定,因此一般不会关注到此参数。但在制做交叉编译工具 (如 gcc、gdb 等) 这种特殊状况下,此值和 --host 不一样,例如交叉编译器 arm-linux-gcc,它运行在 x86-linux 平台 (--host 参数),但处理的是 arm-linux 平台 (--target 参数)。若是是交叉编译一个普通的应用,如运行于 arm-linux 平台的 tftp 程序,则它的运行平台和处理平台都是 arm-linux 平台。

1.2 三种编译类型

编译类型能够分为三种,主要体如今 configure 阶段不一样的配置参数:(假设交叉编译工具链安装在 x86-linux 平台,待编译的目标嵌入式平台为 arm-linux 平台,这里仅为了说明意图,平台命名并不严谨)

[1] 编译 PC 平台普通程序
通常执行以下形式的配置命令:

./configure

将缺省的参数补全,实际等效于以下命令:

./configure --build=x86_linux --host=x86_linux --target=x86_linux

[2] 编译交叉编译工具链
交叉编译工具链的特别之处在于,它在 x86-linux 平台上运行,处理的倒是 arm-linux 平台。制做交叉编译工具链并不须要使用交叉编译。通常执行以下形式的配置命令:

./configure --target=arm_linux

将缺省的参数补全,实际等效于以下命令:

./configure --build=x86_linux --host=x86_linux --target=arm_linux

[3] 交叉编译嵌入式平台程序
生成嵌入式平台的程序须要用用到交叉编译。通常执行以下形式的配置命令:

./configure --host=arm_linux CC=arm-linux-gcc

将缺省的参数补全,实际等效于以下命令:

./configure --build=x86_linux --host=arm_linux --target=arm_linux CC=arm-linux-gcc

实际上,若是咱们要制做运行于嵌入式平台的编译工具(好比 gcc、gdb 等),也能够先执行上面 configure 命令而后执行 make,可是生成的 gcc、gdb 等工具基本上没法在目标嵌入式平台上正常运行,由于硬件带不动,因此嵌入式平台的编译工具链是按 [2] 中的方法制做 ,而不是按 [3] 中的方法制做。

2. GDB 交叉编译与使用实例

嵌入式平台中使用 GDB 时会用到 GDB 的远程 (remote) 调试模式:在目标板上经过 gdbserver 运行待调试的程序,在宿主机上运行 gdb 并经过 'target remote [ip]:[port]' 来链接到目标板上的 gdbserver,从而启动远程调试。各类调试命令在宿主机上输入,程序执行效果(包括打印)在目标板上展现,这很容易理解,由于正在调试的程序原本就是在目标板上运行的。不在目标板上直接运行 gdb 进行调试是由于目标板硬件配置低,跑不动 gdb,固然,不排除某些嵌入式平台的性能很强劲,可以正常运行 gdb。当嵌入式平台的硬件愈来愈强大时,嵌入式平台与通用计算机平台的界限也愈来愈模糊,实际状况也正是这样,硬件性能愈来愈强悍,资源短缺的问题愈来愈淡化,这种发展形势下,嵌入式技术的没落是必然的结果。

搭建嵌入式平台下的 gdb 调试环境,对理解前面交叉编译过程当中的 --build、--host 和 --target 三个参数很是用帮助。

2.1 环境描述

虚拟机:CPU:x86_64,系统:openSUSE Leap 42.3,IP:192.168.202.240
开发板:CPU:mips mt7688,系统:openwrt linux,IP:192.168.202.141
虚拟机上安装的 C 交叉编译器为 mipsel-openwrt-linux-gcc,即交叉编译工具链的前缀为 mipsel-openwrt-linux。

2.2 下载源码

ftp://ftp.gnu.org/gnu/gdb 下载最新版源码 gdb-8.2.tar.gz,解压:

tar zxvf ./gdb-8.2.tar.gz
cd gdb-8.2

2.3 编译 gdb

编译 gdb:

cd gdb-8.2
./configure --target=mipsel-openwrt-linux
make

gdb 运行在虚拟机上,因此它不须要交叉编译。--build 和 --host 参数留空,实际使用的是虚拟机的平台参数。gdb 虽运行在虚拟机上,但它处理的是开发板平台的程序,因此指定 --target 为 mipsel-openwrt-linux,值取的是交叉编译工具链前缀。

2.4 交叉编译 gdbserver

编译 gdbserver:

cd gdb-8.2/gdb/gdbserver
./configure --host=mipsel-openwrt-linux CC=mipsel-openwrt-linux-gcc
make

gdbserver 运行在开发板上,因此须要交叉编译。--build 参数留空,实际使用的是虚拟机的平台参数。--host 参数指定虚拟机平台,值为 mipsel-openwrt-linux。--target 参数留空,因此它的取值将等于 --host 参数值。

2.5 以 remote 方式使用 gdb

开发板:开发板 IP 是 192.168.202.141,则输入下述任一条指令皆可

gdbserver :1234 test
gdbserver 127.0.0.1:1234 test
gdbserver 192.168.202.141:1234 test

主机:首先在 SHELL 命令行里运行 gdb 应用

./gdb

运行上一条命令后,SHELL 将进入 gdb 模式,下列几条指令中 '(gdb)' 是提示符:

(gdb) target remote 192.168.202.141
(gdb) b main.c:55
(gdb) c

上面第一条命令是远程链接到开发板上的 gdbserver。链接以后,就是正常使用了。第二条命令是设置断点。第三条命令是运行程序,注意待调试的程序实际已在开发板上运行了,因此要使用 'c' 指令,而不能使用 'r' 指令,若是输入 'r' 指令,能够看到提示 remote 模式不支持 'r' 指令:

(gdb) r
The "remote" target does not support "run".  Try "help target" or "continue".

3. 遗留问题

交叉编译过程当中,通常使用交叉编译工具链的前缀做 --host 及 --target 的值;--build 参数通常不指定,编译时自动推测。这些都是在实践层面,通常就算写错了,多试一试最终都能编译经过。而对平台描述的定义,即 --build、--host 及 --target 的值的具体取值规则,我没有找到正式的出处和定义,是的,网上没查到。

4. 参考资料

嵌入式 Linux 的 GDB 调试环境创建
Python Exception 异常信息
QT 远程调试 ARM 板中 python 的问题

5. 修改记录

2019-04-11 初稿

相关文章
相关标签/搜索