bloat-o-meter: avoid double counting

Disable 'echo' in the default config, run 'make baseline', then
re-enable 'echo' and run 'make bloatcheck':

function                                             old     new   delta
.rodata                                           182521  182622    +101
packed_usage                                       33714   33792     +78
applet_main                                         3168    3176      +8
applet_names                                        2730    2735      +5
applet_suid                                           99     100      +1
applet_install_loc                                   198     199      +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 6/0 up/down: 194/0)             Total: 194 bytes
   text	   data	    bss	    dec	    hex	filename
 955052	   4195	   1808	 961055	  eaa1f	busybox_old
 955153	   4195	   1808	 961156	  eaa84	busybox_unstripped

The Total bytes value doesn't equal the change in the size of the
binary.  The packed_usage and applet_* items are in .rodata and
are counted twice.  With this modified bloat-o-meter the size of
named items is deducted from .rodata:

function                                             old     new   delta
packed_usage                                       33714   33792     +78
applet_main                                         3168    3176      +8
.rodata                                           105105  105113      +8
applet_names                                        2730    2735      +5
applet_suid                                           99     100      +1
applet_install_loc                                   198     199      +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 6/0 up/down: 101/0)             Total: 101 bytes
   text	   data	    bss	    dec	    hex	filename
 955052	   4195	   1808	 961055	  eaa1f	busybox_old
 955153	   4195	   1808	 961156	  eaa84	busybox_unstripped

v2: Sections numbered less than 10 were always being omitted from
    consideration because splitting "[ 1] .interp" leaves "1]" in
    x[1] where the section name is expected.  This wasn't a problem
    for .rodata (numbered 15 in my testing) but let's fix it anyway.

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Ron Yorston 2021-03-08 19:30:57 +00:00 committed by Denys Vlasenko
parent 307cd26e98
commit 0b25e810ed

View File

@ -43,7 +43,15 @@ if f1 is None or f2 is None:
sym_args = " ".join(sys.argv[3 + flag_timing + dashes:]) sym_args = " ".join(sys.argv[3 + flag_timing + dashes:])
def getsizes(file): def getsizes(file):
sym, alias, lut = {}, {}, {} sym, alias, lut, section = {}, {}, {}, {}
for l in os.popen("readelf -W -S " + file).readlines():
x = l.replace("[ ", "[", 1).split()
if len(x)<6: continue
# Should take these into account too!
#if x[1] not in [".text", ".rodata", ".symtab", ".strtab"]: continue
if x[1] not in [".rodata"]: continue
sym[x[1]] = {"addr" : int(x[3], 16), "size" : int(x[5], 16)}
section[x[0][1:-1]] = {"name" : x[1]}
for l in os.popen("readelf -W -s %s %s" % (sym_args, file)).readlines(): for l in os.popen("readelf -W -s %s %s" % (sym_args, file)).readlines():
l = l.strip() l = l.strip()
if not (len(l) and l[0].isdigit() and len(l.split()) == 8): if not (len(l) and l[0].isdigit() and len(l.split()) == 8):
@ -59,6 +67,10 @@ def getsizes(file):
else: else:
sym[name] = {"addr" : value, "size": size} sym[name] = {"addr" : value, "size": size}
lut[(value, size)] = 0 lut[(value, size)] = 0
# If this item is in a known section deduct its size from
# the size of the section
if ndx in section:
sym[section[ndx]["name"]]["size"] -= size
for addr, sz in iter(alias.keys()): for addr, sz in iter(alias.keys()):
# If the non-GLOBAL sym has an implementation elsewhere then # If the non-GLOBAL sym has an implementation elsewhere then
# it's an alias, disregard it. # it's an alias, disregard it.
@ -66,13 +78,6 @@ def getsizes(file):
# If this non-GLOBAL sym does not have an implementation at # If this non-GLOBAL sym does not have an implementation at
# another address, then treat it as a normal symbol. # another address, then treat it as a normal symbol.
sym[alias[(addr, sz)]["name"]] = {"addr" : addr, "size": sz} sym[alias[(addr, sz)]["name"]] = {"addr" : addr, "size": sz}
for l in os.popen("readelf -W -S " + file).readlines():
x = l.split()
if len(x)<6: continue
# Should take these into account too!
#if x[1] not in [".text", ".rodata", ".symtab", ".strtab"]: continue
if x[1] not in [".rodata"]: continue
sym[x[1]] = {"addr" : int(x[3], 16), "size" : int(x[5], 16)}
return sym return sym
if flag_timing: if flag_timing: