时间旅行调试追踪中的存储器值暴露

文档序号:1866271 发布日期:2021-11-19 浏览:8次 >En<

阅读说明:本技术 时间旅行调试追踪中的存储器值暴露 (Memory value exposure in time travel debug traces ) 是由 J·莫拉 于 2020-04-04 设计创作,主要内容包括:本公开涉及在与使存储器单元值被记录到追踪中的事件相对应的(多个)执行时间之前暴露存储器单元值。包括第一追踪片段和第二追踪片段的追踪片段在追踪内被标识。每个追踪片段记录可执行指令在对应线程上的不间断连续执行。第一追踪片段可以在第二追踪片段之前排序。确定在第二片段的回放期间,存储器单元值可以在第一执行时间处被暴露,第一执行时间在第二执行时间之前,第二执行时间对应于使存储器单元值在追踪记录期间被记录到追踪中的事件。输出数据被生成,该输出数据指示在第二追踪片段的回放期间存储器单元值可以在第一执行时间暴露。(The present disclosure relates to exposing memory cell values prior to execution time(s) corresponding to events that cause the memory cell values to be logged into a trace. A trace segment including a first trace segment and a second trace segment is identified within the trace. Each trace segment records uninterrupted, sequential execution of the executable instructions on the corresponding thread. The first trace segment may be ordered before the second trace segment. It is determined that during playback of the second segment, the memory cell value may be exposed at a first execution time that precedes a second execution time that corresponds to an event that caused the memory cell value to be recorded into the trace during trace recording. Output data is generated indicating that the memory cell values may be exposed at the first execution time during playback of the second track segment.)

时间旅行调试追踪中的存储器值暴露

背景技术

追寻和校正软件代码(通常称为“调试”代码)中不期望的软件行为是软件开发中的核心活动。不期望的软件行为可以包括许多事情,诸如执行崩溃、运行时异常、执行性能缓慢、数据结果不正确、数据损坏等。不期望的软件行为可能由多种因素触发,诸如数据输入、用户输入、竞争条件(例如,当访问共享资源时)等。给定触发器的多样性,不期望的软件行为可能很稀有和看似随机的,并且极难再现。如此,对于开发人员标识给定的不期望软件行为可能非常耗时且困难。一旦不期望的软件行为已经被标识,再次确定其(多个)根本原因可能既耗时又困难。

开发人员用于调试代码的一种方法是使用“现场”调试器。通常,现场调试器附加至现场过程的执行,并且使开发人员能够监测和指导该过程的前向执行。例如,现场调试器可以使开发人员能够设置在它到达特定指令时中止程序执行的断点,设置在它访问特定的存储器地址时中止程序执行的观察点,在它执行时通过代码行单步执行等。

新兴形式的诊断工具支持“历史”调试(也称为“时间旅行”或“反向”调试),其中(多个)程序线程的至少一部分线程的执行被记录/追踪到一个或多个追踪文件(即,追踪(trace))中。使用一些追踪技术,追踪可以包含非常高保真“位准确”的历史追踪数据,这使得(多个)所追踪的线程的(多个)记录部分能够以极高的保真度虚拟地“回放”——甚至低至单个指令的粒度(例如,机器代码指令、中间语言代码指令等)。因此,使用位准确追踪数据,“时间旅行”调试器使开发人员不仅能够监测和指导追踪代码的前向仿真(例如,经由断点、观察点、单步执行等),而且还能够监测并且指导追踪代码的反向仿真(例如,经由反向断点、反向观察点、反向单步执行等)。因此,开发人员可以在追踪之前监测和指导程序的任何部分的执行。

虽然比传统的现场调试器提供了巨大的益处,但时间旅行调试技术仍然存在一些限制。例如,利用现代处理器每秒可能执行数十亿个指令,程序执行期间所收集的追踪数据量有可能是天文数字。因此,许多时间旅行调试技术采用的追踪机制强调针对所执行的每个指令产生最少量的追踪数据。例如,认识到大多数处理器指令是确定性的(即,当给定相同的输入时,它们将始终产生相同的输出),一些时间旅行调试技术依赖于记录在存储器读取发生时它们的值以及任何非确定性指令的旁效应(side effects)(例如,输出)。值得注意的是,为了减少时间旅行追踪器的开销,追踪器可能具有有限的能力来记录它先前记录了哪些存储器值。如此,追踪器可能会记录与来自该存储器单元的多次读取相关的、针对同一存储器单元的多个值,这可能会向时间旅行追踪添加冗余数据。

由于现场调试器被附加至现场过程,它能够随时访问过程的整个存储器空间,因此可以在任何时刻呈现任何可访问存储器单元的任何内容。相比之下,当回放在存储器读取发生时记录它们的时间旅行追踪时,时间旅行调试器可能只能在追踪中存在记录来自该单元的读取的数据分组时确定给定存储器单元的值。这意味着,与现场调试器相比,时间旅行调试器可能会受限于在任何给定时间可以产生的存储器内容。例如,虽然现场调试器可能能够在缓冲区初始化时呈现存储器缓冲区的全部内容(即,因为整个存储器缓冲区都在现场过程的存储器空间中,并且可用于现场调试器),但时间旅行调试器可能只能逐步地呈现存储器缓冲区的内容,因为这些内容是在由仿真器回放时被追踪代码读取。因此,虽然时间旅行调试器比现场调试器提供了显着的益处,诸如能够向前和向后两者分析代码,但与现场调试器相比,它可能在呈现存储器内容的能力受到限制。

发明内容

本文所描述的至少一些实施例分析时间旅行追踪,以标识可以在追踪回放期间在执行时间处被呈现的存储器单元值,该执行时间早于与使这些存储器单元值被记录到追踪中的事件(例如,存储器读取)相对应的执行时间。例如,实施例可以将追踪划分为片段——或在单个线程上所执行的连续指令序列——并且在这些片段中的至少一个片段中标识与在该片段中所发生的读取相对应的存储器单元值,该存储器单元值与片段中的该存储器单元的其他值兼容。该存储器单元值然后可以在片段中更早地暴露,诸如在片段的开始。实施例还可以标识该存储器单元值是否与先前片段兼容,并且如果它兼容,则跨这些片段推送该值。实施例还可以使用启发法以确定该存储器单元值是否与片段之间的追踪记录中的间隙兼容,并且如果它兼容,则跨这些间隙推送该值。实施例可以生成索引数据,以补充现有追踪并且标识可以比它们出现在追踪中的位置更早呈现的追踪中的存储器值,可以重写/修改现有追踪以重新布置存储器值出现在追踪中的位置,或者可以生成全新的追踪,其包括重新布置的存储器值。

一些实施例包括方法、系统和计算机程序产品,用于生成用于在与使存储器单元值被记录到追踪中的事件相对应的执行时间之前的执行时间处,在追踪回放期间生成用于暴露存储器单元值的数据。这些实施例包括标识记录一个或多个线程的先前执行的追踪内的多个追踪片段。每个追踪片段记录多个可执行指令在一个或多个线程的相对应线程上的不间断连续执行。多个追踪片段至少包括第一追踪片段和第二追踪片段。这些实施例至少确定多个追踪片段中的部分排序,包括确定第一追踪片段可以在第二追踪片段之前排序。针对至少第二追踪片段,确定在第二追踪片段的回放期间存储器单元值能够在第一执行时间处被暴露,第一执行时间在第二执行时间之前,第二执行时间对应于使存储器单元值在追踪记录期间被记录到追踪中的事件。这些实施例然后生成输出数据,该输出数据指示在第二追踪片段的回放期间存储器单元值可以在第一执行时间处被暴露。

其他实施例包括方法、系统和计算机程序产品,用于修改追踪以使存储器单元值在对应于使存储器单元值被记录到追踪中的执行时间之前被暴露。这些实施例包括访问记录一个或多个线程的先前执行的追踪,并且在追踪内标识多个数据分组,该数据分组分别记录从特定存储器单元读取的对应存储器单元值。多个数据分组中的每个数据分组对应于至少一个执行事件。这些实施例还包括选择在多个数据分组中的一个数据分组中记录的特定存储器单元值。这些实施例还包括通过执行以下中的至少一项来修改追踪:(i)从至少一个追踪片段移除多个数据分组中的除一个数据分组外的所有数据分组;或者(ii)将数据插入到追踪中,该追踪在追踪回放期间在与多个数据分组相对应的执行事件的执行时间之前的执行时间处、在暴露所选择的特定存储器单元值,以及从追踪移除多个数据分组。

该发明内容被提供以简化的形式介绍对于下面在

具体实施方式

中进一步描述的概念的选择。该发明内容不旨在标识所要求保护的主题的关键特征或必要特征,也不旨在用于辅助确定所要求保护的主题的范围。

附图说明

为了描述本发明的上述和其他优点和特征可以被获得的方式,上面简要描述的本发明的更具体的描述将通过参照在附图中图示的其具体实施例来绘制。要理解的是,这些附图仅描绘了本发明的典型实施例,因此不被认为是对其范围的限制,本发明将通过使用附图来利用附加的特异性和细节描述并且解释,其中:

图1A图示了示例计算环境,该环境促进在与使存储器单元值被记录到追踪中的事件相对应的执行时间之前暴露存储器单元值;

图1B图示了图1A的存储器索引组件的附加细节;

图2图示了其中图1A的计算环境与一个或多个其他计算机系统联网的示例;

图3图示了时间旅行调试追踪的一个示例;

图4A图示了示例时序图,其包括三个线程(包括片段)的执行的时间线;

图4B图示了图4A中的片段的一种潜在总排序的示例;

图5A图示了示例时序图,其包括三个线程(包括片段和间隙)的执行的时间线;

图5B图示了图5A中的片段和间隙的一种潜在总排序的示例;

图6A图示了与执行字符串复制的单个片段的执行相对应的示例时序图,包括现场和时间旅行调试存储器读取和写入定时;

图6B图示了与执行字符串复制的单个片段的执行相对应的示例时序图,包括执行片段内存储器移动;

图7A图示了与执行字符串复制的单个片段的执行相对应的示例时序图,包括现场和时间旅行调试存储器读取和写入定时;

图7B图示了与执行字符串复制的单个片段的执行相对应的示例时序图,包括执行片段内存储器移动;

图8A图示了与多个片段的执行相对应的示例时序图,该多个片段基于正则表达式匹配将字符串拆分为多段并且其包括来自另一线程的片段,包括现场和时间旅行调试存储器读取和写入定时;

图8B图示了与多个片段的执行相对应的示例时序图,该多个片段基于正则表达式匹配将字符串拆分为多段并且其包括来自另一线程的片段,包括执行片段内存储器移动;

图8C图示了与多个片段的执行相对应的示例时序图,该多个片段基于正则表达式匹配将字符串拆分为多段并且其包括来自另一线程的片段,包括在图8B的片段内存储器移动之后执行片段间存储器移动;

图8D图示了与多个片段的执行相对应的示例时序图,该多个片段基于正则表达式匹配将字符串拆分为多段并且其包括来自另一线程的片段,并且示出了与图8A相比的总体存储器移动;

