def test_branch_conditional_direct(resources, tmpdir): test_file = os.path.join(resources, 'branch_conditional_direct.pbtxt') cfg = user_callgraph.Callgraph.from_proto(test_file) source_gen = source_generator.SourceGenerator(tmpdir, cfg) source_gen.write_files() output = compile_and_check_function_for_asm( tmpdir, 'function_2', switch_processor(X86_CONDITIONAL_DIRECT, ARM_CONDITIONAL_DIRECT)) assert output, 'Missing indirect branch'
def test_branch_implicit_fallthrough(resources, tmpdir): test_file = os.path.join(resources, 'branch_implicit_fallthrough.pbtxt') cfg = user_callgraph.Callgraph.from_proto(test_file) source_gen = source_generator.SourceGenerator(tmpdir, cfg) source_gen.write_files() output = compile_and_check_function_for_asm( tmpdir, 'function_2', switch_processor(X86_CONDITIONAL_DIRECT, ARM_CONDITIONAL_DIRECT)) assert output, 'Implicit fallthrough branch error'
def test_branch_direct_call(resources, tmpdir): test_file = os.path.join(resources, 'branch_direct_call.pbtxt') cfg = user_callgraph.Callgraph.from_proto(test_file) source_gen = source_generator.SourceGenerator(tmpdir, cfg) source_gen.write_files() output = compile_and_check_function_for_asm( tmpdir, 'function_2', switch_processor(X86_DIRECT_CALL, ARM_DIRECT_CALL)) assert output, 'Missing direct function call'
def test_prefetch_off(resources, tmpdir): test_file = os.path.join(resources, 'prefetch_cb.pbtxt') cfg = user_callgraph.Callgraph.from_proto(test_file) source_gen = source_generator.SourceGenerator(tmpdir, cfg) source_gen.write_files() # Prefetch does not exist on x86, but we still want to ensure code compiles result = compile_and_check_function_for_asm(tmpdir, 'function_0', 'prfm') if platform.machine() == 'aarch64': assert not result
def test_write_onecallchain(resources, tmpdir): test_file = os.path.join(resources, 'onecallchain.pbtxt') expected_dir = os.path.join(resources, 'write_onecallchain') cfg = user_callgraph.Callgraph.from_proto(test_file) source_gen = source_generator.SourceGenerator(tmpdir, cfg) source_gen.write_files(num_files=1) output = dircmp(tmpdir, expected_dir) diff_files = set(output.same_files) ^ set(output.left_list) assert diff_files == set(), f'Different files: {diff_files}'
def test_dfs(resources, tmpdir, num_files): depth = 10 test_file = os.path.join(resources, 'dfs', f'dfs_depth{depth}_cfg.pb') cfg = user_callgraph.Callgraph.from_proto(test_file) source_gen = source_generator.SourceGenerator(tmpdir, cfg) source_gen.write_files(num_files) misc_c_files = ['main.c'] c_files = glob.glob(f'{tmpdir}/*.c') assert len(c_files) == pytest.approx(num_files + len(misc_c_files), 1) for c_file in c_files: with open(c_file, 'r') as f: matches = re.findall(source_gen.get_header_import_string(), f.read()) assert len(matches) == 1
#!/usr/bin/python3 """Generate source files from provided callgraph.""" import argparse from frontend.code_generator import source_generator from frontend.code_generator import user_callgraph if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('callgraph', type=str, help='path to cfg protobuf') parser.add_argument('output_dir', type=str, help='directory to output c/source files to') parser.add_argument('--num-files', default=None, type=int, help='number of c files to write to') args = parser.parse_args() callgraph = user_callgraph.Callgraph.from_proto(args.callgraph) sg = source_generator.SourceGenerator(args.output_dir, callgraph) sg.write_files(args.num_files)