diff --git a/hunktools/hunk.py b/hunktools/dalf.py similarity index 72% rename from hunktools/hunk.py rename to hunktools/dalf.py index c0df831..a14e374 100755 --- a/hunktools/hunk.py +++ b/hunktools/dalf.py @@ -122,7 +122,46 @@ def read_blocks(infile, is_loadfile): block = read_block(infile, is_loadfile) return result -def parse_hunkfile(hunkfile): + +def group_blocks(blocks): + """group the blocks into relocation groups""" + groups = [] + for block in blocks: + if block[0] in {'NAME', 'UNIT'}: + continue + elif block[0] in {'BSS', 'CODE', 'DATA'}: + current_group = [] + + if block[0] == 'END': + groups.append(current_group) + current_group = [] + else: + current_group.append(block) + return groups + +def print_hunks(hunks): + for i, hunk in enumerate(hunks): + block = hunk[0] + if block[0] == 'NAME': + print("%d: '%s' -> '%s'" % (i, block[0], block[1])) + elif block[0] == 'BSS': + print("%d: '%s' -> %d" % (i, block[0], block[1])) + elif block[0] == 'CODE': + print("%d: '%s', size = %d" % (i, block[0], len(block[1]))) + code = block[1] + disassemble(code) + else: + print("%d: '%s'" % (i, block[0])) + + +def print_overview(hunks): + for i, hunk in enumerate(hunks): + print(" %d: %s" % (i, hunk[0][0])) + for block in hunk[1:]: + print(" %s" % block[0]) + print(" END") + +def parse_hunkfile(hunkfile, disassemble): """Top level parsing function""" with open(hunkfile, 'rb') as infile: id = infile.read(4) @@ -130,69 +169,45 @@ def parse_hunkfile(hunkfile): # can be Header or Unit is_loadfile = True if id == HUNK_BLOCK_HEADER: + print("Hunk Header (03f3)") library_names = read_string_list(infile) - print("Libraries: ", library_names) + print("\tLibraries: ", library_names) hunk_table_size = read_int32(infile) - print("size hunk table: %d" % hunk_table_size) first_slot = read_int32(infile) last_slot = read_int32(infile) + print("\t%d hunks (%d-%d)\n" % (hunk_table_size, first_slot, last_slot)) num_hunk_sizes = last_slot - first_slot + 1 + """ print("first slot: %d, last slot: %d, # hunk sizes: %d" % (first_slot, last_slot, num_hunk_sizes)) + """ hunk_sizes = [read_int32(infile) for i in range(num_hunk_sizes)] - print("hunk sizes: ", hunk_sizes) + #print("hunk sizes: ", hunk_sizes) elif id == HUNK_BLOCK_UNIT: strlen = read_int32(infile) * 4 #print("# name: %d" % strlen) unit_name = str(infile.read(strlen)) - print("UNIT '%s'" % unit_name) - print("---------------------------------------------") + print("Hunk unit (03e7)") + print("\tName: %s\n" % unit_name) else: is_loadfile = False raise Exception('Unsupported header type') blocks = read_blocks(infile, is_loadfile) - #print("%d blocks read: " % len(blocks)) - - # group the blocks into relocation groups - groups = [] - for block in blocks: - if block[0] in {'NAME', 'UNIT'}: - continue - elif block[0] in {'BSS', 'CODE', 'DATA'}: - current_group = [] - - if block[0] == 'END': - groups.append(current_group) - current_group = [] - else: - current_group.append(block) - - for i, group in enumerate(groups): - names = ','.join([block[0] for block in group]) - print("Group %d -> %s" % (i, names)) - - block = group[0] - if block[0] == 'NAME': - print("%d: '%s' -> '%s'" % (i, block[0], block[1])) - elif block[0] == 'BSS': - print("%d: '%s' -> %d" % (i, block[0], block[1])) - elif block[0] == 'CODE': - print("%d: '%s', size = %d" % (i, block[0], len(block[1]))) - print("----------------------------\n") - code = block[1] - disassemble(code) - print("\n---------------------------\n") - #elif block[0] == 'RELOC32': - # print("%d: '%s': %s" % (i, block[0], block[1])) - else: - print("%d: '%s'" % (i, block[0])) + hunks = group_blocks(blocks) + if disassemble: + print_hunks(hunks) + else: + print_overview(hunks) if __name__ == '__main__': - description = """hunk - hunk file reader (c) 2014 Wei-ju Wu""" + description = """dalf.py - Dumps Amiga Load Files with Python (c) 2014 Wei-ju Wu""" parser = argparse.ArgumentParser(description=description) parser.add_argument('hunkfile', help="hunk format file") + parser.add_argument('--disassemble', action="store_true", default=False, + help="show disassembly") + args = parser.parse_args() - parse_hunkfile(args.hunkfile) + parse_hunkfile(args.hunkfile, disassemble=args.disassemble) diff --git a/hunktools/disassemble.py b/hunktools/disassemble.py index 6953ffc..797efeb 100644 --- a/hunktools/disassemble.py +++ b/hunktools/disassemble.py @@ -14,7 +14,7 @@ ADDR_MODES_EXT = { OPCODE_CATEGORIES = { '0000': 'bitops_movep_imm', '0001': 'move.b', '0010': 'move.l', '0011': 'move.w', - '0100': 'misc', '0101': 'addq_subq', '1001': 'sub_subx', + '0100': 'misc', '0101': 'addq_subq', '1001': 'sub_subx', '1011': 'cmp_eor', '0110': 'bcc_bsr_bra', '0111': 'moveq', '1101': 'add_addx', '1110': 'shift_rotate' } @@ -182,6 +182,10 @@ def next_word(size, data, data_offset): data[data_offset:data_offset+2] value = struct.unpack('>h', data[data_offset:data_offset+2])[0] added = 2 + elif size == 'B': + data[data_offset:data_offset+2] + value = (struct.unpack('>h', data[data_offset:data_offset+2])[0]) & 0xff + added = 2 else: raise Exception('unsupported size: ', size) return (value, added) @@ -342,11 +346,18 @@ def _disassemble(data, offset): if bits[0:10] == '0000100000': ea, added1 = operand('l', bits[10:13], bits[13:16], data, offset, skip=2) bitnum, added2 = next_word('W', data, offset + 2) - instr = Operation2('btst', added1 + added2 + 2, bitnum & 0xff, ea) + instr = Operation2('btst', added1 + added2 + 2, IntConstant(bitnum & 0xff), ea) + elif bits[0:8] == '00001100': + size = SIZES[int(bits[8:10], 2)] + immdata, added1 = next_word(size.upper(), data, offset + 2) + ea, added2 = operand(size, bits[10:13], bits[13:16], data, offset, skip=added1) + instr = Operation2('cmpi.' + size, added1 + added2 + 2, IntConstant(immdata), ea) else: detail = bits[8:11] print("bits at offset: %d -> %s" % (offset, bits)) raise Exception('TODO: bitops, detail: ' + detail) + elif category == 'cmp_eor': + raise Exception('TODO: cmp_eor') else: print("\nUnknown instruction\nCategory: ", category, " Bits: ", bits) raise Exception('TODO')