图9A图示了与多个片段的执行相对应的示例时序图,该多个片段基于正则表达式匹配将字符串拆分为多段并且其包括间隙,包括现场和时间旅行调试存储器读取和写入定时;

图9B图示了与多个片段的执行相对应的示例时序图,该多个片段基于正则表达式匹配将字符串拆分为多段并且其包括间隙,包括执行片段间存储器移动;

图9C图示了与多个片段的执行相对应的示例时序图,该多个片段基于正则表达式匹配将字符串拆分为多段并且其包括间隙,包括基于单个线移动分析跨间隙来执行存储器移动;

图9D图示了与多个片段的执行相对应的示例时序图,该多个片段基于正则表达式匹配将字符串拆分为多段并且其包括间隙,包括基于基于注解的分析跨间隙来执行存储器移动;

图9E图示了与多个片段的执行相对应的示例时序图,该多个片段基于正则表达式匹配将字符串拆分为多段并且其包括间隙,包括基于基于分配的分析跨间隙来执行存储器移动;

图10图示了用于生成数据的示例方法的流程图,该数据用于在追踪回放期间使存储器单元值在先于对应于使存储器单元值被记录到追踪中的执行时间的执行时间处被暴露;以及

图11图示了用于修改追踪以使存储器单元值在对应于使存储器单元值被记录到追踪中的执行时间之前被暴露的示例方法的流程图。

具体实施方式

本文所描述的至少一些实施例分析时间旅行追踪,以标识可以在追踪回放期间在执行时间处被呈现的存储器单元值,该执行时间早于与使这些存储器单元值被记录到追踪中的事件(例如,存储器读取)相对应的执行时间。例如,实施例可以将追踪划分为片段——或在单个线程上所执行的连续指令序列——并且在这些片段中的至少一个片段中标识与在该片段中所发生的读取相对应的存储器单元值,该存储器单元值与片段中的该存储器单元的其他值兼容。该存储器单元值然后可以在片段中更早地暴露,诸如在片段的开始。实施例还可以标识该存储器单元值是否与先前片段兼容,并且如果它兼容,则跨这些片段推送该值。实施例还可以使用启发法以确定该存储器单元值是否与片段之间的追踪记录中的间隙兼容,并且如果它兼容,则跨这些间隙推送该值。实施例可以生成索引数据,以补充现有追踪并且标识可以比它们出现在追踪中的位置更早所呈现的追踪中的存储器值,可以重写/修改现有追踪以重新布置存储器值出现在追踪中的位置,或者可以生成全新的追踪,其包括重新布置的存储器值。

图1A图示了示例计算环境100a,其促进在与使存储器单元值被记录到追踪中的事件相对应的执行时间之前暴露存储器单元值。如所描绘的,计算环境100a可以包括或利用专用或通用计算机系统101,其包括计算机硬件,诸如例如一个或多个处理器102、系统存储器103、持久性存储装置104和/或(多个)网络设备105,它们使用一个或多个通信总线106通信耦合。

本发明的范围内的实施例可以包括用于携带或存储计算机可执行指令和/或数据结构的物理和其他计算机可读介质。这种计算机可读介质可以是可以由通用或专用计算机系统访问的任何可用介质。存储计算机可执行指令和/或数据结构的计算机可读介质是计算机存储介质。携带计算机可执行指令和/或数据结构的计算机可读介质是传输介质。因此,通过示例而非限制,本发明的实施例可以包括至少两种明显不同的计算机可读介质:计算机存储介质和传输介质。

计算机存储介质是存储计算机可执行指令和/或数据结构的物理存储介质(例如,系统存储器103和/或持久性存储装置104)。物理存储介质包括计算机硬件,诸如RAM、ROM、EEPROM、固态驱动器(“SSD”)、闪存、相变存储器(“PCM”)、光盘存储装置、磁盘存储装置或者其他磁性存储设备或者(多个)任何其他硬件存储设备,其可以被用以计算机可执行指令或数据结构的形式存储程序代码,该程序代码可以由通用或专用计算机系统访问和执行以实施所公开的本发明的功能性。

传输介质可以包括网络和/或数据链路,其可以被用以携带计算机可执行指令或数据结构形式的程序代码并且可以由通用或专用计算机系统访问。“网络”被限定为能够在计算机系统和/或模块和/或其他电子设备之间传送电子数据的一个或多个数据链路。当信息通过网络或另一通信连接(硬连线、无线或者硬连线或无线的组合)被传递或提供给计算机系统时,计算机系统可以将连接视为传输介质。以上的组合也应该被包括在计算机可读介质的范围内。

进一步地,在到达各种计算机系统组件时,计算机可执行指令或数据结构形式的程序代码可以自动从传输介质传递到计算机存储介质(反之亦然)。例如,通过网络或数据链路所接收的计算机可执行指令或数据结构可以被缓冲在网络接口模块(例如,(多个)网络设备105)内的RAM中,然后最终传递到计算机系统RAM(例如,系统存储器103)和/或计算机系统处的更少的易失性计算机存储介质(例如,持久性存储装置104)。因此,应该理解的是,计算机存储介质可以被包括在也(或者甚至主要地)利用传输介质的计算机系统组件中。

例如,计算机可执行指令包括指令和数据,在一个或多个处理器处执行时,该指令和数据使通用计算机系统、专用计算机系统或专用处理设备执行某个功能或功能组。例如,计算机可执行指令可以是机器代码指令(例如,二进制)、中间格式指令(诸如,汇编语言),或者甚至源代码。

本领域技术人员将了解,本发明可以利用许多类型的计算机系统配置在网络计算环境中实践,包括个人计算机、台式计算机、膝上型计算机、消息处理器、手持式设备、多处理器系统、基于多处理器或可编程的消费性电子产品、网络PC、小型计算机、大型计算机、移动电话、PDA、平板计算机、寻呼机、路由器、交换机等。本发明还可以在分布式系统环境中实践,其中通过网络链接(通过硬连线数据链路、无线数据链路或者通过硬连线和无线数据链路的组合)的本地和远程计算机系统两者都执行任务。如此,在分布式系统环境中,计算机系统可以包括多个组成计算机系统。在分布式系统环境中,程序模块可以位于本地和远程存储器存储设备两者中。

本领域技术人员也将了解,本发明可以在云计算环境中实践。云计算环境可以是分布式的,尽管这不是必需的。当是分布式时,云计算环境可以在组织内进行国际地分布和/或具有跨多个组织所拥有的组件。在该描述和以下权利要求中,“云计算”被定义为用于能够对可配置计算资源(例如,网络、服务器、存储装置、应用和服务)的共享池进行按需网络访问的模型。“云计算”的定义不被限于在适当部署时可以从这种模型所获得的任何其他许多优点。

云计算模型可以由各种特性组成,诸如按需自助服务、广泛的网络访问、资源池化、快速弹性、测量服务等。云计算模型还可以以各种服务模型的形式出现,诸如例如软件即服务(“SaaS”)、平台即服务(“PaaS”)和基础设施即服务(“IaaS”)。云计算模型还可以使用不同的部署模型来部署,诸如私有云、社区云、公共云、混合云等。

一些实施例(诸如,云计算环境)可以包括系统,该系统包括分别能够运行一个或多个虚拟机的一个或多个主机。在操作期间,虚拟机仿真可操作计算系统,从而支持操作系统以及可能还有一个或多个其他应用。在一些实施例中,每个主机包括管理程序,该管理程序使用从虚拟机的视图中所抽象出来的物理资源来仿真针对虚拟机的虚拟资源。管理程序还提供虚拟机之间的适当隔离。因此,从任何给定虚拟机的角度来看,管理程序提供虚拟机正在与物理资源接口连接的错觉,即使虚拟机仅与物理资源的外观(例如,虚拟资源)接口连接。物理资源的示例包括处理能力、存储器、磁盘空间、网络带宽、介质驱动器等。

如图1A所示,每个处理器102可以包括(除其他外)一个或多个处理单元107(例如,处理器核心)和一个或多个缓存108。每个处理单元107经由缓存108加载和执行机器代码指令。在一个或多个执行单元107b处执行这些机器代码指令期间,指令可以使用内部处理器寄存器107a作为临时存储位置,并且可以经由缓存108读取和写入系统存储器103中的各种位置。通常,缓存108临时缓存系统存储器103的部分;例如,缓存108可以包括缓存存储应用代码的系统存储器103的部分的“代码”部分以及缓存存储应用运行时数据的系统存储器103的部分的“数据”部分。如果处理单元107要求尚未存储在缓存108中的数据(例如,代码或应用运行时数据),那么处理单元107可以发起“缓存缺失”,使致所需数据从系统存储器103取得——同时可能将一些其他数据从缓存108“驱逐”回到系统存储器103。

如所图示的,持久性存储装置104可以存储表示可执行软件组件的计算机可执行指令和/或数据结构;对应地,在(多个)处理器102处执行该软件期间,这些计算机可执行指令和/或数据结构的一个或多个部分可以被加载到系统存储器103中。例如,持久性存储装置104被示出为存储与存储器索引组件109、追踪组件110、仿真组件111和(多个)一个或多个应用112相对应的计算机可执行指令和/或数据结构。持久性存储装置104还可以存储数据,诸如记录(多个)应用112中的一个或多个应用的一个或多个执行的(多个)一个或多个追踪113。

通常,存储器索引组件109采用(多个)追踪113中的一个或多个追踪作为输入,并且基于对(多个)这些追踪113的分析,存储器索引组件109标识(多个)存储器单元值,其可以在与使存储器单元值被记录到(多个)追踪113中的事件相对应的(多个)执行时间之前的执行时间处的回放(多个)追踪113期间暴露。存储器索引组件109然后可以生成索引数据以补充(多个)追踪113,以生成包含与索引数据一致的改变的(多个)新追踪113,和/或修改或重写与索引数据一致的(多个)现有追踪113。因此,图1A示出了存储器索引组件109和(多个)追踪113被加载到系统存储器中(即,存储器索引组件109’和(多个)追踪113’),并且存储器索引组件109’和(多个)追踪113’之间的双端箭头指示存储器索引组件109’可以从(多个)这些追踪113’读取并且可能写入(多个)这些追踪113’;如果数据被写入(多个)追踪113’,则该数据也可能被持久化到持久性存储装置104中的(多个)追踪113。

如所提及的,存储器索引组件109对(多个)追踪113执行分析。在实施例中,该分析可以包括静态分析或动态分析中的一个分析或两者。如本文所使用的,静态分析包括仅基于从(多个)追踪113读取的数据来执行分析的存储器索引组件109。另一方面,动态分析可以使用基于(多个)这些追踪113从(多个)应用112的回放/仿真所生成/获得的数据。因此,图1A示出了仿真组件111也可以被加载到系统存储器103(即,仿真组件111’)中,并且(多个)应用112可以由仿真组件111’(即,(多个)应用112’)来仿真。存储器索引组件109’和仿真组件111’之间的双端箭头指示存储器索引组件109’可以请求由仿真组件111’的追踪仿真,并且仿真组件111’可以将该追踪仿真的结果提供到存储器索引组件109’。

如果存在,则追踪组件110可以将(多个)应用112中的一个或多个应用的执行记录或“追踪”到(多个)追踪113中。追踪组件110可以记录(多个)应用112的执行是否是直接在(多个)处理器102上执行,是否是经由所管理的运行时在(多个)处理器102上的执行。因此,图1A还示出了追踪组件110可以被加载到系统存储器103(即,追踪组件110’)中。追踪组件110’和(多个)追踪113’之间的箭头指示追踪组件111’可以将追踪数据记录到(多个)追踪113’中(其然后可以作为(多个)追踪113被持久化到持久性存储装置104)。

计算机系统101可以附加地或备选地从另一计算机系统(例如,使用(多个)网络设备105)接收(多个)追踪113中的一个或多个追踪。例如,图2图示了示例计算环境200,其中图1A的计算机系统101通过一个或多个网络201被连接至一个或多个其他计算机系统202(即,计算机系统202a至202n)。如示例200所示,每个计算机系统202包括追踪组件110和(多个)应用112。如此,计算机系统101可以通过(多个)网络201接收(多个)这些计算机系统202处的(多个)应用112中的一个或多个应用的(多次)先前执行的(多个)一个或多个追踪113。

要注意的是,虽然存储器索引组件109、追踪组件110和/或仿真组件111可能分别是独立的组件或应用,但它们可以备选地被集成到同一应用中(诸如,调试套件),或者可以被集成到另一软件组件中——诸如操作系统组件、管理程序、云结构等。如此,本领域技术人员还将了解,本发明可以在计算机系统101是其部分的云计算环境中实践。

在实施例中,存储器索引组件109、追踪组件110和/或仿真组件111对(多个)追踪113进行操作,该追踪113包括记录应用112的一个或多个线程的先前执行的高保真“位准确”追踪数据,并且其中追踪数据使(多个)这些线程的(多个)任何追踪部分能够将由仿真组件111向下仿真(即,“回放”)到单个指令(例如,机器代码指令、中间语言代码指令等)的粒度。如本文所使用的,“位准确”追踪是包括足够数据以使先前所执行的应用112的代码(例如,在计算机系统101处和/或在计算机系统202中的一个或多个计算机系统处)能够经由仿真组件111的仿真来回放的追踪,使得仿真组件111以与它先前所执行的基本相同的方式来模拟该代码的执行。追踪组件110可以使用多种方法来记录和存储位准确追踪。提供高性能水平和合理追踪大小的两个不同系列的方法现在被简要概括,但要了解的是,本文的实施例创建和操作使用其他方法所记录的追踪。附加地,优化可以被应用于这些系列的方法中的任一种方法,为了简洁起见,其在本文中未描述。

第一系列的方法被建立在对处理器指令(包括虚拟机“虚拟处理器”指令)通常落入以下三个类别中的一个类别的认识之上:(1)被标识为“非确定性”的指令,即不产生可预测的输出,因为它们的输出不完全由通用寄存器(例如,寄存器107a)或缓存(例如,(多个)缓存108)中的数据确定,(2)确定性指令,其输入不取决于存储器值(例如,它们仅取决于处理器寄存器值或代码本身中所限定的值),以及(3)确定性指令,其输入取决于从存储器读取值。因此,在一些实施例中,存储足够的状态数据以再现指令的执行可以通过解决以下问题来完成:(1)如何记录产生不完全由其输入确定的输出的非确定性指令,(2)如何取决于寄存器再现针对指令的输入寄存器的值,以及(3)如何取决于存储器读取再现针对指令的输入存储器的值。

在一些实施例中,(多个)第一方法将非确定性指令的执行记录到(多个)追踪113中,这些非确定性指令通过将这种指令的执行的旁效应存储到(多个)追踪113中来产生不完全由其输入确定的输出。如本文所使用的,“非确定性”指令可以包括不太常见的指令,这些指令(i)每次执行时都会产生非确定性输出(例如,英特尔处理器上的RDTSC,它写入自上次处理器复位到寄存器中以来的处理器循环数目),(ii)可能产生确定性输出,但是取决于在追踪记录期间未追踪的输入(例如,调试寄存器、定时器等),和/或(iii)产生处理器特定信息(例如,英特尔处理器上的CPUID,它将处理器特定数据写入寄存器)。存储这种指令的执行的旁效应可以包括例如存储由指令的执行而改变的寄存器值和/或存储器值。在一些架构中(诸如,来自英特尔)处理器特征(诸如,在虚拟机扩展(VMX)中所发现的那些特征)可以被用以捕捉用于将其旁效应记录到(多个)追踪113中的指令旁效应。

解决如何针对确定性指令(例如,其输入仅取决于处理器寄存器值)再现输入寄存器的值很简单,因为它们是(多个)先前指令的执行的输出。因此,用于记录追踪的(多个)第一方法因此可以减少记录整个系列处理器指令的执行,以存储可以被用以在系列开始时再现寄存器值的数据。在实施例中,(多个)追踪113甚至可能不需要存储在该系列中所执行的特定指令的记录或中间寄存器值。这是因为实际指令可从应用代码本身获得。因此,这些指令可以在回放期间被供应所记录的输入(即,所记录的初始寄存器值集),以与它们在追踪期间相同的方式执行。

最后,用于记录追踪的(多个)第一方法可以解决如何针对确定性指令再现输入存储器的值,该确定性指令的输入取决于通过将这些指令所消耗的存储器值(即,读取)记录到(多个)追踪113中的存储器值——无论指令所读取的值是如何被写入存储器的。换而言之,(多个)一些追踪113可能会记录存储器读取的值,但是不会记录存储器写入的值。例如,尽管值可能由当前线程、另一线程(包括内核,例如作为处理中断的部分)或硬件设备写入存储器,但执行读取的线程的指令的完全回放所需要仅是线程的指令读取的值。这是因为由线程读取的这些值(不必然是被写入存储器的所有值)命令了线程如何执行。

用于记录位准确追踪的第二系列的方法被建立在处理器(例如,处理器102)形成半封闭或准封闭系统的认识之上。例如,一旦针对过程的数据部分(即,代码数据和运行时应用数据)被加载到(多个)缓存108中,处理器102就可以自行运行——无需任何输入——作为针对时间突发的半封闭或准封闭系统。具体地,一旦(多个)缓存108被加载具有数据,处理单元107中的一个或多个处理单元使用存储在(多个)缓存的数据部分中的运行时数据并且使用寄存器107a来执行来自(多个)缓存108的代码部分的指令。当处理单元107需要一些信息流入时(例,如因为它正在执行、将执行或可能执行访问不在(多个)缓存108中的代码或运行时数据的指令),“缓存缺失”发生,并且该信息从系统存储器103被带入(多个)缓存108。然后处理单元107可以然后使用(多个)缓存108中的新信息继续执行,直到新信息再次被带入(多个)缓存108中(例如,由于另一缓存缺失或未缓存的读取)。因此,在第二系列的方法中,追踪组件110可以记录足够的数据,以能够在追踪的处理单元执行时将信息的流入再现到(多个)缓存108中。

图3图示了追踪300的一个示例,其可以对应于图1的(多个)追踪113中的一个或多个追踪,并且其可以根据前述追踪技术中的一种或多种技术来创建。在图3的示例中,追踪300包括一个或多个追踪数据流301。在图3中,三个追踪数据流301(即,追踪数据流301a至301c)被图示。在实施例中,每个追踪数据流301记录从应用112的代码所执行的不同线程的执行。例如,追踪数据流301a可以记录应用112的第一线程的执行,追踪数据流301b可以记录应用112的第二线程的执行,并且追踪数据流301c可以记录应用112的第三线程。如所示出的,每个追踪数据流301包括多个数据分组302(即,针对数据流301a的数据分组302a、针对数据数据流301b的数据分组302b和针对数据流301c的数据分组302c)。由于在每个数据分组302中所记录的特定数据可能会变化,所以它们被示出为具有不同的大小。通常,当使用时间旅行调试技术时,每个数据分组302至少记录作为应用112的该第一线程的部分所执行的一个或多个可执行指令的输入(例如,寄存器值、存储器值、缓存线数据等)。如所示出的,追踪数据流301还可以包括一个或多个关键帧303(例如,关键帧303a至303e),每个关键帧记录足够的信息,诸如寄存器和/或存储器值的快照,使包含关键帧的线程的先前执行能够由仿真组件111从关键帧303向前的点开始回放。此外,追踪数据流301可以包括一个或多个测序事件,如图3中编号为1至9的圆圈所示。虽然每个追踪数据流301通常独立地追踪给定线程,但是测序事件记录跨线程的可排序的事件的发生。例如,这些测序事件可以对应于线程交互的事件,诸如通过共享存储器、经由函数调用等。而为了简单起见,追踪数据流301中的事件顺序通过线程循环方式旋转,要了解的是,它们通常会以不太可预测的方式出现。

在实施例中,追踪113还可以包括被执行的实际代码。因此,在图3中,每个数据分组302被示出为包括非阴影数据输入部分304(即,针对数据分组302a的数据输入部分304a、针对数据分组302b的数据输入部分304b和针对数据分组302c的数据输入部分304c)和阴影代码部分305(即,针对数据分组302a的代码部分305a、针对数据分组302b的代码部分305b和针对数据分组302c的代码部分305c)。在实施例中,分组302中的代码部分305可以包括基于对应的数据输入来执行的可执行指令。然而,在其他实施例中,追踪113可以省略被执行的实际代码,而是依赖于对应用112的代码(例如,来自持久性存储装置104)的单独访问。在这些其他实施例中,每个数据分组可以例如指定适当的(多个)可执行指令的地址或偏移。如图所示,追踪113可以包括任何数目的附加数据流306(即,数据流306a至306n),其可以存储任何类型的附加追踪数据。该附加追踪数据可以包括例如索引数据,诸如偶尔的存储器快照、用于快速定位追踪数据流301中的存储器地址/值的反向查找数据结构等。

本文中的公开涉及将数据插入到在与使存储器单元值被记录到追踪中的事件(例如,存储器读取)相对应的执行时间之前的执行时间处暴露存储器单元值的追踪。这种数据可以被插入到追踪文件或追踪数据流中的任何位置,无论原始存储器单元值被记录在追踪文件或追踪数据流中的何处,只要这种数据使存储器单元值在追踪回放期间在执行时间之前被暴露即可,否则在该执行时间处存储器单元值已经被暴露。如此,当提及插入这种数据时,要了解的是,该数据被插入的时间/地点是相对于执行时间的,而不是数据分组在追踪文件或追踪数据流中的位置。附加地,本领域的普通技术人员将了解,将数据插入到暴露存储器单元值的追踪中可以涵盖以下中的一项或两者:(i)将存储器单元值直接插入到追踪中,或(ii)将还原和/或计算该存储器单元值的部件插入到追踪中(例如,通过插入该值的压缩版本;通过插入可以找到该值的位置的引用,诸如在另一追踪数据流中;通过插入如何可以计算值的引用等)。

图1B图示了提供图1A的存储器索引组件109的附加细节的示例100b。图1B中所描绘的存储器索引组件109包括表示存储器索引组件109可以根据本文所描述的各种实施例来实现的各种功能性的各种子组件(例如,追踪访问114、追踪解析115、追踪排序116、存储器分析117、输出118等)。要了解的是,所描绘的组件——包括其身份、子组件和布置——仅被呈现为辅助描述存储器索引组件109的各种实施例,并且这些组件/子组件不限于软件和/或硬件可以如何实现存储器索引组件109或其特定功能性的各种实施例。

追踪访问组件114访问(多个)追踪113中的至少一个追踪。这可能意味着从持久性存储装置104访问(多个)追踪113,和/或从另一计算机系统(例如,计算机系统202中的一个或多个计算机系统)访问(多个)追踪113。在实施例中,访问追踪113使该追踪至少部分地被加载到系统存储器103中(即,如(多个)追踪113’所示)。

追踪解析组件115解析所访问的(多个)追踪113,以标识所追踪的执行中的至少一个或多个片段。因此,图1B示出了追踪解析组件115可以包括片段标识组件115a。如本文使用的,“片段”是在同一线程上执行的一个或多个连续指令,而没有被任何其他线程中断。在实施例中,片段可以基于测序事件来限定。例如,片段可以是在测序事件之间所执行的连续指令集,具有在追踪开始处的关键帧充当测序事件。

为了图示,图4A图示了示例时序图400a,其示出了三个线程的执行的三个时间线401(即,时间线401a至401c),诸如追踪到图3的数据流301中的三个线程。而为了简单起见,时序图400a中的线程以循环方式执行,但要了解的是,它们通常会以不太可预测的方式执行。如所示出的,这些时间线401中的每个时间线都以关键帧402(即,关键帧402a至402c)开始,其可以例如对应于图3的关键帧303a、303c和303d。这些时间线401中的每个时间线还包括三个测序事件403(即,测序事件403a至403i),诸如图3的测序事件1至9。例如,时间线401a上的测序事件403a、403d和403g可以对应于测序事件1、4和7;时间线401b上的测序事件403b、403e和403h可以对应于测序事件2、5和8;并且时间线401c上的测序事件403c、403f和403i可以对应于测序事件3、6和9。

在图4A的上下文内,时间线401a上的片段可以包括第一片段,该第一片段包括在关键帧402a和测序事件403a之间所执行的代码(箭头404a),第二片段,该第二片段包括在测序事件403a和测序事件403d之间所执行的代码(箭头404d),以及第三片段,该第三片段包括在测序事件403d和测序事件403g之间所执行的代码(箭头404g)。类似地,时间线401b上的片段可以包括关键帧402b和测序事件403b之间的第一片段(箭头404b)、测序事件403b和测序事件403e之间的第二片段(箭头404e)以及测序事件403e和测序事件403h之间的第三片段(箭头404h);时间线401c上的片段可以包括关键帧402c和测序事件403c之间的第一片段(箭头404c)、测序事件403c和测序事件403f之间的第二片段(箭头404f)以及测序事件403f和测序事件403i之间的第三片段(箭头404i)。

追踪解析组件115还可以解析所访问的(多个)追踪113,以标识所访问的(多个)追踪113中的一个或多个间隙。因此,图1B示出了追踪解析组件115可以包括间隙标识组件115b。通常,间隙是针对一个或多个所追踪的线程的追踪数据存在不连续或缺少追踪数据的任何执行时间段。在实施例中,间隙可以有两种形式:大间隙和小间隙。在实施例中,当针对该线程的追踪停止未知时间段时,该线程的追踪中出现大间隙。例如,这可能是因为线程的记录暂停了未知时间段,或者因为所记录的线程被终止并且记录稍后在不同线程上恢复。在实施例中,当线程的记录针对已知目的停止/暂停时,会出现小间隙。例如,当线程进行函数调用,该函数调用暂停该线程的执行以执行非所追踪的线程时,可能会出现小间隙。

为了图示这些概念,图5A图示了与图4A的时序图400a类似的示例时序图500a,但是其包括大间隙和小间隙的示例。作为针对暂停未知时间段的线程的记录而导致的大间隙的示例,假设在图5A中,对应于时间线501b的线程负责针对追踪应用绘制/渲染用户界面窗口112。如果追踪组件110由于用户界面窗口被关闭而停止记录该线程,则追踪组件110不知道稍后用户界面将何时被打开(并且追踪恢复)。在实施例中,在窗口被关闭的时间和窗口稍后被打开的时间(和追踪恢复)之间发生的追踪该线程的间隙可以被认为是大间隙。这个大间隙在图5A中被表示为表示时间线501b的线中的测序事件503b和503e之间的间隙。大间隙的交替示例(未示出)可以是针对对应于时间线501a至501a的线程中的每个线程的记录所关闭的时间段。在该时间段期间,时间线501中的每个时间线501都会存在大间隙。

作为小间隙的示例,假设在图5A中,对应于时间线501a的线程负责解析文件数据。如果该线程调用内核函数以打开文件,并且处置该请求的内核线程没有被追踪,则在实施例中,进行内核调用的所追踪的线程和返回到所追踪的线程的内核调用之间的时间段可以被认为是小间隙。该小间隙在图5A中被表示为时间线501a中的测序事件503d和503g之间的虚线。

基于追踪解析组件115已经在所访问的(多个)追踪113中标识出片段,追踪排序组件116可以标识这些片段当中的排序。这是片段可以由仿真组件111仿真的排序。在实施例中,这可以是部分排序或总排序。在总排序中,(多个)追踪113中的每个所记录的指令相对于(多个)追踪113中的其他指令具有所限定的顺序。在部分排序中,该限制可以被放宽。例如,由于包括关键帧,并且由于两个或多个片段在其存储器访问中没有叠加,这些片段可以由仿真组件111并行地仿真是有可能的。图4B图示了图4A中的片段的一种潜在总排序的示例400b。虽然可以以各种方式对追踪片段排序,示例400b基于测序号顺序对片段进行排序。例如,在图4B中,追踪片段被示出为405a,然后是405b,然后是405c,依此类推到片段405i。这遵循由图4A中的箭头所示出的排序,从关键帧402a开始。例如,图4B中的片段405a对应于在图4A中的关键帧402a和测序事件403a之间所执行的代码片段(箭头404a)。在图4A中从测序事件403a到关键帧402b的虚线箭头之后,图4B中的片段405b对应于在图4A中的关键帧402b和测序事件403b之间所执行的代码片段(箭头404b)。在图4A中从测序事件403b到关键帧402c的虚线箭头之后,图4B中的片段405c对应于在图4A中的关键帧402c和测序事件403c之间所执行的代码片段(箭头404c)。在图4A中从测序事件403c到测序事件403a的虚线箭头之后,图4B中的片段405d对应于在图4A中的测序事件403a和测序事件403d之间所执行的代码片段(箭头404d)。这种模式继续贯穿图4A。

如果间隙由间隙标识组件115b所标识,则追踪排序组件116还可以标识这些间隙在有序片段当中的排序。图5B图示了图5A中的片段和间隙的一种潜在总排序的示例500b。虽然可以以各种方式对追踪片段和间隙排序,示例500b还基于测序号顺序对片段和间隙进行排序。例如,在图5B中,追踪片段被示出为505a,然后是505b,然后是505c,依此类推到片段505i。这包括对大间隙(即,505e)和小间隙(即,505g)进行排序。类似于图4B,该排序遵循由图5A中的箭头所示出的排序,从关键帧502a开始。

利用由追踪解析组件115标识的片段和间隙(如果有),并且利用由追踪排序组件116标识的这些片段和间隙(如果有)的至少部分排序,存储器分析组件117可以执行片段内分析、片段间分析或间隙分析中的一项或多项,以标识可以在追踪仿真期间、在比这些存储器单元值出现在(多个)追踪113中的时间更早的时间处所呈现的存储器单元值。因此,在图1B中,存储器分析组件117包括片段内分析组件117a、片段间分析组件117b和间隙分析组件117c。

片段内分析组件117a单独分析片段,以确定“兼容的”(多个)存储器单元值是否可以被“预取”并且在片段的回放/仿真期间、比(多个)这些存储器单元值出现在针对该片段的追踪数据中的点更早地呈现在片段中。在实施例中,片段内分析组件117a可以通过确定该值是否与片段中的存储器单元的其他先前已知值一致来将给定的存储器单元值标识为与片段中的其他值“兼容”。例如,如果存储器单元值是来自片段内的存储器单元的第一读取的值,则该值将显然与片段中的存储器单元的先前已知值兼容,因为片段中不存在针对存储器单元的先前已知值。另一方面,如果存储器单元值是来自片段内的存储器单元的后续读取的值,则如果该值与片段中的针对存储器单元的先前已知值相匹配,则该值是兼容的。由于从存储器单元读取或写入存储器单元,先前已知值可以是已知的。因此,例如如果(i)片段中的第一读取从单元中获得值“A”,(ii)片段中的后续写入将值“B”写入该单元,以及(iii)主题后续读取从单元中获得值“B”,则从后续读取中获得的值将是兼容的。然而,如果后续读取从单元中获得值“B”以外的任何内容,则从后续读取中获得的值将不兼容,因为该单元已被片段以外的一些内容修改(例如,另一线程、硬件直接存储器访问(DMA)等)。因此,例如,如果后续读取从单元获得值“C”,则该值将与先前两个值不兼容。

值得注意的是,在存在来自存储器单元的多个读取和/或写入的场景中,如果这些读取/写入兼容,则可以通过仅预取存储器单元的初始值来“预取”。例如,在先前示例中,只有值“A”需要被预取;值“B”的写入和值“B”的读取可以经由仿真从存储器单元初始读取之后的指令再现。在后续读取获得值“C”的第二示例中,可能可以预取由第一读取获得的值“A”,但不能预取由后续读取获得的值“C”。

为了展示在片段内预取的概念,图6A和6B图示了与执行字符串复制的函数的执行相对应的示例时序图600a/600b。图6A和6B假定整个函数作为单个片段执行(即,不存在中断其执行的其他线程,并且其执行中没有间隙)。该函数包括以下步骤:

1.设置函数堆栈

2.开始环路

a.复制单个字符

b.将字符与空终止符进行比较以退出

3.结束环路

4.返回

