OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """Symbolizes and prints live objects as recorded by tcmalloc's | |
7 HeapProfilerDumpLiveObjects. | |
8 """ | |
9 | |
10 import os | |
11 import re | |
12 import subprocess | |
13 import sys | |
14 import tempfile | |
15 | |
16 def usage(): | |
17 print """\ | |
18 Usage: | |
19 tools/tcmalloc/print-live-objects.py out/Debug/chrome leaks.dmp | |
20 """ | |
21 | |
22 def LoadDump(dump_file): | |
23 result = [] | |
24 leakfmt = re.compile( | |
25 r"^\s*1:\s*(\d+)\s*\[\s*1:\s*\d+\]\s*@(0x[a-f0-9]+)((\s+0x[a-f0-9]+)*)$") | |
26 line_no = 0; | |
marja
2012/06/06 13:11:06
nit: no ; says the style guide
| |
27 with open(dump_file) as f: | |
28 for line in f: | |
29 line_no = line_no + 1 | |
30 matches = leakfmt.match(line) | |
31 if not matches: | |
32 print "%s: could not parse line %d, skipping" % (dump_file, line_no) | |
33 else: | |
34 trace = { "size": int(matches.group(1)), | |
35 "address": matches.group(2), | |
36 "frames": [f for f in matches.group(3).strip().split(" ")]} | |
37 result.append(trace) | |
38 return result | |
39 | |
40 | |
41 def Symbolize(binary, traces): | |
42 addresses = set() | |
43 for trace in traces: | |
44 for frame in trace["frames"]: | |
45 addresses.add(frame); | |
marja
2012/06/06 13:11:06
here too
| |
46 addr_file, addr_filename = tempfile.mkstemp() | |
47 for addr in addresses: | |
48 os.write(addr_file, "%s\n" % addr) | |
49 os.close(addr_file) | |
50 syms = subprocess.Popen([ | |
51 "addr2line", "-f", "-C", "-e", binary, "@%s" % addr_filename], | |
52 stdout=subprocess.PIPE).communicate()[0].strip().split("\n") | |
53 table = {} | |
54 cwd = os.getcwd() | |
55 for address, symbol, location in zip(addresses, syms[::2], syms[1::2]): | |
56 if location != "??:0": | |
57 filename, line = location.split(":") | |
58 filename = os.path.realpath(filename)[len(cwd)+1:] | |
59 location = "%s:%s" % (filename, line) | |
60 table[address] = { "name": symbol, "location": location } | |
61 for trace in traces: | |
62 frames = [] | |
63 for frame in trace["frames"]: | |
64 frames.append(table[frame]) | |
65 trace["frames"] = frames | |
66 | |
67 | |
68 def Main(argv): | |
69 if sys.platform != 'linux2': | |
70 print 'print-live-objects.py requires addr2line only present on Linux.' | |
71 sys.exit(1) | |
72 | |
73 if len(argv) != 3: | |
74 usage() | |
75 sys.exit(1) | |
76 | |
77 traces = LoadDump(argv[2]) | |
78 Symbolize(argv[1], traces) | |
79 | |
80 if not traces: | |
81 print "No leaks found!" | |
82 | |
83 for trace in traces: | |
84 print "Leak of %d bytes at address %s" % (trace["size"], trace["address"]) | |
85 for frame in trace["frames"]: | |
86 print " %s (%s)" % (frame["name"], frame["location"]) | |
87 print "" | |
88 | |
89 | |
90 if __name__ == '__main__': | |
91 Main(sys.argv) | |
OLD | NEW |