Miasm2
 All Classes Namespaces Files Functions Variables Typedefs Properties Macros
Public Member Functions | Public Attributes | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
miasm2.core.sembuilder.SemBuilder Class Reference
+ Inheritance diagram for miasm2.core.sembuilder.SemBuilder:
+ Collaboration diagram for miasm2.core.sembuilder.SemBuilder:

Public Member Functions

def __init__
 
def functions
 
def parse
 

Public Attributes

 transformer
 

Private Member Functions

def _parse_body
 

Static Private Member Functions

def _create_labels
 

Private Attributes

 _ctx
 
 _functions
 

Detailed Description

Helper for building instruction's semantic side effects method

This class provides a decorator @parse to use on them.
The context in which the function will be parsed must be supplied on
instanciation

Definition at line 97 of file sembuilder.py.

Constructor & Destructor Documentation

def miasm2.core.sembuilder.SemBuilder.__init__ (   self,
  ctx 
)
Create a SemBuilder
@ctx: context dictionnary used during parsing

Definition at line 105 of file sembuilder.py.

106  def __init__(self, ctx):
107  """Create a SemBuilder
108  @ctx: context dictionnary used during parsing
109  """
110  # Init
112  self._ctx = dict(m2_expr.__dict__)
113  self._ctx["irbloc"] = irbloc
114  self._functions = {}
115 
116  # Update context
117  self._ctx.update(ctx)

Member Function Documentation

def miasm2.core.sembuilder.SemBuilder._create_labels ( )
staticprivate
Return the AST standing for label creations

Definition at line 124 of file sembuilder.py.

125  def _create_labels():
126  """Return the AST standing for label creations"""
127  out = ast.parse("lbl_end = ExprId(ir.get_next_instr(instr))").body
128  out += ast.parse("lbl_if = ExprId(ir.gen_label())").body
129  return out

+ Here is the caller graph for this function:

def miasm2.core.sembuilder.SemBuilder._parse_body (   self,
  body,
  argument_names 
)
private
Recursive function transforming a @body to a block expression
Return:
 - AST to append to body (real python statements)
 - a list of blocks, ie list of affblock, ie list of ExprAff (AST)

Definition at line 130 of file sembuilder.py.

131  def _parse_body(self, body, argument_names):
132  """Recursive function transforming a @body to a block expression
133  Return:
134  - AST to append to body (real python statements)
135  - a list of blocks, ie list of affblock, ie list of ExprAff (AST)"""
136 
137  # Init
138  ## Real instructions
139  real_body = []
140  ## Final blocks
141  blocks = [[[]]]
142 
143  for statement in body:
144 
145  if isinstance(statement, ast.Assign):
146  src = self.transformer.visit(statement.value)
147  dst = self.transformer.visit(statement.targets[0])
148 
149  if (isinstance(dst, ast.Name) and
150  dst.id not in argument_names and
151  dst.id not in self._ctx):
152 
153  # Real variable declaration
154  statement.value = src
155  real_body.append(statement)
156  continue
157 
158  dst.ctx = ast.Load()
159 
160  res = ast.Call(func=ast.Name(id='ExprAff',
161  ctx=ast.Load()),
162  args=[dst, src],
163  keywords=[],
164  starargs=None,
165  kwargs=None)
166 
167  blocks[-1][-1].append(res)
168 
169  elif (isinstance(statement, ast.Expr) and
170  isinstance(statement.value, ast.Str)):
171  # String (docstring, comment, ...) -> keep it
172  real_body.append(statement)
173 
174  elif (isinstance(statement, ast.If) and
175  not statement.orelse):
176  # Create jumps : ir.IRDst = lbl_if if cond else lbl_end
177  cond = statement.test
178  real_body += self._create_labels()
179 
180  lbl_end = ast.Name(id='lbl_end', ctx=ast.Load())
181  lbl_if = ast.Name(id='lbl_if', ctx=ast.Load())
182  dst = ast.Call(func=ast.Name(id='ExprCond',
183  ctx=ast.Load()),
184  args=[cond,
185  lbl_if,
186  lbl_end],
187  keywords=[],
188  starargs=None,
189  kwargs=None)
190 
191  if (isinstance(cond, ast.UnaryOp) and
192  isinstance(cond.op, ast.Not)):
193  ## if not cond -> switch exprCond
194  dst.args[1:] = dst.args[1:][::-1]
195  dst.args[0] = cond.operand
196 
197  IRDst = ast.Attribute(value=ast.Name(id='ir',
198  ctx=ast.Load()),
199  attr='IRDst', ctx=ast.Load())
200  blocks[-1][-1].append(ast.Call(func=ast.Name(id='ExprAff',
201  ctx=ast.Load()),
202  args=[IRDst, dst],
203  keywords=[],
204  starargs=None,
205  kwargs=None))
206 
207  # Create the new blocks
208  sub_blocks, sub_body = self._parse_body(statement.body,
209  argument_names)
210  if len(sub_blocks) > 1:
211  raise RuntimeError("Imbricated if unimplemented")
212 
213  ## Close the last block
214  jmp_end = ast.Call(func=ast.Name(id='ExprAff',
215  ctx=ast.Load()),
216  args=[IRDst, lbl_end],
217  keywords=[],
218  starargs=None,
219  kwargs=None)
220  sub_blocks[-1][-1].append(jmp_end)
221  sub_blocks[-1][-1] = ast.List(elts=sub_blocks[-1][-1],
222  ctx=ast.Load())
223  sub_blocks[-1] = ast.List(elts=sub_blocks[-1],
224  ctx=ast.Load())
225 
226  ## Replace the block with a call to 'irbloc'
227  lbl_if_name = ast.Attribute(value=ast.Name(id='lbl_if',
228  ctx=ast.Load()),
229  attr='name', ctx=ast.Load())
230 
231  sub_blocks[-1] = ast.Call(func=ast.Name(id='irbloc',
232  ctx=ast.Load()),
233  args=[lbl_if_name,
234  sub_blocks[-1]],
235  keywords=[],
236  starargs=None,
237  kwargs=None)
238  blocks += sub_blocks
239  real_body += sub_body
240 
241  # Prepare a new block for following statement
242  blocks.append([[]])
243 
244  else:
245  # TODO: real var, +=, /=, -=, <<=, >>=, if/else, ...
246  raise RuntimeError("Unimplemented %s" % statement)
247 
248  return blocks, real_body

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

