diff options
| author | Fabrice Desclaux <fabrice.desclaux@cea.fr> | 2019-03-04 12:22:16 +0100 |
|---|---|---|
| committer | Fabrice Desclaux <fabrice.desclaux@cea.fr> | 2019-03-05 16:52:51 +0100 |
| commit | 26c1075723a02984da6d3bc7423c5c0c43082dc3 (patch) | |
| tree | b67e7b072439f84109bd39dad8ed7f3f135224f8 /miasm/loader/cstruct.py | |
| parent | bb675f5cb34a482c964249656d539e67718bd8dc (diff) | |
| download | focaccia-miasm-26c1075723a02984da6d3bc7423c5c0c43082dc3.tar.gz focaccia-miasm-26c1075723a02984da6d3bc7423c5c0c43082dc3.zip | |
Rename elfesteem loader
Diffstat (limited to 'miasm/loader/cstruct.py')
| -rw-r--r-- | miasm/loader/cstruct.py | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/miasm/loader/cstruct.py b/miasm/loader/cstruct.py new file mode 100644 index 00000000..06d2e002 --- /dev/null +++ b/miasm/loader/cstruct.py @@ -0,0 +1,154 @@ +#! /usr/bin/env python + +from __future__ import print_function +from builtins import zip +from functools import reduce +import struct + +from future.utils import PY3 + +type_size = {} +size2type = {} +for t in 'B', 'H', 'I', 'Q': + s = struct.calcsize(t) + type_size[t] = s * 8 + size2type[s * 8] = t + +type_size['u08'] = size2type[8] +type_size['u16'] = size2type[16] +type_size['u32'] = size2type[32] +type_size['u64'] = size2type[64] + + +def fix_size(fields, wsize): + out = [] + for name, v in fields: + if v.endswith("s"): + pass + elif v == "ptr": + v = size2type[wsize] + elif not v in type_size: + raise ValueError("unknown Cstruct type", v) + else: + v = type_size[v] + out.append((name, v)) + fields = out + return fields + + +class Cstruct_Metaclass(type): + + def __new__(cls, name, bases, dct): + o = super(Cstruct_Metaclass, cls).__new__(cls, name, bases, dct) + o._packstring = o._packformat + \ + "".join(x[1] for x in o._fields) + o._size = struct.calcsize(o._packstring) + return o + + +class CStruct(object): + #__metaclass__ = Cstruct_Metaclass + _packformat = "" + _fields = [] + + @classmethod + def _from_file(cls, f): + return cls(f.read(cls._size)) + + def __init__(self, sex, wsize, *args, **kargs): + if sex == 1: + sex = '<' + else: + sex = '>' + # packformat enforce sex + if self._packformat: + sex = "" + pstr = fix_size(self._fields, wsize) + self._packstring = sex + self._packformat + \ + "".join(x[1] for x in pstr) + self._size = struct.calcsize(self._packstring) + + self._names = [x[0] for x in self._fields] + if kargs: + self.__dict__.update(kargs) + else: + if args: + s = args[0] + else: + s = b"" + s += b"\x00" * self._size + s = s[:self._size] + self._unpack(s) + + def _unpack(self, s): + disas = struct.unpack(self._packstring, s) + for n, v in zip(self._names, disas): + setattr(self, n, v) + + def _pack(self): + return struct.pack(self._packstring, + *(getattr(self, x) for x in self._names)) + + def _spack(self, superstruct, shift=0): + attr = [] + for name in self._names: + s = getattr(self, name) + if isinstance(s, CStruct): + if s in superstruct: + s = reduce(lambda x, y: x + len(y), + superstruct[:superstruct.index(s)], + 0) + s += shift + else: + raise Exception("%r is not a superstructure" % s) + attr.append(s) + return struct.pack(self._packstring, *attr) + + def _copy(self): + return self.__class__(**self.__dict__) + + def __len__(self): + return self._size + + def __str__(self): + if PY3: + return repr(self) + return self.__bytes__() + + def __bytes__(self): + return self._pack() + + def __repr__(self): + return "<%s=%s>" % (self.__class__.__name__, "/".join(repr( + getattr(self, x[0])) for x in self._fields + )) + + def __getitem__(self, item): # to work with format strings + return getattr(self, item) + + def _show(self): + print("##%s:" % self.__class__.__name__) + fmt = "%%-%is = %%r" % max(len(x[0]) for x in self._fields) + for fn, ft in self._fields: + print(fmt % (fn, getattr(self, fn))) + + +class CStructStruct(object): + + def __init__(self, lst, shift=0): + self._lst = lst + self._shift = shift + + def __getattr__(self, attr): + return getattr(self._lst, attr) + + def __str__(self): + if PY3: + return repr(self) + return self.__bytes__() + + def __bytes__(self): + return b"".join( + a if isinstance(a, bytes) else a._spack(self._lst, self._shift) + for a in self._lst + ) |