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.file; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.dex.code.DalvCode; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.AccessFlags; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstMethodRef; 22333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport com.android.dx.rop.cst.CstString; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeList; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.AnnotatedOutput; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Leb128Utils; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.PrintWriter; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Class that representats a method of a class. 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 33de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiropublic final class EncodedMethod extends EncodedMember 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project implements Comparable<EncodedMethod> { 3599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} constant for the method */ 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final CstMethodRef method; 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 3999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code null-ok;} code for the method, if the method is neither 40de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * {@code abstract} nor {@code native} 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final CodeItem code; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. 46de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 4799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param method {@code non-null;} constant for the method 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param accessFlags access flags 4999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param code {@code null-ok;} code for the method, if it is neither 5099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code abstract} nor {@code native} 5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param throwsList {@code non-null;} list of possibly-thrown exceptions, 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * just used in generating debugging output (listings) 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public EncodedMethod(CstMethodRef method, int accessFlags, 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DalvCode code, TypeList throwsList) { 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(accessFlags); 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (method == null) { 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("method == null"); 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.method = method; 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (code == null) { 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.code = null; 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean isStatic = (accessFlags & AccessFlags.ACC_STATIC) != 0; 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.code = new CodeItem(method, code, isStatic, throwsList); 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean equals(Object other) { 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (! (other instanceof EncodedMethod)) { 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return compareTo((EncodedMethod) other) == 0; 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@inheritDoc} 83de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p><b>Note:</b> This compares the method constants only, 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ignoring any associated code, because it should never be the 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * case that two different items with the same method constant 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ever appear in the same list (or same file, even).</p> 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int compareTo(EncodedMethod other) { 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return method.compareTo(other.method); 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String toString() { 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringBuffer sb = new StringBuffer(100); 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(getClass().getName()); 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append('{'); 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(Hex.u2(getAccessFlags())); 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(' '); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(method); 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (code != null) { 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(' '); 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(code); 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append('}'); 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return sb.toString(); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void addContents(DexFile file) { 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MethodIdsSection methodIds = file.getMethodIds(); 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MixedItemSection wordData = file.getWordData(); 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodIds.intern(method); 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (code != null) { 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project wordData.add(code); 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final String toHuman() { 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return method.toHuman(); 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 134333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson public final CstString getName() { 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return method.getNat().getName(); 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void debugPrint(PrintWriter out, boolean verbose) { 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (code == null) { 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.println(getRef().toHuman() + ": abstract or native"); 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project code.debugPrint(out, " ", verbose); 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the constant for the method. 150de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 15199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the constant 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final CstMethodRef getRef() { 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return method; 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 159de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro public int encode(DexFile file, AnnotatedOutput out, 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int lastIndex, int dumpSeq) { 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int methodIdx = file.getMethodIds().indexOf(method); 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int diff = methodIdx - lastIndex; 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int accessFlags = getAccessFlags(); 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int codeOff = OffsettedItem.getAbsoluteOffsetOr0(code); 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean hasCode = (codeOff != 0); 166de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro boolean shouldHaveCode = (accessFlags & 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (AccessFlags.ACC_ABSTRACT | AccessFlags.ACC_NATIVE)) == 0; 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Verify that code appears if and only if a method is 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * declared to have it. 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (hasCode != shouldHaveCode) { 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new UnsupportedOperationException( 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "code vs. access_flags mismatch"); 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (out.annotates()) { 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(0, String.format(" [%x] %s", dumpSeq, 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method.toHuman())); 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(Leb128Utils.unsignedLeb128Size(diff), 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " method_idx: " + Hex.u4(methodIdx)); 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(Leb128Utils.unsignedLeb128Size(accessFlags), 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " access_flags: " + 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AccessFlags.methodString(accessFlags)); 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project out.annotate(Leb128Utils.unsignedLeb128Size(codeOff), 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " code_off: " + Hex.u4(codeOff)); 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 190dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson out.writeUleb128(diff); 191dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson out.writeUleb128(accessFlags); 192dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson out.writeUleb128(codeOff); 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return methodIdx; 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 197