From d8f472a31fd9abcd7c582dc6d3b2c8bf9d929faa Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Mon, 13 Feb 2017 19:06:53 +1030 Subject: [PATCH] Add label processing to disassembler --- disasm.py | 91 +++++++++++++++++++++++++++++++++- disasm_hints/annotations.txt | 6 +++ disasm_hints/jmpcall.txt | 95 ++++++++++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 disasm_hints/annotations.txt create mode 100644 disasm_hints/jmpcall.txt diff --git a/disasm.py b/disasm.py index b6457cb..86084e5 100755 --- a/disasm.py +++ b/disasm.py @@ -21,11 +21,61 @@ import argparse parser = argparse.ArgumentParser() parser.add_argument('file', help='.bin file containing the initial memory dump') +parser.add_argument('--hints', help='File(s) outlining additional jmp/call targets, label names, comments, etc', action='append') args = parser.parse_args() with open(args.file, 'rb') as data: SYN_MEM = memory_from_file(data) +# Find things to label +labels, comments_before, comments_inline = {}, {}, {} +SYN_PTR = 0 +while SYN_PTR < len(SYN_MEM): + word = SYN_MEM[SYN_PTR] + if word in instructions_by_opcode: + instruction, SYN_PTR = Instruction.next_instruction(SYN_MEM, SYN_PTR) + if isinstance(instruction, InstructionJmp) or isinstance(instruction, InstructionJt) or isinstance(instruction, InstructionJf): + if isinstance(instruction, InstructionJmp): + op = instruction.args[0] + else: + op = instruction.args[1] + if isinstance(op, OpLiteral): + loc = op.get(None) + labels['label_{:04x}'.format(loc)] = loc + elif isinstance(instruction, InstructionCall): + if isinstance(instruction.args[0], OpLiteral): + loc = instruction.args[0].get(None) + labels['sub_{:04x}'.format(loc)] = loc + else: + SYN_PTR += 1 +# Read hints +if args.hints: + for hintfile in args.hints: + with open(hintfile, 'r') as data: + while True: + line = data.readline() + if line == '': + break + if line.startswith('jmp '): + loc = int(line.split()[1], 16) + labels['label_{:04x}'.format(loc)] = loc + elif line.startswith('call '): + loc = int(line.split()[1], 16) + labels['sub_{:04x}'.format(loc)] = loc + elif line.startswith('ren '): + old_label = line.split()[1] + new_label = line.split()[2] + labels[new_label] = labels[old_label] + del labels[old_label] + elif line.startswith('cmb '): + loc = int(line.split()[1], 16) + comment = line[line.index(' ', line.index(' ') + 1) + 1:].strip() + if loc not in comments_before: + comments_before[loc] = [] + comments_before[loc].append(comment) + else: + raise Exception('Invalid line in hint file: {}'.format(line)) + def escape_char(char): return char.encode('unicode_escape').decode('utf-8').replace('"', '\\"') @@ -35,6 +85,30 @@ MODE_DAT = False #False, 1 (data), 2 (text) SYN_PTR = 0 while SYN_PTR < len(SYN_MEM): + if SYN_PTR in comments_before: + if MODE_OUT: + print('"') + MODE_OUT = False + if MODE_DAT == 1: + print() + MODE_DAT = False + if MODE_DAT == 2: + print('"') + MODE_DAT = False + for comment in comments_before[SYN_PTR]: + print('; {}'.format(comment)) + if any(v == SYN_PTR for k, v in labels.items()): + if MODE_OUT: + print('"') + MODE_OUT = False + if MODE_DAT == 1: + print() + MODE_DAT = False + if MODE_DAT == 2: + print('"') + MODE_DAT = False + print('${}:'.format(next(k for k, v in labels.items() if v == SYN_PTR))) + word = SYN_MEM[SYN_PTR] if MODE_OUT and word != 19: @@ -72,7 +146,7 @@ while SYN_PTR < len(SYN_MEM): SYN_PTR += 1 else: # Instruction - instruction, SYN_PTR = Instruction.next_instruction(SYN_MEM, SYN_PTR) + instruction, next_SYN_PTR = Instruction.next_instruction(SYN_MEM, SYN_PTR) # Special cases if isinstance(instruction, InstructionOut): if isinstance(instruction.args[0], OpLiteral): @@ -89,5 +163,20 @@ while SYN_PTR < len(SYN_MEM): print('"') MODE_OUT = False print('{:04x}: {}'.format(SYN_PTR, instruction.describe())) + elif isinstance(instruction, InstructionJmp) or isinstance(instruction, InstructionJt) or isinstance(instruction, InstructionJf) or isinstance(instruction, InstructionCall): + if isinstance(instruction, InstructionJmp) or isinstance(instruction, InstructionCall): + op = instruction.args[0] + else: + op = instruction.args[1] + if isinstance(op, OpLiteral): + loc = op.get(None) + if any(v == loc for k, v in labels.items()): + label = next(k for k, v in labels.items() if v == loc) + print('{:04x}: {: <4} ${}'.format(SYN_PTR, instruction.name, label)) + else: + print('{:04x}: {}'.format(SYN_PTR, instruction.describe())) + else: + print('{:04x}: {}'.format(SYN_PTR, instruction.describe())) else: print('{:04x}: {}'.format(SYN_PTR, instruction.describe())) + SYN_PTR = next_SYN_PTR diff --git a/disasm_hints/annotations.txt b/disasm_hints/annotations.txt new file mode 100644 index 0000000..a482af9 --- /dev/null +++ b/disasm_hints/annotations.txt @@ -0,0 +1,6 @@ +jmp 0000 +ren label_0000 start +jmp 0110 +ren label_0110 self_test +cmb 0140 Test jmp +ren label_015b self_test_jmp1 diff --git a/disasm_hints/jmpcall.txt b/disasm_hints/jmpcall.txt new file mode 100644 index 0000000..72d2f23 --- /dev/null +++ b/disasm_hints/jmpcall.txt @@ -0,0 +1,95 @@ +call 0505 +call 0507 +call 05b2 +call 05ee +call 05f8 +call 05fb +call 0607 +call 0623 +call 0634 +call 0645 +call 0653 +call 0670 +call 0683 +call 06bb +call 06e7 +call 0731 +call 07d1 +call 084d +call 0865 +call 086e +call 0882 +call 08c8 +call 08e9 +call 0b94 +call 0cad +call 0d48 +call 0df0 +call 0e48 +call 0e8f +call 0e9e +call 0ec0 +call 0eca +call 0ede +call 0f35 +call 0f98 +call 0fa9 +call 0fcd +call 0fde +call 1000 +call 1011 +call 1022 +call 1033 +call 1044 +call 107a +call 10b7 +call 1135 +call 11a3 +call 11b5 +call 1203 +call 1252 +call 1270 +call 12bf +call 1315 +call 1371 +call 14f0 +call 1501 +call 1512 +call 1523 +call 1534 +call 1545 +call 1659 +call 16b6 +call 16bf +call 16d6 +call 16f4 +call 1705 +call 1721 +call 174c +call 1766 +jmp 015b +jmp 0166 +jmp 01e4 +jmp 02c4 +jmp 02db +jmp 034d +jmp 03e8 +jmp 061e +jmp 06b2 +jmp 06fb +jmp 07e3 +jmp 07ff +jmp 0833 +jmp 08bc +jmp 08cc +jmp 08f8 +jmp 0aae +jmp 0b86 +jmp 0c79 +jmp 0cfe +jmp 0d99 +jmp 0e43 +jmp 112e +jmp 1312 +jmp 1652 +jmp 1747