summaryrefslogtreecommitdiffstats
path: root/tools/tcmalloc
diff options
context:
space:
mode:
authorjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-11 13:21:38 +0000
committerjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-11 13:21:38 +0000
commit8489103d9b1c879eb63ea52b0665bfeadba07c42 (patch)
treedc039c99f6109434048cade9a5b7013f9831c7a9 /tools/tcmalloc
parent4760f74799ed3e2fa53ef32a56464866b9aa3aa0 (diff)
downloadchromium_src-8489103d9b1c879eb63ea52b0665bfeadba07c42.zip
chromium_src-8489103d9b1c879eb63ea52b0665bfeadba07c42.tar.gz
chromium_src-8489103d9b1c879eb63ea52b0665bfeadba07c42.tar.bz2
Add support for dump allocations created in a certain time window
This allows for debugging e.g. objects that are not deleted during a page reload. I also added a tool for parsing and symbolizing the traces. BUG=none TEST=manual Review URL: https://chromiumcodereview.appspot.com/10541026 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141404 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/tcmalloc')
-rwxr-xr-xtools/tcmalloc/print-live-objects.py91
1 files changed, 91 insertions, 0 deletions
diff --git a/tools/tcmalloc/print-live-objects.py b/tools/tcmalloc/print-live-objects.py
new file mode 100755
index 0000000..9886fd1
--- /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)