Merge branch 'master' into v2.2_WIP

This commit is contained in:
Ben Gruver 2016-08-27 12:01:22 -07:00
commit 3735d4778f
75 changed files with 1376 additions and 1075 deletions

View File

@ -79,11 +79,20 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
return opcode.isVolatileFieldAccessor() || opcode == Opcode.THROW_VERIFICATION_ERROR; return opcode.isVolatileFieldAccessor() || opcode == Opcode.THROW_VERIFICATION_ERROR;
} }
private String writeInvalidItemIndex(InvalidItemIndex ex, int type, IndentingWriter writer)
throws IOException {
writer.write("#");
writer.write(ex.getMessage());
writer.write("\n");
return String.format("%s@%d", ReferenceType.toString(type), ex.getInvalidIndex());
}
@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; String referenceString = null;
String referenceString2 = null;
boolean commentOutInstruction = false; boolean commentOutInstruction = false;
@ -100,25 +109,19 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
if (instruction instanceof ReferenceInstruction) { if (instruction instanceof ReferenceInstruction) {
ReferenceInstruction referenceInstruction = (ReferenceInstruction)instruction; ReferenceInstruction referenceInstruction = (ReferenceInstruction)instruction;
try {
Reference reference = referenceInstruction.getReference();
String classContext = null; String classContext = null;
if (methodDef.classDef.options.implicitReferences) { if (methodDef.classDef.options.implicitReferences) {
classContext = methodDef.method.getDefiningClass(); classContext = methodDef.method.getDefiningClass();
} }
try {
Reference reference = referenceInstruction.getReference();
referenceString = ReferenceUtil.getReferenceString(reference, classContext); referenceString = ReferenceUtil.getReferenceString(reference, classContext);
assert referenceString != null; assert referenceString != null;
} catch (InvalidItemIndex ex) { } catch (InvalidItemIndex ex) {
writer.write("#");
writer.write(ex.getMessage());
writer.write("\n");
commentOutInstruction = true; commentOutInstruction = true;
referenceString = writeInvalidItemIndex(ex, referenceInstruction.getReferenceType(),
referenceString = String.format("%s@%d", writer);
ReferenceType.toString(referenceInstruction.getReferenceType()),
ex.getInvalidIndex());
} 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());
@ -126,6 +129,25 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
referenceString = "invalid_reference"; referenceString = "invalid_reference";
} }
if (instruction instanceof DualReferenceInstruction) {
DualReferenceInstruction dualReferenceInstruction =
(DualReferenceInstruction) instruction;
try {
Reference reference2 = dualReferenceInstruction.getReference2();
referenceString2 = ReferenceUtil.getReferenceString(reference2, classContext);
} catch (InvalidItemIndex ex) {
commentOutInstruction = true;
referenceString2 = writeInvalidItemIndex(ex,
dualReferenceInstruction.getReferenceType2(), writer);
} catch (ReferenceType.InvalidReferenceTypeException ex) {
writer.write("#invalid reference type: ");
writer.printSignedIntAsDec(ex.getReferenceType());
commentOutInstruction = true;
referenceString2 = "invalid_reference";
}
}
} }
if (instruction instanceof Instruction31t) { if (instruction instanceof Instruction31t) {
@ -308,11 +330,6 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
writer.write(", "); writer.write(", ");
writeThirdRegister(writer); writeThirdRegister(writer);
break; break;
case Format25x:
writeOpcode(writer);
writer.write(' ');
writeInvoke25xRegisters(writer); // vC, {vD, ...}
break;
case Format35c: case Format35c:
writeOpcode(writer); writeOpcode(writer);
writer.write(' '); writer.write(' ');
@ -355,6 +372,24 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
writer.write(", "); writer.write(", ");
writeVtableIndex(writer); writeVtableIndex(writer);
break; break;
case Format45cc:
writeOpcode(writer);
writer.write(' ');
writeInvokeRegisters(writer);
writer.write(", ");
writer.write(referenceString);
writer.write(", ");
writer.write(referenceString2);
break;
case Format4rcc:
writeOpcode(writer);
writer.write(' ');
writeInvokeRangeRegisters(writer);
writer.write(", ");
writer.write(referenceString);
writer.write(", ");
writer.write(referenceString2);
break;
default: default:
assert false; assert false;
return false; return false;
@ -438,43 +473,6 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
writer.write('}'); writer.write('}');
} }
protected void writeInvoke25xRegisters(IndentingWriter writer) throws IOException {
OneFixedFourParameterRegisterInstruction instruction =
(OneFixedFourParameterRegisterInstruction)this.instruction;
final int parameterRegCount = instruction.getParameterRegisterCount();
writeRegister(writer, instruction.getRegisterFixedC()); // fixed register always present
writer.write(", {");
switch (parameterRegCount) {
case 1:
writeRegister(writer, instruction.getRegisterParameterD());
break;
case 2:
writeRegister(writer, instruction.getRegisterParameterD());
writer.write(", ");
writeRegister(writer, instruction.getRegisterParameterE());
break;
case 3:
writeRegister(writer, instruction.getRegisterParameterD());
writer.write(", ");
writeRegister(writer, instruction.getRegisterParameterE());
writer.write(", ");
writeRegister(writer, instruction.getRegisterParameterF());
break;
case 4:
writeRegister(writer, instruction.getRegisterParameterD());
writer.write(", ");
writeRegister(writer, instruction.getRegisterParameterE());
writer.write(", ");
writeRegister(writer, instruction.getRegisterParameterF());
writer.write(", ");
writeRegister(writer, instruction.getRegisterParameterG());
break;
}
writer.write('}');
}
protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException { protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException {
RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction; RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction;

View File

@ -0,0 +1,54 @@
/*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.baksmali;
import org.junit.Test;
/**
* Test for a bug related to debug items that refer to a register that's outside the expected range for a method
*/
public class LargeLocalTest extends IdenticalRoundtripTest {
@Test
public void testLargeEndLocal() {
runTest("LargeEndLocal");
}
@Test
public void testLargeRestartLocal() {
runTest("LargeRestartLocal");
}
@Test
public void testLargeStartLocal() {
runTest("LargeStartLocal");
}
}

View File

@ -1,55 +0,0 @@
.class public LHelloWorldLambda;
#Ye olde hello world application (with lambdas!)
#To assemble and run this on a phone or emulator:
#
#java -jar smali.jar -o classes.dex HelloWorldLambda.smali HelloWorldFunctionalInterface.smali
#zip HelloWorld.zip classes.dex
#adb push HelloWorld.zip /data/local
#adb shell dalvikvm -cp /data/local/HelloWorld.zip HelloWorld
#
#if you get out of memory type errors when running smali.jar, try
#java -Xmx512m -jar smali.jar HelloWorldLambda.smali
#instead
.super Ljava/lang/Object;
.method public static doHelloWorld(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
.registers 6 # 4 parameters, 2 locals
liberate-variable v0, p0, "helloworld"
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
return-void
.end method
.method public static main([Ljava/lang/String;)V
.registers 9 # 1 parameter, 8 locals
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v1, "Hello World!"
const-string v2, "How" # vD
const-string v3, "are" # vE
const-string v4, "you" # vF
const-string v5, "doing?" # vG
capture-variable v1, "helloworld"
# TODO: do I need to pass the type of the lambda's functional interface here as a type id?
create-lambda v1, LHelloWorldLambda;->doHelloWorld(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
# Method descriptor is not required here, because only the single-abstract method is ever invoked.
invoke-lambda v1, {v2, v3, v4, v5}
box-lambda v6, v1
invoke-virtual {v6, v2, v3, v4, v5}, LHelloWorldFunctionalInterface;->applyFourStrings(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
# FIXME: should be \HelloWorldFunctionalInterface; instead of L...;
# TODO: do we really need the type descriptor here at all?
unbox-lambda v7, v6, LHelloWorldFunctionalInterface;
invoke-lambda v7, {v2, v3, v4, v5}
return-void
.end method

View File

@ -0,0 +1,11 @@
.class LLargeRestartLocal;
.super Ljava/lang/Object;
# virtual methods
.method public static main([Ljava/lang/String;)V
.registers 2
.end local p99
return-void
.end method

View File

@ -0,0 +1,11 @@
.class LLargeEndLocal;
.super Ljava/lang/Object;
# virtual methods
.method public static main([Ljava/lang/String;)V
.registers 2
.restart local p99
return-void
.end method

View File

@ -0,0 +1,11 @@
.class LLargeStartLocal;
.super Ljava/lang/Object;
# virtual methods
.method public static main([Ljava/lang/String;)V
.registers 2
.local p99, "blah":I
return-void
.end method

View File

@ -31,7 +31,7 @@
apply plugin: 'idea' apply plugin: 'idea'
version = '2.1.2' version = '2.1.3'
if (!('release' in gradle.startParameter.taskNames)) { if (!('release' in gradle.startParameter.taskNames)) {
def versionSuffix def versionSuffix
@ -104,8 +104,7 @@ subprojects {
antlr_runtime: 'org.antlr:antlr-runtime:3.5.2', antlr_runtime: 'org.antlr:antlr-runtime:3.5.2',
antlr: 'org.antlr:antlr:3.5.2', antlr: 'org.antlr:antlr:3.5.2',
stringtemplate: 'org.antlr:stringtemplate:3.2.1', stringtemplate: 'org.antlr:stringtemplate:3.2.1',
jflex: 'de.jflex:jflex:1.4.3', jflex_plugin: 'org.xbib.gradle.plugin:gradle-plugin-jflex:1.1.0',
jflex_plugin: 'co.tomlee.gradle.plugins:gradle-jflex-plugin:0.0.2',
proguard_gradle: 'net.sf.proguard:proguard-gradle:5.2.1', proguard_gradle: 'net.sf.proguard:proguard-gradle:5.2.1',
dx: 'com.google.android.tools:dx:1.7', dx: 'com.google.android.tools:dx:1.7',
gson: 'com.google.code.gson:gson:2.3.1', gson: 'com.google.code.gson:gson:2.3.1',
@ -197,5 +196,5 @@ buildscript {
} }
task wrapper(type: Wrapper) { task wrapper(type: Wrapper) {
gradleVersion = '2.11' gradleVersion = '2.14'
} }

View File

@ -51,7 +51,6 @@ public enum Format {
Format22t(4), Format22t(4),
Format22x(4), Format22x(4),
Format23x(4), Format23x(4),
Format25x(4),
Format30t(6), Format30t(6),
Format31c(6), Format31c(6),
Format31i(6), Format31i(6),
@ -63,6 +62,8 @@ public enum Format {
Format3rc(6), Format3rc(6),
Format3rmi(6), Format3rmi(6),
Format3rms(6), Format3rms(6),
Format45cc(8),
Format4rcc(8),
Format51l(10), Format51l(10),
ArrayPayload(-1, true), ArrayPayload(-1, true),
PackedSwitchPayload(-1, true), PackedSwitchPayload(-1, true),

View File

@ -294,8 +294,8 @@ public enum Opcode
INVOKE_VIRTUAL_QUICK(combine(allApis(0xf8), allArtVersions(0xe9)), "invoke-virtual-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_VIRTUAL_QUICK(combine(allApis(0xf8), allArtVersions(0xe9)), "invoke-virtual-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
INVOKE_VIRTUAL_QUICK_RANGE(combine(allApis(0xf9), allArtVersions(0xea)), "invoke-virtual-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_VIRTUAL_QUICK_RANGE(combine(allApis(0xf9), allArtVersions(0xea)), "invoke-virtual-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
INVOKE_SUPER_QUICK(allApis(0xfa), "invoke-super-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_SUPER_QUICK(lastApi(0xfa, 25), "invoke-super-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
INVOKE_SUPER_QUICK_RANGE(allApis(0xfb), "invoke-super-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_SUPER_QUICK_RANGE(lastApi(0xfb, 25), "invoke-super-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
IPUT_OBJECT_VOLATILE(firstApi(0xfc, 9), "iput-object-volatile", ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), IPUT_OBJECT_VOLATILE(firstApi(0xfc, 9), "iput-object-volatile", ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
SGET_OBJECT_VOLATILE(firstApi(0xfd, 9), "sget-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.STATIC_FIELD_ACCESSOR), SGET_OBJECT_VOLATILE(firstApi(0xfd, 9), "sget-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.STATIC_FIELD_ACCESSOR),
@ -305,15 +305,8 @@ public enum Opcode
SPARSE_SWITCH_PAYLOAD(0x200, "sparse-switch-payload", ReferenceType.NONE, Format.SparseSwitchPayload, 0), SPARSE_SWITCH_PAYLOAD(0x200, "sparse-switch-payload", ReferenceType.NONE, Format.SparseSwitchPayload, 0),
ARRAY_PAYLOAD(0x300, "array-payload", ReferenceType.NONE, Format.ArrayPayload, 0), ARRAY_PAYLOAD(0x300, "array-payload", ReferenceType.NONE, Format.ArrayPayload, 0),
// Reuse the deprecated f3-ff opcodes in Art: INVOKE_POLYMORPHIC(firstApi(0xfa, 26), "invoke-polymorphic", ReferenceType.METHOD, ReferenceType.METHOD_PROTO, Format.Format45cc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
INVOKE_LAMBDA(allArtVersions(0xf3),"invoke-lambda", ReferenceType.NONE, Format.Format25x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.EXPERIMENTAL), INVOKE_POLYMORPHIC_RANGE(firstApi(0xfb, 26), "invoke-polymorphic/range", ReferenceType.METHOD, ReferenceType.METHOD_PROTO, Format.Format4rcc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT);
// TODO: What about JUMBO support if the string ID is too large?
CAPTURE_VARIABLE(allArtVersions(0xf5), "capture-variable", ReferenceType.STRING, Format.Format21c, Opcode.EXPERIMENTAL),
CREATE_LAMBDA(allArtVersions(0xf6), "create-lambda", ReferenceType.METHOD, Format.Format21c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL),
// TODO: do we need a capture/liberate wide?
LIBERATE_VARIABLE(allArtVersions(0xf7), "liberate-variable", ReferenceType.STRING, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL),
BOX_LAMBDA(allArtVersions(0xf8), "box-lambda", ReferenceType.NONE, Format.Format22x, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL),
UNBOX_LAMBDA(allArtVersions(0xf9), "unbox-lambda", ReferenceType.TYPE, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL);
//if the instruction can throw an exception //if the instruction can throw an exception
public static final int CAN_THROW = 0x1; public static final int CAN_THROW = 0x1;
@ -359,6 +352,7 @@ public enum Opcode
public final int referenceType; public final int referenceType;
public final Format format; public final Format format;
public final int flags; public final int flags;
public final int referenceType2;
Opcode(int opcodeValue, String opcodeName, int referenceType, Format format) { Opcode(int opcodeValue, String opcodeName, int referenceType, Format format) {
this(opcodeValue, opcodeName, referenceType, format, 0); this(opcodeValue, opcodeName, referenceType, format, 0);
@ -369,6 +363,11 @@ public enum Opcode
} }
Opcode(List<VersionConstraint> versionConstraints, String opcodeName, int referenceType, Format format, int flags) { Opcode(List<VersionConstraint> versionConstraints, String opcodeName, int referenceType, Format format, int flags) {
this(versionConstraints, opcodeName, referenceType, -1, format, flags);
}
Opcode(List<VersionConstraint> versionConstraints, String opcodeName, int referenceType, int referenceType2,
Format format, int flags) {
ImmutableRangeMap.Builder<Integer, Short> apiToValueBuilder = ImmutableRangeMap.builder(); ImmutableRangeMap.Builder<Integer, Short> apiToValueBuilder = ImmutableRangeMap.builder();
ImmutableRangeMap.Builder<Integer, Short> artVersionToValueBuilder = ImmutableRangeMap.builder(); ImmutableRangeMap.Builder<Integer, Short> artVersionToValueBuilder = ImmutableRangeMap.builder();
@ -385,6 +384,7 @@ public enum Opcode
this.artVersionToValueMap = artVersionToValueBuilder.build(); this.artVersionToValueMap = artVersionToValueBuilder.build();
this.name = opcodeName; this.name = opcodeName;
this.referenceType = referenceType; this.referenceType = referenceType;
this.referenceType2 = referenceType2;
this.format = format; this.format = format;
this.flags = flags; this.flags = flags;
} }

View File

@ -39,7 +39,8 @@ public final class ReferenceType {
public static final int TYPE = 1; public static final int TYPE = 1;
public static final int FIELD = 2; public static final int FIELD = 2;
public static final int METHOD = 3; public static final int METHOD = 3;
public static final int NONE = 4; public static final int METHOD_PROTO = 4;
public static final int NONE = 5;
public static String toString(int referenceType) { public static String toString(int referenceType) {
switch (referenceType) { switch (referenceType) {
@ -51,6 +52,8 @@ public final class ReferenceType {
return "field"; return "field";
case METHOD: case METHOD:
return "method"; return "method";
case METHOD_PROTO:
return "method_proto";
default: default:
throw new InvalidReferenceTypeException(referenceType); throw new InvalidReferenceTypeException(referenceType);
} }
@ -65,6 +68,8 @@ public final class ReferenceType {
return FIELD; return FIELD;
} else if (reference instanceof MethodReference) { } else if (reference instanceof MethodReference) {
return METHOD; return METHOD;
} else if (reference instanceof MethodProtoReference) {
return METHOD_PROTO;
} else { } else {
throw new IllegalStateException("Invalid reference"); throw new IllegalStateException("Invalid reference");
} }
@ -76,7 +81,7 @@ public final class ReferenceType {
* @throws InvalidReferenceTypeException * @throws InvalidReferenceTypeException
*/ */
public static void validateReferenceType(int referenceType) { public static void validateReferenceType(int referenceType) {
if (referenceType < 0 || referenceType > 3) { if (referenceType < 0 || referenceType > 4) {
throw new InvalidReferenceTypeException(referenceType); throw new InvalidReferenceTypeException(referenceType);
} }
} }

View File

@ -34,10 +34,7 @@ package org.jf.dexlib2.analysis;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.google.common.collect.FluentIterable; import com.google.common.collect.*;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import org.jf.dexlib2.AccessFlags; import org.jf.dexlib2.AccessFlags;
import org.jf.dexlib2.analysis.util.TypeProtoUtils; import org.jf.dexlib2.analysis.util.TypeProtoUtils;
@ -71,6 +68,8 @@ public class ClassProto implements TypeProto {
protected boolean vtableFullyResolved = true; protected boolean vtableFullyResolved = true;
protected boolean interfacesFullyResolved = true; protected boolean interfacesFullyResolved = true;
protected Set<String> unresolvedInterfaces = null;
public ClassProto(@Nonnull ClassPath classPath, @Nonnull String type) { public ClassProto(@Nonnull ClassPath classPath, @Nonnull String type) {
if (type.charAt(0) != 'L') { if (type.charAt(0) != 'L') {
throw new ExceptionWithContext("Cannot construct ClassProto for non reference type: %s", type); throw new ExceptionWithContext("Cannot construct ClassProto for non reference type: %s", type);
@ -130,6 +129,7 @@ public class ClassProto implements TypeProto {
private final Supplier<LinkedHashMap<String, ClassDef>> interfacesSupplier = private final Supplier<LinkedHashMap<String, ClassDef>> interfacesSupplier =
Suppliers.memoize(new Supplier<LinkedHashMap<String, ClassDef>>() { Suppliers.memoize(new Supplier<LinkedHashMap<String, ClassDef>>() {
@Override public LinkedHashMap<String, ClassDef> get() { @Override public LinkedHashMap<String, ClassDef> get() {
Set<String> unresolvedInterfaces = new HashSet<String>(0);
LinkedHashMap<String, ClassDef> interfaces = Maps.newLinkedHashMap(); LinkedHashMap<String, ClassDef> interfaces = Maps.newLinkedHashMap();
try { try {
@ -141,6 +141,7 @@ public class ClassProto implements TypeProto {
interfaces.put(interfaceType, interfaceDef); interfaces.put(interfaceType, interfaceDef);
} catch (UnresolvedClassException ex) { } catch (UnresolvedClassException ex) {
interfaces.put(interfaceType, null); interfaces.put(interfaceType, null);
unresolvedInterfaces.add(interfaceType);
interfacesFullyResolved = false; interfacesFullyResolved = false;
} }
@ -151,11 +152,13 @@ public class ClassProto implements TypeProto {
} }
} }
if (!interfaceProto.interfacesFullyResolved) { if (!interfaceProto.interfacesFullyResolved) {
unresolvedInterfaces.addAll(interfaceProto.getUnresolvedInterfaces());
interfacesFullyResolved = false; interfacesFullyResolved = false;
} }
} }
} }
} catch (UnresolvedClassException ex) { } catch (UnresolvedClassException ex) {
unresolvedInterfaces.add(type);
interfacesFullyResolved = false; interfacesFullyResolved = false;
} }
@ -166,8 +169,8 @@ public class ClassProto implements TypeProto {
interfaces.put(getType(), null); interfaces.put(getType(), null);
} }
try {
String superclass = getSuperclass(); String superclass = getSuperclass();
try {
if (superclass != null) { if (superclass != null) {
ClassProto superclassProto = (ClassProto) classPath.getClass(superclass); ClassProto superclassProto = (ClassProto) classPath.getClass(superclass);
for (String superclassInterface: superclassProto.getInterfaces().keySet()) { for (String superclassInterface: superclassProto.getInterfaces().keySet()) {
@ -176,17 +179,31 @@ public class ClassProto implements TypeProto {
} }
} }
if (!superclassProto.interfacesFullyResolved) { if (!superclassProto.interfacesFullyResolved) {
unresolvedInterfaces.addAll(superclassProto.getUnresolvedInterfaces());
interfacesFullyResolved = false; interfacesFullyResolved = false;
} }
} }
} catch (UnresolvedClassException ex) { } catch (UnresolvedClassException ex) {
unresolvedInterfaces.add(superclass);
interfacesFullyResolved = false; interfacesFullyResolved = false;
} }
if (unresolvedInterfaces.size() > 0) {
ClassProto.this.unresolvedInterfaces = unresolvedInterfaces;
}
return interfaces; return interfaces;
} }
}); });
@Nonnull
protected Set<String> getUnresolvedInterfaces() {
if (unresolvedInterfaces == null) {
return ImmutableSet.of();
}
return unresolvedInterfaces;
}
/** /**
* Gets the interfaces directly implemented by this class, or the interfaces they transitively implement. * Gets the interfaces directly implemented by this class, or the interfaces they transitively implement.
* *
@ -201,7 +218,8 @@ public class ClassProto implements TypeProto {
FluentIterable.from(getInterfaces().values()).filter(Predicates.notNull()); FluentIterable.from(getInterfaces().values()).filter(Predicates.notNull());
if (!interfacesFullyResolved) { if (!interfacesFullyResolved) {
throw new UnresolvedClassException("Interfaces for class %s not fully resolved", getType()); throw new UnresolvedClassException("Interfaces for class %s not fully resolved: %s", getType(),
String.join(",", getUnresolvedInterfaces()));
} }
return directInterfaces; return directInterfaces;

View File

@ -0,0 +1,66 @@
/*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.base.reference;
import com.google.common.collect.Ordering;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.util.CharSequenceUtils;
import org.jf.util.CollectionUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class BaseMethodProtoReference implements MethodProtoReference {
@Override
public int hashCode() {
int hashCode = getReturnType().hashCode();
return hashCode*31 + getParameterTypes().hashCode();
}
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof MethodProtoReference) {
MethodProtoReference other = (MethodProtoReference)o;
return getReturnType().equals(other.getReturnType()) &&
CharSequenceUtils.listEquals(getParameterTypes(), other.getParameterTypes());
}
return false;
}
@Override
public int compareTo(@Nonnull MethodProtoReference o) {
int res = getReturnType().compareTo(o.getReturnType());
if (res != 0) return res;
return CollectionUtils.compareAsIterable(Ordering.usingToString(), getParameterTypes(), o.getParameterTypes());
}
}

View File

@ -615,9 +615,6 @@ public class MutableMethodImplementation implements MethodImplementation {
case Format23x: case Format23x:
setInstruction(location, newBuilderInstruction23x((Instruction23x) instruction)); setInstruction(location, newBuilderInstruction23x((Instruction23x) instruction));
return; return;
case Format25x:
setInstruction(location, newBuilderInstruction25x((Instruction25x) instruction));
return;
case Format30t: case Format30t:
setInstruction(location, newBuilderInstruction30t(location.codeAddress, setInstruction(location, newBuilderInstruction30t(location.codeAddress,
codeAddressToIndex, codeAddressToIndex,
@ -871,18 +868,6 @@ public class MutableMethodImplementation implements MethodImplementation {
instruction.getReference()); instruction.getReference());
} }
@Nonnull
private BuilderInstruction25x newBuilderInstruction25x(@Nonnull Instruction25x instruction) {
return new BuilderInstruction25x(
instruction.getOpcode(),
instruction.getParameterRegisterCount(),
instruction.getRegisterFixedC(),
instruction.getRegisterParameterD(),
instruction.getRegisterParameterE(),
instruction.getRegisterParameterF(),
instruction.getRegisterParameterG());
}
@Nonnull @Nonnull
private BuilderInstruction3rc newBuilderInstruction3rc(@Nonnull Instruction3rc instruction) { private BuilderInstruction3rc newBuilderInstruction3rc(@Nonnull Instruction3rc instruction) {
return new BuilderInstruction3rc( return new BuilderInstruction3rc(

View File

@ -1,82 +0,0 @@
/*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.builder.instruction;
import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.builder.BuilderInstruction;
import org.jf.dexlib2.iface.instruction.formats.Instruction25x;
import org.jf.dexlib2.util.Preconditions;
import javax.annotation.Nonnull;
public class BuilderInstruction25x extends BuilderInstruction implements Instruction25x {
public static final Format FORMAT = Format.Format25x;
protected final int parameterRegisterCount;
protected final int registerClosure;
protected final int registerD;
protected final int registerE;
protected final int registerF;
protected final int registerG;
public BuilderInstruction25x(@Nonnull Opcode opcode,
int parameterRegisterCount,
int registerClosure,
int registerD,
int registerE,
int registerF,
int registerG) {
super(opcode);
this.parameterRegisterCount =
Preconditions.check25xParameterRegisterCount(parameterRegisterCount);
this.registerClosure = Preconditions.checkNibbleRegister(registerClosure); //at least 1 reg
this.registerD = (parameterRegisterCount>0) ?
Preconditions.checkNibbleRegister(registerD) : 0;
this.registerE = (parameterRegisterCount>1) ?
Preconditions.checkNibbleRegister(registerE) : 0;
this.registerF = (parameterRegisterCount>2) ?
Preconditions.checkNibbleRegister(registerF) : 0;
this.registerG = (parameterRegisterCount>3) ?
Preconditions.checkNibbleRegister(registerG) : 0;
}
@Override public int getRegisterCount() { return parameterRegisterCount + 1; }
@Override public int getParameterRegisterCount() { return parameterRegisterCount; }
@Override public int getRegisterFixedC() { return registerClosure; }
@Override public int getRegisterParameterD() { return registerD; }
@Override public int getRegisterParameterE() { return registerE; }
@Override public int getRegisterParameterF() { return registerF; }
@Override public int getRegisterParameterG() { return registerG; }
@Override public Format getFormat() { return FORMAT; }
}

View File

@ -60,7 +60,7 @@ public class BuilderInstruction35c extends BuilderInstruction implements Instruc
int registerG, int registerG,
@Nonnull Reference reference) { @Nonnull Reference reference) {
super(opcode); super(opcode);
this.registerCount = Preconditions.check35cRegisterCount(registerCount); this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;

View File

@ -0,0 +1,87 @@
/*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.builder.instruction;
import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.builder.BuilderInstruction;
import org.jf.dexlib2.iface.instruction.formats.Instruction45cc;
import org.jf.dexlib2.iface.reference.Reference;
import org.jf.dexlib2.util.Preconditions;
import javax.annotation.Nonnull;
public class BuilderInstruction45cc extends BuilderInstruction implements Instruction45cc {
public static final Format FORMAT = Format.Format45cc;
protected final int registerCount;
protected final int registerC;
protected final int registerD;
protected final int registerE;
protected final int registerF;
protected final int registerG;
@Nonnull protected final Reference reference;
@Nonnull protected final Reference reference2;
public BuilderInstruction45cc(@Nonnull Opcode opcode,
int registerCount,
int registerC,
int registerD,
int registerE,
int registerF,
int registerG,
@Nonnull Reference reference,
@Nonnull Reference reference2) {
super(opcode);
this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
this.registerF = (registerCount>3) ? Preconditions.checkNibbleRegister(registerF) : 0;
this.registerG = (registerCount>4) ? Preconditions.checkNibbleRegister(registerG) : 0;
this.reference = reference;
this.reference2 = reference2;
}
@Override public int getRegisterCount() { return registerCount; }
@Override public int getRegisterC() { return registerC; }
@Override public int getRegisterD() { return registerD; }
@Override public int getRegisterE() { return registerE; }
@Override public int getRegisterF() { return registerF; }
@Override public int getRegisterG() { return registerG; }
@Nonnull @Override public Reference getReference() { return reference; }
@Override public int getReferenceType() { return opcode.referenceType; }
@Nonnull @Override public Reference getReference2() { return reference2; }
@Override public int getReferenceType2() { return opcode.referenceType2; }
@Override public Format getFormat() { return FORMAT; }
}

View File

@ -0,0 +1,72 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.builder.instruction;
import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.builder.BuilderInstruction;
import org.jf.dexlib2.iface.instruction.formats.Instruction4rcc;
import org.jf.dexlib2.iface.reference.Reference;
import org.jf.dexlib2.util.Preconditions;
import javax.annotation.Nonnull;
public class BuilderInstruction4rcc extends BuilderInstruction implements Instruction4rcc {
public static final Format FORMAT = Format.Format4rcc;
protected final int startRegister;
protected final int registerCount;
@Nonnull protected final Reference reference;
@Nonnull protected final Reference reference2;
public BuilderInstruction4rcc(@Nonnull Opcode opcode,
int startRegister,
int registerCount,
@Nonnull Reference reference,
@Nonnull Reference reference2) {
super(opcode);
this.startRegister = Preconditions.checkShortRegister(startRegister);
this.registerCount = Preconditions.checkRegisterRangeCount(registerCount);
this.reference = reference;
this.reference2 = reference2;
}
@Override public int getStartRegister() { return startRegister; }
@Override public int getRegisterCount() { return registerCount; }
@Nonnull @Override public Reference getReference() { return reference; }
@Override public int getReferenceType() { return opcode.referenceType; }
@Nonnull @Override public Reference getReference2() { return reference2; }
@Override public int getReferenceType2() { return opcode.referenceType2; }
@Override public Format getFormat() { return FORMAT; }
}

View File

@ -115,8 +115,6 @@ public abstract class DexBackedInstruction implements Instruction {
return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset); return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset);
case Format23x: case Format23x:
return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset); return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset);
case Format25x:
return new DexBackedInstruction25x(dexFile, opcode, instructionStartOffset);
case Format30t: case Format30t:
return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset); return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset);
case Format31c: case Format31c:
@ -139,6 +137,10 @@ public abstract class DexBackedInstruction implements Instruction {
return new DexBackedInstruction3rmi(dexFile, opcode, instructionStartOffset); return new DexBackedInstruction3rmi(dexFile, opcode, instructionStartOffset);
case Format3rms: case Format3rms:
return new DexBackedInstruction3rms(dexFile, opcode, instructionStartOffset); return new DexBackedInstruction3rms(dexFile, opcode, instructionStartOffset);
case Format45cc:
return new DexBackedInstruction45cc(dexFile, opcode, instructionStartOffset);
case Format4rcc:
return new DexBackedInstruction4rcc(dexFile, opcode, instructionStartOffset);
case Format51l: case Format51l:
return new DexBackedInstruction51l(dexFile, opcode, instructionStartOffset); return new DexBackedInstruction51l(dexFile, opcode, instructionStartOffset);
case PackedSwitchPayload: case PackedSwitchPayload:

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015, Google Inc. * Copyright 2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -33,51 +33,69 @@ package org.jf.dexlib2.dexbacked.instruction;
import org.jf.dexlib2.Opcode; import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.dexbacked.DexBackedDexFile; import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.iface.instruction.formats.Instruction25x; import org.jf.dexlib2.dexbacked.reference.DexBackedReference;
import org.jf.dexlib2.iface.instruction.formats.Instruction45cc;
import org.jf.dexlib2.iface.reference.Reference;
import org.jf.util.NibbleUtils; import org.jf.util.NibbleUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class DexBackedInstruction25x extends DexBackedInstruction implements Instruction25x { public class DexBackedInstruction45cc extends DexBackedInstruction implements Instruction45cc {
public DexBackedInstruction25x(@Nonnull DexBackedDexFile dexFile, public DexBackedInstruction45cc(@Nonnull DexBackedDexFile dexFile,
@Nonnull Opcode opcode, @Nonnull Opcode opcode,
int instructionStart) { int instructionStart) {
super(dexFile, opcode, instructionStart); super(dexFile, opcode, instructionStart);
} }
@Override @Override public int getRegisterCount() {
public int getRegisterCount() {
return getParameterRegisterCount() + 1;
}
@Override
public int getParameterRegisterCount() {
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1));
} }
@Override @Override
public int getRegisterFixedC() { public int getRegisterC() {
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 2)); return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 4));
} }
@Override @Override
public int getRegisterParameterD() { public int getRegisterD() {
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 2)); return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 4));
} }
@Override @Override
public int getRegisterParameterE() { public int getRegisterE() {
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 3)); return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 5));
} }
@Override @Override
public int getRegisterParameterF() { public int getRegisterF() {
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 3)); return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 5));
} }
@Override @Override
public int getRegisterParameterG() { public int getRegisterG() {
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 1));
} }
@Nonnull
@Override
public Reference getReference() {
return DexBackedReference.makeReference(dexFile, opcode.referenceType,
dexFile.readUshort(instructionStart + 2));
}
@Override
public int getReferenceType() {
return opcode.referenceType;
}
@Override
public Reference getReference2() {
return DexBackedReference.makeReference(dexFile, opcode.referenceType2,
dexFile.readUshort(instructionStart + 3));
}
@Override
public int getReferenceType2() {
return opcode.referenceType2;
}
} }

View File

@ -0,0 +1,80 @@
/*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.dexbacked.instruction;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.dexbacked.reference.DexBackedReference;
import org.jf.dexlib2.iface.instruction.formats.Instruction4rcc;
import org.jf.dexlib2.iface.reference.Reference;
import javax.annotation.Nonnull;
public class DexBackedInstruction4rcc extends DexBackedInstruction implements Instruction4rcc {
public DexBackedInstruction4rcc(@Nonnull DexBackedDexFile dexFile,
@Nonnull Opcode opcode,
int instructionStart) {
super(dexFile, opcode, instructionStart);
}
@Override public int getRegisterCount() {
return dexFile.readUbyte(instructionStart + 1);
}
@Override
public int getStartRegister() {
return dexFile.readUshort(instructionStart + 4);
}
@Nonnull
@Override
public Reference getReference() {
return DexBackedReference.makeReference(dexFile, opcode.referenceType,
dexFile.readUshort(instructionStart + 2));
}
@Override
public int getReferenceType() {
return opcode.referenceType;
}
@Override
public Reference getReference2() {
return DexBackedReference.makeReference(dexFile, opcode.referenceType2,
dexFile.readUshort(instructionStart + 3));
}
@Override
public int getReferenceType2() {
return opcode.referenceType2;
}
}

View File

@ -129,9 +129,6 @@ public class CodeItem {
case Format10x: case Format10x:
annotateInstruction10x(out, instruction); annotateInstruction10x(out, instruction);
break; break;
case Format25x:
annotateInstruction25x(out, (Instruction25x) instruction);
break;
case Format35c: case Format35c:
annotateInstruction35c(out, (Instruction35c)instruction); annotateInstruction35c(out, (Instruction35c)instruction);
break; break;
@ -285,30 +282,6 @@ public class CodeItem {
instruction.getOpcode().name, Joiner.on(", ").join(args), reference)); instruction.getOpcode().name, Joiner.on(", ").join(args), reference));
} }
private void annotateInstruction25x(@Nonnull AnnotatedBytes out,
@Nonnull Instruction25x instruction) {
List<String> args = Lists.newArrayList();
int registerCount = instruction.getRegisterCount(); //at least 1.
if (registerCount == 2) {
args.add(formatRegister(instruction.getRegisterParameterD()));
} else if (registerCount == 3) {
args.add(formatRegister(instruction.getRegisterParameterD()));
args.add(formatRegister(instruction.getRegisterParameterE()));
} else if (registerCount == 4) {
args.add(formatRegister(instruction.getRegisterParameterD()));
args.add(formatRegister(instruction.getRegisterParameterE()));
args.add(formatRegister(instruction.getRegisterParameterF()));
} else if (registerCount == 5) {
args.add(formatRegister(instruction.getRegisterParameterD()));
args.add(formatRegister(instruction.getRegisterParameterE()));
args.add(formatRegister(instruction.getRegisterParameterF()));
args.add(formatRegister(instruction.getRegisterParameterG()));
}
out.annotate(6, String.format("%s %s, {%s}",
instruction.getOpcode().name, instruction.getRegisterFixedC(), Joiner.on(", ").join(args)));
}
private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) { private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) {
int startRegister = instruction.getStartRegister(); int startRegister = instruction.getStartRegister();
int endRegister = startRegister + instruction.getRegisterCount() - 1; int endRegister = startRegister + instruction.getRegisterCount() - 1;

View File

@ -0,0 +1,77 @@
/*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.dexbacked.reference;
import com.google.common.collect.ImmutableList;
import org.jf.dexlib2.base.reference.BaseMethodProtoReference;
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
import org.jf.dexlib2.dexbacked.raw.ProtoIdItem;
import org.jf.dexlib2.dexbacked.raw.TypeListItem;
import org.jf.dexlib2.dexbacked.util.FixedSizeList;
import java.util.List;
import javax.annotation.Nonnull;
public class DexBackedMethodProtoReference extends BaseMethodProtoReference {
@Nonnull public final DexBackedDexFile dexFile;
private final int protoIdItemOffset;
public DexBackedMethodProtoReference(@Nonnull DexBackedDexFile dexFile, int protoIndex) {
this.dexFile = dexFile;
this.protoIdItemOffset = dexFile.getProtoIdItemOffset(protoIndex);
}
@Nonnull
@Override
public List<String> getParameterTypes() {
final int parametersOffset = dexFile.readSmallUint(protoIdItemOffset + ProtoIdItem.PARAMETERS_OFFSET);
if (parametersOffset > 0) {
final int parameterCount = dexFile.readSmallUint(parametersOffset + TypeListItem.SIZE_OFFSET);
final int paramListStart = parametersOffset + TypeListItem.LIST_OFFSET;
return new FixedSizeList<String>() {
@Nonnull
@Override
public String readItem(final int index) {
return dexFile.getType(dexFile.readUshort(paramListStart + 2*index));
}
@Override public int size() { return parameterCount; }
};
}
return ImmutableList.of();
}
@Nonnull
@Override
public String getReturnType() {
return dexFile.getType(dexFile.readSmallUint(protoIdItemOffset + ProtoIdItem.RETURN_TYPE_OFFSET));
}
}

View File

@ -49,6 +49,8 @@ public abstract class DexBackedReference {
return new DexBackedMethodReference(dexFile, referenceIndex); return new DexBackedMethodReference(dexFile, referenceIndex);
case ReferenceType.FIELD: case ReferenceType.FIELD:
return new DexBackedFieldReference(dexFile, referenceIndex); return new DexBackedFieldReference(dexFile, referenceIndex);
case ReferenceType.METHOD_PROTO:
return new DexBackedMethodProtoReference(dexFile, referenceIndex);
default: default:
throw new ExceptionWithContext("Invalid reference type: %d", referenceType); throw new ExceptionWithContext("Invalid reference type: %d", referenceType);
} }

View File

@ -182,7 +182,9 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1); String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1);
ImmutableStartLocal startLocal = ImmutableStartLocal startLocal =
new ImmutableStartLocal(codeAddress, register, name, type, null); new ImmutableStartLocal(codeAddress, register, name, type, null);
if (register >= 0 && register < locals.length) {
locals[register] = startLocal; locals[register] = startLocal;
}
return startLocal; return startLocal;
} }
case DebugItemType.START_LOCAL_EXTENDED: { case DebugItemType.START_LOCAL_EXTENDED: {
@ -192,13 +194,23 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
String signature = dexFile.getOptionalString(reader.readSmallUleb128() - 1); String signature = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
ImmutableStartLocal startLocal = ImmutableStartLocal startLocal =
new ImmutableStartLocal(codeAddress, register, name, type, signature); new ImmutableStartLocal(codeAddress, register, name, type, signature);
if (register >= 0 && register < locals.length) {
locals[register] = startLocal; locals[register] = startLocal;
}
return startLocal; return startLocal;
} }
case DebugItemType.END_LOCAL: { case DebugItemType.END_LOCAL: {
int register = reader.readSmallUleb128(); int register = reader.readSmallUleb128();
LocalInfo localInfo = locals[register];
boolean replaceLocalInTable = true; boolean replaceLocalInTable = true;
LocalInfo localInfo;
if (register >= 0 && register < locals.length) {
localInfo = locals[register];
} else {
localInfo = EMPTY_LOCAL_INFO;
replaceLocalInTable = false;
}
if (localInfo instanceof EndLocal) { if (localInfo instanceof EndLocal) {
localInfo = EMPTY_LOCAL_INFO; localInfo = EMPTY_LOCAL_INFO;
// don't replace the local info in locals. The new EndLocal won't have any info at all, // don't replace the local info in locals. The new EndLocal won't have any info at all,
@ -216,11 +228,18 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
} }
case DebugItemType.RESTART_LOCAL: { case DebugItemType.RESTART_LOCAL: {
int register = reader.readSmallUleb128(); int register = reader.readSmallUleb128();
LocalInfo localInfo = locals[register]; LocalInfo localInfo;
if (register >= 0 && register < locals.length) {
localInfo = locals[register];
} else {
localInfo = EMPTY_LOCAL_INFO;
}
ImmutableRestartLocal restartLocal = ImmutableRestartLocal restartLocal =
new ImmutableRestartLocal(codeAddress, register, localInfo.getName(), new ImmutableRestartLocal(codeAddress, register, localInfo.getName(),
localInfo.getType(), localInfo.getSignature()); localInfo.getType(), localInfo.getSignature());
if (register >= 0 && register < locals.length) {
locals[register] = restartLocal; locals[register] = restartLocal;
}
return restartLocal; return restartLocal;
} }
case DebugItemType.PROLOGUE_END: { case DebugItemType.PROLOGUE_END: {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015, Google Inc. * Copyright 2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,17 +31,11 @@
package org.jf.dexlib2.iface.instruction; package org.jf.dexlib2.iface.instruction;
public interface OneFixedFourParameterRegisterInstruction extends VariableRegisterInstruction { import org.jf.dexlib2.iface.reference.Reference;
int getRegisterFixedC();
int getRegisterParameterD();
int getRegisterParameterE();
int getRegisterParameterF();
int getRegisterParameterG();
/** Returns the count of just the parameter register counts; in range of [0, 4] */ import javax.annotation.Nonnull;
int getParameterRegisterCount();
/** Includes the total sum of both fixed and parameter register counts; at least 1 */ public interface DualReferenceInstruction extends ReferenceInstruction {
@Override @Nonnull Reference getReference2();
int getRegisterCount(); int getReferenceType2();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015, Google Inc. * Copyright 2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,7 +31,8 @@
package org.jf.dexlib2.iface.instruction.formats; package org.jf.dexlib2.iface.instruction.formats;
import org.jf.dexlib2.iface.instruction.OneFixedFourParameterRegisterInstruction; import org.jf.dexlib2.iface.instruction.DualReferenceInstruction;
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction;
public interface Instruction25x extends OneFixedFourParameterRegisterInstruction { public interface Instruction45cc extends FiveRegisterInstruction, DualReferenceInstruction {
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015, Google Inc. * Copyright 2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -29,21 +29,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.jf.baksmali; package org.jf.dexlib2.iface.instruction.formats;
import org.junit.Test; import org.jf.dexlib2.iface.instruction.DualReferenceInstruction;
import org.jf.dexlib2.iface.instruction.RegisterRangeInstruction;
public class LambdaTest extends IdenticalRoundtripTest { public interface Instruction4rcc extends RegisterRangeInstruction, DualReferenceInstruction {
private BaksmaliOptions createOptions() {
BaksmaliOptions options = new BaksmaliOptions();
options.apiLevel = 23; // since we need at least level 23 for lambda opcodes
options.experimentalOpcodes = true; // since these opcodes aren't implemented in runtime yet);
return options;
}
@Test
public void testHelloWorldLambda() {
runTest("HelloWorldLambda", createOptions());
}
} }

View File

@ -0,0 +1,96 @@
/*
* Copyright 20116, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.iface.reference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
/**
* This class represents a reference to a method prototype.
*/
public interface MethodProtoReference extends Reference, Comparable<MethodProtoReference> {
/**
* Gets a list of the types of the parameters of this method prototype.
*
* @return A list of the parameter types of this method prototype, as strings.
*/
@Nonnull List<? extends CharSequence> getParameterTypes();
/**
* Gets the return type of the referenced method prototype.
*
* @return The return type of the referenced method prototype.
*/
@Nonnull String getReturnType();
/**
* Returns a hashcode for this MethodProtoReference.
*
* This hashCode is defined to be the following:
*
* <pre>
* {@code
* int hashCode = getReturnType().hashCode();
* hashCode = hashCode*31 + CharSequenceUtils.listHashCode(getParameters());
* }</pre>
*
* @return The hash code value for this ProtoReference
*/
@Override int hashCode();
/**
* Compares this MethodTypeReference to another MethodProtoReference for equality.
*
* This MethodTypeReference is equal to another MethodProtoReference if all of it's "fields" are equal. That is, if
* the return values of getReturnType() and getParameterTypes() are all equal.
*
* Equality for getParameters() should be tested by comparing the string representation of each element. I.e.
* CharSequenceUtils.listEquals(this.getParameterTypes(), other.getParameterTypes())
*
* @param o The object to be compared for equality with this MethodProtoReference
* @return true if the specified object is equal to this MethodProtoReference
*/
@Override boolean equals(@Nullable Object o);
/**
* Compare this MethodTypeReference to another MethodProtoReference.
*
* The comparison is based on the comparison of the return values of getReturnType() and getParameters(),
* in that order. getParameters() should be compared using the semantics of
* org.jf.util.CollectionUtils.compareAsList()
*
* @param o The MethodReference to compare with this MethodProtoReference
* @return An integer representing the result of the comparison
*/
@Override int compareTo(@Nonnull MethodProtoReference o);
}

View File

@ -97,8 +97,6 @@ public abstract class ImmutableInstruction implements Instruction {
return ImmutableInstruction22x.of((Instruction22x)instruction); return ImmutableInstruction22x.of((Instruction22x)instruction);
case Format23x: case Format23x:
return ImmutableInstruction23x.of((Instruction23x)instruction); return ImmutableInstruction23x.of((Instruction23x)instruction);
case Format25x:
return ImmutableInstruction25x.of((Instruction25x) instruction);
case Format30t: case Format30t:
return ImmutableInstruction30t.of((Instruction30t)instruction); return ImmutableInstruction30t.of((Instruction30t)instruction);
case Format31c: case Format31c:

View File

@ -1,97 +0,0 @@
/*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.immutable.instruction;
import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.instruction.formats.Instruction25x;
import org.jf.dexlib2.util.Preconditions;
import javax.annotation.Nonnull;
public class ImmutableInstruction25x extends ImmutableInstruction implements Instruction25x {
public static final Format FORMAT = Format.Format25x;
protected final int parameterRegisterCount;
protected final int registerClosure;
protected final int registerD;
protected final int registerE;
protected final int registerF;
protected final int registerG;
public ImmutableInstruction25x(@Nonnull Opcode opcode,
int parameterRegisterCount,
int registerClosure,
int registerD,
int registerE,
int registerF,
int registerG) {
super(opcode);
this.parameterRegisterCount =
Preconditions.check25xParameterRegisterCount(parameterRegisterCount);
this.registerClosure = Preconditions.checkNibbleRegister(registerClosure);
this.registerD = (parameterRegisterCount>0) ?
Preconditions.checkNibbleRegister(registerD) : 0;
this.registerE = (parameterRegisterCount>1) ?
Preconditions.checkNibbleRegister(registerE) : 0;
this.registerF = (parameterRegisterCount>2) ?
Preconditions.checkNibbleRegister(registerF) : 0;
this.registerG = (parameterRegisterCount>3) ?
Preconditions.checkNibbleRegister(registerG) : 0;
}
public static ImmutableInstruction25x of(Instruction25x instruction) {
if (instruction instanceof ImmutableInstruction25x) {
return (ImmutableInstruction25x)instruction;
}
return new ImmutableInstruction25x(
instruction.getOpcode(),
instruction.getRegisterCount(),
instruction.getRegisterFixedC(),
instruction.getRegisterParameterD(),
instruction.getRegisterParameterE(),
instruction.getRegisterParameterF(),
instruction.getRegisterParameterG());
}
@Override public int getParameterRegisterCount() { return parameterRegisterCount; }
@Override public int getRegisterCount() { return parameterRegisterCount + 1; }
@Override public int getRegisterFixedC() { return registerClosure; }
@Override public int getRegisterParameterD() { return registerD; }
@Override public int getRegisterParameterE() { return registerE; }
@Override public int getRegisterParameterF() { return registerF; }
@Override public int getRegisterParameterG() { return registerG; }
@Override public Format getFormat() { return FORMAT; }
}

View File

@ -61,7 +61,7 @@ public class ImmutableInstruction35c extends ImmutableInstruction implements Ins
int registerG, int registerG,
@Nonnull Reference reference) { @Nonnull Reference reference) {
super(opcode); super(opcode);
this.registerCount = Preconditions.check35cRegisterCount(registerCount); this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;

View File

@ -58,7 +58,7 @@ public class ImmutableInstruction35mi extends ImmutableInstruction implements In
int registerG, int registerG,
int inlineIndex) { int inlineIndex) {
super(opcode); super(opcode);
this.registerCount = Preconditions.check35cRegisterCount(registerCount); this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;

View File

@ -58,7 +58,7 @@ public class ImmutableInstruction35ms extends ImmutableInstruction implements In
int registerG, int registerG,
int vtableIndex) { int vtableIndex) {
super(opcode); super(opcode);
this.registerCount = Preconditions.check35cRegisterCount(registerCount); this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;

View File

@ -0,0 +1,72 @@
/*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.immutable.reference;
import com.google.common.collect.ImmutableList;
import org.jf.dexlib2.base.reference.BaseMethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.immutable.util.CharSequenceConverter;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class ImmutableMethodProtoReference extends BaseMethodProtoReference implements ImmutableReference {
@Nonnull protected final ImmutableList<String> parameters;
@Nonnull protected final String returnType;
public ImmutableMethodProtoReference(@Nullable Iterable<? extends CharSequence> parameters,
@Nonnull String returnType) {
this.parameters = CharSequenceConverter.immutableStringList(parameters);
this.returnType = returnType;
}
@Nonnull public static ImmutableMethodProtoReference of(@Nonnull MethodProtoReference methodProtoReference) {
if (methodProtoReference instanceof ImmutableMethodProtoReference) {
return (ImmutableMethodProtoReference) methodProtoReference;
}
return new ImmutableMethodProtoReference(
methodProtoReference.getParameterTypes(),
methodProtoReference.getReturnType());
}
@Override
public List<? extends CharSequence> getParameterTypes() {
return parameters;
}
@Override
public String getReturnType() {
return returnType;
}
}

View File

@ -52,6 +52,9 @@ public class ImmutableReferenceFactory {
if (reference instanceof MethodReference) { if (reference instanceof MethodReference) {
return ImmutableMethodReference.of((MethodReference)reference); return ImmutableMethodReference.of((MethodReference)reference);
} }
if (reference instanceof MethodProtoReference) {
return ImmutableMethodProtoReference.of((MethodProtoReference) reference);
}
throw new ExceptionWithContext("Invalid reference type"); throw new ExceptionWithContext("Invalid reference type");
} }
@ -66,6 +69,8 @@ public class ImmutableReferenceFactory {
return ImmutableFieldReference.of((FieldReference)reference); return ImmutableFieldReference.of((FieldReference)reference);
case ReferenceType.METHOD: case ReferenceType.METHOD:
return ImmutableMethodReference.of((MethodReference)reference); return ImmutableMethodReference.of((MethodReference)reference);
case ReferenceType.METHOD_PROTO:
return ImmutableMethodProtoReference.of((MethodProtoReference)reference);
} }
throw new ExceptionWithContext("Invalid reference type: %d", referenceType); throw new ExceptionWithContext("Invalid reference type: %d", referenceType);
} }

View File

@ -125,7 +125,7 @@ public class Preconditions {
return offset; return offset;
} }
public static int check35cRegisterCount(int registerCount) { public static int check35cAnd45ccRegisterCount(int registerCount) {
if (registerCount < 0 || registerCount > 5) { if (registerCount < 0 || registerCount > 5) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
String.format("Invalid register count: %d. Must be between 0 and 5, inclusive.", registerCount)); String.format("Invalid register count: %d. Must be between 0 and 5, inclusive.", registerCount));
@ -133,15 +133,6 @@ public class Preconditions {
return registerCount; return registerCount;
} }
public static int check25xParameterRegisterCount(int registerCount) {
if (registerCount < 0 || registerCount > 4) {
throw new IllegalArgumentException(
String.format("Invalid parameter register count: %d. " +
"Must be between 0 and 4, inclusive.", registerCount));
}
return registerCount;
}
public static int checkRegisterRangeCount(int registerCount) { public static int checkRegisterRangeCount(int registerCount) {
if ((registerCount & 0xFFFFFF00) != 0) { if ((registerCount & 0xFFFFFF00) != 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException(

View File

@ -60,6 +60,17 @@ public final class ReferenceUtil {
return sb.toString(); return sb.toString();
} }
public static String getMethodProtoDescriptor(MethodProtoReference methodProtoReference) {
StringBuilder sb = new StringBuilder();
sb.append('(');
for (CharSequence paramType : methodProtoReference.getParameterTypes()) {
sb.append(paramType);
}
sb.append(')');
sb.append(methodProtoReference.getReturnType());
return sb.toString();
}
public static void writeMethodDescriptor(Writer writer, MethodReference methodReference) throws IOException { public static void writeMethodDescriptor(Writer writer, MethodReference methodReference) throws IOException {
writeMethodDescriptor(writer, methodReference, false); writeMethodDescriptor(writer, methodReference, false);
} }
@ -134,12 +145,16 @@ public final class ReferenceUtil {
if (reference instanceof FieldReference) { if (reference instanceof FieldReference) {
FieldReference fieldReference = (FieldReference)reference; FieldReference fieldReference = (FieldReference)reference;
boolean useImplicitReference = fieldReference.getDefiningClass().equals(containingClass); boolean useImplicitReference = fieldReference.getDefiningClass().equals(containingClass);
return getFieldDescriptor((FieldReference)reference, useImplicitReference); return getFieldDescriptor(fieldReference, useImplicitReference);
} }
if (reference instanceof MethodReference) { if (reference instanceof MethodReference) {
MethodReference methodReference = (MethodReference)reference; MethodReference methodReference = (MethodReference)reference;
boolean useImplicitReference = methodReference.getDefiningClass().equals(containingClass); boolean useImplicitReference = methodReference.getDefiningClass().equals(containingClass);
return getMethodDescriptor((MethodReference)reference, useImplicitReference); return getMethodDescriptor(methodReference, useImplicitReference);
}
if (reference instanceof MethodProtoReference) {
MethodProtoReference methodProtoReference = (MethodProtoReference)reference;
return getMethodProtoDescriptor(methodProtoReference);
} }
return null; return null;
} }

View File

@ -54,6 +54,7 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction;
import org.jf.dexlib2.iface.instruction.ReferenceInstruction; import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
import org.jf.dexlib2.iface.instruction.formats.*; import org.jf.dexlib2.iface.instruction.formats.*;
import org.jf.dexlib2.iface.reference.FieldReference; import org.jf.dexlib2.iface.reference.FieldReference;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodReference; import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.iface.reference.StringReference; import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference; import org.jf.dexlib2.iface.reference.TypeReference;
@ -84,7 +85,7 @@ import java.util.zip.Adler32;
public abstract class DexWriter< public abstract class DexWriter<
StringKey extends CharSequence, StringRef extends StringReference, TypeKey extends CharSequence, StringKey extends CharSequence, StringRef extends StringReference, TypeKey extends CharSequence,
TypeRef extends TypeReference, ProtoKey extends Comparable<ProtoKey>, TypeRef extends TypeReference, ProtoRefKey extends MethodProtoReference,
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
ClassKey extends Comparable<? super ClassKey>, ClassKey extends Comparable<? super ClassKey>,
AnnotationKey extends Annotation, AnnotationSetKey, AnnotationKey extends Annotation, AnnotationSetKey,
@ -125,9 +126,9 @@ public abstract class DexWriter<
protected final StringSection<StringKey, StringRef> stringSection; protected final StringSection<StringKey, StringRef> stringSection;
protected final TypeSection<StringKey, TypeKey, TypeRef> typeSection; protected final TypeSection<StringKey, TypeKey, TypeRef> typeSection;
protected final ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection; protected final ProtoSection<StringKey, TypeKey, ProtoRefKey, TypeListKey> protoSection;
protected final FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection; protected final FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection;
protected final MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey, MethodKey> methodSection; protected final MethodSection<StringKey, TypeKey, ProtoRefKey, MethodRefKey, MethodKey> methodSection;
protected final ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey, protected final ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
EncodedValue> classSection; EncodedValue> classSection;
@ -138,9 +139,9 @@ public abstract class DexWriter<
protected DexWriter(Opcodes opcodes, protected DexWriter(Opcodes opcodes,
StringSection<StringKey, StringRef> stringSection, StringSection<StringKey, StringRef> stringSection,
TypeSection<StringKey, TypeKey, TypeRef> typeSection, TypeSection<StringKey, TypeKey, TypeRef> typeSection,
ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection, ProtoSection<StringKey, TypeKey, ProtoRefKey, TypeListKey> protoSection,
FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection, FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection,
MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey, MethodKey> methodSection, MethodSection<StringKey, TypeKey, ProtoRefKey, MethodRefKey, MethodKey> methodSection,
ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey, ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
EncodedValue> classSection, EncodedValue> classSection,
TypeListSection<TypeKey, TypeListKey> typeListSection, TypeListSection<TypeKey, TypeListKey> typeListSection,
@ -347,12 +348,12 @@ public abstract class DexWriter<
protoSectionOffset = writer.getPosition(); protoSectionOffset = writer.getPosition();
int index = 0; int index = 0;
List<Map.Entry<? extends ProtoKey, Integer>> protoEntries = Lists.newArrayList(protoSection.getItems()); List<Map.Entry<? extends ProtoRefKey, Integer>> protoEntries = Lists.newArrayList(protoSection.getItems());
Collections.sort(protoEntries, DexWriter.<ProtoKey>comparableKeyComparator()); Collections.sort(protoEntries, DexWriter.<ProtoRefKey>comparableKeyComparator());
for (Map.Entry<? extends ProtoKey, Integer> entry: protoEntries) { for (Map.Entry<? extends ProtoRefKey, Integer> entry: protoEntries) {
entry.setValue(index++); entry.setValue(index++);
ProtoKey key = entry.getKey(); ProtoRefKey key = entry.getKey();
writer.writeInt(stringSection.getItemIndex(protoSection.getShorty(key))); writer.writeInt(stringSection.getItemIndex(protoSection.getShorty(key)));
writer.writeInt(typeSection.getItemIndex(protoSection.getReturnType(key))); writer.writeInt(typeSection.getItemIndex(protoSection.getReturnType(key)));
writer.writeInt(typeListSection.getNullableItemOffset(protoSection.getParameters(key))); writer.writeInt(typeListSection.getNullableItemOffset(protoSection.getParameters(key)));
@ -946,7 +947,7 @@ public abstract class DexWriter<
InstructionWriter instructionWriter = InstructionWriter instructionWriter =
InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection, InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection,
methodSection); methodSection, protoSection);
writer.writeInt(codeUnitCount); writer.writeInt(codeUnitCount);
for (Instruction instruction: instructions) { for (Instruction instruction: instructions) {
@ -1005,9 +1006,6 @@ public abstract class DexWriter<
case Format23x: case Format23x:
instructionWriter.write((Instruction23x)instruction); instructionWriter.write((Instruction23x)instruction);
break; break;
case Format25x:
instructionWriter.write((Instruction25x)instruction);
break;
case Format30t: case Format30t:
instructionWriter.write((Instruction30t)instruction); instructionWriter.write((Instruction30t)instruction);
break; break;
@ -1029,6 +1027,12 @@ public abstract class DexWriter<
case Format3rc: case Format3rc:
instructionWriter.write((Instruction3rc)instruction); instructionWriter.write((Instruction3rc)instruction);
break; break;
case Format45cc:
instructionWriter.write((Instruction45cc) instruction);
break;
case Format4rcc:
instructionWriter.write((Instruction4rcc) instruction);
break;
case Format51l: case Format51l:
instructionWriter.write((Instruction51l)instruction); instructionWriter.write((Instruction51l)instruction);
break; break;

View File

@ -36,11 +36,14 @@ import com.google.common.primitives.Ints;
import org.jf.dexlib2.Opcode; import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.Opcodes; import org.jf.dexlib2.Opcodes;
import org.jf.dexlib2.ReferenceType; import org.jf.dexlib2.ReferenceType;
import org.jf.dexlib2.iface.instruction.DualReferenceInstruction;
import org.jf.dexlib2.iface.instruction.ReferenceInstruction; import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
import org.jf.dexlib2.iface.instruction.SwitchElement; import org.jf.dexlib2.iface.instruction.SwitchElement;
import org.jf.dexlib2.iface.instruction.formats.*; import org.jf.dexlib2.iface.instruction.formats.*;
import org.jf.dexlib2.iface.reference.FieldReference; import org.jf.dexlib2.iface.reference.FieldReference;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodReference; import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.iface.reference.Reference;
import org.jf.dexlib2.iface.reference.StringReference; import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference; import org.jf.dexlib2.iface.reference.TypeReference;
import org.jf.util.ExceptionWithContext; import org.jf.util.ExceptionWithContext;
@ -51,25 +54,29 @@ import java.util.Comparator;
import java.util.List; import java.util.List;
public class InstructionWriter<StringRef extends StringReference, TypeRef extends TypeReference, public class InstructionWriter<StringRef extends StringReference, TypeRef extends TypeReference,
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference> { FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
ProtoRefKey extends MethodProtoReference> {
@Nonnull private final Opcodes opcodes; @Nonnull private final Opcodes opcodes;
@Nonnull private final DexDataWriter writer; @Nonnull private final DexDataWriter writer;
@Nonnull private final StringSection<?, StringRef> stringSection; @Nonnull private final StringSection<?, StringRef> stringSection;
@Nonnull private final TypeSection<?, ?, TypeRef> typeSection; @Nonnull private final TypeSection<?, ?, TypeRef> typeSection;
@Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection; @Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection; @Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
@Nonnull private final ProtoSection<?, ?, ProtoRefKey, ?> protoSection;
@Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference> @Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, FieldRefKey extends FieldReference,
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey> MethodRefKey extends MethodReference, ProtoRefKey extends MethodProtoReference>
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey>
makeInstructionWriter( makeInstructionWriter(
@Nonnull Opcodes opcodes, @Nonnull Opcodes opcodes,
@Nonnull DexDataWriter writer, @Nonnull DexDataWriter writer,
@Nonnull StringSection<?, StringRef> stringSection, @Nonnull StringSection<?, StringRef> stringSection,
@Nonnull TypeSection<?, ?, TypeRef> typeSection, @Nonnull TypeSection<?, ?, TypeRef> typeSection,
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection) { @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey>( @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection) {
opcodes, writer, stringSection, typeSection, fieldSection, methodSection); return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey>(
opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection);
} }
InstructionWriter(@Nonnull Opcodes opcodes, InstructionWriter(@Nonnull Opcodes opcodes,
@ -77,13 +84,15 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
@Nonnull StringSection<?, StringRef> stringSection, @Nonnull StringSection<?, StringRef> stringSection,
@Nonnull TypeSection<?, ?, TypeRef> typeSection, @Nonnull TypeSection<?, ?, TypeRef> typeSection,
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection) { @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection) {
this.opcodes = opcodes; this.opcodes = opcodes;
this.writer = writer; this.writer = writer;
this.stringSection = stringSection; this.stringSection = stringSection;
this.typeSection = typeSection; this.typeSection = typeSection;
this.fieldSection = fieldSection; this.fieldSection = fieldSection;
this.methodSection = methodSection; this.methodSection = methodSection;
this.protoSection = protoSection;
} }
private short getOpcodeValue(Opcode opcode) { private short getOpcodeValue(Opcode opcode) {
@ -334,19 +343,6 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
} }
} }
public void write(@Nonnull Instruction25x instruction) {
try {
writer.write(getOpcodeValue(instruction.getOpcode()));
writer.write(packNibbles(
instruction.getRegisterParameterG(), instruction.getParameterRegisterCount()));
writer.write(packNibbles(
instruction.getRegisterFixedC(), instruction.getRegisterParameterD()));
writer.write(packNibbles(
instruction.getRegisterParameterE(), instruction.getRegisterParameterF()));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
public void write(@Nonnull Instruction3rc instruction) { public void write(@Nonnull Instruction3rc instruction) {
try { try {
writer.write(getOpcodeValue(instruction.getOpcode())); writer.write(getOpcodeValue(instruction.getOpcode()));
@ -358,6 +354,31 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
} }
} }
public void write(@Nonnull Instruction45cc instruction) {
try {
writer.write(getOpcodeValue(instruction.getOpcode()));
writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount()));
writer.writeUshort(getReferenceIndex(instruction));
writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD()));
writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF()));
writer.writeUshort(getReference2Index(instruction));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
public void write(@Nonnull Instruction4rcc instruction) {
try {
writer.write(getOpcodeValue(instruction.getOpcode()));
writer.write(instruction.getRegisterCount());
writer.writeUshort(getReferenceIndex(instruction));
writer.writeUshort(instruction.getStartRegister());
writer.writeUshort(getReference2Index(instruction));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
public void write(@Nonnull Instruction51l instruction) { public void write(@Nonnull Instruction51l instruction) {
try { try {
writer.write(getOpcodeValue(instruction.getOpcode())); writer.write(getOpcodeValue(instruction.getOpcode()));
@ -452,18 +473,29 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
} }
private int getReferenceIndex(ReferenceInstruction referenceInstruction) { private int getReferenceIndex(ReferenceInstruction referenceInstruction) {
switch (referenceInstruction.getOpcode().referenceType) { return getReferenceIndex(referenceInstruction.getReferenceType(),
referenceInstruction.getReference());
}
private int getReference2Index(DualReferenceInstruction referenceInstruction) {
return getReferenceIndex(referenceInstruction.getReferenceType2(),
referenceInstruction.getReference2());
}
private int getReferenceIndex(int referenceType, Reference reference) {
switch (referenceType) {
case ReferenceType.FIELD: case ReferenceType.FIELD:
return fieldSection.getItemIndex((FieldRefKey)referenceInstruction.getReference()); return fieldSection.getItemIndex((FieldRefKey) reference);
case ReferenceType.METHOD: case ReferenceType.METHOD:
return methodSection.getItemIndex((MethodRefKey)referenceInstruction.getReference()); return methodSection.getItemIndex((MethodRefKey) reference);
case ReferenceType.STRING: case ReferenceType.STRING:
return stringSection.getItemIndex((StringRef)referenceInstruction.getReference()); return stringSection.getItemIndex((StringRef) reference);
case ReferenceType.TYPE: case ReferenceType.TYPE:
return typeSection.getItemIndex((TypeRef)referenceInstruction.getReference()); return typeSection.getItemIndex((TypeRef) reference);
case ReferenceType.METHOD_PROTO:
return protoSection.getItemIndex((ProtoRefKey) reference);
default: default:
throw new ExceptionWithContext("Unknown reference type: %d", throw new ExceptionWithContext("Unknown reference type: %d", referenceType);
referenceInstruction.getOpcode().referenceType);
} }
} }
} }

View File

@ -31,15 +31,17 @@
package org.jf.dexlib2.writer; package org.jf.dexlib2.writer;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodReference; import org.jf.dexlib2.iface.reference.MethodReference;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public interface MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey extends MethodReference, MethodKey> public interface MethodSection<StringKey, TypeKey, ProtoRefKey extends MethodProtoReference,
MethodRefKey extends MethodReference, MethodKey>
extends IndexSection<MethodRefKey> { extends IndexSection<MethodRefKey> {
@Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key); @Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key);
@Nonnull ProtoKey getPrototype(@Nonnull MethodRefKey key); @Nonnull ProtoRefKey getPrototype(@Nonnull MethodRefKey key);
@Nonnull ProtoKey getPrototype(@Nonnull MethodKey key); @Nonnull ProtoRefKey getPrototype(@Nonnull MethodKey key);
@Nonnull StringKey getName(@Nonnull MethodRefKey key); @Nonnull StringKey getName(@Nonnull MethodRefKey key);
int getMethodIndex(@Nonnull MethodKey key); int getMethodIndex(@Nonnull MethodKey key);
} }

View File

@ -43,7 +43,7 @@ import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
class BuilderMethodPool implements MethodSection<BuilderStringReference, BuilderTypeReference, class BuilderMethodPool implements MethodSection<BuilderStringReference, BuilderTypeReference,
BuilderProtoReference, BuilderMethodReference, BuilderMethod>{ BuilderMethodProtoReference, BuilderMethodReference, BuilderMethod>{
@Nonnull private final BuilderContext context; @Nonnull private final BuilderContext context;
@Nonnull private final ConcurrentMap<MethodReference, BuilderMethodReference> internedItems = @Nonnull private final ConcurrentMap<MethodReference, BuilderMethodReference> internedItems =
Maps.newConcurrentMap(); Maps.newConcurrentMap();
@ -61,7 +61,7 @@ class BuilderMethodPool implements MethodSection<BuilderStringReference, Builder
BuilderMethodReference dexPoolMethodReference = new BuilderMethodReference( BuilderMethodReference dexPoolMethodReference = new BuilderMethodReference(
context.typePool.internType(methodReference.getDefiningClass()), context.typePool.internType(methodReference.getDefiningClass()),
context.stringPool.internString(methodReference.getName()), context.stringPool.internString(methodReference.getName()),
context.protoPool.internProto(methodReference)); context.protoPool.internMethodProto(methodReference));
ret = internedItems.putIfAbsent(dexPoolMethodReference, dexPoolMethodReference); ret = internedItems.putIfAbsent(dexPoolMethodReference, dexPoolMethodReference);
return ret==null?dexPoolMethodReference:ret; return ret==null?dexPoolMethodReference:ret;
} }
@ -78,11 +78,11 @@ class BuilderMethodPool implements MethodSection<BuilderStringReference, Builder
} }
@Nonnull @Override @Nonnull @Override
public BuilderProtoReference getPrototype(@Nonnull BuilderMethodReference key) { public BuilderMethodProtoReference getPrototype(@Nonnull BuilderMethodReference key) {
return key.proto; return key.proto;
} }
@Nonnull @Override public BuilderProtoReference getPrototype(@Nonnull BuilderMethod builderMethod) { @Nonnull @Override public BuilderMethodProtoReference getPrototype(@Nonnull BuilderMethod builderMethod) {
return builderMethod.methodReference.proto; return builderMethod.methodReference.proto;
} }

View File

@ -32,6 +32,8 @@
package org.jf.dexlib2.writer.builder; package org.jf.dexlib2.writer.builder;
import com.google.common.collect.Ordering; import com.google.common.collect.Ordering;
import org.jf.dexlib2.base.reference.BaseMethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.writer.DexWriter; import org.jf.dexlib2.writer.DexWriter;
import org.jf.util.CharSequenceUtils; import org.jf.util.CharSequenceUtils;
import org.jf.util.CollectionUtils; import org.jf.util.CollectionUtils;
@ -40,13 +42,14 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
public class BuilderProtoReference implements BuilderProtoPool.ProtoKey, Comparable<BuilderProtoReference> { public class BuilderMethodProtoReference extends BaseMethodProtoReference implements
MethodProtoReference, BuilderReference {
@Nonnull final BuilderStringReference shorty; @Nonnull final BuilderStringReference shorty;
@Nonnull final BuilderTypeList parameterTypes; @Nonnull final BuilderTypeList parameterTypes;
@Nonnull final BuilderTypeReference returnType; @Nonnull final BuilderTypeReference returnType;
int index = DexWriter.NO_INDEX; int index = DexWriter.NO_INDEX;
public BuilderProtoReference(@Nonnull BuilderStringReference shorty, @Nonnull BuilderTypeList parameterTypes, public BuilderMethodProtoReference(@Nonnull BuilderStringReference shorty, @Nonnull BuilderTypeList parameterTypes,
@Nonnull BuilderTypeReference returnType) { @Nonnull BuilderTypeReference returnType) {
this.shorty = shorty; this.shorty = shorty;
this.parameterTypes = parameterTypes; this.parameterTypes = parameterTypes;
@ -62,25 +65,12 @@ public class BuilderProtoReference implements BuilderProtoPool.ProtoKey, Compara
} }
@Override @Override
public int hashCode() { public int getIndex() {
int hashCode = getReturnType().hashCode(); return index;
return hashCode*31 + getParameterTypes().hashCode();
} }
@Override @Override
public boolean equals(@Nullable Object o) { public void setIndex(int index) {
if (o != null && o instanceof BuilderProtoReference) { this.index = index;
BuilderProtoReference other = (BuilderProtoReference)o;
return returnType.equals(other.returnType) &&
CharSequenceUtils.listEquals(parameterTypes, other.parameterTypes);
}
return false;
}
@Override
public int compareTo(@Nonnull BuilderProtoReference o) {
int res = returnType.compareTo(o.returnType);
if (res != 0) return res;
return CollectionUtils.compareAsIterable(Ordering.usingToString(), parameterTypes, o.parameterTypes);
} }
} }

View File

@ -39,12 +39,12 @@ import javax.annotation.Nonnull;
public class BuilderMethodReference extends BaseMethodReference implements BuilderReference { public class BuilderMethodReference extends BaseMethodReference implements BuilderReference {
@Nonnull final BuilderTypeReference definingClass; @Nonnull final BuilderTypeReference definingClass;
@Nonnull final BuilderStringReference name; @Nonnull final BuilderStringReference name;
@Nonnull final BuilderProtoReference proto; @Nonnull final BuilderMethodProtoReference proto;
int index = DexWriter.NO_INDEX; int index = DexWriter.NO_INDEX;
BuilderMethodReference(@Nonnull BuilderTypeReference definingClass, BuilderMethodReference(@Nonnull BuilderTypeReference definingClass,
@Nonnull BuilderStringReference name, @Nonnull BuilderStringReference name,
@Nonnull BuilderProtoReference proto) { @Nonnull BuilderMethodProtoReference proto) {
this.definingClass = definingClass; this.definingClass = definingClass;
this.name = name; this.name = name;
this.proto = proto; this.proto = proto;

View File

@ -32,114 +32,75 @@
package org.jf.dexlib2.writer.builder; package org.jf.dexlib2.writer.builder;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodReference; import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.immutable.reference.ImmutableMethodProtoReference;
import org.jf.dexlib2.util.MethodUtil; import org.jf.dexlib2.util.MethodUtil;
import org.jf.dexlib2.writer.ProtoSection; import org.jf.dexlib2.writer.ProtoSection;
import org.jf.util.CharSequenceUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
class BuilderProtoPool class BuilderProtoPool
implements ProtoSection<BuilderStringReference, BuilderTypeReference, BuilderProtoReference, BuilderTypeList> { implements ProtoSection<BuilderStringReference, BuilderTypeReference, BuilderMethodProtoReference, BuilderTypeList> {
@Nonnull private final BuilderContext context; @Nonnull private final BuilderContext context;
@Nonnull private final ConcurrentMap<ProtoKey, BuilderProtoReference> internedItems = @Nonnull private final ConcurrentMap<MethodProtoReference, BuilderMethodProtoReference> internedItems =
Maps.newConcurrentMap(); Maps.newConcurrentMap();
BuilderProtoPool(@Nonnull BuilderContext context) { BuilderProtoPool(@Nonnull BuilderContext context) {
this.context = context; this.context = context;
} }
@Nonnull public BuilderProtoReference internProto(@Nonnull List<? extends CharSequence> parameters, @Nonnull public BuilderMethodProtoReference internMethodProto(@Nonnull MethodProtoReference methodProto) {
@Nonnull String returnType) { BuilderMethodProtoReference ret = internedItems.get(methodProto);
ProtoKey key = new Key(parameters, returnType);
BuilderProtoReference ret = internedItems.get(key);
if (ret != null) { if (ret != null) {
return ret; return ret;
} }
BuilderProtoReference protoReference = new BuilderProtoReference( BuilderMethodProtoReference protoReference = new BuilderMethodProtoReference(
context.stringPool.internString(MethodUtil.getShorty(parameters, returnType)), context.stringPool.internString(MethodUtil.getShorty(
context.typeListPool.internTypeList(parameters), methodProto.getParameterTypes(), methodProto.getReturnType())),
context.typePool.internType(returnType)); context.typeListPool.internTypeList(methodProto.getParameterTypes()),
context.typePool.internType(methodProto.getReturnType()));
ret = internedItems.putIfAbsent(protoReference, protoReference); ret = internedItems.putIfAbsent(protoReference, protoReference);
return ret==null?protoReference:ret; return ret==null?protoReference:ret;
} }
@Nonnull public BuilderProtoReference internProto(@Nonnull MethodReference methodReference) { @Nonnull public BuilderMethodProtoReference internMethodProto(@Nonnull MethodReference methodReference) {
return internProto(methodReference.getParameterTypes(), methodReference.getReturnType()); return internMethodProto(new ImmutableMethodProtoReference(
methodReference.getParameterTypes(), methodReference.getReturnType()));
} }
@Nonnull @Override public BuilderStringReference getShorty(@Nonnull BuilderProtoReference key) { @Nonnull @Override public BuilderStringReference getShorty(@Nonnull BuilderMethodProtoReference proto) {
return key.shorty; return proto.shorty;
} }
@Nonnull @Override public BuilderTypeReference getReturnType(@Nonnull BuilderProtoReference key) { @Nonnull @Override public BuilderTypeReference getReturnType(@Nonnull BuilderMethodProtoReference proto) {
return key.returnType; return proto.returnType;
} }
@Nullable @Override public BuilderTypeList getParameters(@Nonnull BuilderProtoReference key) { @Nullable @Override public BuilderTypeList getParameters(@Nonnull BuilderMethodProtoReference proto) {
return key.parameterTypes; return proto.parameterTypes;
} }
@Override public int getItemIndex(@Nonnull BuilderProtoReference key) { @Override public int getItemIndex(@Nonnull BuilderMethodProtoReference proto) {
return proto.getIndex();
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderMethodProtoReference, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderMethodProtoReference>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderMethodProtoReference key) {
return key.index; return key.index;
} }
@Nonnull @Override public Collection<? extends Entry<? extends BuilderProtoReference, Integer>> getItems() { @Override protected int setValue(@Nonnull BuilderMethodProtoReference key, int value) {
return new BuilderMapEntryCollection<BuilderProtoReference>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderProtoReference key) {
return key.index;
}
@Override protected int setValue(@Nonnull BuilderProtoReference key, int value) {
int prev = key.index; int prev = key.index;
key.index = value; key.index = value;
return prev; return prev;
} }
}; };
} }
// a placeholder interface to unify the temporary probing key and the BuilderProtoReference class
interface ProtoKey {
@Nonnull List<? extends CharSequence> getParameterTypes();
@Nonnull String getReturnType();
}
// a temporary lightweight class to allow a quick probe if the given prototype has already been interned
private static class Key implements ProtoKey {
@Nonnull private final List<? extends CharSequence> parameters;
@Nonnull private final String returnType;
public Key(@Nonnull List<? extends CharSequence> parameters, @Nonnull String returnType) {
this.parameters = parameters;
this.returnType = returnType;
}
@Nonnull public List<? extends CharSequence> getParameterTypes() {
return parameters;
}
@Nonnull public String getReturnType() {
return returnType;
}
@Override public int hashCode() {
int hashCode = returnType.hashCode();
return hashCode*31 + parameters.hashCode();
}
@Override public boolean equals(Object o) {
if (o != null && o instanceof ProtoKey) {
ProtoKey other = (ProtoKey)o;
return getReturnType().equals(other.getReturnType()) &&
CharSequenceUtils.listEquals(getParameterTypes(), other.getParameterTypes());
}
return false;
}
}
} }

View File

@ -54,7 +54,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringReference, BuilderTypeReference, public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringReference, BuilderTypeReference,
BuilderTypeReference, BuilderProtoReference, BuilderFieldReference, BuilderMethodReference, BuilderTypeReference, BuilderMethodProtoReference, BuilderFieldReference, BuilderMethodReference,
BuilderClassDef, BuilderAnnotation, BuilderAnnotationSet, BuilderTypeList, BuilderField, BuilderMethod, BuilderClassDef, BuilderAnnotation, BuilderAnnotationSet, BuilderTypeList, BuilderField, BuilderMethod,
BuilderEncodedValue, BuilderAnnotationElement> { BuilderEncodedValue, BuilderAnnotationElement> {
@ -176,6 +176,10 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
return context.methodPool.internMethod(method); return context.methodPool.internMethod(method);
} }
@Nonnull public BuilderMethodProtoReference internMethodProtoReference(@Nonnull MethodProtoReference methodProto) {
return context.protoPool.internMethodProto(methodProto);
}
@Nonnull public BuilderReference internReference(@Nonnull Reference reference) { @Nonnull public BuilderReference internReference(@Nonnull Reference reference) {
if (reference instanceof StringReference) { if (reference instanceof StringReference) {
return internStringReference(((StringReference)reference).getString()); return internStringReference(((StringReference)reference).getString());
@ -189,6 +193,9 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
if (reference instanceof FieldReference) { if (reference instanceof FieldReference) {
return internFieldReference((FieldReference)reference); return internFieldReference((FieldReference)reference);
} }
if (reference instanceof MethodProtoReference) {
return internMethodProtoReference((MethodProtoReference) reference);
}
throw new IllegalArgumentException("Could not determine type of reference"); throw new IllegalArgumentException("Could not determine type of reference");
} }

View File

@ -42,7 +42,6 @@ import org.jf.dexlib2.iface.value.*;
import org.jf.dexlib2.writer.DexWriter; import org.jf.dexlib2.writer.DexWriter;
import org.jf.dexlib2.writer.io.DexDataStore; import org.jf.dexlib2.writer.io.DexDataStore;
import org.jf.dexlib2.writer.io.FileDataStore; import org.jf.dexlib2.writer.io.FileDataStore;
import org.jf.dexlib2.writer.pool.ProtoPool.Key;
import org.jf.util.ExceptionWithContext; import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -51,8 +50,8 @@ import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Set; import java.util.Set;
public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference, Key, public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference,
FieldReference, MethodReference, PoolClassDef, MethodProtoReference, FieldReference, MethodReference, PoolClassDef,
Annotation, Set<? extends Annotation>, Annotation, Set<? extends Annotation>,
TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod, TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
EncodedValue, AnnotationElement> { EncodedValue, AnnotationElement> {

View File

@ -31,13 +31,14 @@
package org.jf.dexlib2.writer.pool; package org.jf.dexlib2.writer.pool;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodReference; import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.writer.MethodSection; import org.jf.dexlib2.writer.MethodSection;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class MethodPool extends BaseIndexPool<MethodReference> public class MethodPool extends BaseIndexPool<MethodReference>
implements MethodSection<CharSequence, CharSequence, ProtoPool.Key, MethodReference, PoolMethod> { implements MethodSection<CharSequence, CharSequence, MethodProtoReference, MethodReference, PoolMethod> {
@Nonnull private final StringPool stringPool; @Nonnull private final StringPool stringPool;
@Nonnull private final TypePool typePool; @Nonnull private final TypePool typePool;
@Nonnull private final ProtoPool protoPool; @Nonnull private final ProtoPool protoPool;
@ -53,7 +54,7 @@ public class MethodPool extends BaseIndexPool<MethodReference>
Integer prev = internedItems.put(method, 0); Integer prev = internedItems.put(method, 0);
if (prev == null) { if (prev == null) {
typePool.intern(method.getDefiningClass()); typePool.intern(method.getDefiningClass());
protoPool.intern(method); protoPool.intern(new PoolMethodProto(method));
stringPool.intern(method.getName()); stringPool.intern(method.getName());
} }
} }
@ -62,12 +63,12 @@ public class MethodPool extends BaseIndexPool<MethodReference>
return methodReference.getDefiningClass(); return methodReference.getDefiningClass();
} }
@Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull MethodReference methodReference) { @Nonnull @Override public MethodProtoReference getPrototype(@Nonnull MethodReference methodReference) {
return new ProtoPool.Key(methodReference); return new PoolMethodProto(methodReference);
} }
@Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull PoolMethod poolMethod) { @Nonnull @Override public MethodProtoReference getPrototype(@Nonnull PoolMethod poolMethod) {
return new ProtoPool.Key(poolMethod); return new PoolMethodProto(poolMethod);
} }
@Nonnull @Override public CharSequence getName(@Nonnull MethodReference methodReference) { @Nonnull @Override public CharSequence getName(@Nonnull MethodReference methodReference) {

View File

@ -0,0 +1,56 @@
/*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.pool;
import org.jf.dexlib2.base.reference.BaseMethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodReference;
import java.util.List;
public class PoolMethodProto extends BaseMethodProtoReference implements MethodProtoReference {
private final MethodReference methodReference;
public PoolMethodProto(MethodReference methodReference) {
this.methodReference = methodReference;
}
@Override
public List<? extends CharSequence> getParameterTypes() {
return methodReference.getParameterTypes();
}
@Override
public String getReturnType() {
return methodReference.getReturnType();
}
}

View File

@ -31,21 +31,18 @@
package org.jf.dexlib2.writer.pool; package org.jf.dexlib2.writer.pool;
import com.google.common.collect.Ordering; import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.util.MethodUtil; import org.jf.dexlib2.util.MethodUtil;
import org.jf.dexlib2.writer.pool.ProtoPool.Key;
import org.jf.dexlib2.writer.ProtoSection; import org.jf.dexlib2.writer.ProtoSection;
import org.jf.util.CharSequenceUtils;
import org.jf.util.CollectionUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
public class ProtoPool extends BaseIndexPool<Key> public class ProtoPool extends BaseIndexPool<MethodProtoReference>
implements ProtoSection<CharSequence, CharSequence, Key, TypeListPool.Key<? extends Collection<? extends CharSequence>>> { implements ProtoSection<CharSequence, CharSequence, MethodProtoReference,
TypeListPool.Key<? extends Collection<? extends CharSequence>>> {
@Nonnull private final StringPool stringPool; @Nonnull private final StringPool stringPool;
@Nonnull private final TypePool typePool; @Nonnull private final TypePool typePool;
@Nonnull private final TypeListPool typeListPool; @Nonnull private final TypeListPool typeListPool;
@ -57,78 +54,25 @@ public class ProtoPool extends BaseIndexPool<Key>
this.typeListPool = typeListPool; this.typeListPool = typeListPool;
} }
public void intern(@Nonnull MethodReference method) { public void intern(@Nonnull MethodProtoReference reference) {
// We can't use method directly, because it is likely a full MethodReference. We use a wrapper that computes Integer prev = internedItems.put(reference, 0);
// hashCode and equals based only on the prototype fields
Key key = new Key(method);
Integer prev = internedItems.put(key, 0);
if (prev == null) { if (prev == null) {
stringPool.intern(key.getShorty()); stringPool.intern(getShorty(reference));
typePool.intern(method.getReturnType()); typePool.intern(reference.getReturnType());
typeListPool.intern(method.getParameterTypes()); typeListPool.intern(reference.getParameterTypes());
} }
} }
@Nonnull @Override public CharSequence getShorty(@Nonnull Key key) { @Nonnull @Override public CharSequence getShorty(@Nonnull MethodProtoReference reference) {
return key.getShorty(); return MethodUtil.getShorty(reference.getParameterTypes(), reference.getReturnType());
} }
@Nonnull @Override public CharSequence getReturnType(@Nonnull Key key) { @Nonnull @Override public CharSequence getReturnType(@Nonnull MethodProtoReference protoReference) {
return key.getReturnType(); return protoReference.getReturnType();
} }
@Nullable @Override public TypeListPool.Key<List<? extends CharSequence>> getParameters(@Nonnull Key key) { @Nullable @Override public TypeListPool.Key<List<? extends CharSequence>> getParameters(
return new TypeListPool.Key<List<? extends CharSequence>>(key.getParameters()); @Nonnull MethodProtoReference methodProto) {
} return new TypeListPool.Key<List<? extends CharSequence>>(methodProto.getParameterTypes());
public static class Key implements Comparable<Key> {
@Nonnull private final MethodReference method;
public Key(@Nonnull MethodReference method) {
this.method = method;
}
@Nonnull public String getReturnType() { return method.getReturnType(); }
@Nonnull public List<? extends CharSequence> getParameters() {
return method.getParameterTypes();
}
public String getShorty() {
return MethodUtil.getShorty(method.getParameterTypes(), method.getReturnType());
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('(');
for (CharSequence paramType: getParameters()) {
sb.append(paramType);
}
sb.append(')');
sb.append(getReturnType());
return sb.toString();
}
@Override
public int hashCode() {
int hashCode = getReturnType().hashCode();
return hashCode*31 + CharSequenceUtils.listHashCode(getParameters());
}
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof Key) {
Key other = (Key)o;
return getReturnType().equals(other.getReturnType()) &&
CharSequenceUtils.listEquals(getParameters(), other.getParameters());
}
return false;
}
@Override
public int compareTo(@Nonnull Key o) {
int res = getReturnType().compareTo(o.getReturnType());
if (res != 0) return res;
return CollectionUtils.compareAsIterable(Ordering.usingToString(), getParameters(), o.getParameters());
}
} }
} }

View File

@ -1,8 +0,0 @@
# Functional interface used by HelloWorld.smali
# Required in order to reify the lambda with create-lambda or unbox-lambda instructions
.class public abstract interface LHelloWorldFunctionalInterface;
.super Ljava/lang/Object;
.method public abstract applyFourStrings(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
.end method

View File

@ -1,57 +0,0 @@
.class public LHelloWorldLambda;
#Ye olde hello world application (with lambdas!)
#To assemble and run this on a phone or emulator:
#
#java -jar smali.jar -o classes.dex HelloWorldLambda.smali HelloWorldFunctionalInterface.smali
#zip HelloWorld.zip classes.dex
#adb push HelloWorld.zip /data/local
#adb shell dalvikvm -cp /data/local/HelloWorld.zip HelloWorld
#
#if you get out of memory type errors when running smali.jar, try
#java -Xmx512m -jar smali.jar HelloWorldLambda.smali
#instead
.super Ljava/lang/Object;
.method public static main([Ljava/lang/String;)V
.registers 9 # 1 parameter, 8 locals
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v1, "Hello World!"
const-string v2, "How" # vD
const-string v3, "are" # vE
const-string v4, "you" # vF
const-string v5, "doing?" # vG
capture-variable v1, "helloworld"
# TODO: do I need to pass the type of the lambda's functional interface here as a type id?
create-lambda v1, LHelloWorldLambda;->doHelloWorld(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
# Method descriptor is not required here, because only the single-abstract method is ever invoked.
invoke-lambda v1, {v2, v3, v4, v5}
box-lambda v6, v1 # The type of v6 is now 'LHelloWorldFunctionalInterface;'
invoke-virtual {v6, v2, v3, v4, v5}, LHelloWorldFunctionalInterface;->applyFourStrings(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
# FIXME: should be \HelloWorldFunctionalInterface; instead of L...;
# TODO: do we really need the type descriptor here at all?
unbox-lambda v7, v6, LHelloWorldFunctionalInterface; # The type of v7 is now \HelloWorldFunctionalInterface;
invoke-lambda v7, {v2, v3, v4, v5}
return-void
.end method
.method public static doHelloWorld(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
.registers 6 # 4 parameters, 2 locals
# This helloworld variable is brought to you by the variable liberation front
liberate-variable v0, p0, "helloworld"
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
return-void
.end method

Binary file not shown.

View File

@ -1,6 +1,6 @@
#Sun Feb 14 12:35:03 PST 2016 #Fri Jul 08 16:46:58 PDT 2016
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip

10
gradlew vendored
View File

@ -42,11 +42,6 @@ case "`uname`" in
;; ;;
esac esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME # Attempt to set APP_HOME
# Resolve links: $0 may be a link # Resolve links: $0 may be a link
PRG="$0" PRG="$0"
@ -61,9 +56,9 @@ while [ -h "$PRG" ] ; do
fi fi
done done
SAVED="`pwd`" SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&- cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`" APP_HOME="`pwd -P`"
cd "$SAVED" >&- cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@ -114,6 +109,7 @@ fi
if $cygwin ; then if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`

2
gradlew.bat vendored
View File

@ -46,7 +46,7 @@ echo location of your Java installation.
goto fail goto fail
:init :init
@rem Get command-line arguments, handling Windowz variants @rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args if "%@eval[2+2]" == "4" goto 4NT_args

View File

@ -30,7 +30,7 @@
*/ */
apply plugin: 'antlr' apply plugin: 'antlr'
apply plugin: 'jflex' apply plugin: 'org.xbib.gradle.plugin.jflex'
buildscript { buildscript {
repositories { repositories {
@ -46,10 +46,6 @@ configurations {
// Remove the full antlr library that's added by the antlr plugin. We manually // Remove the full antlr library that's added by the antlr plugin. We manually
// add the smaller antlr_runtime library instead // add the smaller antlr_runtime library instead
compile.exclude group: 'org.antlr', module: 'antlr' compile.exclude group: 'org.antlr', module: 'antlr'
// The jflex lexer doesn't have any runtime dependencies, so remove the dependency
// that gets added by the jflex plugin
compile.exclude group: 'de.jflex', module: 'jflex'
} }
sourceSets { sourceSets {
@ -86,7 +82,6 @@ dependencies {
testCompile depends.junit testCompile depends.junit
antlr depends.antlr antlr depends.antlr
jflex depends.jflex
} }
processResources.inputs.property('version', version) processResources.inputs.property('version', version)
@ -119,8 +114,8 @@ generateGrammarSource {
outputDirectory = new File(outputDirectory, 'org/jf/smali') outputDirectory = new File(outputDirectory, 'org/jf/smali')
} }
generateJFlexSource { jflex {
outputDirectory = new File(outputDirectory, 'org/jf/smali') generateDir = new File(generateDir, 'org/jf/smali')
} }
uploadArchives { uploadArchives {

View File

@ -86,8 +86,6 @@ tokens {
INSTRUCTION_FORMAT21c_FIELD_ODEX; INSTRUCTION_FORMAT21c_FIELD_ODEX;
INSTRUCTION_FORMAT21c_STRING; INSTRUCTION_FORMAT21c_STRING;
INSTRUCTION_FORMAT21c_TYPE; INSTRUCTION_FORMAT21c_TYPE;
INSTRUCTION_FORMAT21c_LAMBDA;
INSTRUCTION_FORMAT21c_METHOD;
INSTRUCTION_FORMAT21ih; INSTRUCTION_FORMAT21ih;
INSTRUCTION_FORMAT21lh; INSTRUCTION_FORMAT21lh;
INSTRUCTION_FORMAT21s; INSTRUCTION_FORMAT21s;
@ -96,14 +94,12 @@ tokens {
INSTRUCTION_FORMAT22c_FIELD; INSTRUCTION_FORMAT22c_FIELD;
INSTRUCTION_FORMAT22c_FIELD_ODEX; INSTRUCTION_FORMAT22c_FIELD_ODEX;
INSTRUCTION_FORMAT22c_TYPE; INSTRUCTION_FORMAT22c_TYPE;
INSTRUCTION_FORMAT22c_STRING;
INSTRUCTION_FORMAT22cs_FIELD; INSTRUCTION_FORMAT22cs_FIELD;
INSTRUCTION_FORMAT22s; INSTRUCTION_FORMAT22s;
INSTRUCTION_FORMAT22s_OR_ID; INSTRUCTION_FORMAT22s_OR_ID;
INSTRUCTION_FORMAT22t; INSTRUCTION_FORMAT22t;
INSTRUCTION_FORMAT22x; INSTRUCTION_FORMAT22x;
INSTRUCTION_FORMAT23x; INSTRUCTION_FORMAT23x;
INSTRUCTION_FORMAT25x;
INSTRUCTION_FORMAT30t; INSTRUCTION_FORMAT30t;
INSTRUCTION_FORMAT31c; INSTRUCTION_FORMAT31c;
INSTRUCTION_FORMAT31i; INSTRUCTION_FORMAT31i;
@ -120,6 +116,8 @@ tokens {
INSTRUCTION_FORMAT3rc_TYPE; INSTRUCTION_FORMAT3rc_TYPE;
INSTRUCTION_FORMAT3rmi_METHOD; INSTRUCTION_FORMAT3rmi_METHOD;
INSTRUCTION_FORMAT3rms_METHOD; INSTRUCTION_FORMAT3rms_METHOD;
INSTRUCTION_FORMAT45cc_METHOD;
INSTRUCTION_FORMAT4rcc_METHOD;
INSTRUCTION_FORMAT51l; INSTRUCTION_FORMAT51l;
LINE_COMMENT; LINE_COMMENT;
LINE_DIRECTIVE; LINE_DIRECTIVE;
@ -210,8 +208,6 @@ tokens {
I_STATEMENT_FORMAT21c_TYPE; I_STATEMENT_FORMAT21c_TYPE;
I_STATEMENT_FORMAT21c_FIELD; I_STATEMENT_FORMAT21c_FIELD;
I_STATEMENT_FORMAT21c_STRING; I_STATEMENT_FORMAT21c_STRING;
I_STATEMENT_FORMAT21c_LAMBDA;
I_STATEMENT_FORMAT21c_METHOD;
I_STATEMENT_FORMAT21ih; I_STATEMENT_FORMAT21ih;
I_STATEMENT_FORMAT21lh; I_STATEMENT_FORMAT21lh;
I_STATEMENT_FORMAT21s; I_STATEMENT_FORMAT21s;
@ -219,12 +215,10 @@ tokens {
I_STATEMENT_FORMAT22b; I_STATEMENT_FORMAT22b;
I_STATEMENT_FORMAT22c_FIELD; I_STATEMENT_FORMAT22c_FIELD;
I_STATEMENT_FORMAT22c_TYPE; I_STATEMENT_FORMAT22c_TYPE;
I_STATEMENT_FORMAT22c_STRING;
I_STATEMENT_FORMAT22s; I_STATEMENT_FORMAT22s;
I_STATEMENT_FORMAT22t; I_STATEMENT_FORMAT22t;
I_STATEMENT_FORMAT22x; I_STATEMENT_FORMAT22x;
I_STATEMENT_FORMAT23x; I_STATEMENT_FORMAT23x;
I_STATEMENT_FORMAT25x;
I_STATEMENT_FORMAT30t; I_STATEMENT_FORMAT30t;
I_STATEMENT_FORMAT31c; I_STATEMENT_FORMAT31c;
I_STATEMENT_FORMAT31i; I_STATEMENT_FORMAT31i;
@ -234,6 +228,8 @@ tokens {
I_STATEMENT_FORMAT35c_TYPE; I_STATEMENT_FORMAT35c_TYPE;
I_STATEMENT_FORMAT3rc_METHOD; I_STATEMENT_FORMAT3rc_METHOD;
I_STATEMENT_FORMAT3rc_TYPE; I_STATEMENT_FORMAT3rc_TYPE;
I_STATEMENT_FORMAT45cc_METHOD;
I_STATEMENT_FORMAT4rcc_METHOD;
I_STATEMENT_FORMAT51l; I_STATEMENT_FORMAT51l;
I_STATEMENT_ARRAY_DATA; I_STATEMENT_ARRAY_DATA;
I_STATEMENT_PACKED_SWITCH; I_STATEMENT_PACKED_SWITCH;
@ -562,18 +558,14 @@ simple_name
| INSTRUCTION_FORMAT21c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD_ODEX] | INSTRUCTION_FORMAT21c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD_ODEX]
| INSTRUCTION_FORMAT21c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_STRING] | INSTRUCTION_FORMAT21c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_STRING]
| INSTRUCTION_FORMAT21c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_TYPE] | INSTRUCTION_FORMAT21c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_TYPE]
| INSTRUCTION_FORMAT21c_LAMBDA -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_LAMBDA]
| INSTRUCTION_FORMAT21c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_METHOD]
| INSTRUCTION_FORMAT21t -> SIMPLE_NAME[$INSTRUCTION_FORMAT21t] | INSTRUCTION_FORMAT21t -> SIMPLE_NAME[$INSTRUCTION_FORMAT21t]
| INSTRUCTION_FORMAT22c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD] | INSTRUCTION_FORMAT22c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD]
| INSTRUCTION_FORMAT22c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD_ODEX] | INSTRUCTION_FORMAT22c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD_ODEX]
| INSTRUCTION_FORMAT22c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_TYPE] | INSTRUCTION_FORMAT22c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_TYPE]
| INSTRUCTION_FORMAT22c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_STRING]
| INSTRUCTION_FORMAT22cs_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22cs_FIELD] | INSTRUCTION_FORMAT22cs_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22cs_FIELD]
| INSTRUCTION_FORMAT22s_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT22s_OR_ID] | INSTRUCTION_FORMAT22s_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT22s_OR_ID]
| INSTRUCTION_FORMAT22t -> SIMPLE_NAME[$INSTRUCTION_FORMAT22t] | INSTRUCTION_FORMAT22t -> SIMPLE_NAME[$INSTRUCTION_FORMAT22t]
| INSTRUCTION_FORMAT23x -> SIMPLE_NAME[$INSTRUCTION_FORMAT23x] | INSTRUCTION_FORMAT23x -> SIMPLE_NAME[$INSTRUCTION_FORMAT23x]
| INSTRUCTION_FORMAT25x -> SIMPLE_NAME[$INSTRUCTION_FORMAT25x]
| INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID] | INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID]
| INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t] | INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t]
| INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD] | INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD]
@ -581,6 +573,8 @@ simple_name
| INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE] | INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE]
| INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD] | INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD]
| INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD] | INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD]
| INSTRUCTION_FORMAT45cc_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT45cc_METHOD]
| INSTRUCTION_FORMAT4rcc_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT4rcc_METHOD]
| INSTRUCTION_FORMAT51l -> SIMPLE_NAME[$INSTRUCTION_FORMAT51l]; | INSTRUCTION_FORMAT51l -> SIMPLE_NAME[$INSTRUCTION_FORMAT51l];
member_name member_name
@ -817,8 +811,6 @@ instruction
| insn_format21c_field_odex | insn_format21c_field_odex
| insn_format21c_string | insn_format21c_string
| insn_format21c_type | insn_format21c_type
| insn_format21c_lambda
| insn_format21c_method
| insn_format21ih | insn_format21ih
| insn_format21lh | insn_format21lh
| insn_format21s | insn_format21s
@ -827,13 +819,11 @@ instruction
| insn_format22c_field | insn_format22c_field
| insn_format22c_field_odex | insn_format22c_field_odex
| insn_format22c_type | insn_format22c_type
| insn_format22c_string
| insn_format22cs_field | insn_format22cs_field
| insn_format22s | insn_format22s
| insn_format22t | insn_format22t
| insn_format22x | insn_format22x
| insn_format23x | insn_format23x
| insn_format25x
| insn_format30t | insn_format30t
| insn_format31c | insn_format31c
| insn_format31i | insn_format31i
@ -849,6 +839,8 @@ instruction
| insn_format3rc_type | insn_format3rc_type
| insn_format3rmi_method | insn_format3rmi_method
| insn_format3rms_method | insn_format3rms_method
| insn_format45cc_method
| insn_format4rcc_method
| insn_format51l | insn_format51l
| insn_array_data_directive | insn_array_data_directive
| insn_packed_switch_directive | insn_packed_switch_directive
@ -927,16 +919,6 @@ insn_format21c_type
INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA nonvoid_type_descriptor INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA nonvoid_type_descriptor
-> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER nonvoid_type_descriptor); -> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER nonvoid_type_descriptor);
insn_format21c_lambda
: //e.g. capture-variable v1, "foobar"
INSTRUCTION_FORMAT21c_LAMBDA REGISTER COMMA STRING_LITERAL
-> ^(I_STATEMENT_FORMAT21c_LAMBDA[$start, "I_STATEMENT_FORMAT21c_LAMBDA"] INSTRUCTION_FORMAT21c_LAMBDA REGISTER STRING_LITERAL);
insn_format21c_method
: //e.g. create-lambda v1, java/io/PrintStream/print(Ljava/lang/Stream;)V
INSTRUCTION_FORMAT21c_METHOD REGISTER COMMA method_reference
-> ^(I_STATEMENT_FORMAT21c_METHOD[$start, "I_STATEMENT_FORMAT21c_METHOD"] INSTRUCTION_FORMAT21c_METHOD REGISTER method_reference);
insn_format21ih insn_format21ih
: //e.g. const/high16 v1, 1234 : //e.g. const/high16 v1, 1234
INSTRUCTION_FORMAT21ih REGISTER COMMA fixed_32bit_literal INSTRUCTION_FORMAT21ih REGISTER COMMA fixed_32bit_literal
@ -982,11 +964,6 @@ insn_format22c_type
INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor
-> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor); -> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor);
insn_format22c_string
: //e.g. liberate-variable v0, v1, "baz"
INSTRUCTION_FORMAT22c_STRING REGISTER COMMA REGISTER COMMA STRING_LITERAL
-> ^(I_STATEMENT_FORMAT22c_STRING[$start, "I_STATEMENT_FORMAT22c_STRING"] INSTRUCTION_FORMAT22c_STRING REGISTER REGISTER STRING_LITERAL);
insn_format22cs_field insn_format22cs_field
: //e.g. iget-quick v0, v1, field@0xc : //e.g. iget-quick v0, v1, field@0xc
INSTRUCTION_FORMAT22cs_FIELD REGISTER COMMA REGISTER COMMA FIELD_OFFSET INSTRUCTION_FORMAT22cs_FIELD REGISTER COMMA REGISTER COMMA FIELD_OFFSET
@ -1014,11 +991,6 @@ insn_format23x
INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER
-> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER); -> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER);
insn_format25x
: //e.g. invoke-lambda vClosure, {vA, vB, vC, vD} -- up to 4 parameters + the closure.
INSTRUCTION_FORMAT25x REGISTER COMMA OPEN_BRACE register_list CLOSE_BRACE
-> ^(I_STATEMENT_FORMAT25x[$start, "I_STATEMENT_FORMAT25x"] INSTRUCTION_FORMAT25x REGISTER register_list);
insn_format30t insn_format30t
: //e.g. goto/32 endloop: : //e.g. goto/32 endloop:
INSTRUCTION_FORMAT30t label_ref INSTRUCTION_FORMAT30t label_ref
@ -1106,6 +1078,16 @@ insn_format3rms_method
throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rms_METHOD.text); throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rms_METHOD.text);
}; };
insn_format45cc_method
: //e.g. invoke-polymorphic {v0..v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J
INSTRUCTION_FORMAT45cc_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA method_reference COMMA method_prototype
-> ^(I_STATEMENT_FORMAT45cc_METHOD[$start, "I_STATEMENT_FORMAT45cc_METHOD"] INSTRUCTION_FORMAT45cc_METHOD register_list method_reference method_prototype);
insn_format4rcc_method
: //e.g. invoke-polymorphic/range {v0,v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J
INSTRUCTION_FORMAT4rcc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA method_reference COMMA method_prototype
-> ^(I_STATEMENT_FORMAT4rcc_METHOD[$start, "I_STATEMENT_FORMAT4rcc_METHOD"] INSTRUCTION_FORMAT4rcc_METHOD register_range method_reference method_prototype);
insn_format51l insn_format51l
: //e.g. const-wide v0, 5000000000L : //e.g. const-wide v0, 5000000000L
INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal

View File

@ -62,6 +62,7 @@ import org.jf.dexlib2.immutable.ImmutableAnnotation;
import org.jf.dexlib2.immutable.ImmutableAnnotationElement; import org.jf.dexlib2.immutable.ImmutableAnnotationElement;
import org.jf.dexlib2.immutable.reference.ImmutableFieldReference; import org.jf.dexlib2.immutable.reference.ImmutableFieldReference;
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference; import org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
import org.jf.dexlib2.immutable.reference.ImmutableMethodProtoReference;
import org.jf.dexlib2.immutable.reference.ImmutableReference; import org.jf.dexlib2.immutable.reference.ImmutableReference;
import org.jf.dexlib2.immutable.reference.ImmutableTypeReference; import org.jf.dexlib2.immutable.reference.ImmutableTypeReference;
import org.jf.dexlib2.immutable.value.*; import org.jf.dexlib2.immutable.value.*;
@ -674,22 +675,6 @@ register_list returns[byte[\] registers, byte registerCount]
$registers[$registerCount++] = parseRegister_nibble($REGISTER.text); $registers[$registerCount++] = parseRegister_nibble($REGISTER.text);
})*); })*);
register_list4 returns[byte[\] registers, byte registerCount]
@init
{
$registers = new byte[4];
$registerCount = 0;
}
: ^(I_REGISTER_LIST
(REGISTER
{
if ($registerCount == 4) {
throw new SemanticException(input, $I_REGISTER_LIST, "A list4 of registers can only have a maximum of 4 " +
"registers. Use the <op>/range alternate opcode instead.");
}
$registers[$registerCount++] = parseRegister_nibble($REGISTER.text);
})*);
register_range returns[int startRegister, int endRegister] register_range returns[int startRegister, int endRegister]
: ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?) : ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?)
{ {
@ -742,8 +727,6 @@ instruction
| insn_format21c_field | insn_format21c_field
| insn_format21c_string | insn_format21c_string
| insn_format21c_type | insn_format21c_type
| insn_format21c_lambda
| insn_format21c_method
| insn_format21ih | insn_format21ih
| insn_format21lh | insn_format21lh
| insn_format21s | insn_format21s
@ -751,12 +734,10 @@ instruction
| insn_format22b | insn_format22b
| insn_format22c_field | insn_format22c_field
| insn_format22c_type | insn_format22c_type
| insn_format22c_string
| insn_format22s | insn_format22s
| insn_format22t | insn_format22t
| insn_format22x | insn_format22x
| insn_format23x | insn_format23x
| insn_format25x
| insn_format30t | insn_format30t
| insn_format31c | insn_format31c
| insn_format31i | insn_format31i
@ -766,6 +747,8 @@ instruction
| insn_format35c_type | insn_format35c_type
| insn_format3rc_method | insn_format3rc_method
| insn_format3rc_type | insn_format3rc_type
| insn_format45cc_method
| insn_format4rcc_method
| insn_format51l_type | insn_format51l_type
| insn_array_data_directive | insn_array_data_directive
| insn_packed_switch_directive | insn_packed_switch_directive
@ -881,30 +864,6 @@ insn_format21c_type
dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
}; };
insn_format21c_lambda
: //e.g. capture-variable v1, "foobar"
^(I_STATEMENT_FORMAT21c_LAMBDA INSTRUCTION_FORMAT21c_LAMBDA REGISTER string_literal)
{
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_LAMBDA.text);
short regA = parseRegister_byte($REGISTER.text);
$method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
dexBuilder.internStringReference($string_literal.value)));
};
insn_format21c_method
: //e.g. create-lambda v1, java/io/PrintStream/print(Ljava/lang/Stream;)V
^(I_STATEMENT_FORMAT21c_METHOD INSTRUCTION_FORMAT21c_METHOD REGISTER method_reference)
{
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_METHOD.text);
short regA = parseRegister_byte($REGISTER.text);
ImmutableMethodReference methodReference = $method_reference.methodReference;
$method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
dexBuilder.internMethodReference(methodReference)));
};
insn_format21ih insn_format21ih
: //e.g. const/high16 v1, 1234 : //e.g. const/high16 v1, 1234
^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal) ^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal)
@ -991,18 +950,6 @@ insn_format22c_type
dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
}; };
insn_format22c_string
: //e.g. liberate-variable v0, v1, "baz"
^(I_STATEMENT_FORMAT22c_STRING INSTRUCTION_FORMAT22c_STRING registerA=REGISTER registerB=REGISTER string_literal)
{
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22c_STRING.text);
byte regA = parseRegister_nibble($registerA.text);
byte regB = parseRegister_nibble($registerB.text);
$method::methodBuilder.addInstruction(new BuilderInstruction22c(opcode, regA, regB,
dexBuilder.internStringReference($string_literal.value)));
};
insn_format22s insn_format22s
: //e.g. add-int/lit16 v0, v1, 12345 : //e.g. add-int/lit16 v0, v1, 12345
^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal) ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal)
@ -1050,23 +997,6 @@ insn_format23x
$method::methodBuilder.addInstruction(new BuilderInstruction23x(opcode, regA, regB, regC)); $method::methodBuilder.addInstruction(new BuilderInstruction23x(opcode, regA, regB, regC));
}; };
insn_format25x
: //e.g. invoke-lambda vClosure, {vD, vE, vF, vG} -- up to 4 parameters + the closure.
^(I_STATEMENT_FORMAT25x INSTRUCTION_FORMAT25x REGISTER register_list4)
{
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT25x.text);
byte closureRegister = parseRegister_nibble($REGISTER.text);
//this depends on the fact that register_list4 returns a byte[4]
byte[] registers = $register_list4.registers;
int parameterRegisterCount = $register_list4.registerCount; // don't count closure register
$method::methodBuilder.addInstruction(new BuilderInstruction25x(opcode,
parameterRegisterCount, closureRegister, registers[0], registers[1],
registers[2], registers[3]));
};
insn_format30t insn_format30t
: //e.g. goto/32 endloop: : //e.g. goto/32 endloop:
^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t label_ref) ^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t label_ref)
@ -1181,6 +1111,47 @@ insn_format3rc_type
dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
}; };
insn_format45cc_method
: //e.g. invoke-polymorphic {v0, v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J
^(I_STATEMENT_FORMAT45cc_METHOD INSTRUCTION_FORMAT45cc_METHOD register_list method_reference method_prototype)
{
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT45cc_METHOD.text);
//this depends on the fact that register_list returns a byte[5]
byte[] registers = $register_list.registers;
byte registerCount = $register_list.registerCount;
ImmutableMethodReference methodReference = $method_reference.methodReference;
ImmutableMethodProtoReference methodProtoReference = new ImmutableMethodProtoReference(
$method_prototype.parameters,
$method_prototype.returnType);
$method::methodBuilder.addInstruction(new BuilderInstruction45cc(opcode, registerCount, registers[0], registers[1],
registers[2], registers[3], registers[4],
dexBuilder.internMethodReference(methodReference),
dexBuilder.internMethodProtoReference(methodProtoReference)));
};
insn_format4rcc_method
: //e.g. invoke-polymorphic {v0..v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J
^(I_STATEMENT_FORMAT4rcc_METHOD INSTRUCTION_FORMAT4rcc_METHOD register_range method_reference method_prototype)
{
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT4rcc_METHOD.text);
int startRegister = $register_range.startRegister;
int endRegister = $register_range.endRegister;
int registerCount = endRegister-startRegister+1;
ImmutableMethodReference methodReference = $method_reference.methodReference;
ImmutableMethodProtoReference methodProtoReference = new ImmutableMethodProtoReference(
$method_prototype.parameters,
$method_prototype.returnType);
$method::methodBuilder.addInstruction(new BuilderInstruction4rcc(opcode, startRegister, registerCount,
dexBuilder.internMethodReference(methodReference),
dexBuilder.internMethodProtoReference(methodProtoReference)));
};
insn_format51l_type insn_format51l_type
: //e.g. const-wide v0, 5000000000L : //e.g. const-wide v0, 5000000000L
^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal) ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal)

View File

@ -476,14 +476,6 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
return newToken(INSTRUCTION_FORMAT21c_TYPE); return newToken(INSTRUCTION_FORMAT21c_TYPE);
} }
"capture-variable" { // e.g. 'capture-variable vB, <string id>'
return newToken(INSTRUCTION_FORMAT21c_LAMBDA);
}
"create-lambda" { // e.g. 'create-lambda vClosure, <method id>'
return newToken(INSTRUCTION_FORMAT21c_METHOD);
}
"const/high16" { "const/high16" {
return newToken(INSTRUCTION_FORMAT21ih); return newToken(INSTRUCTION_FORMAT21ih);
} }
@ -515,14 +507,10 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
return newToken(INSTRUCTION_FORMAT22c_FIELD_ODEX); return newToken(INSTRUCTION_FORMAT22c_FIELD_ODEX);
} }
"instance-of" | "new-array" | "unbox-lambda" { "instance-of" | "new-array" {
return newToken(INSTRUCTION_FORMAT22c_TYPE); return newToken(INSTRUCTION_FORMAT22c_TYPE);
} }
"liberate-variable" {
return newToken(INSTRUCTION_FORMAT22c_STRING);
}
"iget-quick" | "iget-wide-quick" | "iget-object-quick" | "iput-quick" | "iput-wide-quick" | "iput-object-quick" | "iget-quick" | "iget-wide-quick" | "iget-object-quick" | "iput-quick" | "iput-wide-quick" | "iput-object-quick" |
"iput-boolean-quick" | "iput-byte-quick" | "iput-char-quick" | "iput-short-quick" { "iput-boolean-quick" | "iput-byte-quick" | "iput-char-quick" | "iput-short-quick" {
return newToken(INSTRUCTION_FORMAT22cs_FIELD); return newToken(INSTRUCTION_FORMAT22cs_FIELD);
@ -541,7 +529,7 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
return newToken(INSTRUCTION_FORMAT22t); return newToken(INSTRUCTION_FORMAT22t);
} }
"move/from16" | "move-wide/from16" | "move-object/from16" | "box-lambda" { "move/from16" | "move-wide/from16" | "move-object/from16" {
return newToken(INSTRUCTION_FORMAT22x); return newToken(INSTRUCTION_FORMAT22x);
} }
@ -555,10 +543,6 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
return newToken(INSTRUCTION_FORMAT23x); return newToken(INSTRUCTION_FORMAT23x);
} }
"invoke-lambda" { // e.g. invoke-lambda vClosure, {vD, vE, vF, vG} -- at most 4 params
return newToken(INSTRUCTION_FORMAT25x);
}
"goto/32" { "goto/32" {
return newToken(INSTRUCTION_FORMAT30t); return newToken(INSTRUCTION_FORMAT30t);
} }
@ -624,6 +608,14 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
return newToken(INSTRUCTION_FORMAT3rms_METHOD); return newToken(INSTRUCTION_FORMAT3rms_METHOD);
} }
"invoke-polymorphic" {
return newToken(INSTRUCTION_FORMAT45cc_METHOD);
}
"invoke-polymorphic/range" {
return newToken(INSTRUCTION_FORMAT4rcc_METHOD);
}
"const-wide" { "const-wide" {
return newToken(INSTRUCTION_FORMAT51l); return newToken(INSTRUCTION_FORMAT51l);
} }

