Commit f3e2f70f authored by Matthew Cary's avatar Matthew Cary Committed by Commit Bot

Orderfile: Correctly use symbol size to translate offset

The existing logic is not correct for code that's not word-aligned,
which happens frequently with thumb (16-bit) instruction words.

Also asserts that no symbols appear before the starting symbol. We
expect that the only symbols we have are from text, and that the
symbol placed by the linker script occurs not after any
symbol. Breaking either of the assumptions may break assumptions made
elsewhere.

Bug: 893981
Change-Id: I748c9edd0f6a5f49790b4c06d4246ee1cf8f90dc
Reviewed-on: https://chromium-review.googlesource.com/c/1329166
Commit-Queue: Matthew Cary <mattcary@chromium.org>
Reviewed-by: default avatarEgor Pasko <pasko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607524}
parent bd3e6748
...@@ -232,21 +232,21 @@ class SymbolOffsetProcessor(object): ...@@ -232,21 +232,21 @@ class SymbolOffsetProcessor(object):
""" """
dump_offset_to_symbol_info = self._GetDumpOffsetToSymbolInfo() dump_offset_to_symbol_info = self._GetDumpOffsetToSymbolInfo()
logging.info('Offset to Symbol size = %d', len(dump_offset_to_symbol_info)) logging.info('Offset to Symbol size = %d', len(dump_offset_to_symbol_info))
reached_return_addresses_not_found = 0 offsets_not_found = 0
for i in items: for i in items:
dump_offset = get(i) dump_offset = get(i)
idx = dump_offset / 4 idx = dump_offset / 2
assert dump_offset >= 0 and idx < len(dump_offset_to_symbol_info), ( assert dump_offset >= 0 and idx < len(dump_offset_to_symbol_info), (
'Dump offset out of binary range') 'Dump offset out of binary range')
symbol_info = dump_offset_to_symbol_info[idx] symbol_info = dump_offset_to_symbol_info[idx]
if symbol_info is None: if symbol_info is None:
reached_return_addresses_not_found += 1 offsets_not_found += 1
update(i, None) update(i, None)
else: else:
update(i, symbol_info.offset) update(i, symbol_info.offset)
if reached_return_addresses_not_found: if offsets_not_found:
logging.warning('%d return addresses don\'t map to any symbol', logging.warning('%d return addresses don\'t map to any symbol',
reached_return_addresses_not_found) offsets_not_found)
def _GetDumpOffsetToSymbolInfo(self): def _GetDumpOffsetToSymbolInfo(self):
"""Computes an array mapping each word in .text to a symbol. """Computes an array mapping each word in .text to a symbol.
...@@ -261,14 +261,23 @@ class SymbolOffsetProcessor(object): ...@@ -261,14 +261,23 @@ class SymbolOffsetProcessor(object):
assert len(start_syms) == 1, 'Can\'t find unique start of text symbol' assert len(start_syms) == 1, 'Can\'t find unique start of text symbol'
start_of_text = start_syms[0].offset start_of_text = start_syms[0].offset
max_offset = max(s.offset + s.size for s in self.SymbolInfos()) max_offset = max(s.offset + s.size for s in self.SymbolInfos())
text_length_words = (max_offset - start_of_text) / 4 text_length_halfwords = (max_offset - start_of_text) / 2
self._offset_to_symbol_info = [None for _ in xrange(text_length_words)] self._offset_to_symbol_info = [None] * text_length_halfwords
for s in self.SymbolInfos(): for sym in self.SymbolInfos():
offset = s.offset - start_of_text offset = sym.offset - start_of_text
if offset < 0: assert offset >= 0, ('Unexpected symbol before the start of text. '
continue 'Has the linker script broken?')
for i in range(offset / 4, (offset + s.size) / 4): # The low bit of offset may be set to indicate a thumb instruction. The
self._offset_to_symbol_info[i] = s # actual offset is still halfword aligned and so the low bit may be
# safely ignored in the division by two below.
for i in range(offset / 2, (offset + sym.size) / 2):
assert i < text_length_halfwords
other_symbol = self._offset_to_symbol_info[i]
# There may be overlapping symbols, for example fancy
# implementations for __ltsf2 and __gtsf2 (merging common tail
# code). In this case, keep the one that started first.
if other_symbol is None or other_symbol.offset > sym.offset:
self._offset_to_symbol_info[i] = sym
return self._offset_to_symbol_info return self._offset_to_symbol_info
......
...@@ -20,12 +20,12 @@ class ProcessProfilesTestCase(unittest.TestCase): ...@@ -20,12 +20,12 @@ class ProcessProfilesTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
self.symbol_0 = SimpleTestSymbol(self.START_SYMBOL, 0, 0) self.symbol_0 = SimpleTestSymbol(self.START_SYMBOL, 0, 0)
self.symbol_1 = SimpleTestSymbol('1', 8, 16) self.symbol_1 = SimpleTestSymbol('1', 6, 16)
self.symbol_2 = SimpleTestSymbol('2', 32, 8) self.symbol_2 = SimpleTestSymbol('2', 32, 8)
self.symbol_3 = SimpleTestSymbol('3', 40, 12) self.symbol_3 = SimpleTestSymbol('3', 40, 12)
self.offset_to_symbol_info = ( self.offset_to_symbol_info = (
[None, None] + [self.symbol_1] * 4 + [None] * 2 + [self.symbol_2] * 2 [None] * 3 + [self.symbol_1] * 8 + [None] * 5 + [self.symbol_2] * 4 +
+ [self.symbol_3] * 3) [self.symbol_3] * 6)
self.symbol_infos = [self.symbol_0, self.symbol_1, self.symbol_infos = [self.symbol_0, self.symbol_1,
self.symbol_2, self.symbol_3] self.symbol_2, self.symbol_3]
self._file_counter = 0 self._file_counter = 0
...@@ -37,20 +37,22 @@ class ProcessProfilesTestCase(unittest.TestCase): ...@@ -37,20 +37,22 @@ class ProcessProfilesTestCase(unittest.TestCase):
def testGetOffsetToSymbolInfo(self): def testGetOffsetToSymbolInfo(self):
processor = TestSymbolOffsetProcessor(self.symbol_infos) processor = TestSymbolOffsetProcessor(self.symbol_infos)
offset_to_symbol_info = processor._GetDumpOffsetToSymbolInfo() self.assertListEqual(self.offset_to_symbol_info,
self.assertListEqual(self.offset_to_symbol_info, offset_to_symbol_info) processor._GetDumpOffsetToSymbolInfo())
def testOverlappingSymbols(self):
symbol_1 = SimpleTestSymbol(self.START_SYMBOL, 6, 8)
symbol_2 = SimpleTestSymbol('2', 10, 10)
processor = TestSymbolOffsetProcessor([symbol_1, symbol_2])
self.assertListEqual([symbol_1] * 4 + [symbol_2] * 3,
processor._GetDumpOffsetToSymbolInfo())
def testSymbolsBeforeStart(self): def testSymbolsBeforeStart(self):
self.symbol_infos = [SimpleTestSymbol(s.name, s.offset + 8, s.size) self.symbol_infos = [SimpleTestSymbol(s.name, s.offset + 8, s.size)
for s in self.symbol_infos] for s in self.symbol_infos]
self.symbol_infos.append(SimpleTestSymbol('early', 0, 4)) self.symbol_infos.append(SimpleTestSymbol('early', 0, 4))
processor = TestSymbolOffsetProcessor(self.symbol_infos) processor = TestSymbolOffsetProcessor(self.symbol_infos)
offset_to_symbol_info = processor._GetDumpOffsetToSymbolInfo() self.assertRaises(AssertionError, processor._GetDumpOffsetToSymbolInfo)
# The 'early' symbol should be omitted.
self.assertEqual(([None, None] + [self.symbol_infos[1]] * 4 +
[None] * 2 + [self.symbol_infos[2]] * 2 +
[self.symbol_infos[3]] * 3),
offset_to_symbol_info)
def testGetReachedOffsetsFromDump(self): def testGetReachedOffsetsFromDump(self):
processor = TestSymbolOffsetProcessor(self.symbol_infos) processor = TestSymbolOffsetProcessor(self.symbol_infos)
...@@ -74,7 +76,7 @@ class ProcessProfilesTestCase(unittest.TestCase): ...@@ -74,7 +76,7 @@ class ProcessProfilesTestCase(unittest.TestCase):
def testGetOrderedSymbols(self): def testGetOrderedSymbols(self):
processor = TestSymbolOffsetProcessor(self.symbol_infos) processor = TestSymbolOffsetProcessor(self.symbol_infos)
self.assertListEqual(['1', '3', self.START_SYMBOL], self.assertListEqual(['1', '3', self.START_SYMBOL],
processor.GetOrderedSymbols([8, 41, 6, 0])) processor.GetOrderedSymbols([7, 41, 5, 0]))
def testOffsetToSymbolsMap(self): def testOffsetToSymbolsMap(self):
symbol_infos = [SimpleTestSymbol('1', 8, 16), symbol_infos = [SimpleTestSymbol('1', 8, 16),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment