def _main(arguments): """ Main program. Called after the arguments from the CLI interface have been processed. """ print_info("Arguments processed!") print_info("Importing target definition " "'power_v206-power7-ppc64_linux_gcc'...") target = import_definition("power_v206-power7-ppc64_linux_gcc") # Get the arguments functional_units = arguments["functional_unit"] prefix = arguments["output_prefix"] output_path = arguments["output_path"] size = arguments["size"] latency = arguments["average_latency"] distance = arguments["dependency_distance"] if functional_units is None: functional_units = ["ALL"] _generate_benchmark(target, "%s/%s_" % (output_path, prefix), (functional_units, size, latency, distance))
def _main(arguments): """ Program main, after processing the command line arguments :param arguments: Dictionary with command line arguments and values :type arguments: :class:`dict` """ print_info("Arguments processed!") print_info("Importing target definition...") target = import_definition(arguments['target']) if "input_coblst_file" in arguments: print_info("Input file provided") file_fd = open(arguments["input_coblst_file"], 'rb') if struct.unpack("cc", file_fd.read(2)) == ('\x1f', '\x8b'): print_info("Compressed GZIP file detected") file_fd.close() file_fd = gzip.open(arguments["input_coblst_file"]) else: file_fd.close() file_fd = open(arguments["input_coblst_file"]) else: print_info("No input file provided, reading from standard input... ") file_fd = sys.stdin dump_mpt(file_fd, target, arguments)
def _exit(value): if len(_RM_FILES) > 0: print_info("Cleaning temporary files") for rmfile in [fname for fname in _RM_FILES if os.path.isfile(fname)]: os.unlink(rmfile) exit(value)
def main(): """Main function. """ # call the generate method for each model in the memory model list if PARALLEL: print_info("Start parallel execution...") pool = mp.Pool(processes=mp.cpu_count()) pool.map(generate, MEMORY_MODELS, 1) else: print_info("Start sequential execution...") list(map(generate, MEMORY_MODELS)) exit(0)
def _shift_and_fix_registers(registers, offset, addresses, min_address): """Shift register contents.""" sregisters = [] for register in registers: register = register.copy() if not register.name.startswith("GPR"): # Do not shift not GPR registers sregisters.append(register) continue # if GPR value is a negative one, do not shift it value = twocs_to_int(register.value, 64) if value < 0: sregisters.append(register) continue if not ((addresses[0] <= register.value < addresses[1]) and register.value > min_address): sregisters.append(register) continue distance = min((abs(register.value - addr) for addr in addresses[2])) if distance > _FIX_ADDRESS_TOLERANCE: sregisters.append(register) continue print_info( "Shift '%s' from '0x%016X' to '0x%016X'" % (register.name, register.value, register.value + offset), ) register.value = register.value + offset fmt_str = "{0:064b}" value_coded = fmt_str.format(register.value) if len(value_coded) > 64: print_warning( "Overflow during shifting. Cropping of" " register '%s'" % register.name ) register.value = int(value_coded[-64:], 2) sregisters.append(register) return sregisters
def main(): """ Program main """ args = sys.argv[1:] cmdline = microprobe.utils.cmdline.CLI("MicroprobeTest (mpt) to C tool", mpt_options=True, default_config_file="mp_mpt2c.cfg", force_required=['target']) groupname = "MPT to C arguments" cmdline.add_group(groupname, "Command arguments related to MPT to C tool") cmdline.add_option("c-output-file", "O", None, "C output file name", group=groupname, opt_type=new_file_ext(".c"), required=True) groupname = "Fixing options" cmdline.add_group(groupname, "Command arguments related to fixing options") cmdline.add_flag("fix-indirect-branches", None, "Fix branches without known target", groupname) cmdline.add_flag( "fix-branch-next", None, "Force target of branches to be the next " "sequential instruction", groupname) cmdline.add_flag( "fix-memory-references", None, "Ensure that registers used by instructions accessing " "storage are initialized to valid locations", groupname) cmdline.add_flag( "fix-memory-registers", None, "Fix non-storage instructions touching registers used for" " storage address computations (implies " "--fix-memory-referenes flag)", groupname) cmdline.add_flag("endless", None, "Wrap the code generated within an endless loop", groupname) print_info("Processing input arguments...") cmdline.main(args, _main)
def _main(arguments): """ Program main, after processing the command line arguments :param arguments: Dictionary with command line arguments and values :type arguments: :class:`dict` """ print_info("Arguments processed!") print_info("Importing target definition...") target = import_definition(arguments['target']) if arguments['od_bin'] is None: print_error("Unable to find a 'od' utility. Edit your $PATH or use" " the --od-bin parameter") exit(-1) if 'safe' not in arguments: arguments['safe'] = False dump_bin(target, arguments)
def _main(arguments): """ Program main, after processing the command line arguments :param arguments: Dictionary with command line arguments and values :type arguments: :class:`dict` """ if "dump_c2mpt_template" in arguments: dump_c2mpt_template(arguments) _exit(0) if "input_c_file" not in arguments: print_error("argument -i/--input-c-file is required") _exit(-1) print_info("Arguments processed!") print_info("Importing target definition...") target = import_definition(arguments['target']) c2mpt(target, arguments)
def dump_c2mpt_template(arguments): """ :param arguments: :type arguments: """ print_info("Creating a c2mpt C file template...") template_file = findfiles(MICROPROBE_RC['template_paths'], "c2mpt_template.c$")[0] if not os.path.isfile(template_file): print_error("Unable to find base template file: %s" % template_file) _exit(-1) output_file = arguments['output_mpt_file'].rstrip(".mpt") + ".c" print_info("Output file name: %s" % output_file) if os.path.isfile(output_file): print_error("Output file '%s' already exists" % output_file) _exit(-1) try: shutil.copy(template_file, output_file) except IOError: print_error("Something wron when copying '%s' to '%s'\nError: %s " % (template_file, output_file, IOError)) _exit(-1) print_info("Done! You can start editing %s " % output_file)
def _main(arguments): """Program main, after processing the command line arguments. :param arguments: Dictionary with command line arguments and values :type arguments: :class:`dict` """ print_info("Arguments processed!") print_info("Importing target definition...") if 'raw_bin' in arguments: arguments['safe_bin'] = True if 'safe_bin' in arguments: microprobe.MICROPROBE_RC['safe_bin'] = True if 'fix_start_address' not in arguments: arguments['fix_start_address'] = None if "no_wrap_test" in arguments and "wrap_endless" in arguments: print_error( "--no-wrap-test specified and --wrap-endless specified. " "Incompatible options." ) target = import_definition(arguments.pop('target')) test_definition = arguments['mpt_definition'] output_file = arguments['elf_output_file'] print_info("Start generating '%s'" % output_file) generate( test_definition, output_file, target, **arguments )
def dump_bin(target, arguments): """ :param target: :type target: :param arguments: :type arguments: """ print_info("Parsing input file...") cmd = "od -Ax -tx1 -v '%s'" % arguments['input_bin_file'] text_string = run_cmd_output(cmd) bintext = [] for line in text_string.split('\n'): if line == "": continue bintext.append("".join(line.split(' ')[1:])) instrs = interpret_bin("".join(bintext), target, safe=arguments['safe']) for instr in instrs: print(instruction_from_definition(instr).assembly())
def _main(arguments): """ Program main, after processing the command line arguments :param arguments: Dictionary with command line arguments and values :type arguments: :class:`dict` """ print_info("Arguments processed!") print_info("Importing target definition...") target = import_definition(arguments.pop('target')) test_definition = arguments.pop('mpt_definition') outputfile = arguments.pop('c_output_file') print_info("Start generating '%s'" % outputfile) generate(test_definition, outputfile, target, **arguments) print_info("'%s' generated!" % outputfile)
def __call__(self, building_block, target): """ :param building_block: :param dummy_target: """ if len(self._sequence) > MICROPROBE_RC['parallel_threshold']: if MICROPROBE_RC['verbose']: print_info("Enabling parallel processing") return self._parallel(building_block, target) sequence = iter(self._sequence) for bbl in building_block.cfg.bbls: for instr in bbl.instrs: definition = next(sequence) instruction_set_def_properties(instr, definition, building_block=building_block, target=target) return []
def main(): """ Program main """ args = sys.argv[1:] cmdline = CLI("Microprobe Target definition query tool", default_config_file="mp_target.cfg", force_required=['target']) groupname = "Instruction" cmdline.add_group(groupname, "Command arguments related to instruction information") cmdline.add_option( "instructions", "ins", None, "Comma separated list of instructions to obtain information", group=groupname, opt_type=str, required=False) print_info("Processing input arguments...") cmdline.main(args, _main)
def main(): """ Program main """ args = sys.argv[1:] cmdline = CLI("Microprobe Binary to Assembly tool", default_config_file="mp_bin2asm.cfg", force_required=['target']) groupname = "Binary to Assembly arguments" cmdline.add_group(groupname, "Command arguments related to Binary to Assembly tool") cmdline.add_option("input-bin-file", "i", None, "Binary file to process", group=groupname, opt_type=existing_file, required=True) cmdline.add_option("od-bin", "ob", which("od"), "'od' dump utility. Default: %s" % which("od"), group=groupname, opt_type=existing_file) cmdline.add_flag("safe", "S", "Do not fail on unknown decoded binaries", group=groupname) print_info("Processing input arguments...") cmdline.main(args, _main)
def print_info(self): """ """ from microprobe.utils.cmdline import print_info print_info(self._offset_bits) print_info(self._set_bits) print_info(self._tag_bits) bit_range = [0, self._address_size - 1] offset_range = [ self._address_size - 1 - self.offset_bits, self._address_size - 1 ] ccrange = [ self._address_size - 1 - self.offset_bits - self._set_bits, self._address_size - 1 - self.offset_bits - 1 ] print_info((bit_range, offset_range, ccrange))
def _main(arguments): """ Program main, after processing the command line arguments :param arguments: Dictionary with command line arguments and values :type arguments: :class:`dict` """ print_info("Arguments processed!") print_info("Importing target definition...") target = import_definition(arguments['target']) if "input_objdump_file" in arguments: print_info("Input file provided") file_fd = open_generic_fd(arguments["input_objdump_file"], 'r') else: print_info("No input file provided, reading from standard input... ") file_fd = sys.stdin dump_mpt(file_fd, target, arguments)
def _main(arguments): """Program main, after processing the command line arguments. :param arguments: Dictionary with command line arguments and values :type arguments: :class:`dict` """ print_info("Arguments processed!") print_info("Importing target definition...") if 'safe-bin' in arguments: microprobe.MICROPROBE_RC['safe_bin'] = True target = import_definition(arguments.pop('target')) test_definition = arguments['mpt_definition'] output_file = arguments['bin_output_file'] print_info("Start generating '%s'" % output_file) generate( test_definition, output_file, target, **arguments ) print_info("'%s' generated!" % output_file)
def c2mpt_objdump(input_file, arguments): """ :param input_file: :type input_file: :param arguments: :type arguments: """ print_info("Compiling program for target") cprog = arguments["target_c_compiler"] cflags = " -std=c99" cflags += " ".join( [" -I \"" + elem + "\"" for elem in MICROPROBE_RC['template_paths']]) cflags += " \"%s\"" % findfiles(MICROPROBE_RC['template_paths'], "c2mpt.c$")[0] cflags += " -Wl,--section-start,microprobe.text=" cflags += hex(arguments["default_code_address"]) cflags += " -Wl,--section-start,microprobe.data=" cflags += hex(arguments["default_data_address"]) cflags += " " + arguments["target_c_compiler_flags"] suffix = ".target.bin" if "save_temps" in arguments: compile_file = input_file.rstrip(".c") + suffix else: compile_file = _temp_file(suffix=suffix) _RM_FILES.append(compile_file) cmd = "\"%s\" %s \"%s\" -o \"%s\"" % (cprog, cflags, input_file, compile_file) print_info("Executing compilation command") run_cmd(cmd) objdumpprog = arguments["target_objdump"] objdumpflags = " -D -z -j microprobe.data -j microprobe.text" suffix = ".target.dump" if "save_temps" in arguments: objdump_file = input_file.rstrip(".c") + suffix else: objdump_file = _temp_file(suffix=suffix) _RM_FILES.append(objdump_file) cmd = "\"%s\" %s \"%s\"" % (objdumpprog, objdumpflags, compile_file) run_cmd_output_redirect(cmd, objdump_file) print_info("Executing objdump command") return objdump_file
def c2mpt_local_run(input_file, arguments): """ :param input_file: :type input_file: :param arguments: :type arguments: """ print_info("Compiling program for host") cprog = arguments["host_c_compiler"] cflags = " -std=c99" cflags += " -DMPT_BASE_ADDRESS=%d" % arguments.get("host_displacement", 0) cflags += " ".join( [" -I \"" + elem + "\"" for elem in MICROPROBE_RC['template_paths']]) cflags += " \"%s\"" % findfiles(MICROPROBE_RC['template_paths'], "c2mpt.c$")[0] cflags += " -Wl,--section-start,microprobe.text=" cflags += hex(arguments["default_code_address"]) cflags += " -Wl,--section-start,microprobe.data=" cflags += hex(arguments["default_data_address"]) cflags += " " + arguments["host_c_compiler_flags"] suffix = ".host.bin" if "save_temps" in arguments: compile_file = input_file.rstrip(".c") + suffix else: compile_file = _temp_file(suffix=suffix) _RM_FILES.append(compile_file) cmd = "\"%s\" %s \"%s\" -o \"%s\"" % (cprog, cflags, input_file, compile_file) print_info("Executing compilation command") run_cmd(cmd) print_info("Executing the compiled program") vardefinitions = run_cmd_output("%s" % compile_file) return vardefinitions
def _main(arguments): """ Program main, after processing the command line arguments :param arguments: Dictionary with command line arguments and values :type arguments: :class:`dict` """ print_info("Arguments processed!") print_info("Importing target definition...") target = import_definition(arguments['target']) if 'instructions' not in arguments: print_info("Dumping target %s" % target.name) print_target_info(target, None) else: arguments['instructions'] = parse_instruction_list( target, arguments['instructions']) for instruction in arguments['instructions']: print_instruction_info(instruction, None)
def dump_mpt(input_file_fd, target, arguments): """ :param input_file_fd: :type input_file_fd: :param target: :type target: :param arguments: :type arguments: """ try: contents = input_file_fd.read() if six.PY3 and not isinstance(contents, str): contents = contents.decode() except KeyboardInterrupt: print_info("No input data provided. Exiting...") exit(1) print_info("Parsing input file...") print_info("Sections to parse: %s" % arguments['sections']) var_defs, req_defs, instr_defs = \ interpret_objdump(contents, target, strict=arguments.get('strict', False), sections=arguments['sections'], start_address=arguments['from_address'], end_address=arguments['to_address']) print_info("Input file parsed") print_info( "%d instructions processed from the input file" % len(instr_defs) ) if var_defs != []: print_info( "Variables referenced and detected in the dump: %s" % ','.join([var.name for var in var_defs]) ) if req_defs != []: print_warning( "Variables referenced and *NOT* detected in the dump: %s" % ','.join([var.name for var in req_defs]) ) print_warning( "You might need to edit the generated MPT to fix the" " declaration of such variables" ) print_info("Generating the MPT contents...") mpt_config = mpt_configuration_factory() if 'default_code_address' in arguments: mpt_config.set_default_code_address(arguments['default_code_address']) else: mpt_config.set_default_code_address(instr_defs[0].address.displacement) if 'default_data_address' in arguments: mpt_config.set_default_data_address(arguments['default_data_address']) else: mpt_config.set_default_data_address(0) if arguments.get('elf_abi', False): kwargs = {} if "stack_name" in arguments: kwargs["stack_name"] = arguments["stack_name"] if "stack_address" in arguments: kwargs["stack_address"] = Address( base_address="code", displacement=arguments["stack_address"] ) variables, instructions = target.elf_abi( arguments["stack_size"], arguments.get( "start_symbol", None ), **kwargs ) for variable in variables: req_defs.append(variable_to_test_definition(variable)) address = instr_defs[0].address for instr in reversed(instructions): instr_defs = [instruction_to_definition(instr)] + instr_defs address -= instr.architecture_type.format.length if address.displacement < 0: print_error( "Default code address is below zero after" " adding the initialization code." ) print_error( "Check/modify the objdump provided or do not use" " the elf_abi flag." ) exit(-1) mpt_config.set_default_code_address(address.displacement) instr = None if "end_branch_to_itself" in arguments: instr = target.branch_to_itself() elif arguments.get('elf_abi', False): instr = target.nop() if instr is not None: instr.set_label("ELF_ABI_EXIT") instr_defs.append(instruction_to_definition(instr)) for var in var_defs + req_defs: mpt_config.register_variable_definition(var) mpt_config.register_instruction_definitions(instr_defs) print_info("Dumping MPT to '%s'" % arguments['output_mpt_file']) mpt_parser = mpt_parser_factory() mpt_parser.dump_mpt_config(mpt_config, arguments['output_mpt_file'])
def main(): """ Program main """ args = sys.argv[1:] cmdline = CLI( "Microprobe Objdump to MPT tool", default_config_file="mp_objdump2mpt.cfg", force_required=['target'] ) groupname = "Objdump to MPT arguments" cmdline.add_group( groupname, "Command arguments related to Objdump to MPT tool" ) cmdline.add_option( "input-objdump-file", "i", None, "Objdump file to process, if not provided, the input is read from" " standard input", group=groupname, opt_type=existing_file, required=False ) cmdline.add_option( "output-mpt-file", "O", None, "Output file name", group=groupname, opt_type=new_file_ext(".mpt"), required=True ) cmdline.add_flag( "strict", "S", "Be strict when parsing objdump input, if not set, silently skip " "unparsed elements", group=groupname ) cmdline.add_option( "sections", "s", ['.text'], "Space separated CODE section names to interpret. " "(default: '.text' section)", group=groupname, nargs='+', required=False ) cmdline.add_option( "from-address", "f", 0x0, "If set, start interpreting from this address", group=groupname, opt_type=int_type(0, float('+inf')), required=False ) cmdline.add_option( "to-address", "t", float('+inf'), "If set, end interpreting at this address", group=groupname, opt_type=int_type(0, float('+inf')), required=False ) cmdline.add_option( "default-code-address", "X", None, "Default code address", group=groupname, opt_type=int_type(0, float('+inf')), required=False ) cmdline.add_option( "default-data-address", "D", None, "Default data address", group=groupname, opt_type=int_type(0, float('+inf')), required=False ) cmdline.add_flag( "elf-abi", None, "Ensure ELF Application Binary Interface (e.g. define stack, stack" " pointer, etc.)", group=groupname ) cmdline.add_option( "stack-size", None, 4096, "Stack size in bytes (Default: 4096)", group=groupname, opt_type=int_type(0, float('+inf')), required=False ) cmdline.add_option( "stack-name", None, None, "Stack name (Default: microprobe_stack)", group=groupname, opt_type=str, required=False ) cmdline.add_option( "stack-address", None, None, "Stack address (Default: allocated in the data area)", group=groupname, opt_type=int_type(0, float('+inf')), required=False ) cmdline.add_option( "start-symbol", None, None, "Symbol to call after initializing the stack. If not specified, " "no call is performed", group=groupname, opt_type=str, required=False ) cmdline.add_flag( "end-branch-to-itself", None, "A branch to itself instruction will be added at the end of the test", group=groupname ) print_info("Processing input arguments...") cmdline.main(args, _main)
def main(): """ Program main """ args = sys.argv[1:] cmdline = microprobe.utils.cmdline.CLI( "MicroprobeTest (mpt) to TRACE tool", mpt_options=True, default_config_file="mp_mpt2trace.cfg", force_required=['target'] ) groupname = "MPT to trace arguments" cmdline.add_group( groupname, "Command arguments related to MPT to trace tool") cmdline.add_option( "trace-output-file", "O", None, "C output file name", group=groupname, opt_type=new_file_ext([".qt", ".qt.gz", ".qt.bz2"]), required=True ) groupname = "Trace generation options" cmdline.add_group(groupname, "Command arguments related to trace generation options") cmdline.add_option( "default-memory-access-pattern", None, None, "Memory access pattern for memory references that are not modeled by" "Microprobe or not modeled using 'MP' decorator in MPT file. " "Format: comma separated list of addresses or address ranges. If a " "file path is provided, the file is readed to gather the list of " "addresses. The format of the file should be one address or range " "per line. Address range format is : <start>-<end>-<strid>. E.g. " "0x100-0x200-0x010 will generate 0x100,0x110,0x120...0x1F0,0x200 " "pattern.", group=groupname, opt_type=file_with(csv_with_ranges(0, 0xFFFFFFFFFFFFFFFF)), ) cmdline.add_option( "default-branch-pattern", None, None, "Branch pattern for branches that are not modeled by" "Microprobe or not modeled using 'BP' decorator in MPT file. " "Format: string with T or N, for taken and not taken branches, " " respectively. If a file path is provided, the file is readed to " "gather the branch pattern. The format of the file should be one " "string providing the branch pattern (T and N characters).", group=groupname, opt_type=file_with(string_with_chars('TN')), ) cmdline.add_option( "default-branch-indirect-target-pattern", None, None, "Branch target pattern for branches that are not modeled by" "Microprobe or not modeled using 'BT' decorator in MPT file. " "Format: comma separated list of target addresses. If a file " "path is provided, the file is readed to gather the list of addresses." " The format of the file should be one address per line.", group=groupname, opt_type=file_with(csv_with_integer), ) cmdline.add_option( "max-trace-size", None, _DEFAULT_MAX_INS, "Maximum trace size in intructions. Default: %d" % _DEFAULT_MAX_INS, group=groupname, opt_type=int_type(0, 999999999999), ) cmdline.add_flag( "show-trace", None, "Show trace while being generated", group=groupname, ) cmdline.add_flag( "safe-bin", None, "Ignore unrecognized binary codifications (do not" "fail). Useful when MPTs are generated by dumping directly code " "pages, which contain padding zeros and other non-code stuff)", groupname ) print_info("Processing input arguments...") cmdline.main(args, _main)
def generate(test_definition, output_file, target, **kwargs): """ Microbenchmark generation policy. :param test_definition: Test definition object :type test_definition: :class:`MicroprobeTestDefinition` :param output_file: Output file name :type output_file: :class:`str` :param target: Target definition object :type target: :class:`Target` """ end_address_orig = None overhead = 0 if len(test_definition.dat_mappings) > 0: # # Assuming MPT generated from MAMBO full system # dat = target.get_dat(dat_map=test_definition.dat_mappings) dat.control['DAT'] = True for instr in test_definition.code: instr.address = dat.translate(instr.address, rev=True) # Address order might have changed after mapping test_definition.set_instruction_definitions( sorted(test_definition.code, key=lambda x: x.address) ) # remove not translated addresses (needed?) # variables = [var for var in test_definition.variables # if var.address != dat.translate(var.address, rev=True)] # test_definition.set_variables_definition(variables) for var in test_definition.variables: var.address = dat.translate(var.address, rev=True) # Address order might have changed after mapping test_definition.set_variables_definition( sorted(test_definition.variables, key=lambda x: x.address) ) if test_definition.default_code_address != 0: test_definition.default_code_address = dat.translate( test_definition.default_code_address, rev=True ) if test_definition.default_data_address != 0: test_definition.default_data_address = dat.translate( test_definition.default_data_address, rev=True ) for access in test_definition.roi_memory_access_trace: access.address = dat.translate( access.address, rev=True ) if 'raw_bin' in kwargs: print_info("Interpreting RAW dump...") sequence = [] raw_dict = {} current_address = 0 # Assume state file provides the initial code address displ = test_definition.default_code_address test_definition.set_default_code_address(0) for entry in test_definition.code: if (not entry.assembly.upper().startswith("0X") and not entry.assembly.upper().startswith("0B")): raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "assembly (%s)" % entry.assembly ) if entry.label is not None: raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "labels (%s)" % entry.label ) if entry.decorators not in ['', ' ', None, []]: raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "decorators (%s)" % entry.decorators ) if entry.comments not in ['', ' ', None, []]: raise MicroprobeMPTFormatError( "This is not a RAW dump as it contains " "comments (%s)" % entry.comments ) if entry.address is not None: current_address = entry.address + displ if current_address not in raw_dict: raw_dict[current_address] = "" # Assume that raw dump use a 4 bytes hex dump if len(entry.assembly) != 10: raise MicroprobeMPTFormatError( "This is not a RAW 4-byte dump as it contains " "lines with other formats (%s)" % entry.assembly ) raw_dict[current_address] += entry.assembly[2:] if len(raw_dict) > 1: address_ant = sorted(raw_dict.keys())[0] len_ant = len(raw_dict[address_ant])//2 # Assume that raw dump use a 4 bytes hex dump assert len_ant % 4 == 0 for address in sorted(raw_dict.keys())[1:]: if address_ant + len_ant == address: raw_dict[address_ant] += raw_dict[address] len_ant = len(raw_dict[address_ant])//2 raw_dict.pop(address) else: len_ant = len(raw_dict[address])//2 address_ant = address # Assume that raw dump use a 4 bytes hex dump assert len_ant % 4 == 0 sequence = [] for address in sorted(raw_dict.keys()): # Endianess will be big endian, because we are concatenating # full words resulting in the higher bits being encoded first code = interpret_bin( raw_dict[address], target, safe=True, little_endian=False, word_length=4 ) for instr in code: instr.address = address instr = instruction_from_definition(instr) address = address + instr.architecture_type.format.length instr = instruction_to_asm_definition(instr) sequence.append(instr) test_definition.set_instruction_definitions(sequence) reset_steps = [] if 'no_wrap_test' not in kwargs: if test_definition.default_code_address != 0: print_error("Default code address should be zero") exit(-1) print_info("Wrapping function...") start_symbol = "START_TEST" init_address = test_definition.default_code_address for register in test_definition.registers: if register.name == "PC": init_address = register.value if register.name == "PSW_ADDR": init_address = register.value displacements = [] for elem in test_definition.code: if elem.address is not None: if len(displacements) == 0: displacements.append( (elem.address, 4*1024, elem.address - init_address) ) else: displacements.append( (elem.address, elem.address - displacements[-1][0], elem.address - init_address) ) # Get ranges with enough space to put init code # Assuming 4K space is enough displacements = [ displ for displ in displacements if displ[1] >= 4*1024 and displ[2] <= 0 ] if len(displacements) == 0: print_error( "Unable to find space for the initialization code. " "Check the mpt initial code address or state of PC " "for correctness." ) exit(-1) displ_fixed = False if kwargs['fix_start_address']: displacement = kwargs['fix_start_address'] print_info("Start point set to 0x%X" % displacement) displ_fixed = True elif 'fix_long_jump' in kwargs: displacement = sorted(displacements, key=lambda x: x[0])[0][0] if displacement > 2**32: displacement = 0x1000000 print_info("Start point set to 0x%X" % displacement) displ_fixed = True else: displacement = sorted(displacements, key=lambda x: x[2])[-1][0] start_symbol = None init_found = False for instr in test_definition.code: if instr.address == init_address: if instr.label is None: instr.label = "START_TEST" start_symbol = instr.label init_found = True break if not init_found: print_error( "Initial instruction address (%s) not found" % hex(init_address) ) exit(-1) if start_symbol is None: if test_definition.code[0].label is None: test_definition.code[0].label = "START_TEST" start_symbol = test_definition.code[0].label if displacement is None: displacement = 0 instructions = [] reset_steps = [] if 'wrap_endless' in kwargs and 'reset' in kwargs: target.scratch_var.set_address( Address( base_address=target.scratch_var.name ) ) new_ins, overhead, reset_steps = _compute_reset_code( target, test_definition, kwargs, ) instructions += new_ins if 'fix_long_jump' in kwargs: instructions += target.function_call( init_address, long_jump=True ) else: instructions += target.function_call( ("%s" % start_symbol).replace("+0x-", "-0x"), ) if 'wrap_endless' not in kwargs: instructions += [target.nop()] else: instructions += _compute_reset_jump(target, instructions) instructions_definitions = [] for instruction in instructions: instruction.set_label(None) if not displ_fixed: displacement = (displacement - instruction.architecture_type.format.length) current_instruction = MicroprobeAsmInstructionDefinition( instruction.assembly(), None, None, None, instruction.comments, ) instructions_definitions.append(current_instruction) instruction = target.nop() instruction.set_label(None) if not displ_fixed: displacement = (displacement - instruction.architecture_type.format.length) # To avoid overlaps if not displ_fixed: align = 0x100 displacement = ((displacement // align) + 0) * align instructions_definitions[0].address = displacement assert instructions_definitions[0].address is not None # instr = MicroprobeAsmInstructionDefinition( # instruction.assembly(), "ELF_ABI_EXIT", None, None, None) # end_address_orig = \ # (test_definition.default_code_address + displacement_end - # instruction.architecture_type.format.length) instructions_definitions[0].label = "mpt2elf_endless" test_definition.register_instruction_definitions( instructions_definitions, prepend=True, ) assert test_definition.code[0].address is not None if not displ_fixed: test_definition.set_default_code_address( test_definition.default_code_address + displacement, ) for elem in test_definition.code: if elem.address is not None: elem.address = elem.address - displacement else: test_definition.set_default_code_address( displacement ) for elem in test_definition.code: if elem.address is not None: elem.address = elem.address - displacement variables = test_definition.variables variables = [var for var in test_definition.variables if var.address is None or var.address >= 0x00100000] test_definition.set_variables_definition(variables) print_info("Interpreting asm ...") sequence_orig = interpret_asm( test_definition.code, target, [var.name for var in variables] + [target.scratch_var.name], show_progress=True, ) if len(sequence_orig) < 1: raise MicroprobeMPTFormatError( "No instructions found in the 'instructions' entry of the MPT" " file. Check the input file.", ) raw = test_definition.raw raw['FILE_FOOTER'] = "# mp_mpt2elf: Wrapping overhead: %03.2f %%" \ % overhead # end_address = end_address_orig ckwargs = { # 'end_address': end_address, # 'reset': False, # 'endless': 'endless' in kwargs } wrapper_name = "AsmLd" if test_definition.default_data_address is not None: ckwargs['init_data_address'] = \ test_definition.default_data_address if test_definition.default_code_address is not None: ckwargs['init_code_address'] = \ test_definition.default_code_address try: code_wrapper = microprobe.code.get_wrapper(wrapper_name) except MicroprobeValueError as exc: raise MicroprobeException( "Wrapper '%s' not available. Check if you have the wrappers" " of the target installed or set up an appropriate " "MICROPROBEWRAPPERS environment variable. Original error " "was: %s" % (wrapper_name, str(exc)), ) wrapper = code_wrapper(**ckwargs) print_info("Setup synthesizer ...") synthesizer = microprobe.code.Synthesizer( target, wrapper, no_scratch=False, extra_raw=raw, ) variables = test_definition.variables registers = test_definition.registers sequence = sequence_orig if len(registers) >= 0: cr_reg = [ register for register in registers if register.name == "CR" ] registers = [ register for register in registers if register.name != "CR" ] if cr_reg: value = cr_reg[0].value for idx in range(0, 8): cr = MicroprobeTestRegisterDefinition( "CR%d" % idx, (value >> (28 - (idx * 4))) & 0xF, ) registers.append(cr) synthesizer.add_pass( microprobe.passes.initialization.InitializeRegistersPass( registers, skip_unknown=True, warn_unknown=True, skip_control=True, force_reserved=True ), ) synthesizer.add_pass( microprobe.passes.structure.SimpleBuildingBlockPass( len(sequence), ), ) synthesizer.add_pass( microprobe.passes.variable.DeclareVariablesPass( variables, ), ) synthesizer.add_pass( microprobe.passes.instruction.ReproduceSequencePass(sequence), ) if target.name.startswith("power"): fix_branches = [instr.name for instr in target.instructions.values() if instr.branch_conditional] if 'raw_bin' in kwargs: # We do not know what is code and what is data, so we safely # disable the asm generation and keep the values for orig in [21, 17, 19]: synthesizer.add_pass( microprobe.passes.instruction.DisableAsmByOpcodePass( fix_branches, 0, ifval=orig ) ) else: # We know what is code and what is data, so we can safely # fix the branch instructions for new, orig in [(20, 21), (16, 17), (18, 19)]: synthesizer.add_pass( SetInstructionOperandsByOpcodePass( fix_branches, 0, new, force=True, ifval=orig ) ) if kwargs.get("fix_memory_registers", False): kwargs["fix_memory_references"] = True if kwargs.get("fix_memory_references", False): print_info("Fix memory references: On") synthesizer.add_pass( microprobe.passes.memory.FixMemoryReferencesPass( reset_registers=kwargs.get("fix_memory_registers", False), ), ) synthesizer.add_pass( microprobe.passes.register.FixRegistersPass( forbid_writes=['GPR3'], ), ) if kwargs.get("fix_memory_registers", False): print_info("Fix memory registers: On") synthesizer.add_pass( microprobe.passes.register.NoHazardsAllocationPass(), ) if kwargs.get("fix_branch_next", False): print_info("Force branch to next: On") synthesizer.add_pass( microprobe.passes.address.UpdateInstructionAddressesPass( force="fix_flatten_code" in kwargs, noinit=True ) ) synthesizer.add_pass( microprobe.passes.branch.BranchNextPass(force=True), ) if kwargs.get("fix_indirect_branches", False): print_info("Fix indirect branches: On") synthesizer.add_pass( microprobe.passes.address.UpdateInstructionAddressesPass( noinit=True ), ) synthesizer.add_pass( microprobe.passes.branch.FixIndirectBranchPass(), ) if displ_fixed: synthesizer.add_pass( microprobe.passes.address.SetInitAddressPass(displacement) ) synthesizer.add_pass( microprobe.passes.address.UpdateInstructionAddressesPass( noinit=True, init_from_first=not displ_fixed, ), ) synthesizer.add_pass( microprobe.passes.variable.UpdateVariableAddressesPass( ), ) synthesizer.add_pass( microprobe.passes.symbol.ResolveSymbolicReferencesPass( onlyraw=True ), ) print_info("Start synthesizer ...") bench = synthesizer.synthesize() # Save the microbenchmark synthesizer.save(output_file, bench=bench) print_info("'%s' generated!" % output_file) _compile(output_file, target, **kwargs) return
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 _compile(filename, target, **kwargs): if "compiler" not in kwargs: print_info("Compiler not provided") print_info("To compiler the code, first extract the custom") print_info("ld script embedded in the assembly as comments to do") print_info("so execute:") print_info("grep 'MICROPROBE LD' %s | cut -d '@' -f 2" % filename) print_info("then compile using gcc and providing the ld script") print_info("using the -T option.") return print_info("Compiling %s ..." % filename) outputname = ".".join(filename.split(".")[:-1]+["elf"]) ldscriptname = ".".join(filename.split(".")[:-1]+["ldscript"]) fdout = open(ldscriptname, "w") fdin = open(filename, "r") for line in fdin.readlines(): if "MICROPROBE LD" in line: line = line.split("@")[1] fdout.write(line) fdout.close() fdin.close() try: baseldscriptname = findfiles( MICROPROBE_RC['template_paths'], "%s.ldscript" % target.name )[0] except IndexError: print_error("Unable to find template ld script: %s.ldscript" % target.name) exit(-1) cprog = kwargs["compiler"] cflags = " -o %s" % outputname cflags += " -T %s" % ldscriptname cflags += " -T %s " % baseldscriptname cflags += kwargs["compiler_flags"] # We only support BFD linker cflags += " -fuse-ld=bfd " cmd = "%s %s %s" % (cprog, cflags, filename) print_info("Executing compilation command") print_info("%s" % cmd) try: run_cmd(cmd) print_info("'%s' generated!" % outputname) except MicroprobeRunCmdError: cflags += " -static" cmd = "%s %s %s" % (cprog, cflags, filename) print_info("Executing compilation command (statically)") print_info("%s" % cmd) try: run_cmd(cmd) print_info("'%s' generated!" % outputname) except MicroprobeRunCmdError: print_info("'%s' not generated due compilation" " issues. Try manual compilation." % outputname)
def main(): """Program main.""" args = sys.argv[1:] cmdline = microprobe.utils.cmdline.CLI( "MicroprobeTest (mpt) to ELF tool", mpt_options=True, default_config_file="mp_mpt2elf.cfg", force_required=['target'], ) group_name = "MPT to ELF arguments" cmdline.add_group( group_name, "Command arguments related to MPT to ELF tool", ) cmdline.add_option( "elf-output-file", "O", None, "ELF output file name", group=group_name, opt_type=new_file_ext(".s"), required=True, ) cmdline.add_option( "compiler", None, None, "Path to the compiler", group=group_name, ) cmdline.add_option( "compiler-flags", None, "", "Compiler flags to use, if compiler is provided", group=group_name, ) group_name = "Fixing options" cmdline.add_group( group_name, "Command arguments related to fixing options", ) cmdline.add_flag( "fix-indirect-branches", None, "Fix branches without known target", group_name, ) cmdline.add_flag( "fix-branch-next", None, "Force target of branches to be the next " "sequential instruction", group_name, ) cmdline.add_flag( "fix-memory-references", None, "Ensure that registers used by instructions accessing " "storage are initialized to valid locations", group_name, ) cmdline.add_flag( "fix-memory-registers", None, "Fix non-storage instructions touching registers used for" " storage address computations (implies " "--fix-memory-references flag)", group_name, ) cmdline.add_flag( "fix-flatten-code", None, "All code is flatten using consecutive addresses", group_name, ) cmdline.add_flag( "safe-bin", None, "Ignore unrecognized binary codifications (do not" "fail). Useful when MPTs are generated by dumping " "directly code " "pages, which contain padding zeros and other " "non-code stuff)", group_name, ) cmdline.add_flag( "raw-bin", None, "Process all instruction entries together. They " "all shoud be binary entries. Implies --safe-bin " "flag. Useful when MPTs are generated by dumping " "directly code " "pages, which contain padding zeros and other " "non-code stuff)", group_name, ) cmdline.add_flag( "fix-long-jump", None, "Sometimes the generated code is unable compile due a long jump " "displacement required to jump to the start insturction.", group_name, ) cmdline.add_option( "fix-start-address", "S", None, "Sometimes the user requires the main start point to be on specific " "address to avoid compilation issues or comply with the execution " "environment requirements. This flag forces the main entry point of " "execution to be at the specified address. It is up to the user to " "define a proper entry point that does not clash with existing code.", group=group_name, opt_type=int_type(0, 2**64) ) group_name = "Wrapping options" cmdline.add_group( group_name, "Command arguments related to wrapping options", ) cmdline.add_flag( "no-wrap-test", None, "By default the code is wrapped like it was " "a function call, use this flag to disable the " "wrapping", group_name, ) cmdline.add_flag( "wrap-endless", None, "Use this flag to wrap the code in an endless " "loop assuming it is a function. " "If needed (--reset option), additional " "instructions are added to reset the " "the initial state between loop iterations. ", group_name, ) cmdline.add_option( "wrap-endless-threshold", None, 1, "Maximum percentage of instructions allowed in the reset code if " "--wrap-endless and --reset is used. I.e. if 10 is set, the tool will " "fail if the reset code required is more than 10%% of the actual " "code of the test case." " Default is 1%%.", group=group_name, opt_type=float_type(0, 1000), required=False, ) cmdline.add_flag( "reset", None, "Use this flag to enable the generation of reset " "code if wrap-endless is enabled.", group_name, ) print_info("Processing input arguments...") cmdline.main(args, _main)
def generate(test_definition, outputfile, target, **kwargs): """ Microbenchmark generation policy :param test_definition: Test definition object :type test_definition: :class:`MicroprobeTestDefinition` :param outputfile: Outputfile name :type outputfile: :class:`str` :param target: Target definition object :type target: :class:`Target` """ variables = test_definition.variables print_info("Interpreting assembly...") sequence = interpret_asm( test_definition.code, target, [var.name for var in variables] ) if len(sequence) < 1: raise MicroprobeMPTFormatError( "No instructions found in the 'instructions' entry of the MPT" " file. Check the input file." ) max_ins = test_definition.instruction_count if kwargs["max_trace_size"] != _DEFAULT_MAX_INS or max_ins is None: max_ins = kwargs["max_trace_size"] # registers = test_definition.registers # raw = test_definition.raw # if test_definition.default_data_address is None: # print_error("Default data address is needed") # exit(-1) # if test_definition.default_code_address is None: # print_error("Default code address is needed") # exit(-1) wrapper_name = "QTrace" print_info("Creating benchmark synthesizer...") try: cwrapper = microprobe.code.get_wrapper(wrapper_name) except MicroprobeValueError as exc: raise MicroprobeException( "Wrapper '%s' not available. Check if you have the wrappers " "of the target installed or set up an appropriate " "MICROPROBEWRAPPERS environment variable. Original error was: %s" % (wrapper_name, str(exc)) ) start_addr = [ reg.value for reg in test_definition.registers if reg.name in ["PC", "IAR"] ] if start_addr: start_addr = start_addr[0] else: start_addr = test_definition.default_code_address if start_addr != test_definition.default_code_address: print_error( "Default code address does not match register state " "PC/IAR value. Check MPT consistency." ) exit(-1) wrapper_kwargs = {} wrapper_kwargs["init_code_address"] = start_addr wrapper_kwargs["init_data_address"] = test_definition.default_data_address wrapper = cwrapper(**wrapper_kwargs) synth = microprobe.code.TraceSynthesizer( target, wrapper, show_trace=kwargs.get( "show_trace", False), maxins=max_ins, start_addr=start_addr, no_scratch=True ) # if len(registers) >= 0: # synth.add_pass( # microprobe.passes.initialization.InitializeRegistersPass( # registers, skip_unknown=True, warn_unknown=True # ) # ) synth.add_pass( microprobe.passes.structure.SimpleBuildingBlockPass(len(sequence)) ) synth.add_pass( microprobe.passes.instruction.ReproduceSequencePass(sequence) ) synth.add_pass( microprobe.passes.address.UpdateInstructionAddressesPass() ) synth.add_pass( microprobe.passes.branch.NormalizeBranchTargetsPass() ) synth.add_pass( microprobe.passes.memory.InitializeMemoryDecorator( default=kwargs.get("default_memory_access_pattern", None) ) ) synth.add_pass( microprobe.passes.branch.InitializeBranchDecorator( default=kwargs.get("default_branch_pattern", None), indirect=kwargs.get("default_branch_indirect_target_pattern", None) ) ) synth.add_pass( microprobe.passes.symbol.ResolveSymbolicReferencesPass() ) print_info("Synthesizing...") bench = synth.synthesize() # Save the microbenchmark synth.save(outputfile, bench=bench) return
def main(): """ Program main """ args = sys.argv[1:] cmdline = CLI( "Microprobe C to MPT tool", compilation_options=True, default_config_file="mp_c2mpt.cfg", force_required=['target'], ) groupname = "C to MPT arguments" cmdline.add_group(groupname, "Command arguments related to C to MPT tool") cmdline.add_option("input-c-file", "i", None, "C file to process", group=groupname, opt_type=existing_file_ext(".c"), required=False) cmdline.add_option("output-mpt-file", "O", None, "Output file name", group=groupname, opt_type=new_file_ext(".mpt"), required=True) cmdline.add_flag( "strict", "S", "Be strict when parsing objdump input, if not set, silently skip " "unparsed elements", group=groupname) cmdline.add_option("default-code-address", "X", 0x10030000, "Default code address (default: 0x10030000)", group=groupname, opt_type=int_type(0, float('+inf')), required=False) cmdline.add_option("default-data-address", "D", 0x10040000, "Default data address (default: 0x10040000)", group=groupname, opt_type=int_type(0, float('+inf')), required=False) cmdline.add_option("stack-size", None, 4096, "Stack size in bytes (Default: 4096)", group=groupname, opt_type=int_type(0, float('+inf')), required=False) cmdline.add_option( "host-displacement", None, None, "Displacement between static objdump code and loaded image on the " "host. Default computed automatically", group=groupname, opt_type=int_type(0, float('+inf')), required=False) cmdline.add_flag( "fix-displacement", None, "If data contains addresses (such as pointers) to code or data " "regions, the tool will try to fix them adding the necessary " "displacement", group=groupname, ) cmdline.add_option("stack-name", None, "microprobe_stack", "Stack name (Default: microprobe_stack)", group=groupname, opt_type=str, required=False) cmdline.add_option("stack-address", None, None, "Stack address (Default: allocated in the data area)", group=groupname, opt_type=int_type(0, float('+inf')), required=False) cmdline.add_flag( "no-data-initialization", None, "Do not run the compiled code locally to get the contents of" " registered variables before executing the *c2mpt_function*. Only " "statically specified variable contents will be dumped in the MPT" " generated", group=groupname) cmdline.add_flag( "save-temps", None, "Store the generated intermediate files permanently; place them in " "the input source file directory and name them based on the source " "file", group=groupname) cmdline.add_flag( "dump-c2mpt-template", None, "Dump a template C file, which can be used afterwards as an input " "file", group=groupname) cmdline.add_flag( "end-branch-to-itself", None, "A branch to itself instruction will be added at the end of the test", group=groupname) print_info("Processing input arguments...") cmdline.main(args, _main)