about summary refs log tree commit diff stats
path: root/src/miasm/loader/cstruct.py
diff options
context:
space:
mode:
authorTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-10-14 09:09:29 +0000
committerTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-10-14 09:09:29 +0000
commit579cf1d03fb932083e6317967d1613d5c2587fb6 (patch)
tree629f039935382a2a7391bce9253f6c9968159049 /src/miasm/loader/cstruct.py
parent51c15d3ea2e16d4fc5f0f01a3b9befc66b1f982e (diff)
downloadfocaccia-miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.tar.gz
focaccia-miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.zip
Convert to src-layout ta/nix
Diffstat (limited to 'src/miasm/loader/cstruct.py')
-rw-r--r--src/miasm/loader/cstruct.py154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/miasm/loader/cstruct.py b/src/miasm/loader/cstruct.py
new file mode 100644
index 00000000..06d2e002
--- /dev/null
+++ b/src/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
+        )