时序图600a展示了——针对现场调试和时间旅行调试两者——对应于输入字符串的存储器单元值何时可用于读取(即,可见),对应于输出字符串的未初始化的存储器单元何时可见,以及数据何时被写入与输出字符串相对应的存储器单元的示例。例如,时序图600a示出了,在现场调试期间,在以上函数中的步骤一中(即,当函数堆栈被设置时),对应于整个输入字符串的存储器单元值可以可用于读取,并且对应于整个输出字符串的未初始化的存储器单元可以是可见的。相比之下,时序图600a还示出了,在时间旅行调试期间,对应于输入字符串的存储器单元值可能只会随着它们在环路的步骤2a中读取而逐渐变得可见(例如当存储这些值的(多个)数据分组出现在追踪中时),并且仅与在环路的步骤2a中写入这些存储器单元相关,与输出字符串相对应的未初始化的存储器单元可以变得可见。

值得注意的是,在时序图600a/600b中(以及在后续时序图中),时间旅行调试期间未初始化的存储器单元值的可见性取决于代码对存储器单元上所执行的第一动作是写入时追踪中存在的那些值。因此,当追踪组件110捕获对先前未记录的存储器单元的写入作为来自存储器单元的读取加上对存储器单元的写入(例如,代替执行写入而不记录任何内容)时,这些未初始化的值可能可用。如此,在时间旅行调试期间未初始化的存储器单元的值的可用性取决于它们在追踪中,但它们的可用性(或其缺少)不会影响追踪回放期间的正确性。例如,如果未初始化的存储器单元的值在追踪中不可用,则调试器可以将该未知数据显示为问号、随机值、所限定的模式等。

在实施例中,片段内分析组件117a可以确定对应于在步骤2a中在时间旅行调试期间读取的输入字符串的存储器单元值与片段中的那些存储器单元的其他值兼容,并且因此确定这些存储器单元值可以被“预取”并且在仿真/回放期间在片段中较早的点(诸如,片段的开始)可见。此外,片段内分析组件117a可以确定对应于未初始化的存储器的存储器单元值与片段中的那些存储器单元的其他值兼容,并且因此确定该未初始化的存储器也可以在仿真/回放期间在片段中较早的点处(诸如,片段的开始)可见。因此,转到图6B,时序图600b示出了在时间旅行调试期间(即,在函数的步骤1期间,就像在现场调试期间一样),这些存储器单元可以在片段的开始处可见。具体地,与输入字符串相关的各种虚线箭头和虚线框示出了,与读取相对应的存储器单元值可以从追踪中的自然时间位置预取,并且在片段的回放/仿真期间在片段的开始可见(即,步骤1);与输出字符串相关的各种箭头和虚线框还示出了,在片段的回放/仿真期间,未初始化的存储器单元值也可能在片段的开始(即,步骤1)可见。

图7A和7B提供了在片段内预取值的另一示例。具体地,图7A和7B图示了示例时序图700a/700b,其对应于基于正则表达式(RegEx)匹配将字符串拆分为段的函数的执行。值得注意的是,在图6A和6B中定义的各种阴影的含义适用于图7A和7B。再次,图7A和7B假定整个函数作为单个片段执行。该函数包括以下步骤:

1.设置函数堆栈

2.针对结果列表分配存储器

3.调用函数以编译正则表达式

4.开始环路

a.调用函数以找到字符串中的下一RegEx匹配的位置

b.调用函数以从之前所找到的子字符串匹配中创建新字符串

c.将字符串追加至结果

5.结束环路

6.准备返回列表

7.返回

与时序图600a类似,时序图700a展示了——针对现场调试和时间旅行调试两者——对应于读取和未初始化的存储器的存储器单元值何时可能可见的示例。与时序图600a一样,时序图700a示出了,在现场调试期间,将由函数读取的存储器单元值(即,输入正则表达式和输入字符串)以及将由函数写入的未初始化的存储器单元(即,结果列表、所编译的正则表达式和子字符串)在函数入口处(即,在以上步骤1中)可见。而且类似于时序图600a,时序图700a还示出了,在时间旅行调试期间,对应于读取(即,输入正则表达式和输入字符串)的存储器单元值可能仅随着它们在步骤3和4a中被读取而逐渐变得可见,并且与写入(即,结果列表、所编译的正则表达式和子字符串)相对应的未初始化的存储器单元可能仅与在步骤2、3、4b和4c中写入这些存储器单元相关中变得可见。转到图7B,时序图700b示出了在时间旅行调试期间(例如,在片段的开始)在函数的步骤1期间——就像在现场调试期间一样,这些存储器单元可能能够在片段中更早地变得可见。例如,图7B中的各种虚线箭头和虚线框示出了,与读取相对应的存储器单元值可以从追踪中的其自然时间位置来预取,并且在片段的回放/仿真期间在片段的开始(例如,在步骤1中)变得可见。图7B还示出了在片段的回放/仿真期间,未初始化的存储器单元也可能在片段的开始(例如,在步骤1中)变得可见,尽管图7B没有经由虚线箭头或虚线框明确示出该未初始化的存储器的移动。

虽然片段内分析组件117a标识出可以在片段中比它们在片段的追踪中出现的位置更早地预取和暴露的存储器单元值,但是片段间分析组件117b标识出可以跨片段被推送的存储器单元值。在实施例中,片段间分析组件117b可以在片段内分析组件117a对它们已经进行操作之后对片段进行操作,尽管片段间分析组件117b也可能独立于片段内分析组件117a而操作。

片段间分析组件117b通过确定一个片段中的给定存储器单元值是否与一个或多个先前片段兼容来操作。虽然片段内分析组件117a确定给定存储器单元值与先前在同一片段中所看到的存储器单元的值的片段内兼容性,但片段间分析组件117b确定给定存储器单元值与在一个或多个先前片段中所看到的存储器值的兼容性。因此,类似于片段内兼容性分析,片段间兼容性分析还确定存储器单元值与先前(在执行时间中)所看到的值的兼容性。在实施例中,片段间分析组件117b可以通过确定先前片段是否接触该存储器单元来将特定片段中的存储器单元值标识为与邻接的先前片段“兼容”。如果先前片段未接触该存储器单元,那么该值与先前片段兼容,并且可以跨先前片段推送(例如,它可以在先前片段的开始处暴露)。另一方面,如果先前片段确实接触该存储器单元,那么仅当先前片段末端的存储器单元的值与特定片段开始处的存储器单元的值相同时,该存储器单元值才与先前片段兼容。在实施例中,片段间分析组件117b可以确定存储器单元值与多个先前片段兼容。因此,可能可以跨分别与存储器单元值兼容的一系列片段来推送存储器单元值。

为了展示跨片段推送存储器单元值的概念,图8A至8D图示了与结合图7A和7B讨论的函数的执行(即,其基于正则表达式匹配将字符串拆分为多段)相对应的示例时序图800a至800d。值得注意的是,在图6A和6B中定义的各种阴影的含义适用于图8A至8D。与图7A和7B不同,在图8A至8D中,该函数不作为单个片段执行。相反,如步骤“F”处所示,该函数的执行被没有重叠存储器访问的另一所追踪的线程中断(由线程追踪确定)。因此,在图8A至图8D中,存在三个片段——包括执行直到步骤F的函数(即,步骤1到步骤4b的第二实例)的第一片段,包括步骤F本身的第二片段,以及包括在步骤F之后执行函数(即,步骤4C的第二实例到步骤7)的第三片段。

时序图800a展示了——针对现场调试和时间旅行调试两者——对应于读取和未初始化的存储器的存储器单元值何时可能可见的示例。时序图800a与时序图700a相同,除了在步骤F中存在片段之外。因此,时序图800a中的存储器可见性对于现场调试和时间旅行调试是相同的,因为那些可见性是结合图7A描述的。

转到图8B,时序图800b展示了,针对时间旅行调试,片段内分析组件117a可以标识可以在每个片段的开始被暴露的兼容存储器单元值。例如,图8B中的虚线箭头和虚线框示出了,第一片段中的存储器单元值(即,对应于来自输入正则表达式和输入字符串的读取)可以从追踪中的自然时间位置预取,并且在第一片段的回放/仿真期间在第一片段的开始处(例如,在步骤1中)变得可见。类似地,图8B中的虚线箭头和虚线框还示出了,第三片段中的存储器单元值(即,对应于来自输入字符串的读取)可以从追踪中的自然时间位置预取,并且在第三片段的回放/仿真期间在第三片段的开始处(例如,在该片段中在步骤4C的第一实例中)变得可见。尽管图8B没有经由虚线箭头或虚线框明确示出该未初始化的存储器的移动,图8B还示出了在这些片段的回放/仿真期间,未初始化的存储器单元也可能在这些片段的开始(例如,在针对第一片段的步骤1中以及在第三片段的步骤4C中)变得可见。

转到图8C,时序图800c展示了针对时间旅行调试,片段间分析组件117b还可以确定在第三片段的开始处(即,现在在第三片段的步骤4c中)的预取存储器单元值与第二片段(其没有重叠的存储器访问)兼容,因此可以跨第二片段推送并且在第二片段之前暴露。附加地,时序图800c展示了,因为这些存储器单元值也与第一片段兼容,所以它们可以被推送到第一片段的开始处(即,推送到步骤1)。尽管图8C没有经由虚线箭头或虚线框明确示出该未初始化存储器的移动,图8C还示出了未初始化的存储器单元也可以跨第二片段被推送到第一片段的开始。

转到图8D,时序图800d中的虚线箭头和虚线框示出了与来自输入正则表达式和输入字符串的读取相对应的存储器单元值的总体移动。这包括从第一片段内到第一片段开始的存储器单元值的片段内移动以及从第三片段跨第二片段到第一片段开始的存储器单元值的片段间移动。

在实施例中,追踪113可以包括全部或部分存储器快照。如果这些存在,则存储器分析组件117可以将存储器快照视为只是一系列读取(即,来自作为快照的部分的存储器单元的读取)的片段。因此,片段间分析组件117b可以通过将存储器快照之后的片段与受存储器快照影响的存储器单元进行比较来确定给定存储器单元值在该片段中的兼容性。如果兼容,则片段分析组件117b可以确定存储器单元值可以跨存储器快照来推送。

间隙分析组件117c确定存储器单元值是否可以在追踪记录中的间隙上推送。类似于跨片段来推送存储器单元值,这涉及间隙分析组件117c确定存储器单元值是否与间隙兼容。虽然这种分析对于片段来说相当简单(即,因为存在针对片段的追踪数据),但缺少关于间隙期间发生的事情的信息可能会使分析复杂化。在实施例中,由于这种信息的缺少,间隙分析组件117c执行间隙的启发式分析中的一个或多个启发式分析,以推断间隙可能接触了什么存储器。

如所提及的,存在两个主要类别的间隙:大间隙,其中针对线程的追踪停止而不知道——在追踪停止时——何时将再次恢复,以及小间隙,其中线程的记录针对已知目的而被暂停。在一些实施例中,间隙分析组件117c认为大间隙总是不兼容的,因此它不试图跨大间隙来推送存储器单元值。然而,在其他实施例中,间隙分析组件117c可能使用在大间隙期间所执行的非追踪代码的“域特定”知识来跨大间隙来推送存储器单元值。这种域特定知识的示例在下面讨论。针对小间隙,间隙分析组件117c可以执行一种或多种不同类型的启发式分析。五种示例启发法在本文中提供,尽管间隙分析组件117c不被限于使用这些类型的分析,并且甚至不需要支持这些类型的分析中的每种分析。

