Redian新闻
>
调试器是个“大骗子”!

调试器是个“大骗子”!

公众号新闻

我叫GDB,是一个调试器,程序员通过我可以调试他们编写的软件,分析其中的bug。

作为一个调试器,调试分析是我的看家本领,像是给目标进程设置断点,或者让它单步执行,又或是查看进程中的变量、内存数据、CPU的寄存等等操作,我都手到擒来。

你只要输入对应的命令,我就能帮助你调试你的程序。

我之所以有这些本事,都得归功于一个强大的系统函数,它的名字叫ptrace

long ptrace(
 enum __ptrace_request request,
 pid_t pid,
 void *addr,
 void *data
 )
;

不管是开始调试进程,还是下断点、读写进程数据、读写寄存器,我都是通过这个函数来进行,要是没了它,我可就废了。

它的第一个参数是一个枚举型的变量,表示要执行的操作,我支持的调试命令很多都是靠它来实现的:

你可以通过我来启动一个新的进程调试,我会使用fork创建出一个新的子进程,然后在子进程中通过execv来执行你指定的程序。

不过在执行你的程序之前,我会在子进程中调用ptrace函数,然后指定第一个参数为PTRACE_TRACEME,这样一来,我就能监控子进程中发生的事情了,也才能对你指定的程序进行调试。

你也可以让我attach到一个已经运行的进程分析,这样的话,我直接调用ptrace函数,并且指定第一个参数为PTRACE_ATTACH就可以了,然后我就会变成那个进程的父进程。

具体要选择哪种方式来调试,这就看你的需要了。不过不管哪种方式,最终我都会“接管”被调试的进程,它里面发生的各种信号事件我都能得到通知,方便我对它进行调试操作。

软件断点

作为一个调试器,最常用的功能就是给程序下断点了。

你可以通过break命令告诉我,你要在程序的哪个位置添加断点。

当我收到你的命令之后,我会偷偷把被调试进程中那个位置的指令修改为一个0xCC,这是一条特殊指令的CPU机器码——int 3,是x86架构CPU专门用来支持调试的指令。

我的这个修改是偷偷进行的,你如果通过我来查看被调试进程的内存数据,或者在反汇编窗口查看那里的指令,会发现跟之前一样,这其实是我使的障眼法,让你看起来还是原来的数据,实际上已经被我修改过了,你要是不信,你可以另外写个程序来查看那里的数据内容,看看我说的是不是真的。

一旦被调试的进程运行到那个位置,CPU执行这条特殊的指令时,会陷入内核态,然后取出中断描述符表IDT中的3号表项中的处理函数来执行。

IDT中的内容,操作系统一启动早就安排好了,所以系统内核会拿到CPU的执行权,随后内核会发送一个SIGTRAP信号给到被调试的进程。

而因为我的存在,这个信号会被我截获,我收到以后会检查一下是不是程序员之前下的断点,如果是的话,就会显示断点触发了,然后等待程序员的下一步指示。

在没有下一步指示之前,被调试的进程都不会进入就绪队列被调度执行。

直到你使用continue命令告诉我继续,我再偷偷把替换成int 3的指令恢复,然后我再次调用ptrace函数告诉操作系统让它继续运行。

这就是我给程序下断点的秘密。

不知道你有没有发现一个问题,当我把替换的指令恢复后让它继续运行,以后就再也不会中断在这里了,可程序员并没有撤销这个断点,而是希望每次执行到这里都能中断,这可怎么办呢?

我有一个非常巧妙的办法,就是让它单步执行,只执行一条指令,然后又会中断到我这里,但这时候我并不会通知程序员,而仅仅是把刚才恢复的断点又给打上(替换指令),然后就继续运行。这一切都发生的神不知鬼不觉,程序员根本察觉不到。

单步调试

说到单步执行,应该算是程序员调试程序的时候除了下断点之外最常见的操作了,每一次只让被调试的进程运行一条指令,这样方便跟踪排查问题。

你可能很好奇我是如何让它单步执行的呢?

单步执行的实现可比下断点简单多了,我不用去修改被调试进程内存中的指令,只需要调用ptrace函数,传递一个PTRACE_SINGLESTEP参数就行了,操作系统会自动把它设置为单步执行的模式。

我也很好奇操作系统是怎么办到的,就去打听了一下。

原来x86架构CPU有一个标志寄存器,名叫eflags,它里面不止包含了程序运行的一些状态,还有一些工作模式的设定。

其中就有一个TF标记,用来告诉CPU进入单步执行模式,只要把这个标记为设置为1,CPU每执行一条指令,就会触发一次调试异常,调试异常的向量号是1,所以触发的时候,都会取出IDT中的1号表项中的处理函数来执行。

接下来的事情就跟命中断点差不多了,我会截获到内核发给被调试进程的SIGTRAP信号,然后等待程序员的下一步指令。

如果你继续进行单步调试,那我便继续重复这个过程。

如果你有程序的源代码,你还可以进行源码级别的单步调试,不过这里的单步就指的是源代码中的一行了。

这种情况下要稍微麻烦一点,我还要分析出每一行代码对应的指令有哪些,然后用上面说的单步执行指令的方法,一条条指令快速掠过,直到这一行代码对应的指令都执行完成。

内存断点

有的时候,直接给程序中代码的位置下断点并不能包治百病。比如程序员发现某个内存地址的内容老是莫名其妙被修改,想知道到底是哪个函数干的,这时候连地址都没有,根本没法下断点。

单步执行也不行,那么多条指令,得执行到猴年马月去才能找到?

不用担心,我可以帮你解决这个烦恼。

你可以通过watch命令告诉我,让我监视被调试进程中某个内存地址的数据变化,一旦发现被修改,我都会把它给停下来报告给你。

猜猜我是如何做到的呢?

我可以用单步执行的方式,每执行一步,就检查一下内容有没有没修改,一旦发现就停下来通知你们程序员。

不过这种方式实在是太麻烦了,会严重拖垮被调试进程的性能。

好在x86架构的CPU提供了硬件断点的能力,帮我解决了大问题。

在x86架构CPU的内部内置了一组调试寄存器,从DR0到DR7,总共8个。通过在DR0-DR3中设置要监控的内存地址,然后在DR7中设置要监控的模式,是读还是写,剩下的交给CPU就好了。

CPU执行的时候,一旦发现有符合调试寄存器中设置的情况发生时,就会产生调试异常,然后取出IDT中的1号表项中的处理函数来执行,接下来的事情就跟单步调试产生的异常差不多了。

CPU内部依靠硬件电路来完成监控,可比我们软件一条一条的检查快多了!

现在,你不止可以使用watch命令来监控内存被修改,还可以使用rwatchawatch命令来告诉我去监控内存被读或者被写。

我叫GDB,是你调试程序的好伙伴,现在你该知道我是如何工作的了吧!

- EOF -



推荐阅读  点击标题可跳转

0、极客专属:几十款程序员秒懂的T恤/卫衣

1、全球首个开源“福利姬”诞生:自愿共享私密数据,方便网友制作 AI 擦边图

2、本周最火 AutoGPT!GitHub3.6万+标星,解决复杂任务全程无需人类插手

3、三星被曝因 ChatGPT 泄露芯片机密!韩媒惊呼数据“原封不动”直传美国,软银已禁止员工使用


关注「程序员的那些事」加星标,不错过圈内事

点赞和在看就是最大的支持❤️

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
Pano 剪贴板管理器是你需要的一个很棒的 GNOME 扩展 | Linux 中国给春天修剪枝叶外国网红想整蛊诈骗犯,却和“骗子”成为好兄弟?他们的故事感动百万人……博尔赫斯修房屋漏水被骗3万、“骗子”开奔驰上门:原来他们的钱是这么来的!微信公众号新增朗读功能, 新款Model 3产线或已调试完成,抖音上线云客服,脉脉称平台不存在匿名发帖,这就是今天的其他大新闻!31岁美女创业者,竟然是个骗子!华尔街顶级投行被骗走10亿从“你蛾子”到“上门枪毙”,骗子在内卷还是躺平?快速调试PID参数的3种方法。英王庆生,凯特绿裙美出新高度;梅根灰头土脸被骂“该死的骗子”沙伊和解后,中国开始一个“大工程”!美国内心很复杂……加州10大骗局 杀猪盘占三成最多大骗子打败小骗子,富士康也栽在印度手华女被骗28万美元!一场轰动全美的微信群免费购物大骗局,万人被骗千万美元知道员工所有秘密,Meta版AI聊天机器人来了:使用公司内部数据训练,能写代码、调试,还能总结会议230602 三千多个大骗子被“骗子”忽悠5年,又亏了20亿!最惨“股神”,正在搞垮云南白药?世界上唯一被消灭的疫病,致5亿人死亡,却被英国一“骗子”消灭!杀猪盘新手段 网络热恋男友要寄金子 日裔老人被骗4万 加州10大骗局 杀猪盘占3成…这个信号 确定就是骗子Set Me Free -BTS网络约会遭遇“爱情骗子”?警惕!键盘对面可能是心理变态者“玩钓鱼”这个保鲜膜切割器是我用过里更顺手的,几乎解决了所有槽点|开团史上最大骗局被搞死,节前福利妙妙妙!TVB美女主变“印度骗子”!引诱当地人赚美金 多人受害中招彻底被中国制造揭穿,欧美蕞大骗局至此破灭!史上最大骗局被揭穿,此后再无智商税!红脖是美国的雷锋这应该是个“好色的病毒”!高尔夫降维打球被骗28万美元!轰动全美的微信群免费购物大骗局,万人被骗千万美元血赚!夫妇俩冲动买下140年老宅,谁知竟是个“藏宝阁”!瞬间身价暴涨...辽宁高级养老院一段偷拍视频,揭开了世间最大骗局原装6Hz、超频体质,为什么这块处理器是攒机佬的梦中情U?二胎家庭花钱最爽的一次,是入手这个“大件”!家务省一半,孩子少生病,糕妈用了都夸趣图:AI 啥时候能调试代码
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。