def __init__( self, code, target, fmt="hex", _data_cache=False, little_endian=None, word_length=None ): """ :param code: :type code: :param target: :type target: """ self._little_endian = target.little_endian if little_endian is not None: self._stream_little_endian = little_endian else: self._stream_little_endian = target.little_endian endianess_missmatch = self._little_endian != self._stream_little_endian self._code = _normalize_code( code, fmt=fmt, endianess_missmatch=endianess_missmatch, word_length=word_length ) self._fmt = fmt self._target = target self._index = 0 self._data_cache = _data_cache self._lenghts = list(sorted(_compute_target_lengths(target), reverse=True)) self._progress = Progress(len(self._code), msg="Bytes parsed:")
def __call__(self, building_block, dummy_target): """ :param building_block: :param dummy_target: """ for instr in (elem for elem in building_block.init if elem.label is not None): self._register_label(instr) for bbl in building_block.cfg.bbls: if MICROPROBE_RC['verbose']: progress = Progress(len(bbl.instrs), "Registering labels:") for instr in (elem for elem in bbl.instrs if elem.label is not None): self._register_label(instr) if MICROPROBE_RC['verbose']: progress() for instr in (elem for elem in building_block.fini if elem.label is not None): self._register_label(instr) for instr in building_block.init: self._translate_label(instr, building_block.context) for bbl in building_block.cfg.bbls: if MICROPROBE_RC['verbose']: progress = Progress(len(bbl.instrs), "Translating labels:") for instr in bbl.instrs: self._translate_label(instr, building_block.context) if MICROPROBE_RC['verbose']: progress() for instr in building_block.fini: self._translate_label(instr, building_block.context) return []
def __init__(self, code, target, fmt="hex", _data_cache=False): """ :param code: :type code: :param target: :type target: """ self._code = _normalize_code(code, fmt=fmt) self._fmt = fmt self._target = target self._index = 0 self._data_cache = _data_cache self._lenghts = list(reversed(sorted(_compute_target_lengths(target)))) self._progress = Progress(len(self._code), msg="Bytes parsed:")
def __init__(self, size, instructions=None): """ :param size: """ if size < 1: raise MicroprobeValueError("I can not create a Bbl with %d size" % size) if instructions is None: instructions = [] self._copy_id = 0 self._incstep = 10000 self._instrs = [None] * max(self._incstep, (size + 1) * 10) self._pointer = 10 self._instdic = {} self._address = None self._displacement = 0 if MICROPROBE_RC["verbose"]: progress = Progress(size, "Initializing BBL:") if not instructions: for idx in range(0, size): # self._check_size() instr = microprobe.code.ins.Instruction() self._instrs[self._pointer] = instr self._instdic[instr] = self._pointer self._pointer += 10 if MICROPROBE_RC["verbose"]: progress() else: for idx in range(0, size): self._check_size() if idx < len(instructions): self._instrs[self._pointer] = instructions[idx] else: self._instrs[self._pointer] = \ microprobe.code.ins.Instruction() self._instdic[self._instrs[self._pointer]] = self._pointer self._pointer += 10 if MICROPROBE_RC["verbose"]: progress()
def _set_props(largs, queue=None, show_progress=False): rlist = [] if show_progress: progress = Progress(len(largs), msg="Setting instruction properties: ") for args in largs: instr, definition, building_block, target, displ = args instruction_set_def_properties(instr, definition, building_block=building_block, target=target, label_displ=displ) if show_progress: progress() rlist.append(instr) if queue is not None: queue.put(rlist) return rlist
def _wrap(self, bench): """Wrap a benchmark. This function wraps a benchmark using the synthesizer wrapper. The wrapping process is the process of converting the internal representation of the benchmark to the actual string that is written to a file, adding the necessary prologue and epilogue bytes of data. :param bench: Benchmark to wrap. :type bench: :class:`~.Benchmark` :return: A string representation of the benchmark :rtype: :class:`~.str` """ self.wrapper.set_benchmark(bench) bench_str = [] bench_str.append(self.wrapper.headers()) instructions = [] instructions_dict = {} instructions_next_dict = {} for instr in bench.init: instructions.append(instr) for bbl in bench.cfg.bbls: for instr in bbl.instrs: instructions.append(instr) for instr in bench.fini: instructions.append(instr) for instr in instructions: instructions_dict[instr.address] = instr if (instr.branch or instr.syscall or instr.trap): instructions_next_dict[instr.address] = \ instr.decorators['NI']['value'] else: instructions_next_dict[instr.address] = \ instr.address + instr.architecture_type.format.length instr = instructions[0] count = 0 cmd.cmdline.print_info( "Maximum trace size: %s instructions " % self._maxins) progress = Progress(self._maxins, msg="Instructions generated:") while True: count = count + 1 if count > self._maxins: cmd.cmdline.print_info( "Max number of instructions (%d) reached. " "Stoping trace generation." % self._maxins) break try: instr_address = instructions_next_dict[instr.address] if not isinstance(instr_address, InstructionAddress): instr_address = next(instr_address) next_instr = instructions_dict[instr_address] except KeyError: cmd.cmdline.print_info( "Jump to an unknown instruction in address " "%s found. Stoping trace generation." % instr_address) break progress() wrap_ins = self.wrapper.wrap_ins(instr, next_instr=next_instr, show=self._show_trace) bench_str.append( wrap_ins ) instr = next_instr bench_str = [elem for elem in bench_str if elem != ""] return bench_str
def _compute_reset_code(target, test_def, args): instructions = interpret_asm( test_def.code, target, [var.name for var in test_def.variables], show_progress=True, ) # TODO: This can be done in parallel or look for speed up the process instructions = [ instruction_from_definition(instr) for instr in instructions ] instruction_dict = {} address = test_def.default_code_address progress = Progress( len(test_def.roi_memory_access_trace), msg="Building instruction dictionary", ) for instr in instructions: progress() if instr.address is not None: if instr.address.base_address == "code": address = test_def.default_code_address + \ instr.address.displacement instr.set_address(address) else: address = address + instr.architecture_type.format.length instr.set_address(address) instruction_dict[instr.address] = instr free_regs = [] written_after_read_regs = [] read_regs = [] level = 0 dynamic_count = 0 progress = Progress( len(test_def.roi_memory_access_trace), msg="Evaluating register usage", ) reset_regs = set() for access in test_def.roi_memory_access_trace: progress() if access.data_type == "D": continue dynamic_count += 1 try: instr = instruction_dict[access.address] uses = instruction_dict[access.address].uses() sets = instruction_dict[access.address].sets() except KeyError: print_error( "Access to from instruction at address " "0x%016X registered but such instruction is not" " present in the definition." % access.address, ) exit(1) # Calls if instr.mnemonic == "BL": level += 1 elif instr.mnemonic == "BCL": level += 1 elif instr.mnemonic == "BCCTRL": if instr.operands()[2].value in [0, 3]: level += 1 # Returns if instr.mnemonic == "BCLR": if (((instr.operands()[0].value & 0b10100) == 20) and (instr.operands()[2].value == 0)): level -= 1 # TODO: this should include Z and RISCV instructions for call # and return, but currently we do not have memory access traces # for such platforms for reg in uses: if reg not in read_regs: read_regs.append(reg) for reg in sets: if reg in free_regs: continue elif reg not in read_regs: free_regs.append(reg) elif reg not in written_after_read_regs: written_after_read_regs.append(reg) reset_regs = set(read_regs).intersection( set(written_after_read_regs), ) reset_regs = sorted(reset_regs) assert len(free_regs) == len(set(free_regs)) assert len(set(free_regs).intersection(set(reset_regs))) == 0 if len(test_def.roi_memory_access_trace) == 0: # We do not have memory access trace, assume calling conventions reset_regs = target.volatile_registers reset_regs = [ reg for reg in reset_regs if reg in target.volatile_registers] if len(reset_regs) == 0 and len(test_def.roi_memory_access_trace) == 0: print_info( "No memory access trace found. Resetting volatile registers." ) reset_regs = target.volatile_registers unused_regs = sorted( (reg for reg in target.registers.values() if reg not in read_regs), ) # # Make sure scratch registers are reset last # for reg in target.scratch_registers: if reg in reset_regs: reset_regs.remove(reg) reset_regs.append(reg) free_regs = unused_regs + free_regs # Know which ones are not used (or written) and which ones are used # Use them as base / temporal registers for addresses # Check addresses conflict_addresses = {} new_ins = [] progress = Progress( len(test_def.roi_memory_access_trace), msg="Evaluating memory usage", ) for access in test_def.roi_memory_access_trace: progress() if access.data_type == "I": continue val = conflict_addresses.get( access.address, [access.length, access.access_type], ) if access.access_type not in val[1]: val[1] += access.access_type val[0] = max(val[0], access.length) conflict_addresses[access.address] = val fix_addresses = [] for address in conflict_addresses: value = conflict_addresses[address] if value[1] == "RW": wvalue = None for var in test_def.variables: if var.var_type.upper() in ["CHAR", "UINT8_T"]: elem_size = 1 else: raise NotImplementedError end_address = var.address + var.num_elements * elem_size if var.address <= address <= end_address: offset = int((address - var.address) / elem_size) svalue = var.init_value[ offset:offset + int(value[0] / elem_size) ] svalue = "".join(["%02X" % tval for tval in svalue]) wvalue = int(svalue, 16) break if wvalue is None: print_error( "Unable to restore original value for address 0x%X" % address, ) exit(1) if value[0] <= 8: fix_addresses.append((address, value[0], wvalue)) else: for selem in range(0, value[0]//8): sfmt = "%%0%dX" % (2*value[0]) nvalue = sfmt % wvalue nvalue = int(nvalue[selem*16:(selem+1)*16], 16) fix_addresses.append( (address + selem * 8, 8, nvalue) ) reset_steps = [] context = Context() context.set_symbolic(True) if len(fix_addresses) > 0: # TODO: This can be optimized. Reduce the number of instructions to # be added by sorting the reset code (shared values or similar # addresses) # TODO: This can be optimized for use vector registers when # needed # print_info("Adding instructions to reset memory state") reset_register = [ reg for reg in free_regs if reg.type.used_for_address_arithmetic and reg.name != "GPR0" ][0] for address, length, value in fix_addresses: address_obj = Address(base_address="data", displacement=address) new_instructions = target.set_register( reset_register, value, context, opt=False, ) for ins in new_instructions: ins.add_comment( "Reset code. Setting %s to 0X%016X" % (reset_register.name, value), ) reset_steps.append([new_instructions[:], reset_register, value]) context.set_register_value(reset_register, value) try: store_ins = target.store_integer( reset_register, address_obj, length * 8, context, ) new_instructions += store_ins reset_steps.append( [store_ins, reset_register, address_obj, length], ) except MicroprobeCodeGenerationError: areg = [ reg for reg in free_regs if reg.type.used_for_address_arithmetic and reg.name != "GPR0" ][1] set_ins = target.set_register( areg, address, context, opt=False, ) new_instructions += set_ins reset_steps.append([set_ins, areg, address_obj]) context.set_register_value(areg, address_obj) store_ins = target.store_integer( reset_register, address_obj, length * 8, context, ) new_instructions += store_ins reset_steps.append( [store_ins, reset_register, address_obj, length], ) for ins in set_ins: ins.add_comment( "Reset code. Setting %s to 0X%016X" % (areg.name, address), ) for ins in store_ins: ins.add_comment( "Reset code. Setting mem content in 0X%016X" % (address), ) new_ins.extend(new_instructions) # Reset contents of used registers for reset_register in reset_regs: try: value = [ reg for reg in test_def.registers if reg.name == reset_register.name ][0].value except IndexError: continue new_instructions = target.set_register( reset_register, value, context, opt=False, ) reset_steps.append([new_instructions, reset_register, value]) context.set_register_value(reset_register, value) for ins in new_instructions: ins.add_comment( "Reset code. Setting %s to 0X%016X" % (reset_register.name, value), ) new_ins.extend(new_instructions) try: overhead = (((len(new_ins) * 1.0) / dynamic_count) * 100) except ZeroDivisionError: print_warning("Unable to compute overhead. Zero dynamic instruction " "count") overhead = 0 print_info( "%03.2f%% overhead added by resetting code" % overhead, ) if overhead > args['wrap_endless_threshold']: print_error( "Instructions added: %d" % len(new_ins), ) print_error( "Total instructions: %d" % dynamic_count, ) print_error( "Reset code above --wrap-endless-threshold. Stopping generation.", ) exit(1) return new_ins, overhead, reset_steps
def interpret_asm(code, target, labels, log=True, show_progress=False, parallel=True, queue=None): """ Return the list of :class:`~.MicroprobeInstructionDefinition` objects that results from interpreting the *code* (list of assembly statements). The *target* object is used to validate the existence of the instruction and operands in the target and the *labels* are needed to validate the correctness of the symbolic labels used in the assembly statements. :param code: Assembly to interpret :type code: :class:`list` of :class:`~.MicroprobeAsmInstructionDefinition` or string/s to interpret :param target: Target definition :type target: :class:`~.Target` object :param labels: Labels available :type labels: :class:`~.list` of :class:`~.str` :return: A list of instructions, operands, labels, etc. resulting from interpreting the assembly :rtype: :class:`~.list` of :class:`~.MicroprobeInstructionDefinition` :raise microprobe.exceptions.MicroprobeAsmError: if something is wrong during the interpretation """ LOG.debug("Start interpret_asm") instructions_and_params = [] LOG.debug("Extract defined labels") def_labels = labels if def_labels is None: def_labels = [] if isinstance(code, str): code = [code] if len(code) > MICROPROBE_RC["parallel_threshold"] and parallel: # Do parallel parsing processes = [] queues = [] chunksize = max(len(code) // MICROPROBE_RC['cpus'], 1) extra_args = {} extra_args['log'] = log extra_args['show_progress'] = show_progress extra_args['parallel'] = False for chunk in [ code[i:i + chunksize] for i in range(0, len(code), chunksize) ]: queue = mp.Queue() extra_args['queue'] = queue proc = mp.Process(target=interpret_asm, args=(chunk, target, def_labels), kwargs=extra_args) processes.append(proc) queues.append(queue) proc.start() extra_args['show_progress'] = False instructions_and_params = [] for queue in queues: instructions_and_params += queue.get() queue.close() queue.join_thread() for process in processes: process.join() process.terminate() return instructions_and_params try: if show_progress: progress = Progress(len(code), msg="Labels parsed:") for instr_def in code: if isinstance(instr_def, six.string_types): instr_def = _str_to_asmdef(instr_def) if instr_def.label in def_labels: raise MicroprobeAsmError("Label '%s' defined twice!" % instr_def.label) if instr_def.label is not None: def_labels.append(instr_def.label.upper()) if show_progress: progress() if show_progress: progress = Progress(len(code), msg="Instructions parsed:") for instr_def in code: if isinstance(instr_def, six.string_types): instr_def = _str_to_asmdef(instr_def) intr_asm = _interpret_instr_def(instr_def, target, def_labels) instructions_and_params.append(intr_asm) LOG.debug("Instruction: '%s' interpreted", instr_def.assembly) if show_progress: progress() except MicroprobeAsmError as exc: if log: LOG.critical("Assembly provided:") LOG.critical("%20s\t%20s\t%25s\t%s", "-" * 20, "-" * 20, "-" * 25, "-" * 20) LOG.critical("%20s\t%20s\t%25s\t%s", "label", "address", "instruction", "decorators") LOG.critical("%20s\t%20s\t%25s\t%s", "-" * 20, "-" * 20, "-" * 25, "-" * 20) for instr in code: if isinstance(instr, six.string_types): instr = _str_to_asmdef(instr) address = "--" if instr.address is not None: address = "0x%016x" % instr.address LOG.critical("%20s\t%20s\t%25s\t%s", instr.label, address, instr.assembly, instr.decorators) LOG.critical("%20s\t%20s\t%25s\t%s", "-" * 20, "-" * 20, "-" * 25, "-" * 20) LOG.critical("If the previous assembly is not correct, " "check the format of the assembly file provided") raise exc LOG.debug("End interpret_asm") if queue is not None: queue.put(instructions_and_params) return instructions_and_params
def _parallel(self, building_block, target): def _iter_zip(list1, list2, extra=None): idx = 0 try: while True: item1 = next(list1) item2 = next(list2) if extra is None: yield (item1, item2, idx) else: yield tuple([item1, item2] + extra + [idx]) idx = idx + 1 except StopIteration: return props = iter(self._sequence) for bbl in building_block.cfg.bbls: instrs = iter(bbl.instrs) instrs_props = list( _iter_zip(instrs, props, extra=[building_block, target])) csize = max(len(bbl.instrs) // MICROPROBE_RC['cpus'], 1) instrs_propsl = (instrs_props[idx:idx + csize] for idx in range(0, len(self._sequence), csize)) if MICROPROBE_RC['verbose']: print_info("Start mapping to %s threads ... " % MICROPROBE_RC['cpus']) extra_args = {} extra_args['show_progress'] = True processes = [] queues = [] for chunk in instrs_propsl: queue = mp.Queue() extra_args['queue'] = queue proc = mp.Process(target=_set_props, args=(chunk, ), kwargs=extra_args) processes.append(proc) queues.append(queue) proc.start() extra_args['show_progress'] = False new_instrs = [] for queue in queues: new_instrs += queue.get() progress = Progress(len(bbl.instrs), msg="Setting instruction properties: ") instrs = iter(bbl.instrs) for instr, new_instr in zip(instrs, new_instrs): bbl.reset_instruction(instr, new_instr) progress() for queue in queues: queue.close() queue.join_thread() for process in processes: process.join() process.terminate() return []
def interpret_objdump( objdump_output, target, strict=False, sections=None, start_address=-1, end_address=float('+inf') ): """ Returns a :class:`~.MicroprobeTestDefinition` object that results from interpreting the objdump output. The *target* object is used to validate the existence of the instruction and operands. :param objdump_output: Assembly to interpret :type objdump_output: Objdump textual output :param target: Target definition :type target: :class:`~.Target` object :param strict: If set, fail if an opcode can not be interpreted. (Default: False) :type strict: :class:`~.bool` :param sections: List of section names to parse :type sections: :class:`~.list` of :class:`~.str` :param start_address: Start address to interpret :type start_address: ::class:`~.int` :param end_address: End address to interpret :type end_address: ::class:`~.int` :return: An object representing the microprobe test :rtype: :class:`~.list` of :class:`~.MicroprobeTestDefinition` :raise microprobe.exceptions.MicroprobeObjdumpError: if something is wrong during the interpretation of the objdump """ if not strict: MICROPROBE_RC['safe_bin'] = True if isinstance(objdump_output, str): objdump_output = objdump_output.replace('\r', '\n') objdump_output = objdump_output.split('\n') filtered_objdump_output = _objdump_cleanup( objdump_output, sections, start_address, end_address ) code_labels = _find_code_labels(filtered_objdump_output) var_labels = _find_var_labels(filtered_objdump_output, code_labels) labels = code_labels + var_labels label_pattern = _generate_label_pattern(labels) binary_format = _binary_reformat(filtered_objdump_output) asm_format = _asm_reformat(filtered_objdump_output) assert len(binary_format) == len(asm_format) instr_defs = [] current_labels = var_labels[:] progress = Progress(len(binary_format), msg="Lines parsed:") for binary, asm in zip(binary_format, asm_format): instr_def = None if not label_pattern.search(asm): try: instr_def = interpret_asm(binary, target, current_labels) except MicroprobeBinaryError: if strict: raise MicroprobeObjdumpError( "Unable to interpret binary '%s' (asm:' %s')" % (binary, asm) ) else: LOG.warning("Skiping binary '%s' (asm:' %s')", binary, asm) instr_def = None else: try: instr_def = interpret_asm( asm, target, current_labels, log=False ) except MicroprobeAsmError: instr_def = interpret_asm(binary, target, current_labels) if instr_def is not None: fixed_instr_def = _fix_instr_definition(instr_def[0], asm, target) instr_defs.append(fixed_instr_def) if fixed_instr_def.label is not None: current_labels.append(fixed_instr_def.label) progress() variable_defs = [] required_defs = [] for var_label in var_labels: var_def = _interpret_variable(var_label, objdump_output) if var_def is not None: variable_defs.append(var_def) else: LOG.warning( "Variable label: '%s' referenced but not found " "in the dump" ) required_defs.append(_default_variable(var_label)) return variable_defs, required_defs, instr_defs
def dump_dma(arguments): """ :param target: :type target: :param arguments: :type arguments: """ ifile = open(arguments['input_objdump_file'], 'r') inputlines = ifile.readlines() ifile.close() progress = Progress(len(inputlines), msg="Lines parsed:") lines_dict = {} caddress = None displace = 0 for idx, line in enumerate(inputlines): idx = idx + 1 progress() line = line.strip() if line == "" or "file format" in line or line.startswith("Disass"): continue tsplit = line.split("\t") if len(tsplit) not in [1, 3, 4]: raise MicroprobeObjdumpError("Unable to parse '%s' at line '%s'" % (line, idx)) if len(tsplit) == 1: space_split = tsplit[0].split(" ") if len(space_split) != 2: raise MicroprobeObjdumpError( "Unable to parse '%s' at line '%s'" % (line, idx)) address, label = space_split if not label.endswith('>:') or label[0] != '<': raise MicroprobeObjdumpError( "Unable to parse '%s' at line '%s'" % (line, idx)) try: new_address = int(address, 16) except ValueError: raise MicroprobeObjdumpError( "Unable to parse '%s' at line '%s'" % (line, idx)) if caddress is None: caddress = new_address elif new_address != (caddress + displace): caddress = new_address displace = 0 continue if len(tsplit) in [3, 4] and caddress is None: raise MicroprobeObjdumpError( "Unable to know the address of '%s' at line '%s'" % (line, idx)) if not tsplit[0].endswith(":"): raise MicroprobeObjdumpError("Unable to parse '%s' at line '%s'" % (line, idx)) if (caddress + displace) < int(tsplit[0][:-1], 16): caddress = int(tsplit[0][:-1], 16) displace = 0 elif (caddress + displace) > int(tsplit[0][:-1], 16): raise MicroprobeObjdumpError( "Conflicting addresses in '%s' at line '%s'" % (line, idx)) value = "".join(tsplit[1].split(' ')).lower() if caddress in lines_dict: lines_dict[caddress] += value displace += len(value) // 2 else: lines_dict[caddress] = value displace = len(value) // 2 used_addresses = RejectingDict() progress = Progress(len(list(lines_dict.keys())), msg="Writing output") with open(arguments['output_dma_file'], 'w') as fdout: for caddress in sorted(lines_dict): value = lines_dict[caddress] progress() if caddress % 8 != 0: contents = value[0:((caddress % 8) * 2)] value = value[((caddress % 8) * 2):] contents = "0" * (16 - len(contents)) + contents caddress = (caddress // 8) * 8 line = "D %016x %s\n" % (caddress, contents) used_addresses[caddress] = line fdout.write(line) caddress += 8 for idx in range(0, len(value), 16): contents = value[idx:idx + 16] contents += "0" * (16 - len(contents)) line = "D %016x %s\n" % (caddress, contents) used_addresses[caddress] = line fdout.write(line) caddress += 8
def dump_objdump(target, arguments): """ :param target: :type target: :param arguments: :type arguments: """ ifile = open(arguments['input_dma_file'], 'r') dataw = arguments['width_bytes'] inputlines = ifile.readlines() ifile.close() progress = Progress(len(inputlines), msg="Lines parsed:") lines_dict = {} for idx, line in enumerate(inputlines): splitline = line.upper().split(" ") if len(splitline) != 3: raise MicroprobeDMAFormatError("Unable to parse line %d: %s" % (idx, line)) if (splitline[0] != "D" or len(splitline[1]) != 16 or len(splitline[1]) != 16): raise MicroprobeDMAFormatError("Unable to parse line %d: %s" % (idx, line)) key = int(splitline[1], base=16) if key in lines_dict: print_warning("Address (%s) in line %d overwrites previous entry" % (splitline[1], idx)) lines_dict[key] = splitline[2][:-1] progress() current_key = None progress = Progress(len(list(lines_dict.keys())), msg="Detecting segments:") for key in sorted(lines_dict): progress() if current_key is None: current_key = key continue current_address = current_key + (len(lines_dict[current_key]) // 2) if current_address == key: lines_dict[current_key] += lines_dict[key] lines_dict.pop(key) else: current_key = key instrs = [] progress = Progress(len(list(lines_dict.keys())), msg="Interpreting segments:") for key in sorted(lines_dict): progress() current_instrs = interpret_bin(lines_dict[key], target, safe=not arguments['strict']) current_instrs[0].address = Address(base_address='code', displacement=key) instrs += current_instrs maxlen = max([ins.format.length for ins in target.instructions.values()] + [dataw]) * 2 maxlen += maxlen // 2 counter = 0 label_dict = RejectingDict() instr_dict = RejectingDict() range_num = 1 progress = Progress(len(instrs), msg="Computing labels:") for instr_def in instrs: progress() if instr_def.address is not None: counter = instr_def.address.displacement if instr_def.instruction_type is None: for idx in range(0, len(instr_def.asm), dataw * 2): label = None if instr_def.address is not None and idx == 0: label = ".range_%x" % range_num label_dict[counter] = label range_num += 1 elif counter in label_dict: label = label_dict[counter] idx2 = min(idx + (dataw * 2), len(instr_def.asm)) masm = instr_def.asm[idx:idx2].lower() binary = " ".join([ str(masm)[i:i + 2] for i in range(0, len(masm), 2) ]).lower() instr_dict[counter] = [binary, "0x" + masm, label, None, None] counter += (idx2 - idx) // 2 continue instr = instruction_from_definition(instr_def, fix_relative=False) asm = instr.assembly().lower() relative = None absolute = None if instr.branch: for memoperand in instr.memory_operands(): if not memoperand.descriptor.is_branch_target: continue for operand in memoperand.operands: if operand.type.address_relative: relative = operand.value if operand.type.address_absolute: absolute = operand.value masm = instr_def.asm[2:] if len(masm) % 2 != 0: masm = "0" + masm binary = " ".join([str(masm)[i:i + 2] for i in range(0, len(masm), 2)]) label = None if instr_def.address is not None: if counter not in label_dict: label = ".range_%x" % range_num label_dict[counter] = label range_num += 1 else: label = label_dict[counter] elif counter in label_dict: label = label_dict[counter] rtarget = None atarget = None if relative is not None or absolute is not None: if relative is not None: assert absolute is None if isinstance(relative, int): target_addr = counter + relative rtarget = relative elif isinstance(relative, Address): target_addr = counter + relative.displacement rtarget = relative.displacement else: raise NotImplementedError if absolute is not None: assert relative is None if isinstance(absolute, int): target_addr = absolute atarget = absolute elif isinstance(absolute, Address): target_addr = absolute.displacement atarget = absolute.displacement else: raise NotImplementedError if target_addr not in label_dict: label_dict[target_addr] = "branch_%x" % target_addr if target_addr in instr_dict: instr_dict[target_addr][2] = label_dict[target_addr] instr_dict[counter] = [binary, asm, label, rtarget, atarget] counter = counter + (len(masm) // 2) print("") print("%s:\tfile format raw %s" % (os.path.basename(arguments['input_dma_file']), target.isa.name)) print("") print("") print("Disassembly of section .code:") print("") str_format = "%8s:\t%-" + str(maxlen) + "s\t%s" for counter in sorted(instr_dict.keys()): binary, asm, label, rtarget, atarget = instr_dict[counter] if label is not None: print("%016x <%s>:" % (counter, label)) cformat = str_format if rtarget is not None: cformat = str_format + "\t <%s>" % (label_dict[counter + rtarget]) elif atarget is not None: cformat = str_format + "\t <%s>" % (label_dict[atarget]) print(cformat % (hex(counter)[2:], binary, asm))