DirectClassFile.java revision 4c656e4ec2f5c5036dc67fb4034c1e7ff7abf343
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.cf.direct; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.attrib.AttSourceFile; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.cst.ConstantPoolParser; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.Attribute; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.AttributeList; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.ClassFile; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.FieldList; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.MethodList; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.ParseException; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.ParseObserver; 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.StdAttributeList; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.AccessFlags; 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.ConstantPool; 31333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport com.android.dx.rop.cst.CstString; 32fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.cst.CstType; 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.StdConstantPool; 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.StdTypeList; 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type; 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeList; 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ByteArray; 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 4199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Class file with info taken from a {@code byte[]} or slice thereof. 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class DirectClassFile implements ClassFile { 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** the expected value of the ClassFile.magic field */ 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int CLASS_FILE_MAGIC = 0xcafebabe; 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 4899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * minimum {@code .class} file major version 49de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 50092412605d5d500456e9fff475c90691e668b914Elliott Hughes * See http://en.wikipedia.org/wiki/Java_class_file for an up-to-date 51092412605d5d500456e9fff475c90691e668b914Elliott Hughes * list of version numbers. Currently known (taken from that table) are: 52de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 535ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin * J2SE 7.0 = 51 (0x33 hex), 54092412605d5d500456e9fff475c90691e668b914Elliott Hughes * J2SE 6.0 = 50 (0x32 hex), 55092412605d5d500456e9fff475c90691e668b914Elliott Hughes * J2SE 5.0 = 49 (0x31 hex), 56092412605d5d500456e9fff475c90691e668b914Elliott Hughes * JDK 1.4 = 48 (0x30 hex), 57092412605d5d500456e9fff475c90691e668b914Elliott Hughes * JDK 1.3 = 47 (0x2F hex), 58092412605d5d500456e9fff475c90691e668b914Elliott Hughes * JDK 1.2 = 46 (0x2E hex), 59092412605d5d500456e9fff475c90691e668b914Elliott Hughes * JDK 1.1 = 45 (0x2D hex). 60de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Valid ranges are typically of the form 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "A.0 through B.C inclusive" where A <= B and C >= 0, 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which is why we don't have a CLASS_FILE_MIN_MINOR_VERSION. 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int CLASS_FILE_MIN_MAJOR_VERSION = 45; 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 67092412605d5d500456e9fff475c90691e668b914Elliott Hughes /** 68092412605d5d500456e9fff475c90691e668b914Elliott Hughes * maximum {@code .class} file major version 69092412605d5d500456e9fff475c90691e668b914Elliott Hughes * 70092412605d5d500456e9fff475c90691e668b914Elliott Hughes * Note: if you change this, please change "java.class.version" in System.java. 71092412605d5d500456e9fff475c90691e668b914Elliott Hughes */ 725ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin private static final int CLASS_FILE_MAX_MAJOR_VERSION = 51; 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 7499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** maximum {@code .class} file minor version */ 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final int CLASS_FILE_MAX_MINOR_VERSION = 0; 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 7899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code non-null;} the file path for the class, excluding any base directory 79de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * specification 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final String filePath; 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 8399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} the bytes of the file */ 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final ByteArray bytes; 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * whether to be strict about parsing; if 8899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code false}, this avoids doing checks that only exist 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for purposes of verification (such as magic number matching and 90de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * path-package consistency checking) 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final boolean strictParse; 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 9599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code null-ok;} the constant pool; only ever {@code null} 96de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * before the constant pool is successfully parsed 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private StdConstantPool pool; 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 10199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * the class file field {@code access_flags}; will be {@code -1} 102de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * before the file is successfully parsed 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int accessFlags; 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 10799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code null-ok;} the class file field {@code this_class}, 10899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * interpreted as a type constant; only ever {@code null} 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * before the file is successfully parsed 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private CstType thisClass; 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 11499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code null-ok;} the class file field {@code super_class}, interpreted 115de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * as a type constant if non-zero 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private CstType superClass; 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 12099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code null-ok;} the class file field {@code interfaces}; only 12199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * ever {@code null} before the file is successfully 122de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * parsed 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private TypeList interfaces; 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 12799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code null-ok;} the class file field {@code fields}; only ever 128de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * {@code null} before the file is successfully parsed 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private FieldList fields; 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 13399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code null-ok;} the class file field {@code methods}; only ever 134de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * {@code null} before the file is successfully parsed 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private MethodList methods; 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 13999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code null-ok;} the class file field {@code attributes}; only 14099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * ever {@code null} before the file is successfully 141de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * parsed 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private StdAttributeList attributes; 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 14599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code null-ok;} attribute factory, if any */ 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private AttributeFactory attributeFactory; 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 14899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code null-ok;} parse observer, if any */ 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private ParseObserver observer; 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 15299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Returns the string form of an object or {@code "(none)"} 15399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * (rather than {@code "null"}) for {@code null}. 154de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 15599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param obj {@code null-ok;} the object to stringify 15699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the appropriate string form 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static String stringOrNone(Object obj) { 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj == null) { 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return "(none)"; 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return obj.toString(); 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. 168de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 16999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param bytes {@code non-null;} the bytes of the file 17099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param filePath {@code non-null;} the file path for the class, 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * excluding any base directory specification 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param strictParse whether to be strict about parsing; if 17399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code false}, this avoids doing checks that only exist 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for purposes of verification (such as magic number matching and 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * path-package consistency checking) 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public DirectClassFile(ByteArray bytes, String filePath, 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean strictParse) { 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (bytes == null) { 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("bytes == null"); 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (filePath == null) { 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("filePath == null"); 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.filePath = filePath; 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.bytes = bytes; 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.strictParse = strictParse; 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.accessFlags = -1; 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. 195de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 19699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param bytes {@code non-null;} the bytes of the file 19799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param filePath {@code non-null;} the file path for the class, 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * excluding any base directory specification 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param strictParse whether to be strict about parsing; if 20099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code false}, this avoids doing checks that only exist 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for purposes of verification (such as magic number matching and 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * path-package consistency checking) 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public DirectClassFile(byte[] bytes, String filePath, 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean strictParse) { 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this(new ByteArray(bytes), filePath, strictParse); 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the parse observer for this instance. 211de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 21299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param observer {@code null-ok;} the observer 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void setObserver(ParseObserver observer) { 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.observer = observer; 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the attribute factory to use. 220de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 22199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param attributeFactory {@code non-null;} the attribute factory 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void setAttributeFactory(AttributeFactory attributeFactory) { 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (attributeFactory == null) { 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("attributeFactory == null"); 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.attributeFactory = attributeFactory; 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 2324c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * Gets the path where this class file is located. 2334c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * 2344c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche * @return {@code non-null;} the filePath 2354c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche */ 2364c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche public String getFilePath() { 2374c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche return filePath; 2384c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche } 2394c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche 2404c656e4ec2f5c5036dc67fb4034c1e7ff7abf343Benoit Lamarche /** 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the {@link ByteArray} that this instance's data comes from. 242de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 24399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the bytes 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ByteArray getBytes() { 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return bytes; 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getMagic() { 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToInterfacesIfNecessary(); 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return getMagic0(); 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getMinorVersion() { 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToInterfacesIfNecessary(); 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return getMinorVersion0(); 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getMajorVersion() { 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToInterfacesIfNecessary(); 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return getMajorVersion0(); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getAccessFlags() { 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToInterfacesIfNecessary(); 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return accessFlags; 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public CstType getThisClass() { 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToInterfacesIfNecessary(); 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return thisClass; 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public CstType getSuperclass() { 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToInterfacesIfNecessary(); 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return superClass; 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ConstantPool getConstantPool() { 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToInterfacesIfNecessary(); 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return pool; 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public TypeList getInterfaces() { 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToInterfacesIfNecessary(); 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return interfaces; 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public FieldList getFields() { 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToEndIfNecessary(); 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return fields; 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public MethodList getMethods() { 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToEndIfNecessary(); 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return methods; 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public AttributeList getAttributes() { 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseToEndIfNecessary(); 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return attributes; 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 316333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson public CstString getSourceFile() { 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AttributeList attribs = getAttributes(); 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Attribute attSf = attribs.findFirst(AttSourceFile.ATTRIBUTE_NAME); 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (attSf instanceof AttSourceFile) { 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ((AttSourceFile) attSf).getSourceFile(); 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs and returns an instance of {@link TypeList} whose 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data comes from the bytes of this instance, interpreted as a 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * list of constant pool indices for classes, which are in turn 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * translated to type constants. Instance construction will fail 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if any of the (alleged) indices turn out not to refer to 33399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * constant pool entries of type {@code Class}. 334de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param offset offset into {@link #bytes} for the start of the 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param size number of elements in the list (not number of bytes) 33899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} an appropriately-constructed class list 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public TypeList makeTypeList(int offset, int size) { 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (size == 0) { 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return StdTypeList.EMPTY; 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pool == null) { 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalStateException("pool not yet initialized"); 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 348de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return new DcfTypeList(bytes, offset, size, pool, observer); 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 35399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Gets the class file field {@code magic}, but without doing any 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * checks or parsing first. 355de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the magic value 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getMagic0() { 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return bytes.getInt(0); 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 36399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Gets the class file field {@code minor_version}, but 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * without doing any checks or parsing first. 365de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the minor version 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getMinorVersion0() { 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return bytes.getUnsignedShort(4); 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 37399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Gets the class file field {@code major_version}, but 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * without doing any checks or parsing first. 375de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the major version 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getMajorVersion0() { 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return bytes.getUnsignedShort(6); 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Runs {@link #parse} if it has not yet been run to cover up to 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the interfaces list. 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void parseToInterfacesIfNecessary() { 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (accessFlags == -1) { 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parse(); 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Runs {@link #parse} if it has not yet been run successfully. 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void parseToEndIfNecessary() { 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (attributes == null) { 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parse(); 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Does the parsing, handing exceptions. 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void parse() { 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parse0(); 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (ParseException ex) { 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ex.addContext("...while parsing " + filePath); 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ex; 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (RuntimeException ex) { 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ParseException pe = new ParseException(ex); 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pe.addContext("...while parsing " + filePath); 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw pe; 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sees if the .class file header magic/version are within 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * range. 420de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param magic the value of a classfile "magic" field 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param minorVersion the value of a classfile "minor_version" field 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param majorVersion the value of a classfile "major_version" field 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return true iff the parameters are valid and within range 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private boolean isGoodVersion(int magic, int minorVersion, 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int majorVersion) { 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Valid version ranges are typically of the form 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "A.0 through B.C inclusive" where A <= B and C >= 0, 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which is why we don't have a CLASS_FILE_MIN_MINOR_VERSION. 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (magic == CLASS_FILE_MAGIC && minorVersion >= 0) { 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Check against max first to handle the case where 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * MIN_MAJOR == MAX_MAJOR. 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (majorVersion == CLASS_FILE_MAX_MAJOR_VERSION) { 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (minorVersion <= CLASS_FILE_MAX_MINOR_VERSION) { 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (majorVersion < CLASS_FILE_MAX_MAJOR_VERSION && 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project majorVersion >= CLASS_FILE_MIN_MAJOR_VERSION) { 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Does the actual parsing. 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void parse0() { 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (bytes.size() < 10) { 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new ParseException("severely truncated class file"); 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (observer != null) { 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, 0, 0, "begin classfile"); 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, 0, 4, "magic: " + Hex.u4(getMagic0())); 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, 4, 2, 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "minor_version: " + Hex.u2(getMinorVersion0())); 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, 6, 2, 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "major_version: " + Hex.u2(getMajorVersion0())); 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (strictParse) { 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* Make sure that this looks like a valid class file with a 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * version that we can handle. 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!isGoodVersion(getMagic0(), getMinorVersion0(), 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project getMajorVersion0())) { 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new ParseException("bad class file magic (" + 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Hex.u4(getMagic0()) + 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ") or version (" + 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Hex.u2(getMajorVersion0()) + "." + 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Hex.u2(getMinorVersion0()) + ")"); 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ConstantPoolParser cpParser = new ConstantPoolParser(bytes); 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cpParser.setObserver(observer); 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pool = cpParser.getPool(); 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pool.setImmutable(); 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int at = cpParser.getEndOffset(); 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int accessFlags = bytes.getUnsignedShort(at); // u2 access_flags; 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int cpi = bytes.getUnsignedShort(at + 2); // u2 this_class; 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project thisClass = (CstType) pool.get(cpi); 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cpi = bytes.getUnsignedShort(at + 4); // u2 super_class; 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project superClass = (CstType) pool.get0Ok(cpi); 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int count = bytes.getUnsignedShort(at + 6); // u2 interfaces_count 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (observer != null) { 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, at, 2, 495de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro "access_flags: " + 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AccessFlags.classString(accessFlags)); 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, at + 2, 2, "this_class: " + thisClass); 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, at + 4, 2, "super_class: " + 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stringOrNone(superClass)); 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, at + 6, 2, 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "interfaces_count: " + Hex.u2(count)); 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (count != 0) { 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, at + 8, 0, "interfaces:"); 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at += 8; 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project interfaces = makeTypeList(at, count); 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at += count * 2; 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (strictParse) { 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Make sure that the file/jar path matches the declared 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * package/class name. 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String thisClassName = thisClass.getClassType().getClassName(); 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!(filePath.endsWith(".class") && 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project filePath.startsWith(thisClassName) && 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (filePath.length() == (thisClassName.length() + 6)))) { 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new ParseException("class name (" + thisClassName + 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ") does not match path (" + 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project filePath + ")"); 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Only set the instance variable accessFlags here, since 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that's what signals a successful parse of the first part of 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the file (through the interfaces list). 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.accessFlags = accessFlags; 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FieldListParser flParser = 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new FieldListParser(this, thisClass, at, attributeFactory); 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project flParser.setObserver(observer); 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fields = flParser.getList(); 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at = flParser.getEndOffset(); 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MethodListParser mlParser = 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new MethodListParser(this, thisClass, at, attributeFactory); 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project mlParser.setObserver(observer); 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methods = mlParser.getList(); 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at = mlParser.getEndOffset(); 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project AttributeListParser alParser = 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new AttributeListParser(this, AttributeFactory.CTX_CLASS, at, 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attributeFactory); 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project alParser.setObserver(observer); 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attributes = alParser.getList(); 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project attributes.setImmutable(); 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at = alParser.getEndOffset(); 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (at != bytes.size()) { 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new ParseException("extra bytes at end of class file, " + 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "at offset " + Hex.u4(at)); 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (observer != null) { 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, at, 0, "end classfile"); 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Implementation of {@link TypeList} whose data comes directly 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the bytes of an instance of this (outer) class, 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreted as a list of constant pool indices for classes 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which are in turn returned as type constants. Instance 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * construction will fail if any of the (alleged) indices turn out 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not to refer to constant pool entries of type 57099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code Class}. 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static class DcfTypeList implements TypeList { 57399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} array containing the data */ 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final ByteArray bytes; 575de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** number of elements in the list (not number of bytes) */ 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final int size; 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 57999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} the constant pool */ 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final StdConstantPool pool; 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. 584de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 58599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param bytes {@code non-null;} original classfile's bytes 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param offset offset into {@link #bytes} for the start of the 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param size number of elements in the list (not number of bytes) 58999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param pool {@code non-null;} the constant pool to use 59099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param observer {@code null-ok;} parse observer to use, if any 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public DcfTypeList(ByteArray bytes, int offset, int size, 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StdConstantPool pool, ParseObserver observer) { 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (size < 0) { 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("size < 0"); 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bytes = bytes.slice(offset, offset + size * 2); 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.bytes = bytes; 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.size = size; 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.pool = pool; 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < size; i++) { 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project offset = i * 2; 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int idx = bytes.getUnsignedShort(offset); 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstType type; 607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project type = (CstType) pool.get(idx); 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (ClassCastException ex) { 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Translate the exception. 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new RuntimeException("bogus class cpi", ex); 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (observer != null) { 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, offset, 2, " " + type); 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean isMutable() { 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int size() { 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return size; 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getWordCount() { 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // It is the same as size because all elements are classes. 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return size; 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Type getType(int n) { 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int idx = bytes.getUnsignedShort(n * 2); 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ((CstType) pool.get(idx)).getClassType(); 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public TypeList withAddedType(Type type) { 643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new UnsupportedOperationException("unsupported"); 644de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro } 645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 647