探测具有限制性调用约定代码的方法

文档序号:6554303阅读:202来源:国知局
专利名称:探测具有限制性调用约定代码的方法
技术领域
本发明大体涉及软件开发,尤其涉及测试软件的工具。
背景技术
随着软件程序的发展,通常希望测试程序以确定它们是否如所期望的运行。随着软件程序越来越大并且越来越复杂,使得软件执行过慢、占用过多内存或者即使在程序所有的部分都生成了期望输出时也无法交付一个希望的性能水平的可能性越来越大。
通常希望测试程序以确定其是否交付一个希望的性能水平。在软件程序无法交付一个希望性能水平的情况下,性能工程师就可在该程序运行时对其进行分析以识别可修改用于改进性能的部分。
为了便于性能设计,软件开发系统包括能够“探测”程序的工具。“探测”程序通常包括插入被称作“探头”的特定函数的调用。每个探头记录关于在每次执行时其中插入探头的程序的操作状态的信息。例如,可以将一探头插入该程序在程序调用特定函数之前的地方,并且把第二探头也插入该程序中在该程序调用该函数之后的地方。当执行这些探头时,每次都会将其执行的时间写入日志文件。通过分析该日志文件,性能工程师能够确定执行该函数所需的时间量。
作为另一个实例,可以在每个函数的起始处和结尾处插入探头。由这些探头收集的信息可用于分析每一函数的执行次数或者每次调用该函数的执行时间。在分析相对复杂的程序时该性能信息尤为重要。
为了使通过分析所探测的程序所获取的结果能够可靠表示该程序在实际操作中的性能,添加的探头就应该尽可能少的中断该程序的运行。因此,通常将探头插入含有待分析程序的二进制或可执行文件中。在所述二进制文件被充分优化和编译之后该二进制文件才包含所述程序。因此,插入探头不会改变优化或编译过程。
为了将探头插入二进制文件,可以反汇编该二进制文件以识别希望该探头所在的程序内的具体位置。例如函数表通常被包括作为二进制文件的一部分以指定表示每个函数的指令的起始点。
探头也不应该将错误引入运行中的程序,诸如通过改变变量的存储或者破坏存储执行程序所依赖信息的格式。在其中编写应用程序的软件系统能够施加各种编程约定,特别是关于改变函数内寄存器的值的约定。
例如,业已使用特定的调用约定为X86处理器系列开发了许多广泛可用的应用程序。为了遵守该调用约定,处理在X86处理器上运行的程序的编译器可以使用序言(prologue)和尾部(epilogue)部分来实现每个函数。在序言中,函数将其中函数改变的每个寄存器的值压入堆栈。在结尾部分,通过将这些寄存器值的弹出堆栈使得该函数恢复这些寄存器的值。编写与这一函数交互的任何其他例程或工具会假定依据所述调用约定来存储信息。如果没有依据所述调用约定来存储信息,则会导致出错。
可以预期为在其上运行该程序的处理器定制特定的调用约定。例如,可以设计一个使用处理器快速执行的指令的调用约定。因此,由软件系统和旨在其上运行该软件系统的处理器的结合所形成的每个平台都可具有不同的调用约定。例如,某些平台结合了包括X86处理器系列的64位扩展的处理器。这些处理器在诸如AMD64或EMT64T的名称下可用。这些处理器统称为具有X64扩展。基于带有X64扩展的处理器的平台可以使用与基于不带扩展的X86处理器的类似平台不同的调用约定。
所以希望探测一种被开发用于其中传统探测方法会引入错误的X64平台或其他使用调用约定的应用的软件。

发明内容
本发明涉及一种探测被开发用于在其中传统探测方法会引入错误的平台的程序的方法。根据该过程,可以从包装函数内调用探头。这些包装函数允许调用探头函数而不违反该平台的调用约定。
本发明在一个方面涉及探测软件程序的方法,所述软件程序带有适于至少一个在该软件内某位置记录操作信息的探头函数。本方法包括修改该软件程序以将控制传输给一个包装函数,所述包装函数包括至少一个调用该探头函数的计算机可执行指令。
本发明在另一个方面涉及测试在具有寄存器的平台上的软件程序,其中所述寄存器具有值和调用约定,其中在至少一个寄存器内的值在函数调用后仍保持。本方法具有了包括在该函数内的某个被探测位置执行至少一个探头函数的类型。根据本方法,执行该软件程序并且该程序在所述被探测位置处将控制传递给包装函数。在该包装函数内,保持该平台的状态,调用所述探头函数并且重新储存该平台的状态。
本发明在又一个方面涉及带有为实现用于一软件程序的开发环境的计算机可执行指令的计算机可读介质。所述计算机可执行指令修改含有该软件程序可执行版本的二进制文件以包括一探头函数和调用该探头函数的包装函数;在所述二进制文件中识别要执行一探头函数的被识别位置;并且在所述被识别位置将传递控制的控制指令的传递提供给所述包装函数。


