changeset 4:b0766f1984bb

parse annotationsDirectoryItem
author Thinker K.F. Li <thinker@codemud.net>
date Tue, 24 May 2011 09:56:53 +0800
parents a78db169b0c8
children 97b7006ced5f
files paraspace/dexfile.py
diffstat 1 files changed, 145 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/paraspace/dexfile.py	Mon May 23 21:44:58 2011 +0800
+++ b/paraspace/dexfile.py	Tue May 24 09:56:53 2011 +0800
@@ -58,7 +58,7 @@
         self.off = off
         pass
 
-    def __call__(self, sz):
+    def __call__(self, sz=0):
         off = self.off
         self.off = off + sz
         return off
@@ -550,8 +550,23 @@
     pass
 
 
+## \brief File offset to Annotation item.
+#
+# This type is not in libdex of Dalvik.  We add this class to tracking
+# information for layout algorithm.
+#
+class _DEX_AnnotationRefItem(object):
+    annotationOff = None        # 4 bytes
+
+    data_size = 4
+
+    def parse(self, data, off):
+        self.annotationOff = _to_uint(data[off:off + 4])
+        pass
+    pass
+
 class _DEX_AnnotationSetItem(object):
-    size = None                 # 4 bytes
+    # size = None                 # 4 bytes
     annotations = None          # 4 * size bytes
 
     data_size = None
@@ -559,11 +574,109 @@
     def parse(self, data, off):
         moff = man_off(off)
         
-        self.size = _to_uint(data[moff(4):moff(0)])
-        self.annotations = [_to_uint(data[moff(4):moff(0)])
-                            for i in range(self.size)]
+        size = _to_uint(data[moff(4):moff()])
+        
+        def parse_annotation_ref():
+            ref = _DEX_AnnotationRefItem()
+            ref.parse(data, moff())
+            moff(ref.data_size)
+            return ref
+        
+        self.annotations = [parse_annotation_ref()
+                            for i in range(size)]
+
+        self.data_size = moff() - off
+        pass
+    pass
+
+
+class _DEX_FieldAnnotationsItem(object):
+    fieldIdx = None             # 4 bytes
+    annotationsOff = None       # 4 bytes
+
+    data_size = 8
+
+    def parse(self, data, off):
+        moff = man_off(off)
+
+        self.fieldIdx = _to_uint(data[moff(4):moff()])
+        self.annotationsOff = _to_uint(data[moff(4):moff()])
+        pass
+    pass
+
+
+class _DEX_MethodAnnotationsItem(object):
+    methodIdx = None            # 4 bytes
+    annotationsOff = None       # 4 bytes
+
+    data_size = 8
+
+    def parse(self, data, off):
+        moff = man_off(off)
+
+        self.methodIdx = _to_uint(data[moff(4):moff()])
+        self.annotationsOff = _to_uint(data[moff(4):moff()])
+        pass
+    pass
+
+
+class _DEX_ParameterAnnotationsItem(object):
+    methodIdx = None            # 4 bytes
+    annotationsOff = None       # 4 bytes
+
+    data_size = 8
 
-        self.data_size = moff(0) - off
+    def parse(self, data, off):
+        moff = man_off(off)
+
+        self.methodIdx = _to_uint(data[moff(4):moff()])
+        self.annotationsOff = _to_uint(data[moff(4):moff()])
+        pass
+    pass
+
+
+class _DEX_AnnotationsDirectoryItem(object):
+    classAnnotationsOff = None  # 4 bytes
+    fieldAnnotationsItems = None
+    methodAnnotationsItems = None
+    parameterAnnotationsItems = None
+
+    data_size = None
+
+    def parse(self, data, off):
+        moff = man_off(off)
+
+        self.classAnnotationsOff = _to_uint(data[moff(4):moff()])
+        fieldsSize = _to_uint(data[moff(4):moff()])
+        methodsSize = _to_uint(data[moff(4):moff()])
+        parametersSize = _to_uint(data[moff(4):moff()])
+
+        def parse_fieldAnnotationsItem():
+            item = _DEX_FieldAnnotationsItem()
+            item.parse(data, moff())
+            moff(item.data_size)
+            return item
+        
+        def parse_methodAnnotationsItem():
+            item = _DEX_MethodAnnotationsItem()
+            item.parse(data, moff())
+            moff(item.data_size)
+            return item
+        
+        def parse_parameterAnnotationsItem():
+            item = _DEX_ParameterAnnotationsItem()
+            item.parse(data, moff())
+            moff(item.data_size)
+            return item
+        
+        self.fieldAnnotationsItems = [parse_fieldAnnotationsItem()
+                                      for i in range(fieldsSize)]
+        self.methodAnnotationsItems = [parse_methodAnnotationsItem()
+                                       for i in range(methodsSize)]
+        self.parameterAnnotationsItems = [parse_parameterAnnotationsItem()
+                                          for i in range(parametersSize)]
+        
+        self.data_size = moff() - off
         pass
     pass
 
@@ -582,6 +695,7 @@
     _typeLists = None
     _codeItems = None
     _annotationSetItems = None
+    _annotationsDirectoryItems = None
     
     def __init__(self):
         pass
@@ -821,7 +935,7 @@
         
         def parse_annotationSetItem():
             item = _DEX_AnnotationSetItem()
-            item.parse(data, moff(0))
+            item.parse(data, moff())
             moff(item.data_size)
             return item
         
@@ -829,6 +943,24 @@
                                     for i in range(annoset_map.size)]
         pass
 
+    def _parse_annotationsDirectoryItems(self):
+        data = self._data
+        
+        annodir_map = \
+            self.find_map_item_name('kDexTypeAnnotationsDirectoryItem')
+        
+        moff = man_off(annodir_map.offset)
+        
+        def parse_annotationDirItem():
+            item = _DEX_AnnotationsDirectoryItem()
+            item.parse(data, moff())
+            moff(item.data_size)
+            return item
+        
+        self._annotationsDirectoryItems = [parse_annotationDirItem()
+                                           for i in range(annodir_map.size)]
+        pass
+
     def parse(self, data):
         self._data = data
         header = _DEX_header()
@@ -846,6 +978,7 @@
         self._parse_typeLists()
         self._parse_codeItems()
         self._parse_annotationSetItems()
+        self._parse_annotationsDirectoryItems()
         pass
     pass
 
@@ -909,6 +1042,11 @@
     print
     print 'AnnotationSetItems size is %d bytes' % (bytes)
     
+    bytes = sum([annodir.data_size
+                 for annodir in dex._annotationsDirectoryItems])
+    print
+    print 'AnnotationsDirtoryItems size is %d bytes' % (bytes)
+    
     print
     print 'Data maps'
     maps = dex._maps