# HG changeset patch # User Thinker K.F. Li # Date 1312726028 -28800 # Node ID 8e42b2816893a7397c43ffd1a8782c89b8e6ae7f # Parent 78357afb4a9ddd74df5758a5fabaf6a0454fc5df Fixing compute_size() and sizeof() for DEX types. - Prevent compute_size() and sizeof() of depend_* to include size of depend-on. diff -r 78357afb4a9d -r 8e42b2816893 paraspace/dex_deptracker.py --- a/paraspace/dex_deptracker.py Sat Aug 06 19:09:15 2011 +0800 +++ b/paraspace/dex_deptracker.py Sun Aug 07 22:07:08 2011 +0800 @@ -298,12 +298,19 @@ return all_dep_decls +## Mark where we need offset information for link dependencies. +# class _marker(dexfile.null_relocatable): back_type = None def set_marker(self, obj, off): raise NotImplementedError, \ 'The marker does not implement set_marker()' + + ## \brief Prepare data_offset for linking. + def link_prepare(self, obj, name_path, parents, markers_info): + raise NotImplementedError, \ + '_marker should be used to instantiate an instance directly' pass class _uid_marker(_marker): @@ -730,6 +737,7 @@ depon2 = _rel_offset_marker.find_depon(dep[2], parents) offset = depon2.data_offset + obj depon1 = markers_info[dep[1]][offset] + dep_type._depon2_log[depon1] = depon2 name = name_path.split('.')[-1] _dex_tree_set_child(imm_parent, name, depon1) @@ -785,7 +793,7 @@ # \param all_dep_decls is a dictionary returned by prepare_dep_decls(). # def update_offset(dexroot, all_dep_decls): - from dexfile import man_off + from paraspace.dexfile import man_off depon_dep_map = _build_depon_dep_map(all_dep_decls) dex_type_names = _all_dex_type_to_names() @@ -835,12 +843,11 @@ continue if not isinstance(obj, dexfile.relocatable): - #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 + if isinstance(obj_clazz, dexfile.auto_align): + obj = obj_clazz.recompute_align(moff()) + name = name_path.split('.')[-1] + _dex_tree_set_child(parent, name, obj) + pass moff(obj_clazz.sizeof(obj)) continue diff -r 78357afb4a9d -r 8e42b2816893 paraspace/dexfile.py --- a/paraspace/dexfile.py Sat Aug 06 19:09:15 2011 +0800 +++ b/paraspace/dexfile.py Sun Aug 07 22:07:08 2011 +0800 @@ -109,8 +109,8 @@ def _compute_sz(o, _type): if hasattr(o, 'compute_size'): - o.compute_size() - return o.data_size + _type.compute_size(o) + pass return _type.sizeof(o) @@ -190,6 +190,10 @@ def parse(parent, data, off): v = _to_uint(data[off:off + 4]) return v + + @staticmethod + def compute_size(v): + pass @staticmethod def sizeof(v): @@ -209,6 +213,10 @@ return v @staticmethod + def compute_size(v): + pass + + @staticmethod def sizeof(v): return 2 @@ -225,6 +233,10 @@ return v @staticmethod + def compute_size(v): + pass + + @staticmethod def sizeof(v): return 1 @@ -241,6 +253,10 @@ return v @staticmethod + def compute_size(v): + pass + + @staticmethod def sizeof(v): return 4 @@ -258,6 +274,10 @@ return v @staticmethod + def compute_size(v): + pass + + @staticmethod def sizeof(v): return 2 @@ -274,6 +294,10 @@ return v @staticmethod + def compute_size(v): + pass + + @staticmethod def sizeof(v): return _uleb128_sz(v) @@ -290,6 +314,10 @@ return v @staticmethod + def compute_size(v): + pass + + @staticmethod def sizeof(v): return _leb128_sz(v) @@ -315,6 +343,10 @@ return self.recompute_align(off) @staticmethod + def compute_size(v): + pass + + @staticmethod def sizeof(v): return v @@ -377,6 +409,7 @@ def to_str(self): return '' + @staticmethod def compute_size(self): pass @@ -457,7 +490,7 @@ return 0 @staticmethod - def compute_size(): + def compute_size(self): pass @staticmethod @@ -535,6 +568,7 @@ obj.data_size = moff() - off return obj + @staticmethod def compute_size(self): sizes = [_compute_sz(item, self.child_type) for item in self.items] @@ -640,6 +674,7 @@ return 0 return self.child_type.sizeof(v.value) + @staticmethod def compute_size(self): if self.is_true: self.data_size = _compute_sz(self.value, self.child_type) @@ -705,6 +740,7 @@ def sizeof(v): return v.child_type.sizeof(v.value) + @staticmethod def compute_size(self): self.data_size = _compute_sz(self.value, self.child_type) pass @@ -742,6 +778,12 @@ pass +## \brief Make a dependency to a depend-on for back type. +# +# Depend-on is the object that the back type is supposed to point to. +# Back type of a depend must be not a composite type while depend-on +# must be. +# class depend(null_relocatable): depend_on = None @@ -750,6 +792,7 @@ pass def __call__(self, back_type): + assert type(back_type) != type or not issubclass(back_type, composite) self.back_type = back_type return self @@ -792,16 +835,38 @@ class depend_off(depend): + def compute_size(self, child): + pass + + def sizeof(self, child): + if isinstance(child, composite): + return self.back_type.sizeof(child.data_offset) + return self.back_type.sizeof(child) pass class depend_off_rel(depend): relative_to = None + _depon2_log = {} def __init__(self, relative_to, depend_on): super(depend_off_rel, self).__init__(depend_on) self.relative_to = relative_to pass + + def parse(self, parent, data, off): + v = super(depend_off_rel, self).parse(parent, data, off) + return v + + def compute_size(self, child): + pass + + def sizeof(self, child): + if isinstance(child, composite): + pivot = self._depon2_log[child] # depon2 + off_diff = child.data_offset - pivot.data_offset + return self.back_type.sizeof(off_diff) + return self.back_type.sizeof(child) pass @@ -823,7 +888,14 @@ pass v = self.back_type.sizeof(v) return v + + def compute_size(self, child): pass + + def sizeof(self, child): + if isinstance(child, composite): + return self.back_type.sizeof(child.data_idx) + return self.back_type.sizeof(child) pass @@ -1309,7 +1381,7 @@ pass -class _DEX_DebugCodeBlock(relocatable): +class _DEX_DebugCodeBlock(_dex_type): DBG_END_SEQUENCE = 0x00 DBG_ADVANCE_PC = 0x01 DBG_ADVANCE_LINE = 0x02 @@ -1434,6 +1506,10 @@ self.data_size = opcodes_size pass + + @staticmethod + def sizeof(obj): + return obj.data_size @staticmethod def to_str(self): diff -r 78357afb4a9d -r 8e42b2816893 paraspace/tests/dex_deptracker_test.py --- a/paraspace/tests/dex_deptracker_test.py Sat Aug 06 19:09:15 2011 +0800 +++ b/paraspace/tests/dex_deptracker_test.py Sun Aug 07 22:07:08 2011 +0800 @@ -1,10 +1,65 @@ -from paraspace.dexfile import DEXFile, DEXFile_linked +from paraspace import dexfile from paraspace.dex_deptracker import prepare_dep_decls from paraspace.dex_deptracker import restore_dependencies import os + +def _install_dexfile_4_deptracker(): + global dexfile + import imp, sys + from paraspace import dex_deptracker + from paraspace import injection + + try: + new_dexfile = imp.load_compiled('paraspace.dexfile', dexfile.__file__) + except ImportError: + new_dexfile = imp.load_source('paraspace.dexfile', dexfile.__file__) + pass + dex_deptracker.dexfile = new_dexfile + dexfile = new_dexfile + dex_deptracker._nest_types = (dexfile.array, dexfile.cond, dexfile.switch) + + injection.dex_type_2_array_attr_map = \ + injection._saved_dex_type_2_array_attr_map + + sys.modules['paraspace.dexfile'] = new_dexfile + pass + + +def update_offset_test(): + from paraspace.dex_deptracker import collect_all_dep_decls + from paraspace.dex_deptracker import build_dependencies + from paraspace.dex_deptracker import _install_markers + from paraspace.dex_deptracker import _patch_dex_type_markers + from paraspace.dex_deptracker import update_offset + + _install_dexfile_4_deptracker() + + all_dep_decls = collect_all_dep_decls() + _install_markers(all_dep_decls) + _patch_dex_type_markers(all_dep_decls) + + srcdir = os.path.dirname(__file__) + srcroot = os.path.join(srcdir, '..', '..') + testdatapath = os.path.join(srcroot, 'data', 'testdata1.dex') + dex = dexfile.DEXFile.open(testdatapath) + + build_dependencies(dex, all_dep_decls) + + offset0 = dex.typeLists.items[0].value.data_offset + dex.typeLists.items[0].value.data_offset = 0 + offset1 = dex.typeLists.items[1].value.data_offset + dex.typeLists.items[1].value.data_offset = 0 + + update_offset(dex, all_dep_decls) + + assert dex.typeLists.items[0].value.data_offset == offset0 + assert dex.typeLists.items[1].value.data_offset == offset1 + pass + + def restore_dependencies_test(): - from paraspace.dexfile import _DEX_StringId + _install_dexfile_4_deptracker() srcdir = os.path.dirname(__file__) srcroot = os.path.join(srcdir, '..', '..') @@ -13,34 +68,114 @@ decls = prepare_dep_decls() - hello_dex = DEXFile.open(helloworld_path) + hello_dex = dexfile.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) + hello_linked = dexfile.DEXFile_linked.build_dependencies(hello_dex, decls) first_strid = hello_linked.stringIds.items[0] - strid = _DEX_StringId() + strid = dexfile._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 + + +def sizoef_after_build_dep_test(): + from paraspace.dex_deptracker import update_offset + + _install_dexfile_4_deptracker() + + 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.DEXFile.open(helloworld_path) + update_offset(hello_dex, decls) + + get_sz = lambda x: x.sizeof(x) + assert get_sz(hello_dex.header) == 112 + assert get_sz(hello_dex.stringIds) == 0x168 + assert get_sz(hello_dex.typeIds) == (0x250-0x1d8) + assert get_sz(hello_dex.protoIds) == (0x31c-0x250) + assert get_sz(hello_dex.fieldIds) == (0x354-0x31c) + assert get_sz(hello_dex.methodIds) == (0x46c-0x354) + assert get_sz(hello_dex.classDefs) == (0x58c-0x46c) + assert get_sz(hello_dex.annotationSetItems) == (0x5dc-0x58c) + assert get_sz(hello_dex.codeItems) == (0x8b8-0x5dc) + assert get_sz(hello_dex.annotationsDirectoryItems) == (0x928-0x8b8) + assert get_sz(hello_dex.typeLists) == (0x98a-0x928) + assert get_sz(hello_dex.stringDataItems) == (0xe7d-0x98a) + assert get_sz(hello_dex.debugInfoItems) == (0xf31-0xe7d) + assert get_sz(hello_dex.annotationItems) == (0xf82-0xf31) + assert get_sz(hello_dex.encodedArrayItems) == (0xf9d-0xf82) + assert get_sz(hello_dex.classDatas) == (0x1024-0xf9d-1) + assert hello_dex.maps.sizeof(hello_dex.maps) == 0xd0 + + hello_dex.compute_size() + unlinked_sz = hello_dex.sizeof(hello_dex) + assert unlinked_sz == hello_dex.header.fileSize + + hello_linked = dexfile.DEXFile_linked.build_dependencies(hello_dex, decls) + + hello_linked.compute_size() + linked_sz = hello_linked.sizeof(hello_linked) + + assert get_sz(hello_linked.header) == 112 + assert get_sz(hello_linked.stringIds) == 0x168 + assert get_sz(hello_linked.typeIds) == (0x250-0x1d8) + assert get_sz(hello_linked.protoIds) == (0x31c-0x250) + assert get_sz(hello_linked.fieldIds) == (0x354-0x31c) + assert get_sz(hello_linked.methodIds) == (0x46c-0x354) + assert get_sz(hello_linked.classDefs) == (0x58c-0x46c) + assert get_sz(hello_linked.annotationSetItems) == (0x5dc-0x58c) + assert get_sz(hello_linked.codeItems) == (0x8b8-0x5dc) + assert get_sz(hello_linked.annotationsDirectoryItems) == (0x928-0x8b8) + assert get_sz(hello_linked.typeLists) == (0x98a-0x928) + assert get_sz(hello_linked.stringDataItems) == (0xe7d-0x98a) + assert get_sz(hello_linked.debugInfoItems) == (0xf31-0xe7d) + assert get_sz(hello_linked.annotationItems) == (0xf82-0xf31) + assert get_sz(hello_linked.encodedArrayItems) == (0xf9d-0xf82) + + assert linked_sz == unlinked_sz + + first_strid = hello_linked.stringIds.items[0] + strid = dexfile._DEX_StringId() + strid.stringDataOff = first_strid.stringDataOff + hello_linked.stringIds.items.append(strid) + + hello_linked.compute_size() + linked_sz = hello_linked.sizeof(hello_linked) + + assert get_sz(hello_linked.header) == 112 + assert get_sz(hello_linked.stringIds) == 0x16c + assert get_sz(hello_linked.typeIds) == (0x250-0x1d8) + assert get_sz(hello_linked.protoIds) == (0x31c-0x250) + assert get_sz(hello_linked.fieldIds) == (0x354-0x31c) + assert get_sz(hello_linked.methodIds) == (0x46c-0x354) + assert get_sz(hello_linked.classDefs) == (0x58c-0x46c) + assert get_sz(hello_linked.annotationSetItems) == (0x5dc-0x58c) + assert get_sz(hello_linked.codeItems) == (0x8b8-0x5dc) + assert get_sz(hello_linked.annotationsDirectoryItems) == (0x928-0x8b8) + assert get_sz(hello_linked.typeLists) == (0x98a-0x928) + assert get_sz(hello_linked.stringDataItems) == (0xe7d-0x98a) + assert get_sz(hello_linked.debugInfoItems) == (0xf31-0xe7d) + assert get_sz(hello_linked.annotationItems) == (0xf82-0xf31) + assert get_sz(hello_linked.encodedArrayItems) == (0xf9d-0xf82) + + assert linked_sz == (unlinked_sz + 4) + pass diff -r 78357afb4a9d -r 8e42b2816893 paraspace/tests/dexfile_test.py --- a/paraspace/tests/dexfile_test.py Sat Aug 06 19:09:15 2011 +0800 +++ b/paraspace/tests/dexfile_test.py Sun Aug 07 22:07:08 2011 +0800 @@ -279,38 +279,6 @@ pass -def update_offset_test(): - from paraspace.dex_deptracker import collect_all_dep_decls - from paraspace.dex_deptracker import build_dependencies - from paraspace.dex_deptracker import _install_markers - from paraspace.dex_deptracker import _patch_dex_type_markers - from paraspace.dex_deptracker import update_offset - - _install_dexfile_4_deptracker() - - all_dep_decls = collect_all_dep_decls() - _install_markers(all_dep_decls) - _patch_dex_type_markers(all_dep_decls) - - srcdir = os.path.dirname(__file__) - srcroot = os.path.join(srcdir, '..', '..') - testdatapath = os.path.join(srcroot, 'data', 'testdata1.dex') - dex = dexfile.DEXFile.open(testdatapath) - - build_dependencies(dex, all_dep_decls) - - offset0 = dex.typeLists.items[0].value.data_offset - dex.typeLists.items[0].value.data_offset = 0 - offset1 = dex.typeLists.items[1].value.data_offset - dex.typeLists.items[1].value.data_offset = 0 - - update_offset(dex, all_dep_decls) - - assert dex.typeLists.items[0].value.data_offset == offset0 - assert dex.typeLists.items[1].value.data_offset == offset1 - pass - - def restore_dependencies_test(): from paraspace.dex_deptracker import collect_all_dep_decls from paraspace.dex_deptracker import build_dependencies