VS Code-based Linux kernel debugging environment construction and start_kernel tracking analysis

1. Install development tools

sudo apt install build-essential
 
sudo apt install qemu # install QEMU# as a virtual machine
 
sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev
#Dependencies required to compile the kernel --- some basic libraries

2. Download the kernel source code

sudo apt install axel

#Download the source code package
axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz

xz -d linux-5.4.34.tar.xz
 
tar -xvf linux-5.4.34.tar #Decompress the source code
 
cd linux-5.4.34

3. Configure kernel options

make defconfig # Default configuration is based on 'x86_64_defconfig'
make menuconfig # Open debug related options

Press Enter to enter “—>”, “y” and “n” change “[*] [ ]” to perform the following settings respectively:

Kernel hacking —>
Compile-time checks and compiler options —>
[*] Compile the kernel with debug info
[*] Provide GDB scripts for kernel debugging
[*] Kernel debugging
# Turn off KASLR (random address), otherwise the breakpoint will fail. In this way, the debugger can trace the source code. The reason why the random address is set is to prevent hacker attacks:
Processor type and features —->
[ ] Randomize the address of the kernel image (KASLR)

4. Compile and run the kernel

make -j$(nproc) # nproc gives the number of CPU cores/threads available

# Test whether the kernel can be loaded and run normally, because there will be a kernel panic without a file system
qemu-system-x86_64-kernel arch/x86/boot/bzImage

After testing it, a Kernel panic appeared:

5. Create a memory root file system

When the computer is powered on, the kernel is first loaded by the bootloader, and then the kernel needs to mount the memory root file system, which contains the necessary device drivers and tools. The bootloader loads the root file system into the memory, and the kernel will mount it to the root directory/download , and then run the init script in the root file system to perform some startup tasks, and finally mount the real disk root file system.

In order to simplify the experimental environment, we only make the memory root file system here. Here, BusyBox is used to build a minimal memory root file system and provide basic user mode executable programs.

First download the busybox source code from https://www.busybox.net and decompress it. After the decompression is complete, configure, compile and install it like the kernel.

axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2
 
tar -jxvf busybox-1.31.1.tar.bz2
 
cd busybox-1.31.1

make menuconfig #Remember to compile it into a static link instead of a dynamic link library

Settings —>
[*] Build static binary (no shared libs) static compilation

Then compile and install, and it will be installed in the _install directory under the source code directory by default.

make -j$(nproc) & amp; & amp; make install

Then create a memory root file system image, the process is as follows:

mkdir rootfs
 
cd rootfs
 
cp ../../busybox-1.31.1/_install/* ./ -rf
 
mkdir dev proc sys home
 
sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/

Note: The rootfs folder I created under the linux-5.4.34 folder, the linux-5.4.34 folder is at the same level as the busybox-1.31.1 folder, and both are in the /home/mjn directory. As shown below.

Next, prepare the init script file and put it in the root file system and directory (rootfs/init), add the following content to the init file: (Use touch init to create the init script file, then “vim init” to open the init file, and then press i to insert mode, paste it in, then press ESC to enter the command mode, :wq to save and exit.)

#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
echo "Wellcome MajingnanOS!"
echo "--------------------"
cd home
/bin/sh

The mount command is to mount proc and sys.

Next, add executable permissions to the script:

chmod + x init

Packaged into a memory root file system image

find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz

Test to mount the root file system to see if the init script is executed after the kernel is started (note: my rootfs.cpio.gz is placed in the linux-5.4.34 file)

qemu-system-x86_64 -kernel ./arch/x86/boot/bzImage -initrd rootfs.cpio.gz

The init script executed successfully.

6. Configure VSCode to debug Linux kernel

First download the vscode installation package in the linux system, open the Firefox browser that comes with ubuntu to download: official download address, select the .deb download option, here I downloaded:

Then execute the installation command sudo apt install ./.deb, the installation command corresponding to my file is:

sudo apt install ./code_1.76.2-1678817801_amd64.deb

Also install the VSCode plugins C/C++ Intellisense and C/C++ Themes. Since the plug-in C/C++ Intellisense requires GNU Global, it is also necessary to install GNU Global using the following command.

sudo apt install global

Next, search and install these extensions in VScode:

To open the previously prepared linux-5.4.34 folder in vscode, you need to do two things:

(1) Command line input

python ./scripts/gen_compile_commands.py

Since the Linux kernel is highly customized, there is no way to make Intellisense prompt normally by configuring includePath, etc. Here, a Python script is used to generate the compile_commands.json file to help Intellisense prompt normally (including header files and macro definitions, etc.). Run the following command directly in the Linux source code directory to generate compile_commands.json.

(2) You need to manually place the configuration file in the linux-5.4.34 folder before this: create a new .vscode folder, (you need to click ctrl + h to display hidden files) and put all the files in the configuration file Inside the .vscode folder:

Next, you can open the linux-5.4.34 folder in vscode: you can see that the .vscode configuration folder has appeared.

At the same time, change tasks.json: it is consistent with the problem of the previous file placement. (My file placement is changed like this)

Now the debugging environment of vscode is configured.

7. Tracking analysis

Because the starting point of the linux kernel is the “start_kernel” function, so first break the point at start_kernel: click the run and debug icon, add a function breakpoint in the breakpoint: start_kernel, click run–start debugging, you can start from start_kernel Start tracking and analysis.

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. CS introductory skill tree Introduction to LinuxFirst acquaintance with Linux28824 people are studying systematically