06_交叉编译准备

交叉编译准备

背景

在嵌入式 Linux 开发中,往往会出现两个名词,宿主机以及目标机;而实际上我们程序运行的地方是目标机,但是编译出程序的地方却不是目标机而是宿主机,这里有很多中原因了;大致上分为三种:第一种是目标机高度裁剪,连 gcc 都没有,也就没有能力编译;第二种而是目标机性能比较低,编译所耗费的时间比较多;第三种则是目标机虽然能力很强,比如服务器。但是耐不住没有图形化,所以还是交叉编译。

总而言之,就是不方便,所以才有宿主机帮忙编译;所以反过来说宿主机一定是好用的,也就是为什么宿主机铺天盖地就是一堆 debian 或者 ubuntu,反正程序不在这里跑,图形化是很大的优势,图形化所带来的开销又可以不用考虑。

前提

在你的宿主机上已经有交叉编译工具链,而且起码你也得有一个目标机,可能也就是一块板子。

依赖安装

这里默认你的交叉编译工具链是 32 位的,而我们的虚拟机一般都是 64 位的,所以得安装一些库,毕竟 ubuntu 本身是没有帮助我们安装 32 位的库的。

# 这里并不完整,之后要一点点补充
sudo apt install lib32z1-dev
sudo apt install lib32z1 lib32ncurses5
sudo apt install lib32stdc++6
sudo apt install gcc-multilib 

共享文件夹

不知道你知不知道 window 下的共享文件夹,或者 NAS ,这里就是要实现类似的功能,也就是在目标机以及宿主机上共享一个文件夹,通过网络的方式实现,当然目标机和宿主机得在同一个局域网内,不然是做不了;这里使用的方案是 NFS(network file system)。

当然共享文件夹虽说是贡献,但是肯定有一个真实的物理存储,也就是虽然目标机和宿主机在行为上像是在操作同一个文件夹,但是实际上来说肯定是有有一方在物理上存储了这些文件,这一方通常是宿主机,也不绝对,比如服务器,可能就是目标机来提供物理存储了。

建议创建一个工具目录,作为以后挂载的目录,也就是你想共享的文件夹。

# 安装 nfs 服务器
sudo apt install nfs-kernel-server
# /home/haorui/haorui 替换为你自己要共享的目录
# 这么写主要就是懒
sudo bash -c 'echo "/home/haorui/haorui *(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports'
# 重启 nfs 服务
service nfs-kernel-server restart
# 看看有没有挂载成功
showmount -e

然后你需要确保宿主机以及目标机的网络是互通的,也就是 ping 双方的 IP 地址都是通过的,使用 ifconfig 查询自己的 IP 地址。

基本上对于局域网内的宿主机以及目标机并且宿主机是虚拟机,如果要达到上面的效果,只能选择插网线并且使用桥接模式。

然后登录目标机:

# 使用 telnet 或者 ssh 登录目标机后
cd /var
mkdir share
# 按照自己宿主机实际的IP以及共享目录填写
mount -t nfs -o nolock 172.20.92.71:/home/haorui/haorui /var/share/

在这里插入图片描述

左边上下的两个终端分别打印了宿主机的 IP 以及共享目录,而右边的目录则是目标机挂载宿主机的共享目录;也就是说这三个终端运行在不同的地方,左边两个运行在宿主机上,右边一个运行在录播机上。

远程调试

在本地写程序的时候,我们可以很方便的使用 gdb 进行断点调试;在交叉编译的时候,其实我们也可以这么做,这就是远程调试,不过它不仅仅需要 gdb ,还需要一个 gdb server。

写在最前面这是需要注意的, 为了实现远程调试, 我们需要 gdb 以及 gdb server,其中 gdb 是运行在宿主机的, gdb server 是运行在目标机上的,你可以简单地把它们理解为成一种C/S模式,即 gdb 作为客户端, gdb server 作为服务器。

gdb 相关

由于后期要开启 pretty printer 功能,也就是为了看到 STL 容器的内容,甚至是 Boost 容器的内容,我们需要 gdb 有 py 的功能,你可以简单把 pretty printer 和 gdb 的关系看成 VScode 里的插件与 VScode 的关系;这种功能在 gdb 7 之后才有,我们推荐的 gdb 版本大致上是 7.4 或者 9.2 。

gdb 这种东西挺奇怪的,其实我编译过很多个版本,7,8,9,10,11我都编译过,7和8的编译方式是一致的,9突然改变了,10和11也是一致的,但也和9不同的,所以你选择其他的版本的话,你就自己去编吧,看我的没用。

