1.本说明书一个或多个实施例涉及计算机技术领域,尤其涉及一种防内存越界的程序编译方法及装置。
背景技术:
2.程序在内存中预先分配的虚拟地址空间中运行,为了防止程序在访问内存的过程中访问到虚拟地址空间之外的地址空间从而出现内存越界的问题,通常会在访问内存之前对所需访问的地址进行越界检查,并在确保访存地址未发生越界的情况下访问内存。
技术实现要素:
3.有鉴于此,本说明书一个或多个实施例提供一种防内存越界的程序编译方法及装置。
4.为实现上述目的,本说明书一个或多个实施例提供技术方案如下:根据本说明书一个或多个实施例的第一方面,提出了一种防内存越界的程序编译方法,包括:在将源程序编译为目标程序的过程中,针对所述源程序中的内存访问代码生成地址拼接机器码,所述目标程序对应的内存分配空间处于一段连续的虚拟地址段内,所述虚拟地址段的段基址包含位于高位的段号和位于低位的若干零值逻辑位,所述虚拟地址段的段长不小于所述若干零值逻辑位所能够表示的最大地址空间;所述地址拼接机器码用于:针对所述内存访问代码所需访问的原始地址,将所述原始地址的低位数据与所述段号进行拼接,得到的拼接地址用于替代所述原始地址以访问内存中的目标内存空间,其中所述低位数据与所述零值逻辑位的位数相同。
5.根据本说明书一个或多个实施例的第二方面,提出了一种防内存越界的程序编译装置,包括:地址拼接机器码编译单元,用于在将源程序编译为目标程序的过程中,针对所述源程序中的内存访问代码生成地址拼接机器码,所述目标程序对应的内存分配空间处于一段连续的虚拟地址段内,所述虚拟地址段的段基址包含位于高位的段号和位于低位的若干零值逻辑位,所述虚拟地址段的段长不小于所述若干零值逻辑位所能够表示的最大地址空间;所述地址拼接机器码用于:针对所述内存访问代码所需访问的原始地址,将所述原始地址的低位数据与所述段号进行拼接,得到的拼接地址用于替代所述原始地址以访问内存中的目标内存空间,其中所述低位数据与所述零值逻辑位的位数相同。
6.根据本说明书一个或多个实施例的第三方面,提出了一种电子设备,包括:处理器;用于存储处理器可执行指令的存储器;其中,所述处理器通过运行所述可执行指令以实现如第一方面中任一项所述的方
法。
7.根据本说明书一个或多个实施例的第四方面,提出了一种计算机可读存储介质,其上存储有计算机指令,该指令被处理器执行时实现如第一方面中任一项所述方法的步骤。
附图说明
8.图1是一示例性实施例提供的一种防内存越界的程序编译方法的应用场景图。
9.图2是一示例性实施例提供的一种防内存越界的程序编译方法的流程图。
10.图3是一示例性实施例提供的一种拼接寻址方式的硬件实现图。
11.图4是一示例性实施例提供的一种设备的结构示意图。
12.图5是一示例性实施例提供的一种防内存越界的程序编译装置的框图。
具体实施方式
13.这里将详细地对示例性实施例进行说明,其示例表示在附图中。下面的描述涉及附图时,除非另有表示,不同附图中的相同数字表示相同或相似的要素。以下示例性实施例中所描述的实施方式并不代表与本说明书一个或多个实施例相一致的所有实施方式。相反,它们仅是与如所附权利要求书中所详述的、本说明书一个或多个实施例的一些方面相一致的装置和方法的例子。
14.需要说明的是:在其他实施例中并不一定按照本说明书示出和描述的顺序来执行相应方法的步骤。在一些其他实施例中,其方法所包括的步骤可以比本说明书所描述的更多或更少。此外,本说明书中所描述的单个步骤,在其他实施例中可能被分解为多个步骤进行描述;而本说明书中所描述的多个步骤,在其他实施例中也可能被合并为单个步骤进行描述。
15.内存越界是软件系统主要错误之一,它是指内存访问时所指向的地址超出了预先分配给该程序对应的合法地址范围。从访问类型上来分类,内存越界包括读越界和写越界,其中,读越界即程序读取了不属于自己合法地址范围内的数据,如果所读的内存地址是无效的,可能导致程序崩溃;如果所读内存地址是有效的,在读的时候不会马上出现问题,但由于读到的数据是随机的,因此可能会造成不可预料的后果。写越界与读越界类似,是指向自身程序对应的合法地址范围之外的内存空间写入数据的行为,可能导致程序崩溃,或者当该内存空间属于其他程序对应的合法地址范围时,相当于越权了修改其他程序的信息,从而诱发系统性的运行故障或安全性风险。在一的内存越界的示例中,程序首先定义一个数组,比如申请了一个可容纳16个元素的数组,那么使用a[16]或a[20]就都是越界访问,同样a[
‑
10]或a[
‑
16]也是越界访问,而只有使用[0, 15]的数组下标才属于正常访问这个数组对应的合法地址范围的行为,其中,在面向人类的程序语言的视角下,a[x]代表数组中的第x个元素,而在面向计算机的视角下,a[x]会被看作是数组中第x个元素所在的逻辑地址。
[0016]
由于内存越界出现的时机是随机的,表现出来的现象是随机的,而且造成的后果往往也是不可预料且非常严重的,这使得开发人员难以获取这些越界错误的本质来源,从而给内存越界错误的定位和修复带来极大的困难。在相关技术中,通常是采用提前预防的方式来解决内存越界问题。例如,可以在程序a执行任一内存访问指令之前,首先对该内存
访问指令所需访问的访存地址进行越界检查,查看该访存地址是否满足处于程序a的合法地址范围内,如果该访存地址处于程序a的合法地址范围内,那么就按照该访存地址访问内存,如果该访存地址处于程序a的合法地址范围之外,那么就停止按照该内存访问指令访问内存,避免发生越界访问导致的程序崩溃或安全性风险。
[0017]
具体而言,程序a在操作系统或内存分配程序预先分配的虚拟地址空间中运行,以该虚拟地址空间仅包括一个连续的虚拟地址段为例来说明相关技术中的越界检查以及确定访存地址的过程:假设虚拟地址段的段基址为q,该值被存储在地址为m的内存空间中,而虚拟地址段的段长为l,该值被存储在地址为n的内存空间中,那么程序a的合法地址范围便被限制在了[q,q l]之内。对于程序a所发出的任一内存访问指令都需要进行越界检查,设该指令所指示访问的形式地址为x,当该内存访问指令的访存类型为直接访存时,那么该指令最终所需访问的访存地址(也称有效地址)就是x本身,此时就必须首先确定程序a的合法地址范围然后再判断x是否落在该合法地址范围内,如前所述,确定程序a的合法地址范围至少需要虚拟地址段的段基址q和段长l,因此,在执行越界检查的过程中,cpu首先需要在内存中读取地址m中的段基址q以及地址n中的段长l,然后判断x是否满足q≤x≤q l,如果满足则认为该内存访问指令不会发生内存越界错误,可以按照x直接访问内存;当内存访问指令的访存类型为基址加变址访存时,那么该指令的有效地址将是x q,由于形式地址x在该基址加变址的访存类型下即为程序a所需访问的逻辑地址,该值反映的是以程序角度所看待的相对于程序首地址的偏移量,那么在程序a的首地址与虚拟地址段的段基址对齐的情况下,越界检查逻辑可以无需首先计算出有效地址x q,而是可以通过比较段长l(实质上就是允许访问的最大内存空间相对于段基址q的偏移量)和逻辑地址x的大小关系来首先判断该内存访问指令是否会发生内存越界错误,然后在判断该内存访问指令不会发生内存越界错误的情况下(在x≤l的情况下)计算出有效地址x q,最后根据有效地址x q访问内存,显然,判断段长l和逻辑地址x时就必然涉及到cpu读取内存中的地址n以获取段长l,计算出有效地址x q就必然涉及到cpu读取内存中的地址m以获取段基址q。
[0018]
由上述讨论可知,在相关技术中,无论内存访问指令的访存类型是直接访存还是基址加变址访存,无论在越界检查逻辑中是否进行有关地址检查和地址生成的执行顺序的优化,针对一个内存访问指令所实现的一个完整的越界检查和确定有效地址的过程中,必然涉及到至少两次访问内存的过程,在程序的合法地址范围包括多个不连续的虚拟地址段时,则需要更多次地访问内存以获取各虚拟地址段的段基址和段长,从而依次判断访存地址是否处于由多个虚拟地址段共同构成的合法地址范围内,同时越界检查中也涉及到数值大小关系的比较逻辑,而无论是内存访问过程或是数值大小比较过程均会较大的降低执行效率,影响内存访问指令的执行性能。另外,虽然可以将段长和段基址预存储在两个不同的寄存器中,这样在需要获取虚拟地址段的段长和段基址的情况下,就能够避免访问内存而直接读取相应的寄存器,但这种改进无法改变在相关技术中需要通过查询段长和段基址两个因素以完成越界检查(防内存越界)和确定有效地址的必要前提,并且也无法消除相关技术中必然涉及到的数值大小比较过程。
[0019]
为此,本说明书提出了一种防内存越界的程序编译方法,应用于编译器或解释器,可使在编译内存访问代码时生成地址拼接机器码,所述地址拼接机器码在执行时用于根据原始地址的低位数据与段号拼接得到的拼接地址直接访问内存,而无需进行越界检查,即
无需同时查询虚拟地址段的段长和段基址,也不无需进行任何数值大小的比较过程。本说明书所涉及的方案只需在特定的内存分配原则下,利用虚拟地址段的段号这一个因素便同时能够完成防内存越界和确定有效地址的任务,因此极大地提高了预防内存访问代码发生内存越界错误的实施效率。
[0020]
本说明书所涉及的防内存越界的程序编译方法应用于编译器或解释器进行编译的过程中,本说明书实施例所涉及的内存访问指令是指在被执行后能够生成并访问特定访存地址的计算机语言,其形式可以包括高级语言编写的指令、汇编指令、伪指令和机器码等;本说明书实施例所涉及的内存访问代码是指功能上与内存访问指令相同、形式上不包括机器码的具有用户可读性的解释性语言,是必须要通过编译生成机器码后才能够被处理器执行以最终实现内存访问功能的源代码,例如可以包括使用字节码、c 、python、java所编写的各类程序语言;而本说明书实施例所涉及的机器码则是指面向处理器的能够被处理器直接执行的不具备用户可读性的机器语言。
[0021]
在本说明书实施例中,内存在线性地址空间中被划分为若干个内部地址连续的地址段,每个地址段相互之间不重叠,且每个地址段的段基址包含位于高位的段号和位于低位的若干零值逻辑位。图1是一示例性实施例提供的一种防内存越界的程序编译方法的应用场景图,以图1为例,图示中的内存地址需要用6位16进制数(相当于24位二进制数)表示,因此该内存为24位内存,假设一个物理地址所对应的内存空间的大小为1字节(8bit),那么图示内存的内存大小为1b*2^24=16mb,如图所示,该内存被划分为若干个连续的地址段,其中,虚拟地址空间00:0000h~00:ffffh对应的地址段用于加载包括系统程序和操作系统在内的内核态程序;虚拟地址空间01:0000h~01:ffffh对应的地址段用于加载用户态程序应用程序1;虚拟地址空间02:0000h~02:ffffh对应的地址段用于加载用户态程序应用程序2;虚拟地址空间03:0000h~03:ffffh对应的地址段用于加载用户态程序应用程序3,以此类推。可见,在图1所示的内存分配场景中,内存被平均分配为若干个段长相同的地址段,每个地址段的首地址(即段基址)中的高2位(对应于8位二进制数)代表段号,低4位(对应于16位二进制数)代表零值逻辑位,零值逻辑位中每位二进制数的值均为0,每个地址段的段长均等于4位16进制数所能表示的最大地址空间即16^4=65536,由于内存中的每个线性地址均被分配至相应的地址段,使得在图1所示的内存分配场景下内存不存在外部碎片。需要指出的是,虽然图1所示的应用场景中,不同地址段的段长均被设置为相同,但根据实际场景的需要,也可以将地址段的段长设定为其他大小(此时不同地址段的段号位数将可能出现差异),但无论地址段的段长为多少,仍需要保证各个地址段的段基址中除段号以外的逻辑位均为零值逻辑位。
[0022]
在图1所示的应用场景中,系统程序或应用程序在内存中所占的虚拟地址空间均不超过其所在地址段的段长,以应用程序2为例,应用程序2的程序首地址为02:0000h,与虚拟地址空间02:0000h~02:ffffh对应的虚拟地址段的段基址对齐,其被分配的虚拟地址空间不超过虚拟地址段的段长,在应用程序2对应的地址段中,应用程序2维护有包含处理器指令(机器码)的代码段以及包含应用数据的数据段,当应用程序2被加载至对应的地址段并被执行时,cpu会按照地址顺序从低至高地读取其代码段中的机器码并执行相应的处理操作,例如算术运算、指令跳转、存取数据等处理器操作,类似的,当系统程序或其他应用程序被加载至相应地址段并需要被执行时,cpu也会读取相应代码段中的机器码并予以处理。
[0023]
下面结合图1对本说明书的防内存越界的程序编译方法进行详细说明。请参见图2,图2是一示例性实施例提供的一种防内存越界的程序编译方法的流程图。如图2所示,该方法应用于编译器或解释器,该方法可以包括以下步骤:步骤202,在将源程序编译为目标程序的过程中,针对所述源程序中的内存访问代码生成地址拼接机器码,所述目标程序对应的内存分配空间处于一段连续的虚拟地址段内,所述虚拟地址段的段基址包含位于高位的段号和位于低位的若干零值逻辑位,所述虚拟地址段的段长不小于所述若干零值逻辑位所能够表示的最大地址空间。
[0024]
所述地址拼接机器码用于:步骤204,针对所述内存访问代码所需访问的原始地址,将所述原始地址的低位数据与所述段号进行拼接,得到的拼接地址用于替代所述原始地址以访问内存中的目标内存空间,其中所述低位数据与所述零值逻辑位的位数相同。
[0025]
其中,上述的步骤202发生于地址拼接机器码的编译阶段,而步骤204则发生于地址拼接机器码的执行阶段。
[0026]
本说明书实施例所涉及的源程序也称源代码,是指未编译的按照一定的程序设计语言规范书写的文本文件,是一系列人类可读的计算机语言指令。在现代程序语言中,源代码可以是以书籍或者磁带的形式出现,但最为常用的格式是文本文件,这种典型格式的目的是为了编译出计算机程序。计算机源代码的最终目的是将人类可读的文本翻译成为计算机可以执行的二进制机器码,这种过程叫做编译,通过编译器或解释器完成。本说明书实施例所涉及的目标程序又称目的程序,是指源程序经编译后生成的可直接被计算机运行的机器码集合,即目标程序是通过解释器或编译器中的语言处理程序(汇编程序,编译程序,解释程序),由源程序处理(汇编,编译,解释)而成的程序,目标程序由机器码构成的,能够被计算机识别并直接运行,在计算机文件上以.obj作扩展名,目标程序在完成与库函数连接后,便可以直接被加载至内存中运行。
[0027]
源程序中一般都会包含大量的内存访问代码,这些内存访问代码在编译过程中也会转化为相应的机器码,从而作为构成目标程序的一部分。传统的越界检查逻辑任务通常是由操作系统或特定的越界检查程序所完成,即在内存访问代码编译至机器码的过程中只是如实的按照内存访问代码的访存类型以及携带的形式地址,生成用于“根据形式地址和访存类型确定有效地址,并根据有效地址访问内存”的机器码,而并不会产生额外的用于实现越界检查任务的机器码,越界检查的任务是由处理器在读取并执行具有内存访问功能的机器码时调用操作系统或特定的越界检查程序所实现。虽然越界检查程序的底层实现也是基于机器码,但由于每次越界检查机制都至少涉及一次程序调用的过程,因此必然对启用有越界检查机制的目标程序的执行效率造成了负面影响。
[0028]
而在本说明书实施例中,在将源程序编译为目标程序的过程中,会针对所述源程序中的内存访问代码生成地址拼接机器码,而该地址拼接机器码用于对实际访存的地址进行修改,以确保实际访问内存时使用的地址不会出现内存越界错误。因此在目标程序被执行的过程中,处理器只需顺序执行机器码,而无需在每次执行访存机器码时调用操作系统或特定的越界检查程序执行一次越界检查逻辑,相当于取消了程序调用的过程,有效地提高了启用有越界检查机制的目标程序的执行效率。
[0029]
除了对执行越界检查任务的架构进行轻量化处理(取消程序调用过程)之外,本说
明书实施例还进一步取消了越界检查的逻辑过程本身。如前所述,本说明书实施例中生成的地址拼接机器码在被处理器执行时,用于针对所述内存访问代码所需访问的原始地址,将所述原始地址的低位数据与所述段号进行拼接,得到的拼接地址用于替代所述原始地址以访问内存中的目标内存空间,其中所述低位数据与所述零值逻辑位的位数相同。因此,本说明书所涉及的地址拼接机器码在执行过程中,是通过将虚拟地址段的段号与原始地址的低位数据进行拼接,生成必然处于合法地址范围内的拼接地址,并直接根据原始地址“修正”得到的拼接地址访问内存,显然,本说明书所涉及的不涉及对原始地址是否落在合法范围内的判断,于是也就无需从内存中读取出虚拟地址段的段长,也完全不需要执行任何有关数值比较的逻辑,这相当于取消了越界检查的逻辑过程,跳过了越界检查的环节。
[0030]
为了确保生成的拼接地址必然处于目标程序对应的内存分配空间中,首先需要对目标程序的内存分配策略有一定的要求,具体而言,需要使所述目标程序对应的内存分配空间处于一段连续的虚拟地址段内,并且所述虚拟地址段的段基址包含位于高位的段号和位于低位的若干零值逻辑位,所述虚拟地址段的段长不小于所述若干零值逻辑位所能够表示的最大地址空间。在编译器对所述目标程序编译完成且被触发执行的情况下,可以使操作系统将所述目标程序加载至所述内存中的所述虚拟地址段内,并使所述处理器执行所述目标程序中的若干机器码。例如,对于区块链系统中的区块链节点而言,所述源程序或所述目标程序可以为部署于区块链系统中的智能合约。其中,当区块链节点上部署的是基于源程序的智能合约时,该源程序可以是用字节码编写的智能合约,需要在虚拟机环境下执行,而当区块链节点上部署的是基于目标程序的智能合约时,该目标程序则是通过编译得到的由若干机器码构成的aot(ahead of time,提前编译)合约,从而可以在被加载到内存中后由处理器直接执行。
[0031]
在所述内存访问代码的访存类型为直接访存的情况下,则内存访问代码所携带的形式地址x就可以看作为内存访问代码所需访存的原始地址,此时生成的地址拼接机器码将针对原始地址x进行拼接操作,具体而言,如图1所示,假设原始地址x值为01:1234h(图1中显示的原始地址xx:1234h是指原始地址的高2位对应的高位数据可以为任意值,这里以高位数据为01h举例),假设目标程序即为图1中的应用程序2,其所被分配的内存分配空间处于图中所述地址范围处于02:0000h~02:ffffh的虚拟地址段内,该虚拟地址段的段基址q为02:0000h,该值被存储在目标程序数据段的第二预设存储空间中,该第二预设存储空间的地址为m,是编译时就确定的固定值,段基址q中的高2位为段号,低4位为零值逻辑位,而原始地址x中的高2位为高位数据,低4位为低位数据,关于段号和零值逻辑位的位数由处理器预先获知,因此,在执行地址拼接机器码的过程中,cpu首先需要在内存中读取地址m中的段基址q,然后根据预先设定的段号位数从段基址q中的高2位中取出段号02h,或者,在另一实施例中,第二预设存储空间中直接存储有虚拟地址段的段号02h,然后在获取段号后,继续将段号02h与原始地址02:1234h中的低4位取出的低位数据1234h进行拼接操作,得到拼接后的拼接地址02:1234h,进而根据拼接地址02:1234h替代原始地址01:1234h访问内存中的目标内存空间。需要指出的是,本说明书实施例所涉及的地址拼接机器码可能只包含一条机器码,也可能包含有多条机器码,从而作为一个机器码集合共同完成上述处理器操作,例如,上述操作过程中,从地址m中读取段基址q的操作、将段号和低位数据进行地址拼接的操作以及根据拼接地址访存的操作就可能是由地址拼接机器码中包含的多个机器码在执
行时分别实现的。
[0032]
在内存访问代码的访存类型为直接访存以外的情况下,则内存访问代码所携带的形式地址x可能并非直接作为内存访问代码所需访存的原始地址,而是需要根据内存访问代码的访问类型对应的地址计算公式首先计算出原始地址,然后再在原始地址的基础上进行后续的地址拼接操作。例如,当内存访问代码的访存类型为基址加变址访存时,那么该内存访问代码所携带的形式地址x并非其最终所需访问的原始地址,而是作为面向目标程序的逻辑地址x,真正所需访问的原始地址将是x q,因此在编译阶段除了会生成地址拼接机器码还会生成地址计算机器码以计算得到原始地址(线性地址),如图1所示,假设逻辑地址x为00:1234h,那么cpu可以先执行编译生成的地址计算机器码,通过cpu读取出内存中地址m所预先存储的段基址q,接着通过算术运算得到原始地址x q为00:1234h 02:0000h=02:1234h,这里使用的逻辑地址x是作为立即数写在地址计算机器码对应的操作数中,因此无需通过访问内存读取,并且得到的原始地址也就是内存访问代码所需访问的线性地址,然后,cpu继续执行地址拼接机器码,执行过程中无需再次从内存中读取地址m中的段基址q,因为在执行地址计算机器码时已经读取过段基址q,因此段基址此时仍然存储在cpu内部寄存器中,cpu可以直接对内部寄存器中的段基址q进行后续操作,提取出段基址q高2位的段号02h、以及计算得到的原始地址的低位数据1234h,将二者拼接得到拼接地址02:1234h,进而根据拼接地址02:1234h替代原始地址02:1234h访问内存中的目标内存空间。
[0033]
在内存访问代码的访存类型为直接访存以外的情况下,除了可以采用上述的先计算出内存访问代码所需访问的原始地址,再根据计算得到的原始地址进行地址拼接的实施例外,还可以将内存访问代码的实际访存类型均默认为拼接访存的类型,即在编译过程中不考虑根据形式地址计算出原始地址的过程,不生成实际访存类型对应的地址计算机器码,而是只生成上述的地址拼接地址码,并直接将内存访问代码中携带的形式地址看作原始地址以完成后续的拼接操作。例如,当内存访问代码的访存类型为基址加变址访存时,那么在编译过程中就会将该内存访问代码所携带的形式地址x看作为所需访问的原始地址x,进而在生成的地址拼接机器码的操作数中携带该原始地址x,如图1所示,假设原始地址x为00:1234h(实际上就是逻辑地址),那么cpu在执行编译生成的地址拼接机器码时,首先通过cpu读取出内存中地址m所预先存储的段基址q,接着提取出段基址q高2位的段号02h,同时从地址拼接机器码的操作数中直接获取原始地址x的低位数据1234h,将二者进行拼接操作得到拼接地址02:1234h,进而根据拼接地址02:1234h替代原始地址01:1234h访问内存中的目标内存空间。
[0034]
在一实施例中,前述的地址拼接操作具体是指:所述处理器将所述原始地址作为所述拼接地址的低位写入为所述拼接地址所分配的存储空间的低位,并将所述虚拟地址段的段号作为所述拼接地址的高位写入所述存储空间的高位以在所述存储空间中生成所述拼接地址。上述为所述拼接地址所分配的存储空间可以包括内存空间或寄存器,当然,也可以包括硬盘空间。以图1中所示的以拼接方式获得拼接地址为例,第二预设内存空间中预先存储有虚拟地址段的段基址02:0000h,cpu从目标程序发出的地址拼接机器码中读取得到的原始地址为“00:1234h”,根据预设的低位数据的位数和位置从而确定该原始地址中的低位数据为“1234h”,并将该低位数据“1234h”作为所述拼接地址的低位写入为所述拼接地址所分配的存储空间的低位,同时,将按照段号预设的位数和位置从第二预设内存空间读取
出的段基址中提取出段号“02h”,并将段号“02h”作为所述拼接地址的高位写入所述存储空间的高位,以在所述存储空间中生成所述拼接地址“02:1234h”,该原始地址又满足:02:0000h 1234h=02:1234h,不难发现,通过上述拼接方法所得到的原始地址与相关技术中通过基址加变址的算术运算得到的原始地址在数值上一致,即本说明书所涉及的地址拼接机器码在执行时对比相关技术中基址加变址的寻址方式,可以在不使用算术运算的情况下,生成相同数值的原始地址,而对于cpu而言,拼接操作的性能消耗和时耗都远小于算术运算操作,因此通过本说明书所涉及的防内存越界方案,可以减少访存时间,提高了访存效率。
[0035]
之所以能够使拼接地址处于目标程序的合法地址范围内,是因为本说明书实施例中虚拟地址段对应的段基址被设置为包含位于高位的段号和位于低位的若干零值逻辑位,并且所述虚拟地址段的段长不小于所述若干零值逻辑位所能够表示的最大地址空间。以图1为例,目标程序所处的虚拟地址段的段基址为02:0000h,包含高2位的段号02h以及低4位的零值逻辑位0000h,虚拟地址段的段长不小于4位16进制位所能表示的最大地址空间65536,这意味着虚拟地址空间02:0000h~02:ffffh均包含在该虚拟地址段内,若要使最终所需要的访问的目标内存空间的访存地址不发生内存越界错误,则需要保证实际访存地址必须落在为目标程序所分配的虚拟地址段内,而又虚拟地址段的段长不小于所述若干零值逻辑位所能够表示的最大地址空间,因此虚拟地址空间02:0000h~02:ffffh必然处于虚拟地址段内,换句话说,02:0000h~02:ffffh必然属于目标程序的合法地址范围,只需要保证实际访存地址处于02:0000h~02:ffffh范围内就可以保证不发生内存越界错误,显然对于访存地址而言,无论低4位的段偏移量的数值为多少,只要高2位的高位数据为02h,都可以保证访存地址处于虚拟地址空间02:0000h~02:ffffh之内,也即可以保证访存地址不会发生内存越界错误,而02h又恰巧为虚拟地址段的段基址中位于高2位的段号,因此,在本说明书实施例所涉及的内存分配策略下,将目标程序对应的内存分配空间设置为一段连续的虚拟地址段,并保证虚拟地址段具有如下性质:
①
段基址包含位于高位的段号和位于低位的若干零值逻辑位,
②
段长不小于所述若干零值逻辑位所能够表示的最大地址空间,就可以在处理器执行地址拼接机器码时,利用拼接操作将原始地址的低位数据与段号进行拼接得到的拼接地址作为实际访存地址,从而确保在根据拼接地址访存时不会发生内存越界错误。
[0036]
在根据所述拼接地址访问内存中的目标内存空间的过程中,如果所述内存采用页式存储管理机制,那么所述处理器根据所述拼接地址转化得到的物理地址访问所述内存中的所述目标内存空间;如果所述内存未采用页式存储管理机制,那么所述处理器将所述拼接地址作为物理地址访问所述内存中的所述目标内存空间。由于内存在采用页式存储管理的情况下,拼接地址并非直接作为目标内存空间的物理地址,而是包含有页号和页偏移量,且需要进一步查找页表以确定最终的物理地址,因此处理器需要首先将拼接地址转化为物理地址,然后基于转化得到的物理地址访问所述内存中的所述目标内存空间;而内存在未采用页式存储管理的情况下,则拼接地址相当于目的内存空间的物理地址,因此处理器可以将所述拼接地址作为物理地址直接访问所述内存中的所述目标内存空间。通过采用页式存储管理,可以将内存中每个地址段又分别划分为大量的页块,然后根据每个页块的首地址和权限控制信息构建页表,从而方便对内存进行的读写权限进行管理(例如限制用户态程序修改自己代码段的数据),同时也有利于应用虚拟内存技术以实现页粒度的内外存置
换。
[0037]
在本说明书实施例中,提供了一种防内存越界的程序编译方法,在将源程序编译为目标程序的过程中,针对所述源程序中的内存访问代码生成地址拼接机器码,由于本说明书实施例采用了一种特殊的内存分配策略,即目标程序对应的内存分配空间处于一段连续的虚拟地址段内,所述虚拟地址段的段基址包含位于高位的段号和位于低位的若干零值逻辑位,所述虚拟地址段的段长不小于所述若干零值逻辑位所能够表示的最大地址空间,因此可以使地址拼接机器码只需要利用虚拟地址段的段基址一个因素就可以生成不会发生内存越界错误的拼接地址,同时能够完成防内存越界和确定最终访存地址的任务,这意味着在防内存越界以及确定最终访存地址的过程中,可以将访问内存的次数降至一次,或者只需要占用一个寄存器来存放虚拟地址段的段号或段基址,同时也无需执行越界检查的相关逻辑,无需反复执行数值大小比较的过程以及利用算术运算得到有效地址的过程,在实施效率上远优于相关技术中越界检查的实施效率,极大地提高了预防内存访问代码发生内存越界错误的实施效率。
[0038]
在一实施例中,所述虚拟地址段的段长可以为所述若干零值逻辑位所能够表示的最大地址空间。如前所述,为了避免内存越界,需要保证拼接地址所对应的目标内存空间处于虚拟地址段之内,在本说明书实施例中,这一点是通过保证虚拟地址段的段长不小于所述若干零值逻辑位所能够表示的最大地址空间来实现的,但是当虚拟地址段的段长大于所述零值逻辑位所能够表示的最大地址空间的情况下,目标程序可能会被分配到零值逻辑位所能表示的最大地址空间之外但仍属于虚拟地址段中的剩余内存空间,这意味着目标程序在正常执行过程中完全可能申请到上述剩余内存空间之中,然而在本说明书实施例中,地址拼接机器码所生成的拼接地址的地址范围却只会包含于零值逻辑位所能表示的最大地址空间内部,换句话说,对于上述剩余内存空间的正常访问,在应用本说明书实施例所涉及的防内存越界方案后将无法访问,从而影响目标程序的正常运行。
[0039]
具体而言,由于本说明书实施例中地址拼接机器码所涉及的地址拼接操作,将拼接地址的高位数据固定为与虚拟地址段的段号相同,由此生成的拼接地址虽然不会发生内存越界错误,但这相当于将目标程序所能够访问的线性地址空间的空间大小固定为拼接地址中除高位数据之外的低位数据的位数所决定,而低位数据的位数被规定为与虚拟地址段的段基址中零值逻辑位的位数相同(因为高位数据的位数和段号相同,而用于表示内存线性地址的总位数又是预先决定的),因此目标程序所能访问的线性地址空间的空间大小在数值上与零值逻辑位所能够表示的最大地址空间的空间大小相等,等于2^x(x为二进制的零值逻辑位的位数),而对于一个段长大于上述计算得到的最大地址空间的虚拟地址段,在采用本说明书实施例所涉及的防内存越界方案后,会使得该虚拟地址段的一部分内存空间无法被访问到,例如虚拟地址段对应的线性地址空间为01:00h~02:ffh,因此该虚拟地址段的段基址为01:00h,目标段号为01h,段长为512,超过了8位二进制零值逻辑位所能够表示的最大地址空间2^8=256,那么按照本说明书实施例所涉及的地址拼接操作,生成的拼接地址对应的线性地址空间仅包括01:00h~01:ffh,而不包括02:00h~02:ffh,因此这将导致被分配在虚拟地址段中的目标程序无法访问到该虚拟地址段的全部地址空间。所以,可以将所述虚拟地址段的段长设置为所述若干零值逻辑位所能够表示的最大地址空间,这样一来,目标程序将可以完全访问到目标程序所被分配的内存分配空间,从而避免第一用户程
序在执行过程中由于拼接操作的“一刀切”而导致无法完整访问到自身的代码段或数据段并最终导致运行出错的问题,同时还能够提高内存的利用率。另外,在应用上述实施例的基础上,还可以如图1所示那样将内存以紧密排列的方式划分为线性地址空间上连续的多个地址段,从而进一步提高内存的利用率。
[0040]
可选的,还包括:针对所述内存访问代码生成地址计算机器码,所述地址计算机器码用于将根据所述内存访问代码携带的形式地址按照所述内存访问代码的访问类型对应的地址计算公式计算得到的所述原始地址写入第一预设存储空间,以使所述地址拼接机器码在执行时从第一预设存储空间处获取所述原始地址。
[0041]
如前所述,对于不同访存类型的内存访问代码可能会有不同的编译结果,在本说明书实施例中,可以按照内存访问代码的访存类型对应的地址计算公式,计算得到内存访问代码所需访问的原始地址,从而确保后续参与拼接操作的原始地址满足内存访问代码的实际访存需求。例如,在内存访问代码的访存类型为基址加变址访存的情况下,编译器会针对该内存访问代码生成地址计算机器码,具体是基于内存访问代码中携带的逻辑地址(形式地址)以及预存储有段基址的第二预设存储空间,生成调用alu(arithmetic and logic unit,算术逻辑单元)的地址计算机器码,该地址计算机器码的地址码为第一预设存储空间,操作数为作为立即数的内存访问代码中的逻辑地址以及作为地址的第二预设存储空间。在本说明书实施例中,生成的地址计算机器码的执行顺序是设置在地址拼接机器码之前,因此,在所述地址计算机器码被执行时,就会将所述内存访问代码中携带的形式地址与所述段基址相加得到的所述原始地址写入第一预设存储空间,以使得所述地址拼接机器码在执行时从第一预设存储空间处获取所述内存访问代码所需访问的原始地址。
[0042]
可选的,所述地址拼接机器码中包含拼接访存机器码,所述拼接访存机器码用于将所述原始地址写入原始地址寄存器,并根据拼接地址寄存器中生成的所述拼接地址访问所述内存中的所述目标内存空间;其中,所述拼接地址寄存器中的高位空间与预先存储有所述段号的段号寄存器相连,所述拼接地址寄存器中的低位空间与原始地址寄存器中的低位空间相连,所述原始地址寄存器中的低位空间用于存储所述原始地址中包含的所述低位数据。
[0043]
在本说明书实施例中,对于前述地址拼接机器码在执行时所实现的地址拼接操作,可以通过地址拼接机器码中包含的拼接访存机器码实现。本说明书实施例所涉及的拼接访存机器码需要在经过特定硬件改造的处理器上才能够实现,具体而言,可以采用图3所示的硬件架构来实现。图3是一示例性实施例提供的一种拼接寻址方式的硬件实现图,包括段号寄存器、原始地址寄存器和拼接地址寄存器,其中,段号寄存器与拼接地址寄存器中的高位空间相连,原始地址寄存器中的低位空间与拼接地址寄存器中的高位空间相连。具体而言,拼接地址寄存器中高位空间指的是用于存储拼接地址的高位数据(拼接地址的高位数据的位数与段号相同)对应的各逻辑位所在的存储空间,而通过将段号寄存器中用于存储段号的各逻辑位的输出端与拼接地址寄存器中高位空间的输入端对应相连,并保持相同的高低位顺序,以使得段号寄存器中的段号能够作为拼接地址寄存器的输入信号从而被“复制”到拼接地址寄存器中高位空间;同理,原始地址寄存器中的低位空间指的是用于存储拼接地址的低位数据(拼接地址的低位数据的位数与虚拟地址段的段基址中的零值逻辑位的位数相同)对应的各逻辑位所在的存储空间,原始地址寄存器中的低位空间指的是用
于存储原始地址的低位数据(位数与零值逻辑位相同)对应的各逻辑位所在的存储空间,原始地址寄存器中的高位空间指的是用于存储原始地址的高位数据(位数与段号相同)对应的各逻辑位所在的存储空间,因此,通过将原始地址寄存器中的低位空间的输出端与拼接地址寄存器中的低位空间的输入端对应相连,并保持相同的高低位顺序,就能够使得原始地址中的低位数据作为拼接地址寄存器的输入信号被“复制”到拼接地址寄存器中的低位空间。
[0044]
在如图3所示的硬件架构中,cpu配套有新的寻址方式,即本说明书实施例所涉及的拼接寻址方式,该寻址方式需要通过新的指令集实现,例如通过执行本说明书实施例所涉及的拼接访存机器码所触发。在应用拼接寻址方式的过程中,例如cpu在执行拼接访存机器码时,由于段号寄存器中预先存储有段号,因此cpu在执行拼接访存只需要进行如下操作即可完成对应的访存过程:“将所述原始地址写入原始地址寄存器(这部分相当于写操作),根据拼接地址寄存器中生成的所述拼接地址访问所述内存中的所述目标内存空间(这部分相当于寄存器直接寻址操作)”,而在上述cpu访存过程中,cpu通过上述硬件架构中的硬件电路实现所谓的“地址拼接操作”,以使得在cpu将原始地址写入源地址寄存器的时刻,就使拼接地址寄存器中的拼接地址得以生成,因此在上述硬件设计下的寻址方式,理论上只比寄存器直接寻址多“将逻辑地址写入源地址寄存器”这一个写操作,其寻址效率只略低于寄存器直接寻址,但相对于通过算术运算得到访存地址的相关技术而言,极大的缩短了访问内存的时间,在防止内存越界的同时提高了访存效率。
[0045]
可选的,所述地址拼接机器码中包含寄存器拼接机器码和寄存器访存机器码;其中,所述寄存器拼接机器码用于将第一源寄存器中预先存储的所述段号与第二源寄存器中的预先存储的所述低位数据拼接得到的所述拼接地址写入目的寄存器;所述寄存器访存机器码用于根据所述目的寄存器中写入的所述拼接地址访问所述内存中的所述目标内存空间。
[0046]
在本说明书实施例中,所述地址拼接机器码中至少包含寄存器拼接机器码和寄存器访存机器码,用以共同完成地址拼接机器码所需实现的地址拼接操作以及根据拼接地址访存的操作,而由于寄存器拼接机器码和寄存器访存机器码作为现有指令集的一部分,因此可以通过现有的指令集所构成本说明书实施例所涉及的地址拼接机器码。其中,寄存器拼接机器码在执行时用于指示所述处理器将所述原始地址中的低位数据写入第二源寄存器,利用所述处理器提供的寄存器拼接操作,将第一源寄存器中预先存储的段号与第二源寄存器中的低位数据进行拼接,以在目的寄存器中写入拼接得到的所述拼接地址,当然,根据寄存器拼接操作的实际定义情况,也可以直接将原始地址写入第二源寄存器,此时第一源寄存器中预先存储的是虚拟地址段的段基址,从而在执行寄存器拼接操作时,对第一源寄存器中的低位数据(零值逻辑位)进行切割以保留所述段号,对第二源寄存器中的高位数据进行切割以保留所述低位数据,最后将切割得到的所述段号和所述低位数据分别写入目标寄存器中的高位空间和低位空间,从而实现地址拼接操作。以及,在向目的寄存器中写入拼接地址后,可以继续执行编译生成的寄存器访存机器码,以指示处理器根据所述目的寄存器中的所述拼接地址访问所述内存中的所述目标内存空间。
[0047]
在本说明书实施例中,可以采用cpu提供的寄存器拼接操作实现前述的地址拼接操作,而寄存器拼接操作被现有指令集中的寄存器拼接指令所定义,因此,在内存访问代码
的编译过程中,可以使生成的地址拼接机器码包含寄存器拼接机器码和寄存器访存机器码,从而在cpu响应于地址拼接机器码时,可以执行如下逻辑:“将原始地址写入第二源寄存器,对第一源寄存器与第二源寄存器使用寄存器拼接操作,最终拼接得到的拼接地址被写入目的寄存器中,最后使用寄存器直接寻址方式对预设目的寄存器中的拼接地址进行内存访问”,从而实现地址拼接机器码所需完成的功能。在本说明书实施例中,可以利用cpu提供的寄存器拼接操作完成地址拼接操作以生成拼接地址的过程,从而无需对cpu等硬件进行额外的改造,减少开发成本。
[0048]
可选的,所述将源程序编译为目标程序包括:在对所述源程序进行解释执行的过程中,将所述源程序编译为所述目标程序;或者,将所述源程序aot编译为所述目标程序。
[0049]
在本说明书实施例中,将所述源程序编译为所述目标程序,可能是发生在解释执行的过程中,本说明书实施例所涉及的解释执行指的是在边编译边执行,例如,在编译器或解释器对所述源程序中的任一代码完成编译以生成所述任一代码对应的机器码后,就将其加载至虚拟地址段中使处理器执行所述任一机器码;或者,将所述源程序编译为所述目标程序,也可能是发生在编译执行的过程中,本说明书实施例所涉及的编译执行指的是编译完成后执行,例如,在所述目标程序被aot编译完成且被触发执行的情况下,操作系统将所述目标程序加载至所述内存中的所述虚拟地址段内,并使所述处理器执行所述目标程序中的若干机器码。本说明书涉及的防内存越界的程序编译方法可以应用在解释执行的编译过程中,也可以应用在编译执行的过程中,本说明书对此不做任何限制。
[0050]
可选的,所述段号或者所述段基址预先存储在第二预设存储空间,以使所述地址拼接机器码在执行时从第二预设存储空间处获取所述段基址中包含的所述段号。
[0051]
如前所述,地址拼接机器码在执行过程中需要获取目标程序所被分配的虚拟地址段的段号,因此,可以在目标程序被加载至虚拟地址段中执行之前,首先在第二预设存储空间中预先写入虚拟地址段的段基址或段基址中包含的段号,以使地址拼接机器码在执行时能够从第二预设存储空间处获取所述段基址中包含的所述段号。例如第二预设存储空间中预存储有虚拟地址段的段基址时,则地址拼接机器码需要从第二预设存储空间中读取出段基址,并按照预先设定的段号的位数从段基址的高位数据上提取出所述虚拟地址段的段号(在第二预设存储空间中直接存储有段号的情况下,可以直接从第二预设存储空间中读取出所述段号),从而帮助完成原始地址的低位数据与虚拟地址段的段号的拼接,以生成不会发生内存越界的拼接地址访问内存。
[0052]
可选的,在上述说明书实施例的基础上,第二预设存储空间仅参与生成所述地址拼接机器码的编译过程。在本说明书实施例中,由于第二预设存储空间中存储有虚拟地址段的段号或段基址,而其中的段号是用于在执行地址拼接机器码时拼接得到拼接地址的必要信息,因此在目标程序加载至内存中的虚拟地址段中并准备开始执行之前,都需要首先在第二预设存储空间中预先存储虚拟地址段的段基址或段号才能保证后续地址拼接机器码在执行过程中可以正确有效地实现其拼接得到不会越界的拼接地址的功能。然而,在源程序向目标程序进行编译的过程中,源程序中不仅会包含有内存访问代码需要进行编译,还会包含其他的功能代码也需要编译为机器码,而编译得到的机器码可能会涉及申请使用寄存器和内存中的内存空间,这其中就包括第二预设存储空间,而在其他编译后生成的机器码中会使用(例如修改)第二预设存储空间的情况下,就无法保证目标程序在执行过程中
越界检查机制的有效性,因为在其他机器码的操作篡改了第二预设存储空间中存储的值之后,后续执行的地址拼接机器码将读取到错误的段号或段基址,从而无法真正实现防止内存越界的功能。因此,在本说明书实施例中,通过对编译器或解释器进行设置,使第二预设存储空间仅参与生成所述地址拼接机器码的编译过程,即只有在生成地址拼接机器码时,可以在地址拼接机器码中定义使用第二预设存储空间的操作逻辑,而在生成其他机器码时则禁用第二预设存储空间,或将针对第二预设存储空间的操作逻辑限定为只读,从而避免上述可能出现的因第二预设存储空间被篡改而导致的防内存越界机制失效的问题。
[0053]
可选的,第二预设存储空间的修改权限由操作系统所有。在本说明书实施例中,为了使地址拼接机器码在执行过程中能够确保拼接得到的拼接地址处于目标程序所在的虚拟地址段内,需要防止目标程序或其他用户态程序对第二预设存储空间中的段号或段基址进行修改,因为那样将导致地址拼接时所利用的段号并非目标程序所在虚拟地址段的段号,从而使得拼接得到的拼接地址并非属于虚拟地址段内从而造成内存越界错误。例如可以设置对第二预设存储空间进行相关调用的指令为特权指令,因此只有在cpu处于内核态模式或相应于特权指令的情况下才可以对第二预设存储空间中的段号或段基址进行修改,例如操作系统需要将cpu的控制权下放给作为用户态程序的目标程序时,则首先应发出特权指令使cpu将第二预设存储空间中的段号修改为所需要的下放的用户态程序所在虚拟地址段的段基址或段号,然后再将处理器模式调整为用户态模式(或者先修改处理器模式,再发出特权指令修改第二预设存储空间),最后进行特权指令跳转至目标程序的程序入口,使cpu开始读取目标程序的代码段中的指令。通过本说明书实施例,可以避免目标程序在执行过程中私自修改第二预设存储空间中的段号,从而增强了地址拼接机器码在执行过程中的有效性,使之能够有效防止目标程序访问到自己无权访问的地址,增加了系统的安全性。
[0054]
可选的,第二预设存储空间包括下述任一:寄存器、所述虚拟地址段中预定义的内存空间或所述虚拟地址段外预定义的内存空间。其中,当第二预设存储空间为所述虚拟地址段中预定义的内存空间时,例如第二预设存储空间可以为目标程序的首地址对应的内存空间,或者如图1所示可以是数据段中具有固定逻辑地址的内存空间,可以将第二预设存储空间的权限管理模式设置为只读模式,从而避免目标程序在执行过程中修改;当第二预设存储空间为所述虚拟地址段外预定义的内存空间时,由于目标程序在编译完成后所有的访存行为都会收到越界检查的保护,即在目标程序的执行过程中,只有本说明实施例所涉及生成的地址拼接机器码能够访问该第二预设存储空间,这意味着这种访问必然是可信任的,因此无需担心目标程序在执行过程中访问或修改第二预设存储空间,此时可以将第二预设存储空间的权限管理模式设置为读写模式;当第二预设存储空间为寄存器时,该寄存器可以包括所述处理器中的内部寄存器、作为外设的外部寄存器或所述内存中定义的虚拟寄存器。在本说明书实施例中,寄存器可内置于处理器中,与处理器内部的其他通用寄存器具有相同地位,因此cpu默认知晓该寄存器的物理地址,并在相关指令中需要调用该寄存器时按照其对应的物理地址进行访问,在第二预设存储空间为内部寄存器的情况下,由于无需通过访问内存以获取虚拟地址段的段号,因此可以进一步加快地址拼接机器码的执行效率。当然,寄存器也可以为外部寄存器,此时cpu需要通过i/o接口对寄存器进行调用,因此在使用作为外设的外部寄存器时,需要先向操作系统或cpu声明外部寄存器对应的i/o端口地址。同理,寄存器也可以为内存中定义的虚拟寄存器,这相当于在内存中分配一个cpu专
用的内存空间,因此也需要向操作系统或cpu声明该虚拟寄存器在内存中的物理地址。
[0055]
可选的,所述目标程序的首地址与所述虚拟地址段的段基址对齐。在本说明书实施例中,由于目标程序的首地址与目标程序所在的虚拟地址段的段基址对齐,因此目标程序中生成的任意逻辑地址(段偏移量)不仅代表着目标程序的首地址与该虚拟空间之间的相对位置关系(虚拟空间在应用程序内部的偏移量),也实际上能够代表所需访问的目标内存空间距离虚拟地址段的段基址的相对位置关系(内存中实际目标内存空间在虚拟地址段中的段偏移量),且在该虚拟地址段的段基址被设置为低4位均为0(在数值上与目标程序首地址的逻辑地址相同)的情况下,由于段偏移量的实质就是距离段基址之间的距离,因此可以确保目标程序的首地址的逻辑地址与虚拟地址段的段基址中的零值逻辑位在数值上保持统一,均为相同位数的零值逻辑位,这样才能使在cpu在执行目标程序中的内存访问指令时,根据指令中携带的逻辑地址确定的目标内存空间能够正确反映第一用户态程序所实际需要访问的内存空间,因为只有在目标程序的首地址的逻辑地址与虚拟地址段的段基址中的零值逻辑位在数值上保持统一的基础上,目标程序在程序视角下所需访问的目标内存空间的逻辑地址才能够与实际所需访问的目标内存空间在虚拟地址段内的线性地址的低位数据在数值上保持一致,从而保证目标程序在执行过程中不会发生访问的错位,使访问到目标地址空间正是目标程序所需要访问的内存空间。
[0056]
可选的,目标程序的内存分配空间对应的虚拟地址段可以采用如下策略来设置:首先估算出该目标程序可能需要占用的虚拟地址空间,然后基于估算得到的虚拟地址空间在空闲内存中划分新的地址段,以使新划分的地址段的段长匹配于估算得到的虚拟地址空间,具体而言,是使得新划分的地址段的段长不小于估算得到的虚拟地址空间,但同时需要保证新划分的地址段同样满足其段基址包含位于高位的段号和位于低位的若干零值逻辑位,以及段长为所述若干零值逻辑位所能够表示的最大地址空间,因此,最终新划分的地址段的段长只有几个离散的值可取到,且数值上均满足2的n次幂,n为正整数,为了最大限度地减少内部碎片,可以设估算得到的虚拟地址空间的空间大小为r,确定满足如下公式的n:在确定n后,将2
n
作为目标程序的内存分配空间对应的虚拟地址段的段长,然后在内存中搜索一段处于空闲状态、首地址中处于低n位的低位数据均为0且段长为2
n
的连续地址空间作为目标程序对应的虚拟地址段,使得在该内存分配策略下所确定的虚拟地址段的段基址中处于低n位的低位数据作为零值逻辑位,而处于高位的高位数据(除零值逻辑位之外的逻辑位)则作为该虚拟地址段的段号,目标程序在需要被执行时被加载至基于该策略划分的虚拟地址段内,在该策略下所设置的虚拟地址段的段号和零值逻辑位的位数将可能与之前划分好的地址段有一定的差别,不过这并不影响本说明书所涉及的防内存越界方案的应用,地址拼接机器码在执行时用于根据虚拟地址段的段基址中包含的段号和原始地址中处于低n位的低位数据进行拼接,将拼接得到的拼接地址作为最终确定的访存地址访问内存中的目标内存空间。在本说明书实施例中,由于目标程序可以被分配至能够动态调节段长的虚拟地址段,因此可以尽可能的减少内存中的内部碎片,提高内存的利用率。
[0057]
可选的,还包括:在内存分配程序接收到来自所述目标程序的动态内存请求的情况下,所述内存分配程序将所述虚拟地址段中处于空闲状态且满足所述内存请求包含的请求空间大小的虚地址空间分配给所述目标程序,并向操作系统请求为所述虚地址空间分配
物理内存。在源程序编译为目标程序后,目标程序需要被加载在内存中才能运行,在本说明书实施例中,目标程序的内存分配空间被限定在一个连续的虚拟地址段中,因此目标程序在需要被执行时,会被操作系统加载至内存中其所对应的虚拟地址段内,目标程序在被加载到虚拟地址段中后,一般都不会占用虚拟地址段内的全部内存空间,例如,在目标程序刚刚加载至虚拟地址段中时,目标程序仅占有编译时所定义的静态内存,任何一个指定类型的变量都会在编译过程中申请相对应的静态内存空间。然而,在目标程序的执行过程中,可能会产生一些新的内存占用需求,例如对于一个未定义大小的数组,其在编译时所申请的静态内存是不确定的,因此随着目标程序的允许可能需要动态地为其申请更多的动态内存。在本说明书实施例中,当目标程序需要申请额外的动态内存时,首先需要向发生内存分配程序发出动态内存请求,这里的内存分配程序可以是操作系统,也可以是内存中已经加载并运行的专门用于管理目标程序内存分配的程序,在内存分配程序接受到内存分配请求后,由于该内存分配程序预先获知目标程序被分配的虚拟地址段,并且能够获知目标程序当前占用的内存空间以及虚拟地址段中处于空闲状态的内存空间,因此内存分配程序可以相应于内存分配请求,将所述虚拟地址段中处于空闲状态且满足所述内存请求包含的请求空间大小的虚地址空间(动态内存)分配给所述目标程序,并向操作系统请求为所述虚地址空间分配物理内存,于是目标程序便可以获取并使用为其分配的动态内存,同时内存分配程序也会更新当前目标程序当前占用的内存空间、虚拟地址段内处于空闲状态的内存空间。
[0058]
可选的,通过页表的保护机制将目标程序中代码段中的代码和数据段中的只读数据的修改权限设置为只读模式,用于防止目标程序在执行过程中修改代码或只读数据。在本说明书实施例中,可以启用页式存储管理中对内存的保护机制,例如将目标程序中的代码段中的代码和数据段中只读数据部分对应的页面的权限管理模式设置为只读模式,由此可防止目标程序通过修改代码或只读数据来使编译产生的地址拼接机器码失效,从而增加系统的安全性。
[0059]
图4是一示例性实施例提供的一种设备的结构示意图。请参考图4,在硬件层面,该设备包括处理器402、内部总线404、网络接口406、内存408以及非易失性存储器410,当然还可能包括其他业务所需要的硬件。本说明书一个或多个实施例可以基于软件方式来实现,比如由处理器402从非易失性存储器410中读取对应的计算机程序到内存408中然后运行。当然,除了软件实现方式之外,本说明书一个或多个实施例并不排除其他实现方式,比如逻辑器件抑或软硬件结合的方式等等,也就是说以下处理流程的执行主体并不限定于各个逻辑单元,也可以是硬件或逻辑器件。
[0060]
图5是一示例性实施例提供的一种防内存越界的程序编译装置的框图。请参考图5,该装置可以应用于如图4所示的设备中,例如,该装置包括软/硬编译器或软/硬解释器,以实现本说明书的技术方案。其中,所述装置包括:地址拼接机器码编译单元501,用于在将源程序编译为目标程序的过程中,针对所述源程序中的内存访问代码生成地址拼接机器码,所述目标程序对应的内存分配空间处于一段连续的虚拟地址段内,所述虚拟地址段的段基址包含位于高位的段号和位于低位的若干零值逻辑位,所述虚拟地址段的段长不小于所述若干零值逻辑位所能够表示的最大地址空间;所述地址拼接机器码用于:
针对所述内存访问代码所需访问的原始地址,将所述原始地址的低位数据与所述段号进行拼接,得到的拼接地址用于替代所述原始地址以访问内存中的目标内存空间,其中所述低位数据与所述零值逻辑位的位数相同。
[0061]
可选的,还包括:地址计算机器码编译单元502,用于针对所述内存访问代码生成地址计算机器码,所述地址计算机器码用于将根据所述内存访问代码携带的形式地址按照所述内存访问代码的访问类型对应的地址计算公式计算得到的所述原始地址写入第一预设存储空间,以使所述地址拼接机器码在执行时从第一预设存储空间处获取所述原始地址。
[0062]
可选的,所述地址拼接机器码中包含寄存器拼接机器码和寄存器访存机器码;其中,所述寄存器拼接机器码用于将第一源寄存器中预先存储的所述段号与第二源寄存器中的预先存储的所述低位数据拼接得到的所述拼接地址写入目的寄存器;所述寄存器访存机器码用于根据所述目的寄存器中写入的所述拼接地址访问所述内存中的所述目标内存空间。
[0063]
可选的,所述地址拼接机器码中包含拼接访存机器码,所述拼接访存机器码用于将所述原始地址写入原始地址寄存器,并根据拼接地址寄存器中生成的所述拼接地址访问所述内存中的所述目标内存空间;其中,所述拼接地址寄存器中的高位空间与预先存储有所述段号的段号寄存器相连,所述拼接地址寄存器中的低位空间与原始地址寄存器中的低位空间相连,所述原始地址寄存器中的低位空间用于存储所述原始地址中包含的所述低位数据。
[0064]
可选的,所述地址拼接机器码编译单元501具体用于:在对所述源程序进行解释执行的过程中,将所述源程序编译为所述目标程序;或者,将所述源程序aot编译为所述目标程序。
[0065]
可选的,所述段号或者所述段基址预先存储在第二预设存储空间中,以使所述地址拼接机器码在执行时从第二预设存储空间处获取所述段基址中包含的所述段号。
[0066]
可选的,第二预设存储空间包括下述任一:寄存器、所述虚拟地址段中预定义的内存空间或所述虚拟地址段外预定义的内存空间。
[0067]
可选的,第二预设存储空间仅参与生成所述地址拼接机器码的编译过程。
[0068]
可选的,第二预设存储空间的修改权限由操作系统所有。
[0069]
可选的,所述目标程序的首地址与所述虚拟地址段的段基址对齐。
[0070]
可选的,所述内存访问代码包括字节码。
[0071]
可选的,所述源程序或所述目标程序为部署于区块链系统中的智能合约。
[0072]
上述实施例阐明的系统、装置、模块或单元,具体可以由计算机芯片或实体实现,或者由具有某种功能的产品来实现。一种典型的实现设备为计算机,计算机的具体形式可以是个人计算机、膝上型计算机、蜂窝电话、相机电话、智能电话、个人数字助理、媒体播放器、导航设备、电子邮件收发设备、游戏控制台、平板计算机、可穿戴设备或者这些设备中的任意几种设备的组合。
[0073]
在一个典型的配置中,计算机包括一个或多个处理器 (cpu)、输入/输出接口、网
络接口和内存。
[0074]
内存可能包括计算机可读介质中的非永久性存储器,随机存取存储器 (ram) 和/或非易失性内存等形式,如只读存储器 (rom) 或闪存(flash ram)。内存是计算机可读介质的示例。
[0075]
计算机可读介质包括永久性和非永久性、可移动和非可移动媒体可以由任何方法或技术来实现信息存储。信息可以是计算机可读指令、数据结构、程序的模块或其他数据。计算机的存储介质的例子包括,但不限于相变内存 (pram)、静态随机存取存储器 (sram)、动态随机存取存储器 (dram)、其他类型的随机存取存储器 (ram)、只读存储器 (rom)、电可擦除可编程只读存储器 (eeprom)、快闪记忆体或其他内存技术、只读光盘只读存储器 (cd
‑
rom)、数字多功能光盘 (dvd) 或其他光学存储、磁盒式磁带、磁盘存储、量子存储器、基于石墨烯的存储介质或其他磁性存储设备或任何其他非传输介质,可用于存储可以被计算设备访问的信息。按照本文中的界定,计算机可读介质不包括暂存电脑可读媒体 (transitory media),如调制的数据信号和载波。
[0076]
还需要说明的是,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、商品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、商品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个
……”
限定的要素,并不排除在包括所述要素的过程、方法、商品或者设备中还存在另外的相同要素。
[0077]
上述对本说明书特定实施例进行了描述。其它实施例在所附权利要求书的范围内。在一些情况下,在权利要求书中记载的动作或步骤可以按照不同于实施例中的顺序来执行并且仍然可以实现期望的结果。另外,在附图中描绘的过程不一定要求示出的特定顺序或者连续顺序才能实现期望的结果。在某些实施方式中,多任务处理和并行处理也是可以的或者可能是有利的。
[0078]
在本说明书一个或多个实施例使用的术语是仅仅出于描述特定实施例的目的,而非旨在限制本说明书一个或多个实施例。在本说明书一个或多个实施例和所附权利要求书中所使用的单数形式的“一种”、“所述”和“该”也旨在包括多数形式,除非上下文清楚地表示其他含义。还应当理解,本文中使用的术语“和/或”是指并包含一个或多个相关联的列出项目的任何或所有可能组合。
[0079]
应当理解,尽管在本说明书一个或多个实施例可能采用术语第一、第二、第三等来描述各种信息,但这些信息不应限于这些术语。这些术语仅用来将同一类型的信息彼此区分开。例如,在不脱离本说明书一个或多个实施例范围的情况下,第一信息也可以被称为第二信息,类似地,第二信息也可以被称为第一信息。取决于语境,如在此所使用的词语“如果”可以被解释成为“在
……
时”或“当
……
时”或“响应于确定”。
[0080]
以上所述仅为本说明书一个或多个实施例的较佳实施例而已,并不用以限制本说明书一个或多个实施例,凡在本说明书一个或多个实施例的精神和原则之内,所做的任何修改、等同替换、改进等,均应包含在本说明书一个或多个实施例保护的范围之内。
转载请注明原文地址:https://doc.8miu.com/read-1450313.html