xref: /openbmc/openbmc/poky/scripts/tiny/ksum.py (revision c27f31fe)
1#!/usr/bin/env python3
2#
3# Copyright (c) 2016, Intel Corporation.
4#
5# SPDX-License-Identifier: GPL-2.0-only
6#
7# DESCRIPTION 'ksum.py' generates a combined summary of vmlinux and
8# module sizes for a built kernel, as a quick tool for comparing the
9# overall effects of systemic tinification changes.  Execute from the
10# base directory of the kernel build you want to summarize.  Setting
11# the 'verbose' flag will display the sizes for each file included in
12# the summary.
13#
14# AUTHORS
15# Tom Zanussi <tom.zanussi (at] linux.intel.com>
16#
17
18__version__ = "0.1.0"
19
20# Python Standard Library modules
21import os
22import sys
23import getopt
24from subprocess import *
25
26def usage():
27    prog = os.path.basename(sys.argv[0])
28    print('Usage: %s [OPTION]...' % prog)
29    print('  -v,                 display sizes for each file')
30    print('  -h, --help          display this help and exit')
31    print('')
32    print('Run %s from the top-level Linux kernel build directory.' % prog)
33
34verbose = False
35
36n_ko_files = 0
37ko_file_list = []
38
39ko_text = 0
40ko_data = 0
41ko_bss = 0
42ko_total = 0
43
44vmlinux_file = ""
45vmlinux_level = 0
46
47vmlinux_text = 0
48vmlinux_data = 0
49vmlinux_bss = 0
50vmlinux_total = 0
51
52def is_vmlinux_file(filename):
53    global vmlinux_level
54    if filename == ("vmlinux") and vmlinux_level == 0:
55        vmlinux_level += 1
56        return True
57    return False
58
59def is_ko_file(filename):
60    if filename.endswith(".ko"):
61        return True
62    return False
63
64def collect_object_files():
65    print("Collecting object files recursively from %s..." % os.getcwd())
66    for dirpath, dirs, files in os.walk(os.getcwd()):
67        for filename in files:
68            if is_ko_file(filename):
69                ko_file_list.append(os.path.join(dirpath, filename))
70            elif is_vmlinux_file(filename):
71                global vmlinux_file
72                vmlinux_file = os.path.join(dirpath, filename)
73    print("Collecting object files [DONE]")
74
75def add_ko_file(filename):
76        p = Popen("size -t " + filename, shell=True, stdout=PIPE, stderr=PIPE)
77        output = p.communicate()[0].splitlines()
78        if len(output) > 2:
79            sizes = output[-1].split()[0:4]
80            if verbose:
81                print("     %10d %10d %10d %10d\t" % \
82                    (int(sizes[0]), int(sizes[1]), int(sizes[2]), int(sizes[3])), end=' ')
83                print("%s" % filename[len(os.getcwd()) + 1:])
84            global n_ko_files, ko_text, ko_data, ko_bss, ko_total
85            ko_text += int(sizes[0])
86            ko_data += int(sizes[1])
87            ko_bss += int(sizes[2])
88            ko_total += int(sizes[3])
89            n_ko_files += 1
90
91def get_vmlinux_totals():
92        p = Popen("size -t " + vmlinux_file, shell=True, stdout=PIPE, stderr=PIPE)
93        output = p.communicate()[0].splitlines()
94        if len(output) > 2:
95            sizes = output[-1].split()[0:4]
96            if verbose:
97                print("     %10d %10d %10d %10d\t" % \
98                    (int(sizes[0]), int(sizes[1]), int(sizes[2]), int(sizes[3])), end=' ')
99                print("%s" % vmlinux_file[len(os.getcwd()) + 1:])
100            global vmlinux_text, vmlinux_data, vmlinux_bss, vmlinux_total
101            vmlinux_text += int(sizes[0])
102            vmlinux_data += int(sizes[1])
103            vmlinux_bss += int(sizes[2])
104            vmlinux_total += int(sizes[3])
105
106def sum_ko_files():
107    for ko_file in ko_file_list:
108        add_ko_file(ko_file)
109
110def main():
111    try:
112        opts, args = getopt.getopt(sys.argv[1:], "vh", ["help"])
113    except getopt.GetoptError as err:
114        print('%s' % str(err))
115        usage()
116        sys.exit(2)
117
118    for o, a in opts:
119        if o == '-v':
120            global verbose
121            verbose = True
122        elif o in ('-h', '--help'):
123            usage()
124            sys.exit(0)
125        else:
126            assert False, "unhandled option"
127
128    collect_object_files()
129    sum_ko_files()
130    get_vmlinux_totals()
131
132    print("\nTotals:")
133    print("\nvmlinux:")
134    print("    text\tdata\t\tbss\t\ttotal")
135    print("    %-10d\t%-10d\t%-10d\t%-10d" % \
136        (vmlinux_text, vmlinux_data, vmlinux_bss, vmlinux_total))
137    print("\nmodules (%d):" % n_ko_files)
138    print("    text\tdata\t\tbss\t\ttotal")
139    print("    %-10d\t%-10d\t%-10d\t%-10d" % \
140        (ko_text, ko_data, ko_bss, ko_total))
141    print("\nvmlinux + modules:")
142    print("    text\tdata\t\tbss\t\ttotal")
143    print("    %-10d\t%-10d\t%-10d\t%-10d" % \
144        (vmlinux_text + ko_text, vmlinux_data + ko_data, \
145         vmlinux_bss + ko_bss, vmlinux_total + ko_total))
146
147if __name__ == "__main__":
148    try:
149        ret = main()
150    except Exception:
151        ret = 1
152        import traceback
153        traceback.print_exc(5)
154    sys.exit(ret)
155