1*055d4590SKeyi Gui /* 2*055d4590SKeyi Gui * Copyright (C) 2017 The Android Open Source Project 3*055d4590SKeyi Gui * 4*055d4590SKeyi Gui * Licensed under the Apache License, Version 2.0 (the "License"); 5*055d4590SKeyi Gui * you may not use this file except in compliance with the License. 6*055d4590SKeyi Gui * You may obtain a copy of the License at 7*055d4590SKeyi Gui * 8*055d4590SKeyi Gui * http://www.apache.org/licenses/LICENSE-2.0 9*055d4590SKeyi Gui * 10*055d4590SKeyi Gui * Unless required by applicable law or agreed to in writing, software 11*055d4590SKeyi Gui * distributed under the License is distributed on an "AS IS" BASIS, 12*055d4590SKeyi Gui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*055d4590SKeyi Gui * See the License for the specific language governing permissions and 14*055d4590SKeyi Gui * limitations under the License. 15*055d4590SKeyi Gui */ 16*055d4590SKeyi Gui 17*055d4590SKeyi Gui package com.android.dex; 18*055d4590SKeyi Gui 19*055d4590SKeyi Gui import com.android.dex.Dex.Section; 20*055d4590SKeyi Gui import com.android.dex.util.Unsigned; 21*055d4590SKeyi Gui 22*055d4590SKeyi Gui /** 23*055d4590SKeyi Gui * A method_handle_item: 24*055d4590SKeyi Gui * https://source.android.com/devices/tech/dalvik/dex-format#method-handle-item 25*055d4590SKeyi Gui */ 26*055d4590SKeyi Gui public class MethodHandle implements Comparable<MethodHandle> { 27*055d4590SKeyi Gui 28*055d4590SKeyi Gui /** 29*055d4590SKeyi Gui * A method handle type code: 30*055d4590SKeyi Gui * https://source.android.com/devices/tech/dalvik/dex-format#method-handle-type-codes 31*055d4590SKeyi Gui */ 32*055d4590SKeyi Gui public enum MethodHandleType { 33*055d4590SKeyi Gui METHOD_HANDLE_TYPE_STATIC_PUT(0x00), 34*055d4590SKeyi Gui METHOD_HANDLE_TYPE_STATIC_GET(0x01), 35*055d4590SKeyi Gui METHOD_HANDLE_TYPE_INSTANCE_PUT(0x02), 36*055d4590SKeyi Gui METHOD_HANDLE_TYPE_INSTANCE_GET(0x03), 37*055d4590SKeyi Gui METHOD_HANDLE_TYPE_INVOKE_STATIC(0x04), 38*055d4590SKeyi Gui METHOD_HANDLE_TYPE_INVOKE_INSTANCE(0x05), 39*055d4590SKeyi Gui METHOD_HANDLE_TYPE_INVOKE_DIRECT(0x06), 40*055d4590SKeyi Gui METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR(0x07), 41*055d4590SKeyi Gui METHOD_HANDLE_TYPE_INVOKE_INTERFACE(0x08); 42*055d4590SKeyi Gui 43*055d4590SKeyi Gui private final int value; 44*055d4590SKeyi Gui MethodHandleType(int value)45*055d4590SKeyi Gui MethodHandleType(int value) { 46*055d4590SKeyi Gui this.value = value; 47*055d4590SKeyi Gui } 48*055d4590SKeyi Gui fromValue(int value)49*055d4590SKeyi Gui static MethodHandleType fromValue(int value) { 50*055d4590SKeyi Gui for (MethodHandleType methodHandleType : values()) { 51*055d4590SKeyi Gui if (methodHandleType.value == value) { 52*055d4590SKeyi Gui return methodHandleType; 53*055d4590SKeyi Gui } 54*055d4590SKeyi Gui } 55*055d4590SKeyi Gui throw new IllegalArgumentException(String.valueOf(value)); 56*055d4590SKeyi Gui } 57*055d4590SKeyi Gui isField()58*055d4590SKeyi Gui public boolean isField() { 59*055d4590SKeyi Gui switch (this) { 60*055d4590SKeyi Gui case METHOD_HANDLE_TYPE_STATIC_PUT: 61*055d4590SKeyi Gui case METHOD_HANDLE_TYPE_STATIC_GET: 62*055d4590SKeyi Gui case METHOD_HANDLE_TYPE_INSTANCE_PUT: 63*055d4590SKeyi Gui case METHOD_HANDLE_TYPE_INSTANCE_GET: 64*055d4590SKeyi Gui return true; 65*055d4590SKeyi Gui default: 66*055d4590SKeyi Gui return false; 67*055d4590SKeyi Gui } 68*055d4590SKeyi Gui } 69*055d4590SKeyi Gui } 70*055d4590SKeyi Gui 71*055d4590SKeyi Gui private final Dex dex; 72*055d4590SKeyi Gui private final MethodHandleType methodHandleType; 73*055d4590SKeyi Gui private final int unused1; 74*055d4590SKeyi Gui private final int fieldOrMethodId; 75*055d4590SKeyi Gui private final int unused2; 76*055d4590SKeyi Gui MethodHandle( Dex dex, MethodHandleType methodHandleType, int unused1, int fieldOrMethodId, int unused2)77*055d4590SKeyi Gui public MethodHandle( 78*055d4590SKeyi Gui Dex dex, 79*055d4590SKeyi Gui MethodHandleType methodHandleType, 80*055d4590SKeyi Gui int unused1, 81*055d4590SKeyi Gui int fieldOrMethodId, 82*055d4590SKeyi Gui int unused2) { 83*055d4590SKeyi Gui this.dex = dex; 84*055d4590SKeyi Gui this.methodHandleType = methodHandleType; 85*055d4590SKeyi Gui this.unused1 = unused1; 86*055d4590SKeyi Gui this.fieldOrMethodId = fieldOrMethodId; 87*055d4590SKeyi Gui this.unused2 = unused2; 88*055d4590SKeyi Gui } 89*055d4590SKeyi Gui 90*055d4590SKeyi Gui @Override compareTo(MethodHandle o)91*055d4590SKeyi Gui public int compareTo(MethodHandle o) { 92*055d4590SKeyi Gui if (methodHandleType != o.methodHandleType) { 93*055d4590SKeyi Gui return methodHandleType.compareTo(o.methodHandleType); 94*055d4590SKeyi Gui } 95*055d4590SKeyi Gui return Unsigned.compare(fieldOrMethodId, o.fieldOrMethodId); 96*055d4590SKeyi Gui } 97*055d4590SKeyi Gui getMethodHandleType()98*055d4590SKeyi Gui public MethodHandleType getMethodHandleType() { 99*055d4590SKeyi Gui return methodHandleType; 100*055d4590SKeyi Gui } 101*055d4590SKeyi Gui getUnused1()102*055d4590SKeyi Gui public int getUnused1() { 103*055d4590SKeyi Gui return unused1; 104*055d4590SKeyi Gui } 105*055d4590SKeyi Gui getFieldOrMethodId()106*055d4590SKeyi Gui public int getFieldOrMethodId() { 107*055d4590SKeyi Gui return fieldOrMethodId; 108*055d4590SKeyi Gui } 109*055d4590SKeyi Gui getUnused2()110*055d4590SKeyi Gui public int getUnused2() { 111*055d4590SKeyi Gui return unused2; 112*055d4590SKeyi Gui } 113*055d4590SKeyi Gui writeTo(Section out)114*055d4590SKeyi Gui public void writeTo(Section out) { 115*055d4590SKeyi Gui out.writeUnsignedShort(methodHandleType.value); 116*055d4590SKeyi Gui out.writeUnsignedShort(unused1); 117*055d4590SKeyi Gui out.writeUnsignedShort(fieldOrMethodId); 118*055d4590SKeyi Gui out.writeUnsignedShort(unused2); 119*055d4590SKeyi Gui } 120*055d4590SKeyi Gui 121*055d4590SKeyi Gui @Override toString()122*055d4590SKeyi Gui public String toString() { 123*055d4590SKeyi Gui if (dex == null) { 124*055d4590SKeyi Gui return methodHandleType + " " + fieldOrMethodId; 125*055d4590SKeyi Gui } 126*055d4590SKeyi Gui return methodHandleType 127*055d4590SKeyi Gui + " " 128*055d4590SKeyi Gui + (methodHandleType.isField() 129*055d4590SKeyi Gui ? dex.fieldIds().get(fieldOrMethodId) 130*055d4590SKeyi Gui : dex.methodIds().get(fieldOrMethodId)); 131*055d4590SKeyi Gui } 132*055d4590SKeyi Gui } 133