内核调试 · 2014-04-27 0

Bochs调试linux内核环境搭建笔记(1)

一、安装Bochs软件
环境:
Ubuntu 13.10
Bochs版本:
Bochs 2.6

1、安装环境准备:
sudo apt-get install build-essential
sudo apt-get install xorg-dev
sudo apt-get install bison
sudo apt-get install libgtk2.0-dev

2、安装Bochs命令:
./configure –enable-debugger=yes –enable-disasm=yes
sudo make
cp bochs bochsdbg
——如果没有该拷贝,安装时将会报错;
sudo make install

3、安装遇到的问题列表:
问题1、
gui/libgui.a(gtk_enh_dbg_osdep.o): undefined reference to symbol ‘pthread_create@@GLIBC_2.2.5’
解决办法:
 LDFLAGS=’-lpthread’ ./configure –with-x11 –enable-debugger –enable-disasm
问题2、
如果忘了刚才的cp bochs bochsdbg命令,可能会安装失败,那么重复安装时将会报某个keymap已经存在
解决办法:
将bochs在安装目录下面的东西全部删了,重新make install一下。

二、构建bochs调测环境:
注:创建磁盘镜像以及往上面安装是在ubuntu 11.10(虚拟机安装的系统即可)环境上操作的,
主要原因是由于ubuntu 13.10上面的GRUB为2.0版本,该版本已经没有grub-setup命令,
改为了grub-install命令,但是该命令不太熟,暂不研究,故用11.10回避。
1、构建磁盘镜像;
root@machine:# dd if=/dev/zero of=hd1.img count=$((63*16*100))
100800+0 records in
100800+0 records out
51609600 bytes (52 MB) copied, 0.548913 s, 94.0 MB/s
2、挂载磁盘镜像;
root@machine:# losetup /dev/loop0 hd1.img 
3、初始化磁盘设备;
root@machine:# cfdisk -s63 -h16 /dev/loop0
注意:初始化该磁盘时,创建一个Primary分区即可,同时注意需要将该磁盘设置为bootable模式,然后写入,退出;
4、使用fdisk检查刚才的操作;
root@machine:# fdisk -lu /dev/loop0

Disk /dev/loop0: 51 MB, 51609600 bytes
16 heads, 63 sectors/track, 100 cylinders, total 100800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

      Device Boot      Start         End      Blocks   Id  System
/dev/loop0p1   *          63      100799       50368+  83  Linux
5、将分区1挂载到/dev/loop1上面;
root@machine:# losetup /dev/loop1 hd1.img -o $((63*512))
6、格式化/dev/loop1为ext3文件系统格式; 
root@machine:# mkfs.ext3 /dev/loop1
mke2fs 1.41.14 (22-Dec-2010)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
12600 inodes, 50368 blocks
2518 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=51642368
7 block groups
8192 blocks per group, 8192 fragments per group
1800 inodes per group
Superblock backups stored on blocks: 
8193, 24577, 40961

Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 36 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
7、在mnt下面创建img目录,可以留作以后维护使用;
root@machine:# mkdir -p /mnt/img
8、将loop1挂载到/mnt/img/上面;  
root@machine:# mount /dev/loop1 /mnt/img/
9、安装引导程序;
root@machine:# mkdir /mnt/img/boot
root@machine:# cp -r /usr/lib/grub/i386-pc/ /mnt/img/boot/grub
10、生成一个core.img, biosdisk负责读取磁盘, part_msdos负责处理MBR, ext2负责读取ext3分区;
root@machine:# cd /mnt/img/boot/grub/
root@machine:/mnt/img/boot/grub# grub-mkimage -O i386-pc -o core.img biosdisk part_msdos ext2
命令解释:
1)-d使用默认值/usr/lib/grub2/i386-pc;
2)-p指定prefix变量为/bootin/grub2;
3)-o即输出定制的内核到/boot/bootin/grub2/core.img文件中;
4)biosdisk part_msdos ext2,这些都是grub内核所包含的模块,不需要太多;
注:有部分版本不需要参数“-O i386-pc”
注:ext3 基于ext2 的代码,它的磁盘格式和 ext2 的相同,所以此处用ext2读取,因为没有ext3模块。
11、安装grub2到(hd0), 根目录在(hd0,1);
root@machine:/mnt/img/boot/grub# echo “(hd0) /dev/loop0” > ./device.map
device.map文件的意义说明:
首先,其实上述命令中的(hd0)并不意味着grub会安装到“本地硬盘”的MBR中,(hd0,1)也并不意味着grub所需文件在“本地硬盘”第一个分区上;因为在实际写入到设备时,(hd0)会经过device.map文件的映射;只有当device.map文件内容为(hd0) /dev/sda时,上面的说法才成立;而当device.map文件内容为(hd0) /dev/sdb时,比如你插入一个U盘,这时,(hd0)被映射为/dev/sdb,即你的U盘;上述命令将会写入grub到你U盘的MBR上,而将来启动时也会在你U盘上的第一个分区中查找/boot/grub下的模块等文件;这也意味着,如果你要安装grub到U盘,只要将device.map文件内容改为(hd0) /dev/sdb就可以了!
root@machine:/mnt/img/boot/grub# grub-setup -m ./device.map -d /mnt/img/boot/grub/ -r ‘(hd0,1)’ ‘(hd0)’
命令解释:
安装grub2到(hd0), 根目录在(hd0,1)
1)-d即安装grub2时所需的boot.img和core.img等文件所在目录为/mnt/img/boot/grub/;
2)-m即指定device.map文件所在目录为./device.map;
3)末尾的-r (hd0,1)即将来启动grub时所需文件在本地硬盘第一个分区;后面(hd0)即安装grub到本地硬盘MBR;
12、检查一下安装结果;
root@machine:/mnt/img/boot/grub# hexdump -C /dev/loop0 | less
可以看到如下信息:
00000180  7d e8 2e 00 cd 18 eb fe  47 52 55 42 20 00 47 65  |}…….GRUB .Ge|
00000190  6f 6d 00 48 61 72 64 20  44 69 73 6b 00 52 65 61  |om.Hard Disk.Rea|
这说明前面的操作没什么问题了;
13、现在可以把虚拟的镜像设备卸载了;
root@machine:/mnt/img/boot/grub# cd –
root@machine:# umount /mnt/img
root@machine:# losetup -d /dev/loop1
root@machine:# losetup -d /dev/loop0
至此,hd0.img已经搞定了,可以把它拷贝弄出ubuntu 11.10环境,去到安装bochs环境上面;
其实上面搞这么多主要是grub-setup在新版本上面没有了,暂时懒得研究grub-install命令了,
所以就Vmware安装ubuntu 11.10给绕过去。
14、至此只是把img搞定了,下面把bochs给配置一下;
使用命令vim bochsrc,然后输入以下信息即可:
megs: 2000
romimage: file=$BXSHARE/BIOS-bochs-latest
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
ata0-master: type=disk, path=”hd0.img”, cylinders=100, heads=16, spt=63
boot: c
log: bochsout.txt
mouse: enabled=0
cpu: ips=15000000
clock: sync=both
15、测试一下img和bochs的安装情况,通常bochs能不能用,直接shell下面bochs命令就一见分晓,不过基于制作的hd0.img做验证,可以使用命令:
bochs -f bochsrc
注:该bochsrc本来是可以用系统自带默认的,但是配置方面不太熟,如果使用默认的话,会报CPU不支持的错误。
使用上面的命令启动bochs后,需要c一下,因为它默认会停在机器启动的第一条指令上面,然后可以在bochs的客户机上面按F12,选择Hard disk to boot,那么就可以看到grub的提示了。

三、安装内核
1、退出bochs,挂在hd0.img;
root@machine:# mount hd0.img /mnt/img/ -o loop,offset=$((63*512))
2、拷贝bzImage到磁盘上面;
root@machine:# cp /usr/src/linux/arch/x86/boot/bzImage /mnt/img/boot/vmlinuz
3、然后将下列配置写到/mnt/img/boot/grub/grub.cfg里面;
root@machine:# vim /mnt/img/boot/grub/grub.cfg
内容:
# Timeout for menu
set timeout=10
# Set default boot entry as Entry0
set default=0
# Entry0- Load Linux kernel
menuentry “Linux” { 
set root=(hd0,1)
linux /boot/vmlinuz root=/dev/hda1
}
4、开始测试内核了;
umount /mnt/img
bochs -f bochsrc

四、Bochs使用命令整理
1、通过help命令可以查询bochs的调测命令有哪些;
help
h|help – show list of debugger commands
h|help command – show short command description
-*- Debugger control -*-
    help, q|quit|exit, set, instrument, show, trace, trace-reg,
    trace-mem, u|disasm, ldsym, slist
-*- Execution control -*-
    c|cont|continue, s|step, p|n|next, modebp, vmexitbp
-*- Breakpoint management -*-
    vb|vbreak, lb|lbreak, pb|pbreak|b|break, sb, sba, blist,
    bpe, bpd, d|del|delete, watch, unwatch
-*- CPU and memory contents -*-
    x, xp, setpmem, writemem, crc, info,
    r|reg|regs|registers, fp|fpu, mmx, sse, sreg, dreg, creg,
    page, set, ptime, print-stack, ?|calc
-*- Working with bochs param tree -*-
    show “param”, restore
2、命令详解;
具体命令就不详细说明了,通过h command命令都可以查到各个命令的用法,总而言之bochs确实做得挺牛的,熟悉了gdb的使用,转过来发现bochs功能更多更爽一些,不过就是运行得稍微慢了那么一点点。