Пример #1
0
def main():
    global syms, scanned_files
    syms, scanned_files = analyze_source.read_source_and_syms()
    time_start = time.time()
    update_function_scope()
    time_end = time.time()
    debug_print("Time taken: %s" % (time_end - time_start))
Пример #2
0
def read_syms():
    syms = {}

    debug_print("Reading syms...")

    import os
    objdump_path = "./tools/binutils/bin/arm-none-eabi-objdump"
    if 'win' in os.name:
        output = subprocess.check_output(
            [objdump_path + ".exe", "-t", "bn6f.elf"])
    else:
        output = subprocess.check_output([objdump_path, "-t", "bn6f.elf"])

    lines = output.splitlines()[4:]

    for line in lines:
        try:
            sym_tuple = sym_line_regex.findall(line.decode("utf-8"))[0]
        except IndexError:
            break

        sym_list = list(sym_tuple)
        sym_list[0] = int(sym_list[0], 16)
        # symbol name
        syms[sym_tuple[5]] = SymInfo(*sym_list)

    debug_print("Done reading syms!")
    return syms
Пример #3
0
def update_function_scope():
    branch_opcodes = set(
        ("beq", "bne", "bcs", "bcc", "bmi", "bpl", "bvs", "bvc", "bhi", "bls",
         "bge", "blt", "bgt", "ble", "b", "bl"))

    functions = {}

    for sym in syms.values():
        if sym.type == "F":
            functions[sym.name] = sym.filename

    for src_file in scanned_files.values():
        if src_file.filename.startswith("data/dat38"):
            continue
        src_file.line_num = 0
        debug_print(src_file.filename)
        for line in src_file:
            if line.isspace() or line == "":
                continue
            words = parser.for_loop_parse_word_directives(src_file)
            if len(words) == 0:
                # check for opcode
                line = line.strip()
                opcode_parts = line.split(None, 1)
                if len(opcode_parts) > 1 and opcode_parts[0] in branch_opcodes:
                    if opcode_parts[1].endswith("+1"):
                        opcode_parts[1] = opcode_parts[:-2]
                    if opcode_parts[
                            1] in functions and src_file.filename != syms[
                                opcode_parts[1]].filename:
                        change_function_to_thumb_func_start(
                            syms[opcode_parts[1]])
                        del functions[opcode_parts[1]]
            else:
                # test each word to see if it's a function
                # if it is, increment its counter
                for word in words:
                    if word.endswith("+1"):
                        word = word[:-2]
                    if word in functions and src_file.filename != syms[
                            word].filename:
                        change_function_to_thumb_func_start(syms[word])
                        del functions[word]

    # functions that are confirmed local
    for function in functions.keys():
        change_function_to_thumb_local_start(syms[function])

    if os.path.exists("temp/"):
        shutil.rmtree("temp/")
    os.makedirs("temp/")

    for filename, src_file in scanned_files.items():
        os.makedirs("temp/" + os.path.dirname(filename), exist_ok=True)
        with open("temp/" + filename, "w+") as f:
            f.writelines(line + "\n" for line in src_file.commented_lines)
Пример #4
0
def benchmark_list_iterator(scanned_files):
    list_iterator_start_time = time.time()
    for src_file in scanned_files.values():
        src_file.line_num = 0
        output = ""
        for line in src_file._uncommented_lines:
            output += line

    list_iterator_total_time = time.time() - list_iterator_start_time
    debug_print("list_iterator_total_time: %s" % list_iterator_total_time)
Пример #5
0
def benchmark_src_file_iterator(scanned_files):
    src_file_iterator_start_time = time.time()

    for src_file in scanned_files.values():
        src_file.line_num = 0
        output = ""
        for line in src_file:
            output += line

    src_file_iterator_total_time = time.time() - src_file_iterator_start_time
    debug_print("src_file_iterator_total_time: %s" %
                src_file_iterator_total_time)
Пример #6
0
def count_functions(syms, scanned_files):
    branch_opcodes = set(
        ("beq", "bne", "bcs", "bcc", "bmi", "bpl", "bvs", "bvc", "bhi", "bls",
         "bge", "blt", "bgt", "ble", "b", "bl"))
    function_counts = {}

    for sym in syms.values():
        if sym.type == "F":
            function_counts[sym.name] = 0

    for src_file in scanned_files.values():
        if src_file.filename.startswith("data/dat38"):
            continue
        src_file.line_num = 0
        debug_print(src_file.filename)
        for line in src_file:
            if line.isspace() or line == "":
                continue
            words = parser.for_loop_parse_word_directives(src_file)
            if len(words) == 0:
                # check for opcode
                line = line.strip()
                opcode_parts = line.split(None, 1)
                if len(opcode_parts) > 1 and opcode_parts[0] in branch_opcodes:
                    if opcode_parts[1].endswith("+1"):
                        opcode_parts[1] = opcode_parts[:-2]
                    if opcode_parts[1] in function_counts:
                        function_counts[opcode_parts[1]] += 1
            else:
                # test each word to see if it's a function
                # if it is, increment its counter
                for word in words:
                    if word.endswith("+1"):
                        old_word = word
                        word = word[:-2]
                    if word in function_counts:
                        function_counts[word] += 1

    sorted_function_counts = sorted(function_counts.items(),
                                    key=lambda kv: kv[1],
                                    reverse=True)
    output = ""
    for function_pair in sorted_function_counts:
        function_sym = syms[function_pair[0]]
        output += "{:07x} <{}:{}> {}: {}\n".format(function_sym.value,
                                                   function_sym.filename,
                                                   function_sym.line_num + 1,
                                                   function_sym.name,
                                                   function_pair[1])

    with open("function_counts.txt", "w+") as f:
        f.write(output)
Пример #7
0
def recursive_scan_includes(filepath,
                            scanned_files,
                            syms=None,
                            callbacks=None):
    global recursion_depth
    debug_print("recursion depth: %s | file: %s" % (recursion_depth, filepath))
    recursion_depth += 1

    in_block_comment = False

    with open(filepath, "r") as f:
        scanned_files[filepath] = SrcFile(filepath)
        for line_num, line in enumerate(f):
            include_file_list = re.findall(r"\t\.include \"([^\"]+)\"", line)
            if len(include_file_list) > 1:
                raise RuntimeError("More than one group found!")
            elif len(include_file_list) == 1:
                include_given_pathname = include_file_list[0]
                include_real_pathname = include_given_pathname
                if include_given_pathname.endswith(".inc"):
                    if pathlib.Path(include_given_pathname).is_file():
                        pass  # already defined as default
                    elif pathlib.Path("include/" +
                                      include_given_pathname).is_file():
                        include_real_pathname = "include/" + include_given_pathname
                    else:
                        raise RuntimeError(
                            "Path specified by \"%s\" not found!" %
                            include_given_pathname)

                if include_real_pathname not in scanned_files:
                    try:
                        recursive_scan_includes(include_real_pathname,
                                                scanned_files, syms, callbacks)
                    except IOError:
                        raise

            line = line.rstrip("\r\n")

            uncommented_line = ""
            in_line_comment = False
            iter_line = IterStr(line)
            # faster to do this naive check for most cases because "in" is native
            if not in_block_comment and "/*" not in line:
                slash_line_comment_index = line.find("//") * -1
                at_line_comment_index = line.find("@") * -1
                if at_line_comment_index == 1 or slash_line_comment_index == 1:
                    line_comment_index = min(slash_line_comment_index,
                                             at_line_comment_index) * -1
                else:
                    line_comment_index = max(slash_line_comment_index,
                                             at_line_comment_index) * -1

                if line_comment_index == -1:
                    uncommented_line = line
                else:
                    uncommented_line = line[:line_comment_index] + " " * (
                        len(line) - line_comment_index - 1)
            else:
                for char in iter_line:
                    if in_block_comment:
                        uncommented_line += " "
                        if char == "*":
                            try:
                                char = iter_line.next()
                            except StopIteration:
                                break

                            uncommented_line += " "
                            if char == "/":
                                in_block_comment = False
                    elif char == "@":
                        uncommented_line += " " * (len(line) -
                                                   iter_line.index - 1)
                        break
                    elif char == "/":
                        try:
                            char = iter_line.next()
                        except StopIteration:
                            break

                        if char == "/":
                            uncommented_line += "  " + " " * (
                                len(line) - iter_line.index - 1)
                            break
                        elif char == "*":
                            uncommented_line += "  "
                            in_block_comment = True
                    else:
                        uncommented_line += char

            if syms is not None:
                label_name = parser.check_and_parse_colon_label(
                    uncommented_line)
                if label_name is not None:
                    syms[label_name].filename = filepath
                    syms[label_name].line_num = line_num

            if callbacks is not None:
                for callback in callbacks:
                    callback(line, uncommented_line)
            scanned_files[filepath].append_commented_and_uncommented_lines(
                line, uncommented_line)

    recursion_depth -= 1
Пример #8
0
    ap.add_argument("-m", "--make", dest="make", action="store_true")
    ap.add_argument("-p", "--path", dest="input_path")
    args = ap.parse_args()

    if args.input_path is None and os.path.basename(
            os.getcwd()) == "analyze_source":
        os.chdir("../..")
    elif args.input_path is not None:
        os.chdir(args.input_path)

    if args.make:
        syms = make_and_read_syms()
    else:
        syms = read_syms()

    debug_print("Size: %s" % sys.getsizeof(syms))
    sym_dump_output = ""
    cfg_output = ""
    highest_sym_value = 0
    sorted_syms = sorted(syms.items(), key=lambda kv: kv[1].value)
    for sym, sym_info in sorted_syms:
        sym_dump_output += "{}: value=0x{:x}, scope=\"{}\", debug=\"{}\", type=\"{}\", section=\"{}\"\n".format(
            sym, sym_info.value, sym_info.scope, sym_info.debug, sym_info.type,
            sym_info.section)
        if sym_info.type == "F" and sym_info.value >= 0x8000000:
            cfg_output += "{} 0x{:x} {}\n".format("thumb_func", sym_info.value,
                                                  sym)

    with open("bn6f_syms.dump", "w+") as f:
        f.write(sym_dump_output)