mirror of
https://github.com/revanced/smali.git
synced 2025-05-24 02:22:20 +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.Adaptors.ReferenceFormatter;
|
||||||
import org.jf.baksmali.Renderers.*;
|
import org.jf.baksmali.Renderers.*;
|
||||||
|
import org.jf.dexlib2.ReferenceType;
|
||||||
import org.jf.dexlib2.ValueType;
|
import org.jf.dexlib2.ValueType;
|
||||||
import org.jf.dexlib2.iface.value.*;
|
import org.jf.dexlib2.iface.value.*;
|
||||||
import org.jf.dexlib2.util.ReferenceUtil;
|
import org.jf.dexlib2.util.ReferenceUtil;
|
||||||
@ -107,6 +108,17 @@ public abstract class EncodedValueAdaptor {
|
|||||||
return;
|
return;
|
||||||
case ValueType.TYPE:
|
case ValueType.TYPE:
|
||||||
writer.write(((TypeEncodedValue)encodedValue).getValue());
|
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;
|
||||||
import org.jf.baksmali.Adaptors.MethodDefinition.InvalidSwitchPayload;
|
import org.jf.baksmali.Adaptors.MethodDefinition.InvalidSwitchPayload;
|
||||||
import org.jf.baksmali.Adaptors.MethodItem;
|
import org.jf.baksmali.Adaptors.MethodItem;
|
||||||
|
import org.jf.baksmali.Adaptors.ReferenceFormatter;
|
||||||
import org.jf.baksmali.Renderers.LongRenderer;
|
import org.jf.baksmali.Renderers.LongRenderer;
|
||||||
import org.jf.baksmali.BaksmaliOptions;
|
import org.jf.baksmali.BaksmaliOptions;
|
||||||
import org.jf.dexlib2.Opcode;
|
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.Instruction20bc;
|
||||||
import org.jf.dexlib2.iface.instruction.formats.Instruction31t;
|
import org.jf.dexlib2.iface.instruction.formats.Instruction31t;
|
||||||
import org.jf.dexlib2.iface.instruction.formats.UnknownInstruction;
|
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.iface.reference.Reference;
|
||||||
import org.jf.dexlib2.util.ReferenceUtil;
|
import org.jf.dexlib2.util.ReferenceUtil;
|
||||||
import org.jf.util.ExceptionWithContext;
|
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());
|
return String.format("%s@%d", ReferenceType.toString(type), ex.getInvalidIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private interface Writable {
|
||||||
|
void writeTo(IndentingWriter writer) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||||
Opcode opcode = instruction.getOpcode();
|
Opcode opcode = instruction.getOpcode();
|
||||||
String verificationErrorName = null;
|
String verificationErrorName = null;
|
||||||
String referenceString = null;
|
Writable referenceWritable = null;
|
||||||
String referenceString2 = null;
|
Writable referenceWritable2 = null;
|
||||||
|
|
||||||
boolean commentOutInstruction = false;
|
boolean commentOutInstruction = false;
|
||||||
|
|
||||||
@ -109,25 +115,34 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
|
|
||||||
if (instruction instanceof ReferenceInstruction) {
|
if (instruction instanceof ReferenceInstruction) {
|
||||||
ReferenceInstruction referenceInstruction = (ReferenceInstruction)instruction;
|
ReferenceInstruction referenceInstruction = (ReferenceInstruction)instruction;
|
||||||
String classContext = null;
|
final String classContext;
|
||||||
if (methodDef.classDef.options.implicitReferences) {
|
if (methodDef.classDef.options.implicitReferences) {
|
||||||
classContext = methodDef.method.getDefiningClass();
|
classContext = methodDef.method.getDefiningClass();
|
||||||
|
} else {
|
||||||
|
classContext = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Reference reference = referenceInstruction.getReference();
|
Reference reference = referenceInstruction.getReference();
|
||||||
referenceString = ReferenceUtil.getReferenceString(reference, classContext);
|
if (reference instanceof CallSiteReference) {
|
||||||
assert referenceString != null;
|
referenceWritable = indentingWriter -> {
|
||||||
|
ReferenceFormatter.writeCallSiteReference(indentingWriter, (CallSiteReference)reference);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
referenceWritable = indentingWriter -> {
|
||||||
|
indentingWriter.write(ReferenceUtil.getReferenceString(reference, classContext));
|
||||||
|
};
|
||||||
|
}
|
||||||
} catch (InvalidItemIndex ex) {
|
} catch (InvalidItemIndex ex) {
|
||||||
commentOutInstruction = true;
|
commentOutInstruction = true;
|
||||||
referenceString = writeInvalidItemIndex(ex, referenceInstruction.getReferenceType(),
|
String referenceString = writeInvalidItemIndex(ex, referenceInstruction.getReferenceType(),
|
||||||
writer);
|
writer);
|
||||||
|
referenceWritable = indentingWriter -> writer.write(referenceString);
|
||||||
} catch (ReferenceType.InvalidReferenceTypeException ex) {
|
} catch (ReferenceType.InvalidReferenceTypeException ex) {
|
||||||
writer.write("#invalid reference type: ");
|
writer.write("#invalid reference type: ");
|
||||||
writer.printSignedIntAsDec(ex.getReferenceType());
|
writer.printSignedIntAsDec(ex.getReferenceType());
|
||||||
commentOutInstruction = true;
|
commentOutInstruction = true;
|
||||||
|
referenceWritable = indentingWriter -> writer.write("invalid_reference");
|
||||||
referenceString = "invalid_reference";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instruction instanceof DualReferenceInstruction) {
|
if (instruction instanceof DualReferenceInstruction) {
|
||||||
@ -135,17 +150,19 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
(DualReferenceInstruction) instruction;
|
(DualReferenceInstruction) instruction;
|
||||||
try {
|
try {
|
||||||
Reference reference2 = dualReferenceInstruction.getReference2();
|
Reference reference2 = dualReferenceInstruction.getReference2();
|
||||||
referenceString2 = ReferenceUtil.getReferenceString(reference2, classContext);
|
referenceWritable2 = indentingWriter -> {
|
||||||
|
indentingWriter.write(ReferenceUtil.getReferenceString(reference2, classContext));
|
||||||
|
};
|
||||||
} catch (InvalidItemIndex ex) {
|
} catch (InvalidItemIndex ex) {
|
||||||
commentOutInstruction = true;
|
commentOutInstruction = true;
|
||||||
referenceString2 = writeInvalidItemIndex(ex,
|
String referenceString = writeInvalidItemIndex(ex,
|
||||||
dualReferenceInstruction.getReferenceType2(), writer);
|
dualReferenceInstruction.getReferenceType2(), writer);
|
||||||
|
referenceWritable2 = indentingWriter -> indentingWriter.write(referenceString);
|
||||||
} catch (ReferenceType.InvalidReferenceTypeException ex) {
|
} catch (ReferenceType.InvalidReferenceTypeException ex) {
|
||||||
writer.write("#invalid reference type: ");
|
writer.write("#invalid reference type: ");
|
||||||
writer.printSignedIntAsDec(ex.getReferenceType());
|
writer.printSignedIntAsDec(ex.getReferenceType());
|
||||||
commentOutInstruction = true;
|
commentOutInstruction = true;
|
||||||
|
referenceWritable2 = indentingWriter -> indentingWriter.write("invalid reference");
|
||||||
referenceString2 = "invalid_reference";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,7 +252,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
writer.write(' ');
|
writer.write(' ');
|
||||||
writer.write(verificationErrorName);
|
writer.write(verificationErrorName);
|
||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writer.write(referenceString);
|
referenceWritable.writeTo(writer);
|
||||||
break;
|
break;
|
||||||
case Format20t:
|
case Format20t:
|
||||||
case Format30t:
|
case Format30t:
|
||||||
@ -249,7 +266,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
writer.write(' ');
|
writer.write(' ');
|
||||||
writeFirstRegister(writer);
|
writeFirstRegister(writer);
|
||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writer.write(referenceString);
|
referenceWritable.writeTo(writer);
|
||||||
break;
|
break;
|
||||||
case Format21ih:
|
case Format21ih:
|
||||||
case Format21lh:
|
case Format21lh:
|
||||||
@ -293,7 +310,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writeSecondRegister(writer);
|
writeSecondRegister(writer);
|
||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writer.write(referenceString);
|
referenceWritable.writeTo(writer);
|
||||||
break;
|
break;
|
||||||
case Format22cs:
|
case Format22cs:
|
||||||
writeOpcode(writer);
|
writeOpcode(writer);
|
||||||
@ -335,7 +352,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
writer.write(' ');
|
writer.write(' ');
|
||||||
writeInvokeRegisters(writer);
|
writeInvokeRegisters(writer);
|
||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writer.write(referenceString);
|
referenceWritable.writeTo(writer);
|
||||||
break;
|
break;
|
||||||
case Format35mi:
|
case Format35mi:
|
||||||
writeOpcode(writer);
|
writeOpcode(writer);
|
||||||
@ -356,7 +373,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
writer.write(' ');
|
writer.write(' ');
|
||||||
writeInvokeRangeRegisters(writer);
|
writeInvokeRangeRegisters(writer);
|
||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writer.write(referenceString);
|
referenceWritable.writeTo(writer);
|
||||||
break;
|
break;
|
||||||
case Format3rmi:
|
case Format3rmi:
|
||||||
writeOpcode(writer);
|
writeOpcode(writer);
|
||||||
@ -377,18 +394,18 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
writer.write(' ');
|
writer.write(' ');
|
||||||
writeInvokeRegisters(writer);
|
writeInvokeRegisters(writer);
|
||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writer.write(referenceString);
|
referenceWritable.writeTo(writer);
|
||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writer.write(referenceString2);
|
referenceWritable2.writeTo(writer);
|
||||||
break;
|
break;
|
||||||
case Format4rcc:
|
case Format4rcc:
|
||||||
writeOpcode(writer);
|
writeOpcode(writer);
|
||||||
writer.write(' ');
|
writer.write(' ');
|
||||||
writeInvokeRangeRegisters(writer);
|
writeInvokeRangeRegisters(writer);
|
||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writer.write(referenceString);
|
referenceWritable.writeTo(writer);
|
||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writer.write(referenceString2);
|
referenceWritable2.writeTo(writer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert false;
|
assert false;
|
||||||
|
@ -28,8 +28,11 @@
|
|||||||
|
|
||||||
package org.jf.baksmali.Adaptors;
|
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.ReferenceType;
|
||||||
import org.jf.dexlib2.iface.reference.*;
|
import org.jf.dexlib2.iface.reference.*;
|
||||||
|
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||||
import org.jf.dexlib2.util.ReferenceUtil;
|
import org.jf.dexlib2.util.ReferenceUtil;
|
||||||
import org.jf.util.IndentingWriter;
|
import org.jf.util.IndentingWriter;
|
||||||
import org.jf.util.StringUtils;
|
import org.jf.util.StringUtils;
|
||||||
@ -43,6 +46,26 @@ public class ReferenceFormatter {
|
|||||||
writer.write('"');
|
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,
|
public static void writeReference(IndentingWriter writer, int referenceType,
|
||||||
Reference reference) throws IOException {
|
Reference reference) throws IOException {
|
||||||
switch (referenceType) {
|
switch (referenceType) {
|
||||||
@ -58,6 +81,17 @@ public class ReferenceFormatter {
|
|||||||
case ReferenceType.FIELD:
|
case ReferenceType.FIELD:
|
||||||
ReferenceUtil.writeFieldDescriptor(writer, (FieldReference)reference);
|
ReferenceUtil.writeFieldDescriptor(writer, (FieldReference)reference);
|
||||||
return;
|
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:
|
default:
|
||||||
throw new IllegalStateException("Unknown reference type");
|
throw new IllegalStateException("Unknown reference type");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user