1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.dex.cf; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.code.ConcreteMethod; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.code.Ropper; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.direct.DirectClassFile; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.direct.StdAttributeFactory; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.Field; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.FieldList; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.Method; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.MethodList; 273dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornsteinimport com.android.dx.dex.DexOptions; 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.DalvCode; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.PositionList; 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.RopTranslator; 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.file.ClassDefItem; 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.file.EncodedField; 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.file.EncodedMethod; 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.annotation.Annotations; 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.annotation.AnnotationsList; 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.AccessFlags; 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.LocalVariableExtractor; 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.LocalVariableInfo; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RopMethod; 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.DexTranslationAdvice; 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.TranslationAdvice; 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.Constant; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstBoolean; 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstByte; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstChar; 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstFieldRef; 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstInteger; 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstMethodRef; 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstShort; 50333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport com.android.dx.rop.cst.CstString; 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstType; 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.TypedConstant; 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type; 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeList; 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.ssa.Optimizer; 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ExceptionWithContext; 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 5999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Static method that turns {@code byte[]}s containing Java 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classfiles into {@link ClassDefItem} instances. 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class CfTranslator { 6399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** set to {@code true} to enable development-time debugging code */ 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final boolean DEBUG = false; 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class is uninstantiable. 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private CfTranslator() { 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // This space intentionally left blank. 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 7499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Takes a {@code byte[]}, interprets it as a Java classfile, and 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * translates it into a {@link ClassDefItem}. 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 7799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param filePath {@code non-null;} the file path for the class, 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * excluding any base directory specification 7999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param bytes {@code non-null;} contents of the file 803dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein * @param cfOptions options for class translation 813dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein * @param dexOptions options for dex output 8299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the translated class 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static ClassDefItem translate(String filePath, byte[] bytes, 853dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein CfOptions cfOptions, DexOptions dexOptions) { 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 873dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein return translate0(filePath, bytes, cfOptions, dexOptions); 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (RuntimeException ex) { 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String msg = "...while processing " + filePath; 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ExceptionWithContext.withContext(ex, msg); 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Performs the main act of translation. This method is separated 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from {@link #translate} just to keep things a bit simpler in 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * terms of exception handling. 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 9999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param filePath {@code non-null;} the file path for the class, 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * excluding any base directory specification 10199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param bytes {@code non-null;} contents of the file 1023dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein * @param cfOptions options for class translation 1033dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein * @param dexOptions options for dex output 10499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the translated class 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static ClassDefItem translate0(String filePath, byte[] bytes, 1073dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein CfOptions cfOptions, DexOptions dexOptions) { 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DirectClassFile cf = 1093dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein new DirectClassFile(bytes, filePath, cfOptions.strictNameCheck); 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cf.setAttributeFactory(StdAttributeFactory.THE_ONE); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cf.getMagic(); 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1143dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein OptimizerOptions.loadOptimizeLists(cfOptions.optimizeListFile, 1153dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein cfOptions.dontOptimizeListFile); 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Build up a class to output. 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstType thisClass = cf.getThisClass(); 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int classAccessFlags = cf.getAccessFlags() & ~AccessFlags.ACC_SUPER; 121333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson CstString sourceFile = (cfOptions.positionInfo == PositionList.NONE) ? null : 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cf.getSourceFile(); 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassDefItem out = 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new ClassDefItem(thisClass, classAccessFlags, 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cf.getSuperclass(), cf.getInterfaces(), sourceFile); 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Annotations classAnnotations = 1283dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein AttributeTranslator.getClassAnnotations(cf, cfOptions); 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (classAnnotations.size() != 0) { 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.setClassAnnotations(classAnnotations); 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 132de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project processFields(cf, out); 1343dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein processMethods(cf, cfOptions, dexOptions, out); 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return out; 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Processes the fields of the given class. 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 14299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param cf {@code non-null;} class being translated 14399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param out {@code non-null;} output class 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static void processFields(DirectClassFile cf, ClassDefItem out) { 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstType thisClass = cf.getThisClass(); 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FieldList fields = cf.getFields(); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = fields.size(); 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < sz; i++) { 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Field one = fields.get(i); 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstFieldRef field = new CstFieldRef(thisClass, one.getNat()); 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int accessFlags = one.getAccessFlags(); 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (AccessFlags.isStatic(accessFlags)) { 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project TypedConstant constVal = one.getConstantValue(); 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project EncodedField fi = new EncodedField(field, accessFlags); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (constVal != null) { 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project constVal = coerceConstant(constVal, field.getType()); 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.addStaticField(fi, constVal); 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project EncodedField fi = new EncodedField(field, accessFlags); 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.addInstanceField(fi); 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 168de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro Annotations annotations = 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AttributeTranslator.getAnnotations(one.getAttributes()); 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (annotations.size() != 0) { 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.addFieldAnnotations(field, annotations); 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (RuntimeException ex) { 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String msg = "...while processing " + one.getName().toHuman() + 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " " + one.getDescriptor().toHuman(); 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ExceptionWithContext.withContext(ex, msg); 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Helper for {@link #processFields}, which translates constants into 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * more specific types if necessary. 184de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 18599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param constant {@code non-null;} the constant in question 18699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param type {@code non-null;} the desired type 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static TypedConstant coerceConstant(TypedConstant constant, 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Type type) { 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Type constantType = constant.getType(); 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (constantType.equals(type)) { 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return constant; 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (type.getBasicType()) { 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case Type.BT_BOOLEAN: { 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return CstBoolean.make(((CstInteger) constant).getValue()); 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case Type.BT_BYTE: { 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return CstByte.make(((CstInteger) constant).getValue()); 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case Type.BT_CHAR: { 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return CstChar.make(((CstInteger) constant).getValue()); 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case Type.BT_SHORT: { 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return CstShort.make(((CstInteger) constant).getValue()); 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: { 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new UnsupportedOperationException("can't coerce " + 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project constant + " to " + type); 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Processes the methods of the given class. 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 21999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param cf {@code non-null;} class being translated 2203dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein * @param cfOptions {@code non-null;} options for class translation 2213dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein * @param dexOptions {@code non-null;} options for dex output 22299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param out {@code non-null;} output class 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 2243dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein private static void processMethods(DirectClassFile cf, CfOptions cfOptions, 2253dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein DexOptions dexOptions, ClassDefItem out) { 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstType thisClass = cf.getThisClass(); 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MethodList methods = cf.getMethods(); 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = methods.size(); 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < sz; i++) { 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method one = methods.get(i); 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstMethodRef meth = new CstMethodRef(thisClass, one.getNat()); 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int accessFlags = one.getAccessFlags(); 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean isStatic = AccessFlags.isStatic(accessFlags); 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean isPrivate = AccessFlags.isPrivate(accessFlags); 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean isNative = AccessFlags.isNative(accessFlags); 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean isAbstract = AccessFlags.isAbstract(accessFlags); 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean isConstructor = meth.isInstanceInit() || 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project meth.isClassInit(); 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DalvCode code; 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (isNative || isAbstract) { 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // There's no code for native or abstract methods. 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project code = null; 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ConcreteMethod concrete = 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new ConcreteMethod(one, cf, 2493dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein (cfOptions.positionInfo != PositionList.NONE), 2503dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein cfOptions.localInfo); 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project TranslationAdvice advice; 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project advice = DexTranslationAdvice.THE_ONE; 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RopMethod rmeth = Ropper.convert(concrete, advice); 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RopMethod nonOptRmeth = null; 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int paramSize; 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project paramSize = meth.getParameterWordCount(isStatic); 261de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 262de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro String canonicalName 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project = thisClass.getClassType().getDescriptor() 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + "." + one.getName().getString(); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2663dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein if (cfOptions.optimize && 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OptimizerOptions.shouldOptimize(canonicalName)) { 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (DEBUG) { 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.err.println("Optimizing " + canonicalName); 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nonOptRmeth = rmeth; 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project rmeth = Optimizer.optimize(rmeth, 2743dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein paramSize, isStatic, cfOptions.localInfo, advice); 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (DEBUG) { 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project OptimizerOptions.compareOptimizerStep(nonOptRmeth, 2783dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein paramSize, isStatic, cfOptions, advice, rmeth); 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2813dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein if (cfOptions.statistics) { 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CodeStatistics.updateRopStatistics( 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nonOptRmeth, rmeth); 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LocalVariableInfo locals = null; 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2893dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein if (cfOptions.localInfo) { 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project locals = LocalVariableExtractor.extract(rmeth); 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2933dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein code = RopTranslator.translate(rmeth, cfOptions.positionInfo, 2943dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein locals, paramSize, dexOptions); 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2963dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein if (cfOptions.statistics && nonOptRmeth != null) { 2973dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein updateDexStatistics(cfOptions, dexOptions, rmeth, nonOptRmeth, locals, 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project paramSize, concrete.getCode().size()); 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Preserve the synchronized flag as its "declared" variant... 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (AccessFlags.isSynchronized(accessFlags)) { 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project accessFlags |= AccessFlags.ACC_DECLARED_SYNCHRONIZED; 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ...but only native methods are actually allowed to be 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * synchronized. 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!isNative) { 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project accessFlags &= ~AccessFlags.ACC_SYNCHRONIZED; 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 314de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (isConstructor) { 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project accessFlags |= AccessFlags.ACC_CONSTRUCTOR; 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project TypeList exceptions = AttributeTranslator.getExceptions(one); 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project EncodedMethod mi = 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new EncodedMethod(meth, accessFlags, code, exceptions); 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (meth.isInstanceInit() || meth.isClassInit() || 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project isStatic || isPrivate) { 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.addDirectMethod(mi); 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.addVirtualMethod(mi); 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 330de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro Annotations annotations = 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AttributeTranslator.getMethodAnnotations(one); 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (annotations.size() != 0) { 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.addMethodAnnotations(meth, annotations); 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 336de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro AnnotationsList list = 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AttributeTranslator.getParameterAnnotations(one); 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (list.size() != 0) { 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.addParameterAnnotations(meth, list); 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (RuntimeException ex) { 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String msg = "...while processing " + one.getName().toHuman() + 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " " + one.getDescriptor().toHuman(); 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ExceptionWithContext.withContext(ex, msg); 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Helper that updates the dex statistics. 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 3523dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein private static void updateDexStatistics(CfOptions cfOptions, DexOptions dexOptions, 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RopMethod optRmeth, RopMethod nonOptRmeth, 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LocalVariableInfo locals, int paramSize, int originalByteCount) { 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Run rop->dex again on optimized vs. non-optimized method to 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * collect statistics. We have to totally convert both ways, 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * since converting the "real" method getting added to the 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * file would corrupt it (by messing with its constant pool 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * indices). 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DalvCode optCode = RopTranslator.translate(optRmeth, 3643dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein cfOptions.positionInfo, locals, paramSize, dexOptions); 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DalvCode nonOptCode = RopTranslator.translate(nonOptRmeth, 3663dfda9ad1964510e4a7948a240b30cd710e86341Dan Bornstein cfOptions.positionInfo, locals, paramSize, dexOptions); 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Fake out the indices, so code.getInsns() can work well enough 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for the current purpose. 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 373de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro DalvCode.AssignIndicesCallback callback = 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new DalvCode.AssignIndicesCallback() { 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getIndex(Constant cst) { 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Everything is at index 0! 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 0; 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }; 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project optCode.assignIndices(callback); 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nonOptCode.assignIndices(callback); 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CodeStatistics.updateDexStatistics(nonOptCode, optCode); 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CodeStatistics.updateOriginalByteCount(originalByteCount); 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 388