blob: ea1ca7ff23581eb0bd3ce3bffa87baa3296f07fb [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#!/usr/bin/env python3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002#
3# Copyright (c) 2011, Intel Corporation.
4# All rights reserved.
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19#
20#
21# Display details of the kernel build size, broken up by built-in.o. Sort
22# the objects by size. Run from the top level kernel build directory.
23#
24# Author: Darren Hart <dvhart@linux.intel.com>
25#
26
27import sys
28import getopt
29import os
30from subprocess import *
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031
32def usage():
33 prog = os.path.basename(sys.argv[0])
Patrick Williamsc0f7c042017-02-23 20:41:17 -060034 print('Usage: %s [OPTION]...' % prog)
35 print(' -d, display an additional level of drivers detail')
36 print(' -h, --help display this help and exit')
37 print('')
38 print('Run %s from the top-level Linux kernel build directory.' % prog)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050039
40
41class Sizes:
42 def __init__(self, glob):
43 self.title = glob
Brad Bishop6e60e8b2018-02-01 10:27:11 -050044 p = Popen("size -t " + str(glob), shell=True, stdout=PIPE, stderr=PIPE)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050045 output = p.communicate()[0].splitlines()
46 if len(output) > 2:
47 sizes = output[-1].split()[0:4]
48 self.text = int(sizes[0])
49 self.data = int(sizes[1])
50 self.bss = int(sizes[2])
51 self.total = int(sizes[3])
52 else:
53 self.text = self.data = self.bss = self.total = 0
54
55 def show(self, indent=""):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060056 print("%-32s %10d | %10d %10d %10d" % \
57 (indent+self.title, self.total, self.text, self.data, self.bss))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058
59
60class Report:
61 def create(filename, title, subglob=None):
62 r = Report(filename, title)
63 path = os.path.dirname(filename)
64
Brad Bishop6e60e8b2018-02-01 10:27:11 -050065 p = Popen("ls " + str(path) + "/*.o | grep -v built-in.o",
Patrick Williamsc124f4f2015-09-15 14:41:29 -050066 shell=True, stdout=PIPE, stderr=PIPE)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060067 glob = ' '.join(p.communicate()[0].splitlines())
Brad Bishop6e60e8b2018-02-01 10:27:11 -050068 oreport = Report(glob, str(path) + "/*.o")
69 oreport.sizes.title = str(path) + "/*.o"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050070 r.parts.append(oreport)
71
72 if subglob:
73 p = Popen("ls " + subglob, shell=True, stdout=PIPE, stderr=PIPE)
74 for f in p.communicate()[0].splitlines():
75 path = os.path.dirname(f)
Brad Bishop6e60e8b2018-02-01 10:27:11 -050076 r.parts.append(Report.create(f, path, str(path) + "/*/built-in.o"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050077 r.parts.sort(reverse=True)
78
79 for b in r.parts:
80 r.totals["total"] += b.sizes.total
81 r.totals["text"] += b.sizes.text
82 r.totals["data"] += b.sizes.data
83 r.totals["bss"] += b.sizes.bss
84
85 r.deltas["total"] = r.sizes.total - r.totals["total"]
86 r.deltas["text"] = r.sizes.text - r.totals["text"]
87 r.deltas["data"] = r.sizes.data - r.totals["data"]
88 r.deltas["bss"] = r.sizes.bss - r.totals["bss"]
89 return r
90 create = staticmethod(create)
91
92 def __init__(self, glob, title):
93 self.glob = glob
94 self.title = title
95 self.sizes = Sizes(glob)
96 self.parts = []
97 self.totals = {"total":0, "text":0, "data":0, "bss":0}
98 self.deltas = {"total":0, "text":0, "data":0, "bss":0}
99
100 def show(self, indent=""):
101 rule = str.ljust(indent, 80, '-')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600102 print("%-32s %10s | %10s %10s %10s" % \
103 (indent+self.title, "total", "text", "data", "bss"))
104 print(rule)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500105 self.sizes.show(indent)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600106 print(rule)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500107 for p in self.parts:
108 if p.sizes.total > 0:
109 p.sizes.show(indent)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600110 print(rule)
111 print("%-32s %10d | %10d %10d %10d" % \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500112 (indent+"sum", self.totals["total"], self.totals["text"],
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600113 self.totals["data"], self.totals["bss"]))
114 print("%-32s %10d | %10d %10d %10d" % \
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500115 (indent+"delta", self.deltas["total"], self.deltas["text"],
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600116 self.deltas["data"], self.deltas["bss"]))
117 print("\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500118
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500119 def __lt__(this, that):
120 if that is None:
121 return 1
122 if not isinstance(that, Report):
123 raise TypeError
124 return this.sizes.total < that.sizes.total
125
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500126 def __cmp__(this, that):
127 if that is None:
128 return 1
129 if not isinstance(that, Report):
130 raise TypeError
131 if this.sizes.total < that.sizes.total:
132 return -1
133 if this.sizes.total > that.sizes.total:
134 return 1
135 return 0
136
137
138def main():
139 try:
140 opts, args = getopt.getopt(sys.argv[1:], "dh", ["help"])
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600141 except getopt.GetoptError as err:
142 print('%s' % str(err))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500143 usage()
144 sys.exit(2)
145
146 driver_detail = False
147 for o, a in opts:
148 if o == '-d':
149 driver_detail = True
150 elif o in ('-h', '--help'):
151 usage()
152 sys.exit(0)
153 else:
154 assert False, "unhandled option"
155
156 glob = "arch/*/built-in.o */built-in.o"
157 vmlinux = Report.create("vmlinux", "Linux Kernel", glob)
158
159 vmlinux.show()
160 for b in vmlinux.parts:
161 if b.totals["total"] > 0 and len(b.parts) > 1:
162 b.show()
163 if b.title == "drivers" and driver_detail:
164 for d in b.parts:
165 if d.totals["total"] > 0 and len(d.parts) > 1:
166 d.show(" ")
167
168
169if __name__ == "__main__":
170 main()