View File

@ -1,32 +1,35 @@
/* /*
* [The "BSD licence"] * Copyright 2016, Google Inc.
* Copyright (c) 2010 Ben Gruver (JesusFreke)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions are
* are met: * met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * Redistributions of source code must retain the above copyright
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * notice, this list of conditions and the following disclaimer.
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * Redistributions in binary form must reproduce the above
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * copyright notice, this list of conditions and the following disclaimer
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * in the documentation and/or other materials provided with the
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * distribution.
* Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
import org.jf.smali.LiteralTools; package org.jf.smali;import org.jf.smali.LiteralTools;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;

View File

@ -1,18 +1,18 @@
/* /*
* Copyright 2014, Google Inc. * Copyright 2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
* met: * met:
* *
* * Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer * copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the * in the documentation and/or other materials provided with the
* distribution. * distribution.
* * Neither the name of Google Inc. nor the names of its * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from * contributors may be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
@ -29,7 +29,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
import com.google.common.collect.Lists; package org.jf.smali;import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import junit.framework.Assert; import junit.framework.Assert;
import org.antlr.runtime.RecognitionException; import org.antlr.runtime.RecognitionException;

View File

@ -1,32 +1,35 @@
/* /*
* [The "BSD licence"] * Copyright 2016, Google Inc.
* Copyright (c) 2010 Ben Gruver (JesusFreke)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions are
* are met: * met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * Redistributions of source code must retain the above copyright
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * notice, this list of conditions and the following disclaimer.
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * Redistributions in binary form must reproduce the above
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * copyright notice, this list of conditions and the following disclaimer
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * in the documentation and/or other materials provided with the
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * distribution.
* Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
import org.jf.smali.LiteralTools; package org.jf.smali;import org.jf.smali.LiteralTools;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;

View File

@ -1,39 +1,38 @@
/* /*
* [The "BSD licence"] * Copyright 2016, Google Inc.
* Copyright (c) 2010 Ben Gruver
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions are
* are met: * met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * Redistributions of source code must retain the above copyright
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * notice, this list of conditions and the following disclaimer.
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * Redistributions in binary form must reproduce the above
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * copyright notice, this list of conditions and the following disclaimer
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * in the documentation and/or other materials provided with the
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * distribution.
* Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
import org.antlr.runtime.ANTLRInputStream; package org.jf.smali;import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.CommonToken; import org.antlr.runtime.CommonToken;
import org.antlr.runtime.CommonTokenStream; import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException; import org.antlr.runtime.RecognitionException;
import org.jf.smali.expectedTokensTestGrammarLexer;
import org.jf.smali.expectedTokensTestGrammarParser;
import org.jf.smali.smaliFlexLexer;
import org.jf.smali.smaliParser;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -135,9 +134,9 @@ public class LexerTest {
String smaliFile = String.format("LexerTest%s%s.smali", File.separatorChar, test); String smaliFile = String.format("LexerTest%s%s.smali", File.separatorChar, test);
String tokensFile = String.format("LexerTest%s%s.tokens", File.separatorChar, test); String tokensFile = String.format("LexerTest%s%s.tokens", File.separatorChar, test);
expectedTokensTestGrammarLexer expectedTokensLexer = null; org.jf.smali.expectedTokensTestGrammarLexer expectedTokensLexer = null;
try { try {
expectedTokensLexer = new expectedTokensTestGrammarLexer(new ANTLRInputStream( expectedTokensLexer = new org.jf.smali.expectedTokensTestGrammarLexer(new ANTLRInputStream(
LexerTest.class.getClassLoader().getResourceAsStream(tokensFile))); LexerTest.class.getClassLoader().getResourceAsStream(tokensFile)));
} catch (IOException ex) { } catch (IOException ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
@ -145,8 +144,8 @@ public class LexerTest {
CommonTokenStream expectedTokensStream = new CommonTokenStream(expectedTokensLexer); CommonTokenStream expectedTokensStream = new CommonTokenStream(expectedTokensLexer);
expectedTokensTestGrammarParser expectedTokensParser = org.jf.smali.expectedTokensTestGrammarParser expectedTokensParser =
new expectedTokensTestGrammarParser(expectedTokensStream); new org.jf.smali.expectedTokensTestGrammarParser(expectedTokensStream);
try { try {
expectedTokensParser.top(); expectedTokensParser.top();
} catch (RecognitionException ex) { } catch (RecognitionException ex) {

View File

@ -1,32 +1,35 @@
/* /*
* [The "BSD licence"] * Copyright 2016, Google Inc.
* Copyright (c) 2010 Ben Gruver (JesusFreke)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions are
* are met: * met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * Redistributions of source code must retain the above copyright
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * notice, this list of conditions and the following disclaimer.
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * Redistributions in binary form must reproduce the above
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * copyright notice, this list of conditions and the following disclaimer
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * in the documentation and/or other materials provided with the
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * distribution.
* Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
import org.jf.smali.LiteralTools; package org.jf.smali;import org.jf.smali.LiteralTools;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;

View File

@ -1,32 +1,35 @@
/* /*
* [The "BSD licence"] * Copyright 2016, Google Inc.
* Copyright (c) 2010 Ben Gruver (JesusFreke)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions are
* are met: * met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * Redistributions of source code must retain the above copyright
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * notice, this list of conditions and the following disclaimer.
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * Redistributions in binary form must reproduce the above
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * copyright notice, this list of conditions and the following disclaimer
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * in the documentation and/or other materials provided with the
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * distribution.
* Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
import org.jf.smali.LiteralTools; package org.jf.smali;import org.jf.smali.LiteralTools;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;

View File

@ -85,8 +85,6 @@ const-string
check-cast check-cast
new-instance new-instance
const-class const-class
capture-variable
create-lambda
const/high16 const/high16
const-wide/high16 const-wide/high16
const/16 const/16
@ -125,8 +123,6 @@ iput-wide-volatile
iput-object-volatile iput-object-volatile
instance-of instance-of
new-array new-array
unbox-lambda
liberate-variable
iget-quick iget-quick
iget-wide-quick iget-wide-quick
iget-object-quick iget-object-quick
@ -153,7 +149,6 @@ if-le
move/from16 move/from16
move-wide/from16 move-wide/from16
move-object/from16 move-object/from16
box-lambda
cmpl-float cmpl-float
cmpg-float cmpg-float
cmpl-double cmpl-double
@ -204,7 +199,6 @@ add-double
sub-double sub-double
mul-double mul-double
div-double div-double
invoke-lambda
goto/32 goto/32
const-string/jumbo const-string/jumbo
const const

View File

@ -85,8 +85,6 @@ INSTRUCTION_FORMAT21c_STRING("const-string")
INSTRUCTION_FORMAT21c_TYPE("check-cast") INSTRUCTION_FORMAT21c_TYPE("check-cast")
INSTRUCTION_FORMAT21c_TYPE("new-instance") INSTRUCTION_FORMAT21c_TYPE("new-instance")
INSTRUCTION_FORMAT21c_TYPE("const-class") INSTRUCTION_FORMAT21c_TYPE("const-class")
INSTRUCTION_FORMAT21c_LAMBDA("capture-variable")
INSTRUCTION_FORMAT21c_METHOD("create-lambda")
INSTRUCTION_FORMAT21ih("const/high16") INSTRUCTION_FORMAT21ih("const/high16")
INSTRUCTION_FORMAT21lh("const-wide/high16") INSTRUCTION_FORMAT21lh("const-wide/high16")
INSTRUCTION_FORMAT21s("const/16") INSTRUCTION_FORMAT21s("const/16")
@ -125,8 +123,6 @@ INSTRUCTION_FORMAT22c_FIELD_ODEX("iput-wide-volatile")
INSTRUCTION_FORMAT22c_FIELD_ODEX("iput-object-volatile") INSTRUCTION_FORMAT22c_FIELD_ODEX("iput-object-volatile")
INSTRUCTION_FORMAT22c_TYPE("instance-of") INSTRUCTION_FORMAT22c_TYPE("instance-of")
INSTRUCTION_FORMAT22c_TYPE("new-array") INSTRUCTION_FORMAT22c_TYPE("new-array")
INSTRUCTION_FORMAT22c_TYPE("unbox-lambda")
INSTRUCTION_FORMAT22c_STRING("liberate-variable")
INSTRUCTION_FORMAT22cs_FIELD("iget-quick") INSTRUCTION_FORMAT22cs_FIELD("iget-quick")
INSTRUCTION_FORMAT22cs_FIELD("iget-wide-quick") INSTRUCTION_FORMAT22cs_FIELD("iget-wide-quick")
INSTRUCTION_FORMAT22cs_FIELD("iget-object-quick") INSTRUCTION_FORMAT22cs_FIELD("iget-object-quick")
@ -153,7 +149,6 @@ INSTRUCTION_FORMAT22t("if-le")
INSTRUCTION_FORMAT22x("move/from16") INSTRUCTION_FORMAT22x("move/from16")
INSTRUCTION_FORMAT22x("move-wide/from16") INSTRUCTION_FORMAT22x("move-wide/from16")
INSTRUCTION_FORMAT22x("move-object/from16") INSTRUCTION_FORMAT22x("move-object/from16")
INSTRUCTION_FORMAT22x("box-lambda")
INSTRUCTION_FORMAT23x("cmpl-float") INSTRUCTION_FORMAT23x("cmpl-float")
INSTRUCTION_FORMAT23x("cmpg-float") INSTRUCTION_FORMAT23x("cmpg-float")
INSTRUCTION_FORMAT23x("cmpl-double") INSTRUCTION_FORMAT23x("cmpl-double")
@ -204,7 +199,6 @@ INSTRUCTION_FORMAT23x("add-double")
INSTRUCTION_FORMAT23x("sub-double") INSTRUCTION_FORMAT23x("sub-double")
INSTRUCTION_FORMAT23x("mul-double") INSTRUCTION_FORMAT23x("mul-double")
INSTRUCTION_FORMAT23x("div-double") INSTRUCTION_FORMAT23x("div-double")
INSTRUCTION_FORMAT25x("invoke-lambda")
INSTRUCTION_FORMAT30t("goto/32") INSTRUCTION_FORMAT30t("goto/32")
INSTRUCTION_FORMAT31c("const-string/jumbo") INSTRUCTION_FORMAT31c("const-string/jumbo")
INSTRUCTION_FORMAT31i_OR_ID("const") INSTRUCTION_FORMAT31i_OR_ID("const")

View File

@ -93,7 +93,7 @@ if (!('idea' in gradle.startParameter.taskNames)) {
apply plugin: 'org.jetbrains.intellij' apply plugin: 'org.jetbrains.intellij'
intellij { intellij {
version 'IC-14.1.4' version 'IC-15.0.6'
pluginName 'smalidea' pluginName 'smalidea'
updateSinceUntilBuild false updateSinceUntilBuild false

View File

@ -1,81 +0,0 @@
/*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.smalidea.debugging;
import com.intellij.debugger.actions.StepOverActionHandler;
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.ui.JavaDebuggerSupport;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import com.intellij.xdebugger.impl.actions.DebuggerActionHandler;
import com.sun.jdi.request.StepRequest;
import org.jetbrains.annotations.NotNull;
public class SmaliDebuggerSupport extends JavaDebuggerSupport {
private static boolean useModifiedMethod;
static {
try {
DebuggerSession.class.getMethod("stepOver", boolean.class, int.class);
useModifiedMethod = true;
} catch (NoSuchMethodException ex) {
useModifiedMethod = false;
}
}
private final StepOverActionHandler myStepOverActionHandler = new StepOverActionHandler() {
@Override
public void perform(@NotNull final Project project, AnActionEvent e) {
final DebuggerSession session = getSession(project);
if (session != null) {
if (useModifiedMethod) {
session.stepOver(false, StepRequest.STEP_MIN);
} else {
session.stepOver(false);
}
}
}
@Override public boolean isEnabled(@NotNull Project project, AnActionEvent event) {
// TODO: check if we're currently in a smali file?
return super.isEnabled(project, event);
}
};
@NotNull
@Override
public DebuggerActionHandler getStepOverHandler() {
return myStepOverActionHandler;
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.smalidea.debugging;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.ContextUtil;
import com.intellij.debugger.engine.DebugProcessImpl.ResumeCommand;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.events.DebuggerCommandImpl;
import com.intellij.debugger.impl.JvmSteppingCommandProvider;
import com.sun.jdi.request.StepRequest;
import org.jetbrains.annotations.NotNull;
import org.jf.smalidea.SmaliLanguage;
public class SmaliSteppingCommandProvider extends JvmSteppingCommandProvider {
@Override
public ResumeCommand getStepOverCommand(@NotNull final SuspendContextImpl suspendContext, boolean ignoreBreakpoints,
int stepSize) {
final SourcePosition[] location = new SourcePosition[1];
suspendContext.getDebugProcess().getManagerThread().invokeAndWait(new DebuggerCommandImpl() {
@Override protected void action() throws Exception {
location[0] = ContextUtil.getSourcePosition(suspendContext);
}
}) ;
if (location[0] != null && location[0].getFile().getLanguage() == SmaliLanguage.INSTANCE) {
return suspendContext.getDebugProcess().createStepOverCommand(suspendContext, ignoreBreakpoints,
StepRequest.STEP_MIN);
}
return null;
}
}

View File

@ -102,13 +102,16 @@ public class LazyValue<T extends Value> implements Value {
} }
@Nullable @Nullable
private T getNullableValue() { protected T getNullableValue(boolean allowNull) {
if (value == null) { if (value == null) {
try { try {
if (evaluationContext == null) { if (evaluationContext == null) {
final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(project).getContext(); final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(project).getContext();
evaluationContext = debuggerContext.createEvaluationContext(); evaluationContext = debuggerContext.createEvaluationContext();
if (evaluationContext == null) { if (evaluationContext == null) {
if (!allowNull) {
throw new IllegalStateException("Can't create evaluation context");
}
return null; return null;
} }
} }
@ -116,6 +119,9 @@ public class LazyValue<T extends Value> implements Value {
value = SmaliCodeFragmentFactory.evaluateRegister(evaluationContext, method, registerNumber, type); value = SmaliCodeFragmentFactory.evaluateRegister(evaluationContext, method, registerNumber, type);
evaluationContext = null; evaluationContext = null;
} catch (EvaluateException ex) { } catch (EvaluateException ex) {
if (!allowNull) {
throw new IllegalStateException(ex);
}
return null; return null;
} }
} }
@ -124,7 +130,7 @@ public class LazyValue<T extends Value> implements Value {
@Nonnull @Nonnull
protected T getValue() { protected T getValue() {
T value = getNullableValue(); T value = getNullableValue(false);
assert value != null; assert value != null;
return value; return value;
} }
@ -154,7 +160,7 @@ public class LazyValue<T extends Value> implements Value {
} }
@Override public boolean equals(Object obj) { @Override public boolean equals(Object obj) {
Value value = getNullableValue(); Value value = getNullableValue(true);
if (value != null) { if (value != null) {
return value.equals(obj); return value.equals(obj);
} }
@ -162,7 +168,7 @@ public class LazyValue<T extends Value> implements Value {
} }
@Override public int hashCode() { @Override public int hashCode() {
Value value = getNullableValue(); Value value = getNullableValue(true);
if (value != null) { if (value != null) {
return value.hashCode(); return value.hashCode();
} }
@ -170,7 +176,7 @@ public class LazyValue<T extends Value> implements Value {
} }
@Override public String toString() { @Override public String toString() {
Value value = getNullableValue(); Value value = getNullableValue(true);
if (value != null) { if (value != null) {
return value.toString(); return value.toString();
} }

View File

@ -35,6 +35,8 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.debugger.SourcePosition; import com.intellij.debugger.SourcePosition;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.ItemPresentationProviders;
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*; import com.intellij.psi.*;
@ -86,6 +88,10 @@ public class SmaliClass extends SmaliStubBasedPsiElement<SmaliClassStub> impleme
return name.substring(lastDot+1); return name.substring(lastDot+1);
} }
@Override public ItemPresentation getPresentation() {
return ItemPresentationProviders.getItemPresentation(this);
}
@Nullable @Override public String getQualifiedName() { @Nullable @Override public String getQualifiedName() {
SmaliClassStatement classStatement = getStubOrPsiChild(SmaliElementTypes.CLASS_STATEMENT); SmaliClassStatement classStatement = getStubOrPsiChild(SmaliElementTypes.CLASS_STATEMENT);
if (classStatement == null) { if (classStatement == null) {

View File

@ -32,6 +32,7 @@
package org.jf.smalidea.util; package org.jf.smalidea.util;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.psi.*; import com.intellij.psi.*;
import com.intellij.psi.impl.ResolveScopeManager; import com.intellij.psi.impl.ResolveScopeManager;
@ -129,6 +130,10 @@ public class NameUtils {
public static PsiClass resolveSmaliType(@NotNull Project project, @NotNull GlobalSearchScope scope, public static PsiClass resolveSmaliType(@NotNull Project project, @NotNull GlobalSearchScope scope,
@NotNull String smaliType) { @NotNull String smaliType) {
if (DumbService.isDumb(project)) {
return null;
}
JavaPsiFacade facade = JavaPsiFacade.getInstance(project); JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
String javaType = NameUtils.smaliToJavaType(smaliType); String javaType = NameUtils.smaliToJavaType(smaliType);

View File

@ -12,7 +12,7 @@
]]> ]]>
</change-notes> </change-notes>
<idea-version since-build="131"/> <idea-version since-build="143"/>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<fileTypeFactory implementation="org.jf.smalidea.SmaliFileTypeFactory"/> <fileTypeFactory implementation="org.jf.smalidea.SmaliFileTypeFactory"/>
@ -23,8 +23,7 @@
<java.elementFinder implementation="org.jf.smalidea.psi.index.SmaliClassFinder"/> <java.elementFinder implementation="org.jf.smalidea.psi.index.SmaliClassFinder"/>
<stubIndex implementation="org.jf.smalidea.psi.index.SmaliClassNameIndex"/> <stubIndex implementation="org.jf.smalidea.psi.index.SmaliClassNameIndex"/>
<debugger.positionManagerFactory implementation="org.jf.smalidea.debugging.SmaliPositionManagerFactory"/> <debugger.positionManagerFactory implementation="org.jf.smalidea.debugging.SmaliPositionManagerFactory"/>
<xdebugger.debuggerSupport id="SmaliDebuggerSupport" order="first,before XDebuggerSupport" <debugger.jvmSteppingCommandProvider implementation="org.jf.smalidea.debugging.SmaliSteppingCommandProvider"/>
implementation="org.jf.smalidea.debugging.SmaliDebuggerSupport"/>
<debugger.codeFragmentFactory implementation="org.jf.smalidea.debugging.SmaliCodeFragmentFactory"/> <debugger.codeFragmentFactory implementation="org.jf.smalidea.debugging.SmaliCodeFragmentFactory"/>
<stubElementTypeHolder class="org.jf.smalidea.psi.SmaliElementTypes" /> <stubElementTypeHolder class="org.jf.smalidea.psi.SmaliElementTypes" />
<lang.findUsagesProvider language="smali" <lang.findUsagesProvider language="smali"

View File

@ -31,6 +31,7 @@
package org.jf.smalidea; package org.jf.smalidea;
import com.intellij.openapi.project.DumbServiceImpl;
import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl; import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.psi.JavaResolveResult; import com.intellij.psi.JavaResolveResult;
@ -66,6 +67,24 @@ public class ClassReferenceTest extends ResolveTestCase {
Assert.assertEquals("java.lang.Object", ((PsiClass)resolveResults[0].getElement()).getQualifiedName()); Assert.assertEquals("java.lang.Object", ((PsiClass)resolveResults[0].getElement()).getQualifiedName());
} }
/**
* Test a reference to a java class from a smali class, while in dumb mode
*/
public void testJavaReferenceFromSmaliInDumbMode() throws Exception {
SmaliClassTypeElement typeElement = (SmaliClassTypeElement)configureByFileText(
".class public Lblah; .super L<ref>java/lang/Object;", "blah.smali");
Assert.assertNotNull(typeElement);
Assert.assertEquals("Object", typeElement.getName());
DumbServiceImpl.getInstance(getProject()).setDumb(true);
PsiClass psiClass = typeElement.resolve();
Assert.assertNull(psiClass);
DumbServiceImpl.getInstance(getProject()).setDumb(false);
}
/** /**
* Test a reference to a smali class from a smali class * Test a reference to a smali class from a smali class
*/ */
@ -105,6 +124,8 @@ public class ClassReferenceTest extends ResolveTestCase {
Assert.assertEquals("blarg", smaliClass.getQualifiedName()); Assert.assertEquals("blarg", smaliClass.getQualifiedName());
} }
@Override @Override
protected Sdk getTestProjectJdk() { protected Sdk getTestProjectJdk() {
return JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk(); return JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();