def dump_mpt(input_file, target, init_data, arguments): """ :param input_file: :type input_file: :param target: :type target: :param init_data: :type init_data: :param arguments: :type arguments: """ input_file_fd = io.open(input_file, 'r') contents = input_file_fd.read() if six.PY2: contents = contents.encode("ascii") elif six.PY3: pass print_info("Parsing input file...") var_defs, req_defs, instr_defs = \ interpret_objdump(contents, target, strict=arguments.get('strict', False), sections=["microprobe.text"]) 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() mpt_config.set_default_code_address(arguments['default_code_address']) mpt_config.set_default_data_address(arguments['default_data_address']) 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"], "c2mpt_function", **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) if "end_branch_to_itself" in arguments: instr = target.branch_to_itself() else: instr = target.nop() instr.set_label("ELF_ABI_EXIT") instr_defs.append(instruction_to_definition(instr)) mpt_config.set_default_code_address(address.displacement) initialized_variables = {} mindisplacement = None for data in init_data.split('\n'): if data.strip() == "": continue if data.startswith("WARNING"): print_warning(data.split(":")[1].strip()) continue name = data.split("=")[0].strip() values = ast.literal_eval(data.split("=")[1].strip()) initialized_variables[name] = values if mindisplacement is None: mindisplacement = values[2] # TODO: this is unsafe. We should compute the real size maxdisplacement = values[2] + (values[1] * 8) else: mindisplacement = min(values[2], mindisplacement) maxdisplacement = max(values[2] + (values[1] * 8), maxdisplacement) if "host_displacement" in arguments: mindisplacement = arguments.get("host_displacement", mindisplacement) for name, values in initialized_variables.items(): values[2] = values[2] - mindisplacement + \ arguments['default_data_address'] if 'fix_displacement' in arguments: for name, values in initialized_variables.items(): if "*" in values[0] and isinstance(values[4], list): new_values = [] for value in values[4]: if value <= maxdisplacement and value >= mindisplacement: value = value - mindisplacement + \ arguments['default_data_address'] new_values.append(value) values[4] = new_values elif "*" in values[0] and isinstance(values[4], int): if (values[4] <= maxdisplacement and values[4] >= mindisplacement): values[4] = values[4] - mindisplacement + \ arguments['default_data_address'] elif values[0] == "uint8_t" and isinstance(values[4], list): if len(values[4]) > 8: new_values = "".join(["%02x" % elem for elem in values[4]]) # Enable this for testing switched endianness # new_values = [new_values[idx:idx + 2] # for idx in range(0, len(new_values), 2)] # new_values = new_values[::-1] # new_values = "".join(new_values) new_values = _fix_displacement(new_values, mindisplacement, maxdisplacement, arguments) values[4] = [ int(new_values[idx:idx + 2], 16) for idx in range(0, len(new_values), 2) ] for name, values in initialized_variables.items(): mpt_config.register_variable_definition( MicroprobeTestVariableDefinition(name, *values)) print_info("Init values for variable '%s' parsed" % name) for var in var_defs + req_defs: if var.name in list(initialized_variables.keys()): continue if var.name != arguments["stack_name"]: print_warning("Variable '%s' not registered in the C file " "using the macros provided!" % var.name) 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 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 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() except KeyboardInterrupt: print_info("No input data provided. Exiting...") exit(1) print_info("Parsing input file...") skip = True data_mode = False reg_comment = re.compile("^ [0-9][0-9][0-9][0-9][0-9][0-9]: ") reg_label = re.compile(":.*EQU \\*") reg_data = re.compile(" +DC +X'") reg_entry = re.compile(" +DS +") instruction_definitions = [] data_definitions = [] clabel = None hlabel = None paddress = None for line in contents.split("\n"): if " PROC " in line: skip = False if skip: continue if line.startswith("1PP "): continue if line.replace(" ", "") == "": continue if " CONSTANT AREA " in line: data_mode = True continue if "***" in line: continue if data_mode is True and "|" not in line: break if line.startswith("0"): line = line.replace("0", " ", 1) sline = [elem for elem in line.split("|")[0].split(" ") if elem != ""] if data_mode: if line.startswith("0 0"): line = line.replace("0 0", " 0", 1) address = int(sline[0], 16) if len(data_definitions) > 0 and \ (address == data_definitions[-1][0] + len(data_definitions[-1][1]) // 2): data_definitions[-1][1] += "".join(sline[2:]) else: data_definitions.append( [address, "".join(sline[2:]), "constant_area"]) continue if reg_comment.search(line): continue if reg_label.search(line): clabel = hlabel + "_" + sline[2].replace(":", "") continue if sline[2] == "PROC": hlabel = sline[3] continue if sline[2] == "RET": continue if reg_entry.search(line): continue if reg_data.search(line): address = int(sline[0], 16) if len(data_definitions) > 0 and \ (address == data_definitions[-1][0] + len(data_definitions[-1][1]) // 2): data_definitions[-1][1] += "".join(sline[1:3]) data_definitions[-1][2] += "".join(sline[4:]) else: data_definitions.append( [address, "".join(sline[1:3]), " ".join(sline[4:])]) continue idx = 1 value = "" while len(sline[idx]) == 4: value += sline[idx] idx += 1 address = int(sline[0], 16) if address - (len(value) // 2) == paddress: address = None comment = " ".join(sline[idx + 1:]) asm = "0x%s" % value asm_def = MicroprobeAsmInstructionDefinition(asm, clabel, address, None, comment) instruction_definitions.append(asm_def) clabel = None paddress = int(sline[0], 16) instr_defs = interpret_asm(instruction_definitions, target, [], show_progress=True) var_defs = [] for idx, data in enumerate(data_definitions): address = data[0] var_name = "data_%010d" % idx len_init_value = len(data[1]) // 2 init_value = [ int(data[1][2 * idx:2 * (idx + 1)], 16) for idx in range(0, len_init_value) ] var_defs.append( MicroprobeTestVariableDefinition(var_name, "char", len_init_value, address, None, init_value)) 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])) 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) for var in var_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'])