<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用 GDB + Qemu 調(diào)試 Linux 內(nèi)核

          共 6287字,需瀏覽 13分鐘

           ·

          2021-02-09 19:15


          更多奇技淫巧歡迎訂閱博客:https://fuckcloudnative.io

          1. 概述

          在某些情況下,我們需要對于內(nèi)核中的流程進(jìn)行分析,雖然通過 BPF 的技術(shù)可以對于函數(shù)傳入的參數(shù)和返回結(jié)果進(jìn)行展示,但是在流程的調(diào)試上還是不如直接 GDB 單步調(diào)試來的直接。本文采用的編譯方式如下,在一臺 16 核 CentOS 7.7 的機(jī)器上進(jìn)行內(nèi)核源碼相關(guān)的編譯(主要是考慮編譯效率),調(diào)試則是基于 VirtualBox 的 Ubuntu 20.04 系統(tǒng)中,采用 Qemu + GDB 進(jìn)行單步調(diào)試,網(wǎng)上查看了很多文章,在最終進(jìn)行單步跟蹤的時候,始終不能夠在斷點處停止,進(jìn)行過多次嘗試和查詢文檔,最終發(fā)現(xiàn)需要在內(nèi)核啟動參數(shù)上添加 nokaslr ,本文是對整個搭建過程的總結(jié)。

          2. Linux 內(nèi)核編譯和文件系統(tǒng)制作

          Linux 內(nèi)核編譯

          編譯內(nèi)核和制作文件系統(tǒng)在 CentOS 7.7 的機(jī)器上。源碼從國內(nèi)清華的源下載:http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/, 此處選擇 linux-4.19.172.tar.gz 版本。詳細(xì)編譯步驟如下:

          $?sudo?yum?group?install?"Development?Tools"
          $?yum?install?ncurses-devel?bison?flex?elfutils-libelf-devel?openssl-devel

          $?wget?http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/v4.x/linux-4.19.172.tar.gz
          $?tar?xzvf?linux-4.19.172.tar.gz
          $?cd?linux-4.19.172/
          $?make?menuconfig

          在內(nèi)核編譯選項中,開啟如下 “Compile the kernel with debug info”, 4.19.172 中默認(rèn)已經(jīng)選中:

          Kernel hacking —> Compile-time checks and compiler options —> [ ] Compile the kernel with debug info

          以上配置完成后會在當(dāng)前目錄生成 .config 文件,我們可以使用 grep 進(jìn)行驗證:

          #?grep?CONFIG_DEBUG_INFO?.config
          CONFIG_DEBUG_INFO=y

          接著我們進(jìn)行內(nèi)核編譯:

          $?nproc???????#?查看當(dāng)前的系統(tǒng)核數(shù)
          $?make?-j?12??#?或者采用?make?bzImage?進(jìn)行編譯,?-j?N,表示使用多少核并行編譯

          #?未壓縮的內(nèi)核文件,這個在?gdb?的時候需要加載,用于讀取?symbol?符號信息,由于包含調(diào)試信息所以比較大
          $?ls?-hl?vmlinux
          -rwxr-xr-x?1?root?root?449M?Feb??3?14:46?vmlinux

          #?壓縮后的鏡像文件
          $?ls?-hl?./arch/x86_64/boot/bzImage
          lrwxrwxrwx?1?root?root?22?Feb??3?14:47?./arch/x86_64/boot/bzImage?->?../../x86/boot/bzImage

          $?ls?-hl?./arch/x86/boot/bzImage
          -rw-r--r--?1?root?root?7.6M?Feb??3?14:47?./arch/x86/boot/bzImage

          不同發(fā)行版本下的內(nèi)核的詳細(xì)編譯文檔可以參考這里[1]。

          啟動內(nèi)存文件系統(tǒng)制作

          #?首先安裝靜態(tài)依賴,否則會有報錯,參見后續(xù)的排錯章節(jié)
          $?yum?install?-y?glibc-static.x86_64?-y

          $?wget?https://busybox.net/downloads/busybox-1.32.1.tar.bz2
          $?tar?-xvf?busybox-1.32.1.tar.bz2
          $?cd?busybox-1.32.1/

          $?make?menuconfig

          #?安裝完成后生成的相關(guān)文件會在?_install?目錄下
          $?make?&&?make?install

          $?cd?_install
          $?mkdir?proc
          $?mkdir?sys
          $?touch?init

          #??init?內(nèi)容見后續(xù)章節(jié),為內(nèi)核啟動的初始化程序
          $?vim?init

          #?必須設(shè)置成可執(zhí)行文件
          $?chmod?+x?init

          $?find?.?|?cpio?-o?--format=newc?>?./rootfs.img
          cpio:?File?./rootfs.img?grew,?2758144?new?bytes?not?copied
          10777?blocks

          $?ls?-hl?rootfs.img
          -rw-r--r--?1?root?root?5.3M?Feb??2?11:23?rootfs.img

          其中上述的 init 文件內(nèi)容如下,打印啟動日志和系統(tǒng)的整個啟動過程花費(fèi)的時間:

          #!/bin/sh
          echo?"{==DBG==}?INIT?SCRIPT"
          mkdir?/tmp
          mount?-t?proc?none?/proc
          mount?-t?sysfs?none?/sys
          mount?-t?debugfs?none?/sys/kernel/debug
          mount?-t?tmpfs?none?/tmp

          mdev?-s
          echo?-e?"{==DBG==}?Boot?took?$(cut?-d'?'?-f1?/proc/uptime)?seconds"

          #?normal?user
          setsid?/bin/cttyhack?setuidgid?1000?/bin/sh

          到此為止我們已經(jīng)編譯了好了 Linux 內(nèi)核(vmlinux 和 bzImage)和啟動的內(nèi)存文件系統(tǒng)(rootfs.img)。

          錯誤排查

          在編譯過程中出現(xiàn)以下報錯:

          /bin/ld:?cannot?find?-lcrypt
          /bin/ld:?cannot?find?-lm
          /bin/ld:?cannot?find?-lresolv
          /bin/ld:?cannot?find?-lrt
          collect2:?error:?ld?returned?1?exit?status
          Note:?if?build?needs?additional?libraries,?put?them?in?CONFIG_EXTRA_LDLIBS.
          Example:?CONFIG_EXTRA_LDLIBS="pthread?dl?tirpc?audit?pam"

          出錯的原因是因為我們采用靜態(tài)編譯依賴的底層庫沒有安裝,如果不清楚這些庫有哪些 rpm 安裝包提供,則可以通過 yum provides 命令查看,然后安裝相關(guān)依賴包重新編譯即可。

          $?yum?provides?*/libm.a
          //?...
          glibc-static-2.17-317.el7.x86_64?:?C?library?static?libraries?for?-static?linking.
          Repo????????:?base
          Matched?from:
          Filename????:?/usr/lib64/libm.a

          3. Qemu 啟動內(nèi)核

          在上述步驟準(zhǔn)備好以后,我們需要在調(diào)試的 Ubuntu 20.04 的系統(tǒng)中安裝 Qemu 工具,其中調(diào)測的 Ubuntu 系統(tǒng)使用 VirtualBox 安裝。

          $?apt?install?qemu?qemu-utils?qemu-kvm?virt-manager?libvirt-daemon-system?libvirt-clients?bridge-utils

          把上述編譯好的 vmlinux、bzImage、rootfs.img 和編譯的源碼拷貝到我們當(dāng)前 Unbuntu 機(jī)器中。

          拷貝 Linux 編譯的源碼主要是在 gdb 的調(diào)試過程中查看源碼,其中 vmlinux 和 linux 源碼處于相同的目錄,本例中 vmlinux 位于 linux-4.19.172 源目錄中。

          $?qemu-system-x86_64?-kernel?./bzImage?-initrd??./rootfs.img?-append?"nokaslr?console=ttyS0"?-s?-S?-nographic

          使用上述命令啟動調(diào)試,啟動后會停止在界面處,并等待遠(yuǎn)程 gdb 進(jìn)行調(diào)試,在使用 GDB 調(diào)試之前,可以先使用以下命令進(jìn)程測試內(nèi)核啟動是否正常。

          $?qemu-system-x86_64?-kernel?./bzImage?-initrd??./rootfs.img?-append?"nokaslr?console=ttyS0"?-nographic

          其中命令行中各參數(shù)如下:

          • -kernel ./bzImage:指定啟用的內(nèi)核鏡像;
          • -initrd ./rootfs.img:指定啟動的內(nèi)存文件系統(tǒng);
          • -append "nokaslr console=ttyS0" :附加參數(shù),其中 nokaslr 參數(shù)必須添加進(jìn)來,防止內(nèi)核起始地址隨機(jī)化,這樣會導(dǎo)致 gdb 斷點不能命中;參數(shù)說明可以參見這里[2]
          • -s :監(jiān)聽在 gdb 1234 端口;
          • -S :表示啟動后就掛起,等待 gdb 連接;
          • -nographic:不啟動圖形界面,調(diào)試信息輸出到終端與參數(shù) console=ttyS0 組合使用;

          4. GDB 調(diào)試

          在使用 qemu-system-x86_64 命令啟動內(nèi)核以后,進(jìn)入到我們從編譯機(jī)器上拷貝過來的 Linux 內(nèi)核源代碼目錄中,在另外一個終端我們來啟動 gdb 命令:

          [linux-4.19.172]$?gdb
          (gdb)?file?vmlinux???????????#?vmlinux?位于目錄?linux-4.19.172?中
          (gdb)?target?remote?:1234
          (gdb)?break?start_kernel?????#?有些文檔建議使用?hb?硬件斷點,我在本地測試使用?break?也是?ok?的
          (gdb)?c?????????????#?啟動調(diào)試,則內(nèi)核會停止在?start_kernel?函數(shù)處

          整體運(yùn)行界面如下:

          5. Eclipse 圖像化調(diào)試

          我們可以通過 eclipse-cdt 進(jìn)行可視化項目調(diào)試。

          ”File“ -> “New” -> “Project” ,然后選擇 ”Makefile Project with Existing Code“ 選項,后續(xù)按照向?qū)?dǎo)入代碼。

          在 “Run” -> “Debug Configurations” 選項中,創(chuàng)建一個 ”C/C++ Attach to Application“ 的調(diào)試選項。

          • Project:選擇我們剛才創(chuàng)建的項目名字;
          • C/C++ Application:選擇編譯 Linux 內(nèi)核帶符號信息表的 vmlinux;
          • Build before launching:選擇 ”Disable auto build“;
          • Debugger:選擇 gdbserver,具體設(shè)置如下圖;
          • 在 Debugger 中的 Connection 信息中選擇 ”TCP“,并填寫端口為 ”1234“;

          啟動 Debug 調(diào)試,即可看到與 gdb 類似的窗口。

          啟動 ”Debug“ 調(diào)試以后的窗口如下,在 Debug 窗口欄中,設(shè)置與 gdb 調(diào)試相同的步驟即可。

          6. 參考

          • How to compile and install Linux Kernel 5.6.9 from source code[3]
          • 用 qemu + gdb 調(diào)試 linux 內(nèi)核[4] ***
          • QEMU+busybox 搭建 Linux 內(nèi)核運(yùn)行環(huán)境[5] ***
          • QEMU+gdb 調(diào)試 Linux 內(nèi)核全過程[6] *
          • linux 內(nèi)核編譯與調(diào)試方法[7]
          • How to Build A Custom Linux Kernel For Qemu (2015 Edition)[8]
          • qemu 與 qemu-kvm 到底什么區(qū)別[9]
          • 在 qemu 環(huán)境中用 gdb 調(diào)試 Linux 內(nèi)核[10] *

          參考資料

          [1]

          這里: https://www.cyberciti.biz/tips/compiling-linux-kernel-26.html

          [2]

          這里: https://www.zhihu.com/question/270476360

          [3]

          How to compile and install Linux Kernel 5.6.9 from source code: https://www.cyberciti.biz/tips/compiling-linux-kernel-26.html

          [4]

          用 qemu + gdb 調(diào)試 linux 內(nèi)核: https://www.jianshu.com/p/431d606d322c

          [5]

          QEMU+busybox 搭建 Linux 內(nèi)核運(yùn)行環(huán)境: https://www.sunxiaokong.xyz/2020-01-14/lzx-linuxkernel-qemuinit/

          [6]

          QEMU+gdb 調(diào)試 Linux 內(nèi)核全過程: https://blog.csdn.net/jasonLee_lijiaqi/article/details/80967912

          [7]

          linux 內(nèi)核編譯與調(diào)試方法: https://www.cnblogs.com/syw-casualet/p/5271369.html

          [8]

          How to Build A Custom Linux Kernel For Qemu (2015 Edition): http://mgalgs.github.io/2015/05/16/how-to-build-a-custom-linux-kernel-for-qemu-2015-edition.html

          [9]

          qemu 與 qemu-kvm 到底什么區(qū)別: https://www.cnblogs.com/hugetong/p/8808544.html

          [10]

          在 qemu 環(huán)境中用 gdb 調(diào)試 Linux 內(nèi)核: https://www.cnblogs.com/wipan/p/9264979.html


          原文鏈接:https://www.ebpf.top/post/qemu_gdb_busybox_debug_kernel/



          你可能還喜歡

          點擊下方圖片即可閱讀

          什么?WireGuard 可以讓躲在 NAT 后面的客戶端之間直連了??

          云原生是一種信仰???


          關(guān)注上面的公眾號

          后臺回復(fù)?k8s?獲取史上最方便快捷的 Kubernetes 高可用部署工具,只需一條命令,連 ssh 都不需要!



          點擊?"閱讀原文"?獲取更好的閱讀體驗!

          ??給個「在看」,是對我最大的支持??
          瀏覽 58
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美一级A片免费 | 亚洲第一页面 | 韩国三级视频 | 尤物网在线 | 一本大道久久无码精品一区二区三区 |