【问题标题】:Getting "actual" registers from MCInsts (x86)从 MCInsts (x86) 获取“实际”寄存器
【发布时间】:2013-12-06 05:39:48
【问题描述】:

我使用 llvm-mc 的目标是制作一个相对智能的反汇编程序(识别和跟踪本地人,轻松跟踪分支等),其中一部分是创建反汇编指令的字符串表示形式。

当我开始这个时,我希望我能够相对容易地识别MCInsts 使用的寄存器和值,并自己制作另一个我可以轻松使用的表示。但是,经过一番调查,我意识到,以指令的文本表示形式显示的操作数与 MCInst 对象中实际存在的操作数之间的相关性相当低。以下是一些示例(英特尔语法):

  • 将 11587 作为 32 位立即数移动到 eax 将使用 MOV32ri 操作码完成。文本表示将是mov eax, 11587。对应的MCInst 将有两个操作数,一个寄存器和一个立即数。这对我有用。这很棒。
  • 11587 添加到eax 将使用ADD32ri 操作码完成。文本表示为add eax, 11587。但是,这一次,对应的MCInst三个 操作数:eax 有两次,最后是立即数。这不是很好。我可以假设这是降低过程的产物,eax 的第一个实例是目标寄存器,第二个是源寄存器(即使 x86 不区分两者),我可以解决这个问题。
  • 将 32 位 eip 相对值移动到 eax 将使用 MOV32ao32 操作码完成。文本表示为mov eax, dword ptr [11587]。在这种情况下,MCInst 甚至没有eax 的操作数,它只能从操作码名称中存在的操作数类型推断出来。我也可以解决这个问题,但事情变得越来越不漂亮,我只测试了 x86 支持的 1300+ 中的 5-6 种不同的指令。

显然,出于显示文本的目的,我可以使用MCInstPrinter 获得文本表示,但是那里显示的内容与MCInst 所拥有的内容之间的映射仍然很模糊。

有没有一种直接的方法来判断哪些操作数出现在指令的文本表示中?

【问题讨论】:

    标签: c++ assembly x86 llvm


    【解决方案1】:

    添加三个参数听起来像是编译器构建器对Three address code 的偏好正在渗透,因为在英特尔汇编器中没有理由这样做。 (您不能使用 ADD 指令添加和存储到不同的寄存器,但您可以使用 LEA)。

    如果计算所有扩展(如 SSE、FPU 等),操作码会达到数百个,更糟糕的是,由于寻址模式和前缀,操作码会出现多种变体。

    如果您的 llvm-mc 系统不提供该功能,NASM 汇编器在源代码中有一些表,您可以尝试挖掘这些表。

    【讨论】:

      【解决方案2】:

      MC 级别很低,操作数布局取决于操作码。也就是说,有映射表可以告诉你什么在哪里。 MCInstrDesc 和 MCOperandInfo 将告诉您哪些操作数、源和目标,它们是立即数、寄存器等以及一组标志。

      您还需要熟悉 MCRegisterClass 和 MCRegisterInfo 以及其他一些东西。这是一个复杂的接口,因为表示任意目标信息的任务很复杂。

      我会查看各种基于 MC 的工具的代码以开始使用。你不应该需要自己的代表,MC应该有你需要的一切。

      【讨论】:

      • 我查看了 llvm-mc 和 x86 td 文件,但无法找到在不使用 AsmPrinter 的情况下使用用于打印指令的表格的方法。据我所知,整个打印机是使用 tablegen 直接生成 llvm 字节码的,所以我不知道该怎么做。
      猜你喜欢
      • 1970-01-01
      • 2012-02-17
      • 2022-01-13
      • 2019-01-02
      • 2013-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-04
      相关资源
      最近更新 更多