最近在写一个玩具操作系统,在编写过程中,经常需要进行代码调试。平常我们在Windows或者Linux下编写应用程序时,可以使用像VS,GDB等等这些调试工具进行调试,但是现在要调试的不是应用程序,而是操作系统本身。那要怎么调试操作系统的代码呢?笔者就以自己编写玩具操作系统时的经历,介绍一下如何调试操作系统的代码。

在开发操作系统的过程中,一般是先在模拟器或者虚拟机中运行调试,没什么大问题了,再在实体机上运行。常见的模拟器如Bochs、Qemu等,常见的虚拟机如VMWare、VirtualBox、Virtual PC等。

本文就以Windows下的Bochs介绍一下如何使用Bochs模拟器来调试操作系统代码,文中有使用MinGW环境下的命令。

一、Bochs内置调试器

Bochs本身内置的调试器,是汇编级的调试器,对于调试像boot或者loader这样的16位汇编代码时,还是非常有用的,Bochs的调试命令还是非常丰富的,而且与GDB的调试命令也比较相似。下面列一些常用的调试命令:

命令 功能 示例 示例说明
b 打断点 b 0x7c00 在0x7c00处设置断点
c 继续执行 c 继续执行
n 单步执行,不会进入函数调用 n 执行一条语句,如果遇到CALL指令,不会进入函数
s 单步执行,并且会进入函数调用 s 执行一条语句,如果遇到CALL指令,则进入函数
x 显示指定线性地址开始的内存信息 x /32bc 0x7c00 以字符的形式显示线性地址0x7c00开始的32个字节
xp 显示指定物理地址开始的内存信息 x /32bc 0x7c00 以字符的形式显示物理地址0x7c00开始的32个字节
r 显示各通用寄存器的值 r 显示各通用寄存器的值
sreg 显示各段寄存器的值 sreg 显示各段寄存器的值
blist 显示所有断点信息 blist 显示所有断点信息
del 删除断点 del 1 删除1号断点,几号断点是由blist列出
help 显示帮助 help help没有参数则显示命令概览,如果想要查看具体命令的帮助信息,则后面跟上命令即可,比如help info则是查看info命令的帮助信息
q 退出 q 退出调试控制台
ldsym 装载调试符号 ldsym global “loader.sym” 从装载loader.sym文件中装载调试符号,并且作为全局符号

更多的调试命令可以通过help查看。

1.直接运行

在Windows下编写好bxrc文件,则可以在直接双击运行。下图是笔者写的Loader执行完成,准备进入内核的输出画面:

2.调试

在bxrc文件右键弹出菜单中有一个debugger命令,执行它即可进入下面的开始对话框界面,默认是使用的bxrc文件中的配置,如果想要临时修改配置,也可以双击“Edit Options”列表框中的分类进行编辑,完成后执行“start”即开始调试。

此时会暂停在f000:fff0处,如下图所示:

这里就是Bochs的内置调试控制台了,可以在此输入各种调试命令。

下图是笔者调试刚进入Loader的情况:

可以看到,全部是汇编代码,没有任何符号信息,调试起来是相当的费劲,如果不对照源码,根本就难以定位源码。笔者在刚开始写Loader时就是在没有任何调试信息的情况下来调试Loader的,非常费时费力。后面随着代码越来越多(笔者是使用大量的C语言来写Loader的),这种调试方式更是费时费力,其实Bochs是可以加载调试符号的,虽然相对GDB的调试信息,比较简陋,但是还是要方便很多。

Bochs的符号文件格式为“%x %s”,即前面是地址,后面是符号,比如:

00003182 memcpy

表示地址0x00003182为memcpy的入口地址。

使用如下的命令生成调试符号文件:

nm loader.elf | grep -i ' T ' | awk '{ print $1" "$3 }' > loader.sym

可以在CMakeLists.txt中使用:

nm ${CMAKE_BINARY_DIR}/loader/loader.elf | grep -i ' T ' | awk '{ print $$1" "$$3 }' > ${CMAKE_CURRENT_SOURCE_DIR}/loader.sym

生成符号后,就可以使用ldsym来装载调试符号了,如下所示:

可以从图中看到已经有符号信息显示了,调试起来就方便多了。

