mirror of
https://github.com/revanced/smali.git
synced 2025-05-23 18:16:23 +02:00
Add support for invoke-custom and related structures in baksmali
This commit is contained in:
parent
e8760aa46b
commit
48d13b297f
@ -30,6 +30,7 @@ package org.jf.baksmali.Adaptors.EncodedValue;
|
||||
|
||||
import org.jf.baksmali.Adaptors.ReferenceFormatter;
|
||||
import org.jf.baksmali.Renderers.*;
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.ValueType;
|
||||
import org.jf.dexlib2.iface.value.*;
|
||||
import org.jf.dexlib2.util.ReferenceUtil;
|
||||
@ -107,6 +108,17 @@ public abstract class EncodedValueAdaptor {
|
||||
return;
|
||||
case ValueType.TYPE:
|
||||
writer.write(((TypeEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.METHOD_TYPE:
|
||||
ReferenceFormatter.writeReference(writer, ReferenceType.METHOD_PROTO,
|
||||
((MethodTypeEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
case ValueType.METHOD_HANDLE:
|
||||
ReferenceFormatter.writeReference(writer, ReferenceType.METHOD_HANDLE,
|
||||
((MethodHandleEncodedValue)encodedValue).getValue());
|
||||
return;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown encoded value type: " + encodedValue.getValueType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ package org.jf.baksmali.Adaptors.Format;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition;
|
||||
import org.jf.baksmali.Adaptors.MethodDefinition.InvalidSwitchPayload;
|
||||
import org.jf.baksmali.Adaptors.MethodItem;
|
||||
import org.jf.baksmali.Adaptors.ReferenceFormatter;
|
||||
import org.jf.baksmali.Renderers.LongRenderer;
|
||||
import org.jf.baksmali.BaksmaliOptions;
|
||||
import org.jf.dexlib2.Opcode;
|
||||
@ -41,6 +42,7 @@ import org.jf.dexlib2.iface.instruction.*;
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction20bc;
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction31t;
|
||||
import org.jf.dexlib2.iface.instruction.formats.UnknownInstruction;
|
||||
import org.jf.dexlib2.iface.reference.CallSiteReference;
|
||||
import org.jf.dexlib2.iface.reference.Reference;
|
||||
import org.jf.dexlib2.util.ReferenceUtil;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
@ -87,12 +89,16 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
return String.format("%s@%d", ReferenceType.toString(type), ex.getInvalidIndex());
|
||||
}
|
||||
|
||||
private interface Writable {
|
||||
void writeTo(IndentingWriter writer) throws IOException;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
Opcode opcode = instruction.getOpcode();
|
||||
String verificationErrorName = null;
|
||||
String referenceString = null;
|
||||
String referenceString2 = null;
|
||||
Writable referenceWritable = null;
|
||||
Writable referenceWritable2 = null;
|
||||
|
||||
boolean commentOutInstruction = false;
|
||||
|
||||
@ -109,25 +115,34 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
|
||||
if (instruction instanceof ReferenceInstruction) {
|
||||
ReferenceInstruction referenceInstruction = (ReferenceInstruction)instruction;
|
||||
String classContext = null;
|
||||
final String classContext;
|
||||
if (methodDef.classDef.options.implicitReferences) {
|
||||
classContext = methodDef.method.getDefiningClass();
|
||||
} else {
|
||||
classContext = null;
|
||||
}
|
||||
|
||||
try {
|
||||
Reference reference = referenceInstruction.getReference();
|
||||
referenceString = ReferenceUtil.getReferenceString(reference, classContext);
|
||||
assert referenceString != null;
|
||||
if (reference instanceof CallSiteReference) {
|
||||
referenceWritable = indentingWriter -> {
|
||||
ReferenceFormatter.writeCallSiteReference(indentingWriter, (CallSiteReference)reference);
|
||||
};
|
||||
} else {
|
||||
referenceWritable = indentingWriter -> {
|
||||
indentingWriter.write(ReferenceUtil.getReferenceString(reference, classContext));
|
||||
};
|
||||
}
|
||||
} catch (InvalidItemIndex ex) {
|
||||
commentOutInstruction = true;
|
||||
referenceString = writeInvalidItemIndex(ex, referenceInstruction.getReferenceType(),
|
||||
String referenceString = writeInvalidItemIndex(ex, referenceInstruction.getReferenceType(),
|
||||
writer);
|
||||
referenceWritable = indentingWriter -> writer.write(referenceString);
|
||||
} catch (ReferenceType.InvalidReferenceTypeException ex) {
|
||||
writer.write("#invalid reference type: ");
|
||||
writer.printSignedIntAsDec(ex.getReferenceType());
|
||||
commentOutInstruction = true;
|
||||
|
||||
referenceString = "invalid_reference";
|
||||
referenceWritable = indentingWriter -> writer.write("invalid_reference");
|
||||
}
|
||||
|
||||
if (instruction instanceof DualReferenceInstruction) {
|
||||
@ -135,17 +150,19 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
(DualReferenceInstruction) instruction;
|
||||
try {
|
||||
Reference reference2 = dualReferenceInstruction.getReference2();
|
||||
referenceString2 = ReferenceUtil.getReferenceString(reference2, classContext);
|
||||
referenceWritable2 = indentingWriter -> {
|
||||
indentingWriter.write(ReferenceUtil.getReferenceString(reference2, classContext));
|
||||
};
|
||||
} catch (InvalidItemIndex ex) {
|
||||
commentOutInstruction = true;
|
||||
referenceString2 = writeInvalidItemIndex(ex,
|
||||
String referenceString = writeInvalidItemIndex(ex,
|
||||
dualReferenceInstruction.getReferenceType2(), writer);
|
||||
referenceWritable2 = indentingWriter -> indentingWriter.write(referenceString);
|
||||
} catch (ReferenceType.InvalidReferenceTypeException ex) {
|
||||
writer.write("#invalid reference type: ");
|
||||
writer.printSignedIntAsDec(ex.getReferenceType());
|
||||
commentOutInstruction = true;
|
||||
|
||||
referenceString2 = "invalid_reference";
|
||||
referenceWritable2 = indentingWriter -> indentingWriter.write("invalid reference");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -235,7 +252,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
writer.write(' ');
|
||||
writer.write(verificationErrorName);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
referenceWritable.writeTo(writer);
|
||||
break;
|
||||
case Format20t:
|
||||
case Format30t:
|
||||
@ -249,7 +266,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
writer.write(' ');
|
||||
writeFirstRegister(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
referenceWritable.writeTo(writer);
|
||||
break;
|
||||
case Format21ih:
|
||||
case Format21lh:
|
||||
@ -293,7 +310,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
writer.write(", ");
|
||||
writeSecondRegister(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
referenceWritable.writeTo(writer);
|
||||
break;
|
||||
case Format22cs:
|
||||
writeOpcode(writer);
|
||||
@ -335,7 +352,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
writer.write(' ');
|
||||
writeInvokeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
referenceWritable.writeTo(writer);
|
||||
break;
|
||||
case Format35mi:
|
||||
writeOpcode(writer);
|
||||
@ -356,7 +373,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
writer.write(' ');
|
||||
writeInvokeRangeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
referenceWritable.writeTo(writer);
|
||||
break;
|
||||
case Format3rmi:
|
||||
writeOpcode(writer);
|
||||
@ -377,18 +394,18 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
||||
writer.write(' ');
|
||||
writeInvokeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
referenceWritable.writeTo(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString2);
|
||||
referenceWritable2.writeTo(writer);
|
||||
break;
|
||||
case Format4rcc:
|
||||
writeOpcode(writer);
|
||||
writer.write(' ');
|
||||
writeInvokeRangeRegisters(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString);
|
||||
referenceWritable.writeTo(writer);
|
||||
writer.write(", ");
|
||||
writer.write(referenceString2);
|
||||
referenceWritable2.writeTo(writer);
|
||||
break;
|
||||
default:
|
||||
assert false;
|
||||
|
@ -28,8 +28,11 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.baksmali.Adaptors.EncodedValue.EncodedValueAdaptor;
|
||||
import org.jf.dexlib2.MethodHandleType;
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.iface.reference.*;
|
||||
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||
import org.jf.dexlib2.util.ReferenceUtil;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.util.StringUtils;
|
||||
@ -43,6 +46,26 @@ public class ReferenceFormatter {
|
||||
writer.write('"');
|
||||
}
|
||||
|
||||
public static void writeCallSiteReference(IndentingWriter writer, CallSiteReference callSite) throws IOException {
|
||||
writer.write(callSite.getName());
|
||||
writer.write('(');
|
||||
writer.write('"');
|
||||
StringUtils.writeEscapedString(writer, callSite.getMethodName());
|
||||
writer.write("\", ");
|
||||
writeReference(writer, ReferenceType.METHOD_PROTO, callSite.getMethodProto());
|
||||
|
||||
for (EncodedValue encodedValue : callSite.getExtraArguments()) {
|
||||
writer.write(", ");
|
||||
EncodedValueAdaptor.writeTo(writer, encodedValue, null);
|
||||
}
|
||||
writer.write(")@");
|
||||
MethodHandleReference methodHandle = callSite.getMethodHandle();
|
||||
if (methodHandle.getMethodHandleType() != MethodHandleType.STATIC_INVOKE) {
|
||||
throw new IllegalArgumentException("The linker method handle for a call site must be of type static-invoke");
|
||||
}
|
||||
writeReference(writer, ReferenceType.METHOD, callSite.getMethodHandle().getMemberReference());
|
||||
}
|
||||
|
||||
public static void writeReference(IndentingWriter writer, int referenceType,
|
||||
Reference reference) throws IOException {
|
||||
switch (referenceType) {
|
||||
@ -58,6 +81,17 @@ public class ReferenceFormatter {
|
||||
case ReferenceType.FIELD:
|
||||
ReferenceUtil.writeFieldDescriptor(writer, (FieldReference)reference);
|
||||
return;
|
||||
case ReferenceType.METHOD_PROTO:
|
||||
ReferenceUtil.writeMethodProtoDescriptor(writer, (MethodProtoReference)reference);
|
||||
return;
|
||||
case ReferenceType.METHOD_HANDLE:
|
||||
ReferenceUtil.writeMethodHandle(writer, (MethodHandleReference)reference);
|
||||
return;
|
||||
case ReferenceType.CALL_SITE:
|
||||
// We can't use ReferenceUtil.writeCallSite here, because it doesn't write encoded values out in the
|
||||
// exact format we need here.
|
||||
writeCallSiteReference(writer, (CallSiteReference)reference);
|
||||
return;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown reference type");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user