一种残膜回收机防缠绕挑膜装置的制 一种秧草收获机用电力驱动行走机构

基于在时间旅行调试期间更改函数内部加载的数据竞争分析的制作方法

2022-03-26 04:30:24 来源:中国专利 TAG:

基于在时间旅行调试期间更改函数内部加载的数据竞争分析


背景技术:

1.追踪和校正不期望的软件行为是软件开发中的核心活动。不期望的软件行为可以包括许多事情,诸如执行崩溃、运行时异常、缓慢执行性能、不正确的数据结果、数据损坏等。不期望的软件行为可能由多种因素触发,诸如数据输入、用户输入、数据竞争(例如当访问共享资源时)等。给定触发器的多样性,不期望的软件行为可能很稀有且看似随机,并且极难再现。因此,开发者标识给定的不期望软件行为可能非常耗时且困难。一旦不期望的软件行为已经被标识,再次确定其(多个)根本原因可能既耗时又困难。
2.当开发多线程应用时,标识和修复数据竞争可能特别耗时且困难。当多个线程访问同一存储器位置时,就会发生数据竞争,并且其中至少有一个线程在没有仔细控制这些线程的执行顺序的情况下写入该存储器位置。因此,例如,第一线程可能会在第二线程未预期它时,写入存储器位置,从而使第二线程从存储器位置读取无效或意外的值。例如,由于故意使用共享存储器(例如全局变量、堆分配等)时粗心的线程同步,或由于线程无意中写入共享存储器(例如使用流氓指针,使用与不然有效的指针的不正确偏移等),数据竞争可能发生。数据竞争可能难以标识,因为它们可能无法可靠地再现—它们的发生(或其缺乏)可能会降低多个线程执行如何交错的定时—取决于每个线程的工作负载、访问存储器和其他输入/输出设备的定时特性、处理器的总体工作负载、特定用户输入等,定时可能会随时间变化。
3.开发者常规地已经使用多种方法来标识不期望的软件行为,然后标识应用代码中引起不期望的软件行为的(多个)位置。例如,开发者可能会针对不同的输入测试应用代码的不同部分(例如单元测试)。作为另一示例,开发者可能会推断在调试器中执行应用的代码(例如通过设置断点/监视点,通过在代码执行时单步调试代码行等)。作为另一示例,开发者可能会在剖析器中观察代码执行行为(例如定时、覆盖范围)。作为另一示例,开发者可能会将诊断代码(例如轨迹语句)插入应用的代码中。
4.虽然常规的诊断工具(例如调试器、剖析器等)已经在“实况地”向前执行的代码上操作,新兴形式的诊断工具实现“历史的”调试(也称为“时间旅行”或“反向”调试),其中(多个)程序线程的至少一部分的执行被记录到一个或多个轨迹文件(即,被记录的执行)中。使用一些追踪技术,被记录的执行可以包含“位准确”的历史轨迹数据,这使得(多个)追踪线程的(多个)被记录部分能够虚拟地“重放”低至个体指令的粒度(例如机器代码指令、中间语言代码指令等)。因此,使用“位准确”的轨迹数据,诊断工具可以使开发者能够推理主题代码的被记录的先前执行,而不是“实况地”向前执行该代码。例如,历史调试器可以启用前向和反向断点/监视点(watchpoint),可以使代码能够向前和向后单步调试等。另一方面,历史的剖析器可以能够从先前所执行的代码导出代码执行行为(例如定时、覆盖范围)。


技术实现要素:

