Mercurial > paraspace
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 |