# HG changeset patch # User Thinker K.F. Li # Date 1312977914 -28800 # Node ID 0704e23009e4a84ec0ac80a13599787a174f75ec # Parent 372009418896b18bc9375ff679320fb93462c52b Fix bug of not dealing encoded method indices. - Becase space optimization, DEX ecnode value for method indices in _DEX_Method. - _deoptimize_classdata() was called at beginning of build_dependencies(). - _optimize_classdata() was called at end of restore_dependencies(). diff -r 372009418896 -r 0704e23009e4 paraspace/dex_deptracker.py --- a/paraspace/dex_deptracker.py Wed Aug 10 14:28:24 2011 +0800 +++ b/paraspace/dex_deptracker.py Wed Aug 10 20:05:14 2011 +0800 @@ -805,7 +805,72 @@ pass +## \brief Deoptimize methods of classdatas. +# +# This function must be called at beginning of build_dependencies(). +# For space optimization reason, values of method index in _DEX_Method +# are related previous item, except first one. For convenient, +# this function replcae them with absolute ones. It should be reversed +# to relative one when running restore_dependencies(). +# +def _deoptimize_classdata(dexroot): + for classdata in dexroot.classDatas.items: + methods = classdata.directMethods.items + if len(methods) > 1: + firstmethod = methods[0] + lastidx = firstmethod.methodIdx + for method in methods[1:]: + lastidx = lastidx + method.methodIdx + method.methodIdx = lastidx + pass + pass + + methods = classdata.virtualMethods.items + if len(methods) > 1: + firstmethod = methods[0] + lastidx = firstmethod.methodIdx + for method in methods[1:]: + lastidx = lastidx + method.methodIdx + method.methodIdx = lastidx + pass + pass + pass + pass + + +## \biref Optimize methods of classdatas. +# +# \see _deoptimize_classdata +# +def _optimize_classdata(dexroot): + for classdata in dexroot.classDatas.items: + methods = classdata.directMethods.items + if len(methods) > 1: + firstmethod = methods[0] + lastidx = firstmethod.methodIdx + for method in methods[1:]: + save_idx = method.methodIdx + method.methodIdx = method.methodIdx - lastidx + lastidx = save_idx + pass + pass + + methods = classdata.virtualMethods.items + if len(methods) > 1: + firstmethod = methods[0] + lastidx = firstmethod.methodIdx + for method in methods[1:]: + save_idx = method.methodIdx + method.methodIdx = method.methodIdx - lastidx + lastidx = save_idx + pass + pass + pass + pass + + def build_dependencies(dexroot, all_dep_decls): + _deoptimize_classdata(dexroot) _build_associations(dexroot) _build_refs(dexroot) _link_dependencies(dexroot, all_dep_decls) @@ -1070,6 +1135,7 @@ pass _sync_DEXFile_fields(dexroot) + _optimize_classdata(dexroot) pass diff -r 372009418896 -r 0704e23009e4 paraspace/tests/injection_test.py --- a/paraspace/tests/injection_test.py Wed Aug 10 14:28:24 2011 +0800 +++ b/paraspace/tests/injection_test.py Wed Aug 10 20:05:14 2011 +0800 @@ -641,6 +641,7 @@ hello_linked.find_methodids_typeid(helloworld_typeid) for methodid in helloworld_methodids: methodname = hello_linked.get_methodid_name(methodid) + print 'TEST', methodname if methodname == 'onClick': methodidx = hello_linked.get_idx_methodid(methodid) method = hello_linked.find_method_idx(methodidx) @@ -650,6 +651,14 @@ saved_methodid0 = hello_linked.find_methodid_idx(methodidx) methodidx = opvectors[12][1][1] saved_methodid1 = hello_linked.find_methodid_idx(methodidx) + elif methodname == 'write_file': + assert methodid in hello_linked.methodIds.items + methodidx = hello_linked.get_idx_methodid(methodid) + print 'TEST', dexfile.DEXFile_linked.get_typeid_name(methodid.classIdx) + method = hello_linked.find_method_idx(methodidx) + blk = dexfile.DEXFile_linked.get_code_block_method(method) + opvectors = decode_insn_blk(blk) + print opvectors pass pass @@ -686,5 +695,59 @@ assert new_methodid1 in hello_linked.methodIds.items assert new_methodid1 is saved_methodid1 pass + elif methodname == 'write_file': + assert methodid in hello_linked.methodIds.items + methodidx = hello_linked.get_idx_methodid(methodid) + print dexfile.DEXFile_linked.get_typeid_name(methodid.classIdx) + method = hello_linked.find_method_idx(methodidx) + blk = dexfile.DEXFile_linked.get_code_block_method(method) + opvectors = decode_insn_blk(blk) + print opvectors + pass + pass + assert False + pass + + +## \brief Test case for checking methods of classdatas are consistent. +# +# Becase space optimization, DEX ecnode value for method indices +# in \ref _DEX_Method. This test case make sure build_dependencies() +# decode indices correctly. +# +# \see _deoptimize_classdata +# +def class_methods_consistent_test(): + from paraspace.dex_deptracker import prepare_dep_decls + + _install_dexfile_4_deptracker() + + all_dep_decls = prepare_dep_decls() + + srcdir = os.path.dirname(__file__) + datapath = os.path.join(srcdir, '..', '..', 'data') + + hello_path = os.path.join(datapath, 'helloworld.dex') + + hello_dex = dexfile.DEXFile.open(hello_path) + + hello_linked = dexfile.DEXFile_linked.build_dependencies(hello_dex, + all_dep_decls) + + for classdata in hello_linked.classDatas.items: + allmethods = classdata.directMethods.items + \ + classdata.virtualMethods.items + if len(allmethods) < 2: + continue + + firstmethod = allmethods[0] + firstmethodid = firstmethod.methodIdx + for idx, method in enumerate(allmethods[1:]): + try: + assert method.methodIdx.classIdx == firstmethodid.classIdx + except: + print 'ERROR: method %d' % (idx + 1) + raise + pass pass pass