1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright 2019 The ChromiumOS Authors 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7"""Script to do post-process on orderfile generated by C3. 8 9The goal of this script is to take in an orderfile generated by C3, and do 10the following post process: 11 121. Take in the result of nm command on Chrome binary to find out all the 13Builtin functions and put them after the input symbols. 14 152. Put special markers "chrome_begin_ordered_code" and "chrome_end_ordered_code" 16in begin and end of the file. 17 18The results of the file is intended to be uploaded and consumed when linking 19Chrome in ChromeOS. 20""" 21 22 23import argparse 24import os 25import sys 26 27 28def _parse_nm_output(stream): 29 for line in (line.rstrip() for line in stream): 30 if not line: 31 continue 32 33 pieces = line.split() 34 if len(pieces) != 3: 35 continue 36 37 _, ty, symbol = pieces 38 if ty not in "tT": 39 continue 40 41 # We'll sometimes see synthesized symbols that start with $. There isn't 42 # much we can do about or with them, regrettably. 43 if symbol.startswith("$"): 44 continue 45 46 yield symbol 47 48 49def _remove_duplicates(iterable): 50 seen = set() 51 for item in iterable: 52 if item in seen: 53 continue 54 seen.add(item) 55 yield item 56 57 58def run(c3_ordered_stream, chrome_nm_stream, output_stream): 59 head_marker = "chrome_begin_ordered_code" 60 tail_marker = "chrome_end_ordered_code" 61 62 c3_ordered_syms = [x.strip() for x in c3_ordered_stream.readlines()] 63 all_chrome_syms = set(_parse_nm_output(chrome_nm_stream)) 64 # Sort by name, so it's predictable. Otherwise, these should all land in the 65 # same hugepage anyway, so order doesn't matter as much. 66 builtin_syms = sorted( 67 s for s in all_chrome_syms if s.startswith("Builtins_") 68 ) 69 output = _remove_duplicates( 70 [head_marker] + c3_ordered_syms + builtin_syms + [tail_marker] 71 ) 72 output_stream.write("\n".join(output)) 73 74 75def main(argv): 76 parser = argparse.ArgumentParser() 77 parser.add_argument("--chrome_nm", required=True, dest="chrome_nm") 78 parser.add_argument("--input", required=True, dest="input_file") 79 parser.add_argument("--output", required=True, dest="output_file") 80 81 options = parser.parse_args(argv) 82 83 if not os.path.exists(options.input_file): 84 sys.exit("Input orderfile doesn't exist.") 85 86 with open(options.input_file) as in_stream, open( 87 options.chrome_nm 88 ) as chrome_nm_stream, open(options.output_file, "w") as out_stream: 89 run(in_stream, chrome_nm_stream, out_stream) 90 91 92if __name__ == "__main__": 93 sys.exit(main(sys.argv[1:])) 94