Miasm2
 All Classes Namespaces Files Functions Variables Typedefs Properties Macros
jitcore_tcc.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3 
4 import os
5 from distutils.sysconfig import get_python_inc
6 from subprocess import Popen, PIPE
7 
8 from miasm2.ir.ir2C import irblocs2C
9 from miasm2.jitter import jitcore, Jittcc
10 
11 
12 def jit_tcc_compil(func_name, func_code):
13  global Jittcc
14  c = Jittcc.tcc_compil(func_name, func_code)
15  return c
16 
17 
18 class jit_tcc_code():
19 
20  def __init__(self, c):
21  self.c = c
22 
23  def __call__(self, cpu, vm):
24  return Jittcc.tcc_exec_bloc(self.c, cpu, vm)
25 
26 
27 def gen_core(arch, attrib):
28  lib_dir = os.path.dirname(os.path.realpath(__file__))
29 
30  txt = ""
31  txt += '#include "%s/queue.h"\n' % lib_dir
32  txt += '#include "%s/vm_mngr.h"\n' % lib_dir
33  txt += '#include "%s/vm_mngr_py.h"\n' % lib_dir
34  txt += '#include "%s/JitCore.h"\n' % lib_dir
35  txt += '#include "%s/arch/JitCore_%s.h"\n' % (lib_dir, arch.name)
36 
37  txt += r'''
38 #define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;}
39 '''
40  return txt
41 
42 
43 def gen_C_source(ir_arch, func_code):
44  c_source = ""
45  c_source += "\n".join(func_code)
46 
47  c_source = gen_core(ir_arch.arch, ir_arch.attrib) + c_source
48 
49  c_source = """
50  #ifdef __x86_64__
51  #ifndef __LP64__
52  /*
53  for ubuntu ?!? XXX TODO
54  /!\ force 64 bit system using 64 bits libc
55  change this to __ILP32__ to do so.
56  */
57  #define __LP64__
58  #endif
59  #endif
60  """ + "#include <Python.h>\n" + c_source
61 
62  return c_source
63 
64 
65 class objref:
66 
67  def __init__(self, obj):
68  self.obj = obj
69 
70 
71 class myresolver:
72 
73  def __init__(self, offset):
74  self.offset = offset
75 
76  def ret(self):
77  return "return PyLong_FromUnsignedLongLong(0x%X);" % self.offset
78 
79 from miasm2.core.utils import keydefaultdict
80 
81 
82 class resolver:
83 
84  def __init__(self):
85  self.resolvers = keydefaultdict(myresolver)
86 
87  def get_resolver(self, offset):
88  return self.resolvers[offset]
89 
90 
92 
93  "JiT management, using LibTCC as backend"
94 
95  def __init__(self, ir_arch, bs=None):
97  super(JitCore_Tcc, self).__init__(ir_arch, bs)
98  self.resolver = resolver()
99  self.exec_wrapper = Jittcc.tcc_exec_bloc
100  self.tcc_states = {}
101  self.ir_arch = ir_arch
102 
103  def deleteCB(self, offset):
104  "Free the TCCState corresponding to @offset"
105  if offset in self.tcc_states:
106  Jittcc.tcc_end(self.tcc_states[offset])
107  del self.tcc_states[offset]
108 
109  def load(self):
110  # os.path.join(os.path.dirname(os.path.realpath(__file__)), "jitter")
111  lib_dir = os.path.dirname(os.path.realpath(__file__))
112  libs = []
113  libs.append(os.path.join(lib_dir, 'VmMngr.so'))
114  libs.append(os.path.join(lib_dir, 'arch/JitCore_%s.so' % (self.ir_arch.arch.name)))
115  libs = ';'.join(libs)
116  jittcc_path = Jittcc.__file__
117  include_dir = os.path.dirname(jittcc_path)
118  include_dir += ";" + os.path.join(include_dir, "arch")
119  # print include_dir
120 
121  # XXX HACK
122  # As debian/ubuntu have moved some include files using arch directory,
123  # TCC doesn't know them, so we get the info from GCC
124  # For example /usr/include/x86_64-linux-gnu which contains limits.h
125  p = Popen(["cc", "-Wp,-v", "-E", "-"],
126  stdout=PIPE, stderr=PIPE, stdin=PIPE)
127  p.stdin.close()
128  include_files = p.stderr.read().split('\n')
129  include_files = [x[1:]
130  for x in include_files if x.startswith(' /usr/include')]
131  include_files += [include_dir, get_python_inc()]
132  include_files = ";".join(include_files)
133  Jittcc.tcc_set_emul_lib_path(include_files, libs)
134 
135  def __del__(self):
136  for tcc_state in self.tcc_states.values():
137  Jittcc.tcc_end(tcc_state)
138 
139  def jitirblocs(self, label, irblocs):
140  f_name = "bloc_%s" % label.name
141  f_declaration = 'int %s(block_id * BlockDst, JitCpu* jitcpu)' % f_name
142  out = irblocs2C(self.ir_arch, self.resolver, label, irblocs,
143  gen_exception_code=True,
144  log_mn=self.log_mn,
145  log_regs=self.log_regs)
146  out = [f_declaration + '{'] + out + ['}\n']
147  c_code = out
148 
149  func_code = gen_C_source(self.ir_arch, c_code)
150 
151  # open('tmp_%.4d.c'%self.jitcount, "w").write(func_code)
152  self.jitcount += 1
153  tcc_state, mcode = jit_tcc_compil(f_name, func_code)
154  jcode = jit_tcc_code(mcode)
155  self.lbl2jitbloc[label.offset] = mcode
156  self.tcc_states[label.offset] = tcc_state
157  self.addr2obj[label.offset] = jcode
158  self.addr2objref[label.offset] = objref(jcode)
def irblocs2C
Definition: ir2C.py:408