Make SymbolTable.symbols consistent with enumerations and types.

This commit is contained in:
Mike Auty
2017-08-11 19:25:13 +01:00
parent f7f1c1d5e0
commit e434909e50
2 changed files with 31 additions and 20 deletions
+5 -3
View File
@@ -163,15 +163,17 @@ class BaseSymbolTableInterface(validity.ValidityRoutines):
def get_symbols_by_type(self, type_name):
"""Returns the name of all symbols in this table that have type matching type_name"""
for symbol in self.symbols:
for symbol_name in self.symbols:
# This allows for searching with and without the table name (in case multiple tables contain
# the same symbol name and we've not specifically been told which one)
symbol = self.get_symbol(symbol_name)
if symbol.type_name == type_name or (symbol.type_name.endswith(constants.BANG + type_name)):
yield symbol.name
def get_symbols_by_location(self, offset):
"""Returns the name of all symbols in this table that have type matching type_name"""
sort_symbols = [(s.offset, s) for s in sorted(self.symbols, key = lambda x: x.offset)]
"""Returns the name of all symbols in this table that live at a particular offset"""
sort_symbols = [(s.offset, s) for s in
sorted([self.get_symbol(sn) for sn in self.symbols], key = lambda x: x.offset)]
result = bisect.bisect_left(sort_symbols, offset)
if result == len(sort_symbols):
raise StopIteration
+26 -17
View File
@@ -166,7 +166,7 @@ class Version1Format(ISFormatTable):
nt.name = name + "_natives"
super().__init__(context, config_path, name, nt)
self._overrides = {}
self._symbol_cache = None
self._symbol_cache = {}
def _get_natives(self):
"""Determines the appropriate native_types to use from the JSON data"""
@@ -197,24 +197,30 @@ class Version1Format(ISFormatTable):
def get_symbol(self, name):
"""Returns the location offset given by the symbol name"""
# TODO: Add the ability to add/remove/change symbols after creation
# note that this should invalidate/update the cache
if self._symbol_cache.get(name, None):
return self._symbol_cache[name]
symbol = self._json_object['symbols'].get(name, None)
if not symbol:
raise exceptions.SymbolError("Unknown symbol: {}".format(name))
return interfaces.symbols.Symbol(name = name, address = symbol['address'])
self._symbol_cache[name] = interfaces.symbols.Symbol(name = name, address = symbol['address'])
return self._symbol_cache[name]
@property
def symbols(self):
if not self._symbol_cache:
self._symbol_cache = [self.get_symbol(x) for x in self._json_object['symbols']]
return self._symbol_cache
# TODO: Add the ability to add/remove/change symbols after creation, note that this should invalidate the cache
return self._json_object.get('symbols', {}).keys()
@property
def enumerations(self):
"""Returns an iterator of the available enumerations"""
return self._json_object.get('enums', {}).keys()
@property
def types(self):
"""Returns an iterator of the symbol names"""
return list(self._json_object.get('user_types', {}).keys()) + list(self.natives.types)
def get_type_class(self, name):
return self._overrides.get(name, objects.Struct)
@@ -227,11 +233,6 @@ class Version1Format(ISFormatTable):
if name in self._overrides:
del self._overrides[name]
@property
def types(self):
"""Returns an iterator of the symbol names"""
return list(self._json_object.get('user_types', {}).keys()) + list(self.natives.types)
def _interdict_to_template(self, dictionary):
"""Converts an intermediate format dict into an object template"""
if not dictionary:
@@ -366,14 +367,18 @@ class Version3Format(Version2Format):
version = (current - age, age, revision)
def get_symbol(self, name):
"""Returns the location offset given by the symbol name"""
"""Returns the symbol given by the symbol name"""
if self._symbol_cache.get(name, None):
return self._symbol_cache[name]
symbol = self._json_object['symbols'].get(name, None)
if not symbol:
raise exceptions.SymbolError("Unknown symbol: {}".format(name))
symbol_type = None
if 'type' in symbol:
symbol_type = self._interdict_to_template(symbol['type'])
return interfaces.symbols.Symbol(name = name, address = symbol['address'], type = symbol_type)
self._symbol_cache[name] = interfaces.symbols.Symbol(name = name, address = symbol['address'],
type = symbol_type)
return self._symbol_cache[name]
class Version4Format(Version3Format):
@@ -422,7 +427,9 @@ class Version5Format(Version4Format):
version = (current - age, age, revision)
def get_symbol(self, name):
"""Returns the location offset given by the symbol name"""
"""Returns the symbol given by the symbol name"""
if self._symbol_cache.get(name, None):
return self._symbol_cache[name]
symbol = self._json_object['symbols'].get(name, None)
if not symbol:
raise exceptions.SymbolError("Unknown symbol: {}".format(name))
@@ -432,5 +439,7 @@ class Version5Format(Version4Format):
symbol_constant_data = None
if 'constant_data' in symbol:
symbol_constant_data = base64.b64decode(symbol.get('constant_data'))
return interfaces.symbols.Symbol(name = name, address = symbol['address'], type = symbol_type,
constant_data = symbol_constant_data)
self._symbol_cache[name] = interfaces.symbols.Symbol(name = name, address = symbol['address'],
type = symbol_type,
constant_data = symbol_constant_data)
return self._symbol_cache[name]