def miasm2.core.sembuilder.SemBuilder.functions (   self)
Return a dictionnary name -> func of parsed functions

Definition at line 119 of file sembuilder.py.

120  def functions(self):
121  """Return a dictionnary name -> func of parsed functions"""
122  return self._functions.copy()
def miasm2.core.sembuilder.SemBuilder.parse (   self,
  func 
)
Function decorator, returning a correct method from a pseudo-Python
one

Definition at line 249 of file sembuilder.py.

250  def parse(self, func):
251  """Function decorator, returning a correct method from a pseudo-Python
252  one"""
253 
254  # Get the function AST
255  parsed = ast.parse(inspect.getsource(func))
256  fc_ast = parsed.body[0]
257  argument_names = [name.id for name in fc_ast.args.args]
258 
259  # Translate (blocks[0][0] is the current instr)
260  blocks, body = self._parse_body(fc_ast.body, argument_names)
261 
262  # Build the new function
263  fc_ast.args.args[0:0] = [ast.Name(id='ir', ctx=ast.Param()),
264  ast.Name(id='instr', ctx=ast.Param())]
265  cur_instr = blocks[0][0]
266  if len(blocks[-1][0]) == 0:
267  ## Last block can be empty
268  blocks.pop()
269  other_blocks = blocks[1:]
270  body.append(ast.Return(value=ast.Tuple(elts=[ast.List(elts=cur_instr,
271  ctx=ast.Load()),
272  ast.List(elts=other_blocks,
273  ctx=ast.Load())],
274  ctx=ast.Load())))
275 
276  ret = ast.Module([ast.FunctionDef(name=fc_ast.name,
277  args=fc_ast.args,
278  body=body,
279  decorator_list=[])])
280 
281  # To display the generated function, use codegen.to_source
282  # codegen: https://github.com/andreif/codegen
283 
284  # Compile according to the context
285  fixed = ast.fix_missing_locations(ret)
286  codeobj = compile(fixed, '<string>', 'exec')
287  ctx = self._ctx.copy()
288  eval(codeobj, ctx)
289 
290  # Get the function back
291  self._functions[fc_ast.name] = ctx[fc_ast.name]
292  return ctx[fc_ast.name]

+ Here is the call graph for this function:

Member Data Documentation

miasm2.core.sembuilder.SemBuilder._ctx
private

Definition at line 111 of file sembuilder.py.

miasm2.core.sembuilder.SemBuilder._functions
private

Definition at line 113 of file sembuilder.py.

miasm2.core.sembuilder.SemBuilder.transformer

Definition at line 110 of file sembuilder.py.


The documentation for this class was generated from the following file: