Memory 如果v8使用;代码“;或;“文本”;内存类型,或者如果所有内容都在堆/堆栈中

Memory 如果v8使用;代码“;或;“文本”;内存类型,或者如果所有内容都在堆/堆栈中,memory,compiler-construction,v8,jit,Memory,Compiler Construction,V8,Jit,在典型的内存布局中,有4项: 代码/文本(程序本身的编译代码所在的位置) 资料 堆叠 堆 我不熟悉内存布局,所以我想知道v8是一个JIT编译器,它可以动态生成代码,是将这些代码存储在内存的“代码”段中,还是将其与其他内容一起存储在堆中。我不确定操作系统是否允许您访问代码/文本,因此不确定这是否是一个愚蠢的问题 堆和堆栈是程序在运行时可以分配的内存区域。这并不特定于V8或JIT编译器。关于更多细节,我谦恭地建议您阅读插图来源的任何书籍;-) 堆和堆栈是程序在运行时可以分配的内存区域。这并不特定于V

在典型的内存布局中,有4项:

  • 代码/文本(程序本身的编译代码所在的位置)
  • 资料
  • 堆叠
  • 我不熟悉内存布局,所以我想知道v8是一个JIT编译器,它可以动态生成代码,是将这些代码存储在内存的“代码”段中,还是将其与其他内容一起存储在堆中。我不确定操作系统是否允许您访问代码/文本,因此不确定这是否是一个愚蠢的问题


    堆和堆栈是程序在运行时可以分配的内存区域。这并不特定于V8或JIT编译器。关于更多细节,我谦恭地建议您阅读插图来源的任何书籍;-)

    堆和堆栈是程序在运行时可以分配的内存区域。这并不特定于V8或JIT编译器。关于更多细节,我谦恭地建议您阅读插图来源的任何书籍;-)

    对于目前常用的主要CPU上运行的主要操作系统来说,下面是正确的。在旧的或一些嵌入式操作系统上(特别是在没有虚拟内存的操作系统上,情况要简单得多),或者在没有操作系统的情况下运行代码,或者在不支持内存保护的CPU上运行代码时,情况会有所不同

    你问题中的情况有点简单。它没有显示的一点是(虚拟)内存是由操作系统提供给您的页面组成的。每个页面都有自己的权限,控制您的进程是否可以读取、写入和/或执行该页面中的数据

    二进制文件的文本部分将加载到可执行但不可写的页面上。只读数据部分将加载到既不可写也不可执行的页面上。图片中的所有其他内存(未初始化的数据、堆、堆栈)将存储在可写但不可执行的页面上

    这些权限可防止安全缺陷(如缓冲区溢出),否则攻击者可通过使程序跳入攻击者提供的代码或让攻击者覆盖文本部分中的代码来执行任意代码

    现在,关于JIT编译,这些权限的问题是您无法执行JIT编译的代码:如果您将其存储在堆栈或堆(或全局变量内),它将不在可执行页上,因此当您尝试跳入代码时,程序将崩溃。如果您试图将其存储在文本区域(通过使用最后一页上的剩余内存或覆盖部分JIT编译器代码),程序将崩溃,因为您试图写入只读内存

    但幸运的是,操作系统允许您更改页面的权限(在POSIX系统上,可以使用
    mprotect
    和在Windows上使用
    VirtualProtect
    )。因此,您的第一个想法可能是将生成的代码存储在堆上,然后简单地使包含的页面可执行。但是,这可能有点问题:
    VirtualProtect
    mprotect
    的一些实现需要指向页面开头的指针,但是如果使用
    malloc
    (或
    new
    或您的等效语言)分配数组,则数组不一定从页面开头开始。此外,您的阵列可能与其他数据共享一个页面,而您不希望这些数据是可执行的

    为了防止这些问题,您可以在类似Unix的操作系统上使用
    mmap
    ,在Windows上使用
    VirtualAlloc
    等函数,为您提供“自己”的内存页。这些函数将分配足够的页面,以包含您请求的内存,并返回指向该内存开头(将位于第一页开头)的指针。这些页面将不可用于
    malloc
    。也就是说,即使您的数组明显小于操作系统上的页面大小,该页面也将仅用于存储您的数组-后续调用
    malloc
    将不会返回指向该页面内存的指针


    因此,大多数JIT编译器的工作方式是使用
    mmap
    VirtualAlloc
    分配读写内存,将生成的机器指令复制到该内存中,使用
    mprotect
    VirtualProtect
    使内存可执行且不可写(出于安全原因,如果可以避免的话,您永远不希望内存同时具有可执行性和可写性),然后跳转到内存中地址,内存将是内存堆区域的一部分,但它将与堆分离,因为它将不由
    malloc
    free
    管理。以下内容适用于当前常用的主要CPU上运行的主要操作系统。旧的或某些嵌入式操作系统会有所不同TEM(特别是在没有虚拟内存的操作系统上要简单得多),或者在没有操作系统的情况下运行代码,或者在不支持内存保护的CPU上运行代码

    您问题中的图片有点简单。它没有显示(虚拟)内存是由操作系统提供给您的页面组成的。每个页面都有自己的权限,控制您的进程是否可以读取、写入和/或执行该页面中的数据

    二进制文件的文本部分将加载到可执行但不可写的页面上。只读数据部分将加载到既不可写也不可执行的页面上。图片中的所有其他内存((未)初始化数据、堆、堆栈)将存储在可写但不可执行的页面上

    这些权限可防止安全缺陷(如缓冲区溢出),否则攻击者可通过使程序运行来执行任意代码