在第一示例启发法中,本文中被称为“单个线移动分析”,是一种相当幼稚的启发法,它假定小间隙不会修改存储器,并且因此存储器单元值可以跨间隙来推送。由于该启发法是在不依赖对间隙潜在行为的具体知识的情况下针对间隙做出兼容性决策,因此该启发法可能会使一些存储器单元值跨间隙被错误地推送。因此,在时间旅行调试期间,存储器单元的值可能会在它实际有效之前实际上变得可见。然而,在许多场景中,这样做可能不会引起明显的混乱。例如,暴露存储器单元的变量可能会超出范围,并且因此难以达到,或者存储器单元值可能只是提前替换了未初始化的数据。值得注意的是,在现场调试期间,在未初始化的存储器地点(例如,在与堆栈相对应的存储器地点中,由于这些存储器地点被先前的函数调用写入)中,看到看起来像有效数据的情况是相当普遍的;使未初始化的数据比其本应该看起来对用户类似更早地可用。

在第二示例启发法中,本文被称为“基于注解的分析”,间隙分析组件117c利用与在间隙期间执行的非追踪代码相关联的元数据,以确定是否非追踪触摸或可能触摸、针对其兼容性正在被分析的一个或多个存储器单元。示例元数据包括源代码注解语言(SAL)注解、协议等。作为第一示例,注解可以指示哪些(多个)存储器缓冲区作为输入被在间隙期间所执行的函数接收,并且哪些存储器缓冲区被用作函数的输出。在这种情况下,如果(多个)主题存储器单元是输出缓冲区的部分,则间隙分析组件117c可以确定那些存储器单元与间隙不兼容。备选地,如果(多个)主题存储器单元不是输出缓冲区的一部分,则间隙分析组件117c可以确定那些存储器单元与间隙兼容。作为第二示例,在间隙期间所执行的方法可能被注解为不变方法,通过协议,该方法将要求存储器单元值保持恒定。例如,给定下面的分类Foo,

如果在间隙期间对非追踪代码的调用是对成员函数Bar()的调用,并且如果主题存储器单元对应于AlwaysZero或OtherValue,则协议可以被用以确定主题存储器单元值与间隙兼容。作为第三示例,对在间隙期间所执行的函数的后置条件注解可能要求对应于主题存储器单元的缓冲区在函数退出时具有与函数进入时相同的值。因此,后置条件注解将被用以确定主题存储器单元值与间隙兼容。作为第四示例,在间隙期间所执行的非追踪代码可能被注解为没有旁效应(即,在API级别没有外部可见的旁效应),并且因此该注解可以被用以当确定存储器单元值不在非追踪代码内部时,确定主题存储器单元值与间隙兼容。在第三示例启发法中,本文被称为“基于分配的分析”,间隙分析组件117c确定兼容性正在被分析的(多个)存储器单元是否是某个所分配的存储器缓冲区的部分(例如,数据结构的部分)。如果是,则间隙分析组件117c可以将存储器缓冲区视为单个单元,并且确定缓冲区(作为整体)与间隙的兼容性。例如,假设不存在第一存储器单元是否与间隙兼容的具体知识,但是存在第二存储器单元是否与间隙兼容的知识。如果间隙分析组件117c确定第一存储器单元和第二存储器单元是同一缓冲区的部分,那么第一存储器单元可以被确定为与间隙具有与第二存储器单元相同的兼容性。因此,例如如果间隙分析组件117c确定第二存储器单元与间隙兼容(例如,基于另一启发法),则它可能确定第一存储器单元也与间隙兼容。备选地,如果间隙分析组件117c确定第二存储器单元与间隙不兼容,则它可以确定第一存储器单元也与间隙不兼容。值得注意的是,如果分配未被明确观察到,则一些实施例可以将指向存储器缓冲区的指针的第一次出现视为分配。

在第四示例启发法中,本文被称为“基于分配为注解的分析”,如果在间隙期间执行的函数将指向包括存储器单元的、所分配的缓冲区的指针取为参数,则间隙分析组件117c确定存储器单元与间隙不兼容。更一般地,当该第四启发法与第三启发法组合时(即,基于分配的分析),间隙分析组件117c可以确定整个缓冲区与间隙不兼容。该启发法基于以下观察:将所分配的缓冲区作为参数的间隙比未将所分配的缓冲区作为参数的间隙更有可能修改缓冲区。因此,例如如果存在本可以修改缓冲区的两个或多个间隙,并且其中一个间隙将缓冲区作为参数,而(多个)另一个没有,则更有可能将缓冲区作为参数的是修改缓冲区的间隙,而不是(多个)其他间隙修改缓冲区。因此,间隙分析组件117c可以确定缓冲区中的存储器单元与将缓冲区作为参数的间隙不兼容。作为该第四启发法的使用示例,假设有N个间隙、这些间隙周围的N+1个片段集(包括第一间隙之前和最后一个间隙之后的片段集)以及针对与间隙的兼容性正在被分析的两个缓冲区。在这些缓冲区中,第一个缓冲区在第一片段和最后一个片段之间是兼容的,而第二个缓冲区则不是。因为第一缓冲区与所有片段兼容,所以间隙分析组件117c可以确定它也与所有间隙兼容,并且因此可以跨所有间隙被向前推送(例如,推送到第一片段)。针对第二缓冲区,间隙分析组件117c可以确定哪些(多个)间隙将第二缓冲区作为参数,并且如果只存在一个间隙,那么间隙分析组件117c可以确定第二缓冲区与该间隙之后的任何间隙兼容,但是与该间隙之前的任何间隙不兼容。即使通过值,第二缓冲区未在追踪中看到,直到最后一个片段,由中间片段使用指向该缓冲区的指针也可以作为该中间片段可能修改了缓冲区的线索。

在第五示例启发法中,本文被称为“域特定知识分析”,间隙分析组件117c使用在间隙期间所执行的非追踪代码的一些其他知识,以确定主题存储器单元值是否与间隙兼容。如上面提到的,这种启发法还可以被用以确定与大间隙的兼容性。作为示例,存储库代码的存储器往往不会改变(例如,因为代码通常是只读的)。因此,间隙分析组件117c可以确定对应于该所加载的库代码的存储器单元可以被允许跨间隙(例如,在库加载和卸载事件之间)。作为另一示例,通常理解堆栈如何在给定处理器架构和操作系统上表现。使用这种理解,间隙分析组件117c可以确定当前堆栈指针下方的存储器单元与间隙不兼容。作为另一示例,间隙分析组件117c可以确定非追踪代码对应于纯函数的执行(即,其中针对相同的自变量,函数的返回值是相同的,并且其中函数的评估没有旁效应),并且因此主题存储器单元值与间隙兼容。作为又一示例,间隙分析组件117c可以确定在间隙期间所执行的非追踪代码使用.NET框架的公共语言运行时(CLR),其包括仅追加的一些形式的元数据。由于元数据是仅追加的,由元数据所使用的任何存储器单元通常只被写入一次,并且因此间隙分析组件117c可以确定这些存储器单元与间隙兼容(即,因为它们的值通常不在最初写入时改变)。

为了展示跨间隙推送存储器单元值的概念,图9A至图9E图示了通常与结合图7A和7B所讨论的函数的执行(即,其基于正则表达式匹配将字符串拆分为多段)相对应的示例时序图900a至900e。值得注意的是,在图6A和图6B中定义的各种阴影的含义适用于图9A至图9E。与图8A至图8D类似,在图9A至图9E中,该函数也不作为单个片段来执行。相反,在步骤3(即,调用函数以编译正则表达式)中,被调用的函数未被追踪——导致追踪间隙。因此,在图9A至图9E中,有两个片段被小间隙分离。这些片段包括第一片段(包括步骤1和2的执行)和第二片段(包括步骤4a至7的执行)。这些片段在步骤3中被小间隙分离。

时序图900a展示了——针对现场调试和时间旅行调试两者——对应于读取和未初始化的存储器的存储器单元值何时可能可见的示例。时序图900a类似于时序图700a,除了在步骤3中存在间隙之外。因此,时序图900a中的存储器可见性类似于结合图7A描述的那些可见性的现场调试和时间旅行调试,除了输入正则表达式无法在时间旅行调试期间被看到(因为它被间隙消耗了),并且所编译的正则表达式(它是间隙的输出,并且因此现在是读取而不是写入)在用于现场调试的步骤4a的第一实例处完全可见,但仅针对时间旅行调试逐渐可见(即,步骤4a的第一实例和第三实例)。

转到图9B,时序图900b展示了针对时间旅行调试的片段内分析组件117a可以标识可以在每个片段的开始所暴露的兼容存储器单元值。例如,图9B中的虚线箭头和虚线框示出了,第二片段中的存储器单元值(即,对应于来自输入字符串和所编译的正则表达式的读取)可以从追踪中其自然时间位置预取,并且在第二片段的回放/仿真期间在第二片段的开始处(例如,在步骤4a的第一实例中)变得可见。图9B还示出了,在时间旅行调试期间,未初始化的存储器单元也可以在第一片段和第二片段的开始处(例如,在针对结果列表的第一片段的步骤1中,以及在针对子字符串的第二片段的步骤4A的第一实例中)变得可见,尽管图9B没有经由虚线箭头或虚线框明确示出该未初始化存储器的移动。

图9C图示了时序图900c,该时序图基于单个线移动分析(即,以上的第一启发法)在时序图900b之后展示了间隙交叉。使用该分析,简单地推测存储器单元值与步骤3中的间隙兼容。因此,图9C中的虚线箭头和虚线框示出了,第二片段中的存储器单元值(即,对应于来自输入字符串和所编译的正则表达式的读取)可以跨间隙,以便在第一片段的回放/仿真期间在第一片段的开始处(例如,在步骤1中)可见。值得注意的是,这意味着所编译的正则表达式实际上应该在生成所编译的正则表达式的函数被调用之前是可见的。然而,这样做没有什么害处,因为在间隙之后没有符号能够读取该值。因此,虽然用户在查看原始存储器时可以看到该值,但不会有描述该变量/存储器的符号。图9C还示出了在时间旅行调试期间,未初始化的存储器单元也可能在第一片段的开始(例如,在步骤1中)变得可见,尽管图9C没有经由虚线箭头或虚线框明确示出该未初始化的存储器的移动。

图9D图示了时序图900d,该时序图基于基于注解的分析(即,以上第二启发法)在时序图900b之后展示了间隙交叉。此处,间隙分析组件117c可以利用SAL注解、协议等以确定间隙将写入针对所编译的正则表达式所分配的缓冲区。因此,该缓冲区中的存储器单元值与间隙不兼容。然而,与输入字符串相关联的存储器单元值是兼容的。因此,图9D中的虚线箭头和虚线框示出了,在第一片段的回放/仿真期间,对应于输入字符串的第二片段中的存储器单元值可以跨间隙,从而在第一片段的开始(例如,在步骤1中)可见。然而,要注意的是,与所编译的正则表达式相对应的第二片段中的存储器单元值不能。图9D还示出了在时间旅行调试期间,对应于子字符串的未初始化的存储器单元也可能与间隙兼容并且在第一片段的开始处(例如,在步骤1中)变得可见,尽管图9C没有经由虚线箭头或虚线框明确示出该未初始化的存储器的移动。

