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 |
| 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": 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) |
| 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 |