【教程】How to build and debug linux Kernel

1.Envirment:

1.VM-Envriment:windown 7, vmware(ubuntu-18.04.1-live-server-amd64.iso), SecureCRT(ssh remote ubuntu), samba-server(see Appendix 1 samba-server create),gcc-32bit(see Appendix 2 gcc-32bit install , but maybe not need nessesary).

2.Destnation-machine: BOCHS(lastest version form official site), QEMU(lastest version form official site).

Bochs can debug assembly, but can't debug using gdb before recompile. Qemu can using gdb, but can't debug in assembly. So need to install both.

3.Debug-method: TDMGCC(Using its GDB in command line debug).

2.compile

source: linux-4.19 download form official site.

1."make help" to see varity of command rerate operation.

2."make mrproper" to remove last configure.

3."make i386_defconfig", may be need to install some lib.

If want to debug by gdb, should be add some iterms to the ".config" file

1)

CONFIG_DEBUG_INFO=y

2)

Discompile KASLR module. (Must have "not set" keyword.)

# CONFIG_RANDOMIZE_BASE is not set

After input "make bzImage", ".config" file would be change, so need check again.Bellow is change process;

Other method(not good, VFS can't launch.)

"C:\Program Files\qemu\qemu-system-i386.exe" -m 512M -smp 4 -kernel arch\x86\boot\bzImage -drive format=raw,file=./disk.raw -append "init=/linuxrc root=/dev/sda" -s -S -append nokaslr

NOTE: The nokasrl Linux command line parameter disables KASRL. But VFS can't launch.

This has been needed since v4.12, when KASLR was turned on by default

kaslr的全称是kernel address space layout randomization,主要是通过每次开机将kernel image 加载到不同的
的地址来增强安全性。

Error:

a.

scripts/Makefile.lib:196: recipe for target 'scripts/kconfig/zconf.tab.c' failed
make[1]: *** [scripts/kconfig/zconf.tab.c] Error 127

Solution:sudo apt-get install bison

b.

scripts/Makefile.lib:188: recipe for target 'scripts/kconfig/zconf.lex.c' failed
make[1]: *** [scripts/kconfig/zconf.lex.c] Error 127

Solution:sudo apt-get install flex

method to config by text:

a.we can configure is throuth ".config" file, which is stored the configure result. and we can direct modify the file.

b.(Better method)cd linux-4.19\arch\x86\configs, copy "i386_defconfig" to "i386simple_defconfig", then change the config.And can using "i386simple_defconfig" to config,too.

other config method:

referece: https://blog.csdn.net/ffmxnjm/article/details/72933915 LINUX内核目录文件说明以及配置并编译内核的方法

make config - 纯文本界面 (最常用的选择)。
make menuconfig - 基于文本彩色菜单和单选列表。这个选项可以加快开发者开发速度。需要安装ncurses(ncurses-devel)。
make nconfig - 基于文本的彩色菜单。需要安装curses (libcdk5-dev)。
make xconfig - QT/X-windows 界面。需要安装QT。
make gconfig - Gtk/X-windows 界面。需要安装GTK。
make oldconfig - 纯文本界面,但是其默认的问题是基于已有的本地配置文件。
make silentoldconfig - 和oldconfig相似,但是不会显示配置文件中已有的问题的回答。
make olddefconfig -和silentoldconfig相似,但有些问题已经以它们的默认值选择。
make defconfig - 这个选项将会创建一份以当前系统架构为基础的默认设置文件。
make ${PLATFORM}defconfig - 创建一份使用arch/$ARCH/configs/${PLATFORM}defconfig中的值的配置文件。
make allyesconfig - 这个选项将会创建一份尽可能多的问题回答都为‘yes’的配置文件。
make allmodconfig - 这个选项将会创建一份将尽可能多的内核部分配置为模块的配置文件。
注意:内核代码可以放进内核自身,也可以成为一个模块。例如,用户可以将蓝牙驱动作为一个模块加入(独立于内核),或者直接放到内核栗,或者完全不加蓝牙驱动。当代码放到内核本身时,内核将会请求更多的内存并且启动会花费更长的时间。然而,内核会执行的更好。如果代码作为模块加入,代码将会一直存在于硬盘上直到被需要时加载。接着模块被加载到内存中。这可以减少内核的内存使用并减少启动的时间。然而,因为内核和模块在内存上相互独立所以会影响内核的性能。另一种选择是不添加一些代码。举例来说,内核开发人员假如知道系统永远都不会使用蓝牙设备,因此这个驱动就可以不加到内核中。这提升了内核的性能。然而,如果用户之后需要蓝牙设备,那么他么需要安装蓝牙模块或者升级内核才行。

make allnoconfig - 这个选项只会生成内核所必要代码的配置文件。它对尽可能多的问题都回答no。这有时会导致内核无法工作在为编译该内核的硬件上。
make randconfig - 这个选项会对内核选项随机选择(译注:这是做什么用途的?!)。
make localmodconfig - 这个选项会根据当前已加载模块列表和系统配置来生成配置文件。
make localyesconfig - 将所有可装载模块(LKM)都编译进内核(译者注:这里与原文 ‘This will set all module options to yes - most (or all) of the kernel will not be in modules’的意思不同,作者也作出了解释:13307)。
 

4."make bzImage -j4"
Error:

scripts/extract-cert.c:21:10: fatal error: openssl/bio.h: No such file or directory
 #include <openssl/bio.h>
          ^~~~~~~~~~~~~~~
compilation terminated.

Solution:sudo apt-get install libssl-dev

5. "make modules". If using diable modules, don't need do this, such as use "make allnoconfig" before.

6.Windows command line input:

"C:\Program Files\qemu\qemu-system-i386.exe" -m 512M -smp 4 -kernel bzImage

Could be launch the kernel, without rootfs.

3. Create disk image

1. Create disk image file.

windows command: (cd in linux source folder first)

"C:\Program Files\qemu\qemu-img.exe" create -f raw disk.raw 512M

linux command:

mkfs -t ext4 ./disk.raw

2.mount disk image file.(cd in linux source folder first)

mkdir img
sudo mount -o loop ./disk.raw ./img

3.install kernel modules.(maybe no module.)

sudo make modules_install INSTALL_MOD_PATH=./img

then could go to ./img/lib/modules/ to see whethe modules were installed successful.

4. Prepare "init" program.

Move rootft system inot the directry "/img/".  There are 3 method as bellow:

a. sysv init.

b. systemd.

c. busybox init. (Now we used)

4. Compile busybox.

Download busybox source from official site.

Method reference: https://www.cnblogs.com/hellogc/p/7482066.html

1. "make help" to see detail.

2. "make defconfig".

Open .config file, ensure "static" and "no share libs", as bellow, can search keyword to find the place.

3."make".

Will gerate "busybox" file, that only a ELF file in the busybox project.

4.install busybox.

NOTE: Should mount img before.

sudo make CONFIG_PREFIX=~/linux-all/linux-4.19/img install

Comment: make CONFIG_PREFIX=<path_to_disk_img_mount_point> install

Run the mashine:

"C:\Program Files\qemu\qemu-system-i386.exe" -m
 512M -smp 4 -kernel arch\x86\boot\bzImage -drive format=raw,file=./disk.raw -ap
pend "init=/linuxrc root=/dev/sda"

To now, can run but will have a error:

So you need setting more.

6. Configure "busybox init".

busybox init accroding to the file "/etc/inittab", if without this file, will using default setting following:

::sysinit:/etc/init.d/rcS
::askfirst:/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
::restart:/sbin/init
tty2::askfirst:/bin/sh
tty3::askfirst:/bin/sh
tty4::askfirst:/bin/sh

reference the project document, we modify the /etc/inittab as bellow:

::sysinit:/etc/init.d/rcS
::askfirst:/bin/ash
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
::restart:/sbin/init

Then create /etc/init.d/rcS as bellow:

#!/bin/sh

NOTE:Sometimes need the input install busybox command

sudo make CONFIG_PREFIX=~/linux-all/linux-4.19/img install

to update etc derectry change.This maybe a bug.

So would see the console is runed successfully.

5. Mount /dev, /proc, /sys.

To now, if we input "df" command, will prombe:

NOTE: Ignore the gdb bug "Remote ‘g’ packet reply is too long".

So we need do more:

sudo mkdir dev
sudo mkdir proc
sudo mkdir sys

modify /etc/init.d/rcS

#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys

NOTE:Sometimes need the input install busybox command

sudo make CONFIG_PREFIX=~/linux-all/linux-4.19/img install

to update etc derectry change.This maybe a bug.

then reboot.

Input "df" to test, will hint:

6 debug

"C:\Program Files\qemu\qemu-system-i386.exe" -m 512M -smp 4 -kernel arch\x86\boot\bzImage -drive format=raw,file=./disk.raw -append "init=/linuxrc root=/dev/sda" -s -S

Open other cmd windows(or on linux mashine), then input:

F:\Linux-0.11-master>gdb vmlinux

(gdb) target remote localhost:1234

 if using linux platform gdb, command as: (gdb) target remote 192.168.220.1:1234

Sometimes, TDMGCC GDB didn't able to debug, because libs maybe different.

(gdb) b start_kernel

(gdb) c

(gdb) n

(gdb) s

Then you would see the linux 0.11 is running successfully.

7 Using vscode to debug

1.press "F5" would general a "launch.json" file:

2.click "Add confiure..." to add "C/C++: (gdb) Bash on Windows Launch" iterm.

at lastet "launch.json" contain is :

{
    // 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": "(gdb) Bash on Windows Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "Z:/home/hui/linux-all/linux-4.19/vmlinux",
            "args": [],
            "stopAtEntry": false,
            "cwd": "Z:/home/hui/linux-all/linux-4.19",
            "environment": [],
            "externalConsole": true,
            "miDebuggerPath": "C:/TDM-GCC-64/gdb64/bin/gdb.exe",
            "miDebuggerServerAddress": "192.168.220.1:1234",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        },

    ]
}

