首页 文章

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

提问于
浏览
2

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

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

  • 将11587作为32位立即移动到 eax 将使用 MOV32ri 操作码完成 . 文字表示将是 mov eax, 11587 . 相应的 MCInst 将有两个操作数,一个寄存器和一个立即数 . 这适合我 . 这很棒 .

  • 11587 添加到 eax 将使用 ADD32ri 操作码完成 . 文字表示将是 add eax, 11587 . 但是,这次,相应的 MCInst 有三个操作数: eax 有两次,而最后是立即数 . 这不是很好 . 我可以假设这是降级过程的一个工件, eax 的第一个实例是目标寄存器,第二个实例是源(即使x86不区分两者),我可以破解在那附近 .

  • 使用 MOV32ao32 操作码将32位 eip -relative值移动到 eax . 文字表示将是 mov eax, dword ptr [11587] . 在这种情况下, MCInst 甚至没有 eax 的操作数,它只能从操作码名称中的操作数类型推断出来 . 我也可以解决这个问题,但事情越来越少,我只测试了x86支持的1300个不同的指令 .

显然,为了显示文本,我可以用 MCInstPrinter 获得文本表示,但是那里显示的内容和 MCInst 之间的映射仍然很混乱 .

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

2 回答

  • 0

    添加三个参数听起来像Three address code的编译器构建器首选项正在流行,因为在英特尔汇编程序中没有理由这样做 . (您不能使用ADD指令添加和存储到不同的寄存器,但您可以使用LEA) .

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

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

  • 1

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

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

    我会看一下各种基于MC的工具的代码 . 你不应该需要自己的代表,MC应该拥有你需要的一切 .

相关问题