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))
示例#2
0
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)
示例#3
0
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)
示例#4
0
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)
示例#5
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
示例#6
0
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)
示例#7
0
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)
示例#8
0
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)
示例#9
0
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)
示例#10
0
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
    )
示例#11
0
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())
示例#12
0
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)
示例#13
0
    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 []
示例#14
0
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)
示例#15
0
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)
示例#16
0
文件: cache.py 项目: IBM/microprobe
    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))
示例#17
0
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)
示例#18
0
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)
示例#19
0
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
示例#20
0
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
示例#21
0
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)
示例#22
0
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'])
示例#23
0
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)
示例#24
0
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)
示例#25
0
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
示例#26
0
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
示例#27
0
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)
示例#28
0
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)
示例#29
0
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
示例#30
0
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)