summaryrefslogtreecommitdiffstats
path: root/sploit/symtbl.py
diff options
context:
space:
mode:
Diffstat (limited to 'sploit/symtbl.py')
-rw-r--r--sploit/symtbl.py112
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]