Index: tools/tcmalloc/print-live-objects.py |
diff --git a/tools/tcmalloc/print-live-objects.py b/tools/tcmalloc/print-live-objects.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..9886fd1924e141e603ef91ffb3e79772fe219189 |
--- /dev/null |
+++ b/tools/tcmalloc/print-live-objects.py |
@@ -0,0 +1,91 @@ |
+#!/usr/bin/env python |
+# Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""Symbolizes and prints live objects as recorded by tcmalloc's |
+HeapProfilerDumpLiveObjects. |
+""" |
+ |
+import os |
+import re |
+import subprocess |
+import sys |
+import tempfile |
+ |
+def usage(): |
+ print """\ |
+Usage: |
+ tools/tcmalloc/print-live-objects.py out/Debug/chrome leaks.dmp |
+""" |
+ |
+def LoadDump(dump_file): |
+ result = [] |
+ leakfmt = re.compile( |
+ r"^\s*1:\s*(\d+)\s*\[\s*1:\s*\d+\]\s*@(0x[a-f0-9]+)((\s+0x[a-f0-9]+)*)$") |
+ line_no = 0 |
+ with open(dump_file) as f: |
+ for line in f: |
+ line_no = line_no + 1 |
+ matches = leakfmt.match(line) |
+ if not matches: |
+ print "%s: could not parse line %d, skipping" % (dump_file, line_no) |
+ else: |
+ trace = { "size": int(matches.group(1)), |
+ "address": matches.group(2), |
+ "frames": matches.group(3).strip().split(" ")} |
+ result.append(trace) |
+ return result |
+ |
+ |
+def Symbolize(binary, traces): |
+ addresses = set() |
+ for trace in traces: |
+ for frame in trace["frames"]: |
+ addresses.add(frame) |
+ addr_file, addr_filename = tempfile.mkstemp() |
+ for addr in addresses: |
+ os.write(addr_file, "%s\n" % addr) |
+ os.close(addr_file) |
+ syms = subprocess.Popen([ |
+ "addr2line", "-f", "-C", "-e", binary, "@%s" % addr_filename], |
+ stdout=subprocess.PIPE).communicate()[0].strip().split("\n") |
+ table = {} |
+ cwd = os.getcwd() |
+ for address, symbol, location in zip(addresses, syms[::2], syms[1::2]): |
+ if location != "??:0": |
+ filename, line = location.split(":") |
+ filename = os.path.realpath(filename)[len(cwd)+1:] |
+ location = "%s:%s" % (filename, line) |
+ table[address] = { "name": symbol, "location": location } |
+ for trace in traces: |
+ frames = [] |
+ for frame in trace["frames"]: |
+ frames.append(table[frame]) |
+ trace["frames"] = frames |
+ |
+ |
+def Main(argv): |
+ if sys.platform != 'linux2': |
+ print 'print-live-objects.py requires addr2line only present on Linux.' |
+ sys.exit(1) |
+ |
+ if len(argv) != 3: |
+ usage() |
+ sys.exit(1) |
+ |
+ traces = LoadDump(argv[2]) |
+ Symbolize(argv[1], traces) |
+ |
+ if not traces: |
+ print "No leaks found!" |
+ |
+ for trace in traces: |
+ print "Leak of %d bytes at address %s" % (trace["size"], trace["address"]) |
+ for frame in trace["frames"]: |
+ print " %s (%s)" % (frame["name"], frame["location"]) |
+ print "" |
+ |
+ |
+if __name__ == '__main__': |
+ Main(sys.argv) |