调研是一门学问,但是我并不觉得我非常擅长。过去,我没有立志于成为一个研究性的程序员,实践对于我来说更有感觉。只是呢,随着编程年轮的一圈一圈地增长,研究性的开发也变成一个不可缺少的日常活动。虽也说不上是每日必备的活动,但是呢,每隔几天、向周也得做一些相关性的研究。

调研成为日常活动时,那不可避免的,我们也会发现一些研究的手法。尽管,我想总结一些相关的模式,但是对于我来说,时机还不够成熟,我也缺乏相关的经验。

调研是一门艺术。

同样的,起因也是项目的缘故,话题是 Time Travel Debugging,也被译为时间旅行调试。所以,从这次的经验来看,我把过程分为这么几部分:

  1. 概念定义。即什么是时间旅行调试

  2. 资料收集。

  3. 流程模式。

  4. 抽象概念要素。即从上一步中抽象所需要的相关关键要素

  5. 原型设计。

看上去平淡无奇,和普通的技术研究没啥两样。而本文所针对的场景同是,大家都研究得相对较少的领域。

概念定义

定义概念本身可以分为两部分:

  1. 收集其他人对于这个概念的定义。

  2. 抽象出自己对于概念的理解。

  3. 持续完善这个概念的定义。

万事就是得这么开头易。定义概念有几个好出处:

  1. 最好的出处是『维基百科的英文版』,一个世界上大部分国家都能正常访问的知识网站。维基百科有一个重定义的功能,还能帮助我们找到正确的用语。维基百科有一个非常大的特点:啰嗦。

  2. 其次是 Google 索引,就是通过 Google 来找到热门的、大部分情况下可信的介绍网站。

所以,我们先简单引用微软文档的定义(机翻版):

Time Travel Debugging 是一种工具,它使您可以记录(record)正在运行的进程的执行情况,然后在以后向前和向后重放(replay)它。Time Travel Debugging(TTD)通过让您“倒带”(rewind)调试器会话,来帮助您更轻松地调试问题,而不必在发现错误之前重现问题。

我刚看到介绍的时候觉得平谈无奇,直到写这篇文章的时候,我发现了隐藏了关键字:record-replay,于是先在这里提醒一下。

然后呢,维基百科上来了一个更详细的定义:

时间旅行调试是通过源码在时间上的倒退,以了解在执行计算机程序期间发生的事情的过程。

还有对应的说明:

通常来说,调试和调试器是帮助用户进行调试过程的工具,允许用户暂停正在运行的软件的执行并检查程序的当前状态。而后,用户可以及时前进,进入或跳过语句,然后向前执行。而交互(Interactive)式调试器呢,则包括修改代码并根据更新的信息前进的功能。反向(Reverse)调试工具,使用户可以在时间上向后退,以逐步达到程序中的特定点。时间旅行调试器提供了这些功能,还允许用户与程序交互,如果需要,可以更改历史记录,并观察程序如何响应。

从结论上来说,维基百科给了概念上的定义,而微软的文档则是侧重于实现方式上的定义。这样一结论,我们就得到了简单的结论:

时间旅行调试是一种软件开发的调试方式,通过将时间与源码关联,来让开发者了解程序运行期间发生的变化。它记录(record)下了程序在不同时间的状态,以便于在调试时可以向前和向后重放(replay)状态,来展示程序的运行情况。

资料收集

从理论上来说,这一步并不是过于复杂,套路都很简单,常见的来源有:

  • 维基百科。维基百科的概念上一般都会有对应的实现示例。

  • 论文。来源虽多,但是对于我来说,我习惯于 Google Scholar,可以下载。

  • 论文网络。通过论文的 Related Works 和 References,扩大搜索范围,然后借助于 Google Scholar 的被引用数来判定

  • 社交网络。

  • 书和网络。

Wikipedia

