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;
}
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
public boolean writeTo(IndentingWriter writer) throws IOException {
Opcode opcode = instruction.getOpcode();
String verificationErrorName = null;
String referenceString = null;
String referenceString2 = null;
boolean commentOutInstruction = false;
@ -100,25 +109,19 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
if (instruction instanceof ReferenceInstruction) {
ReferenceInstruction referenceInstruction = (ReferenceInstruction)instruction;
String classContext = null;
if (methodDef.classDef.options.implicitReferences) {
classContext = methodDef.method.getDefiningClass();
}
try {
Reference reference = referenceInstruction.getReference();
String classContext = null;
if (methodDef.classDef.options.implicitReferences) {
classContext = methodDef.method.getDefiningClass();
}
referenceString = ReferenceUtil.getReferenceString(reference, classContext);
assert referenceString != null;
} catch (InvalidItemIndex ex) {
writer.write("#");
writer.write(ex.getMessage());
writer.write("\n");
commentOutInstruction = true;
referenceString = String.format("%s@%d",
ReferenceType.toString(referenceInstruction.getReferenceType()),
ex.getInvalidIndex());
referenceString = writeInvalidItemIndex(ex, referenceInstruction.getReferenceType(),
writer);
} catch (ReferenceType.InvalidReferenceTypeException ex) {
writer.write("#invalid reference type: ");
writer.printSignedIntAsDec(ex.getReferenceType());
@ -126,6 +129,25 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
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) {
@ -308,11 +330,6 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
writer.write(", ");
writeThirdRegister(writer);
break;
case Format25x:
writeOpcode(writer);
writer.write(' ');
writeInvoke25xRegisters(writer); // vC, {vD, ...}
break;
case Format35c:
writeOpcode(writer);
writer.write(' ');
@ -355,6 +372,24 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
writer.write(", ");
writeVtableIndex(writer);
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:
assert false;
return false;
@ -438,43 +473,6 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
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 {
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'
version = '2.1.2'
version = '2.1.3'
if (!('release' in gradle.startParameter.taskNames)) {
def versionSuffix
@ -104,8 +104,7 @@ subprojects {
antlr_runtime: 'org.antlr:antlr-runtime:3.5.2',
antlr: 'org.antlr:antlr:3.5.2',
stringtemplate: 'org.antlr:stringtemplate:3.2.1',
jflex: 'de.jflex:jflex:1.4.3',
jflex_plugin: 'co.tomlee.gradle.plugins:gradle-jflex-plugin:0.0.2',
jflex_plugin: 'org.xbib.gradle.plugin:gradle-plugin-jflex:1.1.0',
proguard_gradle: 'net.sf.proguard:proguard-gradle:5.2.1',
dx: 'com.google.android.tools:dx:1.7',
gson: 'com.google.code.gson:gson:2.3.1',
@ -197,5 +196,5 @@ buildscript {
}
task wrapper(type: Wrapper) {
gradleVersion = '2.11'
gradleVersion = '2.14'
}

View File

@ -51,7 +51,6 @@ public enum Format {
Format22t(4),
Format22x(4),
Format23x(4),
Format25x(4),
Format30t(6),
Format31c(6),
Format31i(6),
@ -63,6 +62,8 @@ public enum Format {
Format3rc(6),
Format3rmi(6),
Format3rms(6),
Format45cc(8),
Format4rcc(8),
Format51l(10),
ArrayPayload(-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_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_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(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(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),
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),
ARRAY_PAYLOAD(0x300, "array-payload", ReferenceType.NONE, Format.ArrayPayload, 0),
// Reuse the deprecated f3-ff opcodes in Art:
INVOKE_LAMBDA(allArtVersions(0xf3),"invoke-lambda", ReferenceType.NONE, Format.Format25x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.EXPERIMENTAL),
// 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);
INVOKE_POLYMORPHIC(firstApi(0xfa, 26), "invoke-polymorphic", ReferenceType.METHOD, ReferenceType.METHOD_PROTO, Format.Format45cc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
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);
//if the instruction can throw an exception
public static final int CAN_THROW = 0x1;
@ -359,6 +352,7 @@ public enum Opcode
public final int referenceType;
public final Format format;
public final int flags;
public final int referenceType2;
Opcode(int opcodeValue, String opcodeName, int referenceType, Format format) {
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) {
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> artVersionToValueBuilder = ImmutableRangeMap.builder();
@ -385,6 +384,7 @@ public enum Opcode
this.artVersionToValueMap = artVersionToValueBuilder.build();
this.name = opcodeName;
this.referenceType = referenceType;
this.referenceType2 = referenceType2;
this.format = format;
this.flags = flags;
}

View File

@ -39,7 +39,8 @@ public final class ReferenceType {
public static final int TYPE = 1;
public static final int FIELD = 2;
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) {
switch (referenceType) {
@ -51,6 +52,8 @@ public final class ReferenceType {
return "field";
case METHOD:
return "method";
case METHOD_PROTO:
return "method_proto";
default:
throw new InvalidReferenceTypeException(referenceType);
}
@ -65,6 +68,8 @@ public final class ReferenceType {
return FIELD;
} else if (reference instanceof MethodReference) {
return METHOD;
} else if (reference instanceof MethodProtoReference) {
return METHOD_PROTO;
} else {
throw new IllegalStateException("Invalid reference");
}
@ -76,7 +81,7 @@ public final class ReferenceType {
* @throws InvalidReferenceTypeException
*/
public static void validateReferenceType(int referenceType) {
if (referenceType < 0 || referenceType > 3) {
if (referenceType < 0 || referenceType > 4) {
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.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.*;
import com.google.common.primitives.Ints;
import org.jf.dexlib2.AccessFlags;
import org.jf.dexlib2.analysis.util.TypeProtoUtils;
@ -71,6 +68,8 @@ public class ClassProto implements TypeProto {
protected boolean vtableFullyResolved = true;
protected boolean interfacesFullyResolved = true;
protected Set<String> unresolvedInterfaces = null;
public ClassProto(@Nonnull ClassPath classPath, @Nonnull String type) {
if (type.charAt(0) != 'L') {
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 =
Suppliers.memoize(new Supplier<LinkedHashMap<String, ClassDef>>() {
@Override public LinkedHashMap<String, ClassDef> get() {
Set<String> unresolvedInterfaces = new HashSet<String>(0);
LinkedHashMap<String, ClassDef> interfaces = Maps.newLinkedHashMap();
try {
@ -141,6 +141,7 @@ public class ClassProto implements TypeProto {
interfaces.put(interfaceType, interfaceDef);
} catch (UnresolvedClassException ex) {
interfaces.put(interfaceType, null);
unresolvedInterfaces.add(interfaceType);
interfacesFullyResolved = false;
}
@ -151,11 +152,13 @@ public class ClassProto implements TypeProto {
}
}
if (!interfaceProto.interfacesFullyResolved) {
unresolvedInterfaces.addAll(interfaceProto.getUnresolvedInterfaces());
interfacesFullyResolved = false;
}
}
}
} catch (UnresolvedClassException ex) {
unresolvedInterfaces.add(type);
interfacesFullyResolved = false;
}
@ -166,8 +169,8 @@ public class ClassProto implements TypeProto {
interfaces.put(getType(), null);
}
String superclass = getSuperclass();
try {
String superclass = getSuperclass();
if (superclass != null) {
ClassProto superclassProto = (ClassProto) classPath.getClass(superclass);
for (String superclassInterface: superclassProto.getInterfaces().keySet()) {
@ -176,17 +179,31 @@ public class ClassProto implements TypeProto {
}
}
if (!superclassProto.interfacesFullyResolved) {
unresolvedInterfaces.addAll(superclassProto.getUnresolvedInterfaces());
interfacesFullyResolved = false;
}
}
} catch (UnresolvedClassException ex) {
unresolvedInterfaces.add(superclass);
interfacesFullyResolved = false;
}
if (unresolvedInterfaces.size() > 0) {
ClassProto.this.unresolvedInterfaces = unresolvedInterfaces;
}
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.
*
@ -201,7 +218,8 @@ public class ClassProto implements TypeProto {
FluentIterable.from(getInterfaces().values()).filter(Predicates.notNull());
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;

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:
setInstruction(location, newBuilderInstruction23x((Instruction23x) instruction));
return;
case Format25x:
setInstruction(location, newBuilderInstruction25x((Instruction25x) instruction));
return;
case Format30t:
setInstruction(location, newBuilderInstruction30t(location.codeAddress,
codeAddressToIndex,
@ -871,18 +868,6 @@ public class MutableMethodImplementation implements MethodImplementation {
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
private BuilderInstruction3rc newBuilderInstruction3rc(@Nonnull Instruction3rc instruction) {
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,
@Nonnull Reference reference) {
super(opcode);
this.registerCount = Preconditions.check35cRegisterCount(registerCount);
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;

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

View File

@ -1,5 +1,5 @@
/*
* Copyright 2015, Google Inc.
* Copyright 2016, Google Inc.
* All rights reserved.
*
* 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.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 javax.annotation.Nonnull;
public class DexBackedInstruction25x extends DexBackedInstruction implements Instruction25x {
public DexBackedInstruction25x(@Nonnull DexBackedDexFile dexFile,
@Nonnull Opcode opcode,
int instructionStart) {
public class DexBackedInstruction45cc extends DexBackedInstruction implements Instruction45cc {
public DexBackedInstruction45cc(@Nonnull DexBackedDexFile dexFile,
@Nonnull Opcode opcode,
int instructionStart) {
super(dexFile, opcode, instructionStart);
}
@Override
public int getRegisterCount() {
return getParameterRegisterCount() + 1;
}
@Override
public int getParameterRegisterCount() {
@Override public int getRegisterCount() {
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1));
}
@Override
public int getRegisterFixedC() {
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 2));
public int getRegisterC() {
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 4));
}
@Override
public int getRegisterParameterD() {
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 2));
public int getRegisterD() {
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 4));
}
@Override
public int getRegisterParameterE() {
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 3));
public int getRegisterE() {
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 5));
}
@Override
public int getRegisterParameterF() {
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 3));
public int getRegisterF() {
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 5));
}
@Override
public int getRegisterParameterG() {
public int getRegisterG() {
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:
annotateInstruction10x(out, instruction);
break;
case Format25x:
annotateInstruction25x(out, (Instruction25x) instruction);
break;
case Format35c:
annotateInstruction35c(out, (Instruction35c)instruction);
break;
@ -285,30 +282,6 @@ public class CodeItem {
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) {
int startRegister = instruction.getStartRegister();
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);
case ReferenceType.FIELD:
return new DexBackedFieldReference(dexFile, referenceIndex);
case ReferenceType.METHOD_PROTO:
return new DexBackedMethodProtoReference(dexFile, referenceIndex);
default:
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);
ImmutableStartLocal startLocal =
new ImmutableStartLocal(codeAddress, register, name, type, null);
locals[register] = startLocal;
if (register >= 0 && register < locals.length) {
locals[register] = startLocal;
}
return startLocal;
}
case DebugItemType.START_LOCAL_EXTENDED: {
@ -192,13 +194,23 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
String signature = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
ImmutableStartLocal startLocal =
new ImmutableStartLocal(codeAddress, register, name, type, signature);
locals[register] = startLocal;
if (register >= 0 && register < locals.length) {
locals[register] = startLocal;
}
return startLocal;
}
case DebugItemType.END_LOCAL: {
int register = reader.readSmallUleb128();
LocalInfo localInfo = locals[register];
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) {
localInfo = EMPTY_LOCAL_INFO;
// 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: {
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 =
new ImmutableRestartLocal(codeAddress, register, localInfo.getName(),
localInfo.getType(), localInfo.getSignature());
locals[register] = restartLocal;
if (register >= 0 && register < locals.length) {
locals[register] = restartLocal;
}
return restartLocal;
}
case DebugItemType.PROLOGUE_END: {

View File

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

View File

@ -1,5 +1,5 @@
/*
* Copyright 2015, Google Inc.
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,7 +31,8 @@
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.
*
* 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.
*/
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 {
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());
}
public interface Instruction4rcc extends RegisterRangeInstruction, DualReferenceInstruction {
}

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);
case Format23x:
return ImmutableInstruction23x.of((Instruction23x)instruction);
case Format25x:
return ImmutableInstruction25x.of((Instruction25x) instruction);
case Format30t:
return ImmutableInstruction30t.of((Instruction30t)instruction);
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,
@Nonnull Reference reference) {
super(opcode);
this.registerCount = Preconditions.check35cRegisterCount(registerCount);
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;

View File

@ -58,7 +58,7 @@ public class ImmutableInstruction35mi extends ImmutableInstruction implements In
int registerG,
int inlineIndex) {
super(opcode);
this.registerCount = Preconditions.check35cRegisterCount(registerCount);
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;

View File

@ -58,7 +58,7 @@ public class ImmutableInstruction35ms extends ImmutableInstruction implements In
int registerG,
int vtableIndex) {
super(opcode);
this.registerCount = Preconditions.check35cRegisterCount(registerCount);
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;

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

View File

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

View File

@ -60,6 +60,17 @@ public final class ReferenceUtil {
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 {
writeMethodDescriptor(writer, methodReference, false);
}
@ -134,12 +145,16 @@ public final class ReferenceUtil {
if (reference instanceof FieldReference) {
FieldReference fieldReference = (FieldReference)reference;
boolean useImplicitReference = fieldReference.getDefiningClass().equals(containingClass);
return getFieldDescriptor((FieldReference)reference, useImplicitReference);
return getFieldDescriptor(fieldReference, useImplicitReference);
}
if (reference instanceof MethodReference) {
MethodReference methodReference = (MethodReference)reference;
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;
}

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

View File

@ -36,11 +36,14 @@ import com.google.common.primitives.Ints;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.Opcodes;
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.SwitchElement;
import org.jf.dexlib2.iface.instruction.formats.*;
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.Reference;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
import org.jf.util.ExceptionWithContext;
@ -51,25 +54,29 @@ import java.util.Comparator;
import java.util.List;
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 DexDataWriter writer;
@Nonnull private final StringSection<?, StringRef> stringSection;
@Nonnull private final TypeSection<?, ?, TypeRef> typeSection;
@Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
@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>
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey>
@Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, FieldRefKey extends FieldReference,
MethodRefKey extends MethodReference, ProtoRefKey extends MethodProtoReference>
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey>
makeInstructionWriter(
@Nonnull Opcodes opcodes,
@Nonnull DexDataWriter writer,
@Nonnull StringSection<?, StringRef> stringSection,
@Nonnull TypeSection<?, ?, TypeRef> typeSection,
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection) {
return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey>(
opcodes, writer, stringSection, typeSection, fieldSection, methodSection);
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection) {
return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey>(
opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection);
}
InstructionWriter(@Nonnull Opcodes opcodes,
@ -77,13 +84,15 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
@Nonnull StringSection<?, StringRef> stringSection,
@Nonnull TypeSection<?, ?, TypeRef> typeSection,
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection) {
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection) {
this.opcodes = opcodes;
this.writer = writer;
this.stringSection = stringSection;
this.typeSection = typeSection;
this.fieldSection = fieldSection;
this.methodSection = methodSection;
this.protoSection = protoSection;
}
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) {
try {
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) {
try {
writer.write(getOpcodeValue(instruction.getOpcode()));
@ -452,18 +473,29 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
}
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:
return fieldSection.getItemIndex((FieldRefKey)referenceInstruction.getReference());
return fieldSection.getItemIndex((FieldRefKey) reference);
case ReferenceType.METHOD:
return methodSection.getItemIndex((MethodRefKey)referenceInstruction.getReference());
return methodSection.getItemIndex((MethodRefKey) reference);
case ReferenceType.STRING:
return stringSection.getItemIndex((StringRef)referenceInstruction.getReference());
return stringSection.getItemIndex((StringRef) reference);
case ReferenceType.TYPE:
return typeSection.getItemIndex((TypeRef)referenceInstruction.getReference());
return typeSection.getItemIndex((TypeRef) reference);
case ReferenceType.METHOD_PROTO:
return protoSection.getItemIndex((ProtoRefKey) reference);
default:
throw new ExceptionWithContext("Unknown reference type: %d",
referenceInstruction.getOpcode().referenceType);
throw new ExceptionWithContext("Unknown reference type: %d", referenceType);
}
}
}

View File

@ -31,15 +31,17 @@
package org.jf.dexlib2.writer;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodReference;
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> {
@Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key);
@Nonnull ProtoKey getPrototype(@Nonnull MethodRefKey key);
@Nonnull ProtoKey getPrototype(@Nonnull MethodKey key);
@Nonnull ProtoRefKey getPrototype(@Nonnull MethodRefKey key);
@Nonnull ProtoRefKey getPrototype(@Nonnull MethodKey key);
@Nonnull StringKey getName(@Nonnull MethodRefKey key);
int getMethodIndex(@Nonnull MethodKey key);
}

View File

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

View File

@ -32,6 +32,8 @@
package org.jf.dexlib2.writer.builder;
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.util.CharSequenceUtils;
import org.jf.util.CollectionUtils;
@ -40,14 +42,15 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
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 BuilderTypeList parameterTypes;
@Nonnull final BuilderTypeReference returnType;
int index = DexWriter.NO_INDEX;
public BuilderProtoReference(@Nonnull BuilderStringReference shorty, @Nonnull BuilderTypeList parameterTypes,
@Nonnull BuilderTypeReference returnType) {
public BuilderMethodProtoReference(@Nonnull BuilderStringReference shorty, @Nonnull BuilderTypeList parameterTypes,
@Nonnull BuilderTypeReference returnType) {
this.shorty = shorty;
this.parameterTypes = parameterTypes;
this.returnType = returnType;
@ -62,25 +65,12 @@ public class BuilderProtoReference implements BuilderProtoPool.ProtoKey, Compara
}
@Override
public int hashCode() {
int hashCode = getReturnType().hashCode();
return hashCode*31 + getParameterTypes().hashCode();
public int getIndex() {
return index;
}
@Override
public boolean equals(@Nullable Object o) {
if (o != null && o instanceof BuilderProtoReference) {
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);
public void setIndex(int index) {
this.index = index;
}
}

View File

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

View File

@ -32,114 +32,75 @@
package org.jf.dexlib2.writer.builder;
import com.google.common.collect.Maps;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.immutable.reference.ImmutableMethodProtoReference;
import org.jf.dexlib2.util.MethodUtil;
import org.jf.dexlib2.writer.ProtoSection;
import org.jf.util.CharSequenceUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
class BuilderProtoPool
implements ProtoSection<BuilderStringReference, BuilderTypeReference, BuilderProtoReference, BuilderTypeList> {
implements ProtoSection<BuilderStringReference, BuilderTypeReference, BuilderMethodProtoReference, BuilderTypeList> {
@Nonnull private final BuilderContext context;
@Nonnull private final ConcurrentMap<ProtoKey, BuilderProtoReference> internedItems =
@Nonnull private final ConcurrentMap<MethodProtoReference, BuilderMethodProtoReference> internedItems =
Maps.newConcurrentMap();
BuilderProtoPool(@Nonnull BuilderContext context) {
this.context = context;
}
@Nonnull public BuilderProtoReference internProto(@Nonnull List<? extends CharSequence> parameters,
@Nonnull String returnType) {
ProtoKey key = new Key(parameters, returnType);
BuilderProtoReference ret = internedItems.get(key);
@Nonnull public BuilderMethodProtoReference internMethodProto(@Nonnull MethodProtoReference methodProto) {
BuilderMethodProtoReference ret = internedItems.get(methodProto);
if (ret != null) {
return ret;
}
BuilderProtoReference protoReference = new BuilderProtoReference(
context.stringPool.internString(MethodUtil.getShorty(parameters, returnType)),
context.typeListPool.internTypeList(parameters),
context.typePool.internType(returnType));
BuilderMethodProtoReference protoReference = new BuilderMethodProtoReference(
context.stringPool.internString(MethodUtil.getShorty(
methodProto.getParameterTypes(), methodProto.getReturnType())),
context.typeListPool.internTypeList(methodProto.getParameterTypes()),
context.typePool.internType(methodProto.getReturnType()));
ret = internedItems.putIfAbsent(protoReference, protoReference);
return ret==null?protoReference:ret;
}
@Nonnull public BuilderProtoReference internProto(@Nonnull MethodReference methodReference) {
return internProto(methodReference.getParameterTypes(), methodReference.getReturnType());
@Nonnull public BuilderMethodProtoReference internMethodProto(@Nonnull MethodReference methodReference) {
return internMethodProto(new ImmutableMethodProtoReference(
methodReference.getParameterTypes(), methodReference.getReturnType()));
}
@Nonnull @Override public BuilderStringReference getShorty(@Nonnull BuilderProtoReference key) {
return key.shorty;
@Nonnull @Override public BuilderStringReference getShorty(@Nonnull BuilderMethodProtoReference proto) {
return proto.shorty;
}
@Nonnull @Override public BuilderTypeReference getReturnType(@Nonnull BuilderProtoReference key) {
return key.returnType;
@Nonnull @Override public BuilderTypeReference getReturnType(@Nonnull BuilderMethodProtoReference proto) {
return proto.returnType;
}
@Nullable @Override public BuilderTypeList getParameters(@Nonnull BuilderProtoReference key) {
return key.parameterTypes;
@Nullable @Override public BuilderTypeList getParameters(@Nonnull BuilderMethodProtoReference proto) {
return proto.parameterTypes;
}
@Override public int getItemIndex(@Nonnull BuilderProtoReference key) {
return key.index;
@Override public int getItemIndex(@Nonnull BuilderMethodProtoReference proto) {
return proto.getIndex();
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderProtoReference, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderProtoReference>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderProtoReference key) {
@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;
}
@Override protected int setValue(@Nonnull BuilderProtoReference key, int value) {
@Override protected int setValue(@Nonnull BuilderMethodProtoReference key, int value) {
int prev = key.index;
key.index = value;
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;
public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringReference, BuilderTypeReference,
BuilderTypeReference, BuilderProtoReference, BuilderFieldReference, BuilderMethodReference,
BuilderTypeReference, BuilderMethodProtoReference, BuilderFieldReference, BuilderMethodReference,
BuilderClassDef, BuilderAnnotation, BuilderAnnotationSet, BuilderTypeList, BuilderField, BuilderMethod,
BuilderEncodedValue, BuilderAnnotationElement> {
@ -176,6 +176,10 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
return context.methodPool.internMethod(method);
}
@Nonnull public BuilderMethodProtoReference internMethodProtoReference(@Nonnull MethodProtoReference methodProto) {
return context.protoPool.internMethodProto(methodProto);
}
@Nonnull public BuilderReference internReference(@Nonnull Reference reference) {
if (reference instanceof StringReference) {
return internStringReference(((StringReference)reference).getString());
@ -189,6 +193,9 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
if (reference instanceof FieldReference) {
return internFieldReference((FieldReference)reference);
}
if (reference instanceof MethodProtoReference) {
return internMethodProtoReference((MethodProtoReference) 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.io.DexDataStore;
import org.jf.dexlib2.writer.io.FileDataStore;
import org.jf.dexlib2.writer.pool.ProtoPool.Key;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
@ -51,8 +50,8 @@ import java.io.IOException;
import java.util.Collection;
import java.util.Set;
public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference, Key,
FieldReference, MethodReference, PoolClassDef,
public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference,
MethodProtoReference, FieldReference, MethodReference, PoolClassDef,
Annotation, Set<? extends Annotation>,
TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
EncodedValue, AnnotationElement> {

View File

@ -31,13 +31,14 @@
package org.jf.dexlib2.writer.pool;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.writer.MethodSection;
import javax.annotation.Nonnull;
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 TypePool typePool;
@Nonnull private final ProtoPool protoPool;
@ -53,7 +54,7 @@ public class MethodPool extends BaseIndexPool<MethodReference>
Integer prev = internedItems.put(method, 0);
if (prev == null) {
typePool.intern(method.getDefiningClass());
protoPool.intern(method);
protoPool.intern(new PoolMethodProto(method));
stringPool.intern(method.getName());
}
}
@ -62,12 +63,12 @@ public class MethodPool extends BaseIndexPool<MethodReference>
return methodReference.getDefiningClass();
}
@Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull MethodReference methodReference) {
return new ProtoPool.Key(methodReference);
@Nonnull @Override public MethodProtoReference getPrototype(@Nonnull MethodReference methodReference) {
return new PoolMethodProto(methodReference);
}
@Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull PoolMethod poolMethod) {
return new ProtoPool.Key(poolMethod);
@Nonnull @Override public MethodProtoReference getPrototype(@Nonnull PoolMethod poolMethod) {
return new PoolMethodProto(poolMethod);
}
@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;
import com.google.common.collect.Ordering;
import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.iface.reference.MethodProtoReference;
import org.jf.dexlib2.util.MethodUtil;
import org.jf.dexlib2.writer.pool.ProtoPool.Key;
import org.jf.dexlib2.writer.ProtoSection;
import org.jf.util.CharSequenceUtils;
import org.jf.util.CollectionUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
public class ProtoPool extends BaseIndexPool<Key>
implements ProtoSection<CharSequence, CharSequence, Key, TypeListPool.Key<? extends Collection<? extends CharSequence>>> {
public class ProtoPool extends BaseIndexPool<MethodProtoReference>
implements ProtoSection<CharSequence, CharSequence, MethodProtoReference,
TypeListPool.Key<? extends Collection<? extends CharSequence>>> {
@Nonnull private final StringPool stringPool;
@Nonnull private final TypePool typePool;
@Nonnull private final TypeListPool typeListPool;
@ -57,78 +54,25 @@ public class ProtoPool extends BaseIndexPool<Key>
this.typeListPool = typeListPool;
}
public void intern(@Nonnull MethodReference method) {
// We can't use method directly, because it is likely a full MethodReference. We use a wrapper that computes
// hashCode and equals based only on the prototype fields
Key key = new Key(method);
Integer prev = internedItems.put(key, 0);
public void intern(@Nonnull MethodProtoReference reference) {
Integer prev = internedItems.put(reference, 0);
if (prev == null) {
stringPool.intern(key.getShorty());
typePool.intern(method.getReturnType());
typeListPool.intern(method.getParameterTypes());
stringPool.intern(getShorty(reference));
typePool.intern(reference.getReturnType());
typeListPool.intern(reference.getParameterTypes());
}
}
@Nonnull @Override public CharSequence getShorty(@Nonnull Key key) {
return key.getShorty();
@Nonnull @Override public CharSequence getShorty(@Nonnull MethodProtoReference reference) {
return MethodUtil.getShorty(reference.getParameterTypes(), reference.getReturnType());
}
@Nonnull @Override public CharSequence getReturnType(@Nonnull Key key) {
return key.getReturnType();
@Nonnull @Override public CharSequence getReturnType(@Nonnull MethodProtoReference protoReference) {
return protoReference.getReturnType();
}
@Nullable @Override public TypeListPool.Key<List<? extends CharSequence>> getParameters(@Nonnull Key key) {
return new TypeListPool.Key<List<? extends CharSequence>>(key.getParameters());
}
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());
}
@Nullable @Override public TypeListPool.Key<List<? extends CharSequence>> getParameters(
@Nonnull MethodProtoReference methodProto) {
return new TypeListPool.Key<List<? extends CharSequence>>(methodProto.getParameterTypes());
}
}

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
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
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
# 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
# Resolve links: $0 may be a link
PRG="$0"
@ -61,9 +56,9 @@ while [ -h "$PRG" ] ; do
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@ -114,6 +109,7 @@ fi
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
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
: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 "%@eval[2+2]" == "4" goto 4NT_args

View File

@ -30,7 +30,7 @@
*/
apply plugin: 'antlr'
apply plugin: 'jflex'
apply plugin: 'org.xbib.gradle.plugin.jflex'
buildscript {
repositories {
@ -46,10 +46,6 @@ configurations {
// Remove the full antlr library that's added by the antlr plugin. We manually
// add the smaller antlr_runtime library instead
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 {
@ -86,7 +82,6 @@ dependencies {
testCompile depends.junit
antlr depends.antlr
jflex depends.jflex
}
processResources.inputs.property('version', version)
@ -119,8 +114,8 @@ generateGrammarSource {
outputDirectory = new File(outputDirectory, 'org/jf/smali')
}
generateJFlexSource {
outputDirectory = new File(outputDirectory, 'org/jf/smali')
jflex {
generateDir = new File(generateDir, 'org/jf/smali')
}
uploadArchives {

View File

@ -86,8 +86,6 @@ tokens {
INSTRUCTION_FORMAT21c_FIELD_ODEX;
INSTRUCTION_FORMAT21c_STRING;
INSTRUCTION_FORMAT21c_TYPE;
INSTRUCTION_FORMAT21c_LAMBDA;
INSTRUCTION_FORMAT21c_METHOD;
INSTRUCTION_FORMAT21ih;
INSTRUCTION_FORMAT21lh;
INSTRUCTION_FORMAT21s;
@ -96,14 +94,12 @@ tokens {
INSTRUCTION_FORMAT22c_FIELD;
INSTRUCTION_FORMAT22c_FIELD_ODEX;
INSTRUCTION_FORMAT22c_TYPE;
INSTRUCTION_FORMAT22c_STRING;
INSTRUCTION_FORMAT22cs_FIELD;
INSTRUCTION_FORMAT22s;
INSTRUCTION_FORMAT22s_OR_ID;
INSTRUCTION_FORMAT22t;
INSTRUCTION_FORMAT22x;
INSTRUCTION_FORMAT23x;
INSTRUCTION_FORMAT25x;
INSTRUCTION_FORMAT30t;
INSTRUCTION_FORMAT31c;
INSTRUCTION_FORMAT31i;
@ -120,6 +116,8 @@ tokens {
INSTRUCTION_FORMAT3rc_TYPE;
INSTRUCTION_FORMAT3rmi_METHOD;
INSTRUCTION_FORMAT3rms_METHOD;
INSTRUCTION_FORMAT45cc_METHOD;
INSTRUCTION_FORMAT4rcc_METHOD;
INSTRUCTION_FORMAT51l;
LINE_COMMENT;
LINE_DIRECTIVE;
@ -210,8 +208,6 @@ tokens {
I_STATEMENT_FORMAT21c_TYPE;
I_STATEMENT_FORMAT21c_FIELD;
I_STATEMENT_FORMAT21c_STRING;
I_STATEMENT_FORMAT21c_LAMBDA;
I_STATEMENT_FORMAT21c_METHOD;
I_STATEMENT_FORMAT21ih;
I_STATEMENT_FORMAT21lh;
I_STATEMENT_FORMAT21s;
@ -219,12 +215,10 @@ tokens {
I_STATEMENT_FORMAT22b;
I_STATEMENT_FORMAT22c_FIELD;
I_STATEMENT_FORMAT22c_TYPE;
I_STATEMENT_FORMAT22c_STRING;
I_STATEMENT_FORMAT22s;
I_STATEMENT_FORMAT22t;
I_STATEMENT_FORMAT22x;
I_STATEMENT_FORMAT23x;
I_STATEMENT_FORMAT25x;
I_STATEMENT_FORMAT30t;
I_STATEMENT_FORMAT31c;
I_STATEMENT_FORMAT31i;
@ -234,6 +228,8 @@ tokens {
I_STATEMENT_FORMAT35c_TYPE;
I_STATEMENT_FORMAT3rc_METHOD;
I_STATEMENT_FORMAT3rc_TYPE;
I_STATEMENT_FORMAT45cc_METHOD;
I_STATEMENT_FORMAT4rcc_METHOD;
I_STATEMENT_FORMAT51l;
I_STATEMENT_ARRAY_DATA;
I_STATEMENT_PACKED_SWITCH;
@ -562,18 +558,14 @@ simple_name
| INSTRUCTION_FORMAT21c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD_ODEX]
| INSTRUCTION_FORMAT21c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_STRING]
| 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_FORMAT22c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD]
| INSTRUCTION_FORMAT22c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD_ODEX]
| 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_FORMAT22s_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT22s_OR_ID]
| INSTRUCTION_FORMAT22t -> SIMPLE_NAME[$INSTRUCTION_FORMAT22t]
| INSTRUCTION_FORMAT23x -> SIMPLE_NAME[$INSTRUCTION_FORMAT23x]
| INSTRUCTION_FORMAT25x -> SIMPLE_NAME[$INSTRUCTION_FORMAT25x]
| INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID]
| INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t]
| INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD]
@ -581,6 +573,8 @@ simple_name
| INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE]
| INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_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];
member_name
@ -817,8 +811,6 @@ instruction
| insn_format21c_field_odex
| insn_format21c_string
| insn_format21c_type
| insn_format21c_lambda
| insn_format21c_method
| insn_format21ih
| insn_format21lh
| insn_format21s
@ -827,13 +819,11 @@ instruction
| insn_format22c_field
| insn_format22c_field_odex
| insn_format22c_type
| insn_format22c_string
| insn_format22cs_field
| insn_format22s
| insn_format22t
| insn_format22x
| insn_format23x
| insn_format25x
| insn_format30t
| insn_format31c
| insn_format31i
@ -849,6 +839,8 @@ instruction
| insn_format3rc_type
| insn_format3rmi_method
| insn_format3rms_method
| insn_format45cc_method
| insn_format4rcc_method
| insn_format51l
| insn_array_data_directive
| insn_packed_switch_directive
@ -927,16 +919,6 @@ insn_format21c_type
INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA 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
: //e.g. const/high16 v1, 1234
INSTRUCTION_FORMAT21ih REGISTER COMMA fixed_32bit_literal
@ -982,11 +964,6 @@ insn_format22c_type
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);
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
: //e.g. iget-quick v0, v1, field@0xc
INSTRUCTION_FORMAT22cs_FIELD REGISTER COMMA REGISTER COMMA FIELD_OFFSET
@ -1014,11 +991,6 @@ insn_format23x
INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA 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
: //e.g. goto/32 endloop:
INSTRUCTION_FORMAT30t label_ref
@ -1106,6 +1078,16 @@ insn_format3rms_method
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
: //e.g. const-wide v0, 5000000000L
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.reference.ImmutableFieldReference;
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.ImmutableTypeReference;
import org.jf.dexlib2.immutable.value.*;
@ -674,22 +675,6 @@ register_list returns[byte[\] registers, byte registerCount]
$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]
: ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?)
{
@ -742,8 +727,6 @@ instruction
| insn_format21c_field
| insn_format21c_string
| insn_format21c_type
| insn_format21c_lambda
| insn_format21c_method
| insn_format21ih
| insn_format21lh
| insn_format21s
@ -751,12 +734,10 @@ instruction
| insn_format22b
| insn_format22c_field
| insn_format22c_type
| insn_format22c_string
| insn_format22s
| insn_format22t
| insn_format22x
| insn_format23x
| insn_format25x
| insn_format30t
| insn_format31c
| insn_format31i
@ -766,6 +747,8 @@ instruction
| insn_format35c_type
| insn_format3rc_method
| insn_format3rc_type
| insn_format45cc_method
| insn_format4rcc_method
| insn_format51l_type
| insn_array_data_directive
| insn_packed_switch_directive
@ -881,30 +864,6 @@ insn_format21c_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
: //e.g. const/high16 v1, 1234
^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal)
@ -991,18 +950,6 @@ insn_format22c_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
: //e.g. add-int/lit16 v0, v1, 12345
^(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));
};
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
: //e.g. goto/32 endloop:
^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t label_ref)
@ -1181,6 +1111,47 @@ insn_format3rc_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
: //e.g. const-wide v0, 5000000000L
^(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);
}
"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" {
return newToken(INSTRUCTION_FORMAT21ih);
}
@ -515,14 +507,10 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
return newToken(INSTRUCTION_FORMAT22c_FIELD_ODEX);
}
"instance-of" | "new-array" | "unbox-lambda" {
"instance-of" | "new-array" {
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" |
"iput-boolean-quick" | "iput-byte-quick" | "iput-char-quick" | "iput-short-quick" {
return newToken(INSTRUCTION_FORMAT22cs_FIELD);
@ -541,7 +529,7 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
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);
}
@ -555,10 +543,6 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
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" {
return newToken(INSTRUCTION_FORMAT30t);
}
@ -624,6 +608,14 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
return newToken(INSTRUCTION_FORMAT3rms_METHOD);
}
"invoke-polymorphic" {
return newToken(INSTRUCTION_FORMAT45cc_METHOD);
}
"invoke-polymorphic/range" {
return newToken(INSTRUCTION_FORMAT4rcc_METHOD);
}
"const-wide" {
return newToken(INSTRUCTION_FORMAT51l);
}

View File

@ -1,32 +1,35 @@
/*
* [The "BSD licence"]
* Copyright (c) 2010 Ben Gruver (JesusFreke)
* 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:
* 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.
* modification, are permitted provided that the following conditions are
* met:
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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,
* 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.
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* 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.Test;

View File

@ -1,18 +1,18 @@
/*
* Copyright 2014, Google Inc.
* 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
* 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
* 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
* 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.
*
@ -29,7 +29,7 @@
* 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 junit.framework.Assert;
import org.antlr.runtime.RecognitionException;

View File

@ -1,32 +1,35 @@
/*
* [The "BSD licence"]
* Copyright (c) 2010 Ben Gruver (JesusFreke)
* 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:
* 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.
* modification, are permitted provided that the following conditions are
* met:
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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,
* 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.
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* 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.Test;

View File

@ -1,39 +1,38 @@
/*
* [The "BSD licence"]
* Copyright (c) 2010 Ben Gruver
* 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:
* 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.
* modification, are permitted provided that the following conditions are
* met:
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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,
* 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.
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* 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.CommonTokenStream;
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.Test;
@ -135,9 +134,9 @@ public class LexerTest {
String smaliFile = String.format("LexerTest%s%s.smali", File.separatorChar, test);
String tokensFile = String.format("LexerTest%s%s.tokens", File.separatorChar, test);
expectedTokensTestGrammarLexer expectedTokensLexer = null;
org.jf.smali.expectedTokensTestGrammarLexer expectedTokensLexer = null;
try {
expectedTokensLexer = new expectedTokensTestGrammarLexer(new ANTLRInputStream(
expectedTokensLexer = new org.jf.smali.expectedTokensTestGrammarLexer(new ANTLRInputStream(
LexerTest.class.getClassLoader().getResourceAsStream(tokensFile)));
} catch (IOException ex) {
throw new RuntimeException(ex);
@ -145,8 +144,8 @@ public class LexerTest {
CommonTokenStream expectedTokensStream = new CommonTokenStream(expectedTokensLexer);
expectedTokensTestGrammarParser expectedTokensParser =
new expectedTokensTestGrammarParser(expectedTokensStream);
org.jf.smali.expectedTokensTestGrammarParser expectedTokensParser =
new org.jf.smali.expectedTokensTestGrammarParser(expectedTokensStream);
try {
expectedTokensParser.top();
} catch (RecognitionException ex) {

View File

@ -1,32 +1,35 @@
/*
* [The "BSD licence"]
* Copyright (c) 2010 Ben Gruver (JesusFreke)
* 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:
* 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.
* modification, are permitted provided that the following conditions are
* met:
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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,
* 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.
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* 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.Test;

View File

@ -1,32 +1,35 @@
/*
* [The "BSD licence"]
* Copyright (c) 2010 Ben Gruver (JesusFreke)
* 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:
* 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.
* modification, are permitted provided that the following conditions are
* met:
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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,
* 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.
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* 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.Test;

View File

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

View File

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

View File

@ -93,7 +93,7 @@ if (!('idea' in gradle.startParameter.taskNames)) {
apply plugin: 'org.jetbrains.intellij'
intellij {
version 'IC-14.1.4'
version 'IC-15.0.6'
pluginName 'smalidea'
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
private T getNullableValue() {
protected T getNullableValue(boolean allowNull) {
if (value == null) {
try {
if (evaluationContext == null) {
final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(project).getContext();
evaluationContext = debuggerContext.createEvaluationContext();
if (evaluationContext == null) {
if (!allowNull) {
throw new IllegalStateException("Can't create evaluation context");
}
return null;
}
}
@ -116,6 +119,9 @@ public class LazyValue<T extends Value> implements Value {
value = SmaliCodeFragmentFactory.evaluateRegister(evaluationContext, method, registerNumber, type);
evaluationContext = null;
} catch (EvaluateException ex) {
if (!allowNull) {
throw new IllegalStateException(ex);
}
return null;
}
}
@ -124,7 +130,7 @@ public class LazyValue<T extends Value> implements Value {
@Nonnull
protected T getValue() {
T value = getNullableValue();
T value = getNullableValue(false);
assert value != null;
return value;
}
@ -154,7 +160,7 @@ public class LazyValue<T extends Value> implements Value {
}
@Override public boolean equals(Object obj) {
Value value = getNullableValue();
Value value = getNullableValue(true);
if (value != null) {
return value.equals(obj);
}
@ -162,7 +168,7 @@ public class LazyValue<T extends Value> implements Value {
}
@Override public int hashCode() {
Value value = getNullableValue();
Value value = getNullableValue(true);
if (value != null) {
return value.hashCode();
}
@ -170,7 +176,7 @@ public class LazyValue<T extends Value> implements Value {
}
@Override public String toString() {
Value value = getNullableValue();
Value value = getNullableValue(true);
if (value != null) {
return value.toString();
}

View File

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

View File

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

View File

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

View File

@ -31,6 +31,7 @@
package org.jf.smalidea;
import com.intellij.openapi.project.DumbServiceImpl;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.psi.JavaResolveResult;
@ -66,6 +67,24 @@ public class ClassReferenceTest extends ResolveTestCase {
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
*/
@ -105,6 +124,8 @@ public class ClassReferenceTest extends ResolveTestCase {
Assert.assertEquals("blarg", smaliClass.getQualifiedName());
}
@Override
protected Sdk getTestProjectJdk() {
return JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();