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):
"""
dump_offset_to_symbol_info = self._GetDumpOffsetToSymbolInfo()
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:
dump_offset = get(i)
idx = dump_offset / 4
idx = dump_offset / 2
assert dump_offset >= 0 and idx < len(dump_offset_to_symbol_info), (
'Dump offset out of binary range')
symbol_info = dump_offset_to_symbol_info[idx]
if symbol_info is None:
reached_return_addresses_not_found += 1
offsets_not_found += 1
update(i, None)
else:
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',
reached_return_addresses_not_found)
offsets_not_found)
def _GetDumpOffsetToSymbolInfo(self):
"""Computes an array mapping each word in .text to a symbol.
......@@ -261,14 +261,23 @@ class SymbolOffsetProcessor(object):
assert len(start_syms) == 1, 'Can\'t find unique start of text symbol'
start_of_text = start_syms[0].offset
max_offset = max(s.offset + s.size for s in self.SymbolInfos())
text_length_words = (max_offset - start_of_text) / 4
self._offset_to_symbol_info = [None for _ in xrange(text_length_words)]
for s in self.SymbolInfos():
offset = s.offset - start_of_text
if offset < 0:
continue
for i in range(offset / 4, (offset + s.size) / 4):
self._offset_to_symbol_info[i] = s
text_length_halfwords = (max_offset - start_of_text) / 2
self._offset_to_symbol_info = [None] * text_length_halfwords
for sym in self.SymbolInfos():
offset = sym.offset - start_of_text
assert offset >= 0, ('Unexpected symbol before the start of text. '
'Has the linker script broken?')
# The low bit of offset may be set to indicate a thumb instruction. The
# 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
......
......@@ -20,12 +20,12 @@ class ProcessProfilesTestCase(unittest.TestCase):
def setUp(self):
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_3 = SimpleTestSymbol('3', 40, 12)
self.offset_to_symbol_info = (
[None, None] + [self.symbol_1] * 4 + [None] * 2 + [self.symbol_2] * 2
+ [self.symbol_3] * 3)
[None] * 3 + [self.symbol_1] * 8 + [None] * 5 + [self.symbol_2] * 4 +
[self.symbol_3] * 6)
self.symbol_infos = [self.symbol_0, self.symbol_1,
self.symbol_2, self.symbol_3]
self._file_counter = 0
......@@ -37,20 +37,22 @@ class ProcessProfilesTestCase(unittest.TestCase):
def testGetOffsetToSymbolInfo(self):
processor = TestSymbolOffsetProcessor(self.symbol_infos)
offset_to_symbol_info = processor._GetDumpOffsetToSymbolInfo()
self.assertListEqual(self.offset_to_symbol_info, offset_to_symbol_info)
self.assertListEqual(self.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):
self.symbol_infos = [SimpleTestSymbol(s.name, s.offset + 8, s.size)
for s in self.symbol_infos]
self.symbol_infos.append(SimpleTestSymbol('early', 0, 4))
processor = TestSymbolOffsetProcessor(self.symbol_infos)
offset_to_symbol_info = 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)
self.assertRaises(AssertionError, processor._GetDumpOffsetToSymbolInfo)
def testGetReachedOffsetsFromDump(self):
processor = TestSymbolOffsetProcessor(self.symbol_infos)
......@@ -74,7 +76,7 @@ class ProcessProfilesTestCase(unittest.TestCase):
def testGetOrderedSymbols(self):
processor = TestSymbolOffsetProcessor(self.symbol_infos)
self.assertListEqual(['1', '3', self.START_SYMBOL],
processor.GetOrderedSymbols([8, 41, 6, 0]))
processor.GetOrderedSymbols([7, 41, 5, 0]))
def testOffsetToSymbolsMap(self):
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