Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用GDB和QEMU调试Linux内核?_Linux_Linux Kernel_Gdb_Qemu - Fatal编程技术网

如何使用GDB和QEMU调试Linux内核?

如何使用GDB和QEMU调试Linux内核?,linux,linux-kernel,gdb,qemu,Linux,Linux Kernel,Gdb,Qemu,我是内核开发新手,我想知道如何使用QEMU和gdb运行/调试linux内核。我正在读罗伯特·洛夫的书,但不幸的是,这本书对读者如何安装合适的工具来运行或调试内核没有帮助。。。所以我所做的就是遵循这个教程。我使用eclipse作为IDE在内核上开发,但我想首先让它在QEMU/gdb下工作。到目前为止,我所做的是: 1) 要使用以下命令编译内核: make defconfig (then setting the CONFIG_DEBUG_INFO=y in the .config) make -j4

我是内核开发新手,我想知道如何使用QEMU和gdb运行/调试linux内核。我正在读罗伯特·洛夫的书,但不幸的是,这本书对读者如何安装合适的工具来运行或调试内核没有帮助。。。所以我所做的就是遵循这个教程。我使用eclipse作为IDE在内核上开发,但我想首先让它在QEMU/gdb下工作。到目前为止,我所做的是:

1) 要使用以下命令编译内核:

make defconfig (then setting the CONFIG_DEBUG_INFO=y in the .config)
make -j4
2) 编译完成后,我使用以下命令运行Qemu:

qemu-system-x86_64 -s -S /dev/zero -kernel /arch/x86/boot/bzImage
它以“停止”状态启动内核

3) 因此,我必须使用gdb,我尝试以下命令:

gdb ./vmlinux
正确运行它,但是。。。现在我不知道该怎么办。。。我知道我必须在端口1234(Qemu使用的默认端口)上使用远程调试,使用vmlinux作为调试的符号表文件

所以我的问题是:我应该怎么做才能在Qemu上运行内核,将我的调试器连接到它,从而让它们一起工作,让我的内核开发更轻松。

我会尝试:

(gdb) target remote localhost:1234
(gdb) continue
使用“-s”选项使qemu在端口tcp::1234上侦听,如果您在同一台计算机上,则可以将该端口作为localhost:1234连接到该端口。Qemu的'-s'选项使Qemu停止执行,直到您发出continue命令


最好的办法可能是看一看体面的GDB教程,了解您正在做的事情。看起来很不错。

当您尝试使用gdb启动vmlinux exe时,gdb上的第一件事就是发布CMD:

(gdb)目标远程本地主机:1234

(gdb)中断启动内核

(续)


这将在启动内核时中断内核。

BjoernID的回答对我来说并不真正有效。在第一次继续之后,没有到达断点,在中断时,我会看到如下行:

0x0000000000000000 in ?? ()
(gdb) break rapl_pmu_init
Breakpoint 1 at 0xffffffff816631e7
(gdb) c
Continuing.
^CRemote 'g' packet reply is too long: 08793000000000002988d582000000002019[..]
我想这与不同的CPU模式有关(BIOS中的实模式与Linux启动时的长模式)。无论如何,解决方案是先运行QEMU而不等待(即不使用
-S
):

在我的例子中,我需要在引导过程中中断一些东西,所以在一些分秒后,我运行gdb命令。如果您有更多的时间(例如,您需要调试手动加载的模块),那么时间并不重要

gdb
允许您指定启动时应运行的命令。这使得自动化更容易一些。要连接到QEMU(现在应该已经启动),断开函数并继续执行,请使用:

gdb -ex 'target remote localhost:1234' -ex 'break rapl_pmu_init' -ex c ./vmlinux

对我来说,调试内核的最佳解决方案是使用Eclipse环境中的gdb。您应该在远程调试部分为gdb设置适当的端口(必须与qemu启动字符串中指定的端口相同)。以下是手册:
在Ubuntu 16.10主机上测试的分步程序

为了快速从头开始,我在以下位置制作了一个最小的全自动QEMU+Buildroot示例:主要步骤如下所述

首先获取一个根文件系统
rootfs.cpio.gz
。如果需要,请考虑:

  • 最小的
    init
    -仅可执行映像:
  • Busybox交互系统:
然后在Linux内核上:

git checkout v4.15
make mrproper
make x86_64_defconfig
cat <<EOF >.config-fragment
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
CONFIG_GDB_SCRIPTS=y
EOF
./scripts/kconfig/merge_config.sh .config .config-fragment
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage \
                   -initrd rootfs.cpio.gz -S -s \
                   -append nokaslr
我们完成了

有关内核模块,请参阅:

对于Ubuntu14.04,GDB7.7.1,
hbreak
是必需的,
break
软件断点被忽略。在16.10中不再是这样了。另见:

乱七八糟的
断开连接
以及随后发生的事情都是为了解决错误:

