# This code is in the public domain
#-------------------------------------------------------------------------------
from ..common.utils import struct_parse, elf_assert, parse_cstring_from_stream
-
+from collections import defaultdict
class Section(object):
""" Base class for ELF sections. Also used for all sections types that have
return Symbol(entry, name)
def get_symbol_by_name(self, name):
- """ Get a symbol by its name. Return None if no symbol by the given
- name exists.
+ """ Get a symbol(s) by name. Return None if no symbol by the given name
+ exists.
"""
# The first time this method is called, construct a name to number
# mapping
#
if self._symbol_name_map is None:
- self._symbol_name_map = {}
+ self._symbol_name_map = defaultdict(list)
for i, sym in enumerate(self.iter_symbols()):
- self._symbol_name_map[sym.name] = i
- symnum = self._symbol_name_map.get(name)
- return None if symnum is None else self.get_symbol(symnum)
+ self._symbol_name_map[sym.name].append(i)
+ symnums = self._symbol_name_map.get(name)
+ return [self.get_symbol(i) for i in symnums] if symnums else None
def iter_symbols(self):
""" Yield all the symbols in the table
self.assertIsNotNone(symtab)
# Test we can find a symbol by its name.
- main = symtab.get_symbol_by_name(b'main')
- self.assertIsNotNone(main)
+ mains = symtab.get_symbol_by_name(b'main')
+ self.assertIsNotNone(mains)
# Test it is actually the symbol we expect.
+ self.assertIsInstance(mains, list)
+ self.assertEqual(len(mains), 1)
+ main = mains[0]
self.assertEqual(main.name, b'main')
self.assertEqual(main['st_value'], 0x8068)
self.assertEqual(main['st_size'], 0x28)
undef = symtab.get_symbol_by_name(b'non-existent symbol')
self.assertIsNone(undef)
+ def test_duplicated_symbol(self):
+ with open(os.path.join('test', 'testfiles_for_unittests',
+ 'simple_gcc.elf.arm'), 'rb') as f:
+ elf = ELFFile(f)
+
+ # Find the symbol table.
+ symtab = elf.get_section_by_name(b'.symtab')
+ self.assertIsNotNone(symtab)
+
+ # The '$a' symbols that are present in the test file.
+ expected_symbols = [0x8000, 0x8034, 0x8090, 0x800c, 0x809c, 0x8018,
+ 0x8068]
+
+ # Test we get all expected instances of the symbol '$a'.
+ arm_markers = symtab.get_symbol_by_name(b'$a')
+ self.assertIsNotNone(arm_markers)
+ self.assertIsInstance(arm_markers, list)
+ self.assertEqual(len(arm_markers), len(expected_symbols))
+ for symbol in arm_markers:
+ self.assertEqual(symbol.name, b'$a')
+ self.assertIn(symbol['st_value'], expected_symbols)
+
if __name__ == '__main__':
unittest.main()