Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(631)

Side by Side Diff: tools/android/memdump/memsymbols.py

Issue 19466005: Adding extended report to memdump with resident pages bit reporting. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressing nits. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file
6
7 import base64
8 import os
9 import sys
10 import re
11
12 from optparse import OptionParser
13
14 """Extracts the list of resident symbols of a library loaded in a process.
15
16 This scripts combines the extended output of memdump for a given process
17 (obtained through memdump -x PID) and the symbol table of a .so loaded in that
18 process (obtained through nm -C lib-with-symbols.so), filtering out only those
19 symbols that, at the time of the snapshot, were resident in memory (that are,
20 the symbols which start address belongs to a mapped page of the .so which was
21 resident at the time of the snapshot).
22 The aim is to perform a "code coverage"-like profiling of a binary, intersecting
23 run-time information (list of resident pages) and debug symbols.
24 """
25
26 _PAGE_SIZE = 4096
27
bulach 2013/07/23 08:10:58 nit: two \n between top levels, i.e., add another
Primiano Tucci (use gerrit) 2013/07/23 08:54:00 Done.
28 def _TestBit(word, bit):
29 assert(bit >= 0 and bit < 8)
30 return not not ((word >> bit) & 1)
31
32 def _HexAddr(addr):
33 return hex(addr)[2:].zfill(8)
34
35 def _GetResidentPagesSet(memdump_fh, lib_name, verbose):
36 """Parses the memdump output and extracts the resident page set for lib_name.
37 Args:
38 memdump_fh: Handler of a memdump output file.
39 lib_name: A string containing the name of the library.so to be matched.
40 verbose: Print a verbose header for each mapping matched.
41
42 Returns:
43 A set of resident pages (the key is the page index) for all the
44 mappings matching .*lib_name.
45 """
46 resident_pages = set()
47 MAP_RX = re.compile(
48 r'^([0-9a-f]+)-([0-9a-f]+) ([\w-]+) ([0-9a-f]+) .* "(.*)" \[(.*)\]$')
49 for line in memdump_fh:
50 line = line.rstrip('\r\n')
51 if line.startswith('[ PID'):
52 continue
53
54 r = MAP_RX.match(line)
55 if not r:
56 sys.stderr.write('Skipping %s from %s\n' % (line, memdump_file))
57 continue
58
59 map_start = int(r.group(1), 16)
60 map_end = int(r.group(2), 16)
61 prot = r.group(3)
62 offset = int(r.group(4), 16)
63 assert(offset % _PAGE_SIZE == 0)
64 lib = r.group(5)
65 enc_bitmap = r.group(6)
66
67 if not lib.endswith(lib_name):
68 continue
69
70 bitmap = base64.b64decode(enc_bitmap)
71 map_pages_count = (map_end - map_start + 1) / _PAGE_SIZE
72 bitmap_pages_count = len(bitmap) * 8
73
74 if verbose:
75 print 'Found %s: mapped %d pages in mode %s @ offset %s.' % (
76 lib, map_pages_count, prot, _HexAddr(offset))
77 print ' Map range in the process VA: [%s - %s]. Len: %s' % (
78 _HexAddr(map_start),
79 _HexAddr(map_end),
80 _HexAddr(map_pages_count * _PAGE_SIZE))
81 print ' Corresponding addresses in the binary: [%s - %s]. Len: %s' % (
82 _HexAddr(offset),
83 _HexAddr(offset + map_end - map_start),
84 _HexAddr(map_pages_count * _PAGE_SIZE))
85 print ' Bitmap: %d pages' % bitmap_pages_count
86 print ''
87
88 assert(bitmap_pages_count >= map_pages_count)
89 for i in xrange(map_pages_count):
90 bitmap_idx = i / 8
91 bitmap_off = i % 8
92 if (bitmap_idx < len(bitmap) and
93 _TestBit(ord(bitmap[bitmap_idx]), bitmap_off)):
94 resident_pages.add(offset / _PAGE_SIZE + i)
95 return resident_pages
96
97
98 def main(argv):
99 NM_RX = re.compile(r'^([0-9a-f]+)\s+.*$')
100
101 parser = OptionParser()
102 parser.add_option("-r", "--reverse",
103 action="store_true", dest="reverse", default=False,
104 help="Print out non present symbols")
105 parser.add_option("-v", "--verbose",
106 action="store_true", dest="verbose", default=False,
107 help="Print out verbose debug information.")
108
109 (options, args) = parser.parse_args()
110
111 if len(args) != 3:
112 print 'Usage: %s [-v] memdump.file nm.file library.so' % (
113 os.path.basename(argv[0]))
114 return 1
115
116 memdump_file = args[0]
117 nm_file = args[1]
118 lib_name = args[2]
119
120 if memdump_file == '-':
121 memdump_fh = sys.stdin.readlines()
122 else:
123 memdump_fh = open(memdump_file, 'r')
bulach 2013/07/23 08:10:58 nit: could do .readlines() here too so that the fi
Primiano Tucci (use gerrit) 2013/07/23 08:54:00 Right! Done.
124 resident_pages = _GetResidentPagesSet(memdump_fh, lib_name, options.verbose)
125
126 # Process the nm symbol table, filtering out the resident symbols.
127 nm_fh = open(nm_file, 'r')
128 for line in nm_fh:
129 line = line.rstrip('\r\n')
130 # Skip undefined symbols (lines with no address).
131 if line.startswith(' '):
132 continue
133
134 r = NM_RX.match(line)
135 if not r:
136 sys.stderr.write('Skipping %s from %s\n' % (line, nm_file))
137 continue
138
139 sym_addr = int(r.group(1), 16)
140 sym_page = sym_addr / _PAGE_SIZE
141 last_sym_matched = (sym_page in resident_pages)
142 if (sym_page in resident_pages) != options.reverse:
143 print line
144 return 0
145
146 if __name__=='__main__':
bulach 2013/07/23 08:10:58 nit: space around ==
Primiano Tucci (use gerrit) 2013/07/23 08:54:00 Done.
147 sys.exit(main(sys.argv))
OLDNEW
« tools/android/memdump/memdump.cc ('K') | « tools/android/memdump/memdump.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698