#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright 2019 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Script to do post-process on orderfile generated by C3. The goal of this script is to take in an orderfile generated by C3, and do the following post process: 1. Take in the result of nm command on Chrome binary to find out all the Builtin functions and put them after the input symbols. 2. Put special markers "chrome_begin_ordered_code" and "chrome_end_ordered_code" in begin and end of the file. The results of the file is intended to be uploaded and consumed when linking Chrome in ChromeOS. """ import argparse import os import sys def _parse_nm_output(stream): for line in (line.rstrip() for line in stream): if not line: continue pieces = line.split() if len(pieces) != 3: continue _, ty, symbol = pieces if ty not in "tT": continue # We'll sometimes see synthesized symbols that start with $. There isn't # much we can do about or with them, regrettably. if symbol.startswith("$"): continue yield symbol def _remove_duplicates(iterable): seen = set() for item in iterable: if item in seen: continue seen.add(item) yield item def run(c3_ordered_stream, chrome_nm_stream, output_stream): head_marker = "chrome_begin_ordered_code" tail_marker = "chrome_end_ordered_code" c3_ordered_syms = [x.strip() for x in c3_ordered_stream.readlines()] all_chrome_syms = set(_parse_nm_output(chrome_nm_stream)) # Sort by name, so it's predictable. Otherwise, these should all land in the # same hugepage anyway, so order doesn't matter as much. builtin_syms = sorted( s for s in all_chrome_syms if s.startswith("Builtins_") ) output = _remove_duplicates( [head_marker] + c3_ordered_syms + builtin_syms + [tail_marker] ) output_stream.write("\n".join(output)) def main(argv): parser = argparse.ArgumentParser() parser.add_argument("--chrome_nm", required=True, dest="chrome_nm") parser.add_argument("--input", required=True, dest="input_file") parser.add_argument("--output", required=True, dest="output_file") options = parser.parse_args(argv) if not os.path.exists(options.input_file): sys.exit("Input orderfile doesn't exist.") with open(options.input_file) as in_stream, open( options.chrome_nm ) as chrome_nm_stream, open(options.output_file, "w") as out_stream: run(in_stream, chrome_nm_stream, out_stream) if __name__ == "__main__": sys.exit(main(sys.argv[1:]))