aboutsummaryrefslogtreecommitdiff
path: root/orderfile/post_process_orderfile.py
blob: 5f52aa6feb92f3f5f24c31197000cc3f5c17bf5d (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
92
93
#!/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:]))