mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-11 02:04:11 +00:00
m1n1.constructutils: Move _off to class, improve addr stuff
Signed-off-by: Asahi Lina <lina@asahilina.net>
This commit is contained in:
parent
029ba73f44
commit
83dfa1ef70
1 changed files with 66 additions and 23 deletions
|
@ -139,8 +139,24 @@ class ReloadableConstructMeta(ReloadableMeta, Construct):
|
||||||
|
|
||||||
cls.docs = None
|
cls.docs = None
|
||||||
|
|
||||||
|
cls._off = {}
|
||||||
|
if "subcon" not in attrs:
|
||||||
return cls
|
return cls
|
||||||
|
|
||||||
|
subcon = attrs["subcon"]
|
||||||
|
if isinstance(subcon, Struct):
|
||||||
|
off = 0
|
||||||
|
for subcon in subcon.subcons:
|
||||||
|
try:
|
||||||
|
sizeof = subcon.sizeof()
|
||||||
|
except:
|
||||||
|
break
|
||||||
|
if isinstance(subcon, Renamed):
|
||||||
|
name = subcon.name
|
||||||
|
subcon = subcon.subcon
|
||||||
|
cls._off[name] = off, sizeof
|
||||||
|
off += sizeof
|
||||||
|
return cls
|
||||||
|
|
||||||
class ConstructClassBase(Reloadable, metaclass=ReloadableConstructMeta):
|
class ConstructClassBase(Reloadable, metaclass=ReloadableConstructMeta):
|
||||||
""" Offers two benifits over regular construct
|
""" Offers two benifits over regular construct
|
||||||
|
@ -165,6 +181,10 @@ class ConstructClassBase(Reloadable, metaclass=ReloadableConstructMeta):
|
||||||
|
|
||||||
parsed = None
|
parsed = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._addr = None
|
||||||
|
self._meta = {}
|
||||||
|
|
||||||
def Apply(self, dict=None, **kwargs):
|
def Apply(self, dict=None, **kwargs):
|
||||||
if dict is None:
|
if dict is None:
|
||||||
dict = kwargs
|
dict = kwargs
|
||||||
|
@ -174,6 +194,12 @@ class ConstructClassBase(Reloadable, metaclass=ReloadableConstructMeta):
|
||||||
setattr(self, key, dict[key])
|
setattr(self, key, dict[key])
|
||||||
self._keys += [key]
|
self._keys += [key]
|
||||||
|
|
||||||
|
def set_addr(self, addr=None, stream=None):
|
||||||
|
#print("set_addr", type(self), addr)
|
||||||
|
if addr is not None:
|
||||||
|
self._addr = addr
|
||||||
|
self._set_meta(self, stream)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _build(cls, obj, stream, context, path):
|
def _build(cls, obj, stream, context, path):
|
||||||
cls._build_prepare(obj)
|
cls._build_prepare(obj)
|
||||||
|
@ -196,6 +222,7 @@ class ConstructClassBase(Reloadable, metaclass=ReloadableConstructMeta):
|
||||||
obj._apply(new_obj)
|
obj._apply(new_obj)
|
||||||
|
|
||||||
obj._addr = addr
|
obj._addr = addr
|
||||||
|
cls._set_meta(obj, stream)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -213,11 +240,46 @@ class ConstructClassBase(Reloadable, metaclass=ReloadableConstructMeta):
|
||||||
def _apply(self, obj):
|
def _apply(self, obj):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _set_meta(cls, self, stream=None):
|
||||||
|
if stream is not None:
|
||||||
|
self._meta = {}
|
||||||
|
self._stream = stream
|
||||||
|
|
||||||
|
if isinstance(cls.subcon, Struct):
|
||||||
|
subaddr = int(self._addr)
|
||||||
|
for subcon in cls.subcon.subcons:
|
||||||
|
try:
|
||||||
|
sizeof = subcon.sizeof()
|
||||||
|
except:
|
||||||
|
break
|
||||||
|
if isinstance(subcon, Renamed):
|
||||||
|
name = subcon.name
|
||||||
|
#print(name, subcon)
|
||||||
|
subcon = subcon.subcon
|
||||||
|
if stream is not None and getattr(stream, "meta_fn", None):
|
||||||
|
meta = stream.meta_fn(subaddr, sizeof)
|
||||||
|
if meta is not None:
|
||||||
|
self._meta[name] = meta
|
||||||
|
if isinstance(subcon, Pointer):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
#print(name, subcon)
|
||||||
|
val = self[name]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if isinstance(val, ConstructClassBase):
|
||||||
|
val.set_addr(subaddr)
|
||||||
|
|
||||||
|
subaddr += sizeof
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _parse(cls, stream, context, path):
|
def _parse(cls, stream, context, path):
|
||||||
#print(f"parse {cls} @ {stream.tell():#x} {path}")
|
#print(f"parse {cls} @ {stream.tell():#x} {path}")
|
||||||
addr = stream.tell()
|
addr = stream.tell()
|
||||||
obj = cls.subcon._parse(stream, context, path)
|
obj = cls.subcon._parse(stream, context, path)
|
||||||
|
size = stream.tell() - addr
|
||||||
|
|
||||||
# Don't instance Selects
|
# Don't instance Selects
|
||||||
if isinstance(cls.subcon, Select):
|
if isinstance(cls.subcon, Select):
|
||||||
|
@ -226,29 +288,10 @@ class ConstructClassBase(Reloadable, metaclass=ReloadableConstructMeta):
|
||||||
# Skip calling the __init__ constructor, so that it can be used for building
|
# Skip calling the __init__ constructor, so that it can be used for building
|
||||||
# Use parsed instead, if you need a post-parsing constructor
|
# Use parsed instead, if you need a post-parsing constructor
|
||||||
self = cls.__new__(cls)
|
self = cls.__new__(cls)
|
||||||
self._off = {}
|
|
||||||
self._meta = {}
|
|
||||||
|
|
||||||
if isinstance(cls.subcon, Struct):
|
|
||||||
subaddr = addr
|
|
||||||
for subcon in cls.subcon.subcons:
|
|
||||||
try:
|
|
||||||
sizeof = subcon.sizeof()
|
|
||||||
except:
|
|
||||||
break
|
|
||||||
if isinstance(subcon, Renamed):
|
|
||||||
name = subcon.name
|
|
||||||
subcon = subcon.subcon
|
|
||||||
self._off[name] = subaddr - addr, sizeof
|
|
||||||
if getattr(stream, "meta_fn", None):
|
|
||||||
meta = stream.meta_fn(subaddr, sizeof)
|
|
||||||
if meta is not None:
|
|
||||||
self._meta[name] = meta
|
|
||||||
subaddr += sizeof
|
|
||||||
|
|
||||||
# These might be useful later
|
|
||||||
self._stream = stream
|
|
||||||
self._addr = addr
|
self._addr = addr
|
||||||
|
self._path = path
|
||||||
|
self._meta = {}
|
||||||
|
cls._set_meta(self, stream)
|
||||||
|
|
||||||
self._apply(obj)
|
self._apply(obj)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue