Linux 內核終於可以 debug 了!


低並發編程 戰略上藐視技術,戰術上重視技術  

今天終於成功 debug 了 Linux 內核,允許我一驚一乍給大家分享下喜悅吧!

之前讀 Linux 的源碼,一直想着如果能 debug 就好了。

無奈 Java 出身的我,本來對 c 就很不熟,跑起一個 c 代碼就很費勁了,更別說調試,而且還是調試這種和普通 c 項目不一樣的內核代碼。

僅僅是出於學習 Linux 內核源碼的目的想要調試,所以不想花太多時間研究如何構建這個調試環境,想着在網上找個教程,一次性部署好之后就一直用了,無奈一直沒找到能照着文檔就搭建成功的。

今天終於找到一個大佬的文檔,直接按上面說的就能操作成功,分享給大家,同時我自己也做個備份。

先照着這個文檔,使得可以用 gdb 進行調試:

https://wenfh2020.com/2021/05/19/gdb-kernel-networking/

再按照這個文檔,用 vscode 進行更直觀地調試(當然也是 gdb 方式):

https://wenfh2020.com/2021/06/23/vscode-gdb-debug-linux-kernel/

最終效果是。

虛擬機這邊用 qemu 啟動 Linux 5.0.1 內核。

圖片

本機這邊用 vscode 的 ssh-remote 插件遠程連接虛擬機,然后用 gdb debug。

圖片

給大家放大點。

圖片

main.c 下的主方法。

看到斷點進來相當激動了!這個文檔我可得保存好,虛擬機鏡像也不敢動了,哈哈,以后就可以開開心心 debug Linux 內核啦。

不過中間也踩了好多坑,原本我想着靈活一點,用自己的 ubuntu 版本,用自己想調試的 Linux 內核版本,無奈都失敗了,中間有各種奇奇怪怪的問題...

我就放棄了,乖乖先按照人家的文檔跑起來再說吧~

不知道文檔里是不是有多余操作,反正各種騷操作我是看不懂,還要改 gdb 的源碼。

之后我看看能不能把低版本的 Linux 也搞通,如果大家有更方便地調試方法,可以教教我,這塊真是空白。

 Linux 內核終於可以 debug 了! (qq.com)

gdb 調試 Linux 內核網絡源碼(附視頻)

最近在看 Linux 內核的網絡部分源碼,在 MacOS 上搭建調試環境,通過 gdb 調試,熟悉內核網絡接口的工作流程。

調試環境是跑在虛擬機里的,在 windows 上應該也能將環境搭建起來。


1. 目標


2. 視頻

視頻連接:gdb 調試 Linux 內核網絡源碼


3. 流程

  • 下載 ubuntu 14.04
1
http://mirrors.aliyun.com/ubuntu-releases/14.04/ubuntu-14.04.6-desktop-amd64.iso
  • vmware 安裝 ubuntu。
  1. 虛擬系統磁盤空間,盡量給大一些,例如 100 G。
  2. 通過 root 權限安裝 linux 內核。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 設置 root 密碼。
sudo passwd
# 切換 root 用戶。
su root

# 安裝部分工具。
apt-get install vim tmux openssh-server git -y

# 添加 alias 方便操作終端。
vim ~/.bashrc
# 添加 alias c='clear'
source ~/.bashrc

# 啟動 ssh. 避免后面 qemu 調試導致界面卡死,可以遠程關閉進程。
ps -e | grep ssh
sudo /etc/init.d/ssh start
  • 下載編譯 linux 內核。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 下載內核源碼。
cd /root
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.1.tar.xz
xz -d linux-5.0.1.tar.xz
tar -xvf linux-5.0.1.tar
cd linux-5.0.1

apt install build-essential flex bison libssl-dev libelf-dev libncurses-dev -y

# 設置調試的編譯菜單。
make menuconfig

# 下面選項如果沒有選上的,選上,然后 save 保存設置,退出 exit。
Kernel hacking  --->
     Compile-time checks and compiler options  ---> 
         [*] Compile the kernel with debug info
         [*]     Provide GDB scripts for kernel debugging


Processor type and features  --->
    [*] Randomize the address of the kernel image (KASLR) 

# 編譯內核。
make -j8

mkdir rootfs
  • 調試內核。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 下載測試項目。
cd ..
git clone https://github.com/mengning/menu.git
cd menu
vim Makefile
# 修改編譯項:
# qemu-system-x86_64 -kernel ../linux-5.0.1/arch/x86/boot/bzImage -initrd ../rootfs.img

# 安裝模擬器 qemu 和編譯環境。
apt install qemu libc6-dev-i386

# 編譯測試項目。
make rootfs

# 調試 kernel
qemu-system-x86_64 -kernel ../linux-5.0.1/arch/x86/boot/bzImage -initrd ../rootfs.img -append nokaslr -S -s