维基百科给了一些相应的示例调试器:

  • Elm Debugger

  • Elm Reactor

  • Meiosis Tracer

  • Microsoft Time Travel Debugging (TTD) Tool for native Windows software (x86, x64, ARM, ARM64)

  • ocamldebug for OCaml

  • UDB for Linux

  • rr for x86 Linux

  • provDebugR for R

  • Wallaby.js for JavaScript

  • RevDeBug for C# and Java

  • WhyLine for Java

论文:Google Scholar

直接进行相关的搜索,然后阅读,如:

  • Expositor: Scriptable time-travel debugging with first-class traces

  • Tardis: Affordable time-travel debugging in managed runtimes

  • ……

有意思的事情是,我找到了一个作者写的大量相关论文。即微软的 Mark Marron,写的相关论文(主要是由第一篇看到的,然后搜索作者的相关论文)

  • Time-Travel Debugging for JavaScript/Node.js

  • A Gray Box Approach For High-Fidelity, High-Speed Time-Travel Debugging

  • TARDIS: Affordable Time-Travel Debugging in Managed Runtimes

  • ……

所以,我便深入研究了相关的论文和作品,然后就中奖了 —— 发现了一种解决方案:

论文网络

通过查找论文 References 及对应的 Related Work,我又找到了一系列的论文。诸如于:

  • Framework for Instruction-level Tracing and Analysis of Program Executions

  • Effcient Algorithms for Bidirectional Debugging

  • ReVirt - Enabling Intrusion Analy- sis Through Virtual-Machine Logging and Replay

  • ……

这一点对于那些搞学术的人来说,应该算是比较常见的。

书籍

对于诸如时间旅行调试这一类属学术上的事物。并不能像其它领域,可以通过阅读书的方式来解决,但是搜索成本点高。所以,我并没有怎么尝试去找。

社交网站

一次偶然的机会,我在知乎上搜索了 Time Travel Debugging,然后看到了『存在实现了后退功能的调试器吗?这种功能在实现上有什么难点呢?』这个问题, 又搜索到一波资料。

  • Visual Studio:IntelliTrace

  • GDB:GDB and Reverse Debugging

  • Java:Chronon | DVR for Java

  • .NET:RevDeBug Blog: What Is Reverse Debugging?

  • Chakra / ChakraCore:JavaScript Time-Travel Debugger - Microsoft Research

  • Firefox:WebReplay

  • 用于 C/C++ 的 rr

  • 用于 QEMU 交互运行时分析的 Qira

  • C++ 下的 UndoDB

  • 用于 Node.js 的 Wallaby.js

  • 用于 React 的 Redux

然而,大部分的意义不大 —— 并非开源,还得自己反向编译。

流程模式

对于工程师而言,我们读论文的目的嘛,不就是为了知晓他们是如何解决问题的。所以,我更关注于它实现这些问题的模式。这些会在论文中进行大致的介绍,我们只需要有耐心阅读就可以了。

示例 A

如『TARDIS: Affordable Time-Travel Debugging in Managed Runtimes』 中介绍的实施 TTD 系统的标准方法是:

  1. 定期捕获程序状态的快照

  2. 记录快照之间发生的所有不确定的环境交互,例如控制台 I/O 或计时器事件。

  3. 基于此,在反向执行时,首先还原在反向执行目标之前的最接近的快照,然后从该快照重新执行,从而重放环境和与幂等的环境写入之间的交互,以达到目标。

对应的

示例

又或者是『Framework for Instruction-level Tracing and Analysis of Program Executions』中引入的方式,

