1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright 2019 The Chromium OS Authors. All rights reserved. 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 Chrome OS. 20""" 21 22from __future__ import division, print_function 23 24import argparse 25import os 26import sys 27 28 29def _parse_nm_output(stream): 30 for line in (line.rstrip() for line in stream): 31 if not line: 32 continue 33 34 pieces = line.split() 35 if len(pieces) != 3: 36 continue 37 38 _, ty, symbol = pieces 39 if ty not in 'tT': 40 continue 41 42 # We'll sometimes see synthesized symbols that start with $. There isn't 43 # much we can do about or with them, regrettably. 44 if symbol.startswith('$'): 45 continue 46 47 yield symbol 48 49 50def _remove_duplicates(iterable): 51 seen = set() 52 for item in iterable: 53 if item in seen: 54 continue 55 seen.add(item) 56 yield item 57 58 59def run(c3_ordered_stream, chrome_nm_stream, output_stream): 60 head_marker = 'chrome_begin_ordered_code' 61 tail_marker = 'chrome_end_ordered_code' 62 63 c3_ordered_syms = [x.strip() for x in c3_ordered_stream.readlines()] 64 all_chrome_syms = set(_parse_nm_output(chrome_nm_stream)) 65 # Sort by name, so it's predictable. Otherwise, these should all land in the 66 # same hugepage anyway, so order doesn't matter as much. 67 builtin_syms = sorted(s for s in all_chrome_syms if s.startswith('Builtins_')) 68 output = _remove_duplicates([head_marker] + c3_ordered_syms + builtin_syms + 69 [tail_marker]) 70 output_stream.write('\n'.join(output)) 71 72 73def main(argv): 74 parser = argparse.ArgumentParser() 75 parser.add_argument('--chrome_nm', required=True, dest='chrome_nm') 76 parser.add_argument('--input', required=True, dest='input_file') 77 parser.add_argument('--output', required=True, dest='output_file') 78 79 options = parser.parse_args(argv) 80 81 if not os.path.exists(options.input_file): 82 sys.exit("Input orderfile doesn\'t exist.") 83 84 with open(options.input_file) as in_stream, \ 85 open(options.chrome_nm) as chrome_nm_stream, \ 86 open(options.output_file, 'w') as out_stream: 87 run(in_stream, chrome_nm_stream, out_stream) 88 89 90if __name__ == '__main__': 91 sys.exit(main(sys.argv[1:])) 92