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."""
15 0, os
.path
.join(os
.path
.dirname(__file__
), os
.pardir
, os
.pardir
,
16 'third_party', 'android_platform', 'development',
21 SymbolInfo
= collections
.namedtuple('SymbolInfo', ('name', 'offset', 'size',
24 def SetArchitecture(arch
):
25 """Set the architecture for binaries to be symbolized."""
29 def _FromObjdumpLine(line
):
30 """Create a SymbolInfo by parsing a properly formatted objdump output line.
33 line: line from objdump
36 An instance of SymbolInfo if the line represents a symbol, None otherwise.
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).
42 if len(parts
) < 6 or parts
[2] != 'F':
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)
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.
61 objdump_lines: An iterable of lines
67 for line
in objdump_lines
:
68 symbol_info
= _FromObjdumpLine(line
)
69 if symbol_info
is not None:
70 symbol_infos
.append(symbol_info
)
74 def SymbolInfosFromBinary(binary_filename
):
75 """Runs objdump to get all the symbols from a binary.
78 binary_filename: path to the binary.
81 A list of SymbolInfo from the binary.
83 command
= (symbol
.ToolPath('objdump'), '-t', '-w', binary_filename
)
84 p
= subprocess
.Popen(command
, shell
=False, stdout
=subprocess
.PIPE
)
86 result
= _SymbolInfosFromStream(p
.stdout
)
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
99 symbol_infos: iterable of SymbolInfo instances
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, ...}.
114 symbol_infos: iterable of SymbolInfo instances
117 a dict {name: symbol_info, ...}
119 return {symbol_info
.name
: symbol_info
for symbol_info
in symbol_infos
}