1/* 2 * Copyright 2011, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32package org.jf.dexlib.Code.Analysis; 33 34import org.jf.dexlib.Code.OdexedInvokeInline; 35import org.jf.dexlib.Code.OdexedInvokeVirtual; 36 37import java.io.*; 38import java.util.ArrayList; 39import java.util.List; 40import java.util.regex.Matcher; 41import java.util.regex.Pattern; 42 43public class CustomInlineMethodResolver extends InlineMethodResolver { 44 private DeodexUtil.InlineMethod[] inlineMethods; 45 46 public CustomInlineMethodResolver(String inlineTable) { 47 FileReader fr = null; 48 try { 49 fr = new FileReader(inlineTable); 50 } catch (FileNotFoundException ex) { 51 throw new RuntimeException("Could not find inline table file: " + inlineTable); 52 } 53 54 List<String> lines = new ArrayList<String>(); 55 56 BufferedReader br = new BufferedReader(fr); 57 58 try { 59 String line = br.readLine(); 60 61 while (line != null) { 62 if (line.length() > 0) { 63 lines.add(line); 64 } 65 66 line = br.readLine(); 67 } 68 } catch (IOException ex) { 69 throw new RuntimeException("Error while reading file: " + inlineTable, ex); 70 } 71 72 inlineMethods = new DeodexUtil.InlineMethod[lines.size()]; 73 74 for (int i=0; i<inlineMethods.length; i++) { 75 inlineMethods[i] = parseAndResolveInlineMethod(lines.get(i)); 76 } 77 } 78 79 @Override 80 public DeodexUtil.InlineMethod resolveExecuteInline(AnalyzedInstruction analyzedInstruction) { 81 assert analyzedInstruction.instruction instanceof OdexedInvokeInline; 82 83 OdexedInvokeInline instruction = (OdexedInvokeInline)analyzedInstruction.instruction; 84 int methodIndex = instruction.getInlineIndex(); 85 86 if (methodIndex < 0 || methodIndex >= inlineMethods.length) { 87 throw new RuntimeException("Invalid method index: " + methodIndex); 88 } 89 return inlineMethods[methodIndex]; 90 } 91 92 private static final Pattern longMethodPattern = Pattern.compile("(L[^;]+;)->([^(]+)\\(([^)]*)\\)(.+)"); 93 94 private DeodexUtil.InlineMethod parseAndResolveInlineMethod(String inlineMethod) { 95 Matcher m = longMethodPattern.matcher(inlineMethod); 96 if (!m.matches()) { 97 assert false; 98 throw new RuntimeException("Invalid method descriptor: " + inlineMethod); 99 } 100 101 String className = m.group(1); 102 String methodName = m.group(2); 103 String methodParams = m.group(3); 104 String methodRet = m.group(4); 105 106 ClassPath.ClassDef classDef = ClassPath.getClassDef(className, false); 107 int methodType = classDef.getMethodType(String.format("%s(%s)%s", methodName, methodParams, methodRet)); 108 109 if (methodType == -1) { 110 throw new RuntimeException("Cannot resolve inline method: " + inlineMethod); 111 } 112 113 return new DeodexUtil.InlineMethod(methodType, className, methodName, methodParams, methodRet); 114 } 115} 116