5.本文描述的至少一些实施例利用历史调试技术在函数重放期间替换函数内的加载(load)的值,以便观察替换对函数的(多个)输出的影响。因此,根据本文的实施例,当仿
真给定函数的执行时,仿真器能够修改由该函数读取的一个或多个存储器值,并且然后将该函数的仿真行为与所追踪的行为进行比较。在一些实施例中,调试器使用该比较来确定在被追踪的函数期间存储器竞争是否发生(或可能发生),和/或标识存储器竞争的潜在影响。在一些实施例中,无论在追踪期间数据竞争是否实际发生,调试器都可以执行该分析。
6.例如,修改由给定加载读取的值可以操作以模拟数据竞争的发生。因此,调试器可以观察所模拟的数据竞争可能对函数的行为产生的影响(例如基于模拟数据竞争后函数的(多个)输出的(多个)值),即使在追踪期间没有实际发生数据竞争。因此,当竞争可以被怀疑但是在追踪期间尚未被捕获时,调试器可以在函数中实现数据竞争的模拟。备选地,修改由给定加载读取的值可以操作以模拟对数据竞争的校正。因此,当数据竞争在追踪期间被捕获时,调试器可以观察数据竞争的模拟校正可能对函数的行为产生的影响(例如基于模拟对数据竞争的校正后函数的(多个)输出的(多个)值)。
7.在一些实施例中,方法、系统和计算机程序产品使用被记录的执行来确定函数内部加载修改是否影响被追踪的函数的一个或多个输出。在这些实施例中,计算机系统访问被记录的执行,该被记录的执行包括追踪可执行实体的至少一部分可执行代码的先前执行的轨迹数据。轨迹数据使得能够重放可执行实体的该部分的先前执行。计算机系统标识可执行实体的可执行代码的被追踪部分内的函数。该函数包括可执行指令序列,其消耗零个或更多个输入并且产生一个或多个输出。基于轨迹数据,计算机系统确定一个或多个被追踪的输出数据值,该一个或多个被追踪的输出数据值在先前执行期间由函数的被追踪的实例产生的。计算机系统在函数的可执行指令序列内标识执行从存储器的加载的至少一个可执行指令。计算机系统根据轨迹数据来仿真函数的执行。仿真包括用不同的存储器值替换在函数的被追踪的实例期间由至少一个可执行指令加载的被追踪的存储器值,并且产生针对一个或多个输出的一个或多个仿真的输出数据值。计算机系统确定在一个或多个被追踪的输出数据值与一个或多个仿真的输出数据值之间是否存在差异。基于在一个或多个被追踪的输出数据值与一个或多个仿真的输出数据值之间存在差异,计算机系统在用户接口处或者向软件组件生成通知。
8.该发明内容被提供来以简化的形式介绍对于下面在详细描述中进一步描述的概念的选择。该发明内容不旨在标识要求保护的主题的关键特征或必要特征,也不旨在被用于辅助确定要求保护的主题的范围。
附图说明
9.为了描述本发明的上述和其他优点和特征可以被获取的方式,上面简要描述的本发明的更具体的描述将通过参照在附图中图示的其具体实施例来呈现。要理解的是,这些附图仅描绘了本发明的典型实施例,因此不应被认为是对其范围的限制,本发明将通过使用附图来利用附加的特异性和细节描述并解释,其中:
10.图1a图示了促进使用被记录的执行来确定函数内部加载修改是否影响被追踪的函数的输出的示例计算环境;
11.图1b图示了示例调试组件;
12.图2图示了示例计算环境,其中图1a的计算机系统通过一个或多个网络连接至一个或多个其他计算机系统;
13.图3图示了可执行实体的被记录的执行的示例;
14.图4图示了可执行实体中的函数的示例,其中函数基于其输入和输出而被标识;
15.图5a至5c图示了潜在数据竞争情形的示例;以及
16.图6图示了用于使用被记录的执行来确定函数内部加载修改是否影响被追踪的函数的输出的示例方法的流程图。
具体实施方式
17.本文描述的至少一些实施例利用历史调试技术在函数重放期间替换函数内的加载的值,以便观察替换对函数的(多个)输出的影响。因此,根据本文的实施例,当仿真给定函数的执行时,仿真器能够修改由该函数读取的一个或多个存储器值,并且然后将该函数的仿真行为与被追踪的行为进行比较。在一些实施例中,调试器使用该比较来确定在函数的追踪期间是否发生(或可能发生)存储器竞争,和/或标识存储器竞争的潜在影响。在一些实施例中,无论在追踪期间是否实际发生数据竞争,调试器都可以执行该分析。
18.例如,修改由给定加载读取的值可以操作以模拟数据竞争的发生。因此,调试器可以观察所模拟的数据竞争可能对函数的行为产生的影响(例如基于模拟数据竞争后函数的(多个)输出的(多个)值),即使在追踪期间没有实际发生数据竞争。因此,当竞争可以被怀疑但在追踪期间尚未被捕获时,调试器可以在函数中实现数据竞争模拟。备选地,修改由给定加载读取的值可以操作以模拟对数据竞争的校正。因此,当数据竞争在追踪期间被捕获时,调试器可以观察数据竞争的被模拟的校正可能对函数的行为产生的影响(例如基于模拟对数据竞争的校正之后函数的(多个)输出的(多个)值)。
19.如本领域技术人员将了解的,在函数重放期间替换函数内的加载的值,并且观察替换对函数的(多个)输出的影响可以提供许多技术益处。例如,在测试期间再现数据竞争可能非常困难。另外,即使生产中发生数据竞争,由于追踪引入的执行定时特性的变化,该数据竞争在追踪期间也可能无法再现。因此,即使发生可以被怀疑为数据竞争的程序错误,也可能很难,甚至不可能捕获该数据竞争的轨迹。本文的实施例提供了使所怀疑的数据竞争能够被模拟的工具。基于数据竞争的模拟,所怀疑的数据竞争可以被确认,从而大大简化了查明数据竞争根本原因的过程。另外,即使数据竞争已经在追踪期间发生,也可能不清楚是否实际发生了数据竞争。通过模拟对数据竞争的校正并且观察所得的行为,数据竞争确认可以被大大简化。附加地,即使数据竞争已经在追踪期间发生,也可能不清楚校正数据竞争可能产生的影响。通过模拟对数据竞争的校正,这些影响可以经由仿真被观察—甚至在产生代码修复之前。这些技术益处的净效果是产生不易出错的代码,减少了开发、故障排除和调试所花费的时间。
20.如所指示的,本文的实施例对可执行实体的被记录的执行进行操作。在本说明书和所附权利要求中,“被记录的执行”可以指存储(多个)代码指令的先前执行的记录的任何数据,或者可以被用于至少部分地重建(多个)先前执行的代码指令的先前执行。通常,这些代码指令是可执行实体的一部分,并且作为线程和/或进程(例如作为机器代码指令)在(多个)物理或虚拟处理器上执行,或者在被管理的运行时(例如作为中间语言代码指令)执行。
21.由本文的实施例使用的被记录的执行可以由各种历史调试技术生成。通常,历史调试技术在各个时间记录或重建实体的执行状态,以便使该实体的执行能够在稍后至少部
分地从该执行状态被仿真。该虚拟执行的保真度取决于可用的被记录的执行状态而变化。
22.例如,一类历史调试技术(在本文中称为时间旅行调试)持续记录实体执行的位准确的轨迹。然后,该位准确的轨迹稍后可以被用于将该实体的先前执行忠实地重放下至个体代码指令的保真度。例如,位准确的轨迹可以记录足以再现线程先前执行中的至少一个点的初始处理器状态的信息(例如通过记录处理器寄存器的快照)以及由该线程的指令在该时间点之后执行时读取的数据值(例如存储器读取)。然后,该位准确非日轨迹可以被用于基于向指令供应被记录的读取来重放线程代码指令的执行(以初始处理器状态开始)。
23.另一类历史调试技术(在本文中称为分支轨迹调试)依赖于基于从包括处理器分支轨迹(即,包括是否采取了分支的记录)的转储或快照(例如线程的崩溃转储)向后工作来重建实体的执行状态的至少一部分。这些技术以来自该转储或快照的值(例如存储器和寄存器)开始,并且使用分支轨迹以至少部分地确定代码执行流,迭代地重放实体的代码指令,并且向后和向前以便重建由该代码使用的中间数据值(例如寄存器和存储器),直到这些值达到稳定状态。这些技术可能会在它们可以在多远之前重建数据值以及多少数据值可以被重建方面受到限制。尽管如此,重建的历史执行数据可以被用于历史调试。
24.又一类历史调试技术(在本文中称为重放和快照调试)在实体执行时周期性地记录实体的存储器空间和处理器寄存器的完整快照。如果实体依赖于来自实体的自身存储器以外的源的数据或者来自非确定性源的数据,则这些技术还可以将这样的数据与快照记录在一起。然后,这些技术使用快照中的数据以在快照之间重放实体代码的执行。
25.图1a图示了促进使用被记录的执行来确定函数内部加载修改是否影响被追踪的函数(其例如可能对数据竞争分析有用)的输出的示例计算环境100a。如所描绘的,计算环境100a可以包括或利用专用或通用计算机系统101,其包括计算机硬件,诸如例如一个或多个处理器102、系统存储器103、持久存储装置104和/或(多个)网络设备105,它们使用一个或多个通信总线106通信耦合。
26.本发明的范围内的实施例可以包括用于携带或存储计算机可执行指令和/或数据结构的物理和其他计算机可读介质。这样的计算机可读介质可以是可以由通用或专用计算机系统访问的任何可用介质。存储计算机可执行指令和/或数据结构的计算机可读介质是计算机存储介质。携带计算机可执行指令和/或数据结构的计算机可读介质是传输介质。因此,作为示例而非限制,本发明的实施例可以包括至少两种截然不同的计算机可读介质:计算机存储介质和传输介质。
27.计算机存储介质是存储计算机可执行指令和/或数据结构的物理存储介质(例如系统存储器103和/或持久存储装置104)。物理存储介质包括计算机硬件,诸如ram、rom、eeprom、固态驱动器(“ssd”)、闪存、相变存储器(“pcm”)、光盘存储装置、磁盘存储装置或者其他磁性存储设备、或者可以被用于以计算机可执行指令或数据结构的形式存储程序代码的(多个)任何其他硬件存储设备,该程序代码可以由通用或专用计算机系统访问和执行以实现所公开的本发明的功能性。
28.传输介质可以包括网络和/或数据链路,其可以被用于携带计算机可执行指令或数据结构形式的程序代码并且可以由通用或专用计算机系统访问。“网络”被定义为能够在计算机系统和/或模块和/或其他电子设备之间输送电子数据的一个或多个数据链路。当信息通过网络或另一通信连接(硬连线、无线或者硬连线或无线的组合)被传送或被提供给计
算机系统时,计算机系统可以将连接视为传输介质。以上的组合也应该被包括在计算机可读介质的范围内。
29.进一步地,在到达各种计算机系统组件时,计算机可执行指令或数据结构形式的程序代码可以自动从传输介质被传送到计算机存储介质(反之亦然)。例如,通过网络或数据链路接收到的计算机可执行指令或数据结构可以被缓冲在网络接口模块(例如(多个)网络设备105)内的ram中,并且然后最终被传送到计算机系统ram(例如系统存储器103)和/或计算机系统处的较少易失性的存储介质(例如持久存储装置104)。因此,应该理解的是,计算机可读介质可以被包括在也(甚或主要地)使用传输介质的计算机系统组件中。
30.例如,计算机可执行指令包括指令和数据,在一个或多个处理器处执行时,该指令和数据使通用计算机系统、专用计算机系统或专用处理设备执行特定功能或功能组。计算机可执行指令可以是例如机器代码指令(例如二进制)、中间格式指令(诸如汇编语言)甚或源代码。
31.本领域技术人员将了解,本发明可以利用许多类型的计算机系统配置在网络计算环境中实践,包括个人计算机、台式计算机、膝上型计算机、消息处理器、手持式设备、多处理器系统、基于多处理器或可编程的消费者电子产品、网络pc、小型计算机、大型计算机、移动电话、pda、平板计算机、寻呼机、路由器、交换机等。本发明还可以在分布式系统环境中实践,其中通过网络被链接(通过硬连线数据链路、无线数据链路或者通过硬连线和无线数据链路的组合)的本地和远程计算机系统两者都执行任务。因此,在分布式系统环境中,计算机系统可以包括多个组成计算机系统。在分布式系统环境中,程序模块可以位于本地和远程存储器存储设备两者中。
32.本领域技术人员也将了解,本发明可以在云计算环境中实践。云计算环境可以是分布式的,尽管这不是必需的。当是分布式时,云计算环境可以在组织内国际地被分布和/或具有跨多个组织被处理的组件。在本说明书和以下权利要求中,“云计算”被定义为用于使得能够对可配置计算资源(例如网络、服务器、存储装置、应用和服务)的共享池进行按需网络访问的模型。“云计算”的定义不被限于在适当部署时可以从这样的模型获取其他许多优点中的任何优点。
33.云计算模型可以由各种特性组成,诸如按需自助服务、广泛的网络访问、资源池化、快速弹性、测量服务等等。云计算模型还可以以各种服务模型的形式出现,诸如例如软件即服务(“saas”)、平台即服务(“paas”)和基础设施即服务(“iaas”)。云计算模型还可以使用不同的部署模型来部署,诸如私有云、社区云、公共云、混合云等等。
34.一些实施例(诸如云计算环境)可以包括系统,该系统包括各自能够运行一个或多个虚拟机的一个或多个主机。在操作期间,虚拟机仿真可操作计算系统,从而支持操作系统以及可能还有一个或多个其他应用。在一些实施例中,每个主机包括超管理器(hypervisor),该超管理器使用从虚拟机的视图中所抽象的物理资源来仿真虚拟机的虚拟资源。超管理器还提供虚拟机之间的适当隔离。因此,从任何给定虚拟机的角度来看,超管理器提供虚拟机正在与物理资源对接的错觉,即使虚拟机仅与物理资源的外观(例如虚拟资源)对接。物理资源的示例包括处理能力、存储器、磁盘空间、网络带宽、媒体驱动器等。
35.如图1a所示,每个处理器102可以包括(除其他外)一个或多个处理单元107(例如处理器核心)和一个或多个高速缓存108。每个处理单元107经由高速缓存108加载和执行机
器代码指令。在一个或多个执行单元107b处执行这些机器代码指令期间,指令可以使用内部处理器寄存器107a作为临时存储位置,并且可以经由高速缓存108读取和写入系统存储器103中的各个位置。通常,高速缓存108临时高速缓存系统存储器103的部分;例如高速缓存108可以包括高速缓存系统存储器103的存储应用代码的部分的“代码”部分以及高速缓存系统存储器103的存储应用运行时数据的部分的“数据”部分。如果处理单元107需要尚未存储在高速缓存108中的数据(例如代码或应用运行时数据),则处理单元107可以发起“高速缓存未命中”,从而使所需数据从系统存储器103取得—同时可能将一些其他数据从缓存108“驱逐”回系统存储器103。
36.如所图示的,持久存储装置104可以存储表示可执行软件组件的计算机可执行指令和/或数据结构;对应地,在(多个)处理器102处执行该软件期间,这些计算机可执行指令和/或数据结构的一个或多个部分可以被加载到系统存储器103中。例如,持久存储装置104被示出为存储与调试组件109、追踪器组件110、仿真组件111和一个或多个应用112相对应的计算机可执行指令和/或数据结构。持久存储装置104还可以存储数据,诸如一个或多个被记录的执行113(例如使用上述历史调试技术中的一种或多种技术所生成的)。
37.通常,调试组件109利用仿真组件111,以便基于从(多个)被记录的执行113中的一个或多个被记录的执行113获取的执行状态数据来仿真可执行实体(诸如(多个)应用112)的代码的执行。因此,图1a示出了调试组件109和仿真组件111被加载到系统存储器103(即,调试组件109'和仿真组件111')中,并且(多个)应用112正在仿真组件111'内被仿真(即,(多个)应用112')。
38.通常,追踪器组件110将(多个)应用112中的一个或多个应用的执行记录或“追踪”到(多个)被记录的执行113中(例如使用上述一种或多种类型的历史调试技术)。追踪器组件110可以记录(多个)应用112的执行,无论该执行是直接在(多个)处理器102上的“实况”执行,还是该执行是经由被管理的运行时的(多个)处理器102上的“实况”执行,和/或该执行是经由仿真组件111的仿真执行。因此,图1a还示出了追踪器组件110也被加载到系统存储器103(即,追踪器组件110')中。追踪器组件110'与(多个)被记录的执行113'之间的箭头指示追踪器组件110'可以将轨迹数据记录到(多个)被记录的执行113'中(其然后可以作为(多个)被记录的执行113被持久化到持久存储装置104)。
39.计算机系统101可以附加地或备选地从另一计算机系统(例如使用(多个)网络设备105)接收(多个)被记录的执行113中的一个或多个被记录的执行113。例如,图2图示了示例计算环境200,其中图1a的计算机系统101通过一个或多个网络201连接至一个或多个其他计算机系统202(即,计算机系统202a至202n)。如示例200中所示,每个计算机系统202包括追踪器组件110和(多个)应用112。因此,计算机系统101可以通过(多个)网络201接收(多个)这些计算机系统202处的(多个)应用112中的一个或多个应用的(多个)先前执行的一个或多个被记录的执行113。
40.要注意的是,虽然调试组件109、追踪器组件110和/或仿真组件111可以各自是独立的组件或应用,但是它们可以备选地被集成到同一应用中(诸如调试套件),或者可以被集成到另一软件组件中—诸如操作系统组件、超管理器、云结构等。因此,本领域技术人员还将了解,本发明可以在计算机系统101是其一部分的云计算环境中实践。
41.先前提及到,调试组件109利用仿真组件111,以便使用来自(多个)被记录的执行
113中的一个或多个被记录的执行的执行状态数据来仿真(多个)应用112中的一个或多个应用的代码的执行。根据本文的实施例,当仿真给定应用112的执行时,调试组件109能够修改由应用112读取的一个或多个存储器值,并且然后将所仿真的行为与所追踪的行为进行比较。基于该比较,调试组件109可以确定在应用112的记录执行期间是否发生(或可能发生)存储器竞争和/或标识存储器竞争的潜在影响,无论竞争是否在追踪期间实际发生。在一些实施例中,修改存储器值可以操作以模拟存储器竞争的发生(例如当竞争可以被怀疑但是在追踪期间尚未被捕获时),或模拟校正存储器竞争的影响(例如当竞争在追踪期间被捕获时)。如将解释的,本文的实施例可以可用于检测存储器竞争(或可能的存储器竞争),即使在引起存储器竞争的实体的执行没有被追踪到(多个)被记录的执行113中时。在一些实施例中,调试组件109还可以利用追踪器组件110来将该仿真的执行记录到被记录的执行113中,用于进一步的历史调试分析(例如通过将附加的轨迹数据添加到已有的被记录的执行113,和/或通过创建新的被记录的执行113)。
42.为了演示调试组件109可以如何完成前述内容,图1b图示了提供图1a的调试组件109的附加细节的示例100b。图1b中描绘的调试组件109包括表示调试组件109可以根据本文描述的各种实施例来实现的各种功能的各种组件(例如数据访问114、轨迹/代码分析115、仿真116、仿真分析117、输出118等)。要了解的是,所描绘的组件—包括其标识、子组件和布置—仅被呈现为辅助描述本文描述的调试组件109的各种实施例,并且这些组件不被限于软件和/或硬件可以如何实现本文描述的调试组件109或其特定功能性的各种实施例。
43.如所示,数据访问组件114包括轨迹访问组件114a和代码访问组件114b。轨迹访问组件114a访问(多个)被记录的执行113中的一个或多个被记录的执行,诸如应用112的先前执行的被记录的执行113。图3图示了可执行实体(例如应用112)的被记录的执行300的一个示例,其可以由轨迹访问组件114a访问,其中被记录的执行300可以已经使用时间旅行调试技术被生成。
44.在图3的示例中,被记录的执行300包括多个数据流301(即,数据流301a至301n)。在一些实施例中,每个数据流301记录从应用112的代码执行的不同线程的执行。例如,数据流301a可以记录应用112的第一线程的执行,而数据流301n记录应用112的第n个线程。如所示,数据流301a包括多个数据分组302。由于被记录日志在每个数据分组302中的特定数据可能不同,因此它们被示出为具有不同的大小。通常,当使用时间旅行调试技术时,每个数据分组302至少记录对作为应用112的该第一线程的一部分所执行的一个或多个可执行指令的输入(例如寄存器值、存储器值等)。如所示,数据流301a还可以包括一个或多个关键帧303(例如关键帧303a至303b),其各自记录足够的信息(诸如寄存器和/或存储器值的快照),使得线程的先前执行能够由仿真组件116从关键帧向前的点开始重放。
45.在一些实施例中,被记录的执行113还可以包括作为应用112的一部分所执行的实际代码。因此,在图3中,每个数据分组302被示出为包括非阴影数据输入部分304和阴影代码部分305。在一些实施例中,每个数据分组302的代码部分305(如果存在的话)可以包括基于对应数据输入所执行的可执行指令。然而,在其他一些实施例中,被记录的执行113可以省略被执行的实际代码,而是依赖于具有对应用112的代码(例如来自持久存储装置104)的单独访问。在这些其他实施例中,每个数据分组可以例如指定应用二进制映像中适当的(多个)可执行指令的地址或偏移。尽管未示出,但被记录的执行300也可能包括存储代码执行
的输出中的一个或多个输出的数据流301。
46.如果存在多个数据流301,各自记录不同线程的执行,则这些数据流可以包括定序事件。每个定序事件记录可跨线程排序的事件的发生。例如,定序事件可能与线程之间的交互对应,诸如对线程所共享的存储器的访问。因此,例如如果被追踪到第一数据流(例如301a)中的第一线程向同步变量写入,则第一定序事件可以被记录到该数据流(例如301a)中。稍后,如果被追踪到第二数据流(例如301b)中的第二线程从该同步变量中读取,则第二定序事件可以被记录到该数据流(例如301b)中。这些定序事件可以是固有地有序的。例如,每个定序事件可以与单调递增的值相关联,其中单调递增的值定义了定序事件之间的总顺序。例如,被记录到第一数据流中的第一定序事件可以被赋予值1,被记录到第二数据流中的第二定序事件可以被赋予值2等。
47.返回到图1b,代码访问组件114b可以获取应用112的代码。如果由轨迹访问组件114a获取的(多个)被记录的执行114包括被追踪的代码(例如代码部分305),则代码访问组件114b可以从被记录的执行113中提取该代码。备选地,代码访问组件114b可以从持久存储装置104(例如从应用二进制映像)获取应用112的代码。
48.轨迹/代码分析组件115可以对被记录的执行113和/或由数据访问组件114访问的应用112执行一种或多种类型的分析,数据访问组件114支持在应用112的被记录的执行的仿真期间修改先前由应用112读取的(多个)存储器值。该数据修改可以被例如用作数据竞争分析的一部分。作为描述可能的分析类型的辅助,轨迹/代码分析组件115被示出为潜在地包括函数标识组件115a、输入/输出标识组件115b和加载标识组件115c。
49.在一些实施例中,函数标识组件115a标识主题应用112的代码中的离散“函数”。在一些实施例中,函数标识组件115a可以基于标识来自这些函数的输入和输出来标识这些函数。如本文使用的,“函数”被定义为可执行代码的一个或多个区段的集合,每个区段包括具有零个或更多个“输入”和一个或多个“输出”的一个或多个可执行指令的序列。例如,图4图示了可执行实体中的函数的示例400,其中函数基于其输入和输出而被标识。具体地,图4示出了应用112的代码的表示401。图4还示出了执行的不同区段在表示401中被标识为不同的函数(即,函数402,包括函数402-1至402-9)。这些函数402中的每个函数可以具有零个或更多个输入的不同集合和一个或多个输出的不同集合。例如,在图4中,每个函数402具有(多个)输入403的对应集合和(多个)输出404的对应集合。例如,函数402-1具有(多个)输入403-1的集合和(多个)输出404-1的集合,函数402-2具有(多个)输入403-2的集合(其可能对应于输出404-1的集合)和输出404-2的集合等。因此,结合函数标识组件115a标识函数,输入/输出标识组件115b可以标识对应的输入和输出。
50.虽然所标识函数的范围可能不同,但在一些实施例中,函数标识组件115a可以基于标识应用112中的基础块来标识函数。如相关领域的普通技术人员将了解的并且如本文使用的,“基础块”是作为执行单元的指令序列;即,该序列具有单个输入点和单个输出点,并且基础块中的所有或没有指令执行或不执行(异常除外)。因此,在一些实施例中,“函数”可以包括单个基础块,尽管函数可以备选地包括多个基础块。
51.如本文使用的,“输入”被定义为函数(如上面定义的)从其读取、并且函数本身在读取之前尚未写入的任何数据位置。这些数据位置可以包括例如在函数被录入时它们存在的寄存器和/或函数从中读取但它本身没有分配的任何存储器位置。如果函数分配存储器,
然后在初始化之前从该存储器读取,则可能会出现边缘情况。在这些实例中,实施例可以将对未初始化存储器的读取视为输入或漏洞。如本文使用的,“输出”被定义为函数写入的、其稍后不解除分配的任何数据位置(例如寄存器和/或存储器位置)。例如,函数入口处的堆栈分配,然后是对被分配区域的写入,然后是函数出口处的堆栈解除分配,不会被视为函数输出。另外,如果函数由应用二进制接口(abi)边界来界定,则函数出口处的任何易失性寄存器(即,不用于传递返回值的寄存器)都会隐式地“被解除分配”(即,它们被abi丢弃)—并且因此不是函数的输出。
52.在一些实施例中,函数标识组件115a可能依赖于操作系统和(多个)应用112被编译以便知道哪个(多个)寄存器是对函数的(多个)输入和/或哪个(多个)寄存器是来自函数的(多个)输出的处理器指令集架构(isa)的已知abi—这减少单独追踪寄存器的需要。因此,例如代替单独追踪寄存器,函数标识组件115a可以使用(多个)应用112被编译的abi,以确定(多个)应用112使用哪个(多个)寄存器来将参数传递给函数,和/或(多个)应用112将哪个(多个)寄存器用于返回值。在一些实施例中,调试符号可以被用于补充或替换abi信息。值得注意的是,即使调用函数忽略了被调用函数的返回值,abi和/或符号仍然可用于确定用于存储被调用函数的返回值的寄存器的内容是否已改变。
53.在一些实施例中,函数标识组件115a可以定义和映射包括在其执行内具有一个或多个间隙的指令序列的函数。例如,函数可以包括指令序列,其在执行的中间进行内核调用(可能不被记录)。为了图示,函数402-1可以采取文件句柄和字符作为输入,并且包括将文件的每个字节与输入字符进行比较以找到文件中字符的出现的指令。因为它们依赖于文件数据,所以这些指令可能会进行一个或多个内核调用(未示出)来读取文件(例如使用句柄作为内核调用的参数)。为了标识具有间隙的函数,函数标识组件115a可能需要确保这些间隙在每个函数内关于比较操作而被正确排序,因此文件数据在每个函数中以相同的顺序被处理。要注意的是,在一些实施例中,由内核调用改变的任何寄存器值通常会在(多个)记录的执行113中被追踪。尽管如此,函数标识组件115a可以附加地或备选地使用abi和/或调试符号来追踪哪些寄存器值跨内核调用被保留。例如,堆栈指针(即,x86上的esp或arm上的r13)可以在跨内核调用被保留。
54.在一些实施例中,输入和输出是可组合的。例如,如果应用112中的单个函数被包括性地定义为区段a、b和c中的代码的整体,则该函数的输入集合可以被定义为包括区段a、b和c的输入中的每个输入的组合的输入集合,并且其输出集合可以被定义为包括区段a、b和c的输出中的每个输出的组合的输出集合。要了解的是,当区段b的输入(或输出)由区段a分配(或解除分配)时,或者如果它由区段b分配并且由区段a解除分配,则函数b的该输入(或输出)可以从输入集合(或输出集合)中被省略。还要了解的是,在更广泛的函数(即,包括该区段)内被调用并且不是更广泛的函数的输入(或输出)的区段的任何输入(或输出)可以从更广泛的函数的输入集合(或输出集合)中被省略,或者可以以其他方式被追踪为更广泛的函数的内部。
55.由于函数内联,也可能出现复杂情况,特别是当子函数将不由调试组件109分析时(例如因为它来自第三方库)。例如,假设函数a的第一区段(a1)在调用子函数b之前执行,并且然后函数a的第二区段(a2)在函数b返回之后执行。此处,区段a1和a2自身可能被视为独立的函数,它们具有自己的输入和输出集合。如果函数b采取a1的任何输出作为输入,则这
些输出需要在调用函数b之前被产生;类似地,如果函数a2将函数b的任何输出作为输入,则这些输出需要出现在函数b的调取之后。
56.在一些实施例中,输入/输出标识组件115b标识在追踪期间发生的函数的输入和/或输出中的一个或多个输入和/或输出的实际值。这可以包括例如标识一个或多个输入和/或一个或多个输出的值,这些输入和/或输出被追踪到被记录的执行113和/或使函数中的一个或多个函数由仿真组件116重放,以便再现在追踪期间发生的一个或多个输入和/或一个或多个输出的值(例如以获取可能尚未被追踪到被记录的执行113中的值)。
57.针对给定函数,加载标识组件115c标识在该函数内执行的一个或多个加载。所标识的加载可以从存储器位置加载值,从寄存器位置加载值,或者从某个其他存储器加载值。在一些实施例中,所标识的加载可以被寻址到函数输入中的一个输入;因此,它会是函数已经执行到输入位置的存储之前从输入位置的加载。在这种情况下,加载会预期获取函数外部的数据。在其他情况下,加载可以是对函数内部的数据。例如,加载可以被寻址到先前对应于输入的位置,但是在函数已经对该位置执行一个或多个存储之后(因此,该位置在加载时不再是输入)。在另一示例中,加载可以被寻址到不对应于任何输入的位置,但是在函数已经对该位置执行一个或多个存储之后(例如由函数分配的变量/数据结构)。
58.尽管加载标识组件115c可以标识给定函数内的所有加载,但是加载标识组件115c可以潜在地仅标识(多个)加载的(多个)值可以被追踪到函数输出的(多个)值的那些加载。因此,例如,加载标识组件115c可以从函数的输出开始执行函数的“反向污染(reverse taint)”分析,以标识一个或多个加载与输出之间的数据连续性。例如,从特定输出开始,加载标识组件115c可以分析函数的可执行指令序列,标识执行将函数的输出值放入输出的存储的指令。然后,加载标识组件115c可以标识对应于一个或多个第一加载的可执行指令,这些第一加载被用于产生由该存储写入的输出值。(多个)这些第一加载中的每个第一加载然后可以由加载标识组件115c标识为对输出有贡献的加载。该过程然后可以针对对应于每个第一加载的每个存储器位置重复,以标识对应于(多个)第二加载的可执行指令,该第二加载对由(多个)第一加载读取的(多个)值做出贡献。该过程可以被重复任何次数,以标识一个或多个加载的集合,这些加载贡献了特定输出的值。
59.在一些实施例中,加载标识组件115c操作以标识可能读取受数据竞争影响的数据的加载,并且省略不太可能读取受数据竞争影响的数据的加载。因此,加载标识组件115c可以使用一种或多种启发法来基于加载的目标存储器可以被多个线程使用的相对可能性来对加载进行分类。这样的启发法可以由调试符号(如果可用的话)辅助。例如,如果给定函数内的加载是到与函数堆栈对应的存储器位置或者到常量,则由加载读取的数据不大可能受到数据竞争的影响。因此,加载标识组件115c可以从所标识的加载中省略该加载。相对地,如果给定函数内的加载是到与堆存储器相对应的存储器位置或者到全局变量,则加载可能受到数据竞争的影响。因此,加载标识组件115c可以将该加载包括在所标识的加载中。在一些实施例中,堆栈存储器甚至可以更精细地被追踪。例如,实施例可以确定指向给定函数的堆栈地址的指针是否已被另一函数占用。如果是,则该地址可能比没有被另一函数占用的另一堆栈地址更可能受到数据竞争的影响。另外,没有堆栈地址被另一函数占用的函数比有一个或多个堆栈地址被另一函数占用的函数更不可能遭受数据竞争。如所提及的,被记录的执行113可以包括定序事件。在一些实施例中,加载标识组件115c可以考虑这些定序事
件。例如,如果加载对应于定序事件,则它可能是跨线程同步事件的一部分。因此,该加载可能不太可能是数据竞争的一部分,并且加载标识组件115c可能在所标识的加载中省略该加载,或者至少将其标记为与其他加载相比不太可能成为数据竞争的一部分。在一些实施例中,加载标识组件115c可以至少部分地基于用户输入来操作。例如,加载标识组件115c可以接收指定感兴趣的特定加载的用户输入,可以接收指定感兴趣的变量或数据结构的用户输入等。
60.针对所标识的每个加载,加载值标识组件115d可以标识加载的一个或多个替换值。每个替换值是在仿真组件116仿真加载期间可能被人工地用作加载所获取的值的值。加载值标识组件115d可以与仿真组件116进行的仿真分开操作和/或结合仿真组件116进行的仿真操作。因此,例如,加载值标识组件115d可以在函数仿真之前和/或在函数仿真期间标识给定函数中的一个或多个加载的(多个)替换值。
61.加载值标识组件115d可以从用于确定用什么值替换特定加载的多种方法中选择。例如,加载值标识组件115d可以提示用户输入以从用户获取值,或者可以选择随机值。加载值标识组件115d可以备选地执行函数分析以标识适当的替换值。例如,如果函数的多个先前被执行的实例的轨迹数据可用,则加载值标识组件115d可以分析这些多个实例以标识给定加载的函数的多个实例中的每个实例所读取的值。然后,针对函数的给定实例和该加载,加载值标识组件115d可以选择针对加载典型的替换值(例如如果尝试模拟对数据竞争的校正),或者选择针对加载非典型的替换值(例如如果尝试模拟数据竞争的引入)。
62.在另一示例中,加载值标识组件115d可以结合轨迹数据执行对函数内的数据流的分析,以确定要替换什么值。为了图示这个概念,图5a至5c图示了潜在数据竞争情况的示例500a至500c。如在描述加载标识组件115c时所提及的,所标识的加载可以被寻址到例如与函数输入对应的存储器位置、到以前是输入的存储器位置或不与输入对应的存储器位置。
63.示例500a图示了从与函数输入对应的存储器位置的加载。具体地,矩形501a表示函数随时间的执行—从矩形501a的顶部开始消耗(多个)输入并且在矩形的底部结束,产生输出504a。另一方面,矩形502a表示随时间变化的存储器位置。因此,在函数的入口处,存储器位置的值被示出为“a”,该值被用作函数的输入。箭头505a和505b表示在函数执行期间一些可能的加载和向存储器位置的存储(尽管可能存在其他加载和存储)。如所示,在箭头505a处的存储时,值“b”由函数以外的东西(例如同一进程的另一线程、内核线程、dma等)写入存储器位置。该值稍后在箭头505b处由函数读取。如要了解的,箭头505a处的存储可能是有意的(在这种情况下,值“b”会在箭头505b处的加载时由函数预期),但它也可能是由于数据竞争(在这种情况下,值“a”会在箭头505b处的加载时由函数预期)。给定这种情况,加载值标识组件115d可以选择在箭头505b处将值“a”替换到加载中。在这种情况下,这可能是尝试模拟对数据竞争的校正。值得注意的是,如果在轨迹中不存在箭头505a处的存储,则加载值标识组件115d可以选择将某个其他值替换到箭头505b处的加载中以尝试模拟数据竞争的引入。
64.示例500b图示了从以前是输入的存储器位置的加载。具体地,矩形501b表示函数随时间的执行—从矩形的顶部开始消耗(多个)输入503b并且在矩形的底部结束,产生输出504b。矩形502b表示随时间变化的存储器位置。因此,在函数的入口处,存储器位置的值被示出为“a”,该值被用作函数的输入。箭头505c至505d表示在函数执行期间一些可能的加载
和向存储器位置的存储(尽管可能存在其他加载和存储)。如所示,在箭头505c处的存储时,该函数将值“b”写入存储器位置。稍后,在箭头505d处,值“c”由函数以外的东西(例如同一进程的另一线程、内核线程、dma等)写入存储器位置。该值稍后在箭头505e处由函数读取。如要了解的,箭头505d处的存储可能是有意的(在这种情况下,值“c”会在箭头505e处的加载时由函数预期),但它也可能是由于数据竞争(在这种情况下,值“b”会在箭头505e处的加载时由函数预期)。给定这种情况,加载值标识组件115d可以选择在箭头505e处将值“b”替换到加载中。在这种情况下,这可能是尝试模拟对数据竞争的校正。值得注意的是,如果在轨迹中不存在箭头505d处的存储,则加载值标识组件115d可能选择将一些其他值替换到箭头505e处的加载中以尝试模拟数据竞争的引入。
65.示例500c图示了从不与输入对应的存储器位置的加载。具体地,矩形501c表示函数随时间的执行—从矩形的顶部开始消耗(多个)输入503c(如果有的话)并且在矩形的底部结束,产生输出504c。矩形502c表示随时间变化的存储器位置。箭头505f至505h表示在函数执行期间一些可能的加载和向存储器位置的存储(尽管可能存在其他加载和存储)。如所示,在箭头505f处的存储时,该函数将值“a”写入存储器位置。稍后,在箭头505g处,值“b”由函数以外的东西(例如同一进程的另一线程、内核线程、dma等)写入存储器位置。该值稍后在箭头505h处由函数读取。如要了解的,箭头505g处的存储可能是有意的(在这种情况下,值“b”会在箭头505h处的加载时由函数预期),但它也可能是由于数据竞争(在这种情况下,值“a”会在箭头505h处的加载时由函数预期)。给定这种情况,加载值标识组件115d可以选择在箭头505h处将值“a”替换到加载中。在这种情况下,这可能是尝试模拟对数据竞争的校正。值得注意的是,如果在轨迹中不存在箭头505g处的存储,则加载值标识组件115d可以选择将一些其他值替换到箭头505h处的加载中以尝试模拟数据竞争的引入。
66.转向仿真组件116,仿真组件116基于由轨迹访问组件114a访问的(多个)被记录的执行113中的一个或多个被记录的执行113来仿真由代码访问组件114b访问的代码。例如,仿真组件116可以包括或利用图1a的仿真组件111来仿真被访问的代码。使用仿真组件116,基于执行函数的代码,同时使用来自被记录的执行113的被追踪的数据值引导该代码的执行(包括例如由输入/输出标识组件115b标识的一个或多个被追踪的输入),调试组件109可以重放由函数标识组件115a标识的一个或多个函数。因此,仿真组件116被示出为包括仿真引导组件116a,其可以根据需要向任何被仿真函数的代码供应被追踪的数据值,以便引导函数的仿真以再现函数的被追踪的执行。
67.仿真组件116也被示出为包括加载替换组件116b。结合给定函数的仿真,加载替换组件116b可以用与基于仿真引导组件116a的操作会被预期的值不同的值来替换由加载标识组件115c标识的加载中的一个或多个加载的值。因此,加载替换组件116b可以被视为产生针对仿真引导组件116a的引导的异常。加载替换组件116b可以针对上面结合加载标识组件115c讨论的任何类别的加载产生代替加载值。例如,如果加载是从与输入对应的位置,则加载替换组件116b可以用某个其他值替换从被记录的执行113获取的或者通过重放另一函数所获取的输入值。如果加载是从先前与输入对应但随后被函数写入的位置,则加载替换组件116b可以用某个其他值替换写入的值。如果加载是从不对应于任何输入但是在函数已经执行向该位置的一个或多个存储之后的位置,则加载替换组件116b可以用某个其他值替换写入的值。
68.仿真组件116也被示出为包括输出生成组件116c。输出生成组件116c指示代码仿真将在代码仿真期间生成一个或多个输出值。例如,函数402-1的仿真将产生输出404-1,函数402-2的仿真将产生输出404-2等。如果仿真组件116利用仿真引导组件116a—而不是加载替换组件116b—则给定函数的仿真将产生与追踪期间相同的输出和输出值。因此,仿真引导组件116a可以被用于获取在追踪期间可能尚未被记录的任何输出。然而,如果仿真组件116还利用加载替换组件116b,则函数的仿真可能会偏离函数在追踪期间如何执行,并且它可能产生不同的输出值。因此,针对给定函数,输出生成组件116c可能能够生成一个或多个输出的集合以及一个或多个附加的输出集合,该一个或多个输出的(多个)值与在追踪期间锁产生的那些输出值一致,取决于加载替换组件116b对函数内的哪些加载执行替换和/或加载替换组件116b替换哪些值,该一个或多个附加的输出集合可能具有不同的值。
69.值得注意的是,当执行重放(包括进行存储器加载替换的重放)时,仿真组件116可以利用追踪器组件110以便记录该仿真。因此,仿真组件116可以向被记录的执行113贡献附加轨迹。
70.如所提及的,函数可以包括间隙,诸如由对未被追踪的内核调用的调用引起的间隙。在一些实施例中,仿真组件116可以使用一种或多种技术来优雅地处理任何间隙。作为第一示例,仿真组件116可以从所访问的被记录的执行113确定哪些输入被供应给内核调用,并且然后由仿真组件116基于这些输入来仿真内核调用。作为第二示例,仿真组件116可以将内核调用视为可以在所访问的被记录的执行113中的其他事件之中被排序的事件,并且仿真组件116可以确保通过内核调用进行的任何可见改变(例如改变的存储器值、改变的寄存器值等)作为输入暴露给在内核调用之后执行的代码,而不是仿真内核调用。作为第三示例,仿真组件116可以设置适当的环境上下文,并且然后使用这些输入对正在运行的内核进行实际调用。作为第四示例,仿真组件可能只是提示用户内核调用的结果。
71.仿真分析组件117可以执行对所访问的(多个)应用112的仿真执行的各种类型的分析,包括分析由加载替换组件116b执行的任何加载替换的影响。例如,该分析可以被用作数据竞争分析的一部分,如将进一步讨论的。如所示,仿真分析组件117可以包括例如输出比较组件117a、数据竞争分析组件117b、分类组件117c和/或检查器组件117d。
72.输出比较组件117a可以将在追踪期间由给定函数生成的输出集合与在使用加载替换组件116b替换由一个或多个函数加载读取的(多个)值时由仿真组件116重放该函数期间生成的输出集合进行比较。如果在这些输出集合内有任何差异,则输出比较组件117a可以确定加载替换对函数的输出有影响。如所提及的,在重放期间生成的输出集合可以从被记录的执行113获取,和/或基于在仿真引导组件116a使用轨迹数据引导仿真时仿真组件116对函数的仿真,。
73.基于输出比较组件117a的比较,数据竞争分析组件117b可以确定已经针对给定加载替换了值的加载替换组件116b是否可能已经校正了数据竞争,或者可能已经模拟了数据竞争。如果输出比较组件117a发现被追踪输出的集合和加载替换期间所生成的输出集合没有差异,则替换可能没有校正或模拟数据竞争(至少不是以可检测到的方式)。然而,如果输出集合存在差异,则替换可能已经校正或模拟了数据竞争。在一些实施例中,数据竞争分析组件117b可以确定所模拟的输出集合是具有正常值还是异常值。如果竞争的校正被模拟,并且如果所得输出正常,则可能确实存在竞争。相反,如果竞争的校正被模拟,并且如果所
得输出异常,则可能没有竞争,或者用于模拟校正的值是一个糟糕的选择。类似地,如果竞争的引入被模拟,则观察输出是正常还是异常可以指示所模拟的竞争是否与生产中可能发生的情况相匹配。例如,如果输出保持正常,则该模拟的竞争可能实际上并没有在生产中发生。相反,如果输出异常,并且如果它们与生产中观察到的异常结果类似,则所模拟的竞争可能正在生产中发生。
74.为了确定所仿真的输出是正常的还是异常的,仿真分析组件117可以包括分类组件117c。分类组件117c可以采取给定函数的多个被追踪的实例的输出作为输入。然后,分类组件117c可以在输出中寻找模式(例如使用机器学习技术)以将各种输出分类为针对该函数是正常的还是异常的。例如,分类组件117c可以确定哪些输出值通常落在与彼此的正态分布内(并且因此是正常的),和/或哪些输出值落在该分布之外(并且因此是异常的)。不管使用何种特定分类技术,分类组件117c都可以针对给定函数开发模型,该模型可以被用于确定针对该函数的哪些输出值是正常的或异常的。在一些实施例中,分类组件117c还可以分析函数的输入,并且将针对给定输入典型的输出建模。
75.仿真分析组件117还可以包括检查器组件117d,其可以对被记录的执行113执行一个或多个查询—这些被记录的执行113是否是基于“实况”代码执行而被生成的,或者它们是否是结合仿真而被生成的。这些查询可以检查各种类型的代码行为,诸如存储器泄漏(例如通过针对没有对应的解除分配的任何存储器分配而查询)。在一些实施例中,仿真分析组件117可以针对基于仿真组件116执行存储器加载替换而被记录的轨迹运行一个或多个检查器。因此,仿真分析组件117可以确定存储器加载替换是否引起(或停止)检查器组件117d可检测到的行为。数据竞争分析组件117b可以使用检查器组件117d作为确定存储器加载替换是否可能已经校正了数据竞争或者可能已经模拟了数据竞争的一部分。例如,如果检查器组件117d可检测到的不期望的行为在存储器加载替换之后被修复,则这可能是存储器加载替换修复了存储器竞争的指示。相反,如果检查器组件117d可检测到的不期望的行为在存储器加载替换之后被引入,则这可能是存储器加载替换引起了存储器竞争的指示。
76.输出组件118可以输出仿真组件116的任何代码仿真的结果和/或仿真分析组件117的任何分析的结果。例如,输出组件118可以可视化代码仿真(包括加载值替换),则可以在输出比较组件117a确定所仿真的输出与被追踪的输出不同的情况下生成通知(例如向另一应用或在用户接口处)生成通知,可以呈现被追踪的输出与所仿真输出之间的任何差异等。
77.鉴于前述内容,图6图示了用于使用记录的执行来确定函数内部加载修改是否影响被追踪的函数的一个或多个输出的示例方法600的流程图。方法600现在将在图1至5c的上下文内描述。尽管为了便于描述,方法600的动作以特定的相继顺序示出,但是要了解,这些动作中的一些动作可以以不同的顺序和/或并行实现。
78.如图6所示,方法600包括访问可执行实体的(多个)先前执行的(多个)可重放轨迹的动作601。在一些实施例中,动作601包括访问被记录的执行,该被记录的执行包括追踪可执行实体的可执行代码的至少一部分的先前执行的轨迹数据,该轨迹数据使得能够重放可执行实体的该部分的先前执行。例如,数据访问组件114可以访问应用112的一个或多个被记录的执行113(例如使用轨迹访问组件114a)。如图3所示,(多个)这些被记录的执行113中的每个被记录的执行可以包括至少一个数据流301a,数据流301a包括多个数据分组302;每
个数据分组302可以包括数据输入部分304,其记录对可执行指令的输入,该可执行指令作为应用的先前执行的一部分而被执行。(多个)被记录的执行113可以包括应用112在(多个)处理器102处直接或通过被管理的运行时的先前“实况”执行或者使用仿真组件116对应用112的先前所仿真的执行。因此,在动作601中,一个或多个被记录的执行113可以包括可执行实体的“实况”执行或可执行实体的仿真的执行中的至少一项。
79.方法600还包括标识可执行实体内的函数的动作602。在一些实施例中,动作602包括标识可执行实体的可执行代码的被追踪部分内的函数,该函数包括可执行指令序列,该函数消耗零个或更多个输入并且产生一个或多个输出。例如,函数标识组件115a可以分析应用112的(例如被包含在应用二进制和/或轨迹数据流中的)代码以标识代码中的一个或多个函数。如所讨论的,使用本文的输入和输出的定义,函数是具有零个或更多个输入以及一个或多个输出的可执行指令序列。
80.方法600还包括确定函数的被追踪输出的动作603。在一些实施例中,动作603包括基于轨迹数据确定在先前执行期间由函数的被追踪的实例产生的一个或多个被追踪的输出数据值。例如,输入/输出标识组件115b可以标识在动作602中所标识的函数的一个或多个输出,包括函数的主题实例的(多个)输出值。输出值可以直接从被记录的执行113获取,或者基于(与仿真引导组件116a结合)使用仿真组件116重放函数来获取。尽管未示出,但方法600还可以使用输入/输出标识组件115b来确定在先前执行期间被提供给函数的被追踪的实例的一个或多个被追踪的输入数据值(如果有的话)。
81.方法600还包括标识函数内的内部加载的动作604。在一些实施例中,动作604包括在函数的可执行指令序列内标识执行从存储器执的加载的至少一个可执行指令。例如,加载标识组件115c可以分析函数的可执行指令以标识函数内的一个或多个加载。例如,这些加载可以以系统存储器、寄存器等为目标。在一些实施例中,加载标识组件115c具体标识执行有可能经受存储器竞争的从存储器的加载的(多个)可执行指令。例如,这些加载可能以堆存储器、全局变量或可能由多个线程访问的其他存储器位置为目标。在一些实施例中,加载标识组件115c仅标识可能影响在动作603中所标识的(多个)输出值的那些加载。因此,加载标识组件115c可以执行对可执行指令序列的“反向污染”分析以标识具有与(多个)输出的数据连续性的加载。
82.方法600还包括根据轨迹来仿真函数的执行的动作605。例如,仿真组件116可以仿真函数的可执行指令序列,同时使用仿真引导组件116a连同所访问的被记录的执行113中所包含的轨迹数据一起来引导它们的执行。因此,仿真组件116可以再现函数的先前执行,如被记录的执行113中所记录的。尽管未示出,动作605可以包括在根据轨迹数据仿真函数的执行时针对一个或多个输入(如果有的话)为函数提供一个或多个被追踪的输入数据值。
83.虽然仿真引导组件116a的使用可以重放先前的执行,但是仿真组件116还可以通过用不同值(例如由加载值标识组件115d标识的值)替换加载的被追踪值来修改该重放。因此,如所示,动作605可以包括替换所加载的存储器值的动作605a。在一些实施例中,动作605a包括用不同的存储器值替换在函数的被追踪的实例期间由至少一个可执行指令加载的被追踪的存储器值。例如,当仿真在动作604中所标识的加载时,加载替换组件116b可以用由加载值标识组件115d标识的不同值替换基于被记录的执行113会被使用的值。例如,这可以包括用来自一个或多个被追踪的输入数据值的存储器值替换被追踪的存储器值(例如
以模拟校正数据竞争),或用某个其他存储器值替换被追踪的存储器值。如所示,动作605可以包括从函数产生仿真的输出的动作605b。因此,如输出生成组件116c所表示的,仿真组件116可以针对一个或多个输出产生一个或多个仿真的输出数据值。
84.如将了解的,由于加载替换组件116b的使用,这些输出可能不同于会由函数的标准重放生成的输出。因此,方法600包括比较被追踪的输出和仿真的输出的动作606。在一些实施例中,动作606包括确定在一个或多个被追踪的输出数据值与一个或多个仿真的输出数据值之间是否存在差异。例如,输出比较组件117a可以将在动作603中获取的输出值与在动作605b中生成的输出值进行比较。然后,方法600还包括从比较产生结果的动作607。结果可能是输出相同,或者输出不同。如果输出不同,动作607可以包括:基于在一个或多个被追踪的输出数据值与一个或多个仿真的输出数据值之间存在差异,在用户接口处或者向软件组件生成通知。如果向软件组件生成通知(其可以包括例如调用函数),则动作607可以包括确定一个或多个仿真的输出数据值针对该函数是正常还是异常的,确定一个或多个检查器是否受到用不同的存储器值替换被追踪存储器值影响等。例如,输出组件118c可以生成关于差异和/或数据竞争分析组件117b进行的任何分析的结果的警报,数据竞争分析组件117b可以确定仿真的输出是正常的还是异常的(例如使用分类组件117c),数据竞争分析组件117b可以确定加载替换是否引起检查器的变化(例如使用检查器组件117d)等。
85.如果在动作607中,数据竞争分析组件117b确定一个或多个仿真的输出数据值针对该函数是正常的还是异常的,则该确定可以将一个或多个仿真的输出数据值与来自该函数的一个或多个其他被追踪的实例的被追踪输出值进行比较,诸如通过使用分类组件117c。如果在动作607中,数据竞争分析组件117b确定一个或多个仿真的输出数据值针对函数是正常的,则方法600可以包括数据竞争分析组件117b确定用校正潜在的竞争条件的不同的存储器值替换被追踪的存储器值。备选地,如果在动作607中,数据竞争分析组件117b确定一个或多个仿真的输出数据值针对函数是异常的,则方法600可以包括数据竞争分析组件117b确定用引入潜在的竞争条件的不同的存储器值替换追踪的存储器值。如果在动作607中,输出组件118生成通知,则通知可以使用户接口呈现一个或多个被追踪的输出数据值和一个或多个仿真的输出数据值。
86.因此,本文的实施例利用历史调试技术在函数重放期间替换函数内的加载的值,以便观察替换对(多个)函数输出的影响。修改由给定加载读取的值可以操作以模拟数据竞争的发生。因此,调试器可以观察到锁模拟数据竞争可能对函数行为产生的影响,即使在追踪期间实际上没有发生数据竞争时。因此,当竞争可以被怀疑但是在追踪期间尚未被捕获时,调试器可以在函数中实现数据竞争模拟。备选地,修改由给定加载读取的值可以操作以模拟对数据竞争的校正。因此,当数据竞争在追踪期间被捕获时,调试器可以观察到数据竞争的模拟校正可能对函数的行为产生的影响。这可以减少花费在开发、故障排除和调试上的时间,从而产生较不容易出错的代码的产生。
87.尽管主题已经用特定于结构特征和/或方法动作的语言描述,但是要理解的是,在所附权利要求中限定的主题并不一定被限于所描述的特征或上述动作或者上述动作的顺序。确切地说,所描述的特征和动作被公开为实施权利要求的示例形式。
88.本发明可以在不脱离其精神或基本特性的情况下以其他具体形式实施。所描述的实施例在所有方面仅被认为是说明性的,而不是限制性的。因此,本发明的范围是由所附权
利要求指示的,而不是由前述描述指示的。落入权利要求的等效含义和范围内的所有变化都会被包含在其范围内。当在所附权利要求中引入元素时,冠词“一”、“一个”、“该”和“所述”旨在表示存在一个或多个元素。术语“包括(comprising)”、“包括(including)”和“具有”旨在是包括性的,并且表示可能存在不同于所列举元素的附加元素。
再多了解一些

本文用于企业家、创业者技术爱好者查询,结果仅供参考。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

相关文献