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

Side by Side Diff: tools/find_runtime_symbols/procedure_boundaries.py

Issue 10795028: A tool for mapping runtime addresses to symbol names. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 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
M-A Ruel 2012/07/19 15:21:15 Remove the shebang on files not executable.
Dai Mikurube (NOT FULLTIME) 2012/07/20 04:32:39 Done.
2
3 import bisect
4 import os
5 import re
6 import sys
7
8 class ParsingException(Exception):
9 def __init__(self, value):
M-A Ruel 2012/07/19 15:21:15 The __init__ is not strictly necessary. You can us
Dai Mikurube (NOT FULLTIME) 2012/07/20 04:32:39 Thanks. Done it.
10 self.value = value
11 def __str__(self):
12 return repr(self.value)
13
14
15 class ProcedureBoundary(object):
16 def __init__(self, start, end, name):
17 self.start = start
18 self.end = end
19 self.name = name
20
21
22 class ProcedureBoundaryTable(object):
23 def __init__(self):
24 self.sorted_value_list = []
25 self.dictionary = {}
26 self.sorted = True
27
28 def append(self, entry):
29 if self.sorted_value_list:
30 if self.sorted_value_list[-1] > entry.start:
31 self.sorted = False
32 elif self.sorted_value_list[-1] == entry.start:
33 return
34 self.sorted_value_list.append(entry.start)
35 self.dictionary[entry.start] = entry
36
37 def find_procedure(self, address):
38 if not self.sorted:
39 self.sorted_value_list.sort()
40 self.sorted = True
41 found_index = bisect.bisect_left(self.sorted_value_list, address)
42 found_start_address = self.sorted_value_list[found_index - 1]
43 return self.dictionary[found_start_address]
44
45
46 _ARGUMENT_TYPE_PATTERN = re.compile('\([^()]*\)(\s*const)?')
47 _TEMPLATE_ARGUMENT_PATTERN = re.compile('<[^<>]*>')
48 _LEADING_TYPE_PATTERN = re.compile('^.*\s+(\w+::)')
49
50 def _get_short_function_name(function):
51 while True:
52 function, number = _ARGUMENT_TYPE_PATTERN.subn('', function)
M-A Ruel 2012/07/19 15:21:15 A constant is not strictly necessary when used onl
Dai Mikurube (NOT FULLTIME) 2012/07/20 04:32:39 As far as I remember, only one regexp is kept in m
53 if number == 0:
M-A Ruel 2012/07/19 15:21:15 if not number: unless you want to differentiate wi
Dai Mikurube (NOT FULLTIME) 2012/07/20 04:32:39 Done.
54 break
55 while True:
56 function, number = _TEMPLATE_ARGUMENT_PATTERN.subn('', function)
57 if number == 0:
58 break
59 function = _LEADING_TYPE_PATTERN.sub('\g<1>', function)
60 return function
61
62
63 def get_procedure_boundaries_from_nm_bsd(FILE, mangled=False):
64 """Gets procedure boundaries from a result of nm -n --format bsd.
65
66 Args:
67 FILE: A file object containing a result of nm. It must be sorted and
68 in BSD-style. (Use "[eu-]nm -n --format bsd")
69
70 Returns:
71 A result ProcedureBoundaryTable object.
72 """
73 symbol_table = ProcedureBoundaryTable()
74
75 last_start = 0;
76 routine = '';
M-A Ruel 2012/07/19 15:21:15 ; ?
Dai Mikurube (NOT FULLTIME) 2012/07/20 04:32:39 Wow, removed them. (I was translating this code f
77
78 for line in FILE:
79 symbol_info = line.rstrip().split(None, 2)
80 if len(symbol_info) == 3:
81 if len(symbol_info[0]) == 1:
82 symbol_info = line.split(None, 1)
83 (sym_type, this_routine) = symbol_info
84 sym_value = ''
85 else:
86 (sym_value, sym_type, this_routine) = symbol_info
87 elif len(symbol_info) == 2:
88 if len(symbol_info[0]) == 1:
89 (sym_type, this_routine) = symbol_info
90 sym_value = ''
91 elif len(symbol_info[0]) == 8 or len(symbol_info[0]) == 16:
92 (sym_value, this_routine) = symbol_info
93 sym_type = ' '
94 else:
95 raise ParsingException('Invalid output 1 from (eu-)nm.')
96 else:
97 raise ParsingException('Invalid output 2 from (eu-)nm.')
98
99 if sym_value == '':
100 continue
101
102 start_val = int(sym_value, 16)
103
104 # It's possible for two symbols to share the same address, if
105 # one is a zero-length variable (like __start_google_malloc) or
106 # one symbol is a weak alias to another (like __libc_malloc).
107 # In such cases, we want to ignore all values except for the
108 # actual symbol, which in nm-speak has type "T". The logic
109 # below does this, though it's a bit tricky: what happens when
110 # we have a series of lines with the same address, is the first
111 # one gets queued up to be processed. However, it won't
112 # *actually* be processed until later, when we read a line with
113 # a different address. That means that as long as we're reading
114 # lines with the same address, we have a chance to replace that
115 # item in the queue, which we do whenever we see a 'T' entry --
116 # that is, a line with type 'T'. If we never see a 'T' entry,
117 # we'll just go ahead and process the first entry (which never
118 # got touched in the queue), and ignore the others.
119 if start_val == last_start and (sym_type == 't' or sym_type == 'T'):
120 # We are the 'T' symbol at this address, replace previous symbol.
121 routine = this_routine
122 continue
123 elif start_val == last_start:
124 # We're not the 'T' symbol at this address, so ignore us.
125 continue
126
127 # Tag this routine with the starting address in case the image
128 # has multiple occurrences of this routine. We use a syntax
129 # that resembles template paramters that are automatically
130 # stripped out by ShortFunctionName()
131 this_routine += "<%016x>" % start_val;
132
133 if not mangled:
134 routine = _get_short_function_name(routine)
135 symbol_table.append(ProcedureBoundary(last_start, start_val, routine))
136
137 last_start = start_val
138 routine = this_routine
139
140 if not mangled:
141 routine = _get_short_function_name(routine)
142 symbol_table.append(ProcedureBoundary(last_start, last_start, routine))
143 return symbol_table
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698