comparison paraspace/injection.py @ 108:18be67af7f1e

Use method redirection map for defining redirection
author Thinker K.F. Li <thinker@codemud.net>
date Mon, 01 Aug 2011 12:27:28 +0800
parents 4b3573d039af
children 835336632aba
comparison
equal deleted inserted replaced
107:4b3573d039af 108:18be67af7f1e
215 def dexfile_insert_class(dex, class_def): 215 def dexfile_insert_class(dex, class_def):
216 clone = _clone_classdef(dex, class_def) 216 clone = _clone_classdef(dex, class_def)
217 return clone 217 return clone
218 218
219 219
220 def method_redirect_types(dex, method, redirect_map): 220 ## \brief Redirect types and methods for the code of given method.
221 def method_redirect_types(dex, method, types_redir, methods_redir):
221 from paraspace.dalvik_opcodes import decode_insn_blk, all_opcodes 222 from paraspace.dalvik_opcodes import decode_insn_blk, all_opcodes
222 from paraspace.dalvik_opcodes import encode_opcode_vectors 223 from paraspace.dalvik_opcodes import encode_opcode_vectors
223 from paraspace.dexfile import DEXFile_linked 224 from paraspace.dexfile import DEXFile_linked
224 225
225 if not method.codeOffRef.is_true: 226 if not method.codeOffRef.is_true:
230 op_vectors = decode_insn_blk(insns_blk) 231 op_vectors = decode_insn_blk(insns_blk)
231 232
232 def redirect(opcode, args): 233 def redirect(opcode, args):
233 if opcode == all_opcodes.OP_NEW_INSTANCE: 234 if opcode == all_opcodes.OP_NEW_INSTANCE:
234 typeidx = args[1] 235 typeidx = args[1]
235 if typeidx in redirect_map: 236 if typeidx in types_redir:
236 to_type = redirect_map[typeidx] 237 to_type = types_redir[typeidx]
237 return opcode, (args[0], to_type) 238 return opcode, (args[0], to_type)
238 pass 239 pass
239 elif opcode == all_opcodes.OP_INVOKE_DIRECT: 240 elif opcode == all_opcodes.OP_INVOKE_DIRECT:
240 methodidx = args[2] 241 methodidx = args[2]
242 if methodidx not in methods_redir:
243 return opcode, args
244
245 return opcode, (args[0], args[1], methods_redir[methodidx],
246 args[3], args[4], args[5], args[6])
241 methodid = dex.find_methodid_idx(methodidx) 247 methodid = dex.find_methodid_idx(methodidx)
242 method_typeid = methodid.classIdx 248 method_typeid = methodid.classIdx
243 method_typeidx = dex.get_idx_typeid(method_typeid) 249 method_typeidx = dex.get_idx_typeid(method_typeid)
244 if method_typeidx not in redirect_map: 250 if method_typeidx not in types_redir:
245 method_typeid = dex.find_typeid_idx(method_typeidx - 1) 251 method_typeid = dex.find_typeid_idx(method_typeidx - 1)
246 return opcode, args 252 return opcode, args
247 253
248 new_method_typeidx = redirect_map[method_typeidx] 254 new_method_typeidx = types_redir[method_typeidx]
249 new_method_typeid = dex.find_typeid_idx(new_method_typeidx) 255 new_method_typeid = dex.find_typeid_idx(new_method_typeidx)
250 classdef = dex.find_class_typeid(new_method_typeid) 256 classdef = dex.find_class_typeid(new_method_typeid)
251 method_name = DEXFile_linked.get_methodid_name(methodid) 257 method_name = DEXFile_linked.get_methodid_name(methodid)
252 method_proto = methodid.protoIdx 258 method_proto = methodid.protoIdx
253 259
267 273
268 code.insns.data = new_insns_blk 274 code.insns.data = new_insns_blk
269 pass 275 pass
270 276
271 277
272 def class_redirect_types(dex, classdef, redirect_map): 278 ## \brief Make a map for methods from source type ID to ones from desinate.
279 def make_redir_classes_methods_map(dex_src, typeid_src,
280 dex_dst, typeid_dst):
281 from paraspace.dexfile import DEXFile_linked
282
283 methods_src = [(idx, methodid)
284 for idx, methodid in enumerate(dex_src.methodIds.items)
285 if methodid.classIdx == typeid_src]
286
287 def make_map_methodid(methodid_src):
288 name = DEXFile_linked.get_methodid_name(methodid_src)
289 proto = methodid_src.protoIdx
290 try:
291 methodid_dst = \
292 dex_dst.find_methodid_name_proto(name, proto, typeid_dst)
293 except ValueError:
294 return -1
295 methodidx_dst = dex_dst.get_idx_methodid(methodid_dst)
296 return methodidx_dst
297
298 methods_map = [(methodidx_src, make_map_methodid(methodid_src))
299 for methodidx_src, methodid_src in methods_src]
300 methods_map = [(methodidx_src, methodidx_dst)
301 for methodidx_src, methodidx_dst in methods_map
302 if methodidx_dst != -1]
303 methods_map = dict(methods_map)
304 return methods_map
305
306
307 ## \brief Redirect types and methods mentioned in the code of a class.
308 #
309 # For code of given class definition, Every mentions of types and
310 # methods are rewrote to types and methods according types_redir and
311 # methods_redir respectively.
312 #
313 # \param dex is a DEXFile_linked.
314 # \param classdef is a class definition.
315 # \param types_redir is a map of types.
316 # \param methods_redir is a map of methods.
317 #
318 def class_redirect_types(dex, classdef, types_redir, methods_redir):
273 if not classdef.classDataOffRef.is_true: 319 if not classdef.classDataOffRef.is_true:
274 return 320 return
275 321
276 classdata = classdef.classDataOffRef.value 322 classdata = classdef.classDataOffRef.value
277 for method in classdata.directMethods.items: 323 for method in classdata.directMethods.items:
278 method_redirect_types(dex, method, redirect_map) 324 method_redirect_types(dex, method, types_redir, methods_redir)
279 pass 325 pass
280 for method in classdata.virtualMethods.items: 326 for method in classdata.virtualMethods.items:
281 method_redirect_types(dex, method, redirect_map) 327 method_redirect_types(dex, method, types_redir, methods_redir)
282 pass 328 pass
283 pass 329 pass
284 330
285 331
286 def dexfile_redirect_types(dex, redirect_map, excludes=set([])): 332 ## \brief Make a map to map methods from source types to destinate types.
333 #
334 # This function create a map to map methods from source types to
335 # methods from destinate types in \ref types_redir.
336 #
337 # \param dex is a DEXFile_linked that owns source and destinate types.
338 # \param types_redir is a map of types for redirecting types.
339 # \return a map of method indices.
340 #
341 def _make_methods_redir_for_types_redir(dex, types_redir):
342 methods_map = {}
343 for typeidx_src, typeidx_dst in types_redir.items():
344 typeid_src = dex.find_typeid_idx(typeidx_src)
345 typeid_dst = dex.find_typeid_idx(typeidx_dst)
346 class_methods_map = make_redir_classes_methods_map(dex,
347 typeid_src,
348 dex,
349 typeid_dst)
350 methods_map.update(class_methods_map)
351 pass
352 return methods_map
353
354
355 ## \biref Redirect types of all code in given DEXFile_linked.
356 def dexfile_redirect_types(dex, types_redir, excludes=set([])):
357 methods_redir = _make_methods_redir_for_types_redir(dex, types_redir)
358
287 for classdef in dex.classDefs.items: 359 for classdef in dex.classDefs.items:
288 typeid = classdef.classIdx 360 typeid = classdef.classIdx
289 idx = dex.get_idx_typeid(typeid) 361 idx = dex.get_idx_typeid(typeid)
290 if idx in excludes: 362 if idx in excludes:
291 continue 363 continue
292 class_redirect_types(dex, classdef, redirect_map) 364 class_redirect_types(dex, classdef, types_redir, methods_redir)
293 pass 365 pass
294 pass 366 pass