aboutsummaryrefslogtreecommitdiff
path: root/orderfile/post_process_orderfile.py
blob: 3db0b3b875b6d32a457a12edf2afc8df92eb33a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# 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 Chrome OS.
"""

from __future__ import division, print_function

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:]))