version = int(arch.split("_")[1]) with open(sys.argv[1]) as f: for line in f: pos = [] count += 1 if count == limit: break line_split = line.split() # Construct instruction structure origin = Inst(line_split) # Find the 64-bit encodings base = int(origin.enc(), 16) origin_operand_types = check_operand_types(origin) if len(origin.operands()) and origin_operand_types.find('X') == -1: pp = [[] for i in range(len(origin_operand_types))] logging.info(origin.op() + " " + origin.modifier()) logging.info("0b{:064b}".format(base) + ": " + origin.operands()) for i in range(0, 64): mask = 2**i newcode = base ^ mask # Disassemble the new code dump_file = dump("0x{:016x}".format(newcode), arch) if dump_file and dump_file.find( "?") == -1 and dump_file.find("error") == -1: line = dump_file.split("\n") if version < 40: line_inst = line[1].split() else: line_inst = line[5].split() # [0]: header info, [1] instruction part
# Construct instruction structure origin = Inst(line_split) # Find the 64-bit encodings base = int(origin.enc(), 16) # Bit by bit xor, observe whether opcode changes and guess what this bit represent for i in range(0, 64): mask = 2**i newcode = base ^ mask # Disassemble the new code dump_file = dump("0x{:016x}".format(newcode), arch) # Compare the disassemble to check which field changes: opcode, operand or modifer if dump_file and dump_file.find("?") == -1 and dump_file.find( "error") == -1: line = dump_file.split("\n") if version < 40: line_inst = line[1].split() else: line_inst = line[5].split() # [0]: header info, [1] instruction part line_inst.pop(0) # Parse the new generated disassembly inst = Inst(line_inst, raw=version > 40) if inst.modifier() != origin.modifier() and inst.op( ) == origin.op(): if i not in pos: pos.append(i) # Enumerate all modifiers if len(pos) > 0: logging.info("%s modifier bits %s: ", origin.op(), pos) enumerator.enumerate(base, pos, arch)