Remote 'g' packet reply is too long: 000000000000000017d11000008ef4810120008000000000fdfb8b07000000000d352828000000004040010000000000903fe081ffffffff883fe081ffffffff00000000000e0000ffffffffffe0ffffffffffff07ffffffffffffffff9fffff17d11000008ef4810000000000800000fffffffff8ffffffffff0000ffffffff2ddbf481ffffffff4600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000
相关线程:

  • 可能是GDB错误
  • 像往常一样,osdev.org是解决这些问题的绝佳来源
  • nokaslr
已知的限制:

  • Linux内核不支持使用
    -O0
  • GDB 7.11将在某些类型的制表符完成上消耗您的内存,即使在
    max completions
    fix之后:可能是该补丁中未涉及的某个角落情况。因此,在调试之前执行
    ulimit-sv500000
    是明智的操作。当我为
    sys\u execve
    filename
    参数完成
    file
    时,特别爆炸,如下所示:
另见:

  • 正式Linux内核“文档”

在Linux系统上,vmlinux是一个静态链接的可执行文件,包含 Linux内核采用Linux支持的一种对象文件格式 包括ELF、COFF和a.out。内核可能需要vmlinux文件 调试、符号表生成或其他操作,但必须进行 在用作操作系统内核之前,可通过添加多重引导 标题、引导扇区和设置例程

