diff options
author | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-11 13:21:38 +0000 |
---|---|---|
committer | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-11 13:21:38 +0000 |
commit | 8489103d9b1c879eb63ea52b0665bfeadba07c42 (patch) | |
tree | dc039c99f6109434048cade9a5b7013f9831c7a9 /tools/tcmalloc | |
parent | 4760f74799ed3e2fa53ef32a56464866b9aa3aa0 (diff) | |
download | chromium_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-x | tools/tcmalloc/print-live-objects.py | 91 |
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) |