about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorFlorent Monjalet <florent.monjalet@gmail.com>2015-12-04 10:16:37 +0100
committerFlorent Monjalet <florent.monjalet@gmail.com>2016-01-18 14:02:31 +0100
commitd87a0f89388119604af7f0aaf82a238b10707e5a (patch)
tree1c2b0122d61dd6dc19ac10d985d87edf7f747549
parentba2df16277d7d4deae118ed11e1e92cd478045ec (diff)
downloadmiasm-d87a0f89388119604af7f0aaf82a238b10707e5a.tar.gz
miasm-d87a0f89388119604af7f0aaf82a238b10707e5a.zip
MemStruct/Types: pinned renamed to lval
-rw-r--r--example/jitter/types.py2
-rw-r--r--miasm2/core/types.py79
-rw-r--r--test/core/types.py44
3 files changed, 79 insertions, 46 deletions
diff --git a/example/jitter/types.py b/example/jitter/types.py
index 6d8543b4..f4a7ddb4 100644
--- a/example/jitter/types.py
+++ b/example/jitter/types.py
@@ -229,6 +229,8 @@ print "See that the original array has been modified:"
 print repr(data)
 print
 
+# TODO: type manipulation examples
+
 print "See test/core/types.py and the miasm2.core.types module doc for "
 print "more information."
 
diff --git a/miasm2/core/types.py b/miasm2/core/types.py
index 3c8d5b8b..d6bc3cf5 100644
--- a/miasm2/core/types.py
+++ b/miasm2/core/types.py
@@ -1,5 +1,34 @@
-"""This module provides classes to manipulate C structures backed by a VmMngr
-object (a miasm sandbox virtual memory).
+"""This module provides classes to manipulate pure C types as well as their
+representation in memory. A typical usecase is to use this module to
+easily manipylate structures backed by a VmMngr object (a miasm sandbox virtual
+memory):
+
+    class ListNode(MemStruct):
+        fields = [
+            ("next", Ptr("<I", Self())),
+            ("data", Ptr("<I", Void())),
+        ]
+
+    class LinkedList(MemStruct):
+        fields = [
+            ("head", Ptr("<I", ListNode)),
+            ("tail", Ptr("<I", ListNode)),
+            ("size", Num("<I")),
+        ]
+
+    link = LinkedList(vm, addr1)
+    link.memset()
+    node = ListNode(vm, addr2)
+    node.memset()
+    link.head = node.get_addr()
+    link.tail = node.get_addr()
+    link.size += 1
+    assert link.head.deref == node
+    data = Num("<I").lval(vm, addr3)
+    data.val = 5
+    node.data = data.get_addr()
+    # see examples/jitter/types.py for more info
+
 
 It provides two families of classes, Type-s (Num, Ptr, Str...) and their
 associated MemType-s. A Type subclass instance represents a fully defined C
@@ -29,14 +58,13 @@ And some less common types:
     - RawStruct: abstraction over a simple struct pack/unpack (no mapping to a
       standard C type)
 
-For each type, the `.pinned` property returns a MemType subclass that
+For each type, the `.lval` property returns a MemType subclass that
 allows to access the field in memory.
 
 
 The easiest way to use the API to declare and manipulate new structures is to
 subclass MemStruct and define a list of (<field_name>, <field_definition>):
 