modify iterm is:

            "program": "Z:/home/hui/linux-all/linux-4.19/vmlinux",
            "cwd": "Z:/home/hui/linux-all/linux-4.19",
            "miDebuggerPath": "C:/TDM-GCC-64/gdb64/bin/gdb.exe",
            "miDebuggerServerAddress": "192.168.220.1:1234",

3.make a break point  in  start_kernel() function.

press "F5" will run in start_kernel() function.

Extern Function:

Ignore file setting:

1.New a "settings.json" file.

Click to  add function:

Add function:

{
    "files.exclude": {
        "**/*.o": true,
        "**/*.dwo": true,
        "**/*.cmd": true,
    },
    "search.exclude": {
        "**/*.o": true,
        "**/*.dwo": true,
        "**/*.cmd": true,
    }
}

8 Analyze kerner code

start_kernel() is the first C language function. So everything is analyze from here.

Appendix 1 samba-server create

1 首先确认网络可以相互ping通。

2 终端输入:apt-get install samba

3 先备份 smb.conf 编辑配置,终端输入:

cd /etc/samba/  

ls

cp smb.conf smb.conf-201x-xx-xx

4 nano /etc/samba/smb.conf 编辑配置文件

  1. 找到[homes]browseable = no, 把no 改成 yes, 因为只有这样,windows下才能通 过“计算机”看到“homes”共享目录。----至此,您已经能看到samba共享的目录了。
  2. 当然,以方便调试为目的,所以我们不需要共享homes文件,而是要共享整个根目录。 所以在[homes]这一段下加入一段,不要在[homes]这一段改,否则出错,一定要在下面加,如下:

