use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.
the class CustomMethodInlineTableTest method testCustomMethodInlineTable_Virtual.
@Test
public void testCustomMethodInlineTable_Virtual() throws IOException {
List<ImmutableInstruction> instructions = Lists.newArrayList(new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0), new ImmutableInstruction10x(Opcode.RETURN_VOID));
ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null);
ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.PUBLIC.getValue(), null, null, methodImpl);
ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, null, null, ImmutableList.of(method));
ImmutableDexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), ImmutableList.of(classDef));
ImmutableMultiDexContainer container = new ImmutableMultiDexContainer(ImmutableMap.of("classes.dex", dexFile));
ClassPathResolver resolver = new ClassPathResolver(ImmutableList.<String>of(), ImmutableList.<String>of(), ImmutableList.<String>of(), container.getEntry("classes.dex"));
ClassPath classPath = new ClassPath(resolver.getResolvedClassProviders(), false, ClassPath.NOT_ART);
InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V");
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver, false);
Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0);
Assert.assertEquals(Opcode.INVOKE_VIRTUAL, deodexedInstruction.getOpcode());
MethodReference methodReference = (MethodReference) ((Instruction35c) deodexedInstruction).getReference();
Assert.assertEquals(method, methodReference);
}
use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.
the class ImplicitReferenceTest method testImplicitMethodReference.
@Test
public void testImplicitMethodReference() throws RecognitionException, IOException {
ClassDef classDef = SmaliTestUtils.compileSmali("" + ".class public LHelloWorld;\n" + ".super Ljava/lang/Object;\n" + ".method public static main([Ljava/lang/String;)V\n" + " .registers 1\n" + " invoke-static {p0}, toString()V\n" + " invoke-static {p0}, V()V\n" + " invoke-static {p0}, I()V\n" + " return-void\n" + ".end method");
Method mainMethod = null;
for (Method method : classDef.getMethods()) {
if (method.getName().equals("main")) {
mainMethod = method;
}
}
Assert.assertNotNull(mainMethod);
MethodImplementation methodImpl = mainMethod.getImplementation();
Assert.assertNotNull(methodImpl);
List<Instruction> instructions = Lists.newArrayList(methodImpl.getInstructions());
Instruction35c instruction = (Instruction35c) instructions.get(0);
Assert.assertNotNull(instruction);
Assert.assertEquals(Opcode.INVOKE_STATIC, instruction.getOpcode());
MethodReference method = (MethodReference) instruction.getReference();
Assert.assertEquals(classDef.getType(), method.getDefiningClass());
Assert.assertEquals("toString", method.getName());
instruction = (Instruction35c) instructions.get(1);
Assert.assertNotNull(instruction);
Assert.assertEquals(Opcode.INVOKE_STATIC, instruction.getOpcode());
method = (MethodReference) instruction.getReference();
Assert.assertEquals(classDef.getType(), method.getDefiningClass());
Assert.assertEquals("V", method.getName());
instruction = (Instruction35c) instructions.get(2);
Assert.assertNotNull(instruction);
Assert.assertEquals(Opcode.INVOKE_STATIC, instruction.getOpcode());
method = (MethodReference) instruction.getReference();
Assert.assertEquals(classDef.getType(), method.getDefiningClass());
Assert.assertEquals("I", method.getName());
}
use of org.jf.dexlib2.iface.Method in project tinker by Tencent.
the class BuilderMutableMethodImplementation method fixInstructions.
private void fixInstructions() {
HashSet<MethodLocation> payloadLocations = Sets.newHashSet();
for (MethodLocation location : instructionList) {
BuilderInstruction instruction = location.instruction;
if (instruction != null) {
switch(instruction.getOpcode()) {
case SPARSE_SWITCH:
case PACKED_SWITCH:
{
MethodLocation targetLocation = ((BuilderOffsetInstruction) instruction).getTarget().getLocation();
BuilderInstruction targetInstruction = targetLocation.instruction;
if (targetInstruction == null) {
throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d points to the end of the method.", location.codeAddress, location.index));
}
if (targetInstruction.getOpcode() == Opcode.NOP) {
targetInstruction = getFirstNonNop(targetLocation.index + 1);
}
if (targetInstruction == null || !(targetInstruction instanceof BuilderSwitchPayload)) {
throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d does not refer to a payload instruction.", location.codeAddress, location.index));
}
if ((instruction.opcode == Opcode.PACKED_SWITCH && targetInstruction.getOpcode() != Opcode.PACKED_SWITCH_PAYLOAD) || (instruction.opcode == Opcode.SPARSE_SWITCH && targetInstruction.getOpcode() != Opcode.SPARSE_SWITCH_PAYLOAD)) {
throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d refers to the wrong type of payload instruction.", location.codeAddress, location.index));
}
if (!payloadLocations.add(targetLocation)) {
throw new IllegalStateException("Multiple switch instructions refer to the same payload. " + "This is not currently supported. Please file a bug :)");
}
((BuilderSwitchPayload) targetInstruction).referrer = location;
break;
}
default:
{
break;
}
}
}
}
boolean madeChanges;
do {
madeChanges = false;
for (int index = 0; index < instructionList.size(); index++) {
MethodLocation location = instructionList.get(index);
BuilderInstruction instruction = location.instruction;
if (instruction != null) {
switch(instruction.getOpcode()) {
case GOTO:
{
int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
if (offset < Byte.MIN_VALUE || offset > Byte.MAX_VALUE) {
BuilderOffsetInstruction replacement;
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
} else {
replacement = new BuilderInstruction20t(Opcode.GOTO_16, ((BuilderOffsetInstruction) instruction).getTarget());
}
replaceInstruction(location.index, replacement);
madeChanges = true;
}
break;
}
case GOTO_16:
{
int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
BuilderOffsetInstruction replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
replaceInstruction(location.index, replacement);
madeChanges = true;
}
break;
}
case SPARSE_SWITCH_PAYLOAD:
case PACKED_SWITCH_PAYLOAD:
if (((BuilderSwitchPayload) instruction).referrer == null) {
// if the switch payload isn't referenced, just remove it
removeInstruction(index);
index--;
madeChanges = true;
break;
}
// intentional fall-through
case ARRAY_PAYLOAD:
{
if ((location.codeAddress & 0x01) != 0) {
int previousIndex = location.index - 1;
MethodLocation previousLocation = instructionList.get(previousIndex);
Instruction previousInstruction = previousLocation.instruction;
assert previousInstruction != null;
if (previousInstruction.getOpcode() == Opcode.NOP) {
removeInstruction(previousIndex);
index--;
} else {
addInstruction(location.index, new BuilderInstruction10x(Opcode.NOP));
index++;
}
madeChanges = true;
}
break;
}
default:
{
break;
}
}
}
}
} while (madeChanges);
fixInstructions = false;
}
use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.
the class ClassDefinition method writeDirectMethods.
private Set<String> writeDirectMethods(BaksmaliWriter writer) throws IOException {
boolean wroteHeader = false;
Set<String> writtenMethods = new HashSet<String>();
Iterable<? extends Method> directMethods;
if (classDef instanceof DexBackedClassDef) {
directMethods = ((DexBackedClassDef) classDef).getDirectMethods(false);
} else {
directMethods = classDef.getDirectMethods();
}
for (Method method : directMethods) {
if (!wroteHeader) {
writer.write("\n\n");
writer.write("# direct methods");
wroteHeader = true;
}
writer.write('\n');
// TODO: check for method validation errors
String methodString = formatter.getShortMethodDescriptor(method);
BaksmaliWriter methodWriter = writer;
if (!writtenMethods.add(methodString)) {
writer.write("# duplicate method ignored\n");
methodWriter = getCommentingWriter(writer);
}
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl == null) {
MethodDefinition.writeEmptyMethodTo(methodWriter, method, this);
} else {
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
methodDefinition.writeTo(methodWriter);
}
}
return writtenMethods;
}
use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.
the class DexBackedMethod method getSize.
/**
* Calculate and return the private size of a method definition.
*
* Calculated as: method_idx_diff + access_flags + code_off +
* implementation size + reference size
*
* @return size in bytes
*/
public int getSize() {
int size = 0;
DexReader reader = dexFile.getDataBuffer().readerAt(startOffset);
// method_idx_diff
reader.readLargeUleb128();
// access_flags
reader.readSmallUleb128();
// code_off
reader.readSmallUleb128();
size += reader.getOffset() - startOffset;
DexBackedMethodImplementation impl = getImplementation();
if (impl != null) {
size += impl.getSize();
}
DexBackedMethodReference methodRef = new DexBackedMethodReference(dexFile, methodIndex);
size += methodRef.getSize();
return size;
}
Aggregations