VS结合VisualGDB搭建OpenWrt交叉编译远程调试开发环境

由于此开发环境涉及3设备协同工作,因此先说明一下整体开发环境的配置以及每部分所负责的功能:
1.Windows PC
这里我用的是64位Win7,作为VS的安装环境Windows自然是必不可少的,本机主要用于结合VisualGDB插件完成项目创建,上传编译机编译并部署执行程序到测试机完成gdbserver远程调试(自然是背后gdb前脸VS的全图形可视化调试)
2.Linux PC
这个我这里是CentOS Linux release 7.2.1511 64bit,安装于VMWare虚拟机上(当然也可以用真机,效果更佳!),作为交叉编译OpenWrt执行程序的编译机,由VisualGDB通过ssh连接同步Win机上的项目源码,make文件等并进行编译,同时还作为gdb客户端连接OpenWrt调试服务端并由VisualGDB传递gdb调试操作间接实现Win端的VS图形化调试
3.OpenWrt Router
这个我这里使用的是联想的Y1S路由器,MT7620A mips架构,作为整个开发环境的目标平台,接收Linux编译后的执行程序,并负责启动gdbserver作为远程调试的服务端

整体环境介绍完了,首先要做的是搭建起Linux机上的OpenWrt命令行开发环境(Y1S对应的是OpenWrt-SDK-ramips-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2),并且保证可以使用原始gdb的方式成功进行命令行模式的远程调试,这个就不赘述了,网上有很多相关教程。补充一点,在gdb调试过程中可能会遇到(OpenWrt上线./gdbserver :9876 /mnt/sda1/kcamd启动调试进程):

./scripts/remote-gdb 192.168.99.1:9876 ./build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/kcam/kcamd

This GDB was configured as “–host=x86_64-linux-gnu –target=mipsel-openwrt-linux-uclibc”.

(gdb) b main
Breakpoint 1 at 0x400cac: file main.cpp, line 29.
(gdb) c
Continuing.
warning: `/usr/lib/libstdc++.so.6′: Shared library architecture unknown is not compatible with target architecture mips:isa32r2.
warning: `/lib/libgcc_s.so.1′: Shared library architecture unknown is not compatible with target architecture mips:isa32r2.
warning: Could not load shared library symbols for 5 libraries, e.g. /lib/libuci.so.
Use the “info sharedlibrary” command to see the complete listing.
Do you need “set solib-search-path” or “set sysroot”?

Breakpoint 1, (gdb) n
Remote ‘g’ packet reply is too long: 00000000f8ffffffecdee77740b4ff7701000000f46dff7ffc6dff7f2034847fec6eff7f000101819bffaaacf0ffffff00031c7fffffffff00000000c826e677da6eff7f1c094000406dff7f0098e477f8e0a0000e00000000004400dc7a430087040000900c40000000000000000000a013e877786aff7f786aff7f4c27e67713ff0001a070230029000000a0d1e17724008050ac0c4000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000
(gdb)


“Remote ‘g’ packet reply is too long”这个问题,看到网上有人说可以通过gdb的set arch指定正确的目标设备cpu架构来解决,但我试了半天发现并不能解决,而在OpenWrt上直接使用gdb调试是完全没有问题的,最后发现可以通过一个.patch来修复这个问题:
既然是.patch那还得先从git上下载OpenWrt的源码,然后挂上patch重新编译gdb:

git clone -b barrier_breaker git://github.com/openwrt/openwrt.git

然后先make menuconfig,在文本图形界面中选对Target,Y1S的是“Ralink RT288x/RT3xxx”,然后复制patch内容:

