0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

分析主流硬件平台和操作系统的软件程序Debug原理

QuTG_CloudBrain 来源:移动Labs 2022-12-28 09:12 次阅读

Labs 导读

Debug调试覆盖了整个计算机领域,包括不限于数字电路模拟仿真嵌入式硬件以及应用软件,是技术研发人员必须熟练掌握的重要技能,对于产品研发过程的代码纠错和产品质量把控有重要影响,本文主要探讨分析主流硬件平台和操作系统的软件程序Debug原理。

1

Bug和Debug

说起“Debug”,就不得不提及“Bug”这个程序猿和游戏玩家耳熟能详的词,它由美国格蕾丝·赫柏博士第一次提出,当时运行研究数据的Harvard Mark II计算机突然不能正常工作,经赫柏和团队的反复排查,发现是一只飞蛾飞入了电脑的内部继电器中造成短路而引起的故障。

修复故障后,赫柏在日记中诙谐地记录下了这件事(图1), “Bug”一词(原意为“虫子”)也逐渐被广泛用于形容计算机程序中隐藏的错误,同时,受到从电脑中驱除飞蛾虫子的启发,计算机术语“Debug”(调试排错)开始使用。

87061be2-8609-11ed-bfe3-dac502259ad0.png

图1

Debug调试覆盖了整个计算机领域,包括不限于数字电路、模拟仿真、嵌入式软硬件以及应用软件,是技术研发人员必须熟练掌握的重要技能,对于产品研发过程的代码纠错和产品质量把控有重要影响,本文主要探讨分析主流硬件平台和操作系统的软件程序Debug原理。

2

调试原理-断点

对于如C、C++等编译运行的可执行程序,其Debug断点调试需要硬件和操作系统的支持,主要依赖以下两点:

(1) 硬件平台和操作系统提供设置断点的方法。

(2) 断点触发系统中断通知到调试器的功能。

对于第一点断点的实现,从计算机体系角度看分为软件断点和硬件断点。软件断点是指向指定的代码位置插入专用的断点指令实现(插桩)。而硬件断点则是通过直接利用CPU核心的调试寄存器实现,此场景主要针对不允许写入操作的ROM只读内存和软件断点无法处理的情况,如中断向量表被破坏等。

87250f3e-8609-11ed-bfe3-dac502259ad0.png

图2

不同的硬件架构对应断点实现指令也不相同,如果我们的硬件处理器基于X86系列,其软件断点工作原理是调试器将代码对应位置的原指令的首个字节保存起来,然后写入一条INT3指令(图2)。因为INT3指令的二进制码为11001100b(0xCC),仅有一个字节,所以设置和取消断点时也只需要保存和恢复一个字节。

当CPU执行到INT3指令时,将会触操作系统软中断并停止运行当前进程,转而执行内核定义好的中断处理函数。X86的硬件断点使用DR0-DR7调试地址寄存器,但是由于存储断点地址的寄存器数量有限(DR0-DR3),只能设置4个断点。基于ARM系列的断点实现与X86平台类似, 软件断点的工作原理是用HLT或BRK指令的操作码进行指令替换,硬件断点使用内置在core中的比较器,并在执行到达指定地址时停止执行并触发相应中断,和X86一样,由于只提供有限数量的硬件断点单元也存在断点设置数量限制。

对于第二点操作系统的中断通知,以X86平台为例,Windows平台由操作系统软中断触发的对应函数为KiTrap03(),Linux平台则是do_int3()函数,这些函数均为操作系统内核预先定义好的中断处理例程。KiTrap03()会将断点异常通过调试子系统以调试事件的形式分发给用户模式的调试器,并等待调试器的回复,只有调试器确认该异常为“自己”设置的断点后,才会允许挂起被调试进程进行交互性调试。do_int3()例程则是向被调试进程发送一个SIGTRAP信号,当进程接收到SIGTRAP信号后,当前进程让出CPU暂停运行。

3

调试原理-进程交互模型

调试器和被调试进程的如果都位于同一台物理机,即为跨进程调试,反之为远程调试,远程调试是在跨进程调试的基础上增加了一层网络协议交互。由于Windows和Linux的进程描述模型存在一定差异,我们分别介绍这两种平台的调试器进程交互原理。

3.1 Windows

WIN32内核提供了一组系统Api用于支持调试器与被调试进程交互,这里挑几个重要函数进行介绍。

874101b2-8609-11ed-bfe3-dac502259ad0.png

图3

基于WIN32的调试器交互就是通过上述所示的调试函数和一系列调试事件[1]相结合实现。调试器启动后首先通过CreateProcess函数创建待调试进程,或者通过调用DebugActiveProcess函数捆绑到正在运行的进程,在一系列准备操作后就会进入调试循环阶段,调试器会阻塞调用WaitForDebugEvent函数来等待调试事件通知,当有诸如异常事件或dll文件装卸载事件通知到来时,此函数立即返回,返回的事件信息被封装在DEBUG_EVENT结构中,这个结构包含事件的类型、相关进程描述信息和文件句柄等。

此时调试器就进入了命令交互阶段,调试器将在自定义的事件处理函数ProcessEvent匹配事件并执行对应事件的回调代码,如果是断点触发这类型操作,被调试目标进程的所有线程都会被操作系统挂起,此时调试器可以调用相关函数如GetThreadContext来获取指定线程的上下文信息。调试器和目标进程地调试信息交互基于Windows进程间同步机制,相关信息可参阅微软相关开发文档[2]。

874dedfa-8609-11ed-bfe3-dac502259ad0.png

图4

3.2 Linux

相比Windows,Linux作为开源系统可以透过源码更深入地窥探调试器原理,这里以GDB调试为例。

当我们从shell终端对某个已编译C程序文件进行GDB命令调试时,系统首先会创建GDB进程(调试器进程),该进程会fork出一个子进程(调试目标进程),子进程初始化后首先调用关键系统函数ptrace(PTRACE_TRACEME…),使自身进入被追踪模式;同时调用execv函数执行待调试的C程序文件,此时会暂停当前进程的运行,并且发送一个SIGCHLD信号给父进程,父进程接收到SIGCHLD信号后就可以对被调试的进程进行调试。GDB也支持对已存在的进程进行调试,此时将由GDB进程调用ptrace(PTRACE_ATTACH, pid, ...)对被调试进程进入被追踪模式。

8754db1a-8609-11ed-bfe3-dac502259ad0.png

图5

ptrace系统函数[3]是GDB交互调试的核心依赖函数,该函数的第一个参数request确定要执行的操作模式,这些操作模式定义了调试器控制读写被调试进程的行为,具体支持的操作模式如下:

8772be64-8609-11ed-bfe3-dac502259ad0.png

图6

借助ptrace函数的强大功能,GDB调试器进程可以对调试目标进程的指令空间、数据空间、堆栈和寄存器的值进行读写,如堆栈打印、变量展示修改等。GDB同时会截获内核通知到被调试进程的几乎所有信号,通过对这些信号的拦截和判定,调试器进程就可以对程序进行断点匹配和单步调试等操作[4]。

4

调试器的未来发展

Windows平台的Windbg、Linux的GDB调试器都是功能全面、具有复杂逻辑实现的软件工具,这些debugger调试器因为根植于不同硬件平台和操作系统,存在着底层功能实现和交互模型的显著差异,很明显不适合跨平台发展,而随着Java、Js、python等解释型语言的兴起和云平台的发展,虚拟机调试体系(JDPA、v8 debug protocol)被提出和广泛应用,这种百花齐放的局面让IDE厂家面临着一个非常棘手的问题——调试器交互规范不统一带来的巨大开发难度,微软针对此问题率先提出了DAP(Debug Adapter Protocol)协议,让各厂家IDE(主要是还是服务自家的VsCode)通过相同的协议基于适配器模式与不同语言的debugger通信,力图屏蔽软硬件底层的差异性,降低IDE调试器的开发难度。DAP协议凭借着专业性和普适性得到了业界的一定认可,不过Eclipse和IDEA等JAVA编辑器仍然是直接适配JDPA调试体系的,毕竟软件行业统一规范的背后仍然是各家科技公司行业话语权的争夺。





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 继电器
    +关注

    关注

    132

    文章

    5319

    浏览量

    148522
  • ROM
    ROM
    +关注

    关注

    4

    文章

    562

    浏览量

    85660
  • 比较器
    +关注

    关注

    14

    文章

    1633

    浏览量

    107086
  • 调试器
    +关注

    关注

    1

    文章

    300

    浏览量

    23683

原文标题:应用程序调试原理浅析

