diff options
| author | serpilliere <fabrice.desclaux@cea.fr> | 2015-10-28 22:22:01 +0100 |
|---|---|---|
| committer | Fabrice Desclaux <fabrice.desclaux@cea.fr> | 2015-10-29 21:40:20 +0100 |
| commit | 06fee2b133cd4e2d734d9e164de8028c26c636a8 (patch) | |
| tree | 27edb6e718b5d4a0df0b00e48fb36fd30874be32 | |
| parent | f849393c93fbf0289f4242bc6bc04b062487c461 (diff) | |
| download | miasm-06fee2b133cd4e2d734d9e164de8028c26c636a8.tar.gz miasm-06fee2b133cd4e2d734d9e164de8028c26c636a8.zip | |
Core/parse_asm: clean algo; support delayslot
| -rw-r--r-- | miasm2/core/parse_asm.py | 145 |
1 files changed, 87 insertions, 58 deletions
diff --git a/miasm2/core/parse_asm.py b/miasm2/core/parse_asm.py index 178d0002..2f409172 100644 --- a/miasm2/core/parse_asm.py +++ b/miasm2/core/parse_asm.py @@ -5,6 +5,7 @@ import re import miasm2.expression.expression as m2_expr import miasm2.core.asmbloc as asmbloc from miasm2.core.cpu import gen_base_expr, parse_ast +from miasm2.core.cpu import instruction declarator = {'byte': 8, 'word': 16, @@ -28,7 +29,13 @@ LABEL_RE = re.compile(r'\s*(\S+)\s*:') FORGET_LABEL_RE = re.compile(r'\s*\.LF[BE]\d\s*:') -class DirectiveAlign(object): +class Directive(object): + + """Stand for Directive""" + + pass + +class DirectiveAlign(Directive): """Stand for alignment representation""" @@ -39,6 +46,20 @@ class DirectiveAlign(object): return "Alignment %s" % self.alignment +class DirectiveSplit(Directive): + + """Stand for alignment representation""" + + pass + + +class DirectiveDontSplit(Directive): + + """Stand for alignment representation""" + + pass + + def guess_next_new_label(symbol_pool): """Generate a new label @symbol_pool: the asm_symbol_pool instance""" @@ -77,10 +98,10 @@ def replace_orphan_labels(instr, symbol_pool): instr.args[i] = instr.args[i].replace_expr(replace_id) - STATE_NO_BLOC = 0 STATE_IN_BLOC = 1 + def parse_txt(mnemo, attrib, txt, symbol_pool=None): """Parse an assembly listing. Returns a couple (blocks, symbol_pool), where blocks is a list of asm_bloc and symbol_pool the associated asm_symbol_pool @@ -167,12 +188,10 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None): # TODO continue if directive == 'split': # custom command - raw_data = asmbloc.asm_raw() - raw_data.split = True - lines.append(raw_data) + lines.append(DirectiveSplit()) continue if directive == 'dontsplit': # custom command - lines.append(asmbloc.asm_raw()) + lines.append(DirectiveDontSplit()) continue if directive == "align": align_value = int(line[match_re.end():]) @@ -210,85 +229,95 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None): asmbloc.log_asmbloc.info("___pre asm oki___") # make blocks - block_num = 0 cur_block = None state = STATE_NO_BLOC i = 0 blocks = [] block_to_nlink = None block_may_link = False + delayslot = 0 while i < len(lines): + if delayslot: + if delayslot == 0: + state = STATE_NO_BLOC + else: + delayslot -= 1 + line = lines[i] # no current block if state == STATE_NO_BLOC: - if not isinstance(lines[i], asmbloc.asm_label): + if isinstance(line, DirectiveDontSplit): + block_to_nlink = cur_block + i += 1 + continue + elif isinstance(line, DirectiveSplit): + block_to_nlink = None + i += 1 + continue + elif not isinstance(line, asmbloc.asm_label): + # First line must be a label. If it's not the case, generate + # it. label = guess_next_new_label(symbol_pool) - lines[i:i] = [label] + cur_block = asmbloc.asm_bloc(label, alignment=mnemo.alignment) else: - line = lines[i] cur_block = asmbloc.asm_bloc(line, alignment=mnemo.alignment) - cur_block.block_num = block_num - block_num += 1 - blocks.append(cur_block) - state = STATE_IN_BLOC i += 1 - if block_to_nlink: - block_to_nlink.addto( - asmbloc.asm_constraint(cur_block.label, - C_NEXT)) - block_to_nlink = None + # Generate the current bloc + blocks.append(cur_block) + state = STATE_IN_BLOC + if block_to_nlink: + block_to_nlink.addto( + asmbloc.asm_constraint(cur_block.label, + C_NEXT)) + block_to_nlink = None + continue # in block elif state == STATE_IN_BLOC: - if isinstance(lines[i], asmbloc.asm_raw): - if hasattr(lines[i], 'split'): - state = STATE_NO_BLOC - block_may_link = False - i += 1 - else: - state = STATE_IN_BLOC - block_may_link = True - cur_block.addline(lines[i]) - i += 1 - elif isinstance(lines[i], DirectiveAlign): - cur_block.alignment = lines[i].alignment - i += 1 - # asmbloc.asm_label - elif isinstance(lines[i], asmbloc.asm_label): - if block_may_link: + if isinstance(line, DirectiveSplit): + state = STATE_NO_BLOC + block_to_nlink = None + elif isinstance(line, DirectiveDontSplit): + state = STATE_NO_BLOC + block_to_nlink = cur_block + elif isinstance(line, DirectiveAlign): + cur_block.alignment = line.alignment + elif isinstance(line, asmbloc.asm_raw): + cur_block.addline(line) + block_to_nlink = cur_block + elif isinstance(line, asmbloc.asm_label): + if block_to_nlink: cur_block.addto( - asmbloc.asm_constraint(lines[i], C_NEXT)) - block_may_link = False + asmbloc.asm_constraint(line, C_NEXT)) + block_to_nlink = None state = STATE_NO_BLOC + continue # instruction - else: - cur_block.addline(lines[i]) - if lines[i].dstflow(): - for dst in lines[i].getdstflow(symbol_pool): + elif isinstance(line, instruction): + cur_block.addline(line) + block_to_nlink = cur_block + if not line.breakflow(): + i += 1 + continue + if delayslot: + raise RuntimeError("Cannot have breakflow in delayslot") + if line.dstflow(): + for dst in line.getdstflow(symbol_pool): if not isinstance(dst, m2_expr.ExprId): continue if dst in mnemo.regs.all_regs_ids: continue cur_block.addto(asmbloc.asm_constraint(dst, C_TO)) - # TODO XXX redo this really - - if not lines[i].breakflow() and i + 1 < len(lines): - if not isinstance(lines[i + 1], asmbloc.asm_label): - label = guess_next_new_label(symbol_pool) - lines[i + 1:i + 1] = [label] - else: - state = STATE_NO_BLOC - - if lines[i].splitflow(): - block_to_nlink = cur_block - if not lines[i].breakflow() or lines[i].splitflow(): - block_may_link = True - else: - block_may_link = False + if not line.splitflow(): + block_to_nlink = None - i += 1 + delayslot = line.delayslot + if delayslot == 0: + state = STATE_NO_BLOC + else: + raise RuntimeError("unknown class %s" % line.__class__) + i += 1 for block in blocks: asmbloc.log_asmbloc.info(block) - return blocks, symbol_pool |