转自: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
3 $ cd linux-2.6.35/
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
2 $ cd ..

结果是得到一个压缩的内核镜像文件“./linux-2.6.35/arch/arm/boot/zImage”。

Busybox

接下来,我下载了最新版的Busybox;在前次的教程中我使用了静态编译,但这一次我不会,因为gdbserver(我计划就是要用它)无论如何都需要共享库。

2 $ tar xjf busybox-1.17.1.tar.bz2
3 $ cd busybox-1.17.1
4 $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- defconfig
5 $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- install
6 $ cd ..

结果是得到文件夹“busybox-1.17.1/_install”,包括了一个最小的不包含共享库的根文件系统。

QEMU

我重新从源码编译了QEMU,只包含我需要的模拟ARM系统的二进制文件。

2 tar xzf qemu-0.12.5.tar.gz
3 cd qemu-0.12.5
4 $ ./configure --enable-sdl --disable-kvm --enable-debug --target-list=arm-softmmu
5 $ ./make
6 cd ..

相应的结果是程序“./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
3 cd hello-2.6
4 $ ./configure --host=arm-none-linux-gnueabi
5 make
6 cd ..

结果就是一个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
02 $ mkdir -p lib
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/
10 $ cd ../../

在我的实验中我需要ARM客户机系统那边有一个可用的网络,因此我准备了一个初始化脚本来开启它。该脚本从我的上一个教程扩展而来,下面是我用的脚本“rcS”的内容:

1 #!/bin/sh
2 mount -t proc none /proc
3 mount -t sysfs none /sys
4 /sbin/mdev -s
5 ifconfig lo up
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
6 cd ../../

运行与调试

现在我已经将所有东西准备好:

  • 一个压缩的内核镜像
  • 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
6 break main
7 run

到这里后,调试过程就跟平常一样了。

来源:http://balau82.wordpress.com/2010/08/17/debugging-arm-programs-inside-qemu/

在QEMU中调试ARM程序【转】的更多相关文章

  1. 用Qemu运行/调试arm linux【转】

    转自:https://blog.csdn.net/absurd/article/details/78984244 用Qemu运行/调试arm linux,这事情干过好几次了,久了就忘记了,每次都要重新 ...

  2. 在编译器中调试spark程序处理

    在IDEA中调试spark程序会报错 18/05/16 07:33:51 WARN NativeCodeLoader: Unable to load native-hadoop library for ...

  3. QT Creator 环境使用 remote debug 调试 arm 程序

    这里使用的 4.8.5 QTE 环境,之前尝试过远程使用 GDB 来调试板子上的 QT 程序,但是没成功.没有调试手段比较痛苦,今天又花了点时间,居然搞定了.粗做记录. 工具版本: 1. QtCrea ...

  4. Ubuntu12.10 使用JLink连接开发板用arm-gdb调试ARM程序

    Part1 环境搭建和工具安装 1.1 设置交叉编译环境 安装相关的编译工具: sudo apt-get install build-essential gcc-arm-linux-gnueabi 这 ...

  5. 在ubuntu下使用eclipse来调试ARM程序

    该程序为外部Makefile project,导入到eclipse中来进行编译,之后使用Jlink来进行调试. 这个是因为你在编译的时候没有加-g这个标志,导致没有生成调试文件. 让你指定一个源文件. ...

  6. 在idea中调试spark程序-配置windows上的 spark local模式

    spark程序大致有如下运行模式: standalone模式:spark自带的模式 spark on yarn:利用hadoop yarn来做集群的资源管理 local模式:主要在测试的时候使用, 这 ...

  7. keil程序在外部RAM中调试的问题总结(个人的一点经验总结)

    keil程序在内部RAM调试的基本步骤网上已经有非常多了,我就不再赘述,大家能够在网上搜到非常多. 可是有些时候内部RAM并不够用,这就须要将程序装入外部RAM中调试,而在这个过程中可能会出现各种各样 ...

  8. 在vscode中怎样debug调试go程序

    随着互联网时代的飞速发展,我们编码使用的开发利器也在不断更新换代,古话说工欲善其事必先利其器,对于Java开发者而言,eclipse和idea这两款神器各有千秋,因自己的爱好可以选取不同的IDE,但是 ...

  9. 第49章 在SRAM中调试代码—零死角玩转STM32-F429系列

    第49章     在SRAM中调试代码 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...

随机推荐

  1. 201421123042 《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7-1回答 1.1 自己以前编写的代码中经常出现 ...

  2. django报错Manager isn't accessible via UserInfo instances

    出现这种错误是因为调用模型对象时使用了变量名,而不是对象名(模型类),例如: user = UserInfo()user_li = user.objects.filter(uname=username ...

  3. LeetCode & Q28-Implement strStr-Easy

    String Two Pointers Description: Implement strStr(). Returns the index of the first occurrence of ne ...

  4. Python爬虫之urllib模块1

    Python爬虫之urllib模块1 本文来自网友投稿.作者PG,一个待毕业待就业二流大学生.玄魂工作室未对该文章内容做任何改变. 因为本人一直对推理悬疑比较感兴趣,所以这次爬取的网站也是平时看一些悬 ...

  5. BizTalk 2016 配置 RosettaNet遇到的坑

    本文只针对已经安装好BizTalk 2016 需要在安装RosettaNet加速器的伙伴. IIS配置 权限问题 错误信息 Failed to get IIS metabase property. E ...

  6. linux——网络基础

    装完linux系统要对网络(ip地址,子网掩码,网关,DNS)进行配置,才能连接网络 一,开启网卡eth0 CentOS显示没有网卡(eth0) 2.设置静态IP vim /etc/sysconfig ...

  7. Linux CentOS7.0 (01)在Vmvare Workstation上 安装配置

    一.新建虚拟机 1.创建新的虚拟机 -> 默认典型 ->选择安装介质 2.指定虚拟机名称.安装目录.磁盘容量大小 点击 "完成",创建虚拟机! 随后虚拟机将自动启动安装 ...

  8. HTML5的常用新特性你必须知道

    HTML5的常用新特性你必须知道 1 新的 声明 HTML 有多个不同的版本,只有完全明白页面中使用的确切 HTML 版本,浏览器才能完全正确地显示出 HTML 页面.这就是 的用处. 不是 HTML ...

  9. 发布到NPMJS

    最近在做微服务的前后端设计,打算将客户端中的一个模块独立出来发布到npmjs上,因此,有机会了解了一下npm的发布过程. 参考了很多网上的文章,长篇累牍(但在这里还是真心感谢他们的分享),最终总结成一 ...

  10. MySQL8.0 原子DDL

    Edit MySQL8.0 原子DDL 简介 MySQL8.0 开始支持原子 DDL(atomic DDL),数据字典的更新,存储引擎操作,写二进制日志结合成了一个事务.在没有原子DDL之前,DROP ...