脚本语言代码调试方法及装置、可读存储介质及电子设备与流程

文档序号:26501392发布日期:2021-09-04 02:40阅读:224来源:国知局
脚本语言代码调试方法及装置、可读存储介质及电子设备与流程

1.本公开涉及计算机技术领域,具体而言,涉及一种脚本语言代码调试方法、脚本语言代码调试装置、计算机可读存储介质以及电子设备。


背景技术:

2.lpc语言(由lars pensj
ǒ
开发的编程语言)是在c语言语法的基础上发展出来的脚本语言。作为脚本语言,lpc代码的编译和执行都由其专门的引擎驱动程序来实现。而代码的编写不可避免会产生错误,当错误发生时程序员需要对代码进行调试。
3.相关技术中,使用gdb工具(gdb是gnu开源组织发布的一个unix下的程序调试工具)对在引擎虚拟机中执行的lpc脚本进行调试。由于虚拟机执行的lpc脚本对应的当前的opcode(操作码)无论属于哪个lpc文件的哪一行,在虚拟机中的执行位置都是一样的。因此,使用gdb在指定的lpc文件和行号处设置断点时,需要在lpc文件的不同地方插入对应的断点设置代码。
4.然而,这种方式需要人工添加断点设置代码,且在调试完成后,需要人工对添加的调试代码进行删除,以防止和原本的代码进行混淆,因此极大的降低了lpc代码的调试效率。
5.需要说明的是,在上述背景技术部分公开的信息仅用于加强对本公开的背景的理解,因此可以包括不构成对本领域普通技术人员已知的现有技术的信息。


技术实现要素:

6.本公开的目的在于提供一种脚本语言代码调试方法及装置、计算机可读存储介质及电子设备,进而至少在一定程度上克服相关技术中直接使用gdb工具对脚本语言代码调试时效率低下的问题。
7.本公开的其他特性和优点将通过下面的详细描述变得显然,或部分地通过本公开的实践而习得。
8.根据本公开的第一方面,提供了一种脚本语言代码调试方法,包括:
9.获取当前在虚拟机中被执行的操作码的第一位置属性,所述第一位置属性包括所述操作码所属的目标脚本代码文件的标识和所述操作码对应的脚本代码在所述目标脚本代码文件中的位置信息;
10.将所述第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配;
11.在匹配成功时,调用预设断点跳转函数以在所述操作码处触发断点调试功能。
12.在本公开的一种示例性实施例中,基于前述方案,所述预设断点存储容器包括预设断点存储数组,所述预设断点存储数组中每个元素存储的断点数据包括所述断点的第二位置属性和所述元素的断点状态;
13.其中,所述断点的第二位置属性包括断点所属的脚本代码文件的标识和断点在所
述脚本代码文件中的位置信息;
14.所述元素的断点状态包括未存储断点或存储的断点已被移除的第一状态、已存储断点且已存储的断点无效的第二状态、已存储断点且已存储的断点有效的第三状态。
15.在本公开的一种示例性实施例中,基于前述方案,所述方法还包括:
16.响应于添加目标断点的操作指令,根据元素的索引值的升序顺序遍历所述预设断点存储数组中的元素,在遍历到断点状态为第一状态的元素时,将所述目标断点的第二位置属性存储至所述元素中,并将所述元素的断点状态重新配置为第三状态;
17.响应于移除目标断点的操作指令,将所述目标断点对应的目标元素的断点状态重新配置为第一状态,在所述目标断点对应的目标元素之后存在断点状态为第二状态或第三状态的待调整元素时,针对所述待调整元素,依次将所述待调整元素中存储的断点数据前移至所述待调整元素对应的前一个元素中进行存储;
18.其中,在所述预设断点存储数组中,位于目标元素之后的待调整元素的索引值大于所述目标元素的索引值。
19.在本公开的一种示例性实施例中,基于前述方案,所述方法还包括:
20.响应于针对目标断点的无效状态配置指令,在所述预设断点存储数组中,将所述目标断点对应的目标元素的断点状态重新配置为第二状态;
21.响应于针对目标断点的有效状态配置指令,在所述预设断点存储数组中,将所述目标断点对应的目标元素的断点状态重新配置为第三状态;
22.响应于断点查询操作指令,查询所述预设断点存储数组中存储的断点数据,并根据第一预设格式在客户端显示查询到的所述断点数据。
23.在本公开的一种示例性实施例中,基于前述方案,所述将所述第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配,包括:
24.根据所述预设断点存储数组中的元素的索引值的升序顺序,遍历所述预设断点存储数组中的元素;
25.在遍历到存储的第二位置属性与所述第一位置属性相同且断点状态为第三状态的元素时,停止遍历且确定所述第一位置属性和所述预设断点存储容器中配置的断点的第二位置属性匹配成功。
26.在本公开的一种示例性实施例中,基于前述方案,所述方法还包括:
27.在遍历到存储的断点状态为第一状态的元素时,停止遍历且确定所述第一位置属性和所述预设断点容器中配置的断点的第二位置属性匹配失败,以使所述虚拟机继续执行下一个操作码。
28.在本公开的一种示例性实施例中,基于前述方案,所述将所述第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配,包括:
29.在中断方式为运行到下一个断点处时,将所述第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配。
30.在本公开的一种示例性实施例中,基于前述方案,所述方法还包括:
31.在中断方式为单步跳过时,若虚拟机的当前调用栈深度不大于上次调用栈深度,则调用预设断点跳转函数以在所述操作码处触发断点调试功能;
32.在中断方式为单步进入时,若虚拟机的当前调用栈深度不小于上次调用栈深度,
则调用预设断点跳转函数以在所述操作码处触发断点调试功能;
33.在中断方式为单步完成时,若虚拟机的当前调用栈深度小于上次调用栈深度,则调用预设断点跳转函数以在所述操作码处触发断点调试功能。
34.在本公开的一种示例性实施例中,基于前述方案,所述方法还包括:
35.响应于预设代码调试指令,开启代码调试进程,并在预设断点跳转函数处添加断点调试功能,以在调用所述预设断点跳转函数时触发所述断点调试功能。
36.在本公开的一种示例性实施例中,基于前述方案,所述方法还包括:
37.若所述预设断点跳转函数触发断点调试功能,则获取所述操作码的第一位置属性;
38.基于所述第一位置属性,在所述操作码所属的目标脚本代码文件中读取待打印脚本代码;
39.根据第二预设格式在客户端显示所述操作代码对应的脚本代码和所述待打印脚本代码;
40.其中,所述待打印脚本代码包括在所述目标脚本代码文件中,与所述操作码对应的脚本代码的位置信息的差值在预设阈值内的脚本代码。
41.在本公开的一种示例性实施例中,基于前述方案,在所述操作码处触发断点调试功能后,所述方法还包括:
42.响应于在当前中断期间针对目标全局变量值的查看指令,调用第一预设函数查询所述目标全局变量值,并生成所述目标全局变量值的第一序列化字符串,以在客户端显示所述第一序列化字符串;
43.响应于在当前中断期间针对目标全局变量值的修改指令,调用第二预设函数将所述修改指令中的目标全局变量值进行反序列化,并将反序列化的目标全局变量值赋值给所述目标全局变量。
44.在本公开的一种示例性实施例中,基于前述方案,在所述操作码处触发断点调试功能后,所述方法还包括:
45.响应于在当前中断期间针对目标局部变量值的查看指令,调用第三预设函数基于预先生成的局部变量索引表确定目标局部变量的索引值,根据所述索引值查询所述目标局部变量对应的目标局部变量值,并生成所述目标局部变量值的第二序列化字符串,以在客户端显示所述第二序列化字符串;
46.响应在当前中断期间针对目标局部变量值的修改指令,调用第四预设函数将所述修改指令中的目标局部变量值进行反序列化,并基于预先生成的局部变量索引表确定目标局部变量对应的索引值,根据所述索引值将反序列化后的目标局部变量值赋值给所述目标局部变量。
47.在本公开的一种示例性实施例中,基于前述方案,通过以下方式预先生成所述局部变量索引表:
48.在对脚本代码文件进行编译时,针对解析到的每个局部变量定义处,获取局部变量所属的脚本代码文件的标识、局部变量所属的函数的标识、局部变量的位置信息以及局部变量在所述函数包含的局部变量中被定义的顺序;
49.在根据所述脚本代码文件的标识和所述函数的标识所确定的局部变量索引表中,
存储所述局部变量的标识、所述局部变量的位置信息以及所述局部变量被定义的顺序,以生成所述函数的局部变量索引表;
50.其中,所述局部变量的位置信息包含所述局部变量定义处在所述脚本代码文件中的位置信息;
51.在本公开的一种示例性实施例中,基于前述方案,所述基于预先生成的局部变量索引表确定目标局部变量对应的索引值,包括:
52.响应于在当前中断期间针对目标局部变量值的查看指令或修改指令,获取造成当前中断的当前断点所属的目标脚本代码文件的标识和目标函数的标识,以确定出待查询的局部变量索引表;
53.在所述待查询的局部变量索引表中,确定出与所述查看指令或修改指令中的目标局部变量的标识相同且位置信息小于或等于当前断点在目标脚本代码文件中的位置信息的待查询局部变量;
54.确定位置信息与所述当前断点在目标代码文件中的位置信息的差值最小的待查询局部变量为目标局部变量;
55.根据所述目标局部变量对应的被定义的顺序,确定出所述查看指令或修改指令中的目标局部变量对应的索引值。
56.在本公开的一种示例性实施例中,基于前述方案,在所述操作码处触发断点调试功能后,所述方法还包括:
57.响应于在当前中断期间针对当前断点处的调用栈的查看指令,调用第五预设函数遍历虚拟机的栈帧,以获取当前断点处的调用栈信息,并根据第三预设格式在客户端显示所述当前断点处的调用栈信息。
58.在本公开的一种示例性实施例中,基于前述方案,在所述操作码处触发断点调试功能后,所述方法还包括:
59.响应于在当前中断期间针对目标脚本函数的调用指令,调用第六预设函数执行所述目标脚本函数;
60.其中,所述调用第六预设函数执行所述目标脚本函数包括:
61.将所述目标脚本函数所属的脚本文件的标识、所述目标脚本函数的标识以及所述调用指令中包含的至少一个调用参数的值移动到虚拟机的运行时栈的栈顶;
62.基于所述运行时栈的栈顶中的脚本文件的标识、目标脚本函数的标识、以及调用参数的值执行所述目标脚本函数,并将所述目标脚本函数的返回值存放到所述运行时栈的栈顶;
63.从所述运行时栈的栈顶获取所述目标脚本函数的返回值进行输出;
64.将所述运行时栈的栈顶还原至执行所述目标脚本函数前的状态。
65.根据本公开的第二方面,提供了一种脚本语言代码调试装置,包括:
66.第一位置属性获取模块,被配置为获取当前在虚拟机中被执行的操作码的第一位置属性,所述第一位置属性包括所述操作码所属的目标脚本代码文件的标识和所述操作码对应的脚本代码在所述目标脚本代码文件中的位置信息;
67.位置属性匹配模块,被配置为将所述第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配;
68.断点调试功能触发模块,被配置为在匹配成功时,调用预设断点跳转函数以在所述操作码处触发断点调试功能。
69.根据本公开的第三方面,提供了一种计算机可读存储介质,其上存储有计算机程序,所述程序被处理器执行时实现如上述实施例中第一方面所述的脚本语言代码调试方法。
70.根据本公开实施例的第四方面,提供了一种电子设备,包括:处理器;以及,存储装置,用于存储一个或多个程序,当所述一个或多个程序被所述一个或多个处理器执行时,使得所述一个或多个处理器实现如上述实施例中第一方面所述的脚本语言代码调试方法。
71.由上述技术方案可知,本公开示例性实施例中的脚本语言代码调试方法、脚本语言代码调试装置,以及实现所述脚本语言代码调试方法的计算机可读存储介质及电子设备,至少具备以下优点和积极效果:
72.在本公开的一些实施例所提供的技术方案中,首先,将获取的当前在虚拟机中被执行的操作码的第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配;然后,在匹配成功时,调用预设断点跳转函数以在所述操作码处触发断点调试功能。与相关技术相比,一方面,本公开中通过在预设断点存储容器配置代码调试中的断点,可以提高断点设置的效率;另一方面,本公开通过将当前在虚拟机中被执行的操作码的第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配,以触发断点调试功能,可以避免相关技术中虚拟机进程频繁的进行“中断