--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -6110,8 +6110,19 @@ process_g_packet (struct regcache *regca
   buf_len = strlen (rs->buf);

   /* Further sanity checks, with knowledge of the architecture.  */
-  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)
+  //  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[i].pnum == -1)
+        continue;
+      if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
+        rsa->regs[i].in_g_packet = 0;
+      else
+        rsa->regs[i].in_g_packet = 1;
+    }
+  }

   /* Save the size of the packet sent to us by the target.  It is used
      as a heuristic when determining the max size of packets that the

到toolchain/gdb/patches/中,取名700-fix-remote-g-packet-reply-too-long.patch,接下来重新编译toolchain中的gdb:

make toolchain/gdb/clean
make toolchain/gdb/install

首次编译时会下载一堆源码,可能稍慢,耐心等待,完成后将patch过的gdb复制到预编译sdk中toolchain的bin中覆盖掉源文件:

cp staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mipsel-openwrt-linux-uclibc-gdb ~/Documents/OpenWrt-SDK-ramips-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/

之后再次执行./scripts/remote-gdb进行远程调试,就没问题了,可以通过gdb启动后的config确认:

This GDB was configured as “–host=x86_64-redhat-linux –target=mipsel-openwrt-linux-uclibc”.

另外,目前使用中暂时也没有发现有什么后遗症,常用功能均正常。
接下来进入正题:
打开VS(我这里是2015 Community版)新建VisualGDB项目(Linux Project Wizard);
QQ截图20161112144814
这一步主要就是设置编译及调试设备,如上面的截图所示,先建立Build机的ssh连接,然后Remote toolchain中选择Custom toolchain,然后指定刚才patch编译出并复制到SDK toolchain中的mipsel-openwrt-linux-uclibc-gdb,然后建立Deploy机也就是OpenWrt的ssh连接,选择执行程序的部署路径(默认是/tmp,我改为了u盘路径)。这里可能会遇到的问题是这个:
QQ截图20161112144801
VisualGDB会检查toolchain的完整性,然后会发现Deploy目标机上没有gdbserver,并给出警告,这里由于我的Y1S用的修改过的OpenWrt,opkg的安装路径修改过,gdbserver安装在了/opt/usr/bin/下,因此VisualGDB没有找到,这个无所谓,无视就好,后面会修改项目设置,手动指定gdbserver。
项目创建好后,修改项目的VisualGDB Project Properties:
首先可以关掉Project Settings中的”Skip deployment test when testing the toolchain settings”,这样上面说的找不到gdbserver问题就不会每次修改设置都提示了。
接下来是Makefile Settings,这里面需要修改的是Include directories和Library directories,这里面需要加上Include

/home/kres/Documents/OpenWrt-SDK-ramips-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/include

Library

/home/kres/Documents/OpenWrt-SDK-ramips-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/lib

否则的话,在使用像uci库等OpenWrt的库时就会出现编译找不到头文件,链接找不到lib的问题,当然这里也可以根据实际情况添加额外的inc和lib路径。
下一项Debug Settings中,需要单独设置gdbserver:
QQ截图20161112150357
默认VisualGDB会使用Debug a new instance的方式启动调试,虽然说这里我的deploy机上gdbserver不在默认位置,但我感觉就算VisualGDB可以找到部署设备上的gdbserver可能也会因为一些启动参数的问题导致不能调试,幸好还有Debug with a custom gdb stub(gdbserver protocol),直接选这项,然后按截图中直接指定gdbserver位置及启动参数(这里目标程序可能可以通过某些环境变量指定,懒得查了,直接写死了,其实就是和创建项目时的部署位置一致,另外本页中的Deploy main executable to也可以重新修改)
最后还要修改一下User variables,加入STAGING_DIR项,指到OpenWrt SDK中的staging_dir位置,并勾选Propagate to … 项,如下图所示,否则编译时sdk会提示这个环境变量没有定义的警告。
QQ截图20161112151019
至此,项目设置就全部完成了,一切正常的话此时就可以像一般VS项目一样F5断点调试运行了:
QQ截图20161112151455

博主友情提示:

如在您的评论中需要提及如QQ号、微信号、电子邮件地址或其他隐私敏感信息,欢迎通过>>博主专用加密工具<<加密后发布,原文只有博主可以看到。