我调过的最难调的Bug

每个程序员都有些不畏死亡决战猛兽的英雄事迹。以下这些是我的。
  内存冲突
  毕业不到半年,拿着刚到手的文凭,我在Lexmark公司的一个嵌入式Linux固件开发团队中负责追踪一个内存冲突的问题。因为内存冲突的原因和问题表象总是相差非常大,所以这类问题很难调。有可能是因为缓存溢出,也有可能是指针未初始化,或是指针被多次free,亦或是某处的DMA错误,但是你所见的却是一堆神秘的问题:挂起、指令未定义、打印错误,以及未处理的内核错误。这些都非常频繁,内存冲突看上去似乎是随机出现又很难重现。
  要调试这种问题,第一步是可重现问题。在我们奇迹般地找到这样一个场景之后,故事开始变得好玩起来。
  当时,我们发现在运行时因内存冲突而产生的程序崩溃每几百小时就会出现一次。之后有一天有人发现一个特别的打印任务会产生内存冲突从而在几分钟之内就使程序崩溃。我从来不知道为什么这个打印任务会产生这个问题。现在,我们就可以进一步做些什么了。
  调试
  这个问题可重现之后,我就开始寻找崩溃中出现的模式。最引人注意的是未定义指令和内核错误,它们差不多三分之一的时间就会发生一次。未定义指令的地址是一个合理的内核代码地址,但是CPU读到的这个指令却不是我们期望出现的。这就很简单了,可能是有人不小心写了这些指令。把这些未定义指令的句柄打印出来之后,我可以看到这些错误的指令所在位置的周边内存的状态。
  在做了大量失败的将更多的代码排除出崩溃的尝试之后,一个特殊的崩溃渐渐显现。
  崩溃之王
  这个崩溃解开了所有秘密。当时我们用了一个双核CPU。在这个特殊的崩溃里,首先CPU1在有效的模块地址范围内收到了一个未处理的内核错误,而此时它正在尝试执行模块代码,这段代码可能是一个冲突的页表或是一个无效TLB。而正在处理这个错误时,CPU0在内核地址空间内收到了一个非法的指令陷阱。
  以下是从修改后的未定义指令句柄中打印出来的数据(已转为物理地址,括号中是出错地址)
  undefined instruction: pc=0018abc4
  0018aba0: e7d031a2 e1b03003 1a00000e e2822008
  0018abb0: e1520001 3afffff9 e1a00001 e1a0f00e
  0018abc0: 0bd841e6 (ceb3401c) 00000004 00000001
  0018abd0: 0d066010 5439541b 49fa30e7 c0049ab8
  0018abe0: e2822001 eafffff1 e2630000 e0033000
  0018abf0: e16f3f13 e263301f e0820003 e1510000
  以下是内存域应该显示的数据:
  0018aba0: e7d031a2 e1b03003 1a00000e e2822008
  0018abb0: e1520001 3afffff9 e1a00001 e1a0f00e
  0018abc0: e3310000 (0afffffb) e212c007 0afffff3
  0018abd0: e7d031a2 e1b03c33 1a000002 e3822007
  0018abe0: e2822001 eafffff1 e2630000 e0033000
  0018abf0: e16f3f13 e263301f e0820003 e1510000
  确切地来说,只有一行缓存(中间那32byte)是有冲突的。一个同事指出冲突行中0x49fa30e7这个字是一个魔术cookie,它标记了系统中一个特殊环形缓冲区的入口。入口值的最后一个字永远是一个时间戳,所以0x5439541b是上一个入口的时间戳。我决定去读取这个环形缓冲的内容,但它现在挂在一个不可执行的KGDB提示那了。机器现在跟死了一样。
冷启动攻击
  为获取环形缓冲区的数据,我进行了一次冷启动攻击。我为正在使用的主板搞到了一份概要拷贝,然后发现CPU的复位线上连了一块不受欢迎的板子。我把它短路了,重置CPU而不妨碍DRAM的完整性。然后,我把Boot挂载在引导程序上。
  在引导程序里,我dump到了问题中环形缓冲区的内容。谢天谢地,这个缓存总是在一个固定的物理地址上被定位到,所以找到它不是问题了。
  通过分析错误时间戳周边的环形缓冲区,我们发现了两个老的cache line。这两个cache line里有有效数据,但是在这两个cache line里的时间戳却是环形缓冲区里之前的时间。
  导致CPU0上未定义指令的cache line与环形缓冲区里那两个老cache line之一相当契合,但是这并不说明其他可能的地方也是这样。我发现一个决定性的证据。假设,另一个消失的cache line是导致CPU1上未处理内核错误的元凶。
  错置的cache line
  cache line应该被写入0x0ebd2bc0(环形缓冲区里的cache line),但是事实上却写入了0x0018abc0(冲突的内核码)。这些地址在我们CPU上属于相同的缓存,它们的位[14:5]的值是相同的。不知为何它们有别名。
  bit 28 24 20 16 12 8 4 0
  | | | | | | | |
  0x0ebd2bc0 in binary is 0000 1110 1011 1101 0010 1011 1100 0000
  0x0018abc0 in binary is 0000 0000 0001 1000 1010 1011 1100 0000
  一个地址的低5位是cache line(32字节cache line)里的索引。后10位,即位[14:5],表示缓存集。剩下的17位,即位[31:15],用来表示缓存里当前存的是哪个cache line.
  我向我们的CPU供应商提交了一个bug报告,之后他们制定了一个解决方案,并在下一版本CPU里修复了这个bug。
  我期望听到更多牛掰的此类故事,也期望我自己可以再攒点这样的。

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-11-12 00:18:23

