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.cst; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.ParseException; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.ParseObserver; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.Constant; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstDouble; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstFieldRef; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstFloat; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstInteger; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstInterfaceMethodRef; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstLong; 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstMethodRef; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstNat; 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstString; 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstType; 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstUtf8; 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.StdConstantPool; 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type; 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ByteArray; 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex; 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport static com.android.dx.cf.cst.ConstantTags.*; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parser for a constant pool embedded in a class file. 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class ConstantPoolParser { 4499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} the bytes of the constant pool */ 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final ByteArray bytes; 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} actual parsed constant pool contents */ 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final StdConstantPool pool; 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 5099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} byte offsets to each cst */ 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final int[] offsets; 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * -1 || >= 10; the end offset of this constant pool in the 5599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code byte[]} which it came from or {@code -1} if not 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * yet parsed 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int endOffset; 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 6099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code null-ok;} parse observer, if any */ 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private ParseObserver observer; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 6699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param bytes {@code non-null;} the bytes of the file 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ConstantPoolParser(ByteArray bytes) { 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size = bytes.getUnsignedShort(8); // constant_pool_count 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.bytes = bytes; 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.pool = new StdConstantPool(size); 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.offsets = new int[size]; 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.endOffset = -1; 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the parse observer for this instance. 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param observer {@code null-ok;} the observer 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void setObserver(ParseObserver observer) { 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.observer = observer; 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 8799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Gets the end offset of this constant pool in the {@code byte[]} 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which it came from. 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 9099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code >= 10;} the end offset 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getEndOffset() { 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseIfNecessary(); 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return endOffset; 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the actual constant pool. 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the constant pool 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public StdConstantPool getPool() { 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseIfNecessary(); 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return pool; 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Runs {@link #parse} if it has not yet been run successfully. 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void parseIfNecessary() { 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (endOffset < 0) { 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parse(); 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Does the actual parsing. 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void parse() { 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project determineOffsets(); 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (observer != null) { 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, 8, 2, 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "constant_pool_count: " + Hex.u2(offsets.length)); 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, 10, 0, "\nconstant_pool:"); 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.changeIndent(1); 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 1; i < offsets.length; i++) { 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int offset = offsets[i]; 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((offset != 0) && (pool.getOrNull(i) == null)) { 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parse0(i); 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (observer != null) { 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 1; i < offsets.length; i++) { 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Constant cst = pool.getOrNull(i); 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cst == null) { 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int offset = offsets[i]; 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int nextOffset = endOffset; 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int j = i + 1; j < offsets.length; j++) { 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int off = offsets[j]; 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (off != 0) { 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nextOffset = off; 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, offset, nextOffset - offset, 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Hex.u2(i) + ": " + cst.toString()); 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.changeIndent(-1); 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, endOffset, 0, "end constant_pool"); 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Populates {@link #offsets} and also completely parse utf8 constants. 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void determineOffsets() { 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int at = 10; // offset from the start of the file to the first cst 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int lastCategory; 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 1; i < offsets.length; i += lastCategory) { 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project offsets[i] = at; 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int tag = bytes.getUnsignedByte(at); 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (tag) { 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Integer: 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Float: 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Fieldref: 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Methodref: 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_InterfaceMethodref: 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_NameAndType: { 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lastCategory = 1; 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at += 5; 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Long: 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Double: { 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lastCategory = 2; 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at += 9; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Class: 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_String: { 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lastCategory = 1; 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at += 3; 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Utf8: { 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lastCategory = 1; 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at += bytes.getUnsignedShort(at + 1) + 3; 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: { 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ParseException ex = 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new ParseException("unknown tag byte: " + Hex.u1(tag)); 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ex.addContext("...while preparsing cst " + Hex.u2(i) + 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at offset " + Hex.u4(at)); 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ex; 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endOffset = at; 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parses the constant for the given index if it hasn't already been 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * parsed, also storing it in the constant pool. This will also 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have the side effect of parsing any entries the indicated one 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * depends on. 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param idx which constant 21899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the parsed constant 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private Constant parse0(int idx) { 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Constant cst = pool.getOrNull(idx); 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cst != null) { 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return cst; 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int at = offsets[idx]; 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int tag = bytes.getUnsignedByte(at); 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (tag) { 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Utf8: { 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = parseUtf8(at); 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Integer: { 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int value = bytes.getInt(at + 1); 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = CstInteger.make(value); 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Float: { 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int bits = bytes.getInt(at + 1); 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = CstFloat.make(bits); 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Long: { 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project long value = bytes.getLong(at + 1); 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = CstLong.make(value); 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Double: { 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project long bits = bytes.getLong(at + 1); 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = CstDouble.make(bits); 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Class: { 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int nameIndex = bytes.getUnsignedShort(at + 1); 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstUtf8 name = (CstUtf8) parse0(nameIndex); 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstType(Type.internClassName(name.getString())); 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_String: { 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stringIndex = bytes.getUnsignedShort(at + 1); 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstUtf8 string = (CstUtf8) parse0(stringIndex); 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstString(string); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Fieldref: { 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int classIndex = bytes.getUnsignedShort(at + 1); 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstType type = (CstType) parse0(classIndex); 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int natIndex = bytes.getUnsignedShort(at + 3); 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstNat nat = (CstNat) parse0(natIndex); 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstFieldRef(type, nat); 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Methodref: { 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int classIndex = bytes.getUnsignedShort(at + 1); 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstType type = (CstType) parse0(classIndex); 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int natIndex = bytes.getUnsignedShort(at + 3); 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstNat nat = (CstNat) parse0(natIndex); 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstMethodRef(type, nat); 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_InterfaceMethodref: { 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int classIndex = bytes.getUnsignedShort(at + 1); 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstType type = (CstType) parse0(classIndex); 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int natIndex = bytes.getUnsignedShort(at + 3); 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstNat nat = (CstNat) parse0(natIndex); 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstInterfaceMethodRef(type, nat); 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_NameAndType: { 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int nameIndex = bytes.getUnsignedShort(at + 1); 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstUtf8 name = (CstUtf8) parse0(nameIndex); 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int descriptorIndex = bytes.getUnsignedShort(at + 3); 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstUtf8 descriptor = (CstUtf8) parse0(descriptorIndex); 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstNat(name, descriptor); 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (ParseException ex) { 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ex.addContext("...while parsing cst " + Hex.u2(idx) + 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at offset " + Hex.u4(at)); 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ex; 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (RuntimeException ex) { 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ParseException pe = new ParseException(ex); 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pe.addContext("...while parsing cst " + Hex.u2(idx) + 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at offset " + Hex.u4(at)); 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw pe; 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pool.set(idx, cst); 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return cst; 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parses a utf8 constant. 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param at offset to the start of the constant (where the tag byte is) 31999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the parsed value 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private CstUtf8 parseUtf8(int at) { 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int length = bytes.getUnsignedShort(at + 1); 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at += 3; // Skip to the data. 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ByteArray ubytes = bytes.slice(at, at + length); 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return new CstUtf8(ubytes); 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (IllegalArgumentException ex) { 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Translate the exception 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new ParseException(ex); 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 336