• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# encoding=utf-8
3# ============================================================================
4# @brief    Script file
5# Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17# ============================================================================
18
19'''
20Read in an elf file and generate a 'du' output for it.
21'''
22from __future__ import print_function
23from collections import OrderedDict
24import subprocess
25import re
26import os
27import argparse
28
29if __name__ == '__main__':
30    parser = argparse.ArgumentParser(
31        description='Generate du output from an elf file')
32    parser.add_argument('root_dir', metavar="Root_dir", help="Code root_dir")
33    parser.add_argument('elf', metavar="ELF", help="ELF file to parse")
34    parser.add_argument('nm', metavar="nm", help="gcc nm path")
35    args = parser.parse_args()
36
37    # Get nm and elf filenames from command line args
38    root_dir = args.root_dir
39    nm = args.nm
40    elf = args.elf
41
42    # build command line and run nm
43    cmd = nm + ' -l -A -t x -f sysv -S ' + elf
44    p = subprocess.Popen(
45        cmd.split(),
46        stdin=subprocess.PIPE,
47        stdout=subprocess.PIPE)
48    stdout, stderr = p.communicate()
49    return_code = p.wait()
50    if (return_code != 0):
51        raise Exception(nm + " returned: " + str(return_code))
52
53    # parse the output
54    line_count = 0
55    line_match = 0
56    symbol_type = OrderedDict()
57
58    # Convert stdout from bytes to a string
59    stdoutstr = stdout.decode("utf-8")
60
61    # Loop over each line in the string
62    for line in iter(stdoutstr.splitlines()):
63        line_count = line_count + 1
64
65        sl = line.split("|")
66        if (len(sl) == 7):
67            elfsym = re.match(r'^(.*):([^\s]*)', sl[0])
68            if elfsym:
69                elf = elfsym.group(1)
70                symbol = elfsym.group(2)
71
72                if (len(sl[1].strip())):
73                    location = int(sl[1], 16)
74                else:
75                    location = 0
76
77                c = sl[2].strip()
78                t = sl[3].strip()
79                if (len(sl[4].strip())):
80                    size = int(sl[4], 16)
81                else:
82                    size = 0
83                u2 = sl[5]
84                segmentfileline = re.match(r'([^\t]*)\t(.*):([^\|]*)', sl[6])
85                if segmentfileline:
86                    try:
87                        segment = segmentfileline.group(1)
88                        src_file = segmentfileline.group(2)
89                        src_file_line = int(segmentfileline.group(3))
90                        if segment not in symbol_type:
91                            symbol_type[segment] = list()
92                        symbol_type[segment].append((src_file, symbol, size))
93                        line_match = line_match + 1
94                    except Exception as e:
95                        print("warning:", e.with_traceback())
96
97
98    # Find common filename prefix string from all input files
99    init_prefix = True
100    file_count = 0
101    # Loop through displaying each line and totals
102    segment_total = 0
103    # Loop over each segment
104    for segment in symbol_type:
105        filename_total = 0
106        curr_filename = ''
107
108        # Loop over each symbol in segment
109        for symbol in symbol_type[segment]:
110            filename = symbol[0]
111            sym = symbol[1]
112            size = symbol[2]
113
114            # strip prefix from start of filename
115            if (root_dir):
116                filename = filename.replace(root_dir, '', 1)
117            # convert \\ to / in filename
118            filename = filename.replace('\\', '/')
119
120            if filename != curr_filename:
121                curr_filename = filename
122                filename_total = 0
123            filename_total = filename_total + size
124            segment_total = segment_total + size
125            # print line for filename/function
126            out_str = os.path.normpath('%(sz)-8u./%(segment)s/%(file)s/%(sym)s' %
127                  {'sz': size, 'segment': segment, 'file': filename,
128                   'sym': sym})
129            print(out_str)
130
131        # print total for filename (last one)
132
133        # print total for segment
134        segment_total = 0
135
136    print("done. Lines: %s, Matches: %s" % (str(line_count), str(line_match)))
137