#### How Linux Kernel Prints Text on Screen https://www.youtube.com/watch?v=aAuw2EVCBBg https://www.bilibili.com/video/BV1ex4y1t7WF https://www.kernel.org/ https://docs.kernel.org/dev-tools/gdb-kernel-debugging.html ubuntu22 https://www.qemu.org/docs/master/system/introduction.html # download latest release www.kernel.org # open windows subsystem for linux, ubuntu22, this time explorer.exe . # copy to linux folder # unzip tar -xf linux-6.11.1.tar.xz # this will download all linux-kernel, do not run: git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git # or, you use codespace: wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.11.1.tar.xz tar -xf linux-6.11.1.tar.xz cd linux-6.11.1 make defconfig sudo apt update sudo apt upgrade sudo apt install flex # sudo apt install bison make defconfig #### output: YACC scripts/kconfig/parser.tab.[ch] HOSTCC scripts/kconfig/lexer.lex.o HOSTCC scripts/kconfig/menu.o HOSTCC scripts/kconfig/parser.tab.o HOSTCC scripts/kconfig/preprocess.o HOSTCC scripts/kconfig/symbol.o HOSTCC scripts/kconfig/util.o HOSTLD scripts/kconfig/conf *** Default configuration is based on 'x86_64_defconfig' # # configuration written to .config # #### done tired... next time update make menuconfig # error: # * Unable to find the ncurses package #### * * Unable to find the ncurses package. * Install ncurses (ncurses-devel or libncurses-dev * depending on your distribution). * * You may also need to install pkg-config to find the * ncurses installed in a non-default location. * #### sudo apt install pkg-config sudo apt install libncurses-dev make menuconfig # down to the lowest Kernel hacking ---> Compile-time checks and compiler options ---> Debug information (Disable debug information) ---> (X) Rely on the toolchain's implicit default DWARF versiLon ---> [*] Provide GDB scripts for kernel debugging make -j 8 # :1:10: fatal error: libelf.h: No such file or directory # search for bing.com: libelf.h: No such file or directory # fatal error: gelf.h: No such file or directory sudo apt install libelf-dev make # certs/extract-cert.c:21:10: fatal error: openssl/bio.h: No such file or directory sudo apt-get install aptitude sudo aptitude install libssl-dev make -j 8 # my cpu fans go crazy, i go away from my computer, what i have done # after a long-not-happy time, output these: #### ... OBJCOPY arch/x86/boot/vmlinux.bin AS arch/x86/boot/header.o LD arch/x86/boot/setup.elf OBJCOPY arch/x86/boot/setup.bin BUILD arch/x86/boot/bzImage Kernel: arch/x86/boot/bzImage is ready (#1) #### man make /-j -j [jobs], --jobs[=jobs] Specifies the number of jobs (commands) to run simultaneously. If there is more than one -j option, the last one is effective. If the -j option is given without an argument, make will not limit the number of jobs that can run simultaneously. When make invokes a sub-make, all instances of make will coordinate to run the specified number of jobs at a time; see the sec‐ tion PARALLEL MAKE AND THE JOBSERVER for details. make #### CALL scripts/checksyscalls.sh DESCEND objtool INSTALL libsubcmd_headers Kernel: arch/x86/boot/bzImage is ready (#1) #### done tired... next time make scripts_gdb cd ~/distro mkdir ~/distro cd ~/distro vim init.c ########### init.c #include int main() { printf("Hello, new world. \n"); } ########### gcc -static init.c -o init ls ./init strace ./init man 2 write echo init | cpio -H newc -o > init.cpio sudo apt install cpio echo init | cpio -H newc -o > init.cpio vim # open a file :e fs/read_write.c # search a file /sys_write # create a new file: .gdbinit # in this directory: /linux-6.11.1 :new .gdbinit ########## edit this: add-auto-load-safe-path /path/to/linux-build ########## into this file: .gdbinit add-auto-load-safe-path /linux-6.11.1 gdb vmlinux # open a new terminal qemu-system-x86_64 # need to install qemu tired... next time... # download qemu # QEMU is packaged by most Linux distributions: # Debian/Ubuntu: # For full system emulation: apt-get install qemu-system # For emulating Linux binaries: apt-get install qemu-user-static sudo apt install qemu-system qemu-system-x86_64 # Unable to init server: Could not connect: Connection refused # gtk initialization failed # maybe, can not run form a codespace server # need to run from local, for example, windows subsystem for linux # this could run: qemu-system-x86_64 -nographic # open a new terminal in vscode of codespace: ctrl+shift+~ cd linux-6.11.1 # change this: # qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio -s -S -append nokaslr # add: -nographic qemu-system-x86_64 -nographic -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio -s -S -append nokaslr # open a new terminal: gdb vmlinux # press enter, enter. until see: (gdb) target remote :1234 break ksys_write c # maybe, can not run form a codespace server # try again in local # MarsCode.com # Exit QEMU: To exit QEMU, you can press Ctrl+A and then X. qemu-system-x86_64 -kernel -m 2G -smp 4 -device virtio-net-pci,netdev=net0 -netdev user,id=net0 # In this example, we're allocating 2GB of memory, using 4 CPU cores, and creating a virtual network device. # ask artificial intelligence,large language model, marscode: # qemu-system-x86_64 -nographic -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio -s -S -append nokaslr # # qemu-system-x86_64: This is the QEMU emulator for the x86_64 architecture. # -nographic: This option tells QEMU not to create a graphical display. Instead, it will use a serial console for output. # -kernel arch/x86_64/boot/bzImage: This option specifies the path to the Linux kernel image (bzImage) that QEMU will load and boot. # -initrd ~/distro/init.cpio: This option tells QEMU to use the specified initial ramdisk (initrd) file. The initrd is a temporary file system that is loaded into memory during the boot process and is used to provide early userspace support. # -s: This option enables the QEMU gdbserver on TCP port 1234. This allows you to debug the kernel using a remote GDB debugger. # -S: This option tells QEMU to start the emulation in a paused state. This is useful if you want to attach a debugger before the emulation starts. # -append nokaslr: This option appends the "nokaslr" parameter to the kernel command line. "kaslr" stands for "kernel address space layout randomization", which is a security feature that randomizes the memory addresses of the kernel. The "nokaslr" parameter disables this feature. # echo init | cpio -H newc -o > init.cpio # # echo init: This part of the command simply prints the word "init" to the standard output. # |: This is a pipe symbol that is used to redirect the output of the echo command to the input of the cpio command. # cpio -H newc -o: This is the cpio command that is used to create a new archive. The -H newc option specifies the format of the archive, and the -o option tells cpio to create an archive from the standard input. # > init.cpio: This redirects the output of the cpio command to a file named init.cpio. ########################### https://kviccn.github.io/posts/%E5%B0%86Qemu%E8%BE%93%E5%87%BA%E8%AE%BE%E7%BD%AE%E5%88%B0%E7%BB%88%E7%AB%AF.html ########################## https://fadeevab.com/how-to-setup-qemu-output-to-console-and-automate-using-shell-script/ wget https://people.debian.org/~aurel32/qemu/i386/debian_wheezy_i386_standard.qcow2 -O wheezy.qcow2 qemu-system-x86_64 -nographic wheezy.qcow2 username:root password:root # try in wsl: qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio -s -S -append nokaslr # output: # Guest has not initialized the display (yet). what? tired... #run this: qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio #output: end Kernel panic - not syncing: Attempted tto kill init! cd linux-6.11 make defconfig make menuconfig ---> (X) Rely on the toolchain's implicit default DWARF versiLon ---> [*] Provide GDB scripts for kernel debugging gdb vmlinux qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio -s -S -append nokaslr i got nothing... try again... make defconfig make menuconfig make mkdir ~/distro vim init.c echo init | cpio -H newc -o > init.cpio gdb ##################### warning: File "/home/codespace/linux-6.11.7/scripts/gdb/vmlinux-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load". To enable execution of this file add add-auto-load-safe-path /home/codespace/linux-6.11.7/scripts/gdb/vmlinux-gdb.py line to your configuration file "/home/codespace/.gdbinit". To completely disable this security protection add set auto-load safe-path / line to your configuration file "/home/codespace/.gdbinit". vim /home/codespace/.gdbinit ########### add this line to ignore auto-load set auto-load safe-path / it is turns out to run gdb... # Guest has not initialized the display (yet). # get this error is ok... gdb vmlinux qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio -s -S -append nokaslr (gdb) target remote :1234 (gdb) break ksys_write (gdb) continue Continuing. Breakpoint 1, ksys_write (fd=1, buf=0x36846b50 "Hello, new world. \n", count=19) at fs/read_write.c:633 633 { (gdb) list (gdb) info break (gdb) enable delete breakpoint-number (gdb) delete breakponit 2 still do not get output on terminal...at least get the breakpoint: # Breakpoint 1, ksys_write (fd=1, buf=0x36846b50 "Hello, new world. \n", count=19) at fs/read_write.c:633 # qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio -s -S -append nokaslr # run this, could see a print: qemu-system-x86_64 -nographic -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio -s -S -append "root=/dev/sda console=ttyS0" # run this, could see a breakpoint: qemu-system-x86_64 -nographic -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio -s -S -append nokaslr gdb vmlinux ############################### get a breakpoint Reading symbols from vmlinux... (gdb) target remote :1234 Remote debugging using :1234 0x000000000000fff0 in exception_stacks () (gdb) info b No breakpoints or watchpoints. (gdb) break ksys_write Breakpoint 1 at 0xffffffff8127f4c0: file fs/read_write.c, line 633. (gdb) c Continuing. Breakpoint 1, ksys_write (fd=1, buf=0x1826ab50 "Hello, new world", '.' , " \n", count=53) at fs/read_write.c:633 633 { (gdb) list 628 { 629 return ksys_read(fd, buf, count); 630 } 631 632 ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count) 633 { 634 struct fd f = fdget_pos(fd); 635 ssize_t ret = -EBADF; 636 637 if (f.file) { (gdb) ############################### get a breakpoint (gdb) advance vfs_write Couldn't get information on specified line. what happend... # repeatly run: qemu-system-x86_64 -nographic -kernel arch/x86_64/boot/bzImage -initrd ~/distro/init.cpio -s -S -append nokaslr gdb vmlinux target remote :1234 break vfs_write continue list ctrl+A, X: stop the qemu quit the gdb # again set breakpoint break new_sync_write tired...