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
# 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 opcode is changed, then this bit represent opcode, we find it! # LDG and TEX are the same instructions in fact # RED and ATOM are the same instruction if inst.op() != origin.op() and not i in pos and not \ (inst.op() == "LDG" and origin.op() == "TEX") and not \ (inst.op() == "TEX" and origin.op() =="LDG") and not \ (inst.op() == "RED" and origin.op() == "ATOM") and not \ (inst.op() == "ATOM" and origin.op() == "RED"): logging.info("Opcode changes: %s => %s when bit [%d] is flipped from [%d]", \ origin.op(), inst.op(), i, (base >> i) & 0x1) bits = bits | (((base >> i) & 0x1) << i) pos.append(i) if len(pos) > 0: logging.info( "0b{:064b}".format(bits) + ": %s opcode bits %s: ", origin.op(), pos)
from sets import Set from inst import Inst import subprocess import sys if __name__ == "__main__": opset = Set([]) with open(sys.argv[1]) as f: for line in f: field = line.split() inst = Inst(field, False) if not inst.op() in opset: opset.add(inst.op()) sys.stdout.write(line)
# 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)