changeset 98:c0c127c7b37e

Check and fix issues of map sizes
author Thinker K.F. Li <thinker@codemud.net>
date Mon, 25 Jul 2011 20:37:32 +0800
parents 00cd331f8aa8
children 3898711adb2c
files paraspace/dexfile.py paraspace/injection.py paraspace/tests/injection_test.py
diffstat 3 files changed, 49 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/paraspace/dexfile.py	Mon Jul 25 17:46:20 2011 +0800
+++ b/paraspace/dexfile.py	Mon Jul 25 20:37:32 2011 +0800
@@ -979,7 +979,8 @@
     child_names = \
         'classIdx accessFlags superclassIdx interfacesOff interfacesOffRef ' \
         'sourceFileIdx annotationsOff annotationsOffRef ' \
-        'classDataOff staticValuesOff staticValuesOffRef'.split()
+        'classDataOff classDataOffRef staticValuesOff ' \
+        'staticValuesOffRef'.split()
     pass
 
 
@@ -1702,10 +1703,28 @@
             pass
         raise ValueError, 'can not find class definition for \'%s\'' % (name)
 
+    ## \brief Update size of map items.
+    #
+    # Corresponding data lists of maps may be changed, it should be updated
+    # before restore dependencies and keep it consistent.
+    #
+    def _update_map_sizes(self):
+        for mapitem in self.maps.items.items:
+            attr = DEXFile.block_defs[mapitem.type]
+            datalist = getattr(self, attr)
+            if isinstance(datalist, array):
+                mapitem.size = len(datalist.items)
+                pass
+            pass
+        pass
+
+    ## \brief Return an unlinked version.
     def get_unlinked(self):
         from paraspace.dex_deptracker import restore_dependencies
+
+        self._update_map_sizes()
+        
         unlinked = DEXFile()
-        
         for attr, value in self.__dict__.items():
             setattr(unlinked, attr, value)
             pass
--- a/paraspace/injection.py	Mon Jul 25 17:46:20 2011 +0800
+++ b/paraspace/injection.py	Mon Jul 25 20:37:32 2011 +0800
@@ -37,10 +37,17 @@
 def dex_type_2_array_attr_map():
     global dex_type_2_array_attr_map
     from paraspace.dexfile import DEXFile, array
+    from paraspace.dex_deptracker import _marker
+
+    def skip_marker_type(clazz):
+        while isinstance(clazz, _marker):
+            clazz = clazz.back_type
+            pass
+        return clazz
     
     attr_values = [(attr, getattr(DEXFile, attr))
                    for attr in dir(DEXFile)]
-    type_2_attr = dict([(value.child_type, attr)
+    type_2_attr = dict([(skip_marker_type(value.child_type), attr)
                         for attr, value in attr_values
                         if isinstance(value, array)])
     
--- a/paraspace/tests/injection_test.py	Mon Jul 25 17:46:20 2011 +0800
+++ b/paraspace/tests/injection_test.py	Mon Jul 25 20:37:32 2011 +0800
@@ -19,6 +19,14 @@
     pass
 
 
+def _find_map(dex, map_type):
+    for map in dex.maps.items.items:
+        if map.type == map_type:
+            return map
+        pass
+    pass
+
+
 def inject_fakefile_to_helloworld_test():
     from paraspace.dex_deptracker import prepare_dep_decls
     from paraspace.injection import dexfile_insert_class
@@ -32,6 +40,10 @@
     
     helloworld_fn = os.path.join(srcroot, 'data', 'helloworld.dex')
     helloworld_dex = dexfile.DEXFile.open(helloworld_fn)
+
+    classdef_map = _find_map(helloworld_dex, 0x0006)
+    saved_classdef_map_sz = classdef_map.size
+
     helloworld_linked = \
         dexfile.DEXFile_linked.build_dependencies(helloworld_dex,
                                                   all_dep_decls)
@@ -45,11 +57,18 @@
     fakefile_def = fakefile_linked. \
         find_class_name('Lcom/codemud/fakefile/fakefile;')
 
-    clone = dexfile_insert_class(helloworld_dex, fakefile_def)
+    clone = dexfile_insert_class(helloworld_linked, fakefile_def)
     assert clone
     assert clone != fakefile_def
 
     helloworld_unlinked = helloworld_linked.get_unlinked()
     assert helloworld_unlinked
+
+    # map size for classdef must be increased by 1
+    classdef_map = _find_map(helloworld_unlinked, 0x0006)
+    assert classdef_map.size == saved_classdef_map_sz + 1
+
+    classdata_map = _find_map(helloworld_unlinked, 0x2000)
+    assert classdata_map.size == classdef_map.size
     pass