转自:http://linuxeden.com/html/develop/20100820/104409.html
最近我想调试一个运行在QEMU模拟ARM系统中的Linux程序。我碰到过一些麻烦,因此我会将我的工作过程写在这里。我想用gdbserver来在QEMU中运行一个程序,然后用TCP链接将其连接到运行在我PC上的GDB实例。gdbserver是一个软件层,它实现了GDB的一部分功能(调试残桩),并提供了通过网络(或者串口)连接一个完整的GDB实例的可能性。我想说明的这些都可以通过下面这张图来表示。
使用QEMU内嵌的gdbserver
蓝颜色的部分表示用来运行在我的Ubuntu PC(32位x86)上的软件,而绿色的部分则表示运行在ARM上的软件。qemu-system-arm是一个模拟VersatilePB平台的软件;我尝试过运行可以通过Ubuntu仓库里安装的那个版本(这个软件包叫qemu-kvm-extras),但它必须和最新的Linux版本(2.6.35)一起。因此我打算编译并使用QEMU的上流版本。GDB的server和“client”都来自于ARM的CodeSourcery编译工具集,也就是用于交叉编译ARM软件的编译器。在本例中我想要调试的程序是GNU Hello,这个程序除了打印“Hello World”外没有做多少工作,不过这是一个用GNU Autotools进行交叉编译的好例子。
先决条件
为了接下来的流程,我首先安装了:
- 用于ARM的CodeSourcery GNU/Linux工具链
- 用于编译QEMU的本地x86工具链(Ubuntu的build-essentials软件包)
- 作为调试器图形界面的DDD
- 用于创建Linux文件系统镜像的cpio工具
- libncurses5-dev软件包,用于运行Linux内核和Busybox的菜单式配置
- 用于编译QEMU的libsdl-dev和zlib1g-dev
1 |
$ sudo apt-get install build-essential ddd cpio libncurses5-dev libsdl-dev zlib1g-dev |
3 |
$ chmod +x arm-2010q1-202-arm-none-linux-gnueabi.bin |
4 |
$ ./arm-2010q1-202-arm-none-linux-gnueabi.bin |
我将工具链安装在默认的“~/CodeSourcery”目录下。而这种情况下gdbserver的可执行文件可以在路径“/home/francesco/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/usr/bin/gdbserver”下找到。
注意以后的过程都会在一个专用的文件夹下运行,并且从此以后不在需要root的访问权限。整个过程到结束大概需要使用1Gigabyte的硬盘空间。
Linux内核
首先,我从官方的仓库中获取了最新的内核版本。
2 |
$ tar xjf linux-2.6.35.tar.bz2 |
4 |
$ make ARCH=arm versatile_defconfig |
5 |
$ make ARCH=arm menuconfig |
当菜单出现时,我来到“Kernel Features”节并打开EABI支持;然后退出 (保存配置) 并编译:
1 |
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- all |
结果是得到一个压缩的内核镜像文件“./linux-2.6.35/arch/arm/boot/zImage”。
Busybox
接下来,我下载了最新版的Busybox;在前次的教程中我使用了静态编译,但这一次我不会,因为gdbserver(我计划就是要用它)无论如何都需要共享库。
2 |
$ tar xjf busybox-1.17.1.tar.bz2 |
4 |
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- defconfig |
5 |
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- install |
结果是得到文件夹“busybox-1.17.1/_install”,包括了一个最小的不包含共享库的根文件系统。
QEMU
我重新从源码编译了QEMU,只包含我需要的模拟ARM系统的二进制文件。
2 |
$ tar xzf qemu-0.12.5. tar .gz |
4 |
$ ./configure -- enable -sdl --disable-kvm -- enable -debug --target-list=arm-softmmu |
相应的结果是程序“./qemu-0.12.5/arm-softmmu/qemu-system-arm”,会被用来模拟VersatilePB平台。
GNU Hello
这个软件包需要配置成使用交叉编译;不过这其实很容易做;它只需要一个交叉编译器的前缀。
1 |
$ wget http:// ftp .gnu.org/gnu/hello/hello-2.6. tar .gz |
2 |
$ tar xzf hello-2.6. tar .gz |
4 |
$ ./configure --host=arm-none-linux-gnueabi |
结果就是一个ARM架构的可执行文件“hello-2.6/src/hello”。
完成文件系统构建
所有涉及到的ARM二进制文件 (busybox, gdbserver, hello) 都需要共享库。Codesourcery工具链在安装目录的一个子文件夹下提供了这些库。在我这种情况下就是“/home/francesco/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/lib/”。为了探索哪些库是必需的我使用CodeSourcery工具链所分发的readelf工具。具体说来,我运行了:
01 |
$ arm-none-linux-gnueabi-readelf hello-2.6/src/hello -a |grep lib |
02 |
[Requesting program interpreter: /lib/ld-linux.so.3] |
03 |
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1] |
04 |
0x00000001 (NEEDED) Shared library: [libc.so.6] |
05 |
00010694 00000216 R_ARM_JUMP_SLOT 0000835c __libc_start_main |
06 |
2: 0000835c 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.4 (2) |
07 |
89: 0000844c 4 FUNC GLOBAL DEFAULT 12 __libc_csu_fini |
08 |
91: 0000835c 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_ |
09 |
101: 00008450 204 FUNC GLOBAL DEFAULT 12 __libc_csu_init |
10 |
000000: Version: 1 File: libgcc_s.so.1 Cnt: 1 |
11 |
0x0020: Version: 1 File: libc.so.6 Cnt: 1 |
Hello这个二进制文件需要三个共享库: “ld-linux.so.3″, “libgcc_s.so.1″ 和 “libc.so.6″。我对所有的3个二进制文件都执行了这个命令,并且将所需的库和gdbserver、hello等可执行文件拷贝到Busybox的文件系统里面。
01 |
$ cd busybox-1.17.1/_install |
03 |
$ cp /home/francesco/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/lib/ld-linux.so.3 lib/ |
04 |
$ cp /home/francesco/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/lib/libgcc_s.so.1 lib/ |
05 |
$ cp /home/francesco/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/lib/libm.so.6 lib/ |
06 |
$ cp /home/francesco/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/lib/libc.so.6 lib/ |
07 |
$ cp /home/francesco/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/lib/libdl.so.2 lib/ |
08 |
$ cp /home/francesco/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/usr/bin/gdbserver usr/bin/ |
09 |
$ cp ../../hello-2.6/src/hello usr/bin/ |
在我的实验中我需要ARM客户机系统那边有一个可用的网络,因此我准备了一个初始化脚本来开启它。该脚本从我的上一个教程扩展而来,下面是我用的脚本“rcS”的内容:
2 |
mount -t proc none /proc |
3 |
mount -t sysfs none /sys |
6 |
ifconfig eth0 10.0.2.15 netmask 255.255.255.0 |
7 |
route add default gw 10.0.2.1 |
然后,我将rcS拷贝到Busybox文件系统的“etc/init.d”目录里面并创建压缩的文件系统镜像:
1 |
$ cd busybox-1.17.1/_install |
2 |
$ mkdir -p proc sys dev etc etc/init.d |
3 |
$ cp ../../rcS etc/init.d |
4 |
$ chmod +x etc/init.d/rcS |
5 |
$ find . | cpio -o -- format =newc | gzip > ../../rootfs.img.gz |
运行与调试
现在我已经将所有东西准备好:
- 一个压缩的内核镜像
- QEMU
- 一个压缩的文件系统镜像,包括:
- Busybox
- rcS初始化脚本
- 为ARM编译的GNU Hello二进制文件
- 用于ARM的gdbserver
- 所需的共享库
运行该平台的命令行是:
1 |
$ ./qemu-0.12.5/arm-softmmu/qemu-system-arm -M versatilepb -m 128M -kernel ./linux-2.6.35/arch/arm/boot/zImage -initrd ./rootfs.img.gz -append "root=/dev/ram rdinit=/sbin/init" -redir tcp:1234::1234 |
这里“redir”选项会将我Ubuntu PC的端口1234上的所有TCP通信重定向到ARM客户机系统的1234端口上。系统将会启动,然后会打开一个root权限的控制台。在bash提示符下,我运行调试服务器:
1 |
# gdbserver --multi 10.0.2.15:1234 |
该命令会启动一个服务器并等待1234端口上的GDB连接。在PC上我可以打开调试器:
1 |
$ ddd --debugger arm-none-linux-gnueabi-gdb |
也可以单独运行arm-none-linux-gnueabi-gdb命令或者连接到另外一个前端。要调试远端的程序,我需要告诉GDB使用ARM的共享库而不是本地库(那些用于32位x86的);否则执行的时候调试器会抱怨说库不匹配。
1 |
set solib-absolute-prefix nonexistantpath |
2 |
set solib-search-path /home/francesco/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc/lib/ |
3 |
file ./hello-2.6/src/hello |
4 |
target extended-remote localhost:1234 |
5 |
set remote exec-file /usr/bin/hello |
到这里后,调试过程就跟平常一样了。
来源:http://balau82.wordpress.com/2010/08/17/debugging-arm-programs-inside-qemu/
- 用Qemu运行/调试arm linux【转】
转自:https://blog.csdn.net/absurd/article/details/78984244 用Qemu运行/调试arm linux,这事情干过好几次了,久了就忘记了,每次都要重新 ...
- 在编译器中调试spark程序处理
在IDEA中调试spark程序会报错 18/05/16 07:33:51 WARN NativeCodeLoader: Unable to load native-hadoop library for ...
- QT Creator 环境使用 remote debug 调试 arm 程序
这里使用的 4.8.5 QTE 环境,之前尝试过远程使用 GDB 来调试板子上的 QT 程序,但是没成功.没有调试手段比较痛苦,今天又花了点时间,居然搞定了.粗做记录. 工具版本: 1. QtCrea ...
- Ubuntu12.10 使用JLink连接开发板用arm-gdb调试ARM程序
Part1 环境搭建和工具安装 1.1 设置交叉编译环境 安装相关的编译工具: sudo apt-get install build-essential gcc-arm-linux-gnueabi 这 ...
- 在ubuntu下使用eclipse来调试ARM程序
该程序为外部Makefile project,导入到eclipse中来进行编译,之后使用Jlink来进行调试. 这个是因为你在编译的时候没有加-g这个标志,导致没有生成调试文件. 让你指定一个源文件. ...
- 在idea中调试spark程序-配置windows上的 spark local模式
spark程序大致有如下运行模式: standalone模式:spark自带的模式 spark on yarn:利用hadoop yarn来做集群的资源管理 local模式:主要在测试的时候使用, 这 ...
- keil程序在外部RAM中调试的问题总结(个人的一点经验总结)
keil程序在内部RAM调试的基本步骤网上已经有非常多了,我就不再赘述,大家能够在网上搜到非常多. 可是有些时候内部RAM并不够用,这就须要将程序装入外部RAM中调试,而在这个过程中可能会出现各种各样 ...
- 在vscode中怎样debug调试go程序
随着互联网时代的飞速发展,我们编码使用的开发利器也在不断更新换代,古话说工欲善其事必先利其器,对于Java开发者而言,eclipse和idea这两款神器各有千秋,因自己的爱好可以选取不同的IDE,但是 ...
- 第49章 在SRAM中调试代码—零死角玩转STM32-F429系列
第49章 在SRAM中调试代码 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...
随机推荐
- 第一周-JAVA基本概念
1. 本周学习总结 本周学习内容: 1.JAVA的发展 2.JDK,JVM,JRE, 3.掌握JAVA的组成结构 4.掌握使用简单的编译器写javac与java命令, 关键概念之间的联系: JVM:将 ...
- Struts2之配置
Struts2的默认配置文件是struts.xml放在/web-inf/classes目录下,struts配置文件的最大作用就是配置Action与请求之间的对应关系,并配置逻辑视图名和物理视图名之间的 ...
- SpringMVC源码情操陶冶#task-executor解析器
承接Spring源码情操陶冶-自定义节点的解析.线程池是jdk的一个很重要的概念,在很多的场景都会应用到,多用于处理多任务的并发处理,此处借由spring整合jdk的cocurrent包的方式来进行深 ...
- 用javascript做别踩白块游戏1
初学Javascript做的一个别踩白块小游戏,代码简陋,如下: <!DOCTYPE html> <html> <head> <!-- 禁用缩放功能 --&g ...
- SpringCloud的服务注册中心(三) - 进一步了解 Eureka
一.服务治理参与者 服务注册中心: eureka-server 服务提供者:HELLO-SERVICE 服务消费者 :HELLO-CONSUMER 很多时候,客户端既是服务提供者又是服务消费者,-&g ...
- Python模块 - os , sys.shutil
os 模块是与操作系统交互的一个接口 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录: ...
- leetcode算法: Find Largest Value in Each Tree Row
'''You need to find the largest value in each row of a binary tree.Example:Input: 1 / \ 3 2 / \ \ 5 ...
- spark分区数,task数目,core数,worker节点个数,excutor数量梳理
作者:王燚光链接:https://www.zhihu.com/question/33270495/answer/93424104来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- QT 实现在QLabel上画图
QT之所以不能再任意控件上绘图是因为QT的事件过滤器把控件的绘图事件给过滤了. 在paintevent()函数中,通常需要设置QPainter对象,创建QPainter对象的同时需要指定绘图设备,即继 ...
- Web标准的简单理解 不同内核浏览器的差异以及浏览器渲染简介(转)
Web标准是一系列标准的集合.这些标准大概分三方面:结构.表现和行为.结构化主要有HTML, XHTML和XML,表现主要有CSS,行为标准主要包括对象模型,如 W3C DOM.ECMAScript等 ...