[all]

comment = /

path = /

read only = no

接着在终端输入:testparm 此命令不但能检查参数是否正确,还能使配置立即生效, 不需要重启。

5 还要创建用户,不然只能看到有共享却无法登录。在终端输入:

smbpasswd -a root 然后就会提示输入密码,其实这个名字可以任意,这里用root是为 了方便记忆,因为我会用最高权限。----到这一步,你就可以登录到samba共享文件里 了。

6 (可以不要这一步)重启samba,终端输入: /etc/init.d/samba restart

Appendix 2 gcc-32bit install

If you system is 64-bit, you should add 32-bit lib support.

sudo apt-get install g++-multilib libc6-dev-i386

then

# gcc boot.o -o boot -m32

Appendix 3 Using eclipse to Debug (but failed)

Failed Reason: The method using in linux 0.11 is OK, but using in linux 4.17 is failed(not almost failed, sometimes ok). Maybe because eclipse used too much CPU, memry and so on Computer resource. If change a more expansevive computer, maybe successfully.

Eclipse Edition:

download link: https://stackoverflow.com/questions/27418096/where-can-i-download-eclipse-android-bundle

NOTE: Sometime need may samba server to Computer.

a."Computer" right mouse click. Then select "Map network derve...", as following:

b.

c.

If didn't display in "Computer", eclipse couldn't open the project.

1.New a C project.

NOTE: If linux 0.11 project store in vmware samba server. Couldn't use "\\192.168.220.129\all\home\hui\eclipse-workspace\Linux-0.11-master" as path. Must using "Browse the floder" to setting the path, as below: (Destiation path is "Z:\home\hui\eclipse-workspace").

2. First launch qemu. Command as bellow:

"C:\Program Files\qemu\qemu-system-i386.exe" -m 512M -smp 4 -kernel arch\x86\boot\bzImage -drive format=raw,file=./disk.raw -append "init=/linuxrc root=/dev/sda" -s -S -append nokaslr

3.Confiure the Eclipse.

NOTE: "Host name or IP address" couldn't fill "localhost", will be error, and hint

Should be fill the VMware Network IPv4 Address as following:

3. Then debug as bellow:

猜你喜欢

转载自blog.csdn.net/zhuohui307317684/article/details/82389998