cd ../linux-5.0.1

# 發現低版本的 gdb 調試出現問題,需要升級。
gdb ./vmlinux
  • 安裝高版本 gdb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cd /root
gdb -v | grep gdb
apt remove gdb -y
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt install software-properties-common
sudo apt-get update
sudo apt-get install gcc-snapshot -y
gcc --version
sudo apt install gcc-9 g++-9 -y
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 --slave /usr/bin/g++ g++ /usr/bin/g++-9
gcc --version
#wget https://mirror.bjtu.edu.cn/gnu/gdb/gdb-8.3.tar.xz
wget http://ftp.gnu.org/gnu/gdb/gdb-8.3.tar
tar -xvf gdb-8.3.tar.xz
cd gdb-8.3
# 修改 gdb/remote.c 代碼。
vim gdb/remote.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* Further sanity checks, with knowledge of the architecture.  */
// if (buf_len > 2 * rsa->sizeof_g_packet)
//   error (_("Remote 'g' packet reply is too long (expected %ld bytes, got %d "
//      "bytes): %s"),
//    rsa->sizeof_g_packet, buf_len / 2,
//    rs->buf.data ());

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[i].pnum == -1)
            continue;
        if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
            rsa->regs[i].in_g_packet = 0;
        else
            rsa->regs[i].in_g_packet = 1;
    }
}
1
2
3
4
5
./configure
make -j8
cp gdb/gdb /usr/bin/
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 0 --slave /usr/bin/g++ g++ /usr/bin/g++-9
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 100
  • 調試 tcp 網絡通信。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cd /root/linux-5.0.1
git clone https://github.com/mengning/linuxnet.git
# 拷貝文件到 menu
cd linuxnet/lab2
# 修改拷貝的路徑。
vim Makefile
# cp test_reply.c ../../../menu/test.c
# cp syswrapper.h ../../../menu

make

cd ../../../menu
make rootfs
cd ../linux-5.0.1/linuxnet/lab3
# qemu-system-x86_64 -kernel ../../arch/x86/boot/bzImage -initrd ../rootfs.img

make rootfs

# 調試
qemu-system-x86_64 -kernel ../../arch/x86/boot/bzImage -initrd ../rootfs.img -append nokaslr -S -s
1
2
3
4
5
6
7
8
cd /root/linux-5.0.1
gdb ./vmlinux
# 下斷點。
b tcp_v4_connect
b inet_csk_accept
# gdb 遠程連接調試程序。
target remote : 123
c

用戶可以根據自己的需要去下斷點,也可以修改 linuxnet 源碼進行調試。


4. vscode + gdb

vscode + gdb 調試 Linux 內核更人性化一點。

詳看:vscode + gdb 遠程調試 linux 內核源碼(附視頻)


5. 參考

 

vscode + gdb 遠程調試 linux 內核源碼(附視頻)

前段時間才搭建起來 gdb 調試 Linux 內核網絡源碼視頻 ),但是 gdb 命令調試效率不高。磨刀不誤砍柴工,所以折騰一下 vscode,使調試人性化一點。


1. 視頻

視頻連接:vscode + gdb 遠程調試 linux (EPOLL) 內核源碼


2. 搭建調試環境

要搭建 vscode + gdb 調試 Linux 內核環境,首選要搭建:gdb 調試 Linux 內核源碼視頻,然后再配置 vscode 進行測試調試。


3. vscode 配置

3.1. vscode 插件

  • ms-vscode.cpptools
  • remote-ssh

避免 remote-ssh 工作過程中頻繁要求輸入登錄密碼,最好設置一下 ssh 免密碼登錄(參考:[shell] ssh 快捷登錄)。


3.2. 項目調試配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "kernel-debug",
            "type": "cppdbg",
            "request": "launch",
            "miDebuggerServerAddress": "127.0.0.1:1234",
            "program": "${workspaceFolder}/vmlinux",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "logging": {
                "engineLogging": false
            },
            "MIMode": "gdb",
        }
    ]
}

4. 測試調試

4.1. 虛擬機操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 虛擬機進入 linux 內核源碼目錄。
cd /root/linux-5.0.1

# 從 github 下載內核測試源碼。
git clone https://github.com/wenfh2020/kernel_test.git

# 進入測試源碼目錄。
cd kernel_test/test_epoll_tcp_server
# make 編譯
make
# 通過 qemu 啟動內核測試用例。
make rootfs
# 在 qemu 窗口輸入小寫字符 's', 啟動測試用例服務程序。
s
# 在 qemu 窗口輸入小寫字符 'c', 啟動測試用例客戶端程序。
c

