about summary refs log tree commit diff stats
path: root/example/expression
diff options
context:
space:
mode:
authorserpilliere <serpilliere@users.noreply.github.com>2018-12-20 20:05:55 +0100
committerGitHub <noreply@github.com>2018-12-20 20:05:55 +0100
commit011e1e209b3d00afe3c8e65000209a568c5eb791 (patch)
treed9d50826df2c94bdcc10a2e676cb4739ee685f66 /example/expression
parent75417940371bf1bf95d2f562141f2284d1f77f71 (diff)
parentbff40462030dc01ee651595370479619e15500d2 (diff)
downloadmiasm-011e1e209b3d00afe3c8e65000209a568c5eb791.tar.gz
miasm-011e1e209b3d00afe3c8e65000209a568c5eb791.zip
Merge pull request #904 from commial/feature/export-LLVM
Feature/export llvm
Diffstat (limited to 'example/expression')
-rw-r--r--example/expression/export_llvm.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/example/expression/export_llvm.py b/example/expression/export_llvm.py
new file mode 100644
index 00000000..6f4ed591
--- /dev/null
+++ b/example/expression/export_llvm.py
@@ -0,0 +1,83 @@
+from argparse import ArgumentParser
+from miasm2.analysis.binary import Container
+from miasm2.analysis.machine import Machine
+from miasm2.jitter.llvmconvert import LLVMType, LLVMContext_IRCompilation, LLVMFunction_IRCompilation
+from llvmlite import ir as llvm_ir
+from miasm2.expression.simplifications import expr_simp_high_to_explicit
+
+parser = ArgumentParser("LLVM export example")
+parser.add_argument("target", help="Target binary")
+parser.add_argument("addr", help="Target address")
+parser.add_argument("--architecture", "-a", help="Force architecture")
+args = parser.parse_args()
+
+# This part focus on obtaining an IRCFG to transform #
+cont = Container.from_stream(open(args.target))
+machine = Machine(args.architecture if args.architecture else cont.arch)
+ir = machine.ir(cont.loc_db)
+dis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db)
+asmcfg = dis.dis_multiblock(int(args.addr, 0))
+ircfg = ir.new_ircfg_from_asmcfg(asmcfg)
+ircfg.simplify(expr_simp_high_to_explicit)
+######################################################
+
+# Instanciate a context and the function to fill
+context = LLVMContext_IRCompilation()
+context.ir_arch = ir
+
+func = LLVMFunction_IRCompilation(context, name="test")
+func.ret_type = llvm_ir.VoidType()
+func.init_fc()
+
+# Here, as an example, we arbitrarily represent registers with global
+# variables. Locals allocas are used for the computation during the function,
+# and is finally saved in the aforementionned global variable.
+
+# In other words, for each registers:
+# entry:
+#     ...
+#     %reg_val_in = load i32 @REG
+#     %REG = alloca i32
+#     store i32 %reg_val_in, i32* %REG
+#     ...
+# exit:
+#     ...
+#     %reg_val_out = load i32 %REG
+#     store i32 %reg_val_out, i32* @REG
+#     ...
+
+all_regs = set()
+for block in ircfg.blocks.itervalues():
+    for irs in block.assignblks:
+        for dst, src in irs.get_rw(mem_read=True).iteritems():
+            elem = src.union(set([dst]))
+            all_regs.update(x for x in elem
+                            if x.is_id())
+
+reg2glob = {}
+for var in all_regs:
+    # alloca reg = global reg
+    data = context.mod.globals.get(str(var), None)
+    if data is None:
+        data = llvm_ir.GlobalVariable(context.mod,  LLVMType.IntType(var.size), name=str(var))
+    data.initializer = LLVMType.IntType(var.size)(0)
+    value = func.builder.load(data)
+    func.local_vars_pointers[var.name] = func.builder.alloca(llvm_ir.IntType(var.size), name=var.name)
+    func.builder.store(value, func.local_vars_pointers[var.name])
+    reg2glob[var] = data
+
+# IRCFG is imported, without the final "ret void"
+func.from_ircfg(ircfg, append_ret=False)
+
+# Finish the saving of registers (temporary version to global)
+for reg, glob in reg2glob.iteritems():
+    value = func.builder.load(func.local_vars_pointers[reg.name])
+    func.builder.store(value, glob)
+
+# Finish the function
+func.builder.ret_void()
+
+# Get it back
+open("out.ll", "w").write(str(func))
+# The optimized CFG can be seen with:
+# $ opt -O2 -dot-cfg -S out.ll && xdot cfg.test.dot