-    # FIXME: "I" => "u32"
     class MyStruct(MemStruct):
         fields = [
             # Scalar field: just struct.pack field with one value
@@ -210,10 +238,13 @@ class Type(object):
         return self._unpack(raw)
 
     @property
-    def pinned(self):
+    def lval(self):
         """Returns a class with a (vm, addr) constructor that allows to
         interact with this type in memory.
 
+        In compilation terms, it returns a class allowing to instanciate an
+        lvalue of this type.
+
         @return: a MemType subclass.
         """
         if self in DYN_MEM_STRUCT_CACHE:
@@ -225,7 +256,7 @@ class Type(object):
     def _build_pinned_type(self):
         """Builds the MemType subclass allowing to interract with this type.
 
-        Called by self.pinned when it is not in cache.
+        Called by self.lval when it is not in cache.
         """
         pinned_base_class = self._get_pinned_base_class()
         pinned_type = type("Mem%r" % self, (pinned_base_class,),
@@ -324,7 +355,7 @@ class Ptr(Num):
             in memory
         @dst_type: (MemType or Type) the MemType this Ptr points to.
             If a Type is given, it is transformed into a MemType with
-            TheType.pinned.
+            TheType.lval.
         *type_args, **type_kwargs: arguments to pass to the the pointed
             MemType when instanciating it (e.g. for MemStr encoding or
             MemArray field_type).
@@ -342,10 +373,10 @@ class Ptr(Num):
             dst_type._get_self_type = lambda: self._get_self_type()
             # dst_type cannot be patched here, since _get_self_type of the outer
             # class has not yet been set. Patching dst_type involves calling
-            # dst_type.pinned, which will only return a type that does not point
+            # dst_type.lval, which will only return a type that does not point
             # on MemSelf but on the right class only when _get_self_type of the
             # outer class has been replaced by _MetaMemStruct.
-            # In short, dst_type = dst_type.pinned is not valid here, it is done
+            # In short, dst_type = dst_type.lval is not valid here, it is done
             # lazily in _fix_dst_type
         self._dst_type = dst_type
         self._type_args = type_args
@@ -358,7 +389,7 @@ class Ptr(Num):
             else:
                 raise ValueError("Unsupported usecase for MemSelf, sorry")
         if isinstance(self._dst_type, Type):
-            self._dst_type = self._dst_type.pinned
+            self._dst_type = self._dst_type.lval
 
     @property
     def dst_type(self):
@@ -374,7 +405,7 @@ class Ptr(Num):
             super(Ptr, self).set(vm, addr, val)
 
     def get(self, vm, addr):
-        return self.pinned(vm, addr)
+        return self.lval(vm, addr)
 
     def get_val(self, vm, addr):
         """Get the numeric value of a Ptr"""
@@ -429,14 +460,14 @@ class Struct(Type):
 
     Mapped to MemStruct.
 
-    NOTE: The `.pinned` property of Struct creates classes on the fly. If an
+    NOTE: The `.lval` property of Struct creates classes on the fly. If an
     equivalent structure is created by subclassing MemStruct, an exception
     is raised to prevent creating multiple classes designating the same type.
 
     Example:
         s = Struct("Toto", [("f1", Num("I")), ("f2", Num("I"))])
 
-        Toto1 = s.pinned
+        Toto1 = s.lval
 
         # This raises an exception, because it describes the same structure as
         # Toto1
@@ -469,7 +500,7 @@ class Struct(Type):
         vm.set_mem(addr, raw)
 
     def get(self, vm, addr):
-        return self.pinned(vm, addr)
+        return self.lval(vm, addr)
 
     def get_field(self, vm, addr, name):
         """Get a field value by @name and base structure @addr in @vm VmMngr."""
@@ -618,7 +649,7 @@ class Array(Type):
                 "Assignment only implemented for list and MemSizedArray")
 
     def get(self, vm, addr):
-        return self.pinned(vm, addr)
+        return self.lval(vm, addr)
 
     def size(self):
         if self.is_sized():
@@ -949,7 +980,7 @@ class MemType(object):
     virtual memory.
 
     Globally, MemTypes are not meant to be used directly: specialized
-    subclasses are generated by Type(...).pinned and should be used instead.
+    subclasses are generated by Type(...).lval and should be used instead.
     The main exception is MemStruct, which you may want to subclass yourself
     for syntactic ease.
     """
@@ -1022,11 +1053,11 @@ class MemType(object):
         """Cast this MemType to another MemType (same address, same vm,
         but different type). Return the casted MemType.
 
-        @other_type: either a Type instance (other_type.pinned is used) or a
+        @other_type: either a Type instance (other_type.lval is used) or a
             MemType subclass
         """
         if isinstance(other_type, Type):
-            other_type = other_type.pinned
+            other_type = other_type.lval
         return other_type(self._vm, self.get_addr())
 
     def cast_field(self, field, other_type, *type_args, **type_kwargs):
@@ -1035,7 +1066,7 @@ class MemType(object):
 
         @field: field specification, for example its name for a struct, or an
             index in an array. See the subclass doc.
-        @other_type: either a Type instance (other_type.pinned is used) or a
+        @other_type: either a Type instance (other_type.lval is used) or a
             MemType subclass
         """
         raise NotImplementedError("Abstract")
@@ -1127,7 +1158,7 @@ class MemStruct(MemType):
         assert mstruct.other.deref.foo == 0x1234
 
     Note that:
-        MyStruct = Struct("MyStruct", <same fields>).pinned
+        MyStruct = Struct("MyStruct", <same fields>).lval
     is equivalent to the previous MyStruct declaration.
 
     See the various Type-s doc for more information. See MemStruct.gen_fields
@@ -1166,7 +1197,7 @@ class MemStruct(MemType):
     def cast_field(self, field, other_type):
         """In this implementation, @field is a field name"""
         if isinstance(other_type, Type):
-            other_type = other_type.pinned
+            other_type = other_type.lval
         return other_type(self._vm, self.get_addr(field))
 
     # Field generation method, voluntarily public to be able to gen fields
@@ -1214,7 +1245,7 @@ class MemStruct(MemType):
                                "one. Use it instead.")
 
         # Register this class so that another one will not be created when