# 通過 qemu 命令啟動內核測試用例進行調試。
qemu-system-x86_64 -kernel ../../arch/x86/boot/bzImage -initrd ../rootfs.img -append nokaslr -S -s
# 在 qemu 窗口輸入小寫字符 's', 啟動測試用例服務程序。
s
# 在 qemu 窗口輸入小寫字符 'c', 啟動測試用例客戶端程序。
c

4.2. 實體機操作

  1. vscode 連接遠程虛擬機。
  2. vscode 打開虛擬機 Linux 內核源碼。
  3. vscode 在 Linux 內核源碼的 eventpoll.c 文件,對對應接口(epoll_create, epoll_wait, epoll_ctl)下斷點。
  4. F5 快捷鍵啟動 vscode 調試。

5. 小結

  • 我認為在閱讀 Linux 內核源碼前,最好先把調試環境搭建起來,因為 Linux 內核源碼龐大復雜,新手很難從復雜的源碼調用關系中理清思路。
  • 老師傳道受業,只會給你指出一條學習路線,還會提醒你路上可能遇到哪些大坑,但是路上還有無數小坑,你只有通過實踐調試,才能找到答案。
  • 在求知的路上,讓我們共勉😸!

Ubuntu18.04編譯調試OpenJDK15 - 知乎

Ubuntu18.04編譯調試OpenJDK15

Ubuntu18.04編譯調試OpenJDK15

自從 Oracle Java SE support Roadmap 更新, OpenJDK就分為了 Oracle's OpenJDK和 AdoptOpenJDK

  • Oracle's OpenJDK : Oracle從JDK 9開始開始發布基於GPL協議的開源構建版本,從JDK 11開始,Oracle's OpenJDK和Oracle JDK在功能上幾乎完全一致
  • AdoptOpenJDK : 由社區維護的發行版本,純血的OpenJDK

獲取OpenJDK源碼

OpenJDK 社區采用mercurial 作為版本控制工具. 安裝mercurial

$ sudo apt install mercurial

安裝完成后即可下再OpenJDK源碼, 可以在 OpenJDK Repositories 中找到對應的版本,並通過mercurial下載源碼

以OpenJDK最新版本Master + dev為例

$ hg clone  https://hg.openjdk.java.net/jdk/jdk

經過漫長的等待后 通過

$ bash get_source.sh

獲取源碼,盡量多重復獲取幾次,因此單次下載不一定完整,直到不出現如下提示即下載完整了

WARNING: langtools exited abnormally (255)
WARNING: nashorn exited abnormally (255)

boot JDK

構建OpenJDK需要一個預先存在的JDK。這稱為“boot JDK”

Boot JDK最好是當前版本的前一個版本,即 n-1,因此選擇下載 OpenJDK 14 下載完后解壓備用

Build AdoptOpenJDK

$ cd ${OpenJDK源碼目錄}
$ bash configure --with-boot-jdk=${YourBootJDKPath} --with-debug-level=slowdebug

其中 :

  • --with-boot-jdk : 表示指定boot JDK的路徑,如果已經設置了JAVA_HOME則無需指定
  • --with-debug-level : 表 設置debug等級,可選值為release,fastdebug,slowdebugoroptimized. 默認為releaseslowdebug表示沒有優化,有debug log 其定義於 Define

然后過程中會檢查系統依賴,如果缺少依賴會提示安裝, 下面是所有需要安裝的依賴

$ sudo apt-get install autoconf
$ sudo apt-get install libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev
$ sudo apt-get install libcups2-dev
$ sudo apt-get install libfontconfig1-dev
$ sudo apt-get install libasound2-dev

直到出現如下信息表示配置完成:

summary

它會在 build/目錄生成相應的 configuration , 然后通過

$ make all

編譯.

值得注意的是 如果有多份configurations那么就需要在 CONF環境變量中指定配置不然會如下錯誤

未指定configuration

可以指定CONF環境變量 即可開始編譯

$ CONF=linux-x86_64-server-slowdebug make all

風扇的呼嘯

大概10分鍾左右編譯完成.

完成之后可以在 build/linux-x86_64-server-slowdebug/jdk/bin中執行./java -version

調試

這里選擇使用vscode調試, OpenJDK提供了一個命令

$ make vscode-project

可以快速生產vscode workspace.

我這里使用vscode remote 連接到 Ubuntu中,然后 vscode File-> Open Workspace... 選擇 build/linux-x86_64-server-slowdebug/jdk.code-workspace即可,然后根據提示安裝相應的插件

安裝完成后需要reloadvscode

然后 Run->Open Configurations打開launch.json 在 "name": "java" 的配置中加上 "args": ["-version"] ,然后 F5即可看到如下結果

眾所周知... C/C++ 的入口為 main 函數, 所以 打開 main.c文件, 下一個斷點.. 就可以愉快的玩耍了...

更多編譯的選項可以閱讀官方文檔...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM