background
All along, the understanding of Linux system is at the application level. After reading advanced programming in UNIX environment, I still lack a deep understanding of the implementation methods of some modules in the system, so I want to study the Linux kernel mechanism.
Simply reading the source code is not as good as debugging the kernel step by step. There are many methods to debug the kernel on the Internet, mainly using Qemu+GDB to debug the kernel, but most of the online materials are scattered and the step records are not detailed enough. The author has taken many detours in the implementation process, and it is not convenient to directly use GDB to debug and view the code, Therefore, VS Code+Qemu+GDB is used for Linux kernel debugging, and the main steps in the process are recorded.
environment
Since the personal host is MacOS 10.14.5, use Ubuntu 14.04 amd64 to build the kernel debugging environment on the Parrales Desktop virtual machine.
If the host itself is a Linux system, there is no need to install a virtual machine, and the kernel debugging environment can be built directly, with better performance.
Main steps
summary
- Install Ubuntu in the virtual machine (parales desktop, vmware, etc.) (if the host itself is a Linux system, this step can be omitted)
- Download linux kernel, compile and generate bzImage
- Update GCC, G + +, GDB
- Installing Qemu
- Install VS Code and configure it
Virtual machine Ubuntu installation
Install Ubuntu 14.04 in the virtual machine (Parrales Desktop, vmware, etc.), where the Ubuntu version can be selected freely, as long as Parrales tools can be installed normally.
In addition, the x64 version is the best choice, and the performance will be better. The specific installation process is omitted. Due to the slow update speed of the original apt, the domestic source needs to be updated. Tsinghua apt source is used here
vim /etc/apt/sources.list
Kernel compilation
#Installation and compilation related dependencies apt-get install libncurses5-dev libssl-dev bison flex libelf-dev gcc make openssl libc6-dev #If you choose Tsinghua source here, the domestic speed will be much faster wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v4.x/linux-4.5.tar.gz #decompression tar -xvf linux-4.5.tar.gz cd linux-4.5 #Configure compilation options. Various configurations for kernel compilation can be performed here. Since debugging related configurations have been checked by default, you can exit and save directly from esc make menuconfig #Start multi-threaded compilation. This step will take a long time for the first time. Later, the speed will become faster because intermediate files have been generated make -j8
After compilation, the following will be generated in the directory
./vmLinux
./arch/x86/boot/bzImage
vmLinux is the debugging Map file required by GDB, and bzImage is the large kernel file
If you need to install the kernel, you can perform the following steps (this step is not necessary)
#If you need to install the kernel, make modules_install make install
After installation, restart the host and select a new kernel in Grub.
Update GCC,G++,GDB
Because the default GDB of the system will have the error of "Remote 'g' packet reply is too long" when debugging the kernel, we need to modify the source code of GDB instead of Buy a mobile game account Compiling the new version of GDB source code requires a new version of GCC and G + +, so the following needs to be updated:
#Install GCC-9,G++-9 sudo apt install software-properties-common sudo apt-get update sudo apt install gcc-9 g++-9 #Execute after installation gcc -v #If it is a new version of GCC, it is completed. If it is not a new version, you need to link GCC to gcc-9
Compile and install GDB
#Download GDB. The gnu source of Beijing Jiaotong is used here. The domestic speed will be much faster wget https://mirror.bjtu.edu.cn/gnu/gdb/gdb-8.3.tar.xz tar -xvf gdb-8.3.tar.xz #Make the following changes under gdb/remote.c file /* 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; } } #Compile GDB ./configure ./make -j8 sudo ./make install #Open GDB to see if it is a new version gdb
Qemu configuration
#Installing qemu apt-get install qemu
Make rootfs of helloworld for testing
touch main.c
Type the following code
#include <stdio> int main() { printf("hello world!"); printf("hello world!"); printf("hello world!"); printf("hello world!"); fflush(stdout); while(1); return 0; }
compile
gcc --static -o helloworld main.c echo helloworld | cpio -o --format=newc > rootfs
Qemu direct run test (not required)
qemu-system-x86_64 \ -kernel ./arch/x86/boot/bzImage \ -initrd ./rootfs \ -append "root=/dev/ram rdinit=/helloworld"
Qemu starts GDB debugging
qemu-system-x86_64 \ -kernel ./arch/x86/boot/bzImage \ -initrd ./rootfs \ -append "root=/dev/ram rdinit=/helloworld" \ -smp 2 \ -s -S
The above will open Qemu and enter the state of waiting for debugging. At this time, you can directly gdb debug, as follows (not required)
gdb ./vmLinux #Debug the following target remote:1234 b start_kernel c
It can be found that the kernel is broken at start_ On kernel function
VS code configuration
1. vscode opens the kernel source folder
2. Install the gdb debug plug-in
3. Debug - > open configurations, do the following configuration
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "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", } ] }
Set the breakpoint to start in init/main.c_ In the kernel function, Qemu starts GDB debugging, and vscode start debug starts debugging the kernel.