首页 > 代码库 > linux 3.10 busybox initramfs构建 qemu调试

linux 3.10 busybox initramfs构建 qemu调试

linux 3.10 busybox initramfs构建 qemu调试

我的环境是vm ware虚拟机跑的centos 7 64位系统

1: 安装qemu

先安装SDL,负责qemu运行后只出现VNC server running on `::1:5900‘,而不出现qemu运行窗口,具体参考:

http://www.crifan.com/qemu_test_arm_vnc_server_running_on_127_0_0_1_5900_no_other_output/

 

yum install SDL.i686 SDL.x86_64 SDL-devel.i686 SDL-devel.x86_64

 

 

下载源代码qemu-2.1.0.tar.bz2,解压编译,安装

./configure --prefix=/usr/local/ --target-list=x86_64-softmmu

make && make install

 

创建软链接

ln -n /usr/local//bin/qemu-system-x86_64 /bin/qemu

 

2:下载busybox-1.20.0.tar.bz2,解压,进入源代码目录,运行

make menuconfig 

选择

Busybox Settings --->

    Build Options ---> 

        [*] Build BusyBox as a static binary (no shared libs)

编译安装

make && make install

 

编译过程出现错误

  CC      loginutils/passwd.o

loginutils/passwd.c: 在函数‘passwd_main’中:

loginutils/passwd.c:104:16: 错误:‘rlimit_fsize’的存储大小未知

  struct rlimit rlimit_fsize;

                ^

loginutils/passwd.c:188:2: 警告:隐式声明函数‘setrlimit’ [-Wimplicit-function-declaration]

  setrlimit(RLIMIT_FSIZE, &rlimit_fsize);

  ^

loginutils/passwd.c:188:12: 错误:‘RLIMIT_FSIZE’未声明(在此函数内第一次使用)

  setrlimit(RLIMIT_FSIZE, &rlimit_fsize);

            ^

loginutils/passwd.c:188:12: 附注:每个未声明的标识符在其出现的函数内只报告一次

loginutils/passwd.c:104:16: 警告:未使用的变量‘rlimit_fsize’ [-Wunused-variable]

 

vim include/libbb.h

在#include <sys/mman.h>后面添加

    #include <sys/resource.h>

具体参考http://lists.busybox.net/pipermail/busybox/2012-May/077766.html

 

编译一个简单程序进行测试

 

vim ~/init.c 

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

int main()

{

        while(1){

                printf("Hello world!\n");

                sleep(199999999);

        }

        return 0;

}

 

gcc -static ~/init.c -o /opt/busybox-1.20.0/_install/init

cd /opt/busybox-1.20.0/_install

mknod -m 600 dev/console c 5 1

 

 

进入创建目录和文件

cd _install

mkdir -p dev proc sys etc mnt

touch etc/mdev.conf

mknod -m 600 dev/null c 1 3

 

创建控制台设备文件,不创建这个文件,init脚本不能正常运行。console的初始化代码参考函数:init/main.ckernel_init_freeable

 

mknod -m 600 dev/console c 5 1    

创建init文件:

vim init

内容如下:

#!/bin/sh

echo 

echo "###########################################################"

echo "## Author: ancjf@163.com                                 ##"

echo "## Date: 2014/09/15 16:57:21 CST                           ##"

echo "###########################################################"

echo

 

PATH="/bin:/sbin:/usr/bin:/usr/sbin"

 

if [ ! -f "/bin/busybox" ];then

  echo "cat not find busybox in /bin dir, exit"

  exit 1

fi

 

BUSYBOX="/bin/busybox"

 

echo "build root filesystem..."

$BUSYBOX --install -s

 

if [ ! -d /proc ];then

  echo "/proc dir not exist, create it..."

  $BUSYBOX mkdir /proc

fi

echo "mount proc fs..."

$BUSYBOX mount -t proc proc /proc

 

if [ ! -d /dev ];then

  echo "/dev dir not exist, create it..."

  $BUSYBOX mkdir /dev

fi

echo "mount tmpfs in /dev..."

$BUSYBOX mount -t tmpfs dev /dev

 

$BUSYBOX mkdir -p /dev/pts

echo "mount devpts..."

$BUSYBOX mount -t devpts devpts /dev/pts

 

if [ ! -d /sys ];then

  echo "/sys dir not exist, create it..."

  $BUSYBOX mkdir /sys

fi

echo "mount sys fs..."

$BUSYBOX mount -t sysfs sys /sys

 

echo "/sbin/mdev" > /proc/sys/kernel/hotplug

echo "populate the dev dir..."

$BUSYBOX mdev -s

 

echo "drop to shell..."

$BUSYBOX sh

 

exit 0

 

给init执行的权限

chmod u+x init

3:下载linux-3.10.tar.xz,解压源码,进入源码目录,运行

make menuconfig 

配置编译选项,选中

General setup --->

[*]Initramfs source file(s)

选项,输入制作好的文件系统的目录就可以了,我这里是

/opt/busybox-1.20.0/_install

编译

make bzImage

运行虚拟机:

qemu -kernel ./arch/x86/boot/bzImage -append "no_timer_check"

 

在另一终端下进行gdp调试:

gdb vmlinux

target remote  127.0.0.1:1234

b start_kernel

4:在我的机器上不添加no_timer_check会输出

...trying to set up timer as Virtual Wire IRQ...

后卡住

解决这个问题的方法:

在源代码搜索trying to set up timer as Virtual Wire IRQ,找到函数输出语句在函数check_timer中。

运行虚拟机

qemu -kernel ./arch/x86/boot/bzImage -append "root=/dev/hda init=/bin/sh no_timer_check" -S -s

在内核源代码目录运行

gdb vmlinux

进入gdb命令行后输入命令

target remote  127.0.0.1:1234

b check_timer

c

断点后从输出trying to set up timer as Virtual Wire IRQ后往下执行,发现到timer_irq_works函数后卡住。在timer_irq_works中有语句:

if (no_timer_check)

return 1;

查找no_timer_check,Documentation/x86/x86_64/boot-options.txt中找到no_timer_check选项。

 

5:GDB 调试出现gdb ‘g‘ packet reply is too long修正,

 

下载gdb-7.8.tar.xz

解压

xt -d gdb-7.8.tar.xz

tar xf gdb-7.8.tar.xz

 

 

编辑源代码:

vim gdb/remote.c

 

找到process_g_packet函数

注释调下面两行

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->pnum == -1)

            continue;

        if (rsa->regs->offset >= rsa->sizeof_g_packet)

            rsa->regs->in_g_packet = 0;

        else  

            rsa->regs->in_g_packet = 1;

    }     

}

 

配置编译

./configure --prefix=/usr/local/gdb

Make && make install

设置环境变量

export PATH=/usr/local/gdb/bin:$PATH

 

6:其他问题

xshell下直接执行

qemu -kernel ./arch/x86/boot/bzImage -append "no_timer_check"

键盘输入会出现乱码。在虚拟机环境下执行不会出现这个情况。

linux 3.10 busybox initramfs构建 qemu调试