Linux操作系统相关调试分析

本文详细介绍了如何在Ubuntu环境下编译配置Linux 5.4.34内核,通过GDB调试跟踪start_kernel函数,解析中断处理流程。内容包括安装开发工具、下载内核源码、配置内核选项、启动内核并使用GDB设置断点,以及中断处理的硬件和软件层面的步骤。

Linux操作系统相关调试分析

参考:

  1. 庖丁解牛linux内核
  2. 孟宁老师与李春杰老师《Linux操作系统分析》课程所使用的PPT

环境:ubuntu、linux-5.4.34

一、Linux的编译配置安装

安装开发工具
  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
下载内核源码
  1. sudo apt install axel
  2. axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz
  3. xz -d linux-5.4.34.tar.xz
  4. tar -xvf linux-5.4.34.tar # 解压
  5. cd linux-5.4.34 # 进入内核源码文件夹
配置内核选项

在这里插入图片描述

编译和运行内核

在这里插入图片描述
在这里插入图片描述
后续制作好根文件系统后,就可以开始使用GDB调试跟踪。

二、start_kernel()跟踪

运行操作系统内核,并使用GDB调试跟踪启动过程
  1. 启动内核:qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s
    在这里插入图片描述
  2. 打开令一个终端,输入如下命令,以令GDB连接上内核
    - cd linux-5.4.34/
    - gdb vmlinux
    - (gdb)target remote:1234
    - (gdb)b strat_kernel
    第四条命令是再strat_kernel函数上打上了断点。gdb常用命令如下:
    - c 继续执行
    - b [functionName] 在某函数位置打上断点
    - list 现实当前运行位置代码
    - next 单步跳过
    - step 单步进入
    - bt 显示函数调用堆栈
  3. 跟踪start_kernel函数
    - strat_kernel()
    在这里插入图片描述
    - set_task_stack_end_magic()
    在这里插入图片描述
    - end_of_stack() 执行过后返回set_task_stack_end_magic(),让后再返回到start_kernel()
    在这里插入图片描述
    - arch_local_irq_disable()
    在这里插入图片描述
    - 随后是系统对中断相关的处理
    在这里插入图片描述
总结:

从对start_kernel()的跟踪中可以看出,start_kernel使用set_task_stack_end_magic()函数创建了0号进程init_task,随后对进行中断相关的处理。
start_kernel进程创建部分的流程:
在这里插入图片描述

三、中断过程简述

总流程
  1. 硬件级别保存现场并转入中断处理程序。
  2. 软件级保存现场。
  3. 中断处理。
  4. 软件级现场恢复。
  5. iret,硬件级现场恢复。
硬件

在这里插入图片描述

中断描述符表(IDT):记录相应中断处理程序的CS、eip和权限等信息。
GDT表:全局描述符表,记录系统分段信息。CS指向其中一项。
idtr:存储中断描述符表的基地址。
gdtr:存储GDT表的基地址。

  1. 确定与中断或者异常关联的向量i。
  2. 读idtr寄存器指向的IDT表中的第i项。
  3. 从gdtr中获得GDT表的基地址,使用IDT表中获得的CS找到相应GDT表的相应表项。
  4. 确定中断是由授权的发生源发出的。
    - 中断:中断处理程序的特权不能低于引起中断的程序的特权(对应GDT表中的DPL和CS寄存器中的CPL)。
    - 编程异常:还需比较CPL与对应IDT表项中的DPL。
  5. 检查是否发生特权级的变化,一般指是否由用户态陷入内核态。如果是,控制单元必须开始使用与新特权级别相关的堆栈。
    - 读tr寄存器(记录了进程tss段的基地址),访问运行进程的tss段(记录了进程的内核栈信息)。
    - 用与新特权级相关的栈段和栈指针装载ss和esp寄存器。这些值存在于tss段中。
    - 在新特权级栈中保存先前的ss和esp值,这些信息指明了旧特权级相关栈的逻辑地址。
软件

保存现场,即保存除去硬件已经保存的寄存器内容。按照内核要求顺序,依次push寄存器内容到内核栈。

退出中断
1 软件级别恢复现场
2 硬件级恢复现场
  1. 执行iret汇编指令:
    - 用保存在栈中的值装载CS,eip和eflags寄存器。
    - 检查处理程序的特权级是否等于CS中最低两位的值。若是,iret终止执行;否则,转入3。
    - 从栈中装载CS、eip寄存器。这一步完成后,意味着返回到了用户态堆栈。
    - 检查ds、es、fs和gs段寄存器的内容,如果其中一个寄存器包含的选择符是一个段描述符,并且特权级比当前特权级高,则清除相应的寄存器。从而防止恶意用户程序利用寄存器访问内核空间。

尾注:

学号后三位:453

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值