def make_soong_benchmark(root: LoadedLibrary, defs: Definitions, out: Path) -> None: lib_names = LibNames(root) bp = open(out / 'Android.bp', 'w') bp.write( f'// AUTO-GENERATED BY {os.path.basename(__file__)} -- do not edit\n') bp.write(f'cc_defaults {{\n') bp.write(f' name: "{g_benchmark_name}_all_libs",\n') bp.write(f' runtime_libs: [\n') for lib in bfs_walk(root): if lib.soname in kBionicSonames: continue if lib is root: continue bp.write(f' "{lib_names.name(lib)}",\n') bp.write(f' ],\n') bp.write(f'}}\n') for lib in bfs_walk(root): if lib.soname in kBionicSonames: continue lib_base_name = lib_names.name(lib) asm_name = lib_base_name + '.S' map_name = lib_base_name + '.map' asm_path = out / asm_name map_path = out / map_name has_map_file = make_asm_file(lib, lib is root, asm_path, map_path, defs) if lib is root: bp.write(f'cc_binary {{\n') bp.write(f' defaults: ["{g_benchmark_name}_binary"],\n') else: bp.write(f'cc_test_library {{\n') bp.write(f' defaults: ["{g_benchmark_name}_library"],\n') bp.write(f' name: "{lib_base_name}",\n') bp.write(f' srcs: ["{asm_name}"],\n') bp.write(f' shared_libs: [\n') for need in lib.needed: if need.soname in kBionicSonames: continue bp.write(f' "{lib_names.name(need)}",\n') bp.write(f' ],\n') if has_map_file: bp.write(f' version_script: "{map_name}",\n') bp.write('}\n') bp.close()
def build_symbol_index(lib: LoadedLibrary) -> Definitions: defs: Dict[str, LoadedLibrary] = {} for lib in bfs_walk(lib): for sym in lib.syms.values(): if not sym.defined: continue defs.setdefault(sym.name, lib) return defs
def __init__(self, root: LoadedLibrary): self._root = root self._names: Dict[LoadedLibrary, str] = {} all_libs = [x for x in bfs_walk(root) if x is not root and x.soname not in kBionicSonames] num_digits = math.ceil(math.log10(len(all_libs) + 1)) if g_obfuscate: self._names = {x : f'{i:0{num_digits}}' for i, x in enumerate(all_libs)} else: self._names = {x : re.sub(r'\.so$', '', x.soname) for x in all_libs}
def check_rels(root: LoadedLibrary, defs: Definitions) -> None: # Find every symbol for every relocation in the load group. has_missing = False for lib in bfs_walk(root): rels = lib.rels for sym in rels.got + rels.jump_slots + [sym for off, sym in rels.symbolic]: if sym.name not in defs: if sym.is_weak: pass # print('info: weak undefined', lib.soname, r) else: print(f'error: {lib.soname}: unresolved relocation to {sym.name}') has_missing = True if has_missing: sys.exit('error: had unresolved relocations')
def make_ninja_benchmark(root: LoadedLibrary, defs: Definitions, cc: str, out: Path) -> None: lib_names = LibNames(root) def lib_dso_name(lib: LoadedLibrary) -> str: return lib_names.name(lib) + '.so' ninja = open(out / 'build.ninja', 'w') include_path = os.path.relpath( os.path.dirname(__file__) + '/../include', out) common_flags = f"-Wl,-rpath-link,. -lm -I{include_path}" ninja.write( textwrap.dedent(f'''\ rule exe command = {cc} -fpie -pie $in -o $out {common_flags} $extra_args rule dso command = {cc} -fpic -shared $in -o $out -Wl,-soname,$out {common_flags} $extra_args ''')) for lib in bfs_walk(root): if lib.soname in kBionicSonames: continue lib_base_name = lib_names.name(lib) asm_name = lib_base_name + '.S' map_name = lib_base_name + '.map' asm_path = out / asm_name map_path = out / map_name has_map_file = make_asm_file(lib, lib is root, asm_path, map_path, defs) needed = ' '.join([ lib_dso_name(x) for x in lib.needed if x.soname not in kBionicSonames ]) if lib is root: ninja.write(f'build {lib_base_name}: exe {asm_name} {needed}\n') else: ninja.write( f'build {lib_dso_name(lib)}: dso {asm_name} {needed}\n') if has_map_file: ninja.write(f' extra_args = -Wl,--version-script={map_name}\n') ninja.close() subprocess.run(['ninja', '-C', str(out), lib_names.name(root)], check=True)