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 19333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_Class; 20333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_Double; 21333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_Fieldref; 22333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_Float; 23333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_Integer; 24333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_InterfaceMethodref; 25333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_Long; 26333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_Methodref; 27333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_NameAndType; 28333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_String; 29333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_Utf8; 305ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartinimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_MethodHandle; 315ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartinimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_MethodType; 325ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartinimport static com.android.dx.cf.cst.ConstantTags.CONSTANT_InvokeDynamic; 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.ParseException; 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.ParseObserver; 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.Constant; 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstDouble; 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstFieldRef; 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstFloat; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstInteger; 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstInterfaceMethodRef; 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstLong; 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstMethodRef; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstNat; 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstString; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstType; 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.StdConstantPool; 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type; 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ByteArray; 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex; 50333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport java.util.BitSet; 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parser for a constant pool embedded in a class file. 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class ConstantPoolParser { 5699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} the bytes of the constant pool */ 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final ByteArray bytes; 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 5999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} actual parsed constant pool contents */ 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final StdConstantPool pool; 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 6299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} byte offsets to each cst */ 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final int[] offsets; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * -1 || >= 10; the end offset of this constant pool in the 6799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code byte[]} which it came from or {@code -1} if not 68de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * yet parsed 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int endOffset; 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 7299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code null-ok;} parse observer, if any */ 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private ParseObserver observer; 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. 77de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 7899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param bytes {@code non-null;} the bytes of the file 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ConstantPoolParser(ByteArray bytes) { 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size = bytes.getUnsignedShort(8); // constant_pool_count 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.bytes = bytes; 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.pool = new StdConstantPool(size); 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.offsets = new int[size]; 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.endOffset = -1; 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets the parse observer for this instance. 91de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 9299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param observer {@code null-ok;} the observer 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void setObserver(ParseObserver observer) { 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.observer = observer; 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 9999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Gets the end offset of this constant pool in the {@code byte[]} 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which it came from. 101de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 10299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code >= 10;} the end offset 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getEndOffset() { 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseIfNecessary(); 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return endOffset; 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the actual constant pool. 111de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 11299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the constant pool 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public StdConstantPool getPool() { 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseIfNecessary(); 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return pool; 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Runs {@link #parse} if it has not yet been run successfully. 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void parseIfNecessary() { 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (endOffset < 0) { 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parse(); 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Does the actual parsing. 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void parse() { 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project determineOffsets(); 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (observer != null) { 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, 8, 2, 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "constant_pool_count: " + Hex.u2(offsets.length)); 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, 10, 0, "\nconstant_pool:"); 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.changeIndent(1); 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 141333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson /* 142333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson * Track the constant value's original string type. True if constants[i] was 143333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson * a CONSTANT_Utf8, false for any other type including CONSTANT_string. 144333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson */ 145333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson BitSet wasUtf8 = new BitSet(offsets.length); 146333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 1; i < offsets.length; i++) { 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int offset = offsets[i]; 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((offset != 0) && (pool.getOrNull(i) == null)) { 150333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson parse0(i, wasUtf8); 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (observer != null) { 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 1; i < offsets.length; i++) { 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Constant cst = pool.getOrNull(i); 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cst == null) { 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int offset = offsets[i]; 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int nextOffset = endOffset; 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int j = i + 1; j < offsets.length; j++) { 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int off = offsets[j]; 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (off != 0) { 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nextOffset = off; 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 169333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson String human = wasUtf8.get(i) 170333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson ? Hex.u2(i) + ": utf8{\"" + cst.toHuman() + "\"}" 171333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson : Hex.u2(i) + ": " + cst.toString(); 172333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson observer.parsed(bytes, offset, nextOffset - offset, human); 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.changeIndent(-1); 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project observer.parsed(bytes, endOffset, 0, "end constant_pool"); 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Populates {@link #offsets} and also completely parse utf8 constants. 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void determineOffsets() { 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int at = 10; // offset from the start of the file to the first cst 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int lastCategory; 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 1; i < offsets.length; i += lastCategory) { 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project offsets[i] = at; 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int tag = bytes.getUnsignedByte(at); 1905ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin try { 1915ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin switch (tag) { 1925ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_Integer: 1935ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_Float: 1945ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_Fieldref: 1955ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_Methodref: 1965ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_InterfaceMethodref: 1975ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_NameAndType: { 1985ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin lastCategory = 1; 1995ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin at += 5; 2005ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin break; 2015ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 2025ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_Long: 2035ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_Double: { 2045ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin lastCategory = 2; 2055ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin at += 9; 2065ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin break; 2075ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 2085ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_Class: 2095ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_String: { 2105ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin lastCategory = 1; 2115ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin at += 3; 2125ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin break; 2135ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 2145ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_Utf8: { 2155ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin lastCategory = 1; 2165ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin at += bytes.getUnsignedShort(at + 1) + 3; 2175ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin break; 2185ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 2195ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_MethodHandle: { 2205ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin throw new ParseException("MethodHandle not supported"); 2215ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 2225ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_MethodType: { 2235ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin throw new ParseException("MethodType not supported"); 2245ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 2255ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_InvokeDynamic: { 2265ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin throw new ParseException("InvokeDynamic not supported"); 2275ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 2285ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin default: { 2295ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin throw new ParseException("unknown tag byte: " + Hex.u1(tag)); 2305ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 2325ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } catch (ParseException ex) { 2335ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin ex.addContext("...while preparsing cst " + Hex.u2(i) + " at offset " + Hex.u4(at)); 2345ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin throw ex; 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project endOffset = at; 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parses the constant for the given index if it hasn't already been 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * parsed, also storing it in the constant pool. This will also 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * have the side effect of parsing any entries the indicated one 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * depends on. 246de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param idx which constant 24899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the parsed constant 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 250333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson private Constant parse0(int idx, BitSet wasUtf8) { 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Constant cst = pool.getOrNull(idx); 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cst != null) { 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return cst; 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int at = offsets[idx]; 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int tag = bytes.getUnsignedByte(at); 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (tag) { 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Utf8: { 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = parseUtf8(at); 263333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson wasUtf8.set(idx); 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Integer: { 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int value = bytes.getInt(at + 1); 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = CstInteger.make(value); 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Float: { 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int bits = bytes.getInt(at + 1); 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = CstFloat.make(bits); 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Long: { 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project long value = bytes.getLong(at + 1); 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = CstLong.make(value); 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Double: { 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project long bits = bytes.getLong(at + 1); 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = CstDouble.make(bits); 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Class: { 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int nameIndex = bytes.getUnsignedShort(at + 1); 288333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson CstString name = (CstString) parse0(nameIndex, wasUtf8); 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstType(Type.internClassName(name.getString())); 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_String: { 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stringIndex = bytes.getUnsignedShort(at + 1); 294333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson cst = parse0(stringIndex, wasUtf8); 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Fieldref: { 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int classIndex = bytes.getUnsignedShort(at + 1); 299333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson CstType type = (CstType) parse0(classIndex, wasUtf8); 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int natIndex = bytes.getUnsignedShort(at + 3); 301333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson CstNat nat = (CstNat) parse0(natIndex, wasUtf8); 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstFieldRef(type, nat); 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_Methodref: { 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int classIndex = bytes.getUnsignedShort(at + 1); 307333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson CstType type = (CstType) parse0(classIndex, wasUtf8); 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int natIndex = bytes.getUnsignedShort(at + 3); 309333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson CstNat nat = (CstNat) parse0(natIndex, wasUtf8); 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstMethodRef(type, nat); 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_InterfaceMethodref: { 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int classIndex = bytes.getUnsignedShort(at + 1); 315333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson CstType type = (CstType) parse0(classIndex, wasUtf8); 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int natIndex = bytes.getUnsignedShort(at + 3); 317333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson CstNat nat = (CstNat) parse0(natIndex, wasUtf8); 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstInterfaceMethodRef(type, nat); 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case CONSTANT_NameAndType: { 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int nameIndex = bytes.getUnsignedShort(at + 1); 323333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson CstString name = (CstString) parse0(nameIndex, wasUtf8); 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int descriptorIndex = bytes.getUnsignedShort(at + 3); 325333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson CstString descriptor = (CstString) parse0(descriptorIndex, wasUtf8); 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cst = new CstNat(name, descriptor); 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 3295ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_MethodHandle: { 3305ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin throw new ParseException("MethodHandle not supported"); 3315ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 3325ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_MethodType: { 3335ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin throw new ParseException("MethodType not supported"); 3345ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 3355ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin case CONSTANT_InvokeDynamic: { 3365ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin throw new ParseException("InvokeDynamic not supported"); 3375ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 3385ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin default: { 3395ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin throw new ParseException("unknown tag byte: " + Hex.u1(tag)); 3405ca383d7373cf7c54706b8e70d534deee8d2e3addelphinemartin } 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (ParseException ex) { 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ex.addContext("...while parsing cst " + Hex.u2(idx) + 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at offset " + Hex.u4(at)); 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ex; 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (RuntimeException ex) { 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ParseException pe = new ParseException(ex); 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pe.addContext("...while parsing cst " + Hex.u2(idx) + 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project " at offset " + Hex.u4(at)); 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw pe; 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pool.set(idx, cst); 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return cst; 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parses a utf8 constant. 359de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param at offset to the start of the constant (where the tag byte is) 36199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the parsed value 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 363333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson private CstString parseUtf8(int at) { 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int length = bytes.getUnsignedShort(at + 1); 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at += 3; // Skip to the data. 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ByteArray ubytes = bytes.slice(at, at + length); 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 371333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson return new CstString(ubytes); 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (IllegalArgumentException ex) { 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Translate the exception 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new ParseException(ex); 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 378