3 # Copyright 2004 Matt Mackall <mpm@selenic.com>
5 # Inspired by perl Bloat-O-Meter (c) 1997 by Andi Kleen
7 # This software may be used and distributed according to the terms
8 # of the GNU General Public License, incorporated herein by reference.
13 sys
.stderr
.write("usage: %s [-t] file1 file2 [-- <readelf options>]\n"
15 sys
.stderr
.write("\t-t\tShow time spent on parsing/processing\n")
16 sys
.stderr
.write("\t--\tPass additional parameters to readelf\n")
20 flag_timing
, dashes
= (False, False)
22 for f
in sys
.argv
[1:]:
24 if f
== "--": # sym_args
27 if f
== "-t": # timings
30 if not os
.path
.exists(f
):
31 sys
.stderr
.write("Error: file '%s' does not exist\n" % f
)
41 if f1
is None or f2
is None:
44 sym_args
= " ".join(sys
.argv
[3 + flag_timing
+ dashes
:])
46 sym
, alias
, lut
= {}, {}, {}
47 for l
in os
.popen("readelf -W -s %s %s" % (sym_args
, file)).readlines():
49 if not (len(l
) and l
[0].isdigit() and len(l
.split()) == 8):
51 num
, value
, size
, typ
, bind
, vis
, ndx
, name
= l
.split()
52 if ndx
== "UND": continue # skip undefined
53 if typ
in ["SECTION", "FILES"]: continue # skip sections and files
54 if "." in name
: name
= "static." + name
.split(".")[0]
55 value
= int(value
, 16)
56 size
= int(size
, 16) if size
.startswith('0x') else int(size
)
57 if vis
!= "DEFAULT" and bind
!= "GLOBAL": # see if it is an alias
58 alias
[(value
, size
)] = {"name" : name
}
60 sym
[name
] = {"addr" : value
, "size": size
}
61 lut
[(value
, size
)] = 0
62 for addr
, sz
in iter(alias
.keys()):
63 # If the non-GLOBAL sym has an implementation elsewhere then
64 # it's an alias, disregard it.
65 if not (addr
, sz
) in lut
:
66 # If this non-GLOBAL sym does not have an implementation at
67 # another address, then treat it as a normal symbol.
68 sym
[alias
[(addr
, sz
)]["name"]] = {"addr" : addr
, "size": sz
}
69 for l
in os
.popen("readelf -W -S " + file).readlines():
72 # Should take these into account too!
73 #if x[1] not in [".text", ".rodata", ".symtab", ".strtab"]: continue
74 if x
[1] not in [".rodata"]: continue
75 sym
[x
[1]] = {"addr" : int(x
[3], 16), "size" : int(x
[5], 16)}
79 start_t1
= int(time
.time() * 1e9
)
82 end_t1
= int(time
.time() * 1e9
)
83 start_t2
= int(time
.time() * 1e9
)
86 end_t2
= int(time
.time() * 1e9
)
87 start_t3
= int(time
.time() * 1e9
)
88 grow
, shrink
, add
, remove
, up
, down
= 0, 0, 0, 0, 0, 0
89 delta
, common
= [], {}
91 for name
in iter(old
.keys()):
96 if name
not in common
:
98 sz
= old
[name
]["size"]
100 delta
.append((-sz
, name
))
103 if name
not in common
:
105 sz
= new
[name
]["size"]
107 delta
.append((sz
, name
))
110 d
= new
[name
].get("size", 0) - old
[name
].get("size", 0)
111 if d
>0: grow
, up
= grow
+1, up
+d
112 elif d
<0: shrink
, down
= shrink
+1, down
-d
115 delta
.append((d
, name
))
120 end_t3
= int(time
.time() * 1e9
)
122 print("%-48s %7s %7s %+7s" % ("function", "old", "new", "delta"))
125 old_sz
= old
.get(n
, {}).get("size", "-")
126 new_sz
= new
.get(n
, {}).get("size", "-")
127 print("%-48s %7s %7s %+7d" % (n
, old_sz
, new_sz
, d
))
129 total
="(add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s)%%sTotal: %s bytes"\
130 % (add
, remove
, grow
, shrink
, up
, -down
, up
-down
)
131 print(total
% (" "*(80-len(total
))))
133 print("\n%d/%d; %d Parse origin/new; processing nsecs" %
134 (end_t1
-start_t1
, end_t2
-start_t2
, end_t3
-start_t3
))
135 print("total nsecs: %d" % (end_t3
-start_t1
))