-
Notifications
You must be signed in to change notification settings - Fork 53
Examples | Iterate through a `struc_t` and its dependencies whilst maintaining their order
If you have some structure that you're trying to export to some other language/framework, but it's full of references and is dependant on a ton of other structures/enumerations/unions. You can throw a solver like the following at it so that way you can get them ordered properly before outputting them to some useful format.
import pycosat
class structures:
@staticmethod
def collect(st):
for m in st.members:
s = m.type
if isinstance(s, list):
s, _ = s
if isinstance(s, tuple):
s, _ = s
if isinstance(s, struc.structure_t):
for item in deps(s):
yield item
yield st, s
elif struc.has(m.typeinfo):
s = struc.by(m.typeinfo)
for item in deps(s):
yield item
yield st, s
else:
print('unknown type', m)
continue
return
@staticmethod
def dependencies(iterable):
res = {}
for st, dep in iterable:
res.setdefault(dep, set())
res.setdefault(st, set()).add(dep)
return res
@staticmethod
def results(start, dependencies):
rules = {}
for dep, items in dependencies.items():
[ rules.setdefault(item, set()) for item in items ]
rules.update(dependencies)
assert(start in rules)
to, of, variables = {}, {}, [item for item in rules]
for i, item in enumerate(variables):
to[item], of[1 + i] = 1 + i, item
clauses = []
for item, dependencies in rules.items():
for dependency in dependencies:
clauses.append([-to[item], +to[dependency]])
continue
clauses.append([+to[start]])
for solution in pycosat.itersolve(clauses):
result = [ item for item in solution ]
yield [ of[item] for item in result ]
return
mystruc = struc.search('*whatever*')
allstructures = structures.collect(mystruc)
theirdependencies = structures.dependencies(allstructures)
for struc in structures.results(mystruc, theirdependencies):
print(struc)
Useful format? Normally you'd just use mystruc
as an object so you can iterate through members and extract types, but to get a contiguous layout of them, you can just use structure.members(mystruc)
which will give you the offset, size, and tags for every member (including holes). There's also structure.fragment
if you're trying to slice some part of a function frame so you can copy the exact data for some external python.
print('struct ' + mystruc.name + '{')
for offset, size, tags in structure.members(mystruc):
member = mystruc.by(offset)
myname = tags.get('__name__', "unnamed_{:x}".format(offset))
mycomment = "// {!s}".format(tags)
print(' char %s[%d]; // %s'%(myname, size, mycomment))
print('}')
(note: For brevity, this is not tracking pointers or "complex" types. To do get the structure name for a type, you can use struc.by
on a member_t.typeinfo
property, pythonic types via member_t.type
, or db.t.array
to get information about complicated types)
|