Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
| OLD | NEW |