文章出处:【微信号:CloudBrain-TT,微信公众号:云脑智库】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    什么是操作系统

    什么是操作系统  操作系统是一个大型的软件系统,其功能复杂,体系庞大。从不同的角度看的结果也不同,正是“横看成岭侧成峰”,下面我们通过最典型的两个角度来
    发表于 09-13 10:10

    嵌入式操作系统的通用硬件抽象层设计

    的计算机系统。它自底向上包括3个主要部分:硬件环境、嵌入式操作系统和嵌入式应用程序硬件环境是整个嵌入式
    发表于 12-07 10:30

    主流嵌入式操作系统有哪些?

    ,是由操作系统Linux、中间件以及核心应用程序组成的软件栈。通过android SDK提供的API以及相应的开发工具,程序员可以很方便的开发android
    发表于 07-10 19:02

    Linux操作系统怎么移植到ARM平台

    目前,在嵌入式系统里基于ARM微核的嵌入式处理器以其功耗低,功能强大的优点已经成为市场的主流。与此同时,在网络上发展起来的Linux操作系统,以其功能强大,开放源代码,支持硬件种类众多
    发表于 08-19 06:39

    怎么设计开源嵌入式操作系统学习平台

    近年来,随着嵌入式系统的飞速发展和广泛应用,裸机模式已无法适应日益复杂的系统开发,嵌入式操作系统已经成为开发中不可或缺的核心软件,对其进行学习研究的需求也日益突出。 嵌入式
    发表于 08-28 07:22

    主流物联网操作系统的比较

    、实时性和安全的传感、连接、云端管理服务软件平台。目前物联网操作系统大致可以分为两类:一类是为物联网而生的 OS,即针对物联网而做的 OS ,之前并没有,代表产品有 ARM 公司的 Mbed OS、庆科
    发表于 09-17 09:05

    ARM操作系统应用程序

    ZYNQ将CPU和FPGA集成到了一起 开发人员需要具备技能: 1.ARM操作系统应用程序 2.设备驱动程序 3.FPGA硬件逻辑设计 需要了解Linux
    发表于 07-22 08:55

    如何使嵌入式操作系统在不同的硬件平台上有效地运行

    嵌入式系统硬件环境、嵌入式操作系统和应用程序组成,硬件环境是操作系统和应用
    发表于 11-05 08:06

    为什么要用操作系统

    何谓操作系统1.什么是操作系统操作系统是管理和控制计算机硬件软件资源的计算机程序,是直接运行
    发表于 12-14 07:56

    什么是计算机操作系统

    什么是计算机操作系统操作系统是一种为应用程序提供服务的系统软件,是一个完整的计算机系统的有机组成部分。从层次上来看,
    发表于 12-14 06:50

    硬件看门狗在操作系统下是怎么用的?

    关于软件看门狗:在裸机程序软件看门狗,大家都会在必要的地方喂狗保证看门狗有效;但在微操作系统下,程序的流向都是在
    发表于 09-07 16:49

    基于eCos操作系统的FLASH驱动程序分析与移植

    基于eCos操作系统的FLASH驱动程序分析与移植 0 引 言   嵌入式系统需要支持的外部设备种类繁多,如何构造运行良好的嵌入式设备的驱动
    发表于 12-28 10:50 1265次阅读
    基于eCos<b class='flag-5'>操作系统</b>的FLASH驱动<b class='flag-5'>程序</b><b class='flag-5'>分析</b>与移植

    Windows应用程序操作系统,计算机硬件之间的相互关系

    前面说过操作系统能很好的去操作底层硬件,但是不知道什么时候去操作操作到了什么程度,这些都是由应用程序
    的头像 发表于 06-29 08:49 1.2w次阅读

    汽车操作系统的教程信息及看法

    vehicles. 操作系统 (OS) 是管理基于计算机的系统的所有硬件软件所必需的,它是汽车行业的关键软件
    的头像 发表于 07-14 08:17 955次阅读
    汽车<b class='flag-5'>操作系统</b>的教程信息及看法

    深度解析全球操作系统格局

    操作系统是负责协调、管理和控制计算机硬件软件资源的程序,是整个计算机的核心系统软件。 按照操作系统
    的头像 发表于 01-18 15:00 1047次阅读
    深度解析全球<b class='flag-5'>操作系统</b>格局