Skip to content

Commit

Permalink
Revert "Better handling of methods in multiple sections."
Browse files Browse the repository at this point in the history
This reverts commit b1163a7.

Cr-Commit-Position: refs/heads/master@{#332666}
  • Loading branch information
Jason Kersey committed Jun 3, 2015
1 parent 2894712 commit a57cac2
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 124 deletions.
9 changes: 1 addition & 8 deletions tools/cygprofile/check_orderfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@

import logging
import optparse
import os
import sys

import cyglog_to_orderfile
import cygprofile_utils
import patch_orderfile
import symbol_extractor
Expand Down Expand Up @@ -79,12 +77,7 @@ def main():
(binary_filename, orderfile_filename) = argv[1:]

symbol_extractor.SetArchitecture(options.arch)
obj_dir = cygprofile_utils.GetObjDir(binary_filename)
symbol_to_sections_map = \
cyglog_to_orderfile.GetSymbolToSectionsMapFromObjectFiles(obj_dir)
section_to_symbols_map = patch_orderfile.InvertMapping(symbol_to_sections_map)
symbols = patch_orderfile.GetSymbolsFromOrderfile(orderfile_filename,
section_to_symbols_map)
symbols = patch_orderfile.GetSymbolsFromOrderfile(orderfile_filename)
symbol_infos = symbol_extractor.SymbolInfosFromBinary(binary_filename)
# Missing symbols is not an error since some of them can be eliminated through
# inlining.
Expand Down
56 changes: 23 additions & 33 deletions tools/cygprofile/cyglog_to_orderfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
import multiprocessing
import optparse
import os
import re
import tempfile
import string
import sys
import tempfile

import cygprofile_utils
import symbol_extractor
Expand Down Expand Up @@ -126,40 +125,31 @@ def _AllSymbolInfos(object_filenames):
return result


def GetSymbolToSectionsMapFromObjectFiles(obj_dir):
"""Creates a mapping from symbol to linker section names by scanning all
the object files.
def _GetSymbolToSectionMapFromObjectFiles(obj_dir):
""" Creates a mapping from symbol to linker section name by scanning all
the object files.
"""
object_files = _GetObjectFileNames(obj_dir)
symbol_to_sections_map = {}
symbol_to_section_map = {}
symbol_warnings = cygprofile_utils.WarningCollector(300)
symbol_infos = _AllSymbolInfos(object_files)
for symbol_info in symbol_infos:
symbol = symbol_info.name
if symbol.startswith('.LTHUNK'):
continue
section = symbol_info.section
if ((symbol in symbol_to_sections_map) and
(not symbol_info.section in symbol_to_sections_map[symbol])):
symbol_to_sections_map[symbol].append(section)
# Check if this is the understood case of constructor/destructor
# signatures. G++ emits up to three types of constructor/destructors:
# complete, base, and allocating. If they're all the same they'll
# get folded together.
if not (re.match('[CD][123]E', symbol) and
(symbol_extractor.Demangle(symbol) ==
symbol_extractor.Demangle(symbol_to_sections_map[symbol][0]
.lstrip('.text.')))):
symbol_warnings.Write('Symbol ' + symbol +
' in conflicting sections ' +
', '.join(symbol_to_sections_map[symbol]))
if ((symbol in symbol_to_section_map) and
(symbol_to_section_map[symbol] != symbol_info.section)):
symbol_warnings.Write('Symbol ' + symbol +
' in conflicting sections ' + section +
' and ' + symbol_to_section_map[symbol])
elif not section.startswith('.text'):
symbol_warnings.Write('Symbol ' + symbol +
' in incorrect section ' + section)
else:
symbol_to_sections_map[symbol] = [ section ]
symbol_to_section_map[symbol] = section
symbol_warnings.WriteEnd('bad sections')
return symbol_to_sections_map
return symbol_to_section_map


def _WarnAboutDuplicates(offsets):
Expand All @@ -182,14 +172,14 @@ def _WarnAboutDuplicates(offsets):
return ok


def _OutputOrderfile(offsets, offset_to_symbol_infos, symbol_to_sections_map,
def _OutputOrderfile(offsets, offset_to_symbol_infos, symbol_to_section_map,
output_file):
"""Outputs the orderfile to output_file.
Args:
offsets: Iterable of offsets to match to section names
offset_to_symbol_infos: {offset: [SymbolInfo]}
symbol_to_sections_map: {name: [section1, section2]}
symbol_to_section_map: {name: section}
output_file: file-like object to write the results to
"""
success = True
Expand All @@ -200,12 +190,11 @@ def _OutputOrderfile(offsets, offset_to_symbol_infos, symbol_to_sections_map,
try:
symbol_infos = _FindSymbolInfosAtOffset(offset_to_symbol_infos, offset)
for symbol_info in symbol_infos:
if symbol_info.name in symbol_to_sections_map:
sections = symbol_to_sections_map[symbol_info.name]
for section in sections:
if not section in output_sections:
output_file.write(section + '\n')
output_sections.add(section)
if symbol_info.name in symbol_to_section_map:
section = symbol_to_section_map[symbol_info.name]
if not section in output_sections:
output_file.write(section + '\n')
output_sections.add(section)
else:
unknown_symbol_warnings.Write(
'No known section for symbol ' + symbol_info.name)
Expand Down Expand Up @@ -233,14 +222,15 @@ def main():
(log_filename, lib_filename, output_filename) = argv[1:]
symbol_extractor.SetArchitecture(options.arch)

obj_dir = cygprofile_utils.GetObjDir(lib_filename)
obj_dir = os.path.abspath(os.path.join(
os.path.dirname(lib_filename), '../obj'))

log_file_lines = map(string.rstrip, open(log_filename).readlines())
offsets = _ParseLogLines(log_file_lines)
_WarnAboutDuplicates(offsets)

offset_to_symbol_infos = _GroupLibrarySymbolInfosByOffset(lib_filename)
symbol_to_sections_map = GetSymbolToSectionsMapFromObjectFiles(obj_dir)
symbol_to_section_map = _GetSymbolToSectionMapFromObjectFiles(obj_dir)

success = False
temp_filename = None
Expand All @@ -249,7 +239,7 @@ def main():
(fd, temp_filename) = tempfile.mkstemp(dir=os.path.dirname(output_filename))
output_file = os.fdopen(fd, 'w')
ok = _OutputOrderfile(
offsets, offset_to_symbol_infos, symbol_to_sections_map, output_file)
offsets, offset_to_symbol_infos, symbol_to_section_map, output_file)
output_file.close()
os.rename(temp_filename, output_filename)
temp_filename = None
Expand Down
13 changes: 6 additions & 7 deletions tools/cygprofile/cyglog_to_orderfile_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,15 @@ def write(self, data):
name='Symbol3', offset=0x16, size=0x13, section='dummy'),
symbol_extractor.SymbolInfo(
name='Symbol32', offset=0x16, size=0x13, section='dummy'),]}
symbol_to_sections_map = {
'Symbol': ['.text.Symbol'],
'Symbol2': ['.text.Symbol2', '.text.hot.Symbol2'],
'Symbol3': ['.text.Symbol3'],
'Symbol32': ['.text.Symbol32']}
symbol_to_section_map = {
'Symbol': '.text.Symbol',
'Symbol2': '.text.Symbol2',
'Symbol3': '.text.Symbol3',
'Symbol32': '.text.Symbol32'}
fake_output = FakeOutputFile()
cyglog_to_orderfile._OutputOrderfile(
offsets, offset_to_symbol_infos, symbol_to_sections_map, fake_output)
offsets, offset_to_symbol_infos, symbol_to_section_map, fake_output)
expected = """.text.Symbol2
.text.hot.Symbol2
.text.Symbol3
.text.Symbol32
"""
Expand Down
6 changes: 0 additions & 6 deletions tools/cygprofile/cygprofile_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,3 @@ def DetectArchitecture(default='arm'):
return match.group(1)
else:
return default


def GetObjDir(libchrome):
"""Get the path to the obj directory corresponding to the given libchrome."""
return os.path.abspath(os.path.join(
os.path.dirname(libchrome), '../obj'))
81 changes: 22 additions & 59 deletions tools/cygprofile/patch_orderfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import optparse
import sys

import cyglog_to_orderfile
import cygprofile_utils
import symbol_extractor

Expand Down Expand Up @@ -94,33 +93,19 @@ def _StripPrefix(line):
Returns:
The symbol, SymbolName in the example above.
"""
line = line.rstrip('\n')
for prefix in _PREFIXES:
if line.startswith(prefix):
return line[len(prefix):]
return line # Unprefixed case


def _SectionNameToSymbols(section_name, section_to_symbols_map):
"""Returns all symbols which could be referred to by section_name."""
if section_name in section_to_symbols_map:
for symbol in section_to_symbols_map[section_name]:
yield symbol
else:
section_name = _StripPrefix(section_name)
name = _RemoveClone(section_name)
if name != '' and name != '*' and name != '.text':
yield section_name


def _GetSymbolsFromStream(lines, section_to_symbols_map):
"""Gets the symbols from an iterable of lines.
def _GetSymbolsFromStream(lines):
"""Get the symbols from an iterable of lines.
Filters out wildcards and lines which do not correspond to symbols.
Args:
lines: iterable of lines from an orderfile.
section_to_symbols_map: The mapping from section to symbol name. If a
section isn't in the mapping, it is assumed the
section name is the prefixed symbol name.
Returns:
Same as GetSymbolsFromOrderfile
Expand All @@ -129,29 +114,27 @@ def _GetSymbolsFromStream(lines, section_to_symbols_map):
symbols = []
unique_symbols = set()
for line in lines:
line = line.rstrip('\n')
for symbol in _SectionNameToSymbols(line, section_to_symbols_map):
if not symbol in unique_symbols:
symbols.append(symbol)
unique_symbols.add(symbol)
line = _StripPrefix(line)
name = _RemoveClone(line)
if name == '' or name == '*' or name == '.text':
continue
if not line in unique_symbols:
symbols.append(line)
unique_symbols.add(line)
return symbols


def GetSymbolsFromOrderfile(filename, section_to_symbols_map):
def GetSymbolsFromOrderfile(filename):
"""Return the symbols from an orderfile.
Args:
filename: The name of the orderfile.
section_to_symbols_map: The mapping from section to symbol name. If a
section isn't in the mapping, it is assumed the
section name is the prefixed symbol name.
Returns:
A list of symbol names.
"""
with open(filename, 'r') as f:
return _GetSymbolsFromStream(f.xreadlines(), section_to_symbols_map)

return _GetSymbolsFromStream(f.xreadlines())

def _SymbolsWithSameOffset(profiled_symbol, name_to_symbol_info,
offset_to_symbol_info):
Expand Down Expand Up @@ -211,30 +194,15 @@ def _ExpandSymbols(profiled_symbols, name_to_symbol_infos,
return all_symbols


def _PrintSymbolsAsSections(symbol_names, symbol_to_sections_map, output_file):
def _PrintSymbolsWithPrefixes(symbol_names, output_file):
"""For each symbol, outputs it to output_file with the prefixes."""
unique_outputs = set()
for name in symbol_names:
if name in symbol_to_sections_map:
for linker_section in symbol_to_sections_map[name]:
if not linker_section in unique_outputs:
output_file.write(linker_section + '\n')
unique_outputs.add(linker_section)
else:
for prefix in _PREFIXES:
linker_section = prefix + name
if not linker_section in unique_outputs:
output_file.write(linker_section + '\n')
unique_outputs.add(linker_section)


def InvertMapping(x_to_ys):
"""Given a map x -> [y1, y2...] return inverse mapping y->[x1, x2...]."""
y_to_xs = {}
for x, ys in x_to_ys.items():
for y in ys:
y_to_xs.setdefault(y, []).append(x)
return y_to_xs
for prefix in _PREFIXES:
linker_section = prefix + name
if not linker_section in unique_outputs:
output_file.write(linker_section + '\n')
unique_outputs.add(linker_section)


def main(argv):
Expand All @@ -254,15 +222,10 @@ def main(argv):
symbol_extractor.SetArchitecture(options.arch)
(offset_to_symbol_infos, name_to_symbol_infos) = _GroupSymbolInfosFromBinary(
binary_filename)
obj_dir = cygprofile_utils.GetObjDir(binary_filename)
symbol_to_sections_map = \
cyglog_to_orderfile.GetSymbolToSectionsMapFromObjectFiles(obj_dir)
section_to_symbols_map = InvertMapping(symbol_to_sections_map)
profiled_symbols = GetSymbolsFromOrderfile(orderfile_filename,
section_to_symbols_map)
expanded_symbols = _ExpandSymbols(profiled_symbols,
name_to_symbol_infos, offset_to_symbol_infos)
_PrintSymbolsAsSections(expanded_symbols, symbol_to_sections_map, sys.stdout)
profiled_symbols = GetSymbolsFromOrderfile(orderfile_filename)
expanded_symbols = _ExpandSymbols(
profiled_symbols, name_to_symbol_infos, offset_to_symbol_infos)
_PrintSymbolsWithPrefixes(expanded_symbols, sys.stdout)
# The following is needed otherwise Gold only applies a partial sort.
print '.text' # gets methods not in a section, such as assembly
print '.text.*' # gets everything else
Expand Down
10 changes: 3 additions & 7 deletions tools/cygprofile/patch_orderfile_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,24 +64,20 @@ def testExpandSymbols(self):
self.assertEquals(symbol_names[1], symbol_name2)
self.assertEquals(symbol_names[2], "symbolThatShouldntMatch")

def testPrintSymbolsAsSections(self):
def testPrintSymbolWithPrefixes(self):
class FakeOutputFile(object):
def __init__(self):
self.output = ''
def write(self, s):
self.output = self.output + s
test_symbol = "dummySymbol"
test_symbol2 = "otherSymbol"
symbol_names = [test_symbol, test_symbol2]
symbol_names = [test_symbol]
fake_output = FakeOutputFile()
patch_orderfile._PrintSymbolsAsSections(symbol_names,
{test_symbol2: ['section1', 'section2']}, fake_output)
patch_orderfile._PrintSymbolsWithPrefixes(symbol_names, fake_output)
expected_output = """.text.startup.dummySymbol
.text.hot.dummySymbol
.text.unlikely.dummySymbol
.text.dummySymbol
section1
section2
"""
self.assertEquals(fake_output.output, expected_output)

Expand Down
4 changes: 0 additions & 4 deletions tools/cygprofile/symbol_extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,3 @@ def CreateNameToSymbolInfo(symbol_infos):
','.join([hex(x.offset) for x in infos])))
warnings.WriteEnd('symbols at multiple offsets.')
return symbol_infos_by_name

def DemangleSymbol(mangled_symbol):
"""Return the demangled form of mangled_symbol."""
return symbol.CallCppFilt(mangled_symbol)

0 comments on commit a57cac2

Please sign in to comment.