Unregister from GCM when the only GCM app is removed
[chromium-blink-merge.git] / tools / cygprofile / symbol_extractor.py
blob81c6e66d8fbca2805ba8b7c673d12eb18a3d8d14
1 #!/usr/bin/python
2 # Copyright 2015 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Utilities to get and manipulate symbols from a binary."""
8 import collections
9 import os
10 import re
11 import subprocess
12 import sys
14 sys.path.insert(
15 0, os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
16 'third_party', 'android_platform', 'development',
17 'scripts'))
18 import symbol
21 SymbolInfo = collections.namedtuple('SymbolInfo', ('name', 'offset', 'size',
22 'section'))
24 def SetArchitecture(arch):
25 """Set the architecture for binaries to be symbolized."""
26 symbol.ARCH = arch
29 def _FromObjdumpLine(line):
30 """Create a SymbolInfo by parsing a properly formatted objdump output line.
32 Args:
33 line: line from objdump
35 Returns:
36 An instance of SymbolInfo if the line represents a symbol, None otherwise.
37 """
38 # All of the symbol lines we care about are in the form
39 # 0000000000 g F .text.foo 000000000 [.hidden] foo
40 # where g (global) might also be l (local) or w (weak).
41 parts = line.split()
42 if len(parts) < 6 or parts[2] != 'F':
43 return None
45 assert len(parts) == 6 or (len(parts) == 7 and parts[5] == '.hidden')
46 accepted_scopes = set(['g', 'l', 'w'])
47 assert parts[1] in accepted_scopes
49 offset = int(parts[0], 16)
50 section = parts[3]
51 size = int(parts[4], 16)
52 name = parts[-1].rstrip('\n')
53 assert re.match('^[a-zA-Z0-9_.]+$', name)
54 return SymbolInfo(name=name, offset=offset, section=section, size=size)
57 def _SymbolInfosFromStream(objdump_lines):
58 """Parses the output of objdump, and get all the symbols from a binary.
60 Args:
61 objdump_lines: An iterable of lines
63 Returns:
64 A list of SymbolInfo.
65 """
66 symbol_infos = []
67 for line in objdump_lines:
68 symbol_info = _FromObjdumpLine(line)
69 if symbol_info is not None:
70 symbol_infos.append(symbol_info)
71 return symbol_infos
74 def SymbolInfosFromBinary(binary_filename):
75 """Runs objdump to get all the symbols from a binary.
77 Args:
78 binary_filename: path to the binary.
80 Returns:
81 A list of SymbolInfo from the binary.
82 """
83 command = (symbol.ToolPath('objdump'), '-t', '-w', binary_filename)
84 p = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE)
85 try:
86 result = _SymbolInfosFromStream(p.stdout)
87 return result
88 finally:
89 p.wait()
92 def GroupSymbolInfosByOffset(symbol_infos):
93 """Create a dict {offset: [symbol_info1, ...], ...}.
95 As several symbols can be at the same offset, this is a 1-to-many
96 relationship.
98 Args:
99 symbol_infos: iterable of SymbolInfo instances
101 Returns:
102 a dict {offset: [symbol_info1, ...], ...}
104 offset_to_symbol_infos = collections.defaultdict(list)
105 for symbol_info in symbol_infos:
106 offset_to_symbol_infos[symbol_info.offset].append(symbol_info)
107 return dict(offset_to_symbol_infos)
110 def CreateNameToSymbolInfo(symbol_infos):
111 """Create a dict {name: symbol_info, ...}.
113 Args:
114 symbol_infos: iterable of SymbolInfo instances
116 Returns:
117 a dict {name: symbol_info, ...}
119 return {symbol_info.name: symbol_info for symbol_info in symbol_infos}