标签:kernel 调用 Linux 34 init 深入 linux 64
一、实验环境配置
系统环境:Ubuntu16.04
实验说明:本人学号末两位70,对应__64x_sys_msgrcv系统调用
注:不能在上次实验的基础上做,要重新下载解压linux-5.4.34文件
1、安装开发工具
1 sudo apt install build-essential 2 sudo apt install qemu # install QEMU 3 sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev
2、下载内核源码
1 sudo apt install axel 2 axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/ 3 linux-5.4.34.tar.xz 4 xz -d linux-5.4.34.tar.xz 5 tar -xvf linux-5.4.34.tar 6 cd linux-5.4.34
3、配置内核选项
make defconfig # Default configuration is based on 'x86_64_defconfig' make menuconfig # 打开debug相关选项 Kernel hacking ---> Compile-time checks and compiler options ---> [*] Compile the kernel with debug info [*] Provide GDB scripts for kernel debugging [*] Kernel debugging # 关闭KASLR,否则会导致打断点失败 Processor type and features ----> [] Randomize the address of the kernel image (KASLR)
4、编译和运行内核
1 make -j$(nproc) # nproc gives the number of CPU cores/threads 2 available 3 # 测试⼀下内核能不能正常加载运⾏,因为没有⽂件系统最终会kernel panic 4 qemu-system-x86_64 -kernel arch/x86/boot/bzImage
5、制作根文件系统
1 ⾸先从https://www.busybox.net下载 busybox源代码解压,解压完成后,跟内核⼀样先配置编译,并安装。 2 axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2 3 tar -jxvf busybox-1.31.1.tar.bz2 4 cd busybox-1.31.1
1 make menuconfig 2 记得要编译成静态链接,不⽤动态链接库。 3 Settings ---> 4 [*] Build static binary (no shared libs) 5 然后编译安装,默认会安装到源码⽬录下的 _install ⽬录中。 6 make -j$(nproc) && make install
1 然后制作内存根⽂件系统镜像,⼤致过程如下: 2 mkdir rootfs 3 cd rootfs 4 cp ../busybox-1.31.1/_install/* ./ -rf 5 mkdir dev proc sys home 6 sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/
1 准备init脚本⽂件放在根⽂件系统跟⽬录下(rootfs/init),添加如下内容到init⽂件。 2 #!/bin/sh 3 mount -t proc none /proc 4 mount -t sysfs none /sys 5 echo "Wellcome MengningOS!" 6 echo "--------------------" 7 cd home 8 /bin/sh 9 给init脚本添加可执⾏权限 10 chmod +x init
1 打包成内存根⽂件系统镜像(rootfs目录下) 2 find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz 3 测试挂载根⽂件系统,看内核启动完成后是否执⾏init脚本 4 qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz
可以看到init脚本已被执行
二、使用gdb跟踪调试
1、gdb问题处理
在用gdb打断点的时候,出现Remote ‘g’ packet reply is too long错误,查询得到参考解决办法https://blog.csdn.net/superking3188/article/details/8477574。
改完代码后进行重新编译和安装
./configure make make install
2、验证内核初始化
启动虚拟机 qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s
在linux-5.4.34目录下启动gdb
gdb vmlinux
target remote:1234
在start_kernel、trap_init、cou_init、syscall_init位置打上断点
依次执行,可以清晰的看出系统内核初始化的顺序为start_kernel->trap_init->cou_init->syscall_init
3、跟踪70号系统调用
在linux-5.4.34/arch/x86/entry/syscalls/syscall_64.tbl文件中可以查看70对应的系统调用为__64x_sys_msgrcv
为了观察该系统调用,在rootfs/home目录下写一个程序来触发系统调用
int main() { asm volatile( "movl $0x46,%eax\n\t" //使⽤EAX传递系统调⽤号70 "syscall\n\t" //触发系统调⽤ ); return 0; }
对该程序进行静态编译
gcc testSys.c -o testSys -static
重新打包内存跟文件系统镜像
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
启动虚拟机
qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s
在linux-5.4.34目录下启动gdb调试
gdb vmlinux target remote:1234 b __64x_sys_msgrcv
c
此时可以看到home目录下已经存在我们刚刚生成的可执行文件,执行该文件即可触发70号系统调用
获取到了70号系统调用的返回信息
使用bt命令查看栈信息
可以看到该系统调用涉及到do_syscall_64和entry_SYSCALL_64两个内核函数。
三、系统调用的保存和恢复现场
系统调用入口为entry_SYSCALL_64,其中使用了swapgs这一方法来快照式的保存现场,加快了系统调用,随后对一些相关寄存器进行压栈操作。
随后执行了do_syscall_64函数
在do_syscall_64函数中,获取到系统调用号所对应的入口,跳转执行。
随后便执行相关的系统调用
调用结束后恢复现场
四、总结
本次实验中,学习了gdb工具,使用gdb断点调试完成了内核初始化顺序的验证;查看了70号系统调用的调用过程,详细了解了系统调用的保存和恢复现场。
标签:kernel,调用,Linux,34,init,深入,linux,64 来源: https://www.cnblogs.com/awesomeluxu/p/12965167.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。