Linux GDB+UML(User-Mode Linux)调试

来源:互联网 发布:淘宝数据魔方登陆 编辑:程序博客网 时间:2024/05/01 01:21

本文系转载:http://blog.sina.com.cn/s/blog_70dd16910101akk2.html

前言

用户模式的Linux(UML:User-Mode Linux)是指将Linux作为一个独立的、可移植的Linux内核而创建,其实现包含在子目录arch/um中。然而,它并不是运行在某种新的硬件之上,而是运行在基于Linux系统调用接口所实现的虚拟机之上。因此用户模式的Linux可以使得Linux内核成为一个运行在Linux系统之上的、独立的用户模式进程。
将一个内核的副本当做用户模式下的进程来运行有多个优势。首先其运行在一个受约束的虚拟处理器上,所以有错误的内核不会破坏“真正”的系统;其次对软/硬件的不同配置可以在相同的框架下进行不同的尝试;更重要的是对Linux内核开发人员来说,可以轻易利用gdb对用户模式Linux进行调试,因为归根到底它始终是一个进程。因此利用UML一方面可以加快Linux内核的开发过程;另一方面也有助于我们对Linux内核运行机制的了解。本文研究如何搭建gdb+uml的调试环境。
备注:我使用的系统是Debian-6.07。

第一部分 UML系统搭建
第一步:下载Linux内核
下载linux-2.6.38.tar.bz2:
ftp://ftp.kernel.org/pub/linux/kernel/v2.6/

第二步:解压内核,生成基于um的配置文件
$cd /home/tom
$tar xvf linux-2.6.38.tar.bz2
$cd linux-2.6.38
$make ARCH=um defconfig
示意图如下:
Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试
第三步:修改配置文件
$make menuconfig ARCH=um
1.配置General Setup->Initial RAM filesystem and RAM disk(initramfs/initrd)support
示意图如下:
Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试
2.选择Kernel hacking->Kernel debugging
示意图如下
Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试
3.选择Kernel hacking->Compile the kernel with debug info
示意图如下:
Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试
第四步:编译内核
$make ARCH=um 2>&1 | tee build.log
示意图如下:
Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试
第五步:下载linux根文件系统Debian-Squeeze-x86-root_fs.bz2
下载地址:
http://fs.devloop.org.uk/
备注:当然了,我们也可以自己制作根文件系统,O(∩_∩)O~。
将Debian-Squeeze-x86-root_fs.bz2下载到/home/tom/Public/目录下,运行命令:
$bunzip2 Debian-Squeeze-x86-root_fs.bz2
解压生成Debian-Squeeze-x86-root_fs根文件系统。

第六步:切换到root用户,运行User-mode Linux
$cd ~/Public/linux-2.6.38
$sudo bash    //将bash运行在root权限下
#./linux udb0=../Debian-Squeeze-x86-root_fs mem=32m
执行结果如下:
Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试
第三部分 gdb+uml调试
保持第二部分User-mode Linux处于正在运行,开启另外一个终端,在该终端中首先查询User-mode Linux进程的进程号。
$ps –el |grep linux
Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试
备注:其中的uml根进程号为17425,但是gdb绑定的是其子进程17427.

启动gdb,连接User-Mode Linux进程,设置断点,并进行调试。
$cd ~/Public/linux-2.6.38
$sudo bash
#gdb linux
示意图如下:
Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试
在gdb的调试环境下连接到User-Mode Linux进程,设置断点,即可进行调试。
使用命令:
$attach 17427
$break sys_clone
$info break
$continue
示意图如下:
Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试
此时我们在User-Mode Linux环境中打入ls –l /命令,系统将会在sys_clone()函数处停下来,示意图如下:
Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试

现在就可以在gdb中查看sys_clone()函数运行的状态。

Linux <wbr>GDB+UML(User-Mode <wbr>Linux)调试
此时我们就可以用常用的gdb命令,对sys_clone()函数进行跟踪、调试。

自己用虚拟机安装ubuntu11.10,下载linux-3.0.1重新编译了内核
安装操作过程中,终止于第五步,下载linux根文件系统Debian-Squeeze-x86-root_fs.bz2,bunzip2解压缩之后,执行./linux udb0=../Debian-Squeeze-x86-root_fs mem=32m,显示错误为:
root@ubuntu:/usr/src/linux-3.0.1# ./linux udb0=../Debian-Squeeze-x86-root_fs mem=32m
Locating the bottom of the address space ... 0x0
Locating the top of the address space ... 0xc0000000
Core dump limits :
soft - 0
hard - NONE
Checking that ptrace can change system call numbers...OK
Checking syscall emulation patch for ptrace...OK
Checking advanced syscall emulation patch for ptrace...OK
Checking for tmpfs mount on /dev/shm...nothing mounted on /dev/shm
Checking PROT_EXEC mmap in /tmp/...OK
Checking for the skas3 patch in the host:
  - /proc/mm...not found: No such file or directory
  - PTRACE_FAULTINFO...not found
  - PTRACE_LDT...not found
