• 调试分析Linux 0.00引导程序


    Bochs虚拟机的配置文件

    简介 Bochs 虚拟机的配置文件

    描述待启动的虚拟机的配置,例如内存大小、启动镜像、网络功能、存储配置。

    Bochs运行后,会先查找配置文件,解析模拟器要虚拟的系统相关信息后启动系统。

    如何设置从软驱启动

    highlighter- routeros
    floppya: 1_44="Image", status=inserted
    boot: a

    如何设置从硬盘启动

    highlighter- routeros
    ata0-master: type=disk, path="30M.sample", cylinders=615, heads=6, spt=17
    boot: disk

    如何设置调试选项

    • log: bochsout.txt:设置日志生成文件。
    • config_interface:配置界面,一系列菜单和对话框。根据平台的不同,有3种配置界面可供选择。
    • display_library:这一行指定了Bochs如何渲染模拟机的显示输出。
    highlighter- vala
    # windows
    config_interface: win32config
    display_library: win32, options="gui_debug"
    
    # Linux
    # display_library: x, options="gui_debug"
    
    # MacOS
    # display_library: sdl2
    • win32 表示它将使用Windows原生的GUI库。options="gui_debug" 表示在GUI中启用调试功能。

    Bochs虚拟机的调试技巧

    如何单步跟踪?

    命令s,或点击Step(s)

    如何设置断点进行调试?

    • vb / vbreak seg:0ffset在虚拟地址上设置指令断点。
    • lb / lbreak addr在线性地址上设置断点。
    • b / break / pb / pbreak addr在物理地址上设置断点。
    • info break显示当前所有断点的信息。
    • d / del / delete n删除断点 n。(断点是从1开始编号的)

    如何查看通用寄存器的值?

    registers / reg / r

    如何查看系统寄存器的值?

    • sreg查看段寄存器
    • info flags查看标志寄存器
    • cr查看控制寄存器

    如何查看内存指定位置的值?

    • x /nuf addr检查位于线性地址addr处的内存内容
    • xp /nuf addr检查位于物理地址addr处的内存内容
    • 参数n:显示内存单元的计数值,默认为1
    • 参数u:单元大小,默认为w
      • b:bytes 1字节
      • h:halfwords 2字节
      • w:words 4字节
      • g:giantwords 8字节
    • 参数f:显示格式,默认为x
      • x:hex 十六进制数
      • d:decimal 十进制数
      • u:unsigned 无符号十进制
      • o:octal 八进制
      • t:binary 二进制数
      • c:char 对应的字符

    如何查看各种表,如 gdtidtldt 等?

    • info gdt
      • info gdt [num] 显示第num
    • info idt
    • info ldt

    如何查看 TSS

    info tss

    如何查看栈中的内容?

    print-stack

    如何在内存指定地方进行反汇编?

    • u/disasm/disassemble start end
    • u /10:反汇编从当前地址开始的10条指令

    计算机引导程序

    如何查看 0x7c00 处被装载了什么?

    查看数据: View -> Linear Dump 输入 0x7c00

    反汇编:u/disasm/disassemble 0x7c00 end

    如何把真正的内核程序从硬盘或软驱装载到自己想要放的地方;

    调用BIOS中断int 0x13功能2从启动盘读取代码。

    如何查看实模式的中断程序?

    实模式的中断向量表处于内存0开始的地方。中断向量表中中断向量保存着中断程序的入口地址。

    如何静态创建 gdtidt

    在程序中定义数据,静态输入对应的gdtidt的值。

    如何从实模式切换到保护模式?

    控制寄存器CR0位0,为标志PE。置位时为保护模式,复位时为实模式。

    利用lmsw指令,Load Machine State Word,将PE置为1,切换到保护模式。

    调试跟踪 jmpi 0,8 ,解释如何寻址?

    此时不是实模式下的段基址与偏移地址的寻址方式了。段值已经是段选择子。

    0为偏移量,8为段选择子,对应GDT中的段描述符2。

    即从GDT中找到段选择子为 8的段描述符,然后从段描述符中,取出基地址(base address),与偏移量合成线性地址。

    该指令执行后,CS:IP即变为0x8:0x0

    实验报告

    请简述 head.s 的工作原理

    • 初始化GDT和IDT,设置GDHR和IDTR。
    • 设置8253定时芯片。
    • 设置定时中断门描述符和系统调用陷阱门描述符,分别在IDT表的第8项和第128项。
    • 利用iret命令,跳转到程序 任务0。

    记录head.s的内存分布状况

    简述head.s 5762行在做什么

    5762行:

    assembly
    <57> pushl $0x17        	# 堆栈段选择符(SS)入栈
    <58> pushl $init_stack		# 堆栈段偏移(SP)入栈
    <59> pushfl					# 标志寄存器入栈
    <60> pushl $0x0f			# 代码段选择符(CS)入栈
    <61> pushl $task0			# 代码段偏移(IP)入栈
    <62> iret

    因为当前head.s 程序是内核程序,特权级别为 0。

    由于处于特权级0的代码不能直接把控制权转移到特权级3的代码中执行,但中断返回操作可以。因此,可以利用中断返回指令 iret来启动任务0。

    具体操作是,在初始堆栈init_stack中人工设置一个返回环境(初始堆栈也是任务0的用户栈):

    • 任务0的 TSS段选择符加载到任务寄存器LTR
    • 任务0的 LDT段选择符加载到LDTR
    • 任务0的用户栈指针(SS:SP),代码指针(CS:IP)以及标志寄存器压入栈中。
    • 执行返回中断指令iret。弹出栈中内容,对应到任务0的堆栈指针、代码指针、标志寄存器。

    简述iret执行后,pc如何找到下一条指令?

    由于在iret前,栈中压入了代码指针,即代码段的段选择符和偏移量(CS:IP),所以iret后,弹出代码指针,pc根据当前代码指针执行下一条指令。

    记录 iret 执行前后,栈是如何变化的?

    执行前:可以看到,栈顶自下的5个内容(双字)分别为 IP、CS、EFLAGS、SP、SS。对应压栈的顺序。

    执行后:可见,弹出5个双字,

    当任务进行系统调用时,即 int 0x80 时,记录栈的变化情况。

    任务0进行系统调用int 0x80前:

    SS:0x17 ESP:0x0bd8

    CS:0x0F EIP:0x10E9

    栈空间为任务0的用户栈,即init_stack

    系统调用后:

    SS:0x10 ESP:0x0e4c

    CS:0x08 EIP:0x166

    栈空间为任务0的内核栈。ESP不为0x0e60,可知栈中压入了内容。

    观察图,发现栈中压入了5个双字,由栈顶自下分别为 调用前的EIP、调用前的CS、调用前的EFLAGS、调用前的ESP、调用前的SS

    可知,在调用中断时,指令int 0x80,会将当前任务的该 5个寄存器内容压入调用后的栈空间中。也就是被调用者保存


    __EOF__

  • 本文作者: 江水为竭
  • 本文链接: https://www.cnblogs.com/Az1r/p/17953235
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    MySQL数据库(一)
    【赠书活动】1024程序员狂欢节充能书单!
    【前端实例代码】如何使用 HTML 和 CSS 快速创建一个响应式导航栏
    力扣202-快乐数——哈希集合
    51单片机仿真软件 Proteus 8 Pro 安装步骤
    Lodash常用方法介绍
    中缀表达式转后缀表达式详解
    EfficientNet代码复现--ICML2019
    【最详细】最新最全Redis面试大全(50道)
    CentOS Nginx crontab 定时执行PHP代码命令任务(tp5.1 tp6 EasyTask) 每天重启执行PHP自定义命令
  • 原文地址:https://www.cnblogs.com/Az1r/p/17953235