-        # calling cls._type.pinned
+        # calling cls._type.lval
         DYN_MEM_STRUCT_CACHE[cls._type] = cls
 
         cls._gen_attributes()
@@ -1336,7 +1367,7 @@ class MemArray(MemType):
 
     It can be indexed for setting and getting elements, example:
 
-        array = Array(Num("I")).pinned(vm, addr))
+        array = Array(Num("I")).lval(vm, addr))
         array[2] = 5
         array[4:8] = [0, 1, 2, 3]
         print array[20]
@@ -1371,7 +1402,7 @@ class MemSizedArray(MemArray):
     """A fixed size MemArray.
 
     This type is dynamically sized. Generate a fixed @field_type and @array_len
-    array which has a static size by using Array(type, size).pinned.
+    array which has a static size by using Array(type, size).lval.
     """
 
     @property
diff --git a/test/core/types.py b/test/core/types.py
index db72449c..f1ff706b 100644
--- a/test/core/types.py
+++ b/test/core/types.py
@@ -119,7 +119,7 @@ assert memval == 8
 
 # Str tests
 ## Basic tests
-memstr = Str().pinned(jitter.vm, addr_str)
+memstr = Str().lval(jitter.vm, addr_str)
 memstr.val = ""
 assert memstr.val == ""
 assert jitter.vm.get_mem(memstr.get_addr(), 1) == '\x00'
@@ -138,13 +138,13 @@ assert mstruct.s.deref.val == "That's all folks!"
 assert memstr.val == "That's all folks!"
 
 ## Other address, same value, same encoding
-memstr2 = Str().pinned(jitter.vm, addr_str2)
+memstr2 = Str().lval(jitter.vm, addr_str2)
 memstr2.val = "That's all folks!"
 assert memstr2.get_addr() != memstr.get_addr()
 assert memstr2 == memstr
 
 ## Same value, other encoding
-memstr3 = Str("utf16").pinned(jitter.vm, addr_str3)
+memstr3 = Str("utf16").lval(jitter.vm, addr_str3)
 memstr3.val = "That's all folks!"
 assert memstr3.get_addr() != memstr.get_addr()
 assert memstr3.get_size() != memstr.get_size() # Size is different
@@ -156,7 +156,7 @@ assert memstr3.val == memstr.val # But the python value is the same
 # Array tests
 # Allocate buffer manually, since memarray is unsized
 alloc_addr = my_heap.vm_alloc(jitter.vm, 0x100)
