从MCInsts(x86)获取“实际”寄存器

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

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

  • 将11587作为一个32位立即数移动到eax中将使用MOV32ri操作码。 文本表示将是mov eax, 11587 。 相应的MCInst将有两个操作数,一个寄存器和一个立即数。 这对我有用。 这很棒。
  • 使用ADD32ri操作码可以将11587添加到eax 。 文本表示将是add eax, 11587 。 但是,这次,相应的MCInst有三个操作数: eax有两次,直接结束。 这不是很好。 我可以假设这是下降过程的人为因素, eax的第一个实例是目标寄存器,第二个是源(尽管x86不区分这两个),我可以破解在那附近。
  • 使用MOV32ao32操作码将32位eip相对值移至eax 。 文本表示将是mov eax, dword ptr [11587] 。 在这种情况下, MCInst甚至没有eax的操作数,只能从操作码名称中存在的操作数类型推断出来。 我也可以解决这个问题,但事情变得越来越不美观了,我只测试了x86支持的1300多种不同的指令。
  • 显然,为了显示文本,我可以用MCInstPrinter获得文本表示,但是在那里显示的内容与MCInst具有的内容之间的映射仍然是泥泞的。

    有没有一种直接的方法可以告诉哪些操作数出现在指令的文本表示中?


    添加三个参数听起来像是一个编译器构建器首选项。三个地址代码正在流传,因为在英特尔汇编器中没有这样的理由。 (您不能通过ADD指令添加和存储到不同的寄存器,但可以使用LEA)。

    如果您计算所有扩展(如SSE,FPU等),则操作码会达到数百个,并且由于寻址模式和前缀的原因,操作码有多种变体。

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


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

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

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

    链接地址: http://www.djcxy.com/p/72441.html

    上一篇: Getting "actual" registers from MCInsts (x86)

    下一篇: Does anybody know what this C++ inline assembly does?