条件判断

继续执行”过程对代码调试性能的影响,提高代码调试的效率。
73.本公开应当理解的是,以上的一般描述和后文的细节描述仅是示例性和解释性的,并不能限制本公开。
附图说明
74.此处的附图被并入说明书中并构成本说明书的一部分,示出了符合本公开的实施例,并与说明书一起用于解释本公开的原理。显而易见地,下面描述中的附图仅仅是本公开的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
75.图1示出本公开一示例性实施例中脚本语言代码调试方法的流程示意图;
76.图2示出本公开一示例性实施例中预设断点存储数组的存储结构示意图;
77.图3示出本公开一示例性实施例中添加断点的方法的流程示意图;
78.图4示出本公开一示例性实施例中移除断点的方法的流程示意图;
79.图5示出本公开一示例性实施例中断点移除前后的预设断点存储数组的状态的示意图;
80.图6示出本公开一示例性实施例中将第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配的方法的流程示意图;
81.图7示出本公开一示例实施例中根据中断方式调试代码的方法的流程示意图;
82.图8示出本公开一示例性实施例中展示断点附件的脚本代码的方法的流程示意图;
83.图9示出本公开一示例性实施例中预先生成局部变量索引表的方法的流程示意
图;
84.图10示出本公开一示例性实施例中基于预先生成的局部变量索引表确定局部变量对应的索引值的方法的流程示意图;
85.图11示出本公开一示例性实施例中在中断期间对目标脚本函数进行调用的方法的流程示意图;
86.图12示出本公开一示例性实施例中另一种脚本代码调试方法的流程示意图;
87.图13示出本公开一示例性实施例中脚本语言代码调试装置的结构示意图;
88.图14示出本公开示例性实施例中计算机存储介质的结构示意图;以及,
89.图15示出本公开示例性实施例中电子设备的结构示意图。
具体实施方式
90.现在将参考附图更全面地描述示例实施方式。然而,示例实施方式能够以多种形式实施,且不应被理解为限于在此阐述的范例;相反,提供这些实施方式使得本公开将更加全面和完整,并将示例实施方式的构思全面地传达给本领域的技术人员。所描述的特征、结构或特性可以以任何合适的方式结合在一个或更多实施方式中。在下面的描述中,提供许多具体细节从而给出对本公开的实施方式的充分理解。然而,本领域技术人员将意识到,可以实践本公开的技术方案而省略所述特定细节中的一个或更多,或者可以采用其它的方法、组元、装置、步骤等。在其它情况下,不详细示出或描述公知技术方案以避免喧宾夺主而使得本公开的各方面变得模糊。
91.本说明书中使用用语“一个”、“一”、“该”和“所述”用以表示存在一个或多个要素/组成部分/等;用语“包括”和“具有”用以表示开放式的包括在内的意思并且是指除了列出的要素/组成部分/等之外还可存在另外的要素/组成部分/等;用语“第一”和“第二”等仅作为标记使用,不是对其对象的数量限制。
92.此外,附图仅为本公开的示意性图解,并非一定是按比例绘制。图中相同的附图标记表示相同或类似的部分,因而将省略对它们的重复描述。附图中所示的一些方框图是功能实体,不一定必须与物理或逻辑上独立的实体相对应。
93.lpc语言是由lars pensj
ǒ
在1989年根据c语言开发而来的脚本语言,主要用于开发mud(mutiple userdimension,多角色世界)游戏。
94.作为脚本语言,lpc代码的编译和执行都由其专门的引擎驱动程序来完成的。具体的,引擎驱动程序的编译模块首先将lpc脚本代码编译成opcode(操作码),opcode的功能和传统编译型语言编译后产生的机器码类似,只不过传统的编译性语言是在cpu上执行,而lpc脚本代码是在引擎驱动模块的虚拟机中执行。引擎驱动模块的虚拟机模块会循环读入下一个opcode,然后根据当前读入的opcode的含义来执行不同的功能。
95.代码的编写不可避免产生错误,当错误发生时程序员需要对代码进行调试。调试的本质是对代码执行过程的控制、追踪、修改,其中最基本的功能是中断。
96.针对传统编译型语言的动态调试器已经十分成熟,gdb工具是最常使用的调试工具之一。使用gdb工具调试用c语言编写的lpc引擎程序轻而易举,然而如果直接使用gdb工具调试在引擎的虚拟机中执行的lpc脚本则十分困难。具体的,虚拟机执行opcode的过程相当于执行一个大的“switch

case”语句的过程,无论当前的opcode属于哪个lpc文件的哪
一行,在虚拟机中的执行位置都是一样的,因此直接使用gdb工具在指定的lpc文件和行号处设置断点时,就只能使用条件断点,断点位置设置在执行opcode之前,断点条件设置为断点对应的opcode所属文件和所属行号。
97.同时,官方提供的lpc脚本代码的调试手段是原始的打印输出调试方法,即利用引擎驱动程序提供的内置函数debug_message(string msg)(不同版本的引擎的驱动可能有不同的内置函数名称,但功能是相同的,都是将参数中的字符串输出到debug文件),在需要的地方打印需要的信息,以达到调试的目的。
98.然而,直接使用现有的gdb条件断点的方式进行代码调试时,需要人工在不同地方插入各种调试代码,费时费力,同时添加的调试代码易和原本的逻辑代码混淆,且调试代码添加之后需要人工删除,此外,添加调试代码之后需要重新编译脚本和执行,增加调试时间。
99.此外,直接使用现有的gdb条件断点的方式进行代码调试,等待中断的时间较长,严重会降低调试性能。具体的,大多数的条件断点,需要正在调试的进程被中断之后在gdb这一层进行条件判断,条件符合则维持中断,不符合则交回控制权让正在调试的进程继续运行。在对一般进程进行条件断点时,并不会带来性能的严重影响,然而虚拟机执行opcode的地方会十分频繁的使用,如果在此处设置条件断点,则虚拟机的进程会频繁进行“中断

条件判断

继续执行”的过程,从而严重影响的调试的性能。
100.在本公开的实施例中,首先提供了一种脚本语言代码调试方法,至少在一定程度上克服上述相关技术中存在的缺陷。
101.图1示出本公开一示例性实施例中脚本语言代码调试方法的流程示意图,参考图1,该方法包括:
102.步骤s110,获取当前在虚拟机中被执行的操作码的第一位置属性,所述第一位置属性包括所述操作码所属的目标脚本代码文件的标识和所述操作码对应的脚本代码在所述目标脚本代码文件中的位置信息;
103.步骤s120,将所述第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配;
104.步骤s130,在匹配成功时,调用预设断点跳转函数以在所述操作码处触发断点调试功能。
105.在图1所示实施例所提供的技术方案中,首先,将获取的当前在虚拟机中被执行的操作码的第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配;然后,在匹配成功时,调用预设断点跳转函数以在所述操作码处触发断点调试功能。与相关技术相比,一方面,本公开中通过在预设断点存储容器配置代码调试中的断点,可以提高断点设置的效率;另一方面,本公开通过将当前在虚拟机中被执行的操作码的第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配,以触发断点调试功能,可以避免相关技术中虚拟机进程频繁的进行“中断