UML running in SKAS0 mode
Adding 20332544 bytes to physical memory to account for exec-shield gap
Linux version 3.0.1 (root@ubuntu) (gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) ) #2 Thu Nov 21 23:42:01 PST 2013
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 13053
Kernel command line: udb0=../Debian-Squeeze-x86-root_fs mem=32m root=98:0
udb0=../Debian-Squeeze-x86-root_fs specified on command line is almost certainly a ubd -> udb TYPO
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 28956k available
NR_IRQS:15
Calibrating delay loop... 2164.32 BogoMIPS (lpj=10821632)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
Checking for host processor cmov support...Yes
Checking that host ptys support output SIGIO...Yes
Checking that host ptys support SIGIO on close...No, enabling workaround
Using 2.6 host AIO
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
Switching to clocksource itimer
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
mconsole (version 2) initialized on /root/.uml/I1uHgL/mconsole
Checking host MADV_REMOVE support...
MADV_REMOVE failed, err = -38
Can't release memory to the host - memory hotplug won't be supported

Host TLS support detected
Detected host type: i386 (GDT indexes 6 to 9)
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
msgmni has been set to 56
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
TCP cubic registered
NET: Registered protocol family 17
Initialized stdio console driver
Console initialized on /dev/tty0
console [tty0] enabled
Initializing software serial port version 1
console [mc-1] enabled
Couldn't stat "root_fs" : err = 2
Failed to initialize ubd device 0 :Couldn't determine size of device's file
VFS: Cannot open root device "98:0" or unknown-block(98,0)

Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(98,0)
0ac5ced8:  [<081c56c4>] dump_stack+0x1c/0x20
0ac5cef0:  [<081c5788>] panic+0x4b/0x12d
0ac5cf24:  [<08049958>] mount_block_root+0x20d/0x223
0ac5cf7c:  [<080499ba>] mount_root+0x4c/0x54
0ac5cfa0:  [<08049ade>] prepare_namespace+0x11c/0x143
0ac5cfa8:  [<08049685>] kernel_init+0xe7/0xec
0ac5cfb8:  [<08067334>] run_kernel_thread+0x38/0x40
0ac5cfe4:  [<0805a53f>] new_thread_handler+0x8a/0xb6
0ac5cffc:  [<00000000>] 0x0
EIP: 0073:[<b7781424>] CPU: 0 Not tainted ESP: 007b:bf936038 EFLAGS: 00200292
    Not tainted
EAX: 00000000 EBX: 000008b5 ECX: 00000013 EDX: 000008b5
ESI: 000008b1 EDI: 0000001c EBP: bf936064 DS: 007b ES: 007b
0ac5ce88:  [<0806ce86>] show_regs+0xc5/0xcb
0ac5ceb4:  [<0805c53f>] panic_exit+0x23/0x39
0ac5cec8:  [<0808b324>] notifier_call_chain+0x25/0x4a
0ac5cef0:  [<0808b377>] atomic_notifier_call_chain+0x15/0x17
0ac5cf00:  [<081c57a3>] panic+0x66/0x12d
0ac5cf24:  [<08049958>] mount_block_root+0x20d/0x223
0ac5cf7c:  [<080499ba>] mount_root+0x4c/0x54
0ac5cfa0:  [<08049ade>] prepare_namespace+0x11c/0x143
0ac5cfa8:  [<08049685>] kernel_init+0xe7/0xec
0ac5cfb8:  [<08067334>] run_kernel_thread+0x38/0x40
0ac5cfe4:  [<0805a53f>] new_thread_handler+0x8a/0xb6
0ac5cffc:  [<00000000>] 0x0
Aborted
      于是在《嵌入式linux学习资料之使用UML调试Linux内核和模块》中找到:
新手在自己制作根文件系统时可能会出现一些麻烦,如果文件拷少了,UML运行不起来,如果不管三七二十一,把Host OS的所有文件都拷进去,又浪费空间。所以如果嫌麻烦的话,可以直接到UML官网上下载自己喜欢的发行版本的根文件系统,作为映像文件来运行UML。需要注意的是,所使用的根文件系统类型一定要是UML内核所支持的类型,否则系统在启动时会出现下面的错误:Kernel panic - not syncing: VFS: Unable to mount root fs onunknown-block(98,0)
      新手刚开始学习UML+GDB调试环境的搭建,望有经验者提供帮助。
参考资料:
关于uml参考:
http://user-mode-linux.sourceforge.net/
http://fs.devloop.org.uk/
https://www.youtube.com/watch?v=li5EiItG-GU

关于gdb调试参考
http://blog.csdn.net.sixxs.org/wei801004/article/details/4253911
http://jinxin16897123.blog.163.com/blog/static/1629260620121121452596/
http://blog.csdn.net.sixxs.org/wei801004/article/details/4253886