Code generation JIT仿真和跟踪脏内存块

Code generation JIT仿真和跟踪脏内存块,code-generation,jit,emulation,Code Generation,Jit,Emulation,我正在为玩具CPU(TR3200CPU)开发一个模拟器。实际上我有一个纯解释器内核,但我正在研究开发一个跟踪JIT cpu内核。 我怀疑如何跟踪已经JIT的源代码是否被模拟代码(自修改代码或类似于操作系统将编程加载到RAM的代码)修改 我正在考虑使用分段树或区间树来解决这个问题,但我找不到任何信息或示例来说明如何处理这个问题 换句话说。。。我知道如何使用JIT(我正在考虑使用asmjit),我应该将jitted代码存储在一个使用jitted块的开始地址作为索引的映射上;我对如何处理循环计数和设备

我正在为玩具CPU(TR3200CPU)开发一个模拟器。实际上我有一个纯解释器内核,但我正在研究开发一个跟踪JIT cpu内核。 我怀疑如何跟踪已经JIT的源代码是否被模拟代码(自修改代码或类似于操作系统将编程加载到RAM的代码)修改 我正在考虑使用分段树或区间树来解决这个问题,但我找不到任何信息或示例来说明如何处理这个问题

换句话说。。。我知道如何使用JIT(我正在考虑使用asmjit),我应该将jitted代码存储在一个使用jitted块的开始地址作为索引的映射上;我对如何处理循环计数和设备与jitted代码同步有一些想法。但我不清楚如何处理来宾程序在jitted内存块上的写入

例如:我们有一个简单的操作系统,它在地址0x100-0x500执行了一个程序,并且返回正确。JIT cpu核心将(乐观地)生成表示这些代码块的本机代码。现在,如果操作系统加载另一个程序并将其放置在0x200-0x300地址块上,则不应在0x100-0x500的旧jitted块被覆盖时使其无效。
或者最坏的情况是,程序会自我重写,使jitted块无效如何检测到这一点?

即使使用一个中等复杂的数据结构来跟踪来宾内存的更改,问题在于必须能够从jitted代码中查询和更新它。为了避免代码大小出现荒谬的膨胀,您可能需要在jitted代码执行存储指令时插入对某个函数的调用,该函数将写入间隔树(而不是内联写入)。性能可能会受到影响,您可以从一开始就解释代码。此外,必须非常小心,以免仿真器的其他部分在不更新数据结构的情况下写入相应的页面

有一种稍微不那么便携的方法,它涉及到利用主机操作系统的虚拟内存设施。当JIT为来宾内存块发出代码时,将相应的虚拟内存页标记为只读。任何后续的写入尝试都将触发一个异常(如
SIGSEGV
),该异常可被宿主程序捕获。在收到此异常后,宿主程序会立即使从与出错页重叠的来宾内存生成的所有jitted代码无效,然后重新启用对该页的写访问,以便完成存储

虽然此解决方案可以处理大多数写操作,但它不能处理一段jitted代码修改紧跟其后的指令的情况。想知道为什么,考虑会发生什么:

  • jitted代码存储到来宾内存中的一部分,从该部分jitted下面的指令之一
  • 宿主程序引发并处理异常。故障页面中的所有jitted代码(包括其存储首先触发异常的代码)都将无效。再次启用写入访问权限
  • 异常处理程序返回,但在哪里?当然,对于出错指令,这是无效代码的一部分!哦 据我所知,有两种选择。要么忽略此问题,有效地使修改邻近指令的代码行为未定义,要么在异常处理程序中设置某种无效标志,并在每次存储后对其进行测试,如果测试失败,则跳转到解释器中


    快速搜索建议您处理对来宾内存的修改,但我无法验证它。

    嘿!为什么投反对票?可能是因为没有明确的问题。:-)谢谢你回答为什么投票被否决。我会试着重写。在漫长的一天之前,我在医院的候诊室通过电话写下了这封信。。。。