1cc1dc7a3Sopenharmony_ci#!/usr/bin/env python3
2cc1dc7a3Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0
3cc1dc7a3Sopenharmony_ci# -----------------------------------------------------------------------------
4cc1dc7a3Sopenharmony_ci# Copyright 2021-2022 Arm Limited
5cc1dc7a3Sopenharmony_ci#
6cc1dc7a3Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); you may not
7cc1dc7a3Sopenharmony_ci# use this file except in compliance with the License. You may obtain a copy
8cc1dc7a3Sopenharmony_ci# of the License at:
9cc1dc7a3Sopenharmony_ci#
10cc1dc7a3Sopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
11cc1dc7a3Sopenharmony_ci#
12cc1dc7a3Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
13cc1dc7a3Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14cc1dc7a3Sopenharmony_ci# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15cc1dc7a3Sopenharmony_ci# License for the specific language governing permissions and limitations
16cc1dc7a3Sopenharmony_ci# under the License.
17cc1dc7a3Sopenharmony_ci# -----------------------------------------------------------------------------
18cc1dc7a3Sopenharmony_ci"""
19cc1dc7a3Sopenharmony_ciThe ``astc_dump_binary`` utility provides a wrapper around the ``objdump``
20cc1dc7a3Sopenharmony_ciutility to extract disassembly of specific functions. Currently only matches
21cc1dc7a3Sopenharmony_cithe root name, for sake of command line sanity, so all overloads get dumped.
22cc1dc7a3Sopenharmony_ci
23cc1dc7a3Sopenharmony_ciUsing __attribute__((noinline)) can be useful during profiling to stop any
24cc1dc7a3Sopenharmony_cifunctions of interest getting inlined once they get too small ...
25cc1dc7a3Sopenharmony_ci"""
26cc1dc7a3Sopenharmony_ci
27cc1dc7a3Sopenharmony_ci
28cc1dc7a3Sopenharmony_ciimport argparse
29cc1dc7a3Sopenharmony_ciimport re
30cc1dc7a3Sopenharmony_ciimport shutil
31cc1dc7a3Sopenharmony_ciimport subprocess as sp
32cc1dc7a3Sopenharmony_ciimport sys
33cc1dc7a3Sopenharmony_ci
34cc1dc7a3Sopenharmony_ci
35cc1dc7a3Sopenharmony_cidef run_objdump(binary, symbol):
36cc1dc7a3Sopenharmony_ci    """
37cc1dc7a3Sopenharmony_ci    Run objdump on a single binary and extract the range for a given symbol.
38cc1dc7a3Sopenharmony_ci
39cc1dc7a3Sopenharmony_ci    Output is printed to stdout.
40cc1dc7a3Sopenharmony_ci
41cc1dc7a3Sopenharmony_ci    Args:
42cc1dc7a3Sopenharmony_ci        binary (str): The path of the binary file to process.
43cc1dc7a3Sopenharmony_ci        symbol (str): The symbol to match.
44cc1dc7a3Sopenharmony_ci
45cc1dc7a3Sopenharmony_ci    Raises:
46cc1dc7a3Sopenharmony_ci        CalledProcessException: The ``objdump`` subprocess failed for any reason.
47cc1dc7a3Sopenharmony_ci    """
48cc1dc7a3Sopenharmony_ci    args = [
49cc1dc7a3Sopenharmony_ci        "objdump", "-C",
50cc1dc7a3Sopenharmony_ci        "-M", "intel",
51cc1dc7a3Sopenharmony_ci        "--no-show-raw",
52cc1dc7a3Sopenharmony_ci        "-d", "-S",
53cc1dc7a3Sopenharmony_ci        binary
54cc1dc7a3Sopenharmony_ci    ]
55cc1dc7a3Sopenharmony_ci
56cc1dc7a3Sopenharmony_ci    result = sp.run(args, stdout=sp.PIPE, stderr=sp.PIPE,
57cc1dc7a3Sopenharmony_ci                    check=True, universal_newlines=True)
58cc1dc7a3Sopenharmony_ci
59cc1dc7a3Sopenharmony_ci    funcPattern = re.compile(r"^[0-9a-f]{16} <(.*?)\(.*\)>:$")
60cc1dc7a3Sopenharmony_ci
61cc1dc7a3Sopenharmony_ci    funcLines = []
62cc1dc7a3Sopenharmony_ci    funcActive = False
63cc1dc7a3Sopenharmony_ci    lines = result.stdout.splitlines()
64cc1dc7a3Sopenharmony_ci
65cc1dc7a3Sopenharmony_ci    for line in lines:
66cc1dc7a3Sopenharmony_ci        match = funcPattern.match(line)
67cc1dc7a3Sopenharmony_ci        if match:
68cc1dc7a3Sopenharmony_ci            funcName = match.group(1)
69cc1dc7a3Sopenharmony_ci            if funcName == symbol:
70cc1dc7a3Sopenharmony_ci                funcActive = True
71cc1dc7a3Sopenharmony_ci            else:
72cc1dc7a3Sopenharmony_ci                funcActive = False
73cc1dc7a3Sopenharmony_ci
74cc1dc7a3Sopenharmony_ci        if funcActive:
75cc1dc7a3Sopenharmony_ci            funcLines.append(line)
76cc1dc7a3Sopenharmony_ci
77cc1dc7a3Sopenharmony_ci    print("\n".join(funcLines))
78cc1dc7a3Sopenharmony_ci
79cc1dc7a3Sopenharmony_cidef parse_command_line():
80cc1dc7a3Sopenharmony_ci    """
81cc1dc7a3Sopenharmony_ci    Parse the command line.
82cc1dc7a3Sopenharmony_ci
83cc1dc7a3Sopenharmony_ci    Returns:
84cc1dc7a3Sopenharmony_ci        Namespace: The parsed command line container.
85cc1dc7a3Sopenharmony_ci    """
86cc1dc7a3Sopenharmony_ci    parser = argparse.ArgumentParser()
87cc1dc7a3Sopenharmony_ci
88cc1dc7a3Sopenharmony_ci    parser.add_argument("binary", type=argparse.FileType("r"),
89cc1dc7a3Sopenharmony_ci                        help="The new binary to dump")
90cc1dc7a3Sopenharmony_ci
91cc1dc7a3Sopenharmony_ci    parser.add_argument("symbol", type=str,
92cc1dc7a3Sopenharmony_ci                        help="The function name to dump")
93cc1dc7a3Sopenharmony_ci
94cc1dc7a3Sopenharmony_ci    return parser.parse_args()
95cc1dc7a3Sopenharmony_ci
96cc1dc7a3Sopenharmony_ci
97cc1dc7a3Sopenharmony_cidef main():
98cc1dc7a3Sopenharmony_ci    """
99cc1dc7a3Sopenharmony_ci    The main function.
100cc1dc7a3Sopenharmony_ci
101cc1dc7a3Sopenharmony_ci    Returns:
102cc1dc7a3Sopenharmony_ci        int: The process return code.
103cc1dc7a3Sopenharmony_ci    """
104cc1dc7a3Sopenharmony_ci    args = parse_command_line()
105cc1dc7a3Sopenharmony_ci
106cc1dc7a3Sopenharmony_ci    # Preflight - check that size exists. Note that size might still fail at
107cc1dc7a3Sopenharmony_ci    # runtime later, e.g. if the binary is not of the correct format
108cc1dc7a3Sopenharmony_ci    path = shutil.which("objdump")
109cc1dc7a3Sopenharmony_ci    if not path:
110cc1dc7a3Sopenharmony_ci        print("ERROR: The 'objdump' utility is not installed on the PATH")
111cc1dc7a3Sopenharmony_ci        return 1
112cc1dc7a3Sopenharmony_ci
113cc1dc7a3Sopenharmony_ci    # Collect the data
114cc1dc7a3Sopenharmony_ci    try:
115cc1dc7a3Sopenharmony_ci        run_objdump(args.binary.name, args.symbol)
116cc1dc7a3Sopenharmony_ci    except sp.CalledProcessError as ex:
117cc1dc7a3Sopenharmony_ci        print("ERROR: The 'objdump' utility failed")
118cc1dc7a3Sopenharmony_ci        print("       %s" % ex.stderr.strip())
119cc1dc7a3Sopenharmony_ci        return 1
120cc1dc7a3Sopenharmony_ci
121cc1dc7a3Sopenharmony_ci    return 0
122cc1dc7a3Sopenharmony_ci
123cc1dc7a3Sopenharmony_ci
124cc1dc7a3Sopenharmony_ciif __name__ == "__main__":
125cc1dc7a3Sopenharmony_ci    sys.exit(main())
126