changeset 123:78357afb4a9d

Test case for restore_dependencies()
author Thinker K.F. Li <thinker@codemud.net>
date Sat, 06 Aug 2011 19:09:15 +0800
parents 6e4b6414789b
children 8e42b2816893
files paraspace/dex_deptracker.py paraspace/dexfile.py paraspace/tests/dex_deptracker_test.py
diffstat 3 files changed, 81 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/paraspace/dex_deptracker.py	Sat Aug 06 19:07:20 2011 +0800
+++ b/paraspace/dex_deptracker.py	Sat Aug 06 19:09:15 2011 +0800
@@ -777,6 +777,13 @@
     return depon_dep_map
 
 
+## \brief Update offset for all relocatable of a DEXFile.
+#
+# Update offset of instances of \ref _dex_type.
+#
+# \param dexroot is a linked (called build_dependencies()) \ref DEXFile.
+# \param all_dep_decls is a dictionary returned by prepare_dep_decls().
+#
 def update_offset(dexroot, all_dep_decls):
     from dexfile import man_off
 
@@ -794,10 +801,10 @@
         return name_path
     
     moff = man_off(0)
-    queue = [(dexroot, 'DEXFile')]
+    queue = [(dexroot, 'DEXFile', None)]
     
     while queue:
-        obj, name_path = queue.pop()
+        obj, name_path, parent = queue.pop()
         
         obj_clazz, parent_clazz = _resolve_name_path(name_path)
         if isinstance(obj_clazz, dexfile.depend):
@@ -818,7 +825,7 @@
             pass
 
         if isinstance(obj, (tuple, list)):
-            attrs = [(elt, make_path(elt, name_path, str(idx)))
+            attrs = [(elt, make_path(elt, name_path, str(idx)), obj)
                      for idx, elt in enumerate(obj)]
             attrs.reverse()
             queue = queue + attrs
@@ -828,14 +835,19 @@
             continue
 
         if not isinstance(obj, dexfile.relocatable):
-            clazz, parent = _resolve_name_path(name_path)
-            moff(clazz.sizeof(obj))
+            #if isinstance(obj_clazz, dexfile.auto_align):
+            #    obj = obj_clazz.recompute_align(moff())
+            #    print '%s %x %d' % (name_path, moff(), obj)
+            #    name = name_path.split('.')[-1]
+            #    _dex_tree_set_child(parent, name, obj)
+            #    pass
+            moff(obj_clazz.sizeof(obj))
             continue
         
         children = obj.children()
         attr_n_names = [(_dex_tree_get_child(obj, child_name), child_name)
                       for child_name in children]
-        attrs = [(attr, make_path(attr, name_path, attr_name))
+        attrs = [(attr, make_path(attr, name_path, attr_name), obj)
                  for attr, attr_name in attr_n_names]
         attrs.reverse()
         queue = queue + attrs
@@ -844,6 +856,8 @@
 
 
 def _sync_dex_header(dex):
+    from paraspace.dexfile import auto_align
+    
     header = dex.header
     map_items = dex.maps.items.items
     for map_item in map_items:
@@ -896,10 +910,15 @@
         
         data_sz = obj.sizeof(obj)
         map_item.offset = moff(data_sz)
+        if attr_name == 'maps':
+            padding_sz = dexfile.auto_align.sizeof(dex.maps.padding)
+            map_item.offset = map_item.offset + padding_sz
+            pass
+        
         if attr_name not in ('maps', 'header'):
             map_item.size = len(obj.items)
         else:
-            map_item.size = obj.sizeof(obj)
+            map_item.size = 1
             pass
         pass
     pass
@@ -917,6 +936,8 @@
 ## \brief Restore to raw value before linking for dependencies.
 #
 def restore_dependencies(dexroot, all_dep_decls):
+    update_offset(dexroot, all_dep_decls)
+    
     for obj, parents, name_path in \
             _travel_dex_relocatable(dexroot):
         if name_path not in all_dep_decls:
--- a/paraspace/dexfile.py	Sat Aug 06 19:07:20 2011 +0800
+++ b/paraspace/dexfile.py	Sat Aug 06 19:09:15 2011 +0800
@@ -305,11 +305,14 @@
     def __init__(self, bits):
         self.bits = bits
         pass
-    
-    def parse(self, parent, data, off):
+
+    def recompute_align(self, off):
         mask = (1 << self.bits) - 1
         padding_sz = ((off + mask) & ~mask) - off
         return padding_sz
+    
+    def parse(self, parent, data, off):
+        return self.recompute_align(off)
 
     @staticmethod
     def sizeof(v):
@@ -891,10 +894,11 @@
 
 
 class _DEX_MapItemBlock(composite):
+    padding = auto_align(2)
     num = uint32
     items = array('num', _DEX_MapItem)
 
-    child_names = 'num items'.split()
+    child_names = 'padding num items'.split()
     pass
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/paraspace/tests/dex_deptracker_test.py	Sat Aug 06 19:09:15 2011 +0800
@@ -0,0 +1,46 @@
+from paraspace.dexfile import DEXFile, DEXFile_linked
+from paraspace.dex_deptracker import prepare_dep_decls
+from paraspace.dex_deptracker import restore_dependencies
+import os
+
+def restore_dependencies_test():
+    from paraspace.dexfile import _DEX_StringId
+    
+    srcdir = os.path.dirname(__file__)
+    srcroot = os.path.join(srcdir, '..', '..')
+    datadir = os.path.join(srcroot, 'data')
+    helloworld_path = os.path.join(datadir, 'helloworld.dex')
+    
+    decls = prepare_dep_decls()
+    
+    hello_dex = DEXFile.open(helloworld_path)
+    strids_size_saved = hello_dex.header.stringIdsSize
+    typeids_off_saved = hello_dex.header.typeIdsOff
+    data_off_saved = hello_dex.header.dataOff
+    map_off_saved = hello_dex.header.mapOff
+    file_sz_saved = hello_dex.header.fileSize
+    for map_item in hello_dex.maps.items.items:
+        print '%d %x' % (map_item.type, map_item.offset)
+        pass
+
+    hello_linked = DEXFile_linked.build_dependencies(hello_dex, decls)
+    
+    first_strid = hello_linked.stringIds.items[0]
+    strid = _DEX_StringId()
+    strid.stringDataOff = first_strid.stringDataOff
+    hello_linked.stringIds.items.append(strid)
+
+    restore_dependencies(hello_linked, decls)
+
+    print file_sz_saved, hello_linked.header.fileSize
+    print map_off_saved, hello_linked.header.mapOff
+    for map_item in hello_linked.maps.items.items:
+        print '%d %x' % (map_item.type, map_item.offset)
+        pass
+
+    assert hello_linked.header.fileSize == (file_sz_saved + 4)
+    assert hello_linked.header.stringIdsSize == (strids_size_saved + 1)
+    assert hello_linked.header.typeIdsOff == (typeids_off_saved + 4)
+    assert hello_linked.header.dataOff == (data_off_saved + 4)
+    assert hello_linked.header.mapOff == (map_off_saved + 4)
+    pass