diff options
Diffstat (limited to 'miasm2/core/objc.py')
| -rw-r--r-- | miasm2/core/objc.py | 189 |
1 files changed, 104 insertions, 85 deletions
diff --git a/miasm2/core/objc.py b/miasm2/core/objc.py index 1a8624c1..62ac798d 100644 --- a/miasm2/core/objc.py +++ b/miasm2/core/objc.py @@ -62,11 +62,25 @@ def objc_to_str(objc, result=None): class ObjC(object): """Generic ObjC""" + def __init__(self, align, size): + self._align = align + self._size = size + def set_align_size(self, align, size): """Set C object alignment and size""" - self.align = align - self.size = size + self._align = align + self._size = size + + @property + def align(self): + """Alignment (in bytes) of the C object""" + return self._align + + @property + def size(self): + """Size (in bytes) of the C object""" + return self._size def eq_base(self, other): return (self.__class__ == other.__class__ and @@ -83,6 +97,9 @@ class ObjC(object): return cmp(self.align, other.align) return cmp(self.size, other.size) + def __hash__(self): + return hash((self.__class__, self._align, self._size)) + def __str__(self): return objc_to_str(self) @@ -91,8 +108,13 @@ class ObjCDecl(ObjC): """C Declaration identified""" def __init__(self, name, align, size): - super(ObjCDecl, self).__init__() - self.name, self.align, self.size = name, align, size + super(ObjCDecl, self).__init__(align, size) + self._name = name + + name = property(lambda self: self._name) + + def __hash__(self): + return hash((super(ObjCDecl, self).__hash__(), self._name)) def __repr__(self): return '<%s %s>' % (self.__class__.__name__, self.name) @@ -111,9 +133,7 @@ class ObjCInt(ObjC): """C integer""" def __init__(self): - super(ObjCInt, self).__init__() - self.size = None - self.align = None + super(ObjCInt, self).__init__(None, None) def __str__(self): return 'int' @@ -133,14 +153,33 @@ class ObjCPtr(ObjC): @void_p_size: pointer size (in bytes) """ - super(ObjCPtr, self).__init__() + super(ObjCPtr, self).__init__(void_p_align, void_p_size) + self._lock = False + self.objtype = objtype - self.align = void_p_align - self.size = void_p_size + if objtype is None: + self._lock = False + + def get_objtype(self): + assert self._lock is True + return self._objtype + + def set_objtype(self, objtype): + assert self._lock is False + self._lock = True + self._objtype = objtype + + objtype = property(get_objtype, set_objtype) + + def __hash__(self): + # Don't try to hash on an unlocked Ptr (still mutable) + assert self._lock + return hash((super(ObjCPtr, self).__hash__(), hash(self._objtype))) def __repr__(self): return '<%s %r>' % (self.__class__.__name__, self.objtype.__class__) + def __cmp__(self, other): ret = self.cmp_base(other) if ret: @@ -158,11 +197,15 @@ class ObjCArray(ObjC): @elems: number of elements in the array """ - super(ObjCArray, self).__init__() - self.elems = elems - self.objtype = objtype - self.align = objtype.align - self.size = elems * objtype.size + super(ObjCArray, self).__init__(objtype.align, elems * objtype.size) + self._elems = elems + self._objtype = objtype + + objtype = property(lambda self: self._objtype) + elems = property(lambda self: self._elems) + + def __hash__(self): + return hash((super(ObjCArray, self).__hash__(), self._elems, hash(self._objtype))) def __repr__(self): return '<%r[%d]>' % (self.objtype, self.elems) @@ -180,20 +223,17 @@ class ObjCArray(ObjC): class ObjCStruct(ObjC): """C object for structures""" - def __init__(self, name): - super(ObjCStruct, self).__init__() - self.name = name - self.fields = [] - - def add_field(self, name, objtype, offset, size): - """Add a field into the structure - @name: field name - @objtype: field type - @offset: field offset in the structure - @size: field size - """ + def __init__(self, name, align, size, fields): + super(ObjCStruct, self).__init__(align, size) + self._name = name + self._fields = tuple(fields) + + name = property(lambda self: self._name) + fields = property(lambda self: self._fields) - self.fields.append((name, objtype, offset, size)) + def __hash__(self): + args = tuple((name, offset, size) for (name, _, offset, size) in self._fields) + return hash((super(ObjCStruct, self).__hash__(), self._name, hash(args))) def __repr__(self): out = [] @@ -211,32 +251,21 @@ class ObjCStruct(ObjC): ret = self.cmp_base(other) if ret: return ret - ret = cmp(len(self.fields), len(other.fields)) - if ret: - return ret - for field_a, field_b in zip(self.fields, other.fields): - ret = cmp(field_a, field_b) - if ret: - return ret - return 0 + return cmp(self.name, other.name) class ObjCUnion(ObjC): """C object for unions""" - def __init__(self, name): - super(ObjCUnion, self).__init__() - self.name = name - self.fields = [] - - def add_field(self, name, objtype, offset, size): - """Add a field into the structure - @name: field name - @objtype: field type - @offset: field offset in the structure - @size: field size - """ + def __init__(self, name, align, size, fields): + super(ObjCUnion, self).__init__(align, size) + self._name = name + self._fields = tuple(fields) - self.fields.append((name, objtype, offset, size)) + name = property(lambda self: self._name) + fields = property(lambda self: self._fields) + + def __hash__(self): + return hash((super(ObjCUnion, self).__hash__(), self._name, hash(self._fields))) def __repr__(self): out = [] @@ -254,22 +283,16 @@ class ObjCUnion(ObjC): ret = self.cmp_base(other) if ret: return ret - ret = cmp(len(self.fields), len(other.fields)) - if ret: - return ret - for field_a, field_b in zip(self.fields, other.fields): - ret = cmp(field_a, field_b) - if ret: - return ret - return 0 + return cmp(self.name, other.name) class ObjCEllipsis(ObjC): """C integer""" def __init__(self): - super(ObjCEllipsis, self).__init__() - self.size = None - self.align = None + super(ObjCEllipsis, self).__init__(None, None) + + align = property(lambda self: self._align) + size = property(lambda self: self._size) def __cmp__(self, other): return self.cmp_base(other) @@ -279,13 +302,19 @@ class ObjCFunc(ObjC): """C object for Functions""" def __init__(self, name, abi, type_ret, args, void_p_align, void_p_size): - super(ObjCFunc, self).__init__() - self.name = name - self.abi = abi - self.type_ret = type_ret - self.args = args - self.align = void_p_align - self.size = void_p_size + super(ObjCFunc, self).__init__(void_p_align, void_p_size) + self._name = name + self._abi = abi + self._type_ret = type_ret + self._args = tuple(args) + + args = property(lambda self: self._args) + type_ret = property(lambda self: self._type_ret) + abi = property(lambda self: self._abi) + name = property(lambda self: self._name) + + def __hash__(self): + return hash((super(ObjCFunc, self).__hash__(), hash(self._args), self._type_ret, self._abi, self._name)) def __repr__(self): return "<%s %s>" % (self.__class__.__name__, @@ -304,17 +333,7 @@ class ObjCFunc(ObjC): ret = self.cmp_base(other) if ret: return ret - ret = cmp(self.name, other.name) - if ret: - return ret - ret = cmp(len(self.args), len(other.args)) - if ret: - return ret - for arg_a, arg_b in zip(self.args, other.args): - ret = cmp(arg_a, arg_b) - if ret: - return ret - return 0 + return cmp(self.name, other.name) OBJC_PRIO = { ObjC: 0, @@ -1447,22 +1466,22 @@ class CTypesManager(object): out = self.leaf_types.types.get(type_id, None) assert out is not None elif isinstance(type_id, CTypeUnion): - out = ObjCUnion(type_id.name) + args = [] align_max, size_max = 0, 0 for name, field in type_id.fields: objc = self._get_objc(field, resolved, to_fix, lvl + 1) resolved[field] = objc align_max = max(align_max, objc.align) size_max = max(size_max, objc.size) - out.add_field(name, objc, 0, objc.size) + args.append((name, objc, 0, objc.size)) align, size = self.union_compute_align_size(align_max, size_max) - out.set_align_size(align, size) + out = ObjCUnion(type_id.name, align, size, args) elif isinstance(type_id, CTypeStruct): - out = ObjCStruct(type_id.name) align_max, size_max = 0, 0 + args = [] offset, align_max = 0, 1 pad_index = 0 for name, field in type_id.fields: @@ -1475,13 +1494,13 @@ class CTypesManager(object): pad_index += 1 size = new_offset - offset pad_objc = self._get_objc(CTypeArray(self.padding, size), resolved, to_fix, lvl + 1) - out.add_field(pad_name, pad_objc, offset, pad_objc.size) + args.append((pad_name, pad_objc, offset, pad_objc.size)) offset = new_offset - out.add_field(name, objc, offset, objc.size) + args.append((name, objc, offset, objc.size)) offset += objc.size align, size = self.struct_compute_align_size(align_max, offset) - out.set_align_size(align, size) + out = ObjCStruct(type_id.name, align, size, args) elif isinstance(type_id, CTypePtr): target = type_id.target |