如果每次调试时都手动输入ldsym来装载调试信息还是比较繁琐,可以直接配置在bxrc文件中,添加下面一行配置即可:

debug_symbols: file="loader.sym", offset=0x8000

本文链接地址:https://blog.csdn.net/witton/article/details/126414601?spm=1001.2014.3001.5501

二、Bochs+GDB调试

由于Bochs内置的调试器是汇编级的,在操作系统进入内核后,将会有大量的C代码,如果还是使用汇编级的调试还是相当麻烦的,这就需要有源码级的调试了,GDB将成为首选源码级调试器。如果还是Bochs模拟器的话,可以使用GDB连接到Bochs来进行源码级调试。

Windows下的Bochs默认安装文件是不支持GDB调试的,需要自己重新编译Bochs源码,编译时需要添加参数--enable-gdb-stub,下面是笔者在MinGW下编译Bochs的参数:

../bochs-2.7/configure --enable-all-optimizations --enable-long-phy-address --enable-alignment-check --enable-pci --enable-cdrom --enable-gameport --enable-large-ramfile --enable-show-ips --with-all-libs --enable-usb --enable-usb-ohci --enable-usb-ehci --enable-usb-xhci --enable-logging --enable-fpu --enable-3dnow --enable-busmouse --enable-iodebug --enable-sb16 --enable-ne2000 --enable-clgd54xx --enable-voodoo --enable-es1370 --enable-e1000 --with-rfb --enable-x86-debugger --enable-debugger-gui --enable-gdb-stub --with-win32

然后在bxrc文件中,添加下面一行配置:

gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0

输入命令(注意一定要使用自己编译的Bochs,不能像前面那样在右键菜单中使用Debugger了):

./bochs -f bochsrc.bxrc -q

即可看到Bochs控制台中输出:

Waiting for gdb connection on port 1234

这是在等待GDB的连接,这里的连接端口为1234

在MinGW控制台输入如下命令启动交叉编译的GDB:

x86_64-elf-gdb -ex "file build/kernel/kernel" -ex "target remote :1234" -ex "b kmain"
  • -ex “file build/kernel/kernel”
    让GDB自动装载build/kernel/kernel文件中的调试信息

  • -ex “target remote :1234”
    远程连接本机的1234端口

  • -ex “b kmain”
    在kmain函数入口设置断点

这样就可以开启GDB的源码级调试了,如下图所示:

使用命令行方式手动输入GDB命令来调试还是麻烦了点,可以直接使用Visual Studio来可视化调试,目前新版本的Visual Studio已经支持使用GDB来调试GCC生成的C/C++程序了,可以参见笔者前面的博文:Visual Studio 2022使用MinGW来编译调试C/C++程序

下图为笔者使用VS 2022调试Kernel的情况,可以看到借助VS IDE的强大功能,调试起来是非常方便,与调试VC的普通应用程序体验高度一致:

由于Bochs是完全使用软件的方式来模拟,使用它调试运行内核,是相当慢的,后面笔者将介绍使用Qemu来运行调试操作系统,Qemu的运行效率比Bochs快很多,参见后文:使用QEMU+GDB调试操作系统代码

希望此文能帮助到喜欢研究、编写操作系统的读者,更希望有朝一日看到国人能够写出完全自主的操作系统并流行起来!哈哈!

使用Bochs调试操作系统代码相关推荐

  1. 使用 Bochs 调试操作系统

    编译安装 Bochs 下载 bochs 源码 http://sourceforge.net/projects/bochs/files/bochs/2.6.8/ 解压之后进入该目录,进行配置 sudo ...

  2. 用bochs调试自己写的系统引导代码

    1 安装和配置bochs 首先从bochs.sourceforge.net里面把BOCHS给download下来,鉴于Windows的普及,仅仅谈BOCHS在win下的使用方法,其实在其它的OS中方法 ...

  3. 使用Bochs调试Linux内核初级入门

    之所以能用Bochs调试Linux内核,还是因为Bochs做了一些工作: 安装完成以后如下:如果使用bochs.exe加载操作系统映像,就是在虚拟机中运行操作系统: 如果使用bochsdbg.exe加 ...

  4. IDT系列:(二)中断处理过程,使用bochs调试IDT中的中断服务程序

    一.中断处理的过程 根据Intel 64 and IA-32 Architectures Software Developer's Manual 的介绍,在中断或异常产生是,CPU会将当前执行的指令( ...

  5. Bochs调试Linux内核

    总结:cmd进入Bochs安装路径后运行如下命令bochsdbg  -q -f bochsrc.bxrc 调试的命令主要包括: vbreak  地址 打断点,配合c执行到该地址 info r      ...

  6. 一份简单的在 Linux下编译及调试 C 代码的指南

    摘要: 一份简单的在 Linux下编译及调试 C 代码的指南 对于Linux下的C程序员来说,几乎天天都会和Linux打交道.但在很多人的眼中,Linux是一个易用性极差.靠命令驱动的操作系统,根本无 ...

  7. bochs调试方法与指令详解

    bochs调试FAQ: 一 基本调试命令 1.       Q:如何从引导扇区开始设置断点? A: BIOS被载入内存中运行,其引导扇区的地址一般都是在0x7c00,因为在实模式下,逻辑地址和物理地址 ...

  8. Bochs调试Linux内核6 - 启动过程调试 - 跳到bootsect引导程序执行

    接此,​​​​​​Bochs调试Linux内核5 - 启动过程调试 - 认识Bootsect.S_bcbobo21cn的专栏-CSDN博客 看一下,0x00007c11 这里是重复执行串传送:而后一条 ...

  9. Bochs调试Linux内核5 - 启动过程调试 - 认识Bootsect.S

    先参阅 Bochs调试Linux内核 - 定位内核中的变量或数据结构_bcbobo21cn的专栏-CSDN博客​​​​​​ ,运行到<bochs:1>,输入vbreak 0x0000:0x ...

最新文章

  1. 尚硅谷学Javaweb,关于正则表达式笔记
  2. Jquery-zTree的基本用法
  3. Confluence 6 找到在创建 XML 备份的时候出现的错误
  4. 微信公众帐号开发教程第14篇-自定义菜单的创建及菜单事件响应
  5. magento 输出关联产品
  6. python连接数据库设置编码_python操作mysql中文显示乱码的解决方法
  7. 为什么 Rust 连续 4 年获「最受喜爱编程语言」?
  8. 浏览器的资源并发亲试
  9. jsp下Kindeditor环境搭建
  10. 操作系统学习(十三) 、中断和异常
  11. php下载地址转换工具,php把url转换迅雷thunder资源下载地址的简单示例
  12. 计算机水印如何操作,图片的水印如何添加|怎么用word给图片添加水印
  13. 移动硬盘计算机管理无法显示,为什么移动硬盘插在电脑上不显示_移动硬盘为什么在电脑上面显示不出来-系统城...
  14. 形容词记忆(六):ive, ile, ary后缀常用词
  15. linux 复制 u盘 只读,Linux_ubuntu系统下向U盘拷贝数据提示目标是只读的,在ubuntu11.04下使用U盘的时候, - phpStudy...
  16. 用GATK进行二代测序数据 SNP Calling 流程:(二)bwa比对和HaplotypeCaller 变异检测
  17. rpm常用命令汇总 -- 安装,升级,查询,验证,卸载
  18. java 空白图片_图片文件打印空白的解决办法
  19. 服务器乌班图不显示鼠标,鼠标指针不显示怎么回事
  20. Esp8266进阶之路11 企业者的福音之8266接入阿里智能,点亮一盏LED灯,期待天猫精灵语音控制的不约而至!

热门文章

  1. 笔试题strcpy写法
  2. 关于爱情,关于出轨这件事
  3. Photoshop(5)不一样的抠图与字体
  4. 人机交互设计——评价谷歌拼音输入法(安卓版)
  5. c 语言中 %d,%lu等区别
  6. mysql 1118错误_Mysql 出现Error 1118的一种解决方法 | 学步园
  7. Webview清空历史纪录的正确姿势
  8. 离散数学 —— 谓词逻辑(自由变量、量词的约束范围、谓词公式的等价式与蕴涵式、前束范式、US、UG、ES、EG)
  9. 【js数据结构】栈解决佩兹糖果盒问题
  10. 用Asprise的OCR包,处理验证码