此初始根文件系统的映像必须存储在可访问的位置 由Linux引导加载程序加载到计算机的引导固件。这可能是 根文件系统本身,光盘上的一个引导映像,磁盘上的一个小分区 本地磁盘(启动准备,通常使用ext4或FAT文件系统)或 TFTP服务器(在可以从以太网引导的系统上)

  • 编译linux内核

    应用此系列构建内核,启用CONFIG\u DEBUG\u INFO(但关闭CONFIG\u DEBUG\u INFO)

  • 安装GDB和Qemu

    sudo pacman -S gdb qemu
    
  • 创建initramfs

    #!/bin/bash
    
    # Os     : Arch Linux
    # Kernel : 5.0.3
    
    INIT_DIR=$(pwd)
    BBOX_URL="https://busybox.net/downloads/busybox-1.30.1.tar.bz2"
    BBOX_FILENAME=$(basename ${BBOX_URL})
    BBOX_DIRNAME=$(basename ${BBOX_FILENAME} ".tar.bz2")
    RAM_FILENAME="${INIT_DIR}/initramfs.cpio.gz"
    
    function download_busybox {
        wget -c ${BBOX_URL} 2>/dev/null
    }
    
    function compile_busybox {
        tar xvf ${BBOX_FILENAME} && cd "${INIT_DIR}/${BBOX_DIRNAME}/"
        echo "[*] Settings > Build options > Build static binary (no shared libs)"
        echo "[!] Please enter to continue"
        read tmpvar
        make menuconfig && make -j2 && make install
    }
    
    function config_busybox {
        cd "${INIT_DIR}/${BBOX_DIRNAME}/"
        rm -rf initramfs/ && cp -rf _install/ initramfs/
        rm -f initramfs/linuxrc
        mkdir -p initramfs/{dev,proc,sys}
        sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} initramfs/dev/
    
    cat > "${INIT_DIR}/${BBOX_DIRNAME}/initramfs/init" << EOF
    #!/bin/busybox sh
    mount -t proc none /proc
    mount -t sysfs none /sys
    
    exec /sbin/init
    EOF
    
        chmod a+x initramfs/init
        cd "${INIT_DIR}/${BBOX_DIRNAME}/initramfs/"
        find . -print0 | cpio --null -ov --format=newc | gzip -9 > "${RAM_FILENAME}"
        echo "[*] output: ${RAM_FILENAME}"
    
    }
    
    download_busybox
    compile_busybox
    config_busybox
    
  • 用GDB调试Linux内核

    ~/Projects/kernelbuild/linux-5.0.3 ➭ gdb vmlinux
    ...
    (gdb) target remote localhost:1234
    Remote debugging using localhost:1234
    0xffffffff89a4b852 in ?? ()
    (gdb) break start_kernel
    Breakpoint 1 at 0xffffffff826ccc08
    (gdb)
    Display all 190 possibilities? (y or n)
    (gdb) info functions
    All defined functions:
    
    Non-debugging symbols:
    0xffffffff81000000  _stext
    0xffffffff81000000  _text
    0xffffffff81000000  startup_64
    0xffffffff81000030  secondary_startup_64
    0xffffffff810000e0  verify_cpu
    0xffffffff810001e0  start_cpu0
    0xffffffff810001f0  __startup_64
    0xffffffff81000410  pvh_start_xen
    0xffffffff81001000  hypercall_page
    0xffffffff81001000  xen_hypercall_set_trap_table
    0xffffffff81001020  xen_hypercall_mmu_update
    0xffffffff81001040  xen_hypercall_set_gdt
    0xffffffff81001060  xen_hypercall_stack_switch
    0xffffffff81001080  xen_hypercall_set_callbacks
    0xffffffff810010a0  xen_hypercall_fpu_taskswitch
    0xffffffff810010c0  xen_hypercall_sched_op_compat
    0xffffffff810010e0  xen_hypercall_platform_op
    

  • 非常感谢它的工作:)。我刚刚读完了非淀粉出版社出版的关于DDD、eclipse和gdb的书,但这本书中没有远程调试。我的内核现在正在启动,但它似乎需要时间来加载(因为Qemu在我的机器上似乎只使用1个线程),并且现在被阻塞在:?内核线程助手+0x0/0x10。这是内核加载的方式吗?我的意思是,我们不应该在加载后有一个命令提示符吗?谢谢,这对我有用。然而,我不知道如何强制内核
    #!/bin/bash
    
    # Os     : Arch Linux
    # Kernel : 5.0.3
    
    INIT_DIR=$(pwd)
    BBOX_URL="https://busybox.net/downloads/busybox-1.30.1.tar.bz2"
    BBOX_FILENAME=$(basename ${BBOX_URL})
    BBOX_DIRNAME=$(basename ${BBOX_FILENAME} ".tar.bz2")
    RAM_FILENAME="${INIT_DIR}/initramfs.cpio.gz"
    
    function download_busybox {
        wget -c ${BBOX_URL} 2>/dev/null
    }
    
    function compile_busybox {
        tar xvf ${BBOX_FILENAME} && cd "${INIT_DIR}/${BBOX_DIRNAME}/"
        echo "[*] Settings > Build options > Build static binary (no shared libs)"
        echo "[!] Please enter to continue"
        read tmpvar
        make menuconfig && make -j2 && make install
    }
    
    function config_busybox {
        cd "${INIT_DIR}/${BBOX_DIRNAME}/"
        rm -rf initramfs/ && cp -rf _install/ initramfs/
        rm -f initramfs/linuxrc
        mkdir -p initramfs/{dev,proc,sys}
        sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} initramfs/dev/
    
    cat > "${INIT_DIR}/${BBOX_DIRNAME}/initramfs/init" << EOF
    #!/bin/busybox sh
    mount -t proc none /proc
    mount -t sysfs none /sys
    
    exec /sbin/init
    EOF
    
        chmod a+x initramfs/init
        cd "${INIT_DIR}/${BBOX_DIRNAME}/initramfs/"
        find . -print0 | cpio --null -ov --format=newc | gzip -9 > "${RAM_FILENAME}"
        echo "[*] output: ${RAM_FILENAME}"
    
    }
    
    download_busybox
    compile_busybox
    config_busybox
    
    #!/bin/bash
    
    KER_FILENAME="/home/debug/Projects/kernelbuild/linux-5.0.3/arch/x86/boot/bzImage"
    RAM_FILENAME="/home/debug/Projects/kerneldebug/initramfs.cpio.gz"
    
    qemu-system-x86_64 -s -kernel "${KER_FILENAME}" -initrd "${RAM_FILENAME}" -nographic -append "console=ttyS0"
    
    $ ./qemuboot_vmlinux.sh
    SeaBIOS (version 1.12.0-20181126_142135-anatol)
    
    
    iPXE (http://ipxe.org) 00:03.0 C980 PCI2.10 PnP PMM+07F92120+07EF2120 C980
    
    
    Booting from ROM...
    Probing EDD (edd=off to disable)... o
    [    0.019814] Spectre V2 : Spectre mitigation: LFENCE not serializing, switching to generic retpoline
    can't run '/etc/init.d/rcS': No such file or directory
    
    Please press Enter to activate this console.
    / #  uname -a
    Linux archlinux 5.0.3 #2 SMP PREEMPT Mon Mar 25 10:27:13 CST 2019 x86_64 GNU/Linux
    / #
    
    ~/Projects/kernelbuild/linux-5.0.3 ➭ gdb vmlinux
    ...
    (gdb) target remote localhost:1234
    Remote debugging using localhost:1234
    0xffffffff89a4b852 in ?? ()
    (gdb) break start_kernel
    Breakpoint 1 at 0xffffffff826ccc08
    (gdb)
    Display all 190 possibilities? (y or n)
    (gdb) info functions
    All defined functions:
    
    Non-debugging symbols:
    0xffffffff81000000  _stext
    0xffffffff81000000  _text
    0xffffffff81000000  startup_64
    0xffffffff81000030  secondary_startup_64
    0xffffffff810000e0  verify_cpu
    0xffffffff810001e0  start_cpu0
    0xffffffff810001f0  __startup_64
    0xffffffff81000410  pvh_start_xen
    0xffffffff81001000  hypercall_page
    0xffffffff81001000  xen_hypercall_set_trap_table
    0xffffffff81001020  xen_hypercall_mmu_update
    0xffffffff81001040  xen_hypercall_set_gdt
    0xffffffff81001060  xen_hypercall_stack_switch
    0xffffffff81001080  xen_hypercall_set_callbacks
    0xffffffff810010a0  xen_hypercall_fpu_taskswitch
    0xffffffff810010c0  xen_hypercall_sched_op_compat
    0xffffffff810010e0  xen_hypercall_platform_op