mirror of
https://github.com/revanced/smali.git
synced 2025-05-06 17:34:34 +02:00
Add support for method handle and call site references in ReferenceUtil
This commit is contained in:
parent
d82252e4d6
commit
e8760aa46b
@ -32,7 +32,13 @@
|
||||
package org.jf.dexlib2.util;
|
||||
|
||||
import org.jf.dexlib2.ValueType;
|
||||
import org.jf.dexlib2.iface.AnnotationElement;
|
||||
import org.jf.dexlib2.iface.value.*;
|
||||
import org.jf.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Set;
|
||||
|
||||
public final class EncodedValueUtils {
|
||||
public static boolean isDefaultValue(EncodedValue encodedValue) {
|
||||
@ -59,5 +65,99 @@ public final class EncodedValueUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void writeEncodedValue(Writer writer, EncodedValue encodedValue) throws IOException {
|
||||
switch (encodedValue.getValueType()) {
|
||||
case ValueType.BOOLEAN:
|
||||
writer.write(Boolean.toString(((BooleanEncodedValue) encodedValue).getValue()));
|
||||
break;
|
||||
case ValueType.BYTE:
|
||||
writer.write(Byte.toString(((ByteEncodedValue)encodedValue).getValue()));
|
||||
break;
|
||||
case ValueType.CHAR:
|
||||
writer.write(Integer.toString(((CharEncodedValue)encodedValue).getValue()));
|
||||
break;
|
||||
case ValueType.SHORT:
|
||||
writer.write(Short.toString(((ShortEncodedValue)encodedValue).getValue()));
|
||||
break;
|
||||
case ValueType.INT:
|
||||
writer.write(Integer.toString(((IntEncodedValue)encodedValue).getValue()));
|
||||
break;
|
||||
case ValueType.LONG:
|
||||
writer.write(Long.toString(((LongEncodedValue)encodedValue).getValue()));
|
||||
break;
|
||||
case ValueType.FLOAT:
|
||||
writer.write(Float.toString(((FloatEncodedValue)encodedValue).getValue()));
|
||||
break;
|
||||
case ValueType.DOUBLE:
|
||||
writer.write(Double.toString(((DoubleEncodedValue)encodedValue).getValue()));
|
||||
break;
|
||||
case ValueType.ANNOTATION:
|
||||
writeAnnotation(writer, (AnnotationEncodedValue)encodedValue);
|
||||
break;
|
||||
case ValueType.ARRAY:
|
||||
writeArray(writer, (ArrayEncodedValue)encodedValue);
|
||||
break;
|
||||
case ValueType.STRING:
|
||||
writer.write('"');
|
||||
StringUtils.writeEscapedString(writer, ((StringEncodedValue)encodedValue).getValue());
|
||||
writer.write('"');
|
||||
break;
|
||||
case ValueType.FIELD:
|
||||
ReferenceUtil.writeFieldDescriptor(writer, ((FieldEncodedValue)encodedValue).getValue());
|
||||
break;
|
||||
case ValueType.ENUM:
|
||||
ReferenceUtil.writeFieldDescriptor(writer, ((EnumEncodedValue)encodedValue).getValue());
|
||||
break;
|
||||
case ValueType.METHOD:
|
||||
ReferenceUtil.writeMethodDescriptor(writer, ((MethodEncodedValue)encodedValue).getValue());
|
||||
break;
|
||||
case ValueType.TYPE:
|
||||
writer.write(((TypeEncodedValue)encodedValue).getValue());
|
||||
break;
|
||||
case ValueType.METHOD_TYPE:
|
||||
ReferenceUtil.writeMethodProtoDescriptor(writer, ((MethodTypeEncodedValue)encodedValue).getValue());
|
||||
break;
|
||||
case ValueType.METHOD_HANDLE:
|
||||
ReferenceUtil.writeMethodHandle(writer, ((MethodHandleEncodedValue)encodedValue).getValue());
|
||||
break;
|
||||
case ValueType.NULL:
|
||||
writer.write("null");
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown encoded value type");
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeAnnotation(Writer writer, AnnotationEncodedValue annotation) throws IOException {
|
||||
writer.write("Annotation[");
|
||||
writer.write(annotation.getType());
|
||||
|
||||
Set<? extends AnnotationElement> elements = annotation.getElements();
|
||||
for (AnnotationElement element: elements) {
|
||||
writer.write(", ");
|
||||
writer.write(element.getName());
|
||||
writer.write('=');
|
||||
writeEncodedValue(writer, element.getValue());
|
||||
}
|
||||
|
||||
writer.write(']');
|
||||
}
|
||||
|
||||
private static void writeArray(Writer writer, ArrayEncodedValue array) throws IOException {
|
||||
writer.write("Array[");
|
||||
|
||||
boolean first = true;
|
||||
for (EncodedValue element: array.getValue()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
writer.write(", ");
|
||||
}
|
||||
writeEncodedValue(writer, element);
|
||||
}
|
||||
|
||||
writer.write(']');
|
||||
}
|
||||
|
||||
private EncodedValueUtils() {}
|
||||
}
|
||||
|
@ -31,12 +31,15 @@
|
||||
|
||||
package org.jf.dexlib2.util;
|
||||
|
||||
import org.jf.dexlib2.MethodHandleType;
|
||||
import org.jf.dexlib2.iface.reference.*;
|
||||
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||
import org.jf.util.StringUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
public final class ReferenceUtil {
|
||||
@ -61,14 +64,24 @@ public final class ReferenceUtil {
|
||||
}
|
||||
|
||||
public static String getMethodProtoDescriptor(MethodProtoReference methodProtoReference) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('(');
|
||||
for (CharSequence paramType : methodProtoReference.getParameterTypes()) {
|
||||
sb.append(paramType);
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
try {
|
||||
writeMethodProtoDescriptor(stringWriter, methodProtoReference);
|
||||
} catch (IOException ex) {
|
||||
// IOException shouldn't happen for a StringWriter...
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
sb.append(')');
|
||||
sb.append(methodProtoReference.getReturnType());
|
||||
return sb.toString();
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
public static void writeMethodProtoDescriptor(Writer writer, MethodProtoReference methodProtoReference)
|
||||
throws IOException {
|
||||
writer.write('(');
|
||||
for (CharSequence paramType : methodProtoReference.getParameterTypes()) {
|
||||
writer.write(paramType.toString());
|
||||
}
|
||||
writer.write(')');
|
||||
writer.write(methodProtoReference.getReturnType());
|
||||
}
|
||||
|
||||
public static void writeMethodDescriptor(Writer writer, MethodReference methodReference) throws IOException {
|
||||
@ -129,6 +142,62 @@ public final class ReferenceUtil {
|
||||
writer.write(fieldReference.getType());
|
||||
}
|
||||
|
||||
public static String getMethodHandleString(MethodHandleReference methodHandleReference) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
try {
|
||||
writeMethodHandle(stringWriter, methodHandleReference);
|
||||
} catch (IOException ex) {
|
||||
// IOException shouldn't happen for a StringWriter...
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
public static void writeMethodHandle(Writer writer, MethodHandleReference methodHandleReference)
|
||||
throws IOException {
|
||||
writer.write(MethodHandleType.toString(methodHandleReference.getMethodHandleType()));
|
||||
writer.write('@');
|
||||
|
||||
Reference memberReference = methodHandleReference.getMemberReference();
|
||||
if (memberReference instanceof MethodReference) {
|
||||
writeMethodDescriptor(writer, (MethodReference)memberReference);
|
||||
} else {
|
||||
writeFieldDescriptor(writer, (FieldReference)memberReference);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getCallSiteString(CallSiteReference callSiteReference) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
try {
|
||||
writeCallSite(stringWriter, callSiteReference);
|
||||
} catch (IOException ex) {
|
||||
// IOException shouldn't happen for a StringWriter...
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
public static void writeCallSite(Writer writer, CallSiteReference callSiteReference) throws IOException {
|
||||
writer.write(callSiteReference.getName());
|
||||
writer.write('(');
|
||||
writer.write('"');
|
||||
StringUtils.writeEscapedString(writer, callSiteReference.getMethodName());
|
||||
writer.write('"');
|
||||
writer.write(", ");
|
||||
writeMethodProtoDescriptor(writer, callSiteReference.getMethodProto());
|
||||
|
||||
for (EncodedValue encodedValue : callSiteReference.getExtraArguments()) {
|
||||
writer.write(", ");
|
||||
EncodedValueUtils.writeEncodedValue(writer, encodedValue);
|
||||
}
|
||||
writer.write(")@");
|
||||
MethodHandleReference methodHandle = callSiteReference.getMethodHandle();
|
||||
if (methodHandle.getMethodHandleType() != MethodHandleType.STATIC_INVOKE) {
|
||||
throw new IllegalArgumentException("The linker method handle for a call site must be of type static-invoke");
|
||||
}
|
||||
writeMethodDescriptor(writer, (MethodReference)callSiteReference.getMethodHandle().getMemberReference());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getReferenceString(@Nonnull Reference reference) {
|
||||
return getReferenceString(reference, null);
|
||||
@ -156,6 +225,14 @@ public final class ReferenceUtil {
|
||||
MethodProtoReference methodProtoReference = (MethodProtoReference)reference;
|
||||
return getMethodProtoDescriptor(methodProtoReference);
|
||||
}
|
||||
if (reference instanceof MethodHandleReference) {
|
||||
MethodHandleReference methodHandleReference = (MethodHandleReference)reference;
|
||||
return getMethodHandleString(methodHandleReference);
|
||||
}
|
||||
if (reference instanceof CallSiteReference) {
|
||||
CallSiteReference callSiteReference = (CallSiteReference)reference;
|
||||
return getCallSiteString(callSiteReference);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user