我们的框架由两个主要组件组成:一个称为 Nirvana 的运行时引擎和一个称为 iDNA(使用 Nirvana 的诊断基础设施)的跟踪记录和检索工具。

  • Nirvana。运行时引擎结合使用动态二进制翻译和解释来模拟目标机器的指令集。在模拟过程中,它向客户端应用程序插入回调,该回调记录的信息,足以在以后重新模拟应用程序的执行。记录的信息可以包括正在执行的 guest 指令的属性(例如,指令的地址、地址以及内存位置的读写值(如果是内存访问指令)、模块加载、异常、线程创建等事件,它还可以包括有关符号信息的位置信息(如果可用)。

  • iDNA 由两个主要组件组成:iDNA Trace Writer 在跟踪记录期间(trace recording)使用,iDNA Trace Reader ,在从记录的跟踪重新模拟期间使用。

对应的一些关键代码的设计:

Event name Description
TranslationEvent when a new instruction is translated
SequencingEvent start of a sequence point and other special events
InstructionStartEvent start of every instruction
MemReadEvent memory read
MemWriteEvent memory write
MemRefEvent memory reference
FlowChangeEvent flow control instruction (branch, call, ret)
CallRets calls and returns
DllLoadEvent load of a new module

相似的,还有其它不同的模式,由于篇幅原因,这里就不展开介绍了。

抽象概念要素

走马观花式的阅读了一系列论文之后,我大概有了如何设计一个系统的思路了。

基本概念

首先,让我们来看一下所有的一些关键信息:

  • 语言类型:脚本语言、编译型原生语言、编译型虚拟机语言等

  • 创建快照时机:编译时、转译时、编译后等

  • 操作级别:指令级、代码级、虚拟机、操作系统等(PS:从理论上来说,应该还 MIR)

  • 关键要素:Recording / Replay、Checkpoint / Snapshots 等

  • 注意事项:I/O、Network、Filesystem、Event 等

  • 其它:GC 算法、快速管理、缓存管理等

因为它需要根据具体的场景来做出选择,所以便只是简单的逻列一下。

代码与场景示例

如『Framework for Instruction-level Tracing and Analysis of Program Executions』中的示例

Original (guest) code:
mov eax,[ebp+4]
Translated (host) code:
mov esi, nirvContext._ebp
add esi, 4 ; callee saved register
mov edx, esi ; 2nd argument ????→ address of memory accessed
mov ecx, nirvContext ; 1st argument ????→ pointer to NirvContext
push 4 ; 3rd argument ????→ number of bytes accessed
call MemRefCallback ; calling convention assumes ecx and edx hold 1st and 2nd argument
mov eax, [esi] ; simulate intended memory read
mov nirvContext._eax, eax ; update NirvContext with new value

原型设计

有了论文,阅读了相关的源码之后,我大概有了一个思路:

  1. 通过回调的思路,在运行时收集应用的状态信息

  2. 针对特殊的事件、IO、网络等,进行特殊的记录和缓存

  3. 在编译时,对代码运行转换

  4. 回放时,根据指令返回相应的结果

当然了 Demo 已经写好,只是呢,因为某种原因不方便贴在这里。

其它

我一直在寻找一种方式,以系统性的记录对于某一领域的调研,这一篇文章相当于作为一个开始。

相关链接:

  1. https://docs.microsoft.com/zh-cn/windows-hardware/drivers/debugger/time-travel-debugging-overview

  2. https://en.wikipedia.org/wiki/Timetraveldebugging

  3. https://www.zhihu.com/question/57574574/

调研技巧(上):以『时间旅行调试』为例相关推荐

  1. vfp 修改本机时间_时间旅行调试

    MSRC(微软安全应急响应中心)致力于联合世界范围内的厂商和安全研究人员,共同防御安全威胁并推动提升微软的产品安全.MSRC会尽可能快地评估外部报告给他们的漏洞,但如果微软的工作人员必须在与研究人员确 ...

  2. [日推荐]『绿豆旅行记账』能帮你省钱的旅行小工具

    2019独角兽企业重金招聘Python工程师标准>>> 眼看十一长假就要来啦,许多小伙伴一定早早地就做好的旅行计划,八天长假畅快玩,也是一笔不小的开销哦,怎么控制旅行中的花费呢,这款 ...

  3. 谷歌调试器调试的js_时辰?? “时间旅行”调试器

    谷歌调试器调试的js Chronon是一个新的"时空旅行"调试器. Chronon包含一个"飞行数据记录器",该记录器记录程序内部执行的代码行,并将其保存到文件 ...

  4. [日推荐]『梦想旅行』出国旅行全攻略!

    2019独角兽企业重金招聘Python工程师标准>>> 今天小编来推荐一个出国吃喝玩乐游购娱全攻略小程序,有了它就不用辛辛苦苦做攻略啦! 梦想旅行 **简介:**汇聚境外数万热门旅行 ...

  5. [日推荐]『旅行翻译』不懂外语也能走遍天下!

    2019独角兽企业重金招聘Python工程师标准>>> 难得的国庆&中秋长假,国内旅游人太多,不如出国玩玩,但是,不懂外语怎么办?没关系,这个小程序来帮你-- 旅行翻译 简介 ...

  6. [日推荐]『众跑联盟』懒癌拯救者

    2019独角兽企业重金招聘Python工程师标准>>> 好不容易放假,懒癌发作,就想瘫在家里不动,正在厨房做饭的老妈让你去楼下卖瓶酱油,怎么破? 万能的小编这就奉上一款小程序拯救你, ...

  7. [日推荐]『车助手360』车主必备

    2019独角兽企业重金招聘Python工程师标准>>> 又到了堵堵堵的周一 每到周一,有车一族的小伙伴们最大的烦心事就是堵车和找停车场的问题. 开车去上班,堵了一路,眼看要迟到,公司 ...

  8. [日推荐]『旅行云清单』列好清单,准备出发!

    2019独角兽企业重金招聘Python工程师标准>>> 国庆长假倒计时啦,再上两天班,就可以出去浪罗!,听说有的小伙伴今天下班就可以开启度假模式了,那么,你的行李收拾得怎么样了?可别 ...

  9. [日推荐]『钢琴优课』你免费的私人随身钢琴老师

    2019独角兽企业重金招聘Python工程师标准>>> 小编今天的文艺细胞有点炸,所以看到了这个小程序之后,就迫不及待的想要分享给大家啦!没错,这又是一款乐器自学小程序,这次学习的主 ...

最新文章

  1. Elasticsearch6.1.3 for CRUD
  2. UVa11134 Fabled Rooks(贪心算法)
  3. Linux sed命令使用
  4. 检索数据_14_返回不重复的记录
  5. spark_spark连接hive config
  6. 方法性能分析器--装饰者模式应用
  7. php pdf 文字水印图片,php如何给pdf加上文字水印和图片水印[未测试]
  8. JavaScript或MyEclipse—如何解决js文件导入到MyEclipse工程后出错?
  9. 关闭MySQL日志,删除mysql-bin.0000*日志文件
  10. Vulkan入门(一)-环境配置.md
  11. 提高计算机访问硬盘的速度慢,嫌电脑速度不够快?教你5招提升硬盘性能!
  12. 电脑录屏软件哪个最好用?都是高效高清!
  13. python函数分为哪几种_python函数有哪几种
  14. JAVA案例之使用接口实现手机功能
  15. android+动态隐藏图标,2018安卓手机怎么隐藏图标 进入隐藏应用界面
  16. 关于Gephi的安装的一些问题
  17. 地狱模式的居转户记录05
  18. 【图解】什么是拥塞控制,这应该是把拥塞控制讲的最好的文章了
  19. Office-Tool
  20. 几行代码实现用Python输出表情包

热门文章

  1. 数独游戏(Sudoku Game)
  2. 初级程序员 VS 高级程序员
  3. SETP7 Basic V11 SP1
  4. Excel收纳箱:记录下如何通过VBA代码获取当前列
  5. tomcat安装,环境变量配置,以及在eclipse上配置tomcat
  6. Swift之函数的语法分析和使用示例
  7. 【超硬核】还不知道怎么入门算法?这篇双指针让你吃到饱【力扣真题】+【算法图解】
  8. Windows server 2012 Web服务
  9. php在文本框中输入一个年份_判断其生肖_并输出在文本框旁边.代码,PHP开发工程师面试真题之Web网页设计(附参考答案)_PHP教程...
  10. 鸿蒙OS 2.0内测版,鸿蒙系统2.0安装包下载地址