17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Copyright 2013 The Chromium Authors. All rights reserved. 27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Use of this source code is governed by a BSD-style license that can be 37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# found in the LICENSE file. 47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport logging 67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport os 77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom lib.symbol import FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS, TYPEINFO_SYMBOLS 97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 117dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochLOGGER = logging.getLogger('dmprof') 127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass Bucket(object): 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch """Represents a bucket, which is a unit of memory block classification.""" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def __init__(self, stacktrace, allocator_type, typeinfo, typeinfo_name): 187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._stacktrace = stacktrace 197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._allocator_type = allocator_type 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._typeinfo = typeinfo 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._typeinfo_name = typeinfo_name 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_stackfunction = stacktrace 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_joined_stackfunction = '' 257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_stacksourcefile = stacktrace 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_joined_stacksourcefile = '' 277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_typeinfo = typeinfo_name 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self.component_cache = '' 307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def __str__(self): 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result = [] 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result.append(self._allocator_type) 347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if self._symbolized_typeinfo == 'no typeinfo': 357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result.append('tno_typeinfo') 367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch else: 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result.append('t' + self._symbolized_typeinfo) 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result.append('n' + self._typeinfo_name) 397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch result.extend(['%s(@%s)' % (function, sourcefile) 407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for function, sourcefile 417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch in zip(self._symbolized_stackfunction, 427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_stacksourcefile)]) 437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return ' '.join(result) 447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def symbolize(self, symbol_mapping_cache): 467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch """Makes a symbolized stacktrace and typeinfo with |symbol_mapping_cache|. 477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Args: 497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch symbol_mapping_cache: A SymbolMappingCache object. 507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch """ 517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch # TODO(dmikurube): Fill explicitly with numbers if symbol not found. 527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_stackfunction = [ 537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch symbol_mapping_cache.lookup(FUNCTION_SYMBOLS, address) 547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for address in self._stacktrace] 557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_joined_stackfunction = ' '.join( 567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_stackfunction) 577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_stacksourcefile = [ 587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch symbol_mapping_cache.lookup(SOURCEFILE_SYMBOLS, address) 597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for address in self._stacktrace] 607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_joined_stacksourcefile = ' '.join( 617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_stacksourcefile) 627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if not self._typeinfo: 637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_typeinfo = 'no typeinfo' 647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch else: 657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_typeinfo = symbol_mapping_cache.lookup( 667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch TYPEINFO_SYMBOLS, self._typeinfo) 677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if not self._symbolized_typeinfo: 687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._symbolized_typeinfo = 'no typeinfo' 697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def clear_component_cache(self): 717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self.component_cache = '' 727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @property 747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def stacktrace(self): 757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._stacktrace 767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @property 787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def allocator_type(self): 797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._allocator_type 807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @property 827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def typeinfo(self): 837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._typeinfo 847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @property 867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def typeinfo_name(self): 877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._typeinfo_name 887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @property 907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def symbolized_stackfunction(self): 917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._symbolized_stackfunction 927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @property 947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def symbolized_joined_stackfunction(self): 957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._symbolized_joined_stackfunction 967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @property 987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def symbolized_stacksourcefile(self): 997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._symbolized_stacksourcefile 1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @property 1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def symbolized_joined_stacksourcefile(self): 1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._symbolized_joined_stacksourcefile 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch @property 1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def symbolized_typeinfo(self): 1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._symbolized_typeinfo 1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass BucketSet(object): 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch """Represents a set of bucket.""" 1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def __init__(self): 1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._buckets = {} 1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._code_addresses = set() 1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._typeinfo_addresses = set() 1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def load(self, prefix): 1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch """Loads all related bucket files. 1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Args: 1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch prefix: A prefix string for bucket file names. 1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch """ 1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch LOGGER.info('Loading bucket files.') 1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch n = 0 1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch skipped = 0 1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch while True: 1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch path = '%s.%04d.buckets' % (prefix, n) 1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if not os.path.exists(path) or not os.stat(path).st_size: 1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if skipped > 10: 1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break 1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch n += 1 1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch skipped += 1 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch continue 1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch LOGGER.info(' %s' % path) 1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch with open(path, 'r') as f: 1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._load_file(f) 1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch n += 1 1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch skipped = 0 1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def _load_file(self, bucket_f): 1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for line in bucket_f: 1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch words = line.split() 1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch typeinfo = None 1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch typeinfo_name = '' 1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stacktrace_begin = 2 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for index, word in enumerate(words): 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if index < 2: 1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch continue 1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if word[0] == 't': 1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch typeinfo = int(word[1:], 16) 1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._typeinfo_addresses.add(typeinfo) 1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch elif word[0] == 'n': 1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch typeinfo_name = word[1:] 1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch else: 1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stacktrace_begin = index 1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break 1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stacktrace = [int(address, 16) for address in words[stacktrace_begin:]] 1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for frame in stacktrace: 1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._code_addresses.add(frame) 1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self._buckets[int(words[0])] = Bucket( 1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stacktrace, words[1], typeinfo, typeinfo_name) 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def __iter__(self): 1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for bucket_id, bucket_content in self._buckets.iteritems(): 1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch yield bucket_id, bucket_content 1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def __getitem__(self, bucket_id): 1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._buckets[bucket_id] 1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def get(self, bucket_id): 1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return self._buckets.get(bucket_id) 1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def symbolize(self, symbol_mapping_cache): 1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for bucket_content in self._buckets.itervalues(): 1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bucket_content.symbolize(symbol_mapping_cache) 1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def clear_component_cache(self): 1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for bucket_content in self._buckets.itervalues(): 1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bucket_content.clear_component_cache() 1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch def iter_addresses(self, symbol_type): 1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if symbol_type in [FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS]: 1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for function in self._code_addresses: 1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch yield function 1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch else: 1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for function in self._typeinfo_addresses: 1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch yield function 189