条件判断

继续执行”过程对代码调试性能的影响,提高代码调试的效率。
106.以下对图1所示实施例中各个步骤的具体实施方式进行详细阐述:
107.在步骤s110中,获取当前在虚拟机中被执行的操作码的第一位置属性。
108.本示例性实施方案中的脚本代码可以包括用lpc语言编写的脚本代码。步骤s110
中的虚拟机可以包括lpc脚本代码对应的引擎驱动程序中的虚拟机。具体的,对于lpc脚本代码而言,其编译和执行都由对应的引擎驱动程序来完成,引擎驱动程序的编译模块首先将lpc脚本代码编译成opcode(操作码),然后引擎驱动程序的虚拟机模块会循环读入一个opcode,根据读入的opcode的来执行不同的功能,以实现lpc脚本代码的逻辑。步骤s110中的当前在虚拟机中被执行的操作码可以理解为lpc脚本代码对应的引擎驱动程序中的虚拟机模块当前读入的opcode。
109.在示例性的实施方式中,当前在虚拟机中被执行的操作码的第一位置属性包括操作码所属的目标脚本代码文件的标识和操作码对应的脚本代码在目标脚本代码文件中的位置信息。其中,操作码所属的目标脚本代码文件的标识可以包括操作码所属的目标脚本代码文件的名称,操作码对应的脚本代码在目标脚本代码文件中的位置信息可以包括操作码对应的脚本代码在目标脚本代码文件中的行号。
110.例如,在lpc脚本代码文件1的第5行的脚本代码a被编译成了opcode1(操作码1),虚拟机代码interpret.c中的“eval_instruction”函数得到当前的opcode是opcode1,则可以获取到opcode1的第一位置属性为:lpc脚本代码文件1的第5行,即表示opcode1对应的脚本代码a在lpc脚本代码文件1的第5行。
111.接下来,在步骤s120中,将第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配。
112.在示例性的实施方式中,预设断点存储容器可以包括预设断点存储数组,预设断点存储数组中每个元素存储的断点数据包括断点的第二位置属性和元素的断点状态。
113.其中,断点的第二位置属性包括断点所属的脚本代码文件的标识和断点在脚本代码文件中的位置信息,例如,断点的第二位置属性可以表示断点被配置在哪个脚本代码文件的第几行。
114.元素的断点状态包括未存储断点或存储的断点已被移除的第一状态、已存储断点且已存储的断点无效的第二状态、已存储断点且已存储的断点有效的第三状态。可以理解的是,元素的断点状态用于指示元素当前是否能够用于存储断点数据。元素的断点状态也可以用于指示元素中存储的断点数据的状态。
115.具体的,当元素的断点状态为第一状态时,表示该元素中当前没有存储断点数据或存储的断点数据已被移除,即表示该元素可以用于存储用户新添加的断点数据;当元素的断点状态为第二状态或第三状态时,表示该元素中已经存储过了断点数据,当前不能被用于存储用户新添加的其它的断点数据。其中,当元素的断点状态为第二状态时,表示元素中当前存储的断点数据无效,即不触发断点调试功能,当元素的断点状态为第三状态时,表示元素中当前存储的断点数据有效,即可以触发断点调试功能。
116.举例而言,可以定义一个全局数组,用于存储用户(如代码调试人员)添加的断点信息,即为上述的预设断点存储数组。其中,全局数组的大小可以根据需求进行自定义,例如定义一个包括10的元素的全局数组,数组的大小符合即可以满足调试断点数量的需求,又不影响代码运行的性能的原则即可。全局数组的每个元素可以为用于存储断点数据的结构体,结构体中包含文件名、行号、状态标记。状态标记字段包括上述的第一状态、第二状态、第三状态共3个状态,每个元素的结构体中的状态标记为第一状态、第二状态、第三状态中的一种。例如,状态标记a表示上述的第一状态、状态标记b表示上述的第二状态、状态标
记c表示上述的第三状态。
117.图2示出本公开一示例性实施例中预设断点存储数组的存储结构示意图。参考图2,21表示预设断点存储数组中的元素,22表示预设断点存储数组中的元素中存储的断点数据,包括元素的断点状态、断点所属的脚本代码文件的文件名、断点在脚本代码文件中的行号信息。
118.需要说明的是,预设断点存储数组中每个元素的断点状态的初始状态标记为第一状态,即为未设置过断点的第一状态。
119.示例性的,在对脚本语言代码进行断点调试之前,可以根据调试需求,在上述的预设断点存储数组中添加调试时需要的断点数据。图3示出本公开一示例性实施例中添加断点的方法的流程示意图。参考图3,该方法可以包括步骤s310至步骤s320。
120.在步骤s310中,响应于添加目标断点的指令,根据元素的索引值的升序顺序遍历预设断点存储数组中的元素。
121.在步骤s320中,在遍历到断点状态为第一状态的元素时,将目标断点的第二位置属性存储至当前元素中,并将当前元素的断点状态重新配置为第三状态。
122.进一步的,用户还可以根据需求将不需要的断点数据从预设断点存储数组中移除。示例性的,图4示出本公开一示例性实施例中移除断点的方法的流程示意图。参考图4,该方法可以包括步骤s410至步骤s420。
123.在步骤s410中,响应于移除目标断点的操作指令,将目标断点对应的目标元素的断点状态重新配置为第一状态。
124.例如,目标断点存储在预设断点存储数组的第3个元素中,响应于移除目标断点的操作指令,可以将预设断点存储数组的第3个元素的状态重新配置为第一状态。而对于第3个元素中存储的需要被移除的目标断点的第二位置属性可以删除也可以不删除,但是第3个元素的断点状态需要被配置为第一状态。
125.在步骤s420中,在目标断点对应的目标元素之后存在断点状态为第二状态或第三状态的待调整元素时,针对待调整元素,依次将待调整元素中存储的断点数据前移至待调整元素对应的前一个元素中进行存储。
126.其中,在预设断点存储数组中,位于目标元素之后的待调整元素的索引值大于目标元素的索引值。也就是说,待调整元素可以包括预设断点存储数组中索引值大于目标断点对应的目标元素的索引值的元素。
127.需要说明的是,如果在目标断点对应的目标元素之后不存在断点状态为第二状态多第三状态的待调整元素,则只需要将目标断点对应的目标元素的断点状态重新配置为第一状态即可。此时的第一状态可以理解为当前元素存储过断点但存储的断点已被移除。
128.示例性的,图5示出本公开一示例性实施例中断点移除前后的预设断点存储数组的状态的示意图。参考图5,元素51中存储的断点为需要被移除的目标断点,即需要被移除的目标断点为“test.c:3”,该断点的断点数据存储在预设断点存储数组的第3个元素中。
129.在图5的示例中,位于断点存储数组的第3个元素之后的第4个元素和第5个元素中存储了其他的断点数据,即第4个元素和第5个元素的断点状态为第二状态或第三状态,则在移除目标断点“test.c:3”时,则可以先将第3个元素的断点状态重新配置为第一状态,然后将第4个元素中存储的断点数据前移至第3个元素中进行存储,将第5个元素中存储的断
点数据前移至第4个元素中进行存储。
130.在断点数据前移存储时,断点数据中的元素的断点状态保持不变,例如,在将第4个元素中存储的断点数据前移至第3个元素中存储之前,第4个元素中存储的元素的断点状态为第二状态,则前移后,第3个元素中存储的元素的断点状态仍为第二状态。也就是说,第3个元素之前重新配置的第一状态又被第4个元素中存储的元素的断点状态所替代。
131.示例性的,还可以通过预设的断点状态配置指令,修改预设断点存储数组中的元素的断点状态。其具体实施方式可以是:
132.响应于针对目标断点的无效状态配置指令,在预设断点存储数组中,将目标断点对应的目标元素的断点状态重新配置为第二状态;
133.响应于针对目标断点的有效状态配置指令,预设断点存储数组中,将目标断点对应的目标元素的断点状态重新配置为第三状态。
134.举例而言,在预设数组中添加了某个断点后,调试人员暂时不需要使用该断点,则可以通过预设的断点无效状态配置指令,将预设存储数组中存储该断点的元素的状态的配置为第二状态,当再次需要使用该断点时,又可以通过预设的断点有效状态配置指令,将预设存储数组中存储该断点的元素的状态重新配置为第三状态。
135.进一步的,还可以通过预设的断点数据查询指令,查询已经配置的断点数据。其具体实施方式可以是:
136.响应于断点查询操作指令,查询预设断点存储数组中存储的断点数据,并根据第一预设格式在客户端显示查询到的断点数据。
137.在示例性的实施方式中,第一预设格式可以包括根据断点所属的脚本文件的标识、断点在其所属的脚本文件的位置信息、元素的断点状态的顺序在客户端显示查询到的断点数据。例如根据“test.c:7,b”的格式在客户端显示查询到的断点数据。其中,b可以理解为上述的第二状态对的状态标记,其表示在test.c文件的第7行设置了断点,当前断点的状态为无效。
138.举例而言,可以预先编写与预设断点数组配套的断点数据操作函数,分别实现添加断点、移除断点、使断点无效或生效、查看断点的功能。
139.如前所述,状态标记a可以表示上述的第一状态、状态标记b可以表示上述的第二状态、状态标记c可以表示上述的第三状态。在添加断点时,断点数据操作函数可以遍历预设断点数据存储数组,直到遇到状态标记字段为a的元素,则添加断点并将元素的断点状态标记修改为c;移除断点时,断点数据操作函数可以将该断点对应的元素的断点状态标记修改为a并将该断点后的所有的断点数据往前移一个;使断点无效时,断点数据操作函数可以将该断点对应的元素的断点状态标记修改为b;使断点有效时,断点数据操作函数可以将该断点对应的元素的断点状态标记修改为c;查看断点数据时,断点数据操作函数可以将预设断点存储数组中存储的断点数据按照第一预设格式返回。
140.进一步的,可以将断点数据操作函数封装为断点添加指令(break)、断点移除指令(delete)、无效状态设置指令(disable)、有效状态设置指令(enable)、断点查询指令(info)。这样,代码调试人员可以方便的根据对应的指令调用上述的断点数据操作函数以实现对应的功能。
141.在预设断点存储容器中预先配置断点数据后,则可以将步骤s110中获取的第一位
置属性和预设断点存储容器中存储的断点的第二位置属性进行匹配,以实现lpc脚本语言代码的断点调试。
142.图6示出本公开一示例性实施例中将第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配的方法的流程示意图。参考图6,该方法可以包括步骤s610至步骤s630。其中:
143.在步骤s610中,根据预设断点存储数组中的元素的索引值的升序顺序,遍历预设断点存储数组中的元素。
144.其中,元素的索引值可以包括元素的下标。
145.在步骤s620中,在遍历到存储的第二位置属性与第一位置属性相同且断点状态为第三状态的元素时,停止遍历且确定第一位置属性和预设断点存储容器中配置的断点的第二位置属性匹配成功。
146.在步骤s630中,在遍历到存储的断点状态为第一状态的元素时,停止遍历且确定第一位置属性和预设断点容器中配置的断点的第二位置属性匹配失败,以使虚拟机继续执行下一个操作码。
147.举例而言,可以在lpc的虚拟机代码interpret.c的“eval_instruction”函数中执行opcode之前,插入一段代码,该代码的功能是遍历预设断点存储数组,一旦确定当前opcode的第一位置属性与某个断点状态为第三状态的元素中存储的第二位置属性相同,则确定匹配成功,即判断当前opcode为断点,且可以停止此次遍历;一旦遇到断点状态为第一状态的元素,则确定匹配失败,即判断当前opcode不是断点,且停止遍历,同时使虚拟机可以继续执行下一个opcode。
148.在本公开中,由于分别通过上述的步骤s310至步骤s320的断点添加方法和上述的步骤s410至步骤s440的断点移除方法来实现断点的添加和移除,则可以将断点设置在数组的前面,且由于断点数据中存储了元素的断点状态,这样,在步骤s120中进行第一位置属性和断点的第二位置属性的遍历匹配时,可以根据元素的断点状态确定是否继续进行遍历,从而可以提前终止遍历,提高断点的判断速度,进而可以进一步提升断点调试的效率和性能。
149.通过步骤s110和步骤s120,可以判断当前在虚拟机被执行的操作码是否为断点。进一步的,在判断当前在虚拟机被执行的操作码是否为断点时,还可以对当前的中断方式进行判断。
150.在示例性的实施方式中,中断方式可以包括运行到下次断点处(continue)、单步跳过(next)、单步进入(step)、单步完成(finish)。
151.举例而言,可以定义一个全局的中断方式变量,例如g_break_flag变量,其共有4个取值,分别为取值d代表中断方式为运行到下次断点处(continue)、取值e代表中断方式为单步跳过(next)、取值f代表中断方式为单步进入(step)、取值g代表中断方式为单步完成(finish)。
152.同时,可以编写gdb扩展的python脚本,在该脚本中分别封装continue、next、step、finish四种命令,在对这四种命令进行封装时,首先将g_break_flag的值变为每个命令对应的取值,然后执行gdb的continue命令,以在实现中断后将执行权交回虚拟机的进程。
153.例如,在对中断方式为运行到下次断点处的命令进行封装时,可以将g_break_flag的值取为e,然后执行gdb的continue命令。这样,当用户输入continue命令时,就可以知道当前的中断方式为运行到下次断点处,且在下次断点处执行断点功能后,可以通过执行gdb的continue命令,将执行权交回虚拟机的进程。
154.示例性的,步骤s120的具体实施方式可以是:在中断方式为运行到下一个断点处时,将第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配。
155.接下来,在步骤s130中,在匹配成功时,调用预设断点跳转函数以在操作码处触发断点调试功能。
156.示例性的,在中断方式为单步跳过、单步进入、单步完成中的任一种时,则可以只通过判断虚拟机的调用栈深度的变化,来确定是否执行中断。
157.具体的,在中断方式为单步跳过时,若虚拟机的当前调用栈深度不大于上次调用栈深度,则调用预设断点跳转函数以在所述操作码处触发断点调试功能;
158.在中断方式为单步进入时,若虚拟机的当前调用栈深度不小于上次调用栈深度,则调用预设断点跳转函数以在所述操作码处触发断点调试功能;
159.在中断方式为单步完成时,若虚拟机的当前调用栈深度小于上次调用栈深度,则调用预设断点跳转函数以在所述操作码处触发断点调试功能。
160.需要说明的是,在本公开中,仅在当前的断点的中断方式为运行到下一断点处时,才遍历预设断点存储容器,以进行第一位置属性和预设断点存储容器中配置的断点的第二位置属性的匹配。在断点的中断方式为单步跳过、单步进入、单步完成时,则不需要遍历预设断点存储容器,直接根据调用栈深度的变化,来确定是否执行中断。
161.图7示出本公开一示例实施例中根据中断方式调试代码的方法的流程示意图。参考图7,该方法可以包括步骤s710至步骤s780。
162.在步骤s710中,获取当前在虚拟机中被执行的操作码的第一位置属性;
163.在步骤s720中,判断当前的中断方式,在当前的中断方式为运行到下一个断点处时,执行步骤s730,在当前的中断方式为单步跳过时,执行步骤s740,在当前的中断方式为单步进入时,执行步骤s750,在当前的中断方式为单步完成时,执行步骤s760。
164.在步骤s730中,判断所述第一位置属性和预设断点存储容器中配置的断点的第二位置属性是否匹配,在匹配成功时,执行步骤s770,若否,则执行步骤s780。
165.在步骤s740中,判断当前调用栈深度是否小于或等于上次调用栈深度,若是,则执行步骤s770,若否,则执行步骤s780。
166.在步骤s750中,判断当前调用栈深度是否大于或等于上次调用栈深度,若是,则执行步骤s770,若否,则执行步骤s780。
167.在步骤s760中,判断当前调用栈深度是否小于上次调用栈深度,若是,则执行步骤s770,若否,则执行步骤s780。
168.在步骤s770中,调用预设断点跳转函数以触发断点调试功能。
169.在步骤s780中,继续执行下一个操作码。
170.通过上述的步骤s710至步骤s780,也可以实现不同方式的中断调试功能。其中,虚拟机的调用栈中可以包括多个栈帧,调用栈深度可以理解为调用栈中包含的栈帧的个数。
171.需要说明的是,在虚拟机的调用栈中,调用栈指针csp指向调用栈栈顶的指针,其
存储的是当前调用栈栈顶的地址,调用栈深度越大,调用栈指针csp也越大,所以在中断方式为单步跳过、单步进入、单步完成中的任一种时,也可以通过判断虚拟机的调用栈指针csp的变化,来确定是否执行中断,将上述的步骤s710至步骤s780中的技术术语“调用栈深度”替换为“调用栈指针csp”即可。
172.示例性的,上述的脚本语言代码调试方法还可以包括:响应于预设代码调试指令,开启代码调试进程,并在预设断点跳转函数处添加断点调试功能,以在调用预设断点跳转函数时触发断点调试功能。
173.其中,添加的断点调试功能可以包括gdb自带的断点调试功能。在预设断点跳转函数处添加了断点调试功能后,一旦虚拟机的进程调用预设断点跳转函数,则可以触发所添加的断点调试功能。
174.举例而言,可以编写一个断点跳转函数,例如debuger_trigger(),该函数内代码任意,例如,该函数可以调用debug_message(msg)将感兴趣的信息打印出来,将该函数作为预设断点跳转函数。同时,还可以编写gdb扩展的python脚本:python脚本启动后无限循环接收用户输入,将用户的输入作为指令解析。可以在该python脚本中封装代码调试指令,例如封装attach指令,该指令可以作为上述的预设代码调试指令,其功能是:开启一个代码调试进程,并自动在预设断点跳转函数“debugger_trigger”处添加一个断点,可以理解为自动在预设断点跳转函数处自动添加gdb自带的断点调试功能,一旦虚拟机的进程调用debuger_trigger函数,则会触发断点,即会触发gdb自带的断点调试功能以实现对脚本语言代码的断点调试。
175.示例性的,为了方便的代码调试,还可以在发生中断时,向用户展示断点附近的脚本代码。图8示出本公开一示例性实施例中展示断点附件的脚本代码的方法的流程示意图。参考图8,该方法可以包括步骤s810至步骤s830。其中:
176.在步骤s810中,若预设断点跳转函数触发断点调试功能,则获取所述操作码的第一位置属性;
177.在步骤s820中,基于所述第一位置属性,在所述操作码所属的目标脚本代码文件中读取待打印脚本代码;
178.在步骤s830中,根据第二预设格式在客户端显示所述操作代码对应的脚本代码和所述待打印脚本代码。
179.其中,待打印脚本代码包括在所述目标脚本代码文件中,与所述操作码对应的脚本代码的位置信息的差值在预设阈值内的脚本代码。
180.举例而言,可以在编写的gdb扩展的python脚本中,通过gdb.events.stop.connect(on_event)语句注册gdb中的断点处理函数,在断点处理函数中获取到当前opcode所属的脚本代码文件和当前opcod对应的脚本代码在该脚本代码文件中的行号,然后读取和该行号的差值在预设阈值内的脚本代码并格式化打印输出。例如,读取当前opcode对应的脚本代码所在的行号的前后两行的脚本代码并格式化打印输出。
181.以当前触发的断点在demo.c文件的第7行为例,可以根据第二预设格式输出如下的打印脚本代码:
[0182]“demo.c:7
[0183]
5:{
[0184]
6:int a=101;
[0185]
7:int b=202;
[0186]
8:int c=a+b;
[0187]
(lpc_gdb)”[0188]
其中,上述代码中“5、6、7、8”为脚本代码所在的行号,demo.c:7为设置的断点的第二位置属性。
[0189]
示例性的,在操作码处触发断点调试功能后,所述脚本语言代码调试方法还包括:
[0190]
响应于在当前中断期间针对目标全局变量值的查看指令,调用第一预设函数查询所述目标全局变量值,并生成目标全局变量值的第一序列化字符串,以在客户端显示第一序列化字符串;
[0191]
响应于在当前中断期间针对目标全局变量值的修改指令,调用第二预设函数将修改指令中的目标全局变量值进行反序列化,并将反序列化的目标全局变量值赋值给目标全局变量。
[0192]
举例而言,可以在脚本代码的虚拟机中添加打印变量值和导入变量值的函数,以实现对断点处可访问的变量值进行查看和修改的功能。
[0193]
例如,对于全局变量而言,可以定义第一预设函数,第一预设函数的名称可以为dump_global_value(char*name)。第一预设函数可以返回用户输入的全局变量的值的序列化字符串,其中,第一预设函数中的参数name可以表示全局变量的名字。具体的,第一预设函数可以调用lpc的虚拟机代码的object.c文件中的find_global_variable函数以查询用户输入的全局变量的值,调用lpc的虚拟机代码的object.c文件中的save_variable_2函数以将查询到的全局变量的值序列化。
[0194]
进一步的,可以定义第二预设函数,第二预设函数的名称可以为restore_global_value(char*name,char*value)。第二预设函数可以将用户输入的value字符串反序列化后的值赋给name对应的全局变量。具体的,第二预设函数可以调用lpc的虚拟机代码中的object.c文件中的restore_svalue函数以将用户输入的字符串反序列化。
[0195]
其中,序列化可以理解为将虚拟机中存储的不同类型的变量的值转换为字符串类型,由于虚拟机中存放的lpc变量值,有各种各样的类型,包括整型、字符串、数组、字典等,在把这些类型的变量的值展示给用户时,就需要先将它们序列化后转换成字符串,然后打印到客户端的显示界面中;同理,用户输入的变量的值通常为字符串的形式,因此,在使用用户输入的字符串类型的值来修改不同类型的变量的值时,就需要将字符串反序列化成对应的变量类型的值。
[0196]
示例性的,在操作码出触发断点调试功能后,所述脚本语言代码调试方法还包括:
[0197]
响应于在当前中断期间针对目标局部变量值的查看指令,调用第三预设函数基于预先生成的局部变量索引表确定目标局部变量的索引值,根据索引值查询目标局部变量对应的目标局部变量值,并生成目标局部变量值的第二序列化字符串,以在客户端显示第二序列化字符串;
[0198]
响应在当前中断期间针对目标局部变量值的修改指令,调用第四预设函数将所述修改指令中的目标局部变量值进行反序列化,并基于预先生成的局部变量索引表确定目标局部变量对应的索引值,根据所述索引值将反序列化后的目标局部变量值赋值给对应的目
标局部变量。
[0199]
举例而言,对于局部变量而言,由于在虚拟机编译lpc脚本代码后,局部变量的名字没有保留,所以可以通过索引的方式来查看和修改局部变量值。虚拟机代码interpret.c的变量fp中存储着当前的局部变量的起始地址,通过(fp+index),即可索引到要查询的局部变量值,其中index即为局部变量的索引值,其可以通过预先生成的局部变量的索引表确定。
[0200]
对于局部变量的值的查看而言,可以定义第三预设函数,例如,第三预设函数的名称可以为dump_local_value_by_index(int index),其可以根据用户输入的局部变量的索引值index查询该局部变量的值,并返回局部变量的值的序列化字符串。同样的,第三预设函数可以调用lpc的虚拟机代码的object.c文件中的save_variable_2函数以将查询到的局部变量的值进行序列化。
[0201]
对于局部变量的值的修改而言,可以定义第四预设函数,例如第四函数的名称可以为restore_local_value_by_index(int index,char*value),第四预设函数可以将value字符串反序列化后的值赋给index对应的局部变量。同样的,第四预设函数可以调用lpc的虚拟机代码中的object.c文件中的restore_svalue函数以将用户输入的value字符串反序列化。
[0202]
进一步的,图9示出本公开一示例性实施例中预先生成局部变量索引表的方法的流程示意图。参考图9,该方法可以包括步骤s910至步骤s920。
[0203]
在步骤s910中,在对脚本代码文件进行编译时,针对解析到的每个局部变量定义处,获取局部变量所属的脚本代码文件的标识、局部变量所属的函数的标识、局部变量的位置信息以及局部变量在所述函数包含的局部变量中被定义的顺序。
[0204]
其中,局部变量的位置信息包含局部变量定义处在脚本代码文件中的位置信息,例如,局部变量定义处在脚本代码文件中的行号。局部变量在所述函数包含的局部变量中被定义的顺序可以包括当前局部变量是其所属的函数中被定义的第几个局部变量。
[0205]
示例性的,在对脚本代码文件进行调试的过程中,需要在虚拟机中执行脚本代码文件对应的opcode,因此,编译模块会将脚本代码文件进行编译,以将脚本代码编译成opcode。在对脚本代码文件进行编译时,可以在解析到局部变量定义处时,获取当前定义的局部变量所在的脚本代码文件名、函数名、当前局部变量定义处在脚本代码文件中的行号、当前局部变量是其所属的函数中被定义的第几个局部变量。
[0206]
在步骤s920中,在根据所述脚本代码文件的标识和所述函数的标识所确定的局部变量索引表中,存储所述局部变量的标识、所述局部变量的位置信息以及所述局部变量被定义的顺序,以生成所述函数的局部变量索引表。
[0207]
示例性的,在某个函数中定义了局部变量时,可以根据该函数所属的脚本代码文件的标识和该函数的标识生成该函数的布局变量索引表,然后,在该函数的局部变量索引表中存储该函数中被定义的各局部变量的标识、各局部变量对应的定义处的位置信息和局部变量对应的被定义的顺序,从而生成该函数的局部变量索引表。
[0208]
需要说明的是,在某个函数中可能存在具有不同作用域的相同名称的局部变量,对于相同名称的局部变量需要各自存储其对应的定义处的位置信息和被定义的顺序。
[0209]
在生成每个函数的局部变量索引表后,可以存储每个函数的局部变量索引表。从
而在触发断点后,可以根据函数的局部变量索引表确定出用户想要查询或修改的局部变量的索引值。
[0210]
示例性的,图10示出本公开一示例性实施例中基于预先生成的局部变量索引表确定局部变量对应的索引值的方法的流程示意图。参考图10,该方法可以包括步骤s1010至步骤s1040。
[0211]
在步骤s1010中,响应于在当前中断期间针对目标局部变量值的查看指令或修改指令,获取造成当前中断的当前断点所属的目标脚本代码文件的标识和目标函数的标识,以确定出待查询的局部变量索引表。
[0212]
示例性的,在当前中断期间,可以将造成当前中断的当前断点所属的脚本代码文件的标识和所属函数的标识所确定的局部变量索引表,作为待查询的局部变量索引表。
[0213]
在步骤s1020中,在待查询的局部变量索引表中,确定出与查看指令或修改指令中的目标局部变量的标识相同且位置信息小于或等于当前断点在目标脚本代码文件中的位置信息的待查询局部变量。
[0214]
示例性的,在中断期间,需要修改或查看的局部变量为断点处或断点处之前的局部变量,因此,需要在待查询的局部变量索引表中,确定与对应的指令中的局部变量的标识相同且位置信息小于或等于当前断点在脚本代码文件中的位置信息的局部变量。
[0215]
接下来,在步骤s1030中,确定位置信息与当前断点在目标代码文件中的位置信息的差值最小的待查询局部变量为目标局部变量。
[0216]
示例性的,如前所述,在同一个函数中,可能会存在由于被定义在脚本代码文件的不同位置而具有不同作用域的同名局部变量,因此,在待查询的局部变量索引表中,可能会确定出多个待查询局部变量,可以将距离当前断点处最近的局部变量确定为目标局部变量。
[0217]
在步骤s1040中,根据所述目标局部变量对应的被定义的顺序,确定出所述查看指令或修改指令中的目标局部变量对应的索引值。
[0218]
在示例性的实施方式中,可以将目标局部变量对应的被定义的顺序,确定为目标局部变量对应的索引值。
[0219]
示例性的,确定局部变量对应的索引值后,例如为idex,虚拟机代码interpret.c中的变量fp中存储着当前的目标局部变量的起始地址,根据(fp+index)即可索引到当前的目标局部变量的值,以对其执行修改或查询操作。
[0220]
举例而言,lpc脚本语言代码的编译采用了语法制导的翻译方式,在语法解析阶段,在解析到局部变量定义处时,可以获取当前定义的局部变量所在的lpc文件名、函数名、及其在lpc文件中的行号以及当前被定义的局部变量在其对应的函数中被定义的顺序(即定义序号,可以表示该局部变量是其所在的函数中的第几个局部变量),此时可以以“文件名+函数名”的形式保存一个局部变量索引表文件,然后将该局部变量的局部变量名、在lpc文件中的行号和在对应的函数中被定义的顺序添加到保存的局部变量索引表文件中。
[0221]
在动态调试时,当触发了lpc脚本的断点后,虚拟机中可以获取当前断点所属的lpc文件名、函数名和其在lpc文件中的行号,此时,需要修改或查看某个局部变量的值时,则可以在当前断点所属的lpc文件名和函数名对应的局部变量索引表中,找到与需要修改或查看的局部变量名同名,且对应的行号小于或等于当前断点所在的行号,且对应的行号
与当前断点所在的行号的差值最小的局部变量,其就是要查询或修改的局部变量,取出该局部变量对应的被定义的顺序,将其作为局部变量的索引值index,进而根据上述的根据(fp+index)即可索引到当前的目标局部变量的值。
[0222]
在示例性的实施方式中,可以编写gdb扩展的python脚本,以封装修改或查看全局变量或局部变量的指令,方便用户操作。具体的,可以编写lpc_file模块,功能是解析lpc脚本文件,解析出每个函数内的局部变量的定义顺序,以预先生成局部变量索引表,从而可以通过局部变量索引表确定当前要查询或修改的局部变量的索引值。
[0223]
同时,可以封装print、set、print_local、set_local四个命令,print命令和set命令分别将用户输入的变量名直接传入第一预设函数(如上述的dump_global_value函数)和第二预设函数(如上述的restore_global_value函数),实现对全局变量的查看和修改。print_local命令和set_local命令分别先将用户输入的变量名通过上述的lpc_file模块转换为对应的索引值,再分别将索引值传入第三预设函数(如上述的dump_local_value_by_index函数)和第四预设函数(如上述的restore_local_value_by_index函数,以实现对局部变量的查看和修改。
[0224]
进一步的,在所述操作码处触发断点调试功能后,所述方法还包括:响应于在当前中断期间针对当前断点处的调用栈的查看指令,调用第五预设函数遍历虚拟机的栈帧,以获取当前断点处的调用栈信息,并根据第三预设格式在客户端显示所述当前断点处的调用栈信息。
[0225]
其中,当前断点处的调用栈信息可以理解为当前断点处的函数调用关系。通过当前断点处的调用栈信息可以回溯断点函数的来源,便于调试人员更高效的调试代码。
[0226]
示例性的,在本公开中,可以在客户端的显示界面中打印当前断点处的调用栈。具体的,可以定义第五预设函数,其功能是根据第三预设格式返回lpc当前断点处的调用栈信息。
[0227]
举例而言,可以定义第五预设函数“dump_backtrace()”,其功能是将当前断点处的lpc调用栈按照一定格式组成字符串并返回。具体的,lpc的虚拟机代码interpret.c中的变量control_stack中存储着调用栈的起始地址,csp是当前栈顶的地址,调用栈的每个栈帧都包含了调用下一个函数时所在的位置信息以及下一个函数在下一个lpc文件函数表中的索引,因此通过遍历栈帧可以获取到每次函数调用的跳转信息,然后通过第三预设格式返回获取到的函数调用的跳转信息。例如,demo.c文件中的某段代码如下所示:
[0228]“1void test2()
[0229]
2{
[0230]
3int a=10;
[0231]
4}
[0232]
5void test()
[0233]
6{
[0234]
7test2()
[0235]
8}
[0236]
9void create()
[0237]
10{
[0238]
11test()
[0239]
12}”[0240]
其中,在上述的12行代码中,每行代码最前面的数字为该代码的行号,其不属于代码本身的内容。如果在上述代码的第11行触发断点,则响应于在当前中断期间针对当前断点处的调用栈的查看指令,可以按照第三预设格式返回如下的调用栈信息:
[0241]“call test2()at/demo.c:7
[0242]
call test()at/demo.c:11”[0243]
上述返回的断点处的调用栈信息可以表示:在demo.c的11行调用了test()函数,然后又在test()函数中demo.c的第7行调用了test2()函数。
[0244]
在示例性的实施方式中,可以对查询断点处的调用栈的指令进行封装,例如将第五预设函数封装为“backtrace”指令,在用户输入“backtrace”指令时,可以调用第五预设函数实现当前断点处的调用栈的打印输出。
[0245]
进一步的,在所述操作码处触发断点调试功能后,所述脚本语言代码调试方法还包括:
[0246]
响应于在当前中断期间针对目标脚本函数的调用指令,调用第六预设函数执行所述目标脚本函数。
[0247]
示例性的,图11示出本公开一示例性实施例中在中断期间对目标脚本函数进行调用的方法的流程示意图。参考图11,该方法可以包括步骤s1110至步骤s1140。其中:
[0248]
在步骤s1110中,将目标脚本函数所属的脚本文件的标识、目标脚本函数的标识以及调用指令中包含的至少一个调用参数的值移动到虚拟机的运行时栈的栈顶。
[0249]
示例性的,可以通过调用虚拟机的内置函数“push_svalue”,将目标脚本函数所属的脚本文件的标识、目标脚本函数的标识、以及用户输入的至少一个调用参数的值移动移动到虚拟机的运行时栈的栈顶。
[0250]
在步骤s1120中,基于运行时栈的栈顶中的脚本文件的标识、目标脚本函数的标识、以及调用参数的值执行目标脚本函数,并将目标脚本函数的返回值存放到运行时栈的栈顶。
[0251]
示例性的,可以调用虚拟机的内置函数“f_call_other”,将运行时栈中的值看作要调用的脚本代码文件的标识、函数的标识以及参数的值,然后根据脚本代码文件的标识和函数的标识以及参数的值调用对应的脚本代码文件中对应的函数,并将函数的返回值存放到运行时栈的栈顶。
[0252]
接下来,在步骤s1130中,从运行时栈的栈顶获取目标脚本函数的返回值进行输出。
[0253]
示例性的,虚拟机可以从运行时栈的栈顶获取目标脚本函数的返回值并打印输出在客户端的显示界面中。
[0254]
在步骤s1140中,将运行时栈的栈顶还原至执行目标脚本函数前的状态。
[0255]
示例性的,在执行完目标脚本函数后,可以调用虚拟机的内置函数“pop_stack”将运行时栈还原至执行目标脚本函数之前的状态。这样,既可以实现在中断期间对目标脚本函数的执行调用,又不影响后续的调试过程。
[0256]
举例而言,可以预先定义第六预设函数,第六预设函数的名称可以为“call_
debuger_func”,对应的第六预设函数的形式可以为“call_debuger_func(char*filename,char*funcname,int numarg,

)”。具体的,前3个参数分别为要执行的目标脚本函数所属的脚本代码文件的文件名、要执行的目标脚本函数的函数名、以及要传参的个数,最后的
“…”
为可变长参数,其中,可变长参数表示可传入numarg个字符串,且每个字符串都可反序列化为一个参数值。第六预设函数的功能是执行一次用户指定的目标脚本文件中的目标脚本函数,将目标脚本函数的返回值作为第六预设函数的返回值。第六预设函数的实现过程可以是:先调用虚拟机的内置函数“push_svalue”以将传入的“filename、funcname,以及多个参数值(即传入numarg个字符串被反序列化后的参数值)”移动到运行时栈的栈顶中,然后调用虚拟机中的内置函数“f_call_other”,最后再调用虚拟机中的内置函数“pop_stack”运行时栈的栈顶还原到执行目标脚本函数之前的状态。
[0257]
其中,“f_call_other”函数的功能是将运行时栈中的几个值看作是要调用执行的lpc文件名、函数名、参数值,然后调用对应的lpc文件中对应的函数,并将函数的返回值放到栈顶,待调用处取用。
[0258]
图12示出本公开一示例性实施例中另一种脚本代码调试方法的流程示意图。参考图12,该方法可以包括步骤s1210至步骤s1260。其中:
[0259]
在步骤s1210中,获取当前在虚拟机中被执行的操作码的第一位置属性。其中,步骤s1210中的第一位置属性的说明可以参考和上述的步骤s110中的第一位置属性的说明。
[0260]
在步骤s1220中,遍历预设断点存储数组,将第一位置属性和预设断点存储数组中的断点的第二位置属性进行匹配。
[0261]
在步骤s1230中,判断是否在当前操作码处设置断点,若是,则转至步骤s1240,否则,转至步骤s1250。
[0262]
示例性的,在第一位置属性和预设断点存储数组中的断点的第二位置属性相同时,则确定在当前操作码处设置了断点,否则没有在当前操作码处设置断点。
[0263]
在步骤s1240中,判断在当前操作码处设置的断点是否生效,若是,则转至步骤s1260,否则转至步骤s1250。
[0264]
举例而言,可以根据预设断点存储数组中的元素的断点状态确定当前操作码处设置的断点是否生效。若为上述的第二状态则无效,若为上述的第三状态则有效。
[0265]
在步骤s1250中,继续执行下一个操作码。
[0266]
在步骤s1260中,调用预设断点调试函数在当前操作码处实现中断。
[0267]
通过本公开的实施方式,通过对虚拟机程序的改造,可以将判断断点的触发从gdb的条件断点方式调整为直接在虚拟机中进行,免去了频繁中断的消耗,大大提升了在调试过程中的运行性能,提高了lpc脚本语言代码动态调试的效率。
[0268]
进一步的,由于在预设断点数组中,将设置的断点都存储在预设断点存储数组的前面的元素中,即将设置的断点都存储在索引值小的元素中,在按照索引值的升序顺序遍历预设断点数组时,一旦遍历到未设置断点的元素或设置的断点被移除的元素,则可以直接停止遍历,保证了不一定必须完全遍历预设断点存储数组,进一步提升断点调试的性能和效率。
[0269]
与此同时,通过编译时将每个lpc文件的每个函数或模块中的局部变量名和其对应的索引值的映射关系存储到局部变量索引表中,可以根据用户输入的局部变量名,自动
的索引到对应的局部变量,避免用户自己人工计算局部变量的索引值的过程,降低了在虚拟机中调试lpc脚本代码的使用门槛,进一步提高了断点调试的效率。
[0270]
通过相关的预设函数和对应的封装指令,可以实现对断点处可访问的变量值进行查看和修改的功能、打印lpc当前断点处的调用栈的功能、在中断期间执行任意指定脚本函数的功能,进一步方便用户使用gdb工具对lpc脚本代码进行高效的调试。
[0271]
本领域技术人员可以理解实现上述实施方式的全部或部分步骤被实现为由cpu执行的计算机程序。在该计算机程序被cpu执行时,执行本发明提供的上述方法所限定的上述功能。所述的程序可以存储于一种计算机可读存储介质中,该存储介质可以是只读存储器,磁盘或光盘等。
[0272]
此外,需要注意的是,上述附图仅是根据本发明示例性实施方式的方法所包括的处理的示意性说明,而不是限制目的。易于理解,上述附图所示的处理并不表明或限制这些处理的时间顺序。另外,也易于理解,这些处理可以是例如在多个模块中同步或异步执行的。
[0273]
图13示出本公开一示例性实施例中脚本语言代码调试装置的结构示意图。参考图13,该脚本语言代码调试装置1300可以包括第一位置属性获取模块1310、位置属性匹配模块1320以及断点调试功能触发模块1330。
[0274]
第一位置属性获取模块1310,被配置为获取当前在虚拟机中被执行的操作码的第一位置属性,所述第一位置属性包括所述操作码所属的目标脚本代码文件的标识和所述操作码对应的脚本代码在所述目标脚本代码文件中的位置信息;
[0275]
位置属性匹配模块1320,被配置为将所述第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配;
[0276]
断点调试功能触发模块1330,被配置为在匹配成功时,调用预设断点跳转函数以在所述操作码处触发断点调试功能。
[0277]
在本公开的一种示例性实施方式中,基于前述实施例,预设断点存储容器包括预设断点存储数组,所述预设断点存储数组中每个元素存储的断点数据包括所述断点的第二位置属性和所述元素的断点状态;
[0278]
其中,所述断点的第二位置属性包括断点所属的脚本代码文件的标识和断点在所述脚本代码文件中的位置信息;
[0279]
所述元素的断点状态包括未存储断点或存储的断点已被移除的第一状态、已存储断点且已存储的断点无效的第二状态、已存储断点且已存储的断点有效的第三状态。
[0280]
在本公开的一种示例性实施方式中,基于前述实施例,上述脚本语言代码调试装置1300还可以包括断点添加模块和断点移除模块,其中:
[0281]
断点添加模块被配置为响应于添加目标断点的操作指令,根据元素的索引值的升序顺序遍历所述预设断点存储数组中的元素,在遍历到断点状态为第一状态的元素时,将所述目标断点的第二位置属性存储至所述元素中,并将所述元素的断点状态重新配置为第三状态;
[0282]
断点移除模块被配置为响应于移除目标断点的操作指令,将所述目标断点对应的目标元素的断点状态重新配置为第一状态,在所述目标断点对应的目标元素之后存在断点状态为第二状态或第三状态的待调整元素时,针对所述待调整元素,依次将所述待调整元
素中存储的断点数据前移至所述待调整元素对应的前一个元素中进行存储;
[0283]
其中,在所述预设断点存储数组中,位于目标元素之后的待调整元素的索引值大于所述目标元素的索引值。
[0284]
在本公开的一种示例性实施方式中,基于前述实施例,上述脚本语言代码调试装置1300还可以包括断点无效模块、断点有效模块和断点查询模块,其中:
[0285]
断点无效模块被配置为响应于针对目标断点的无效状态配置指令,在所述预设断点存储数组中,将所述目标断点对应的目标元素的断点状态重新配置为第二状态;
[0286]
断点有效模块被配置为响应于针对目标断点的有效状态配置指令,在所述预设断点存储数组中,将所述目标断点对应的目标元素的断点状态重新配置为第三状态;
[0287]
断点查询模块被配置为响应于断点查询操作指令,查询所述预设断点存储数组中存储的断点数据,并根据第一预设格式在客户端显示查询到的所述断点数据。
[0288]
在本公开的一种示例性实施方式中,基于前述实施例,上述的位置属性匹配模块1320还被具体配置为:
[0289]
根据所述预设断点存储数组中的元素的索引值的升序顺序,遍历所述预设断点存储数组中的元素;
[0290]
在遍历到存储的第二位置属性与所述第一位置属性相同且断点状态为第三状态的元素时,停止遍历且确定所述第一位置属性和所述预设断点存储容器中配置的断点的第二位置属性匹配成功;
[0291]
在遍历到存储的断点状态为第一状态的元素时,停止遍历且确定所述第一位置属性和所述预设断点容器中配置的断点的第二位置属性匹配失败,以使所述虚拟机继续执行下一个操作码。
[0292]
在本公开的一种示例性实施方式中,基于前述实施例,上述的位置属性匹配模块1320还被具体配置为:
[0293]
在中断方式为运行到下一个断点处时,将所述第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配。
[0294]
在本公开的一种示例性实施方式中,基于前述实施例,脚本语言代码调试装置1300还包括中断方式确定模块,该中断方式确定模块被配置为:
[0295]
在中断方式为单步跳过时,若虚拟机的当前调用栈深度不大于上次调用栈深度,则调用预设断点跳转函数以在所述操作码处触发断点调试功能;
[0296]
在中断方式为单步进入时,若虚拟机的当前调用栈深度不小于上次调用栈深度,则调用预设断点跳转函数以在所述操作码处触发断点调试功能;
[0297]
在中断方式为单步完成时,若虚拟机的当前调用栈深度小于上次调用栈深度,则调用预设断点跳转函数以在所述操作码处触发断点调试功能。
[0298]
在本公开的一种示例性实施方式中,基于前述实施例,上述的脚本语言代码调试装置1300还包括断点功能预添加模块,该模块被具体配置为:
[0299]
响应于预设代码调试指令,开启代码调试进程,并在预设断点跳转函数处添加断点调试功能,以在调用所述预设断点跳转函数时触发所述断点调试功能。
[0300]
在本公开的一种示例性实施方式中,基于前述实施例,上述的脚本语言代码调试装置1300还包括断点代码打印模块,该模块被配置为:
[0301]
若所述预设断点跳转函数触发断点调试功能,则获取所述操作码的第一位置属性;
[0302]
基于所述第一位置属性,在所述操作码所属的目标脚本代码文件中读取待打印脚本代码;
[0303]
根据第二预设格式在客户端显示所述操作代码对应的脚本代码和所述待打印脚本代码;
[0304]
其中,所述待打印脚本代码包括在所述目标脚本代码文件中,与所述操作码对应的脚本代码的位置信息的差值在预设阈值内的脚本代码。
[0305]
在本公开的一种示例性实施方式中,基于前述实施例,上述的脚本语言代码调试装置1300还包括全局变量访问模块,该全局变量访问模块被具体配置为:
[0306]
响应于在当前中断期间针对目标全局变量值的查看指令,调用第一预设函数查询所述目标全局变量值,并生成所述目标全局变量值的第一序列化字符串,以在客户端显示所述第一序列化字符串;
[0307]
响应于在当前中断期间针对目标全局变量值的修改指令,调用第二预设函数将所述修改指令中的目标全局变量值进行反序列化,并将反序列化的目标全局变量值赋值给所述目标全局变量。
[0308]
在本公开的一种示例性实施方式中,基于前述实施例,上述的脚本语言代码调试装置1300还包括局部变量访问模块,该局部变量访问模块被具体配置为:
[0309]
响应于在当前中断期间针对目标局部变量值的查看指令,调用第三预设函数基于预先生成的局部变量索引表确定目标局部变量的索引值,根据所述索引值查询所述目标局部变量对应的目标局部变量值,并生成所述目标局部变量值的第二序列化字符串,以在客户端显示所述第二序列化字符串;
[0310]
响应在当前中断期间针对目标局部变量值的修改指令,调用第四预设函数将所述修改指令中的目标局部变量值进行反序列化,并基于预先生成的局部变量索引表确定目标局部变量对应的索引值,根据所述索引值将反序列化后的目标局部变量值赋值给所述目标局部变量。
[0311]
在本公开的一种示例性实施方式中,基于前述实施例,通过以下方式预先生成所述局部变量索引表:
[0312]
在对脚本代码文件进行编译时,针对解析到的每个局部变量定义处,获取局部变量所属的脚本代码文件的标识、局部变量所属的函数的标识、局部变量的位置信息以及局部变量在所述函数包含的局部变量中被定义的顺序;
[0313]
在根据所述脚本代码文件的标识和所述函数的标识所确定的局部变量索引表中,存储所述局部变量的标识、所述局部变量的位置信息以及所述局部变量被定义的顺序,以生成所述函数的局部变量索引表;
[0314]
其中,所述局部变量的位置信息包含所述局部变量定义处在所述脚本代码文件中的位置信息;
[0315]
在本公开的一种示例性实施方式中,基于前述实施例,所述基于预先生成的局部变量索引表确定目标局部变量对应的索引值,包括:
[0316]
响应于在当前中断期间针对目标局部变量值的查看指令或修改指令,获取造成当
前中断的当前断点所属的目标脚本代码文件的标识和目标函数的标识,以确定出待查询的局部变量索引表;
[0317]
在所述待查询的局部变量索引表中,确定出与所述查看指令或修改指令中的目标局部变量的标识相同且位置信息小于或等于当前断点在目标脚本代码文件中的位置信息的待查询局部变量;
[0318]
确定位置信息与所述当前断点在目标代码文件中的位置信息的差值最小的待查询局部变量为目标局部变量;
[0319]
根据所述目标局部变量对应的被定义的顺序,确定出所述查看指令或修改指令中的目标局部变量对应的索引值。
[0320]
在本公开的一种示例性实施方式中,基于前述实施例,脚本语言代码调试装置1300还包括调用栈信息查看模块,该模块被配置为:
[0321]
响应于在当前中断期间针对当前断点处的调用栈的查看指令,调用第五预设函数遍历虚拟机的栈帧,以获取当前断点处的调用栈信息,并根据第三预设格式在客户端显示所述当前断点处的调用栈信息。
[0322]
在本公开的一种示例性实施方式中,基于前述实施例,脚本语言代码调试装置1300还包括目标脚本函数执行模块,该模块被配置为:
[0323]
响应于在当前中断期间针对目标脚本函数的调用指令,调用第六预设函数执行所述目标脚本函数;
[0324]
其中,所述调用第六预设函数执行所述目标脚本函数包括:
[0325]
将所述目标脚本函数所属的脚本文件的标识、所述目标脚本函数的标识以及所述调用指令中包含的至少一个调用参数的值移动到虚拟机的运行时栈的栈顶;
[0326]
基于所述运行时栈的栈顶中的脚本文件的标识、目标脚本函数的标识、以及调用参数的值执行所述目标脚本函数,并将所述目标脚本函数的返回值存放到所述运行时栈的栈顶;
[0327]
从所述运行时栈的栈顶获取所述目标脚本函数的返回值进行输出;
[0328]
将所述运行时栈的栈顶还原至执行所述目标脚本函数前的状态。
[0329]
上述脚本语言代码调试装置中各单元的具体细节已经在对应的脚本语言代码调试方法中进行了详细的描述,因此此处不再赘述。
[0330]
应当注意,尽管在上文详细描述中提及了用于动作执行的设备的若干模块或者单元,但是这种划分并非强制性的。实际上,根据本公开的实施方式,上文描述的两个或更多模块或者单元的特征和功能可以在一个模块或者单元中具体化。反之,上文描述的一个模块或者单元的特征和功能可以进一步划分为由多个模块或者单元来具体化。
[0331]
此外,尽管在附图中以特定顺序描述了本公开中方法的各个步骤,但是,这并非要求或者暗示必须按照该特定顺序来执行这些步骤,或是必须执行全部所示的步骤才能实现期望的结果。附加的或备选的,可以省略某些步骤,将多个步骤合并为一个步骤执行,以及/或者将一个步骤分解为多个步骤执行等。
[0332]
通过以上的实施方式的描述,本领域的技术人员易于理解,这里描述的示例实施方式可以通过软件实现,也可以通过软件结合必要的硬件的方式来实现。因此,根据本公开实施方式的技术方案可以以软件产品的形式体现出来,该软件产品可以存储在一个非易失
性存储介质(可以是cd

rom,u盘,移动硬盘等)中或网络上,包括若干指令以使得一台计算设备(可以是个人计算机、服务器、移动终端、或者网络设备等)执行根据本公开实施方式的方法。
[0333]
在本公开示例性实施方式中,还提供了一种能够实现上述方法的计算机存储介质。其上存储有能够实现本说明书上述方法的程序产品。在一些可能的实施例中,本公开的各个方面还可以实现为一种程序产品的形式,其包括程序代码,当所述程序产品在终端设备上运行时,所述程序代码用于使所述终端设备执行本说明书上述“示例性方法”部分中描述的根据本公开各种示例性实施方式的步骤。
[0334]
参考图14所示,描述了根据本公开的实施方式的用于实现上述方法的程序产品1400,其可以采用便携式紧凑盘只读存储器(cd

rom)并包括程序代码,并可以在终端设备,例如个人电脑上运行。然而,本公开的程序产品不限于此,在本文件中,可读存储介质可以是任何包含或存储程序的有形介质,该程序可以被指令执行系统、装置或者器件使用或者与其结合使用。
[0335]
所述程序产品可以采用一个或多个可读介质的任意组合。可读介质可以是可读信号介质或者可读存储介质。可读存储介质例如可以为但不限于电、磁、光、电磁、红外线、或半导体的系统、装置或器件,或者任意以上的组合。可读存储介质的更具体的例子(非穷举的列表)包括:具有一个或多个导线的电连接、便携式盘、硬盘、随机存取存储器(ram)、只读存储器(rom)、可擦式可编程只读存储器(eprom或闪存)、光纤、便携式紧凑盘只读存储器(cd

rom)、光存储器件、磁存储器件、或者上述的任意合适的组合。
[0336]
计算机可读信号介质可以包括在基带中或者作为载波一部分传播的数据信号,其中承载了可读程序代码。这种传播的数据信号可以采用多种形式,包括但不限于电磁信号、光信号或上述的任意合适的组合。可读信号介质还可以是可读存储介质以外的任何可读介质,该可读介质可以发送、传播或者传输用于由指令执行系统、装置或者器件使用或者与其结合使用的程序。
[0337]
可读介质上包含的程序代码可以用任何适当的介质传输,包括但不限于无线、有线、光缆、rf等等,或者上述的任意合适的组合。
[0338]
可以以一种或多种程序设计语言的任意组合来编写用于执行本公开操作的程序代码,所述程序设计语言包括面向对象的程序设计语言—诸如java、c++等,还包括常规的过程式程序设计语言—诸如“c”语言或类似的程序设计语言。程序代码可以完全地在用户计算设备上执行、部分地在用户设备上执行、作为一个独立的软件包执行、部分在用户计算设备上部分在远程计算设备上执行、或者完全在远程计算设备或服务器上执行。在涉及远程计算设备的情形中,远程计算设备可以通过任意种类的网络,包括局域网(lan)或广域网(wan),连接到用户计算设备,或者,可以连接到外部计算设备(例如利用因特网服务提供商来通过因特网连接)。
[0339]
此外,在本公开的示例性实施例中,还提供了一种能够实现上述方法的电子设备。
[0340]
所属技术领域的技术人员能够理解,本公开的各个方面可以实现为系统、方法或程序产品。因此,本公开的各个方面可以具体实现为以下形式,即:完全的硬件实施方式、完全的软件实施方式(包括固件、微代码等),或硬件和软件方面结合的实施方式,这里可以统称为“电路”、“模块”或“系统”。
[0341]
下面参照图15来描述根据本公开的这种实施方式的电子设备1500。图15显示的电子设备1500仅仅是一个示例,不应对本公开实施例的功能和使用范围带来任何限制。
[0342]
如图15所示,电子设备1500以通用计算设备的形式表现。电子设备1500的组件可以包括但不限于:上述至少一个处理单元1510、上述至少一个存储单元1520、连接不同系统组件(包括存储单元1520和处理单元1510)的总线1530以及显示单元1540。
[0343]
其中,所述存储单元存储有程序代码,所述程序代码可以被所述处理单元1510执行,使得所述处理单元1510执行本说明书上述“示例性方法”部分中描述的根据本公开各种示例性实施方式的步骤。例如,所述处理单元1510可以执行如图1中所示的:步骤s110,获取当前在虚拟机中被执行的操作码的第一位置属性;步骤s120,将所述第一位置属性和预设断点存储容器中配置的断点的第二位置属性进行匹配;步骤s130,在匹配成功时,调用预设断点跳转函数以在所述操作码处触发断点调试功能。
[0344]
又,所述处理单元1510可以执行如图3、图4以及图6至图12所示的方法中的步骤。
[0345]
存储单元1520可以包括易失性存储单元形式的可读介质,例如随机存取存储单元(ram)15201和/或高速缓存存储单元15202,还可以进一步包括只读存储单元(rom)15203。
[0346]
存储单元1520还可以包括具有一组(至少一个)程序模块15205的程序/实用工具15204,这样的程序模块15205包括但不限于:操作系统、一个或者多个应用程序、其它程序模块以及程序数据,这些示例中的每一个或某种组合中可能包括网络环境的实现。
[0347]
总线1530可以为表示几类总线结构中的一种或多种,包括存储单元总线或者存储单元控制器、外围总线、图形加速端口、处理单元或者使用多种总线结构中的任意总线结构的局域总线。
[0348]
电子设备1500也可以与一个或多个外部设备1600(例如键盘、指向设备、蓝牙设备等)通信,还可与一个或者多个使得用户能与该电子设备1500交互的设备通信,和/或与使得该电子设备1500能与一个或多个其它计算设备进行通信的任何设备(例如路由器、调制解调器等等)通信。这种通信可以通过输入/输出(i/o)接口1550进行。并且,电子设备1500还可以通过网络适配器1560与一个或者多个网络(例如局域网(lan),广域网(wan)和/或公共网络,例如因特网)通信。如图所示,网络适配器1560通过总线1530与电子设备1500的其它模块通信。应当明白,尽管图中未示出,可以结合电子设备1500使用其它硬件和/或软件模块,包括但不限于:微代码、设备驱动器、冗余处理单元、外部磁盘驱动阵列、raid系统、磁带驱动器以及数据备份存储系统等。
[0349]
通过以上的实施方式的描述,本领域的技术人员易于理解,这里描述的示例实施方式可以通过软件实现,也可以通过软件结合必要的硬件的方式来实现。因此,根据本公开实施方式的技术方案可以以软件产品的形式体现出来,该软件产品可以存储在一个非易失性存储介质(可以是cd

rom,u盘,移动硬盘等)中或网络上,包括若干指令以使得一台计算设备(可以是个人计算机、服务器、终端装置、或者网络设备等)执行根据本公开实施方式的方法。
[0350]
此外,上述附图仅是根据本公开示例性实施例的方法所包括的处理的示意性说明,而不是限制目的。易于理解,上述附图所示的处理并不表明或限制这些处理的时间顺序。另外,也易于理解,这些处理可以是例如在多个模块中同步或异步执行的。
[0351]
本领域技术人员在考虑说明书及实践这里公开的发明后,将容易想到本公开的其
他实施例。本申请旨在涵盖本公开的任何变型、用途或者适应性变化,这些变型、用途或者适应性变化遵循本公开的一般性原理并包括本公开未公开的本技术领域中的公知常识或惯用技术手段。说明书和实施例仅被视为示例性的,本公开的真正范围和精神由权利要求指出。
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1