我调过的最难调的Bug的相关文章

中秋节动动鼠标 众口不再难调

昨日下午3点,李喻又签收了一个包裹."这是从上海网购的鲜肉月饼,我们家这次中秋赏月的东西总算齐全了."在电子商务和物流产业发达的今天,人们的生活有了更多的可能,传统中秋美食也不再囿于地域,指尖轻轻一点,网购南北货,月饼吃全国,互联网缩短了舌尖距离. 动动鼠标 众口不再难调 两周前,李喻就开始为今年中秋的家族聚会做策划.姑父是当年的上海知青,表姐夫是山西人,李喻想通过记忆中的味道,让自家的外来"姑爷"们回味一下家乡的感觉."之前我向同学和朋友打听了不同地方的

LAMP系统性能调优之MySQL服务器调优

如今,开发人员不断地开发和部署使用LAMP(Linux.Apache.MySQL 和 PHP/Perl)架构的应用程序.但是,服务器管理员常常对应用程序本身没有什么控制能力,因为应用程序是别人编写的.本文重点讨论为实现最高效率而对数据库层进行的调优. 关于 MySQL 调优 有3 种方法可以加快 MySQL服务器的运行速度,效率从低到高依次为: 替换有问题的硬件. 对MySQL进程的设置进行调优. 对查询进行优化. 替换有问题的硬件通常是我们的第一考虑,主要原因是数据库会占用大量资源.不过这种解

oracle数据库性能调优技术:索引调优

一.概述 随着数据库在各个领域的使用不断增长,越来越多的应用提出了高性能的要求.数据库性能调优是知识密集型的学科,需要综合考虑各种复杂的因素:数据库缓冲区的大小.索引的创建.语句改写等等.总之,数据库性能调优的目的在于使系统运行得更快. 调优需要有广泛的知识,这使得它既简单又复杂. 说调优简单,是因为调优者不必纠缠于复杂的公式和规则.许多学术界和业界的研究者都在尝试将调优和查询处理建立在数学基础之上. 称调优复杂,是因为如果要完全理解常识所依赖的原理,还需要对应用.数据库管理系统.操作系统以及硬

webview可以调本地的h5 也可以调百度 为啥就是不能调自己写放在iis下的h5

问题描述 webview可以调本地的h5 也可以调百度 为啥就是不能调自己写放在iis下的h5 之前我记得是可以的 不知道改什么了 现在就是不行 求大佛指点啊 解决方案 404还是什么..iis机子开了防火墙还是杀毒?80端口通么? 解决方案二: 是访问不到iss你的html5网页??

传统零售商网上开店价格体系难调

本报实习记者 赵向阳 北京报道 忽如一夜春风来.2009年末,一些传统的零售商纷纷推出自己的网上商城. 2009年12月30日,我国零售业龙头,百联集团推出了B2C电子商务平台"百联股份网上商城".同样在12月份,上海农工商超市斥资上亿元打造的"便利通网上商城"正式上线.而在这之前,国美.苏宁.物美以及利群集团都在电子商务领域进行了不同程度的尝试.此外,中粮.蒙牛.海尔.富士康等上游供应商也纷纷构建自己的电子购物平台. 以实体店铺为主要销售渠道的传统零售商为何开始&

手机搜狐视频怎么调亮度 搜狐视频调亮度方法

在手机中搜狐视频调亮度技巧有很多有直接拉屏幕就可以的哦,也有下面方法操作可以实现的具体如下. 1.我们在手机中点击打开进入到 手机搜狐视频里 然后找到要调整的 视频 如下图所示 2.之后我们在手机视频中点击视频的中央区域,如下图所示 3.之后我们再找到 视频左侧上下滑动即可调节亮度 细节如下图所示 好了到此我们的视频就打开成功了哦.

windows10系统下word调不出输入法怎么办 调不出输入法解决办法

具体如下: 1.新建word(这里是为了防止有用文件丢失,先保存关闭了不用),并打开. 依次点击:文件-选项. 2.高级-去掉打钩 输入法控制处于活动状态-确定. 3.此时需要重启word.重启后测试输入法就好了. 以上内容就是小编为大家带来的关于windows10系统下word调不出输入法问题的解决方法了.同样碰到输入法问题的用户们,可以尝试上述步骤操作看看.

微信怎么调成扬声器模式 微信调成扬声器模式方法

微信扬声器模式其实非常的简单只需要简单的几步就可以实现了,下面以Android系统手机为例子. 1.我们点击手机中的微信,进入之后再点击右下角[我](如下图所示)     2.然后在我的界面中找到设置点击进入     3.点击[聊天]选项,如下图所示     4.在此我们点击[使用听筒播放语音]后的绿色按钮,如图所示     5.按钮变为灰色表示开启扬声器模式   ps 小编使用的iphone手机发现只要把语音按一下就会自动杨声器了不知道安卓手机是不是这样的哦.

调优日志切换(Tuning Log Switches)

调优日志切换(Tuning Log Switches)   日志切换:LGWR进程停止写日志到当前日志文件,关闭日志文件,打开新的日志文件并写日志缓存中的数据到新的日志文件.   日志切换可以命令ALTER SYSTEM SWITCH LOGFILE或者ALTER SYSTEM ARCHIVE LOG来手工执行,也可以通过设置参数LOG_ARCHIVE_START使其自动执行.一般的原因是一个进程不能将生成的重做日志从缓存中写到当前的日志文件,因为已经使用到当前日志文件的最后一个数据块.