-memarray = Array(Num("I")).pinned(jitter.vm, alloc_addr)
+memarray = Array(Num("I")).lval(jitter.vm, alloc_addr)
 memarray[0] = 0x02
 assert memarray[0] == 0x02
 assert jitter.vm.get_mem(memarray.get_addr(),
@@ -188,8 +188,8 @@ except ValueError:
     pass
 
 
-memsarray = Array(Num("I"), 10).pinned(jitter.vm)
-# And Array(type, size).pinned generates statically sized types
+memsarray = Array(Num("I"), 10).lval(jitter.vm)
+# And Array(type, size).lval generates statically sized types
 assert memsarray.sizeof() == Num("I").size() * 10
 memsarray.memset('\xcc')
 assert memsarray[0] == 0xcccccccc
@@ -237,7 +237,7 @@ for val in ms2.s2:
     assert val == 1
 
 ### Field assignment (MemSizedArray)
-array2 = Array(Num("B"), 10).pinned(jitter.vm)
+array2 = Array(Num("B"), 10).lval(jitter.vm)
 jitter.vm.set_mem(array2.get_addr(), '\x02'*10)
 for val in array2:
     assert val == 2
@@ -406,8 +406,8 @@ assert b.a.deref == a
 
 # Cast tests
 # MemStruct cast
-MemInt = Num("I").pinned
-MemShort = Num("H").pinned
+MemInt = Num("I").lval
+MemShort = Num("H").lval
 dword = MemInt(jitter.vm)
 dword.val = 0x12345678
 assert isinstance(dword.cast(MemShort), MemShort)
@@ -427,7 +427,7 @@ ms2.s2[5] = 0xab
 assert MemShort(jitter.vm, ms2.s2.get_addr(4)).val == 0xabcd
 
 # void* style cast
-MemPtrVoid = Ptr("I", Void()).pinned
+MemPtrVoid = Ptr("I", Void()).lval
 p = MemPtrVoid(jitter.vm)
 p.val = mstruct.get_addr()
 assert p.deref.cast(MyStruct) == mstruct
@@ -474,17 +474,17 @@ assert BitField(Num("B"), [("f1", 1), ("f2", 4), ("f3", 1)]) != \
         BitField(Num("B"), [("f1", 2), ("f2", 4), ("f3", 1)])
 
 
-# Quick MemField.pinned/MemField hash test
-assert Num("f").pinned(jitter.vm, addr) == Num("f").pinned(jitter.vm, addr)
+# Quick MemField.lval/MemField hash test
+assert Num("f").lval(jitter.vm, addr) == Num("f").lval(jitter.vm, addr)
 # Types are cached
-assert Num("f").pinned == Num("f").pinned
-assert Num("d").pinned != Num("f").pinned
-assert Union([("f1", Num("I")), ("f2", Num("H"))]).pinned == \
-        Union([("f1", Num("I")), ("f2", Num("H"))]).pinned
-assert Array(Num("B")).pinned == Array(Num("B")).pinned
-assert Array(Num("I")).pinned != Array(Num("B")).pinned
-assert Array(Num("B"), 20).pinned == Array(Num("B"), 20).pinned
-assert Array(Num("B"), 19).pinned != Array(Num("B"), 20).pinned
+assert Num("f").lval == Num("f").lval
+assert Num("d").lval != Num("f").lval
+assert Union([("f1", Num("I")), ("f2", Num("H"))]).lval == \
+        Union([("f1", Num("I")), ("f2", Num("H"))]).lval
+assert Array(Num("B")).lval == Array(Num("B")).lval
+assert Array(Num("I")).lval != Array(Num("B")).lval
+assert Array(Num("B"), 20).lval == Array(Num("B"), 20).lval
+assert Array(Num("B"), 19).lval != Array(Num("B"), 20).lval
 
 
 # Repr tests
@@ -496,8 +496,8 @@ print repr(cont), '\n'
 print repr(uni), '\n'
 print repr(bit), '\n'
 print repr(ideas), '\n'
-print repr(Array(MyStruct2.get_type(), 2).pinned(jitter.vm, addr)), '\n'
-print repr(Num("f").pinned(jitter.vm, addr)), '\n'
+print repr(Array(MyStruct2.get_type(), 2).lval(jitter.vm, addr)), '\n'
+print repr(Num("f").lval(jitter.vm, addr)), '\n'
 print repr(memarray)
 print repr(memsarray)
 print repr(memstr)