图9E图示了时序图900e,该时序图基于基于分配的分析(即,以上第三启发法)在时序图900b之后展示了间隙交叉。此处,间隙分析组件117c可能观察到针对所编译的正则表达式的缓冲区和用于输入字符串的缓冲区在间隙之前被分配,因此将这两个缓冲区整体标识为与间隙兼容。因此,图9E中的虚线箭头和虚线框示出了,在第一片段的回放/仿真期间,对应于所编译的正则表达式和输入字符串的第二片段中的存储器单元值可以跨间隙,从而在第一片段的开始处(例如,在步骤1中)可见。图9E还示出了,在时间旅行调试期间,对应于子字符串的未初始化的存储器单元可能与间隙不兼容(即,因为它们是在间隙之后分配的),因此它们不会跨越间隙。

返回到图1B,输出组件118基于存储器分析组件117的分析来生成数据输出。这可以包括例如生成补充所访问的(多个)追踪113的索引数据(例如,作为数据流306中的一个或多个数据流),以指示哪些存储器值可以早于记录存储器读取的数据分组暴露,重写所访问的(多个)追踪113中的一个或多个追踪以重新定位追踪中的存储器单元值,和/或写入包括重新定位的存储器单元值的全新追踪113。因此,在图1B中,输出组件118被示出为潜在地包括索引数据生成组件118a、追踪修改/重写组件118b和/或追踪生成组件118c。

特别关注追踪修改/重写组件118b和追踪生成组件118c,要注意的是,包括重新定位的存储器值的重写或新生成的追踪可以比原始访问追踪113占用更少的存储空间。例如,假设在给定片段内,存在来自给定存储器单元的多次读取。反过来,这可能意味着存在记录了针对该存储器单元的一个或多个值的多个数据分组。如果这些值在片段内兼容,则存储器单元的初始值可能会被记录在片段的开始,并且其他数据分组可能能够被丢弃。这同样跨片段适用。例如,如果存在与存储器单元值兼容的一系列片段,则该存储器单元值可能会被推送到针对该系列片段的开始,并且对应于来自该存储器单元的读取的数据分组可能能够从片段丢弃。因此,追踪修改/重写组件118b和/或追踪生成组件118c可以导致更小的追踪,其转而可能能够更有效地被仿真。

图10图示了用于生成数据的示例方法1000的流程图,该数据用于在追踪回放期间使存储器单元值在先于对应于使存储器单元值被记录到追踪中的执行时间的执行时间处被暴露。方法1000现在在图1A至图9E及其对应描述的上下文内描述。

如图所示,方法1000包括访问追踪的行动1001。在一些实现中,行动1001包括访问记录一个或多个线程的先前执行的追踪。例如,参照图1A和图1B,追踪访问组件114可以访问(多个)追踪113中的一个或多个追踪,其记录(多个)应用112中的一个或多个应用的先前执行。图3图示了包括多个追踪数据流301的追踪300的一个示例,每个追踪数据流都记录执行线程。

方法1000还包括标识记录追踪片段的行动1002。在一些实现中,行动1002包括标识记录一个或多个线程的先前执行的追踪内的多个追踪片段,每个追踪片段记录多个可执行指令在一个或多个线程的对应线程上的不间断连续执行,多个追踪片段至少包括第一追踪片段和第二追踪片段。例如,片段标识组件115a可以标识(多个)所访问的追踪113中的片段。例如,图3和4A图示了图3的追踪300可以基于测序号被划分为片段。

方法1000还可以包括标识间隙的行动1003。在一些实现中,行动1003包括标识由第一追踪片段对非追踪代码的调用所引起的追踪记录中的间隙。因此,第一追踪片段记录第一线程的第一可执行指令的执行,并且第二追踪片段记录第一线程的第二可执行指令的执行,并且其中第一追踪片段和第二追踪片段由间隙分离。例如,间隙标识组件115b可以标识(多个)访问追踪113中的间隙。例如,图5A示出了两种类型的间隙——箭头504e处的大间隙,其中针对第二线程的追踪停止了未知时间段;以及箭头504g处的小间隙,其中第一线程的记录出于已知目的暂停。

如图所示,行动1002和1003可以被并行执行。然而,在实现中,它们可以被备选地串行执行(以任一顺序)。

方法1000还包括对追踪进行排序的行动1004。在一些实现中,行动1004包括至少确定多个追踪片段中的部分排序,包括确定第一追踪片段可以在第二追踪片段之前排序。例如,追踪排序组件116可以标识在行动1002和1003中所标识的片段和间隙(如果有的话)的完整或部分排序。例如,图4B示出了图4A中的追踪片段可以基于测序事件进行排序,并且图5B示出了图5A中的追踪片段和间隙可以基于测序事件进行排序。因此,在行动1004中,第一追踪片段可以由第一测序事件约束,并且第二追踪片段可以由第二测序事件约束,并且确定第一追踪片段可以在第二追踪片段之前被排序,该第二追踪片段可以基于确定第一测序事件在第二测序事件之前发生。

方法1000还包括标识存储器值以在追踪中向前推送的行动1005。例如,存储器分析组件117可以使用一种或多种类型的分析,以标识可以比它们出现在追踪中更早暴露的存储器值。

如图所示,行动1005可以包括一个或多个子行动,包括片段内预取值的行动1005a。在一些实现中,行动1005a包括确定在第二追踪片段的回放期间存储器单元值能够在第一执行时间处被暴露,第一执行时间在第二执行时间之前,第二执行时间对应于使存储器单元值在追踪记录期间被记录到追踪中的事件。例如,这可以包括确定对应事件是来自存储器单元的读取,该读取是来自片段中的该存储器单元的第一(即,初始)所记录的读取。备选地,这可以包括确定存储器单元值与在第二追踪片段内的对存储器单元的一个或多个其他存储器访问兼容。例如,片段内分析组件117a可以在片段内执行存储器兼容性分析。这可以包括片段内分析组件117a基于确定以下至少一项来确定存储器单元值与一个或多个其他存储器访问兼容:(i)来自存储器单元的读取是第二追踪片段内来自存储器单元的第一读取;或(ii)来自存储器单元的读取是第二追踪片段内对存储器单元的后续存储器访问,并且存储器单元值与第二追踪片段内的存储器单元的先前已知值相匹配。片段内存储器值兼容性/移动的示例结合图6A至图7B讨论。因此,第二追踪片段可能对应于图6A和6B所示的片段或者图7A和7B所示的片段。片段内存储器值兼容性/移动的附加示例如图8B和9B所示。

行动1005的子行动还可以包括跨片段上推送值的行动1005b。在一些实现中,当第一追踪片段记录第一线程的第一可执行指令的执行并且第二追踪片段记录第二线程的第二可执行指令的执行时,并且当第一追踪片段在第二追踪片段之前排序时,行动1005b进行操作,并且可以包括确定来自第二追踪片段的存储器单元值可以在追踪回放期间在第一追踪片段之前暴露。这可以包括确定存储器单元值与第一片段兼容。例如,片段间分析组件117b可以跨片段来执行存储器兼容性分析。这可以包括片段间分析组件117b基于确定以下至少一项来确定存储器单元值与第一片段兼容:(i)第一追踪片段没有对存储器单元的存储器访问;或(ii)第一追踪片段具有对存储器单元的一个或多个存储器访问,并且第一追踪片段末端的存储器单元的第一值与第二追踪片段开始处的存储器单元的第二值相匹配。片段间存储器值兼容性/移动的示例结合图8A至图8D讨论。因此,结合该行动讨论的第一追踪片段可以对应于覆盖图8A至图8D中的步骤F之前的步骤的片段,并且结合该行动所讨论的第二追踪片段可以对应于覆盖图8A至图8D中的步骤F之后的步骤的片段。

如所提及的,存储器快照可能被认为是进行读取操作的片段,并且因此行动1005b可能会在跨存储器快照来推送值。例如,如果第一追踪片段和第二追踪片段由存储器快照分离,则行动1005b可以包括确定来自第二追踪片段的存储器单元值可以在追踪回放期间在存储器快照之前暴露。为了确定来自第二追踪片段的存储器单元值是否可以在追踪回放期间在存储器快照之前暴露,片段分析组件117b可以确定以下的一项:(i)存储器快照缺少针对存储器单元的快照信息,或(ii)存储器快照存储针对在第二追踪片段的开始处与针对存储器单元的第二值相匹配的存储器单元的第一值。

行动1005的子行动还可以包括跨间隙来推送值的行动1005c。如果结合方法1000所讨论的第一片段和第二片段之间存在小间隙,则在一些实现中,行动1005c包括确定在追踪回放期间来自第二追踪片段的存储器单元值可以在间隙之前暴露。这可以包括确定存储器单元值与间隙兼容。例如,间隙分析组件117c可以使用一种或多种启发法以确定存储器单元与间隙的兼容性。这些启发法可以包括例如单个线移动分析(即,假定存储器单元是兼容的)、基于注解的分析(即,确定函数调用的参数注解是否指示被调用的函数可以写入存储器单元)、基于分配的分析(即,存储器单元是否是包括另一存储器单元的存储器缓冲区的部分,该存储器单元是或可以在间隙之前暴露)和/或基于分配为注解的分析(即,确定函数是否将存储器单元或存储器单元的指针作为参数)。

虽然未在图10中明确示出,但行动1005a至行动1005c中的一个或多个行动是可并行化的(例如,为了提高性能/响应性)。例如,一些实现可以在行动1005a中针对独立于其他片段的每个单独片段进行分析,并且因此可能并行地对每个单独片段进行分析。其他实现可以独立地针对每个存储器单元(或缓冲区)进行分析。其他实现可以针对每个片段独立地执行片段内分析,但然后移动到针对片段间和间隙交叉阶段的每个缓冲区分析。如本领域的普通技术人员将了解的,这些任务可以以多种方式组织以实现它们的并行化。然而,在实施方式中,行动1005a至行动1005c可以被备选地串行执行(以各种顺序)。例如,一些实施方式可能以1005a、然后1005b、然后1005c的顺序串行地执行行动1005a至行动1005c。

