1b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson/* 2b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * Copyright (C) 2017 The Android Open Source Project 3b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * 4b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * Licensed under the Apache License, Version 2.0 (the "License"); 5b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * you may not use this file except in compliance with the License. 6b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * You may obtain a copy of the License at 7b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * 8b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * http://www.apache.org/licenses/LICENSE-2.0 9b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * 10b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * Unless required by applicable law or agreed to in writing, software 11b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * distributed under the License is distributed on an "AS IS" BASIS, 12b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * See the License for the specific language governing permissions and 14b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * limitations under the License. 15b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson */ 16b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonpackage com.android.dx.dex.file; 17b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson 18b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.rop.cst.Constant; 19b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.rop.cst.CstBaseMethodRef; 20b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.rop.cst.CstFieldRef; 21b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.rop.cst.CstInterfaceMethodRef; 22b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.rop.cst.CstMethodHandle; 23b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.util.AnnotatedOutput; 24b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.util.Hex; 25b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson 26b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson/** 27b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * Representation of a method handle in a DEX file. 28b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson */ 29b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonpublic final class MethodHandleItem extends IndexedItem { 30b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson 31b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson /** The item size when placed in a DEX file. */ 32b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson private final int ITEM_SIZE = 8; 33b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson 34b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson /** {@code non-null;} The method handle represented by this item. */ 35b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson private final CstMethodHandle methodHandle; 36b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson 37b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson /** 38b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * Constructs an instance. 39b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * 40b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * @param methodHandle {@code non-null;} The method handle to represent in the DEX file. 41b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson */ 42b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson public MethodHandleItem(CstMethodHandle methodHandle) { 43b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson this.methodHandle = methodHandle; 44b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } 45b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson 46b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson /** {@inheritDoc} */ 47b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson @Override 48b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson public ItemType itemType() { 49b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson return ItemType.TYPE_METHOD_HANDLE_ITEM; 50b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } 51b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson 52b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson /** {@inheritDoc} */ 53b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson @Override 54b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson public int writeSize() { 55b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson return ITEM_SIZE; 56b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } 57b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson 58b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson /** {@inheritDoc} */ 59b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson @Override 60b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson public void addContents(DexFile file) { 61b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson MethodHandlesSection methodHandles = file.getMethodHandles(); 62b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson methodHandles.intern(methodHandle); 63b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } 64b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson 65b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson /** {@inheritDoc} */ 66b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson @Override 67b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson public void writeTo(DexFile file, AnnotatedOutput out) { 68b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson int targetIndex = getTargetIndex(file); 69d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson int mhType = methodHandle.getMethodHandleType(); 70b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson if (out.annotates()) { 71d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson out.annotate(0, indexString() + ' ' + methodHandle.toString()); 72d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson String typeComment = " // " + CstMethodHandle.getMethodHandleTypeName(mhType); 73d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson out.annotate(2, "type: " + Hex.u2(mhType) + typeComment); 74d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson out.annotate(2, "reserved: " + Hex.u2(0)); 75d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson String targetComment = " // " + methodHandle.getRef().toString(); 76b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson if (methodHandle.isAccessor()) { 77d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson out.annotate(2, "fieldId: " + Hex.u2(targetIndex) + targetComment); 78b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } else { 79d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson out.annotate(2, "methodId: " + Hex.u2(targetIndex) + targetComment); 80b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } 81d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson out.annotate(2, "reserved: " + Hex.u2(0)); 82b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } 83d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson out.writeShort(mhType); 84b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson out.writeShort(0); 85b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson out.writeShort(getTargetIndex(file)); 86b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson out.writeShort(0); 87b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } 88b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson 89b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson private int getTargetIndex(DexFile file) { 90b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson Constant ref = methodHandle.getRef(); 91b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson if (methodHandle.isAccessor()) { 92b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson FieldIdsSection fieldIds = file.getFieldIds(); 93b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson return fieldIds.indexOf((CstFieldRef) ref); 94b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } else if (methodHandle.isInvocation()) { 95b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson if (ref instanceof CstInterfaceMethodRef) { 96b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson ref = ((CstInterfaceMethodRef)ref).toMethodRef(); 97b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } 98b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson MethodIdsSection methodIds = file.getMethodIds(); 99b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson return methodIds.indexOf((CstBaseMethodRef) ref); 100b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } else { 101b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson throw new IllegalStateException("Unhandled invocation type"); 102b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } 103b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson } 104b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson} 105