附图并未按比例画出。附图中,用类似的编号表示在各图中示出的每一相等或接近相等的组件。为了简明起见,并未在每张附图中标出每一组件。在附图中图1是要探测的程序的部分的表示;图2A是根据本发明一个实施例的加入了一探头函数的被修改程序的表示;图2B是根据本发明第二实施例的加入了一探头函数的被修改程序的表示;图3是根据本发明又一个实施例加入了探头函数的被修改程序的表示;图4是根据本发明实现一程序的过程的流程图。
具体实施例方式
我们已经认识到在探测为使用限制性调用约定的平台而编写的计算机程序的问题。在一平台上使用这一调用约定的一个实例,该平台包括用于带有X64扩展的处理器的MicrosoftWindows操作系统。
图1给出了对该平台生成的代码的汇编级版本的实例。例如图1可表示通过反汇编可执行文件的某部分所创建的显示。示出了调用程序110的一部分。调用程序110包括调用了在此表示为“OriginalFunction.”的函数的指令112。
在此实例中,被调用函数150表示“OriginalFunction”。被调用函数150由返回指令156结束。返回指令156在函数调用112之后的指令处将程序控制返回给调用程序110。根据在此实例中使用的调用约定,使用处理器内某些寄存器来把参数传递给被调用函数。所述被调用函数可以修改这些寄存器内的值而不违反该调用约定。一般说来,能将被修改的值从被调用函数返回给调用函数的寄存器可表示为“易失寄存器”。
作为函数调用的一部分,由该函数使用的参数值通过调用程序110被载入易失寄存器。在此实例中,预调用指令114将送给所述函数的参数值存储在易失寄存器内。
如果要求的参数量多于能被存储在易失寄存器内的量,则另外的参数可以存储在与调用程序110相关联的堆栈框架的已定义位置内。预调用指令115表示存储在堆栈上的参数的指令。调用程序110也包括在函数调用112之后把表示函数结果的值从易失寄存器中卸载的后调用指令116。如果要返回的结果多于易失寄存器能够接收的量,则这些结果可以存储在与调用程序110相关联的堆栈框架的预定义位置内。
根据此约定,被调用函数150可以修改易失寄存器而无需中断调用程序110的操作。其他寄存器被认为是易失寄存器。如果被调用函数150修改任何非易失寄存器,它就必须存储在这些寄存器内的值并且在返回到调用程序110之前恢复它们。因此,被调用函数150包括了存储在被调用函数150内可以修改的任何非易失寄存器状态的序言部分152。被调用函数150还包括了恢复被存储在序言152内存储的任何非易失寄存器状态的尾部部分154。当编译被调用函数150时,必须为存储所有的被请求非易失寄存器分配足够的存储器空间。
在许多实例中,当每个函数在作为一个堆栈实现的存储器结构内执行时都为每个函数分配存储空间。每次一调用函数,就创建一个新的堆栈框架。创建堆栈框架动态地分配可由函数使用的存储。当该函数完成执行时,该堆栈框架可以弹出该堆栈以便允许该程序的其他部分重新使用那些存储空间。
在某些实例中,使用框架指针识别堆栈框架的起始点。在这一实施例中,可以从所述框架指针中识别出为弹出一个堆栈框架而从该堆栈中移除的信息的量。在其他实例中,在编译时间就固定了用于一函数的堆栈框架的大小。堆栈指针标记该堆栈的底部。因此可以通过由一个堆栈框架大小来偏置该框架指针来识别为弹出一个堆栈框架而从该堆栈中移除的信息的量。在调用约定允许任一种用于识别堆栈框架大小的方法的情况下,为一程序添加探头应该不会产生关于任一方法的错误。
该程序的其他函数或部分可依赖于具有由所述调用约定所规定的格式的堆栈。例如在处理异常时,以预先确定的格式安排存储器是很重要的。一旦出现异常,通常就必须终止执行中的函数而不是通过其正常的函数序言来处理。响应于该异常条件通常被称为“异常处理程序”的程序依赖于诸如其堆栈框架大小的关于该函数的信息,来“展开”所述堆栈并且在异常条件出现的指针之后的某位置上将所述处理系统置于在所述调用程序中重新开始执行的状态。
为了异常处理程序能够正确地展开该堆栈,它就必须访问定义了每个堆栈框架是怎样建立的信息,这些信息包括了诸如为所述被调用函数分配的堆栈框架大小的细节。在此描述的实施例中,将该信息存储在作为已编译程序一部分存储的函数表内。在编译时间,就在该函数表内为每个函数作出指示堆栈框架大小的条目,所述条目用于在运行时间设置堆栈框架的大小。展开该堆栈所需的任何附加信息也被存储在该函数表内。
在所述的实施例中,没有使用框架指针识别堆栈框架的起始点。而是设置该框架指针用于指向该堆栈框架的底部。通过相对于该框架指针的索引定位在堆栈框架中用于一特定函数的存储位置。一旦设置该框架指针用于指向该框架的结尾就不再使用该对该堆栈的压入和弹出。可以通过从所述框架指针中减去当前函数的预先确定的框架大小来识别该堆栈框架的起始点。
就该调用约定而言,仅仅在可执行文件中插入对探头函数的一个调用是无法产生期望结果的。为保存要传递参数所必须的存储位置在调用函数的所述堆栈框架内都是不能得到的。此外,在调用约定的任何部分依赖于静态信息(诸如堆栈框架的大小)的情况下,所述被调用函数就不具有在其中能够存储处理器的非易失状态的堆栈框架。如某些调用约定所作的将非易失寄存器的值压入该堆栈会改变所述堆栈结构而破坏了所述调用约定。
在所述实施例中通过使用“包装函数”能够避免由于程序内插入探头而违反所述调用约定所造成的问题。在此使用的术语“包装函数”指的是调用了另一个函数的函数。所述包装函数可以是为了该目的单独添加的函数或可以服务于其他的函数。构造所述包装函数使得在可执行文件中插入对包装函数中的调用不会破坏所述调用约定。配置所述包装函数使得它能够符合该平台的调用约定地调用探头函数。在下面描述的实施例中,在被探测程序内应该执行探头函数的点上通过把所述包装函数作为控制指令传送给包装函数而将所述包装函数插入一可执行文件内。此外,可以增强在可执行文件内用于该被探测程序的函数表以包括对该包装函数的一个引用。
在一个实施例中,所述包装函数的执行创建了包括为了探头函数的正确操作所必须存储的任何参数的存储空间的堆栈框架。在探头执行期间,用于该调用函数的堆栈框架、所述包装函数和所述探头都遵守该平台的调用约定。
是基于在所述调用函数内插入探头函数的位置来使用特定实施例的。图2A示出了在被调用函数的起始处插入探头函数的本发明的一个实施例。调用函数210可以表示图1中描述的调用程序110的相同部分。然而已修改了函数调用112(图1)用于创建指向标识为“NewFunction”的函数的函数调用212。
例如可以使用允许以自动、半自动或手动方式编辑可执行码的传统开发工具来做出这些修改。实现NewFunction作为包装函数220。它包括对探头函数的函数调用226。在函数调用226处所调用的探头函数可以执行本领域已知的用于在被调用函数起始处执行一探头函数的操作,诸如存储执行时间、存储寄存器的值、存储调用堆栈等等。
包装函数220包括了保持平台状态并且设置框架指针以表示为包装函数220分配的堆栈框架底部的序言222。包装函数220包括了恢复平台状态并且通过调节所述堆栈指针解除为包装函数220分配的堆栈框架的分配的相应的尾部部分224。平台的状态可以通过处理器的寄存器内的值所反映出来。必须被存储以保护平台状态的特定寄存器依靠所述调用约定并且还可依靠包装函数220或者该包装函数可能调用的其他函数的操作。在此被用作一个实例的调用约定中,序言222存储由包装函数220修改的易失和非易失寄存器的值以及由包装函数220调用的探头函数中被修改而未被保护的任何易失寄存器的值。在此特定的实例中,存储了寄存器RCX和RDX。
不考虑在编译被探测程序之后添加对包装函数220的调用的事实,包装函数220遵守了该平台的调用约定。因此,如果在指令226处调用的探头函数或包装函数220的执行期间出现了异常,背离所述调用约定就无法阻碍异常处理程序的操作。
包装函数220以控制指令的传递结束,在此示出为跳转指令230。跳转指令230的目标是在图1中示出作为被调用函数150的实例的OriginalFunction。结果是执行函数调用212的净效应与在被探测程序中函数调用112的执行相同,除了在函数调用226中指出的探头函数在原始被调用函数150之前被执行。
图2B示出了在被调用函数结尾插入探头函数的实施例。在此实施例中,被调用函数250是被调用函数150的修改版本。除了修改了返回指令156(图1)之外,被调用函数250包括被调用函数150的所有指令。返回指令156由跳转指令256代替。
如图2A的实施例,在图2B中表示的实施例导致了在被探测程序内的希望位置处调用探头函数的包装函数的执行。在此实施例中,被调用函数以在此作为跳转函数256的控制指令的传递结尾,控制传递给将识别为“NewFunction2”的包装函数260。
包装函数260的执行导致新堆栈框架的分配。该堆栈框架包括用于存储在调用包装函数26时为保护该程序状态所需的信息的足够空间。在示出的实施例中,包装函数260包括依据所述调用约定建立堆栈框架并保护该状态的序言264。包装函数260还可另外包括恢复该状态并且展开该堆栈框架的尾部266。包装函数260还包括可用于初始化在函数调用262处被调用的探头函数的预调用指令268。在此实例中,预调用指令268把要传递给所述探头函数的参数存储在用于根据所述调用约定向函数传递自变量的寄存器中。
包装函数260以返回指令270结尾。因为包装函数260是由跳转指令256而不是call指令所调用的,在包装函数260结尾处执行的返回指令270与现有技术中在被调用函数150结尾处执行的返回指令具有相同的效果。然而执行图2B中示出的指令的净效应是在从被调用函数250返回之前就在指令262处执行被调用的探头函数。现在转到图3,提供了另外实施例的一个实例。图3示出了调用函数310的一部分。在此实施例中,紧接着函数调用312的之前和之后用探头探测调用程序310。正如先前的实例,通过为包装函数添加函数调用来插入每个探头。函数调用317具有在函数调用312之前添加探头的效果。函数调用319具有在由函数调用所调用的函数执行之后添加一探头的效果。在此实例中,并未修改被调用函数,并且该函数可以是例如图1中示出的函数150。
函数调用317调用包装函数320。包装函数320包括序言部分322和尾部部分324。序言部分322建立堆栈框架并且存储由包装函数320或由包装函数320调用的探头函数所改变的易失寄存器的状态。在所述实施例中,因为所述探头函数保护了没有被直接改变的非易失寄存器的状态,所以包装函数320就无需存储这些寄存器的状态。尾部324展开该堆栈框架并且恢复那些存储在序言322内的易失寄存器的值。函数调用326调用所述探头函数,而该探头函数可以是现有技术中的探头。预调用指令328根据该平台的函数调用约定把参数传递给所述探头函数。
包装函数320以在此为返回指令330的控制指令的传递作为结尾。返回指令330在执行函数调用312处将控制返回给被调用函数310。执行函数调用317的净效果是在函数调用312之前执行探头函数,但仍满足调用约定。
函数调用319调用包装函数360。包装函数360在执行时创建为易失寄存器提供存储的堆栈框架,其中所述易失寄存器可以通过执行该包装函数或由该包装函数360所调用的探头函数来改变。包装函数360包括了建立所述堆栈框架并且存储作为包装函数360或包含其中的探头函数的结果而被改变的任何易失寄存器的状态。预调用指令368设置要传递给在函数调用366处被调用的探头函数的参数值。尾部364展开所述堆栈框架并且恢复存储在序言362内的易失寄存器的状态。
包装函数360以把函数执行返回给调用函数310的返回指令作为结束。在所述调用函数310中执行的下一个指令是后调用指令116。除了是在对指定为“OriginalFunction”的函数调用之前还是之后调用探头函数之外,执行在图3中示出的调用函数310的部分的净效果与图1中示出的调用函数110的部分的执行相同。
现在转到图4,示出了用于探测一程序的过程的实例。图4是探测一程序的过程410的流程图。在此实施例中,已编译该程序或者已将该程序转换成可执行文件,正如“二进制”或DLL模块。可执行文件包括了表示运行该程序的处理器可执行的单独指令的二进制代码。例如图4可以表示由开发人员在软件开发环境中使用性能分析工具所产生的过程。可编码该过程作为计算机可执行指令或者可通过人类输入的动作和计算机可执行指令的组合来编码该过程。例如图4可以表示由开发人员在软件开发环境中使用性能分析工具所产生的过程。
可执行文件还包括指示了文件内每个函数位置的函数表。该函数表包括处理异常或执行程序操作所必需的信息。例如该信息可包括为一函数所创建的堆栈框架的大小。
过程410在过程框412处开始。在过程框412处反汇编所述二进制文件。文件可以整体反汇编或者可反汇编选择的部分。在示出的实施例中,反汇编该二进制的足够部分以允许识别用于插入一探头的位置。
现有的程序开发环境通常包括反汇编工具使得程序开发人员可以在创建二进制文件之后分析或处理程序。可以使用传统的反汇编程序。在为用户显示代码的实施例中,可以反汇编整个二进制文件并且可以为每条指令生成人类可认知的助记符。在自动识别探头位置的情况下,仅仅对能够辨认在插入探头的位置之前和/或之后的指令起始和结尾处的代码进行反汇编就足够了。
过程行进到处理框414。在处理框414处,识别将插入探头的位置。在所述的实施例中,由用户识别的探头位置表示通过由开发环境通过的用户界面提供的一个位置。
用户可以指出一个或多个探头的位置。在图4的实例中描述了对单个探头的处理。例如用户可以通过指出显示在用户界面上代码内的一个位置表明一探头的位置。此外,用户还可通过指定插入探头位置的特性来指出一个或多个探头的位置。例如,用户界面允许用户在程序特定区域内每个函数的之前和之后或者在从一特定模块中调用的每个函数的起始和结尾处指定要插入的探头。指定探头位置的所述具体方法并不作为本发明的限制。
在示出的实施例中,用于插入一探头的具体处理步骤依赖于插入该探头的位置。可以如图2A所示处理在函数入口处插入的探头。可以如图2B所示处理在函数出口处插入的探头。可以如图3所示处理在其他位置处(如在调用函数内函数调用之前或之后)插入的探头。判定框416判定所指定的探头位置是否需要将探头放置在函数入口。如果是这样,处理就行进到处理框420。
在处理框420处,把表示要添加的探头的函数和所述包装函数添加至所述二进制文件。通过将可执行代码附加在所述二进制文件的结尾处或者以任何其他的便利方式来添加这些函数。该探头可以是在传统上用于探测代码的探头函数。所述包装函数可以结合图2A所示,被转换成表示可执行计算机指令的二进制代码。
在处理框422处,更新所述函数表以表示出被添加的函数。具体说来,是把所述探头和包装函数添加至所述函数表。在该函数表保持关于处理异常所需函数的信息的程度上,这些信息是包括在所述函数表内的。例如,函数表内的条目可以指定对所述函数分配的堆栈框架大小。
在处理框424处,修改所述二进制代码以将对探测函数的任何调用重新定向新进添加的包装函数。在图2A所示的实施例中,通过使用所述包装函数代替对探测函数的函数调用的目标来做出这一变化。使用反汇编的代码识别在所述二进制文件内表示目标函数并由此需要被改变的特定字节。可以在反汇编的程序或者直接在所述二进制文件中做出这一替代。被添加至代码的包装函数以将控制指令的传送至所述被探测函数起始处作为结束。
如果判定框416判定探头位置不在函数入口,则处理就行进到判定框430。判定框430判定是否在函数的出口处插入所述探头。
如果是在一函数出口处插入所述探头,则处理就行进至处理框440。在处理框440处,将包装函数和探头函数添加至所述二进制代码。如在处理框440内,通过在所述二进制文件的结尾处附加可执行代码或者以任何其他的便利方式来添加这些函数。该探头函数可以是现有技术中的探头函数。所述包装函数可以如图2B所示,被转换成表示可执行计算机指令的二进制代码。
在处理框442处,更新所述二进制文件内的函数表以反映出添加至所述代码的包装和探头函数。如在处理框422内,更新该函数表包括识别所述被添加的函数以及处理异常所需的其他信息,诸如为所述函数分配的堆栈框架大小。
在处理框444处,被探测函数的出口指令被重新定向到所述包装函数。如图2B所示,可以通过使用到所述包装函数的跳转指令代替在被探测函数结尾处的返回指令来完成这一重新定向。在此实施例中,在步骤440处添加的所示包装函数以提供了所述调用程序的恰当返回的返回指令来结尾。
如果判定框430判定探头位置不在函数的出口处,则处理就行进到处理框450。在所述的实施例中,将探头位置约束在函数入口、函数出口或紧接着函数调用的前一或后一指令处。如果处理到达过程框450,则探头位置不是函数的入口或出口,因此就被处理成紧接着函数调用的前一或后一指令处。
在处理框450处,将包装函数和探头函数添加至所述二进制代码。如在处理框420内,通过在所述二进制文件的结尾处附加可执行代码或者以任何其他的便利方式来添加这些函数。。
在处理框452处,更新所述二进制文件内的函数表以反映出添加至所述代码的包装和探头函数。如在过程框422内,更新该函数表包括识别所述被添加的函数以及处理异常所需的其他信息,诸如对所述函数分配的堆栈框架大小。
在处理框454处,在被探测的代码的恰当位置上插入对所述包装函数的调用。添加一调用指令改变了表示被探测函数的二进制文件部分的长度。在改变被探测函数的长度影响了存储的关于所述被探测函数或其他存储在所述二进制文件内其它函数的任何信息的情况下,也要更新该信息。由此即使在添加了所述探头之后,也能够正确地执行所述二进制文件。
图4中所示的过程表示了为一程序添加一个探头所需的步骤。为测试一个程序通常需要添加多个探头。可以为每个插入的探头重复图4中示出的过程。在重复这些过程步骤时,可以结合某些动作。例如可以为所有被添加的函数同时更新函数表。或者相同的探头和包装函数可用于多个探头的插入,从而减少了必需添加至所述函数表或附加在所述二进制文件之后的函数总数。
一旦完成了添加所有期望探头的处理,就可执行被探测程序。所述探头函数在被调用时能够捕捉关于此被探测程序的操作信息,诸如通过写入一日志文件。随后此信息可由一机器分析或经处理后显示给操作者。随后就可以使用这些信息来调试或分析被探测程序的性能。
以上讨论了本发明至少一个实施例的若干方面,应该认识到本领域普通技术人员能够轻易获取各种改变、修改和改进。
例如执行操作的具体步骤对本发明来说并不关键。描述了反汇编一个二进制文件以识别对原始函数的调用指令,而该调用指令由依次调用探头的对新函数的调用所代替。是通过在二进制文件中插入二进制代码来调用所述新函数还是通过修改所述反汇编代码并在随后该代码转换回可执行代码来做出这一代替是无关紧要的。
同样,结合了存储作为二进制文件的可执行代码来描述本发明。用于存储那些信息的文件结构不作为对本发明的限制。可由计算机处理作为可执行程序的信息的任何排列都可被认为是可执行文件。此外,包括可执行的文件不限于指令或函数表。所述可执行代码可以包括其他信息。此外,所述可执行代码不是必须包含函数表。能够以任何方式存储处理异常所需的信息或执行代码。根据为该平台建立的约定通过处理该文件就可以明确地存储或确定该信息。
能够以多种方式的任一种实现本发明的上述实施例。例如可以使用硬件、软件或它们的组合来实现这些实施例。当以软件实现时,可以在任何合适的处理器或处理器集合上执行软件代码,而不论软件代码在单个计算机内提供的或是在多个计算机中分布的。应该认识到执行上述函数的任何组件或组件集合通常可被认为是控制上述函数的一个或多个控制器。能够以各种方式来实现所述一个或多个控制器,诸如使用专用硬件或使用通用硬件(诸如一个或多个处理器),它们使用微代码或软件来编程以执行上述函数。
同样在此略述的各种方法或过程也可编码成在使用各种操作系统或平台的任何一种的一个或多个处理器上可执行的软件。此外,可以使用任何数量合适的编程语言和/或传统的编程或脚本工具来编写该软件,并可将该软件编译成可执行机器语言代码。
在此方面,本发明的一个实施例涉及用一个或多个程序编码的计算机可读介质(或多个计算机可读介质)(例如计算机存储器、一个或多个软盘、致密盘、光盘、磁带等),当这些程序在一个或多个计算机或其他处理器常执行时,就可执行实现了上述本发明各实施例的方法。计算机可读介质可以是便携的,以使得存储其上的程序可被载入一个或多个不同的计算机或其他处理器以实现以上讨论的本发明的各方面。
在此使用的术语“程序”在一般意义上指的是可用于编程计算机或其他处理器以实现上述本发明各个方面的任何类型的计算机代码或指令集。此外还应认识到,根据此实施例的一个方面,执行时实现本发明方法的一个或多个计算机程序不是必须位于单个计算机或处理器上,而是能够以模块化的形式分布在多个不同的计算机或处理器中以实现本发明的各个方面。此外在通常的意义下使用的术语“函数”指可传递控制给一函数的某些部分。某些编程语言提供被称作函数的特定构造。在此使用的术语不受此限制。该术语旨在包括指定作为子程序、方法、进程或其他名称的程序的各部分。
可以单独、结合或以未在前述实施例中特别讨论的各种安排来使用本发明的各个方面,因此本发明的应用就不限于在前的描述或示出的附图中所阐明的组件的细节和安排。例如,在一个实施例中描述的各个方面能够与在其他实施例中描述的各个方面以任何方式结合。
在权利要求中使用诸如“第一”、“第二”、“第三”等等的序数术语来修饰的声明要素本身并不意味着任何优先权、优越性,也不意味着一个声明要素的次序先于另一个要素或在一方法中执行动作的时间的次序,而(序数术语的使用)仅仅是作为用于将具有一指定名的声明要素和具有相同名的另一个要素相区别的标号,从而辨别声明的各要素。
而且,在此使用的措辞和术语仅出于描述的目的并且不应被认为具有任何限制的意义。“包括”、“包含”或者“具有”、“含有”、“带有”以及它们在此的变化的使用意味着包括了其后列出的项和其等效物以及附加的项。
这些改变、修改和改进旨在成为本公开内容的一部分,并且认为在本发明的精神和范围之内。因此在前的描述和附图仅出于实例的目的。
权利要求
1.一种探测软件程序的方法,其中所述软件程序在执行时具有多个位置和操作状态,其中至少一个探头函数适于将关于操作状态的信息记录于所述软件程序内的一位置处,所述方法包括修改所述软件程序用于引发包装函数的执行,而所述包装函数包括引发所述探头函数的执行的至少一个计算机可执行指令。
2.如权利要求1所述的方法,其特征在于,所述探头函数包括将关于所述软件程序的操作状态的信息写入一日志文件的至少一个计算机可执行指令,并且所述包装函数包括存储表示所述软件程序的操作状态的信息的包装函数。
3.如权利要求1所述的方法,其特征在于,所述软件程序由至少一个可执行文件表示,并且修改所述软件程序包括a)反汇编至少一个可执行文件的至少一部分;b)在所述可执行文件的反汇编部分识别引发第三函数执行的指令;c)在至少一个可执行文件内使用引发所述包装函数执行的指令来代替引发所述第三函数执行的所述指令;以及d)在所述包装函数内包括引发所述第三函数执行的指令。
4.如权利要求3所述的方法,其特征在于,在至少一个可执行文件内使用引发所述包装函数执行的指令来代替引发所述第三函数执行的所述指令包括使用对所述包装函数的调用来代替对所述第三函数的调用。
5.如权利要求4所述的方法,其特征在于,在所述包装函数内包括引发所述第三函数执行的指令包括在所述包装函数内包括以所述第三函数作为其目标的跳转指令。
6.如权利要求1所述的方法,其特征在于,所述软件程序由至少一个可执行文件表示,并且修改所述软件程序包括a)反汇编至少一个可执行文件的至少一部分;b)在所述可执行文件的反汇编部分识别在第三函数内并且引发在目标位置处一指令执行的指令;c)在至少一个可执行文件内使用引发所述包装函数执行的指令来代替所述被识别指令;以及d)在所述包装函数内包括引发在目标位置处的指令执行的指令。
7.如权利要求1所述的方法,其特征在于,所述软件程序由至少一个可执行文件表示,并且修改所述软件程序包括a)在所述至少一个可执行文件内插入一在探头位置处执行以引发所述包装函数执行的指令;b)在所述包装函数内包括一引发在所述软件程序内邻近所述探头位置处的指令执行的指令。
8.如权利要求1所述的方法,其特征在于,所述可执行文件实质上是由可以被带有X64扩展的处理器所处理的指令组成的。
9.如权利要求1所述的方法,其特征在于,所述包装函数包括在调用所述探头函数后从所存储信息中恢复所述软件程序的操作状态的至少一个计算机可执行指令。
10.一种测试在具有各寄存器的平台上具有多个位置的软件程序的方法,所述寄存器具有值和调用约定,而在至少一个寄存器中的所述值在函数调用后被保存,所述方法的类型为包括在所述程序内的被探测位置处执行至少一个探头函数的方法,并且所述方法还包括按下列步骤执行所述软件程序a)在所述被探测位置上执行引发包装函数执行的指令;以及b)从所述包装函数内i)保存所述平台的状态;ii)调用所述探头函数;以及iii)恢复所述平台的状态。
11.如权利要求10所述的测试软件程序的方法,其特征在于,执行引发包装函数执行的指令还包括为所述包装函数形成一个堆栈框架。
12.如权利要求11所述的测试软件程序的方法,其特征在于,保存所述平台的状态包括在用于所述包装函数的堆栈框架内存储至少一个寄存器的值。
13.如权利要求10所述的测试软件程序的方法,其特征在于a)执行引发包装函数执行的指令包括执行以所述包装函数作为目标的调用指令;以及b)所述方法还包括从所述包装函数内执行以第二函数为目标的跳转指令。
14.如权利要求10所述的测试软件程序的方法,其特征在于a)执行引发包装函数执行的指令包括执行来自第二函数内以所述包装函数作为目标的跳转指令;以及b)所述方法还包括从所述包装函数内执行一返回指令。
15.如权利要求10所述的测试软件程序的方法,其特征在于a)执行引发包装函数执行的指令包括执行以所述包装函数作为目标的调用指令;以及b)所述方法还包括从所述包装函数内执行一返回指令。
16.一种具有实现用于软件程序的开发环境的计算机可执行指令的计算机可读介质,所述计算机可执行指令执行的步骤包括a)修改含有所述软件程序的可执行版本的二进制文件以包括探头函数和调用该探头函数的包装函数;b)在所述二进制文件中识别要执行探头函数的被识别位置;以及c)在所述被识别位置处提供引发所述包装函数执行的指令。
17.如权利要求16所述的计算机可读介质,其特征在于,执行包括在所述二进制文件中识别被识别位置的步骤的所述计算机可执行指令还包括执行接收来自人类输入的步骤的计算机可执行指令。
18.如权利要求16所述的计算机可读介质,其特征在于,执行包括修改二进制文件的步骤的计算机可执行指令包括执行包括将所述包装函数和所述探头函数的可执行版本附加给所述二进制文件的步骤的计算机可执行指令。
19.如权利要求18所述的计算机可读介质,其特征在于,执行包括修改二进制文件的步骤的计算机可执行指令还包括执行包括修改一函数表以包含识别关于所述包装函数的信息的步骤的计算机可执行指令。
20.如权利要求18所述的计算机可读介质,其特征在于,执行包括在所述被识别位置提供引发所述包装函数执行的步骤的计算机可执行指令还包括执行包括改变表示所述软件程序的指令的所述二进制文件的一部分的步骤的计算机可执行指令。
全文摘要
揭示了一种在其中可使用探头函数探测待测程序的计算机程序的开发环境。通过其结构遵守开发所述计算机程序用的平台的限制性调用约定的包装函数来调用所述探头函数。通过遵守所述调用约定,即使在调用异常处理程序或者依赖于遵守所述调用约定的其他程序元素的情况下,也能在测试期间完成对所述计算机程序的正确操作。一旦被探测,就可测试所述计算机程序以确定它是否执行所希望的逻辑功能从而确定该程序的或用于其他测试功能的性能。
文档编号G06F11/36GK1838088SQ200610004199
公开日2006年9月27日 申请日期2006年2月24日 优先权日2005年3月24日
发明者I·B·阿龙亚 申请人:微软公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1