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

Side by Side Diff: tools/cygprofile/symbol_extractor.py

Issue 886563002: Switch from nm to objdump for the cygprofile tools. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 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
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright 2015 The Chromium Authors. All rights reserved. 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 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Utilities to get and manipulate symbols from a binary.""" 6 """Utilities to get and manipulate symbols from a binary."""
7 7
8 import collections 8 import collections
9 import os 9 import os
10 import re 10 import re
11 import subprocess 11 import subprocess
12 import sys 12 import sys
13 13
14 sys.path.insert( 14 sys.path.insert(
15 0, os.path.join(sys.path[0], '..', '..', 'third_party', 'android_platform', 15 0, os.path.join(sys.path[0], '..', '..', 'third_party', 'android_platform',
16 'development', 'scripts')) 16 'development', 'scripts'))
17 import symbol 17 import symbol
18 18
19 19
20 # TODO(lizeb): Change symbol.ARCH to the proper value when "arm" is no longer 20 # TODO(lizeb): Change symbol.ARCH to the proper value when "arm" is no longer
21 # the only possible value. 21 # the only possible value.
22 _NM_BINARY = symbol.ToolPath('nm') 22 _OBJDUMP_BINARY = symbol.ToolPath('objdump')
pasko 2015/01/28 18:55:37 The phrase 'This is required, as nm doesn't provid
Benoit L 2015/01/29 10:02:01 Yes, the goal is to have only one way to parse obj
pasko 2015/01/29 12:24:42 Sounds good, but please either remove the 'require
23 23
24 24
25 SymbolInfo = collections.namedtuple('SymbolInfo', ('name', 'offset', 'size')) 25 SymbolInfo = collections.namedtuple('SymbolInfo', ('name', 'offset', 'size',
26 'section'))
26 27
27 28
28 def FromNmLine(line): 29 def _FromObjdumpLine(line):
29 """Create a SymbolInfo by parsing a properly formatted nm output line. 30 """Create a SymbolInfo by parsing a properly formatted objdump output line.
30 31
31 Args: 32 Args:
32 line: line from nm 33 line: line from objdump
33 34
34 Returns: 35 Returns:
35 An instance of SymbolInfo if the line represents a symbol, None otherwise. 36 An instance of SymbolInfo if the line represents a symbol, None otherwise.
36 """ 37 """
37 # We are interested in two types of lines: 38 # All of the symbol lines we care about are in the form
38 # This: 39 # 0000000000 g F .text.foo 000000000 [.hidden] foo
39 # 00210d59 00000002 t _ZN34BrowserPluginHostMsg_Attach_ParamsD2Ev 40 # where g (global) might also be l (local) or w (weak).
40 # offset size <symbol_type> symbol_name 41 parts = line.split()
41 # And that: 42 if len(parts) < 6 or parts[2] != 'F':
42 # 0070ee8c T WebRtcSpl_ComplexBitReverse
43 # In the second case we don't have a size, so use -1 as a sentinel
44 if not re.search(' (t|W|T) ', line):
45 return None 43 return None
46 parts = line.split() 44 offset = int(parts[0], 16)
pasko 2015/01/29 12:24:42 To prevent loosing information without knowing let
47 if len(parts) == 4: 45 section = parts[3]
48 return SymbolInfo( 46 size = int(parts[4], 16)
49 offset=int(parts[0], 16), size=int(parts[1], 16), name=parts[3]) 47 name = parts[-1]
50 elif len(parts) == 3: 48 return SymbolInfo(name=name, offset=offset, section=section, size=size)
51 return SymbolInfo(
52 offset=int(parts[0], 16), size=-1, name=parts[2])
53 else:
54 return None
55 49
56 50
57 def SymbolInfosFromStream(nm_lines): 51 def _SymbolInfosFromStream(objdump_lines):
58 """Parses the output of nm, and get all the symbols from a binary. 52 """Parses the output of objdump, and get all the symbols from a binary.
59 53
60 Args: 54 Args:
61 nm_lines: An iterable of lines 55 objdump_lines: An iterable of lines
62 56
63 Returns: 57 Returns:
64 A list of SymbolInfo. 58 A list of SymbolInfo.
65 """ 59 """
66 # TODO(lizeb): Consider switching to objdump to simplify parsing. 60 # TODO(lizeb): Consider switching to objdump to simplify parsing.
pasko 2015/01/28 18:55:37 this change is implementing the TODO (!)
Benoit L 2015/01/29 10:02:01 Arg, indeed. It is so rare to remove TODOs, it wou
pasko 2015/01/29 12:24:42 the blame is on me for nagging to add this TODO, t
67 symbol_infos = [] 61 symbol_infos = []
68 for line in nm_lines: 62 for line in objdump_lines:
69 symbol_info = FromNmLine(line) 63 symbol_info = _FromObjdumpLine(line)
70 if symbol_info is not None: 64 if symbol_info is not None:
71 symbol_infos.append(symbol_info) 65 symbol_infos.append(symbol_info)
72 return symbol_infos 66 return symbol_infos
73 67
74 68
75 def SymbolInfosFromBinary(binary_filename): 69 def SymbolInfosFromBinary(binary_filename):
76 """Runs nm to get all the symbols from a binary. 70 """Runs objdump to get all the symbols from a binary.
77 71
78 Args: 72 Args:
79 binary_filename: path to the binary. 73 binary_filename: path to the binary.
80 74
81 Returns: 75 Returns:
82 A list of SymbolInfo from the binary. 76 A list of SymbolInfo from the binary.
83 """ 77 """
84 command = (_NM_BINARY, '-S', '-n', binary_filename) 78 command = (_OBJDUMP_BINARY, '-t', '-w', binary_filename)
85 p = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE) 79 p = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE)
86 try: 80 try:
87 result = SymbolInfosFromStream(p.stdout) 81 result = _SymbolInfosFromStream(p.stdout)
88 return result 82 return result
89 finally: 83 finally:
90 p.wait() 84 p.wait()
91 85
92 86
93 def GroupSymbolInfosByOffset(symbol_infos): 87 def GroupSymbolInfosByOffset(symbol_infos):
94 """Create a dict {offset: [symbol_info1, ...], ...}. 88 """Create a dict {offset: [symbol_info1, ...], ...}.
95 89
96 As several symbols can be at the same offset, this is a 1-to-many 90 As several symbols can be at the same offset, this is a 1-to-many
97 relationship. 91 relationship.
(...skipping 13 matching lines...) Expand all
111 def CreateNameToSymbolInfo(symbol_infos): 105 def CreateNameToSymbolInfo(symbol_infos):
112 """Create a dict {name: symbol_info, ...}. 106 """Create a dict {name: symbol_info, ...}.
113 107
114 Args: 108 Args:
115 symbol_infos: iterable of SymbolInfo instances 109 symbol_infos: iterable of SymbolInfo instances
116 110
117 Returns: 111 Returns:
118 a dict {name: symbol_info, ...} 112 a dict {name: symbol_info, ...}
119 """ 113 """
120 return {symbol_info.name: symbol_info for symbol_info in symbol_infos} 114 return {symbol_info.name: symbol_info for symbol_info in symbol_infos}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698