woo*_*tok 3 x86 code-generation llvm codegen
我想替换jmp *(eax)代码中的间接指令以mov *(eax),ebx; jmp *ebx获取x86可执行文件.
在实现之前,我想制作LLVM编译器,每次jmp *(eax)通过添加一些打印语句检测到指令时记录输出.
然后我想继续替换间接序列.
从我从谷歌搜索和文章中看到的,我可以通过修改llvm后端中的x86asmprinter来实现这一点.但我不知道该怎么做.任何帮助或阅读将不胜感激.
注意:我的实际要求涉及间接跳转和弹出,但我想从此开始,以便在我深入了解之前了解更多后端.
我完成了我的项目.发布我的方法以造福他人.
LLVM后端的主要功能是根据目标体系结构和其他规范将中间表示转换为最终可执行文件.LLVM后端本身由几个阶段组成,这些阶段针对特定的优化,指令选择,调度和指令发送.这些阶段是必需的,因为IR是一种非常通用的表示,需要进行大量修改才能最终将它们转换为目标特定的可执行文件.
1)每次编译生成时都要记录 jmp *(eax)
我们可以通过在指令发出/打印阶段添加打印语句来实现这一点.在完成IR的大部分主转换之后,会有一个AsmPrinter传递,它通过每个函数的基本块中的每个机器指令.这个主循环是在lib/CodeGen/AsmPrinter/AsmPrinter.cpp:AsmPrinter::EmitFunctionBody().还有其他相关的函数,如EmitFunctionEpilogue,EmitFunctionPrologue.这些函数最终调用EmitInstruction用于特定的体系结构,例如:lib/Target/X86/X86AsmPrinter.cpp.如果您稍微修改一下,可以调用MI.getOpcode()并将其与定义的枚举枚举进行比较,以便打印日志.
例如,对于在X86中使用寄存器的跳转,它是X86 :: JMP64r.您可以使用MI.getOperand(0)等获取相关的寄存器.
if(MI->getOpcode() == X86::JMP64r)
dbgs() << "Found jmp *x instruction\n";
Run Code Online (Sandbox Code Playgroud)
2)更换说明所需的更改取决于您需要的更换类型.如果您需要有关寄存器或先前指令的更多上下文,我们需要在Pass链中实现更高的更改.存在称为选择DAG(有向非循环图)的指令的表示,其存储每个指令与先前指令的依赖性.例如,在序列中
mov myvalue,%rax
jmp *rax
Run Code Online (Sandbox Code Playgroud)
由于rax的值取决于mov指令,因此DAG将使jmp指令指向移动指令(以及可能在其之前的其他节点).您可以使用所需的节点替换此处的节点.如果操作正确,最终应该更改最终指令.SelectionDAG代码位于lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp.总是最好先找到想要改变的理想场所.在DAG进行拓扑排序之前,每个IR语句都会经历多次更改,以使指令处于线性序列中.可以使用-view-dag*选项查看图表llc --help-hidden.就我而言,我刚刚在EmitInstruction中添加了一个特定的检查,并添加了代码以发出我想要的两条指令.
LLVM文档总是在那里,但我发现Eli Bendersky的两篇文章比任何其他资源更有帮助.LLVM指令的生命周期和更深入研究LLVM代码生成.这些文章讨论了非常复杂的TableGen描述和指令匹配过程,如果你感兴趣的话,这很酷.
| 归档时间: |
|
| 查看次数: |
383 次 |
| 最近记录: |