下载 gdb

# 找个地方把安装包放好
cd ~/package/compress/
wget https://ftp.gnu.org/gnu/gdb/gdb-9.2.tar.gz
# 解压
# -C ../ 可以不加如果直接解压到当前目录,../是解压路径
tar zxvf gdb-9.2.tar.gz -C ../

安装 gdb

# lspwd : /home/haorui/package/gdb-9.2
# 先下载个依赖
sudo apt-get install texinfo
sudo apt install libexpat1-dev
mkdir build
cd build/
# 生成 makefile
# configure 填写绝对路径
# target 按照自己目标机的 体系结构
# program-prefix 即程序的前缀名
# prefix 即程序安装路径、
# with-python 指定编译 gdb 使用的 python
/home/haorui/package/gdb-9.2/configure  --target=arm-linux --program-prefix=arm-hisiv600-linux-  --prefix=/home/haorui/tools/arm-hisiv600-linux-gdb -with-python=/usr/bin/python3.8
make -j8
# 不要随便加 sudo ,如果指定安装路径,否则 sudo 会把文件夹的权限提升到 root ,操作起来反而不方便
make install
make clean
cd ..
rm -rf build

安装 gdb server

# pwd : /home/haorui/package/gdb-9.2/gdb/gdbserver
# host 填写自己得交叉编译工具链前缀
./configure --host=arm-hisiv600-linux --program-prefix=arm-hisiv600-linux- --prefix=/home/haorui/tools/arm-hisiv600-linux-gdbserver
# 不要使用并行编译,也就是 -j
make
make install
make clean

测试 gdb

如下测试一下即可:

在这里插入图片描述

需要看看 gdb 的 pretty-printer 的功能是否具备,当然你看到 1 of 1 printers enabled ,其实跟没有开启一样,当然这就是之后要去解决的问题;但是这项功能有没有又是另一回事。

在这里插入图片描述

如图这是当初编译的 gdb , 7.11.1 版本,使用 python 2.x 编译,压根就没有 pretty-printer 功能。

重要已知问题

在 ubunut 18.04 下,使用 gdb 进行远程调试会出现以下错误,

Reading /lib/ld-linux.so.3 from remote target...
Reading symbols from target:/lib/ld-linux.so.3...
Remote 'g' packet reply is too long (expected 168 bytes, got 328 bytes): 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0fdffbe00000000c0fafcb6100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

网上对这个问题的修复大致上是这样的,这里这里把网友的解决方案贴出来,以此为戒:

将:

if (buf_len > 2 * rsa->sizeof_g_packet)
    error (_("Remote 'g' packet reply is too long: %s"), rs->buf);

修改为:

if (buf_len > 2 * rsa->sizeof_g_packet) {
   rsa->sizeof_g_packet = buf_len ;
   for (i = 0; i < gdbarch_num_regs (gdbarch); i++) {
       if (rsa->regs->pnum == -1)
          continue;
       if (rsa->regs->offset >= rsa->sizeof_g_packet)
          rsa->regs->in_g_packet = 0;
       else
          rsa->regs->in_g_packet = 1;
   }
}

这个修改方案你说行不通也不是,但凡是修改源码都是最后面的事情了,这一上来就打个抗生素不太好,建议还是跟踪一下错误;首先这个问题不是必现,也就是有人的机器上会出现,有人不会,那么说明程序本身应该是没有太大的问题的,可能是依赖。

我去找了一下,发现是 gdb 编译的时候缺少一个可选的依赖库,expat(一个XML的解析器),所以就安装一下咯,在 ubunutu 下sudo apt install libexpat1-dev 这样就可以了。

总而言之,不要随意修改源代码,尤其在你不知道修改的是什么的情况下;这一个问题来来回回几十个回复都是像上面这样修改,其实并不太好;我相信第一个修复者是有认真分析的,但是后来的人可能都只是照搬而已。

已知问题汇总

  • 使用 python 3.9 安装 gdb 会失败,原因是接口发生更替,编译得过去,但是会出现段错误
  • 使用 python 2.x 安装 gdb ,可能导致 gdb 部分功能不完全开启
  • gdb 和 gdbserver 是成对使用的,不会混合使用, gdb 和 gdbserver 是 C/S 模式,通信的信令在不同的版本间可能有所不同;当然也不是不能混用,毕竟只是有可能不同
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值