方法1000还包括生成输出数据的行动1006。在一些实现中,行动1006包括生成输出数据,该输出数据指示存储器单元值可以在第二追踪片段的回放期间在第一执行时间被暴露。例如,输出组件118可以使用索引数据生成组件118a来生成追踪索引数据,该追踪索引数据补充(多个)访问的追踪,并且指示存储器单元值可以在比数据分组记录由存储器分析组件117所确定的存储器读取更早的执行时间点暴露,可以使用追踪修改/重写组件118b来修改现有追踪,以移动/重新排序由存储器分析组件117所确定的追踪数据,和/或可以使用追踪生成组件118c来生成记录由存储器分析组件117所确定的存储器值的全新追踪。因此,在行动1006中,生成输出数据可以包括以下项中的至少一项:基于所生成的输出数据利用索引数据补充追踪,基于所生成的输出数据来重写追踪,或基于所生成的输出数据来生成新的追踪。这可以附加地或备选地包括基于所生成的输出数据来修改追踪的先前存储器快照以包含存储器单元值,基于所生成的输出数据来插入包括存储器单元值的存储器快照等。

不管输出数据的形式如何,该数据可以包括生成指示存储器单元值可以在第二追踪片段的回放期间在第二追踪片段的开始处被暴露的追踪输出数据(即,片段内移动);在追踪回放期间,在第一追踪片段之前,生成指示存储器单元值可以被暴露的输出数据(即,片段间移动);生成追踪输出,指示存储器单元值可以在追踪回放期间在间隙之前(即,跨越间隙)暴露;和/或生成追踪输出,该追踪输出指示存储器单元值可以在追踪回放期间在存储器快照(即,跨越存储器快照)之前被暴露。

如所提及的,生成输出数据可以包括重写追踪。为了图示该概念,图11图示了用于修改追踪以使存储器单元值在对应于使存储器单元值被记录到追踪中的执行时间之前被暴露的示例方法1100的流程图。方法1100当前在图1A至图9E及其对应描述的上下文内描述。

如图所示,方法1100包括访问追踪的行动1101。在一些实现中,行动1101包括访问记录一个或多个线程的先前执行的追踪。例如,参照图1A和图1B,追踪访问组件114可以访问(多个)追踪113中的一个或多个追踪,其记录(多个)应用112中的一个或多个应用的先前执行。图3图示了包括多个追踪数据流301的追踪300的一个示例,追踪数据流中的每个追踪数据流都记录执行线程。

方法1100还包括标识记录存储器单元的值的数据分组的行动1102。在一些实现中,行动1102包括在追踪内标识各自记录从特定存储器单元读取的对应存储器单元值的多个数据分组,多个数据分组中的每个数据分组对应于至少一个执行事件。方法1100还包括选择特定存储器单元值的行动1103。在一些实现中,行动1103包括选择在多个数据分组中的一个数据分组中所记录的特定存储器单元值。例如,存储器索引组件109可以标识对追踪中的存储器单元的多个兼容访问,并且确定存储器单元值中的至少一个存储器单元值可以在追踪中更早地推送。

如所讨论的,存储器索引组件109可以采用多种方法以确定存储器兼容性。例如,存储器索引组件109可以最初标识追踪中的片段(即,使用追踪解析组件115)。如此,方法1100可以包括解析追踪以标识多个追踪片段,包括第一追踪片段和第二追踪片段,其中每个追踪片段记录多个可执行指令在一个或多个线程中的对应线程上的不间断连续执行。在该场景中,多个数据分组可以对应于第二追踪片段。另外,存储器索引组件109可以标识那些片段当中的至少部分排序(即,使用追踪排序组件116)。例如,方法1100还可以包括至少确定多个追踪片段中的部分排序,包括确定第一追踪片段在第二追踪片段之前可排序。

在标识出片段和至少两个片段当中的排序之后,存储器索引组件109可以使用存储器分析组件117来标识对追踪中的存储器单元的多个兼容访问,并且确定存储器单元值中的至少一个存储器单元值可以在追踪中更早地推送。这可以包括例如片段内分析(即,片段内分析组件117a)、片段间分析(即,片段间分析组件117b)和/或间隙分析(即,间隙分析组件117c)。

方法1100还包括修改追踪的行动1104。修改/重写追踪所采取的特定动作可能会变化。例如,图11示出了行动1104可以包括从追踪片段中移除除一个数据分组外的所有数据分组的行动1104a。在一些实施方式中,行动1104a包括从至少一个追踪片段中移除多个数据分组中的除一个数据分组外的所有数据分组。例如,追踪修改/重写组件118b可以丢弃追踪片段中的除第一数据分组之外的所有数据分组。考虑到片段内级别,追踪修改/重写组件118b甚至可以丢弃追踪中的除第一数据分组之外的所有数据分组。备选地,行动1104可以包括在对应于数据分组的执行时间之前的执行时间处插入暴露特定存储器单元值的数据的行动1104b以及丢弃数据分组的行动1105。在一些实现中,行动1104b和1104c包括将数据插入到追踪中,该追踪在与多个数据分组相对应的执行事件的执行时间之前的执行时间处、在追踪回放期间暴露所选择的特定存储器单元值,以及从追踪移除多个数据分组。例如,追踪修改/重写组件118b可以将数据插入到追踪中,该追踪早于对应于多个数据分组的执行事件的执行时间暴露特定存储器单元值,诸如在(或接近)第二片段的开始、在第一片段中,或者甚至在更早的片段中。这也可以包括交叉间隙和/或存储器快照。追踪修改/重写组件118b也可以丢弃对应于后续存储器访问的数据分组,因为它们可以经由所插入的存储器单元值和/或经由基于所插入的存储器单元值的追踪回放获得。

作为一个示例,方法1100可以操作以移动存储器值内片段。在该实施例中,片段内分析组件117a可以确定所选择的特定存储器单元值在第二片段内是兼容的。然后,当将数据插入到在追踪回放期间在与多个数据分组相对应的执行事件的执行时间之前的执行时间处暴露所选择的特定存储器单元值的追踪中时,行动1104可以包括将数据插入到在第二追踪片段的开始处暴露所选择的特定存储器单元值的追踪中。

作为另一示例,方法1100可以操作以移动存储器值间片段。在该示例中,片段间分析组件117b可以确定所选择的特定存储器单元值在第一追踪片段内是兼容的。然后,当在方法将数据插入到追踪中,追踪在追踪回放期间在与多个数据分组相对应的执行事件的执行时间之前的执行时间处暴露所选择的特定存储器单元值,行动1104可以包括将数据插入到在第一追踪片段中暴露所选择的特定存储器单元值的追踪中。在实施例中,当确定所选择的特定存储器单元值与第一追踪片段兼容时,片段间分析组件117b可以确定以下中的至少一项:(i)第一追踪片段不具有对特定存储器单元的存储器访问,或(ii)第一追踪片段具有对特定存储器单元的一个或多个存储器访问,并且第一追踪片段末端的特定存储器单元的值与第二追踪片段开始的特定存储器单元的第二值相匹配。

作为又一示例,方法1100可以操作以在存储器快照上移动存储器值。在该示例中,第一追踪片段和第二追踪片段可以由存储器快照分离,并且片段间分析组件117b可以确定所选择的特定存储器单元值与存储器快照兼容。然后,将数据插入到追踪中,追踪在追踪回放期间在与多个数据分组相对应的执行事件的执行时间之前的执行时间处暴露所选择的特定存储器单元值,行动1104可以包括将数据插入到在第一追踪片段中以及在存储器快照之前暴露所选择的特定存储器单元值的追踪中。在实施例中,当确定所选择的特定存储器单元值与存储器快照兼容时,片段间分析组件117b可以确定以下中的至少一项:(i)存储器快照缺少针对特定存储器单元的快照信息,或(ii)存储器快照存储针对特定存储器单元的第一值,该第一值与第二追踪片段开始处的针对特定存储器单元的第二值相匹配。

作为又一示例,方法1100可以操作以在间隙上移动存储器值。在该示例中,第一追踪片段和第二追踪片段可以由追踪记录中的小间隙分离,并且间隙分析组件117c可以确定所选择的特定存储器单元值与该小间隙兼容。然后,当将数据插入到追踪中,追踪在追踪回放期间在与多个数据分组相对应的执行事件的执行时间之前的执行时间处暴露所选择的特定存储器单元值,行动1104可以包括将数据插入到在第一追踪片段中以及在小间隙之前暴露所选择的特定存储器单元值的追踪中。在实施例中,当确定所选择的特定存储器单元值与第一追踪片段兼容时,间隙分析组件117c可以确定以下中的至少一项:(i)函数调用的参数注解是否指示被调用的函数可以写入特定存储器单元,(ii)特定存储器单元是否是存储器缓冲区的部分,该存储器缓冲区包括在间隙之前暴露或可以暴露的另一存储器单元,(iii)或者该函数是否将特定存储器单元或特定存储器单元的指针作为参数。

如结合追踪排序组件116提及的,实施例可以标识片段当中的全排序或片段之间的部分排序。例如,如果两个(或更多个)追踪片段的开始和末端处的所有存储器单元值都兼容,则不管(多个)片段的排序如何,追踪排序组件116可能不会在它们之间强制执行全排序,而是使得这些追踪片段能够被部分排序。在实施例中,部分排序片段可以为改进的兼容性分析提供一些机会。例如,假设有四个片段A、B、C和D——由于片段A、B和C的共享兼容性——被排序为使得片段A在前,并且片段D在后,但是片段B和C可以按任一顺序出现。在该场景中,存储器单元值可以从片段C直接推送到片段A,而无需考虑片段B。另外,当考虑片段D中的特定存储器单元值与片段A、B和C的兼容性(与其他片段不完全兼容)时,这种兼容可以被并行地进行(例如,在片段A、B和C上使用映射化简(mapreduce)拆分)。

要了解的是,本文所公开的实施例可以提供多种有价值的技术益处。从调试的观点来看,在比追踪记录中更早的执行时间呈现存储器值提供了更有价值的调试信息,包括与现场调试期间可用的存储器信息更紧密对准的存储器信息。从追踪的观点来看,在追踪回放期间更早地暴露存储器值的能力可以通过丢弃存储相同存储器值或该存储器值的衍生物的数据分组来使追踪大小能够被减少,而不是可以经由追踪回放获得的存储器值——导致更小和更有效地回放追踪。

尽管主题已经用特定于结构特征和/或方法行动的语言描述,但是要理解的是,在所附权利要求中限定的主题并不必然被限于所描述的特征或上述行动或者上述行动的顺序。相反,所描述的特征和行动被公开为实现权利要求的示例形式。

本发明可以在不脱离其精神或基本特点的情况下以其他具体形式实施。所描述的实施例在所有方面仅被认为是说明性的,而不是限制性的。因此,本发明的范围是由所附权利要求指示的,而不是由前述描述指示的。落入权利要求的等同含义和范围内的所有变化都会被包含在其范围内。当在所附权利要求中引入元素时,冠词“一”、“一个”、“该”和“所述”旨在表示存在一个或多个元素。术语“包括”、“包含”和“具有”旨在是包括性的,并且表示可能存在不同于所列举元素的附加元素。

50页详细技术资料下载
上一篇:一种医用注射器针头装配设备
下一篇:通信装置、通信方法及通信程序

网友询问留言

已有0条留言

还没有人留言评论。精彩留言会获得点赞!

精彩留言,会给你点赞!