diff options
Diffstat (limited to 'sploit/symtbl.py')
-rw-r--r-- | sploit/symtbl.py | 112 |
1 files changed, 44 insertions, 68 deletions
diff --git a/sploit/symtbl.py b/sploit/symtbl.py index a471958..86800f5 100644 --- a/sploit/symtbl.py +++ b/sploit/symtbl.py @@ -73,112 +73,88 @@ with the Symtbl base address. print(s.a, s.b, s.c, s.d) # "998 999 1000 1001" """ +from sploit.types.indextbl import IndexTbl +from sploit.types.index_entry import IndexEntry + def Symtbl(*, base=0, **symbols): """ Create a new Symtbl object. Return an empty Symtbl or, optionally, one initialized with the given - symbol values. Arguments _must_ be keyword arguments. + symbol values. Arguments must be keyword arguments. Users should call this function instead of attempting to construct the Symtbl class. Construction is implemented via a normal function to prevent any argument name from conflicting with __init__'s bound instance parameter. """ - self = SymtblImpl({}, 0, base) + self = SymtblImpl(base, 0, dict()) for k, v in symbols.items(): self[k] = v return self -class SymtblImpl: +class SymtblImpl(IndexTbl): """Symtbl implementation class""" - def __init__(self, entries, adjust, base): + def __init__(self, base, adjust, entries): """Construct Symtbl from instance data.""" + super().__init__(base) + object.__setattr__(self, "__adjust__", adjust) object.__setattr__(self, "__entries__", entries) - object.__setattr__(self, "__adjust__", adjust) - object.__setattr__(self, "base", base) - def __index__(self): - """Convert object to integer using base value.""" - return self.base + def __repr__(self): + """Return human-readable Symtbl.""" + FMT = "\n{:<20} {:<20}" + s = f"{len(self)} symbols @ {hex(self)}" - def __matmul__(self, base): - """Create remapped version of object at absolute base.""" - return SymtblImpl(self.__entries__, self.__adjust__, int(base)) + if len(self) > 0: + s += FMT.format("ADDRESS", "SYMBOL") - def __add__(self, offset): - """Create remapped version of object at relative base.""" - return self @ (self.base + offset) + for key, value in self: + key = f"[{key}]" if isinstance(value, IndexEntry) else key + s += FMT.format(hex(value), key) - def __sub__(self, offset): - """Create remapped version of object at relative base.""" - return self @ (self.base - offset) + return s def __rshift__(self, offset): - """Create symbol adjusted version of object.""" - return SymtblImpl(self.__entries__, self.__adjust__ + int(offset), self.base) + """Return symbol-adjusted version of object.""" + adjust = self.__adjust__ + int(offset) + return SymtblImpl(self.base, adjust, self.__entries__) def __lshift__(self, offset): - """Create symbol adjusted version of object.""" + """Return symbol-adjusted version of object.""" return self >> (-offset) def __mod__(self, offset): - """Create symbol rebased version of object.""" + """Return symbol-rebased version of object.""" return self >> (self.base - offset) - def __getattr__(self, symbol): - """Return symbol offset or subtable via pseudo-attribute.""" - return self[symbol] + # IndexTbl abstract methods - def __setattr__(self, symbol, value): - """Set symbol offset or subtable via pseudo-attribute.""" - self[symbol] = value + def __copy__(self): + """Return copy of object with shared symbol entries.""" + return SymtblImpl(self.base, self.__adjust__, self.__entries__) - def __delattr__(self, symbol): - """Unset symbol via pseudo-attribute.""" - del self[symbol] + def __iter__(self): + """Iterate over table items, sorted by offsets.""" + it = { k: self[k] for k in self.__entries__}.items() + return iter(sorted(it, key=lambda x: int(x[1]))) def __len__(self): """Return number of defined symbols.""" return len(self.__entries__) - def __getitem__(self, symbol): - """Return symbol offset, subtable, or translated offset via subscript.""" - if symbol == "base": - return self.base - offset = self.__entries__[symbol] if type(symbol) is str else symbol + def __getindex__(self, index): + """Return symbol value or translated offset.""" + if isinstance(index, (int, IndexEntry)): offset = index + else: offset = self.__entries__[index] return offset + (self.base + self.__adjust__) - def __setitem__(self, symbol, value): - """Set symbol offset or subtable via subscript.""" - if symbol == "base": - object.__setattr__(self, "base", int(value)) - elif symbol in dir(self): - raise KeyError(f"Symtbl: key is reserved: {symbol}") - elif type(symbol) is not str: - raise TypeError(f"Symtbl: key must be a string: {symbol}") - else: - self.__entries__[symbol] = value - (self.base + self.__adjust__) - - def __delitem__(self, symbol): - """Unset symbol via subscript.""" - del self.__entries__[symbol] + def __setindex__(self, index, value): + """Set symbol value.""" + if isinstance(index, (int, IndexEntry)): + raise TypeError(f"Symtbl: Unsupported key type: {type(index)}") + self.__entries__[index] = value - (self.base + self.__adjust__) - def __iter__(self): - """Iterate over table entries as key:value tuples, like dict.items().""" - return iter(sorted({ k: self[k] for k in self.__entries__ }.items(), key=lambda v: int(v[1]))) - - def __contains__(self, symbol): - """Test symbol name membership in table.""" - return symbol in self.__entries__ - - def __repr__(self): - """Return human-readable Symtbl.""" - FMT = "\n{:<20} {:<20}" - s = f"{len(self)} symbols @ {hex(self)}" - if len(self) > 0: - s += FMT.format("ADDRESS", "SYMBOL") - for symbol, offset in self: - disp = f"[{symbol}]" if type(offset) is not int else symbol - s += FMT.format(hex(offset), disp) - return s + def __delindex__(self, index): + """Delete symbol.""" + del self.__entries__[index] |