mirror of
https://github.com/revanced/smali.git
synced 2025-05-04 08:34:25 +02:00
Merge branch 'master' into v2.2_WIP
This commit is contained in:
commit
3735d4778f
@ -79,11 +79,20 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
return opcode.isVolatileFieldAccessor() || opcode == Opcode.THROW_VERIFICATION_ERROR;
|
return opcode.isVolatileFieldAccessor() || opcode == Opcode.THROW_VERIFICATION_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String writeInvalidItemIndex(InvalidItemIndex ex, int type, IndentingWriter writer)
|
||||||
|
throws IOException {
|
||||||
|
writer.write("#");
|
||||||
|
writer.write(ex.getMessage());
|
||||||
|
writer.write("\n");
|
||||||
|
return String.format("%s@%d", ReferenceType.toString(type), ex.getInvalidIndex());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||||
Opcode opcode = instruction.getOpcode();
|
Opcode opcode = instruction.getOpcode();
|
||||||
String verificationErrorName = null;
|
String verificationErrorName = null;
|
||||||
String referenceString = null;
|
String referenceString = null;
|
||||||
|
String referenceString2 = null;
|
||||||
|
|
||||||
boolean commentOutInstruction = false;
|
boolean commentOutInstruction = false;
|
||||||
|
|
||||||
@ -100,25 +109,19 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
|
|
||||||
if (instruction instanceof ReferenceInstruction) {
|
if (instruction instanceof ReferenceInstruction) {
|
||||||
ReferenceInstruction referenceInstruction = (ReferenceInstruction)instruction;
|
ReferenceInstruction referenceInstruction = (ReferenceInstruction)instruction;
|
||||||
|
String classContext = null;
|
||||||
|
if (methodDef.classDef.options.implicitReferences) {
|
||||||
|
classContext = methodDef.method.getDefiningClass();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Reference reference = referenceInstruction.getReference();
|
Reference reference = referenceInstruction.getReference();
|
||||||
|
|
||||||
String classContext = null;
|
|
||||||
if (methodDef.classDef.options.implicitReferences) {
|
|
||||||
classContext = methodDef.method.getDefiningClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
referenceString = ReferenceUtil.getReferenceString(reference, classContext);
|
referenceString = ReferenceUtil.getReferenceString(reference, classContext);
|
||||||
assert referenceString != null;
|
assert referenceString != null;
|
||||||
} catch (InvalidItemIndex ex) {
|
} catch (InvalidItemIndex ex) {
|
||||||
writer.write("#");
|
|
||||||
writer.write(ex.getMessage());
|
|
||||||
writer.write("\n");
|
|
||||||
commentOutInstruction = true;
|
commentOutInstruction = true;
|
||||||
|
referenceString = writeInvalidItemIndex(ex, referenceInstruction.getReferenceType(),
|
||||||
referenceString = String.format("%s@%d",
|
writer);
|
||||||
ReferenceType.toString(referenceInstruction.getReferenceType()),
|
|
||||||
ex.getInvalidIndex());
|
|
||||||
} catch (ReferenceType.InvalidReferenceTypeException ex) {
|
} catch (ReferenceType.InvalidReferenceTypeException ex) {
|
||||||
writer.write("#invalid reference type: ");
|
writer.write("#invalid reference type: ");
|
||||||
writer.printSignedIntAsDec(ex.getReferenceType());
|
writer.printSignedIntAsDec(ex.getReferenceType());
|
||||||
@ -126,6 +129,25 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
|
|
||||||
referenceString = "invalid_reference";
|
referenceString = "invalid_reference";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instruction instanceof DualReferenceInstruction) {
|
||||||
|
DualReferenceInstruction dualReferenceInstruction =
|
||||||
|
(DualReferenceInstruction) instruction;
|
||||||
|
try {
|
||||||
|
Reference reference2 = dualReferenceInstruction.getReference2();
|
||||||
|
referenceString2 = ReferenceUtil.getReferenceString(reference2, classContext);
|
||||||
|
} catch (InvalidItemIndex ex) {
|
||||||
|
commentOutInstruction = true;
|
||||||
|
referenceString2 = writeInvalidItemIndex(ex,
|
||||||
|
dualReferenceInstruction.getReferenceType2(), writer);
|
||||||
|
} catch (ReferenceType.InvalidReferenceTypeException ex) {
|
||||||
|
writer.write("#invalid reference type: ");
|
||||||
|
writer.printSignedIntAsDec(ex.getReferenceType());
|
||||||
|
commentOutInstruction = true;
|
||||||
|
|
||||||
|
referenceString2 = "invalid_reference";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instruction instanceof Instruction31t) {
|
if (instruction instanceof Instruction31t) {
|
||||||
@ -308,11 +330,6 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writeThirdRegister(writer);
|
writeThirdRegister(writer);
|
||||||
break;
|
break;
|
||||||
case Format25x:
|
|
||||||
writeOpcode(writer);
|
|
||||||
writer.write(' ');
|
|
||||||
writeInvoke25xRegisters(writer); // vC, {vD, ...}
|
|
||||||
break;
|
|
||||||
case Format35c:
|
case Format35c:
|
||||||
writeOpcode(writer);
|
writeOpcode(writer);
|
||||||
writer.write(' ');
|
writer.write(' ');
|
||||||
@ -355,6 +372,24 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
writer.write(", ");
|
writer.write(", ");
|
||||||
writeVtableIndex(writer);
|
writeVtableIndex(writer);
|
||||||
break;
|
break;
|
||||||
|
case Format45cc:
|
||||||
|
writeOpcode(writer);
|
||||||
|
writer.write(' ');
|
||||||
|
writeInvokeRegisters(writer);
|
||||||
|
writer.write(", ");
|
||||||
|
writer.write(referenceString);
|
||||||
|
writer.write(", ");
|
||||||
|
writer.write(referenceString2);
|
||||||
|
break;
|
||||||
|
case Format4rcc:
|
||||||
|
writeOpcode(writer);
|
||||||
|
writer.write(' ');
|
||||||
|
writeInvokeRangeRegisters(writer);
|
||||||
|
writer.write(", ");
|
||||||
|
writer.write(referenceString);
|
||||||
|
writer.write(", ");
|
||||||
|
writer.write(referenceString2);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert false;
|
assert false;
|
||||||
return false;
|
return false;
|
||||||
@ -438,43 +473,6 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
|
|||||||
writer.write('}');
|
writer.write('}');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeInvoke25xRegisters(IndentingWriter writer) throws IOException {
|
|
||||||
OneFixedFourParameterRegisterInstruction instruction =
|
|
||||||
(OneFixedFourParameterRegisterInstruction)this.instruction;
|
|
||||||
final int parameterRegCount = instruction.getParameterRegisterCount();
|
|
||||||
|
|
||||||
writeRegister(writer, instruction.getRegisterFixedC()); // fixed register always present
|
|
||||||
|
|
||||||
writer.write(", {");
|
|
||||||
switch (parameterRegCount) {
|
|
||||||
case 1:
|
|
||||||
writeRegister(writer, instruction.getRegisterParameterD());
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
writeRegister(writer, instruction.getRegisterParameterD());
|
|
||||||
writer.write(", ");
|
|
||||||
writeRegister(writer, instruction.getRegisterParameterE());
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
writeRegister(writer, instruction.getRegisterParameterD());
|
|
||||||
writer.write(", ");
|
|
||||||
writeRegister(writer, instruction.getRegisterParameterE());
|
|
||||||
writer.write(", ");
|
|
||||||
writeRegister(writer, instruction.getRegisterParameterF());
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
writeRegister(writer, instruction.getRegisterParameterD());
|
|
||||||
writer.write(", ");
|
|
||||||
writeRegister(writer, instruction.getRegisterParameterE());
|
|
||||||
writer.write(", ");
|
|
||||||
writeRegister(writer, instruction.getRegisterParameterF());
|
|
||||||
writer.write(", ");
|
|
||||||
writeRegister(writer, instruction.getRegisterParameterG());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
writer.write('}');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException {
|
protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException {
|
||||||
RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction;
|
RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction;
|
||||||
|
|
||||||
|
54
baksmali/src/test/java/org/jf/baksmali/LargeLocalTest.java
Normal file
54
baksmali/src/test/java/org/jf/baksmali/LargeLocalTest.java
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
|
@ -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
|
@ -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
|
@ -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
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
|
|
||||||
version = '2.1.2'
|
version = '2.1.3'
|
||||||
|
|
||||||
if (!('release' in gradle.startParameter.taskNames)) {
|
if (!('release' in gradle.startParameter.taskNames)) {
|
||||||
def versionSuffix
|
def versionSuffix
|
||||||
@ -104,8 +104,7 @@ subprojects {
|
|||||||
antlr_runtime: 'org.antlr:antlr-runtime:3.5.2',
|
antlr_runtime: 'org.antlr:antlr-runtime:3.5.2',
|
||||||
antlr: 'org.antlr:antlr:3.5.2',
|
antlr: 'org.antlr:antlr:3.5.2',
|
||||||
stringtemplate: 'org.antlr:stringtemplate:3.2.1',
|
stringtemplate: 'org.antlr:stringtemplate:3.2.1',
|
||||||
jflex: 'de.jflex:jflex:1.4.3',
|
jflex_plugin: 'org.xbib.gradle.plugin:gradle-plugin-jflex:1.1.0',
|
||||||
jflex_plugin: 'co.tomlee.gradle.plugins:gradle-jflex-plugin:0.0.2',
|
|
||||||
proguard_gradle: 'net.sf.proguard:proguard-gradle:5.2.1',
|
proguard_gradle: 'net.sf.proguard:proguard-gradle:5.2.1',
|
||||||
dx: 'com.google.android.tools:dx:1.7',
|
dx: 'com.google.android.tools:dx:1.7',
|
||||||
gson: 'com.google.code.gson:gson:2.3.1',
|
gson: 'com.google.code.gson:gson:2.3.1',
|
||||||
@ -197,5 +196,5 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
task wrapper(type: Wrapper) {
|
task wrapper(type: Wrapper) {
|
||||||
gradleVersion = '2.11'
|
gradleVersion = '2.14'
|
||||||
}
|
}
|
@ -51,7 +51,6 @@ public enum Format {
|
|||||||
Format22t(4),
|
Format22t(4),
|
||||||
Format22x(4),
|
Format22x(4),
|
||||||
Format23x(4),
|
Format23x(4),
|
||||||
Format25x(4),
|
|
||||||
Format30t(6),
|
Format30t(6),
|
||||||
Format31c(6),
|
Format31c(6),
|
||||||
Format31i(6),
|
Format31i(6),
|
||||||
@ -63,6 +62,8 @@ public enum Format {
|
|||||||
Format3rc(6),
|
Format3rc(6),
|
||||||
Format3rmi(6),
|
Format3rmi(6),
|
||||||
Format3rms(6),
|
Format3rms(6),
|
||||||
|
Format45cc(8),
|
||||||
|
Format4rcc(8),
|
||||||
Format51l(10),
|
Format51l(10),
|
||||||
ArrayPayload(-1, true),
|
ArrayPayload(-1, true),
|
||||||
PackedSwitchPayload(-1, true),
|
PackedSwitchPayload(-1, true),
|
||||||
|
@ -294,8 +294,8 @@ public enum Opcode
|
|||||||
|
|
||||||
INVOKE_VIRTUAL_QUICK(combine(allApis(0xf8), allArtVersions(0xe9)), "invoke-virtual-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
INVOKE_VIRTUAL_QUICK(combine(allApis(0xf8), allArtVersions(0xe9)), "invoke-virtual-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||||
INVOKE_VIRTUAL_QUICK_RANGE(combine(allApis(0xf9), allArtVersions(0xea)), "invoke-virtual-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
INVOKE_VIRTUAL_QUICK_RANGE(combine(allApis(0xf9), allArtVersions(0xea)), "invoke-virtual-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||||
INVOKE_SUPER_QUICK(allApis(0xfa), "invoke-super-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
INVOKE_SUPER_QUICK(lastApi(0xfa, 25), "invoke-super-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||||
INVOKE_SUPER_QUICK_RANGE(allApis(0xfb), "invoke-super-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
INVOKE_SUPER_QUICK_RANGE(lastApi(0xfb, 25), "invoke-super-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||||
|
|
||||||
IPUT_OBJECT_VOLATILE(firstApi(0xfc, 9), "iput-object-volatile", ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
IPUT_OBJECT_VOLATILE(firstApi(0xfc, 9), "iput-object-volatile", ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
|
||||||
SGET_OBJECT_VOLATILE(firstApi(0xfd, 9), "sget-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.STATIC_FIELD_ACCESSOR),
|
SGET_OBJECT_VOLATILE(firstApi(0xfd, 9), "sget-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.STATIC_FIELD_ACCESSOR),
|
||||||
@ -305,15 +305,8 @@ public enum Opcode
|
|||||||
SPARSE_SWITCH_PAYLOAD(0x200, "sparse-switch-payload", ReferenceType.NONE, Format.SparseSwitchPayload, 0),
|
SPARSE_SWITCH_PAYLOAD(0x200, "sparse-switch-payload", ReferenceType.NONE, Format.SparseSwitchPayload, 0),
|
||||||
ARRAY_PAYLOAD(0x300, "array-payload", ReferenceType.NONE, Format.ArrayPayload, 0),
|
ARRAY_PAYLOAD(0x300, "array-payload", ReferenceType.NONE, Format.ArrayPayload, 0),
|
||||||
|
|
||||||
// Reuse the deprecated f3-ff opcodes in Art:
|
INVOKE_POLYMORPHIC(firstApi(0xfa, 26), "invoke-polymorphic", ReferenceType.METHOD, ReferenceType.METHOD_PROTO, Format.Format45cc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT),
|
||||||
INVOKE_LAMBDA(allArtVersions(0xf3),"invoke-lambda", ReferenceType.NONE, Format.Format25x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.EXPERIMENTAL),
|
INVOKE_POLYMORPHIC_RANGE(firstApi(0xfb, 26), "invoke-polymorphic/range", ReferenceType.METHOD, ReferenceType.METHOD_PROTO, Format.Format4rcc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT);
|
||||||
// TODO: What about JUMBO support if the string ID is too large?
|
|
||||||
CAPTURE_VARIABLE(allArtVersions(0xf5), "capture-variable", ReferenceType.STRING, Format.Format21c, Opcode.EXPERIMENTAL),
|
|
||||||
CREATE_LAMBDA(allArtVersions(0xf6), "create-lambda", ReferenceType.METHOD, Format.Format21c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL),
|
|
||||||
// TODO: do we need a capture/liberate wide?
|
|
||||||
LIBERATE_VARIABLE(allArtVersions(0xf7), "liberate-variable", ReferenceType.STRING, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL),
|
|
||||||
BOX_LAMBDA(allArtVersions(0xf8), "box-lambda", ReferenceType.NONE, Format.Format22x, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL),
|
|
||||||
UNBOX_LAMBDA(allArtVersions(0xf9), "unbox-lambda", ReferenceType.TYPE, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL);
|
|
||||||
|
|
||||||
//if the instruction can throw an exception
|
//if the instruction can throw an exception
|
||||||
public static final int CAN_THROW = 0x1;
|
public static final int CAN_THROW = 0x1;
|
||||||
@ -359,6 +352,7 @@ public enum Opcode
|
|||||||
public final int referenceType;
|
public final int referenceType;
|
||||||
public final Format format;
|
public final Format format;
|
||||||
public final int flags;
|
public final int flags;
|
||||||
|
public final int referenceType2;
|
||||||
|
|
||||||
Opcode(int opcodeValue, String opcodeName, int referenceType, Format format) {
|
Opcode(int opcodeValue, String opcodeName, int referenceType, Format format) {
|
||||||
this(opcodeValue, opcodeName, referenceType, format, 0);
|
this(opcodeValue, opcodeName, referenceType, format, 0);
|
||||||
@ -369,6 +363,11 @@ public enum Opcode
|
|||||||
}
|
}
|
||||||
|
|
||||||
Opcode(List<VersionConstraint> versionConstraints, String opcodeName, int referenceType, Format format, int flags) {
|
Opcode(List<VersionConstraint> versionConstraints, String opcodeName, int referenceType, Format format, int flags) {
|
||||||
|
this(versionConstraints, opcodeName, referenceType, -1, format, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
Opcode(List<VersionConstraint> versionConstraints, String opcodeName, int referenceType, int referenceType2,
|
||||||
|
Format format, int flags) {
|
||||||
ImmutableRangeMap.Builder<Integer, Short> apiToValueBuilder = ImmutableRangeMap.builder();
|
ImmutableRangeMap.Builder<Integer, Short> apiToValueBuilder = ImmutableRangeMap.builder();
|
||||||
ImmutableRangeMap.Builder<Integer, Short> artVersionToValueBuilder = ImmutableRangeMap.builder();
|
ImmutableRangeMap.Builder<Integer, Short> artVersionToValueBuilder = ImmutableRangeMap.builder();
|
||||||
|
|
||||||
@ -385,6 +384,7 @@ public enum Opcode
|
|||||||
this.artVersionToValueMap = artVersionToValueBuilder.build();
|
this.artVersionToValueMap = artVersionToValueBuilder.build();
|
||||||
this.name = opcodeName;
|
this.name = opcodeName;
|
||||||
this.referenceType = referenceType;
|
this.referenceType = referenceType;
|
||||||
|
this.referenceType2 = referenceType2;
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,8 @@ public final class ReferenceType {
|
|||||||
public static final int TYPE = 1;
|
public static final int TYPE = 1;
|
||||||
public static final int FIELD = 2;
|
public static final int FIELD = 2;
|
||||||
public static final int METHOD = 3;
|
public static final int METHOD = 3;
|
||||||
public static final int NONE = 4;
|
public static final int METHOD_PROTO = 4;
|
||||||
|
public static final int NONE = 5;
|
||||||
|
|
||||||
public static String toString(int referenceType) {
|
public static String toString(int referenceType) {
|
||||||
switch (referenceType) {
|
switch (referenceType) {
|
||||||
@ -51,6 +52,8 @@ public final class ReferenceType {
|
|||||||
return "field";
|
return "field";
|
||||||
case METHOD:
|
case METHOD:
|
||||||
return "method";
|
return "method";
|
||||||
|
case METHOD_PROTO:
|
||||||
|
return "method_proto";
|
||||||
default:
|
default:
|
||||||
throw new InvalidReferenceTypeException(referenceType);
|
throw new InvalidReferenceTypeException(referenceType);
|
||||||
}
|
}
|
||||||
@ -65,6 +68,8 @@ public final class ReferenceType {
|
|||||||
return FIELD;
|
return FIELD;
|
||||||
} else if (reference instanceof MethodReference) {
|
} else if (reference instanceof MethodReference) {
|
||||||
return METHOD;
|
return METHOD;
|
||||||
|
} else if (reference instanceof MethodProtoReference) {
|
||||||
|
return METHOD_PROTO;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Invalid reference");
|
throw new IllegalStateException("Invalid reference");
|
||||||
}
|
}
|
||||||
@ -76,7 +81,7 @@ public final class ReferenceType {
|
|||||||
* @throws InvalidReferenceTypeException
|
* @throws InvalidReferenceTypeException
|
||||||
*/
|
*/
|
||||||
public static void validateReferenceType(int referenceType) {
|
public static void validateReferenceType(int referenceType) {
|
||||||
if (referenceType < 0 || referenceType > 3) {
|
if (referenceType < 0 || referenceType > 4) {
|
||||||
throw new InvalidReferenceTypeException(referenceType);
|
throw new InvalidReferenceTypeException(referenceType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,7 @@ package org.jf.dexlib2.analysis;
|
|||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
import com.google.common.collect.FluentIterable;
|
import com.google.common.collect.*;
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
import org.jf.dexlib2.AccessFlags;
|
import org.jf.dexlib2.AccessFlags;
|
||||||
import org.jf.dexlib2.analysis.util.TypeProtoUtils;
|
import org.jf.dexlib2.analysis.util.TypeProtoUtils;
|
||||||
@ -71,6 +68,8 @@ public class ClassProto implements TypeProto {
|
|||||||
protected boolean vtableFullyResolved = true;
|
protected boolean vtableFullyResolved = true;
|
||||||
protected boolean interfacesFullyResolved = true;
|
protected boolean interfacesFullyResolved = true;
|
||||||
|
|
||||||
|
protected Set<String> unresolvedInterfaces = null;
|
||||||
|
|
||||||
public ClassProto(@Nonnull ClassPath classPath, @Nonnull String type) {
|
public ClassProto(@Nonnull ClassPath classPath, @Nonnull String type) {
|
||||||
if (type.charAt(0) != 'L') {
|
if (type.charAt(0) != 'L') {
|
||||||
throw new ExceptionWithContext("Cannot construct ClassProto for non reference type: %s", type);
|
throw new ExceptionWithContext("Cannot construct ClassProto for non reference type: %s", type);
|
||||||
@ -130,6 +129,7 @@ public class ClassProto implements TypeProto {
|
|||||||
private final Supplier<LinkedHashMap<String, ClassDef>> interfacesSupplier =
|
private final Supplier<LinkedHashMap<String, ClassDef>> interfacesSupplier =
|
||||||
Suppliers.memoize(new Supplier<LinkedHashMap<String, ClassDef>>() {
|
Suppliers.memoize(new Supplier<LinkedHashMap<String, ClassDef>>() {
|
||||||
@Override public LinkedHashMap<String, ClassDef> get() {
|
@Override public LinkedHashMap<String, ClassDef> get() {
|
||||||
|
Set<String> unresolvedInterfaces = new HashSet<String>(0);
|
||||||
LinkedHashMap<String, ClassDef> interfaces = Maps.newLinkedHashMap();
|
LinkedHashMap<String, ClassDef> interfaces = Maps.newLinkedHashMap();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -141,6 +141,7 @@ public class ClassProto implements TypeProto {
|
|||||||
interfaces.put(interfaceType, interfaceDef);
|
interfaces.put(interfaceType, interfaceDef);
|
||||||
} catch (UnresolvedClassException ex) {
|
} catch (UnresolvedClassException ex) {
|
||||||
interfaces.put(interfaceType, null);
|
interfaces.put(interfaceType, null);
|
||||||
|
unresolvedInterfaces.add(interfaceType);
|
||||||
interfacesFullyResolved = false;
|
interfacesFullyResolved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,11 +152,13 @@ public class ClassProto implements TypeProto {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!interfaceProto.interfacesFullyResolved) {
|
if (!interfaceProto.interfacesFullyResolved) {
|
||||||
|
unresolvedInterfaces.addAll(interfaceProto.getUnresolvedInterfaces());
|
||||||
interfacesFullyResolved = false;
|
interfacesFullyResolved = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (UnresolvedClassException ex) {
|
} catch (UnresolvedClassException ex) {
|
||||||
|
unresolvedInterfaces.add(type);
|
||||||
interfacesFullyResolved = false;
|
interfacesFullyResolved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,8 +169,8 @@ public class ClassProto implements TypeProto {
|
|||||||
interfaces.put(getType(), null);
|
interfaces.put(getType(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String superclass = getSuperclass();
|
||||||
try {
|
try {
|
||||||
String superclass = getSuperclass();
|
|
||||||
if (superclass != null) {
|
if (superclass != null) {
|
||||||
ClassProto superclassProto = (ClassProto) classPath.getClass(superclass);
|
ClassProto superclassProto = (ClassProto) classPath.getClass(superclass);
|
||||||
for (String superclassInterface: superclassProto.getInterfaces().keySet()) {
|
for (String superclassInterface: superclassProto.getInterfaces().keySet()) {
|
||||||
@ -176,17 +179,31 @@ public class ClassProto implements TypeProto {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!superclassProto.interfacesFullyResolved) {
|
if (!superclassProto.interfacesFullyResolved) {
|
||||||
|
unresolvedInterfaces.addAll(superclassProto.getUnresolvedInterfaces());
|
||||||
interfacesFullyResolved = false;
|
interfacesFullyResolved = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (UnresolvedClassException ex) {
|
} catch (UnresolvedClassException ex) {
|
||||||
|
unresolvedInterfaces.add(superclass);
|
||||||
interfacesFullyResolved = false;
|
interfacesFullyResolved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unresolvedInterfaces.size() > 0) {
|
||||||
|
ClassProto.this.unresolvedInterfaces = unresolvedInterfaces;
|
||||||
|
}
|
||||||
|
|
||||||
return interfaces;
|
return interfaces;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
protected Set<String> getUnresolvedInterfaces() {
|
||||||
|
if (unresolvedInterfaces == null) {
|
||||||
|
return ImmutableSet.of();
|
||||||
|
}
|
||||||
|
return unresolvedInterfaces;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the interfaces directly implemented by this class, or the interfaces they transitively implement.
|
* Gets the interfaces directly implemented by this class, or the interfaces they transitively implement.
|
||||||
*
|
*
|
||||||
@ -201,7 +218,8 @@ public class ClassProto implements TypeProto {
|
|||||||
FluentIterable.from(getInterfaces().values()).filter(Predicates.notNull());
|
FluentIterable.from(getInterfaces().values()).filter(Predicates.notNull());
|
||||||
|
|
||||||
if (!interfacesFullyResolved) {
|
if (!interfacesFullyResolved) {
|
||||||
throw new UnresolvedClassException("Interfaces for class %s not fully resolved", getType());
|
throw new UnresolvedClassException("Interfaces for class %s not fully resolved: %s", getType(),
|
||||||
|
String.join(",", getUnresolvedInterfaces()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return directInterfaces;
|
return directInterfaces;
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
@ -615,9 +615,6 @@ public class MutableMethodImplementation implements MethodImplementation {
|
|||||||
case Format23x:
|
case Format23x:
|
||||||
setInstruction(location, newBuilderInstruction23x((Instruction23x) instruction));
|
setInstruction(location, newBuilderInstruction23x((Instruction23x) instruction));
|
||||||
return;
|
return;
|
||||||
case Format25x:
|
|
||||||
setInstruction(location, newBuilderInstruction25x((Instruction25x) instruction));
|
|
||||||
return;
|
|
||||||
case Format30t:
|
case Format30t:
|
||||||
setInstruction(location, newBuilderInstruction30t(location.codeAddress,
|
setInstruction(location, newBuilderInstruction30t(location.codeAddress,
|
||||||
codeAddressToIndex,
|
codeAddressToIndex,
|
||||||
@ -871,18 +868,6 @@ public class MutableMethodImplementation implements MethodImplementation {
|
|||||||
instruction.getReference());
|
instruction.getReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private BuilderInstruction25x newBuilderInstruction25x(@Nonnull Instruction25x instruction) {
|
|
||||||
return new BuilderInstruction25x(
|
|
||||||
instruction.getOpcode(),
|
|
||||||
instruction.getParameterRegisterCount(),
|
|
||||||
instruction.getRegisterFixedC(),
|
|
||||||
instruction.getRegisterParameterD(),
|
|
||||||
instruction.getRegisterParameterE(),
|
|
||||||
instruction.getRegisterParameterF(),
|
|
||||||
instruction.getRegisterParameterG());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private BuilderInstruction3rc newBuilderInstruction3rc(@Nonnull Instruction3rc instruction) {
|
private BuilderInstruction3rc newBuilderInstruction3rc(@Nonnull Instruction3rc instruction) {
|
||||||
return new BuilderInstruction3rc(
|
return new BuilderInstruction3rc(
|
||||||
|
@ -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; }
|
|
||||||
}
|
|
@ -60,7 +60,7 @@ public class BuilderInstruction35c extends BuilderInstruction implements Instruc
|
|||||||
int registerG,
|
int registerG,
|
||||||
@Nonnull Reference reference) {
|
@Nonnull Reference reference) {
|
||||||
super(opcode);
|
super(opcode);
|
||||||
this.registerCount = Preconditions.check35cRegisterCount(registerCount);
|
this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
|
||||||
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
|
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
|
||||||
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
|
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
|
||||||
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
|
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
|
||||||
|
@ -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; }
|
||||||
|
}
|
@ -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; }
|
||||||
|
}
|
@ -115,8 +115,6 @@ public abstract class DexBackedInstruction implements Instruction {
|
|||||||
return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset);
|
return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset);
|
||||||
case Format23x:
|
case Format23x:
|
||||||
return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset);
|
return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset);
|
||||||
case Format25x:
|
|
||||||
return new DexBackedInstruction25x(dexFile, opcode, instructionStartOffset);
|
|
||||||
case Format30t:
|
case Format30t:
|
||||||
return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset);
|
return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset);
|
||||||
case Format31c:
|
case Format31c:
|
||||||
@ -139,6 +137,10 @@ public abstract class DexBackedInstruction implements Instruction {
|
|||||||
return new DexBackedInstruction3rmi(dexFile, opcode, instructionStartOffset);
|
return new DexBackedInstruction3rmi(dexFile, opcode, instructionStartOffset);
|
||||||
case Format3rms:
|
case Format3rms:
|
||||||
return new DexBackedInstruction3rms(dexFile, opcode, instructionStartOffset);
|
return new DexBackedInstruction3rms(dexFile, opcode, instructionStartOffset);
|
||||||
|
case Format45cc:
|
||||||
|
return new DexBackedInstruction45cc(dexFile, opcode, instructionStartOffset);
|
||||||
|
case Format4rcc:
|
||||||
|
return new DexBackedInstruction4rcc(dexFile, opcode, instructionStartOffset);
|
||||||
case Format51l:
|
case Format51l:
|
||||||
return new DexBackedInstruction51l(dexFile, opcode, instructionStartOffset);
|
return new DexBackedInstruction51l(dexFile, opcode, instructionStartOffset);
|
||||||
case PackedSwitchPayload:
|
case PackedSwitchPayload:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015, Google Inc.
|
* Copyright 2016, Google Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -33,51 +33,69 @@ package org.jf.dexlib2.dexbacked.instruction;
|
|||||||
|
|
||||||
import org.jf.dexlib2.Opcode;
|
import org.jf.dexlib2.Opcode;
|
||||||
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
|
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
|
||||||
import org.jf.dexlib2.iface.instruction.formats.Instruction25x;
|
import org.jf.dexlib2.dexbacked.reference.DexBackedReference;
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction45cc;
|
||||||
|
import org.jf.dexlib2.iface.reference.Reference;
|
||||||
import org.jf.util.NibbleUtils;
|
import org.jf.util.NibbleUtils;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class DexBackedInstruction25x extends DexBackedInstruction implements Instruction25x {
|
public class DexBackedInstruction45cc extends DexBackedInstruction implements Instruction45cc {
|
||||||
public DexBackedInstruction25x(@Nonnull DexBackedDexFile dexFile,
|
public DexBackedInstruction45cc(@Nonnull DexBackedDexFile dexFile,
|
||||||
@Nonnull Opcode opcode,
|
@Nonnull Opcode opcode,
|
||||||
int instructionStart) {
|
int instructionStart) {
|
||||||
super(dexFile, opcode, instructionStart);
|
super(dexFile, opcode, instructionStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public int getRegisterCount() {
|
||||||
public int getRegisterCount() {
|
|
||||||
return getParameterRegisterCount() + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getParameterRegisterCount() {
|
|
||||||
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1));
|
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRegisterFixedC() {
|
public int getRegisterC() {
|
||||||
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 2));
|
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRegisterParameterD() {
|
public int getRegisterD() {
|
||||||
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 2));
|
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRegisterParameterE() {
|
public int getRegisterE() {
|
||||||
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 3));
|
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRegisterParameterF() {
|
public int getRegisterF() {
|
||||||
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 3));
|
return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRegisterParameterG() {
|
public int getRegisterG() {
|
||||||
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 1));
|
return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Reference getReference() {
|
||||||
|
return DexBackedReference.makeReference(dexFile, opcode.referenceType,
|
||||||
|
dexFile.readUshort(instructionStart + 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getReferenceType() {
|
||||||
|
return opcode.referenceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Reference getReference2() {
|
||||||
|
return DexBackedReference.makeReference(dexFile, opcode.referenceType2,
|
||||||
|
dexFile.readUshort(instructionStart + 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getReferenceType2() {
|
||||||
|
return opcode.referenceType2;
|
||||||
|
}
|
||||||
}
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -129,9 +129,6 @@ public class CodeItem {
|
|||||||
case Format10x:
|
case Format10x:
|
||||||
annotateInstruction10x(out, instruction);
|
annotateInstruction10x(out, instruction);
|
||||||
break;
|
break;
|
||||||
case Format25x:
|
|
||||||
annotateInstruction25x(out, (Instruction25x) instruction);
|
|
||||||
break;
|
|
||||||
case Format35c:
|
case Format35c:
|
||||||
annotateInstruction35c(out, (Instruction35c)instruction);
|
annotateInstruction35c(out, (Instruction35c)instruction);
|
||||||
break;
|
break;
|
||||||
@ -285,30 +282,6 @@ public class CodeItem {
|
|||||||
instruction.getOpcode().name, Joiner.on(", ").join(args), reference));
|
instruction.getOpcode().name, Joiner.on(", ").join(args), reference));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void annotateInstruction25x(@Nonnull AnnotatedBytes out,
|
|
||||||
@Nonnull Instruction25x instruction) {
|
|
||||||
List<String> args = Lists.newArrayList();
|
|
||||||
|
|
||||||
int registerCount = instruction.getRegisterCount(); //at least 1.
|
|
||||||
if (registerCount == 2) {
|
|
||||||
args.add(formatRegister(instruction.getRegisterParameterD()));
|
|
||||||
} else if (registerCount == 3) {
|
|
||||||
args.add(formatRegister(instruction.getRegisterParameterD()));
|
|
||||||
args.add(formatRegister(instruction.getRegisterParameterE()));
|
|
||||||
} else if (registerCount == 4) {
|
|
||||||
args.add(formatRegister(instruction.getRegisterParameterD()));
|
|
||||||
args.add(formatRegister(instruction.getRegisterParameterE()));
|
|
||||||
args.add(formatRegister(instruction.getRegisterParameterF()));
|
|
||||||
} else if (registerCount == 5) {
|
|
||||||
args.add(formatRegister(instruction.getRegisterParameterD()));
|
|
||||||
args.add(formatRegister(instruction.getRegisterParameterE()));
|
|
||||||
args.add(formatRegister(instruction.getRegisterParameterF()));
|
|
||||||
args.add(formatRegister(instruction.getRegisterParameterG()));
|
|
||||||
}
|
|
||||||
out.annotate(6, String.format("%s %s, {%s}",
|
|
||||||
instruction.getOpcode().name, instruction.getRegisterFixedC(), Joiner.on(", ").join(args)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) {
|
private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) {
|
||||||
int startRegister = instruction.getStartRegister();
|
int startRegister = instruction.getStartRegister();
|
||||||
int endRegister = startRegister + instruction.getRegisterCount() - 1;
|
int endRegister = startRegister + instruction.getRegisterCount() - 1;
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,8 @@ public abstract class DexBackedReference {
|
|||||||
return new DexBackedMethodReference(dexFile, referenceIndex);
|
return new DexBackedMethodReference(dexFile, referenceIndex);
|
||||||
case ReferenceType.FIELD:
|
case ReferenceType.FIELD:
|
||||||
return new DexBackedFieldReference(dexFile, referenceIndex);
|
return new DexBackedFieldReference(dexFile, referenceIndex);
|
||||||
|
case ReferenceType.METHOD_PROTO:
|
||||||
|
return new DexBackedMethodProtoReference(dexFile, referenceIndex);
|
||||||
default:
|
default:
|
||||||
throw new ExceptionWithContext("Invalid reference type: %d", referenceType);
|
throw new ExceptionWithContext("Invalid reference type: %d", referenceType);
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,9 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
|
|||||||
String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1);
|
String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1);
|
||||||
ImmutableStartLocal startLocal =
|
ImmutableStartLocal startLocal =
|
||||||
new ImmutableStartLocal(codeAddress, register, name, type, null);
|
new ImmutableStartLocal(codeAddress, register, name, type, null);
|
||||||
locals[register] = startLocal;
|
if (register >= 0 && register < locals.length) {
|
||||||
|
locals[register] = startLocal;
|
||||||
|
}
|
||||||
return startLocal;
|
return startLocal;
|
||||||
}
|
}
|
||||||
case DebugItemType.START_LOCAL_EXTENDED: {
|
case DebugItemType.START_LOCAL_EXTENDED: {
|
||||||
@ -192,13 +194,23 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
|
|||||||
String signature = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
|
String signature = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
|
||||||
ImmutableStartLocal startLocal =
|
ImmutableStartLocal startLocal =
|
||||||
new ImmutableStartLocal(codeAddress, register, name, type, signature);
|
new ImmutableStartLocal(codeAddress, register, name, type, signature);
|
||||||
locals[register] = startLocal;
|
if (register >= 0 && register < locals.length) {
|
||||||
|
locals[register] = startLocal;
|
||||||
|
}
|
||||||
return startLocal;
|
return startLocal;
|
||||||
}
|
}
|
||||||
case DebugItemType.END_LOCAL: {
|
case DebugItemType.END_LOCAL: {
|
||||||
int register = reader.readSmallUleb128();
|
int register = reader.readSmallUleb128();
|
||||||
LocalInfo localInfo = locals[register];
|
|
||||||
boolean replaceLocalInTable = true;
|
boolean replaceLocalInTable = true;
|
||||||
|
LocalInfo localInfo;
|
||||||
|
if (register >= 0 && register < locals.length) {
|
||||||
|
localInfo = locals[register];
|
||||||
|
} else {
|
||||||
|
localInfo = EMPTY_LOCAL_INFO;
|
||||||
|
replaceLocalInTable = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (localInfo instanceof EndLocal) {
|
if (localInfo instanceof EndLocal) {
|
||||||
localInfo = EMPTY_LOCAL_INFO;
|
localInfo = EMPTY_LOCAL_INFO;
|
||||||
// don't replace the local info in locals. The new EndLocal won't have any info at all,
|
// don't replace the local info in locals. The new EndLocal won't have any info at all,
|
||||||
@ -216,11 +228,18 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
|
|||||||
}
|
}
|
||||||
case DebugItemType.RESTART_LOCAL: {
|
case DebugItemType.RESTART_LOCAL: {
|
||||||
int register = reader.readSmallUleb128();
|
int register = reader.readSmallUleb128();
|
||||||
LocalInfo localInfo = locals[register];
|
LocalInfo localInfo;
|
||||||
|
if (register >= 0 && register < locals.length) {
|
||||||
|
localInfo = locals[register];
|
||||||
|
} else {
|
||||||
|
localInfo = EMPTY_LOCAL_INFO;
|
||||||
|
}
|
||||||
ImmutableRestartLocal restartLocal =
|
ImmutableRestartLocal restartLocal =
|
||||||
new ImmutableRestartLocal(codeAddress, register, localInfo.getName(),
|
new ImmutableRestartLocal(codeAddress, register, localInfo.getName(),
|
||||||
localInfo.getType(), localInfo.getSignature());
|
localInfo.getType(), localInfo.getSignature());
|
||||||
locals[register] = restartLocal;
|
if (register >= 0 && register < locals.length) {
|
||||||
|
locals[register] = restartLocal;
|
||||||
|
}
|
||||||
return restartLocal;
|
return restartLocal;
|
||||||
}
|
}
|
||||||
case DebugItemType.PROLOGUE_END: {
|
case DebugItemType.PROLOGUE_END: {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015, Google Inc.
|
* Copyright 2016, Google Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -31,17 +31,11 @@
|
|||||||
|
|
||||||
package org.jf.dexlib2.iface.instruction;
|
package org.jf.dexlib2.iface.instruction;
|
||||||
|
|
||||||
public interface OneFixedFourParameterRegisterInstruction extends VariableRegisterInstruction {
|
import org.jf.dexlib2.iface.reference.Reference;
|
||||||
int getRegisterFixedC();
|
|
||||||
int getRegisterParameterD();
|
|
||||||
int getRegisterParameterE();
|
|
||||||
int getRegisterParameterF();
|
|
||||||
int getRegisterParameterG();
|
|
||||||
|
|
||||||
/** Returns the count of just the parameter register counts; in range of [0, 4] */
|
import javax.annotation.Nonnull;
|
||||||
int getParameterRegisterCount();
|
|
||||||
|
|
||||||
/** Includes the total sum of both fixed and parameter register counts; at least 1 */
|
public interface DualReferenceInstruction extends ReferenceInstruction {
|
||||||
@Override
|
@Nonnull Reference getReference2();
|
||||||
int getRegisterCount();
|
int getReferenceType2();
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015, Google Inc.
|
* Copyright 2016, Google Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -31,7 +31,8 @@
|
|||||||
|
|
||||||
package org.jf.dexlib2.iface.instruction.formats;
|
package org.jf.dexlib2.iface.instruction.formats;
|
||||||
|
|
||||||
import org.jf.dexlib2.iface.instruction.OneFixedFourParameterRegisterInstruction;
|
import org.jf.dexlib2.iface.instruction.DualReferenceInstruction;
|
||||||
|
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction;
|
||||||
|
|
||||||
public interface Instruction25x extends OneFixedFourParameterRegisterInstruction {
|
public interface Instruction45cc extends FiveRegisterInstruction, DualReferenceInstruction {
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015, Google Inc.
|
* Copyright 2016, Google Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -29,21 +29,10 @@
|
|||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jf.baksmali;
|
package org.jf.dexlib2.iface.instruction.formats;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.jf.dexlib2.iface.instruction.DualReferenceInstruction;
|
||||||
|
import org.jf.dexlib2.iface.instruction.RegisterRangeInstruction;
|
||||||
|
|
||||||
public class LambdaTest extends IdenticalRoundtripTest {
|
public interface Instruction4rcc extends RegisterRangeInstruction, DualReferenceInstruction {
|
||||||
|
|
||||||
private BaksmaliOptions createOptions() {
|
|
||||||
BaksmaliOptions options = new BaksmaliOptions();
|
|
||||||
options.apiLevel = 23; // since we need at least level 23 for lambda opcodes
|
|
||||||
options.experimentalOpcodes = true; // since these opcodes aren't implemented in runtime yet);
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHelloWorldLambda() {
|
|
||||||
runTest("HelloWorldLambda", createOptions());
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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);
|
||||||
|
}
|
@ -97,8 +97,6 @@ public abstract class ImmutableInstruction implements Instruction {
|
|||||||
return ImmutableInstruction22x.of((Instruction22x)instruction);
|
return ImmutableInstruction22x.of((Instruction22x)instruction);
|
||||||
case Format23x:
|
case Format23x:
|
||||||
return ImmutableInstruction23x.of((Instruction23x)instruction);
|
return ImmutableInstruction23x.of((Instruction23x)instruction);
|
||||||
case Format25x:
|
|
||||||
return ImmutableInstruction25x.of((Instruction25x) instruction);
|
|
||||||
case Format30t:
|
case Format30t:
|
||||||
return ImmutableInstruction30t.of((Instruction30t)instruction);
|
return ImmutableInstruction30t.of((Instruction30t)instruction);
|
||||||
case Format31c:
|
case Format31c:
|
||||||
|
@ -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; }
|
|
||||||
}
|
|
@ -61,7 +61,7 @@ public class ImmutableInstruction35c extends ImmutableInstruction implements Ins
|
|||||||
int registerG,
|
int registerG,
|
||||||
@Nonnull Reference reference) {
|
@Nonnull Reference reference) {
|
||||||
super(opcode);
|
super(opcode);
|
||||||
this.registerCount = Preconditions.check35cRegisterCount(registerCount);
|
this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
|
||||||
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
|
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
|
||||||
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
|
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
|
||||||
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
|
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
|
||||||
|
@ -58,7 +58,7 @@ public class ImmutableInstruction35mi extends ImmutableInstruction implements In
|
|||||||
int registerG,
|
int registerG,
|
||||||
int inlineIndex) {
|
int inlineIndex) {
|
||||||
super(opcode);
|
super(opcode);
|
||||||
this.registerCount = Preconditions.check35cRegisterCount(registerCount);
|
this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
|
||||||
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
|
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
|
||||||
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
|
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
|
||||||
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
|
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
|
||||||
|
@ -58,7 +58,7 @@ public class ImmutableInstruction35ms extends ImmutableInstruction implements In
|
|||||||
int registerG,
|
int registerG,
|
||||||
int vtableIndex) {
|
int vtableIndex) {
|
||||||
super(opcode);
|
super(opcode);
|
||||||
this.registerCount = Preconditions.check35cRegisterCount(registerCount);
|
this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount);
|
||||||
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
|
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
|
||||||
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
|
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
|
||||||
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
|
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -52,6 +52,9 @@ public class ImmutableReferenceFactory {
|
|||||||
if (reference instanceof MethodReference) {
|
if (reference instanceof MethodReference) {
|
||||||
return ImmutableMethodReference.of((MethodReference)reference);
|
return ImmutableMethodReference.of((MethodReference)reference);
|
||||||
}
|
}
|
||||||
|
if (reference instanceof MethodProtoReference) {
|
||||||
|
return ImmutableMethodProtoReference.of((MethodProtoReference) reference);
|
||||||
|
}
|
||||||
throw new ExceptionWithContext("Invalid reference type");
|
throw new ExceptionWithContext("Invalid reference type");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +69,8 @@ public class ImmutableReferenceFactory {
|
|||||||
return ImmutableFieldReference.of((FieldReference)reference);
|
return ImmutableFieldReference.of((FieldReference)reference);
|
||||||
case ReferenceType.METHOD:
|
case ReferenceType.METHOD:
|
||||||
return ImmutableMethodReference.of((MethodReference)reference);
|
return ImmutableMethodReference.of((MethodReference)reference);
|
||||||
|
case ReferenceType.METHOD_PROTO:
|
||||||
|
return ImmutableMethodProtoReference.of((MethodProtoReference)reference);
|
||||||
}
|
}
|
||||||
throw new ExceptionWithContext("Invalid reference type: %d", referenceType);
|
throw new ExceptionWithContext("Invalid reference type: %d", referenceType);
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ public class Preconditions {
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int check35cRegisterCount(int registerCount) {
|
public static int check35cAnd45ccRegisterCount(int registerCount) {
|
||||||
if (registerCount < 0 || registerCount > 5) {
|
if (registerCount < 0 || registerCount > 5) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format("Invalid register count: %d. Must be between 0 and 5, inclusive.", registerCount));
|
String.format("Invalid register count: %d. Must be between 0 and 5, inclusive.", registerCount));
|
||||||
@ -133,15 +133,6 @@ public class Preconditions {
|
|||||||
return registerCount;
|
return registerCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int check25xParameterRegisterCount(int registerCount) {
|
|
||||||
if (registerCount < 0 || registerCount > 4) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
String.format("Invalid parameter register count: %d. " +
|
|
||||||
"Must be between 0 and 4, inclusive.", registerCount));
|
|
||||||
}
|
|
||||||
return registerCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int checkRegisterRangeCount(int registerCount) {
|
public static int checkRegisterRangeCount(int registerCount) {
|
||||||
if ((registerCount & 0xFFFFFF00) != 0) {
|
if ((registerCount & 0xFFFFFF00) != 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
@ -60,6 +60,17 @@ public final class ReferenceUtil {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getMethodProtoDescriptor(MethodProtoReference methodProtoReference) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append('(');
|
||||||
|
for (CharSequence paramType : methodProtoReference.getParameterTypes()) {
|
||||||
|
sb.append(paramType);
|
||||||
|
}
|
||||||
|
sb.append(')');
|
||||||
|
sb.append(methodProtoReference.getReturnType());
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public static void writeMethodDescriptor(Writer writer, MethodReference methodReference) throws IOException {
|
public static void writeMethodDescriptor(Writer writer, MethodReference methodReference) throws IOException {
|
||||||
writeMethodDescriptor(writer, methodReference, false);
|
writeMethodDescriptor(writer, methodReference, false);
|
||||||
}
|
}
|
||||||
@ -134,12 +145,16 @@ public final class ReferenceUtil {
|
|||||||
if (reference instanceof FieldReference) {
|
if (reference instanceof FieldReference) {
|
||||||
FieldReference fieldReference = (FieldReference)reference;
|
FieldReference fieldReference = (FieldReference)reference;
|
||||||
boolean useImplicitReference = fieldReference.getDefiningClass().equals(containingClass);
|
boolean useImplicitReference = fieldReference.getDefiningClass().equals(containingClass);
|
||||||
return getFieldDescriptor((FieldReference)reference, useImplicitReference);
|
return getFieldDescriptor(fieldReference, useImplicitReference);
|
||||||
}
|
}
|
||||||
if (reference instanceof MethodReference) {
|
if (reference instanceof MethodReference) {
|
||||||
MethodReference methodReference = (MethodReference)reference;
|
MethodReference methodReference = (MethodReference)reference;
|
||||||
boolean useImplicitReference = methodReference.getDefiningClass().equals(containingClass);
|
boolean useImplicitReference = methodReference.getDefiningClass().equals(containingClass);
|
||||||
return getMethodDescriptor((MethodReference)reference, useImplicitReference);
|
return getMethodDescriptor(methodReference, useImplicitReference);
|
||||||
|
}
|
||||||
|
if (reference instanceof MethodProtoReference) {
|
||||||
|
MethodProtoReference methodProtoReference = (MethodProtoReference)reference;
|
||||||
|
return getMethodProtoDescriptor(methodProtoReference);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction;
|
|||||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
||||||
import org.jf.dexlib2.iface.instruction.formats.*;
|
import org.jf.dexlib2.iface.instruction.formats.*;
|
||||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||||
|
import org.jf.dexlib2.iface.reference.MethodProtoReference;
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||||
import org.jf.dexlib2.iface.reference.StringReference;
|
import org.jf.dexlib2.iface.reference.StringReference;
|
||||||
import org.jf.dexlib2.iface.reference.TypeReference;
|
import org.jf.dexlib2.iface.reference.TypeReference;
|
||||||
@ -84,7 +85,7 @@ import java.util.zip.Adler32;
|
|||||||
|
|
||||||
public abstract class DexWriter<
|
public abstract class DexWriter<
|
||||||
StringKey extends CharSequence, StringRef extends StringReference, TypeKey extends CharSequence,
|
StringKey extends CharSequence, StringRef extends StringReference, TypeKey extends CharSequence,
|
||||||
TypeRef extends TypeReference, ProtoKey extends Comparable<ProtoKey>,
|
TypeRef extends TypeReference, ProtoRefKey extends MethodProtoReference,
|
||||||
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
|
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
|
||||||
ClassKey extends Comparable<? super ClassKey>,
|
ClassKey extends Comparable<? super ClassKey>,
|
||||||
AnnotationKey extends Annotation, AnnotationSetKey,
|
AnnotationKey extends Annotation, AnnotationSetKey,
|
||||||
@ -125,9 +126,9 @@ public abstract class DexWriter<
|
|||||||
|
|
||||||
protected final StringSection<StringKey, StringRef> stringSection;
|
protected final StringSection<StringKey, StringRef> stringSection;
|
||||||
protected final TypeSection<StringKey, TypeKey, TypeRef> typeSection;
|
protected final TypeSection<StringKey, TypeKey, TypeRef> typeSection;
|
||||||
protected final ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection;
|
protected final ProtoSection<StringKey, TypeKey, ProtoRefKey, TypeListKey> protoSection;
|
||||||
protected final FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection;
|
protected final FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection;
|
||||||
protected final MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey, MethodKey> methodSection;
|
protected final MethodSection<StringKey, TypeKey, ProtoRefKey, MethodRefKey, MethodKey> methodSection;
|
||||||
protected final ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
|
protected final ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
|
||||||
EncodedValue> classSection;
|
EncodedValue> classSection;
|
||||||
|
|
||||||
@ -138,9 +139,9 @@ public abstract class DexWriter<
|
|||||||
protected DexWriter(Opcodes opcodes,
|
protected DexWriter(Opcodes opcodes,
|
||||||
StringSection<StringKey, StringRef> stringSection,
|
StringSection<StringKey, StringRef> stringSection,
|
||||||
TypeSection<StringKey, TypeKey, TypeRef> typeSection,
|
TypeSection<StringKey, TypeKey, TypeRef> typeSection,
|
||||||
ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection,
|
ProtoSection<StringKey, TypeKey, ProtoRefKey, TypeListKey> protoSection,
|
||||||
FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection,
|
FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection,
|
||||||
MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey, MethodKey> methodSection,
|
MethodSection<StringKey, TypeKey, ProtoRefKey, MethodRefKey, MethodKey> methodSection,
|
||||||
ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
|
ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
|
||||||
EncodedValue> classSection,
|
EncodedValue> classSection,
|
||||||
TypeListSection<TypeKey, TypeListKey> typeListSection,
|
TypeListSection<TypeKey, TypeListKey> typeListSection,
|
||||||
@ -347,12 +348,12 @@ public abstract class DexWriter<
|
|||||||
protoSectionOffset = writer.getPosition();
|
protoSectionOffset = writer.getPosition();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
List<Map.Entry<? extends ProtoKey, Integer>> protoEntries = Lists.newArrayList(protoSection.getItems());
|
List<Map.Entry<? extends ProtoRefKey, Integer>> protoEntries = Lists.newArrayList(protoSection.getItems());
|
||||||
Collections.sort(protoEntries, DexWriter.<ProtoKey>comparableKeyComparator());
|
Collections.sort(protoEntries, DexWriter.<ProtoRefKey>comparableKeyComparator());
|
||||||
|
|
||||||
for (Map.Entry<? extends ProtoKey, Integer> entry: protoEntries) {
|
for (Map.Entry<? extends ProtoRefKey, Integer> entry: protoEntries) {
|
||||||
entry.setValue(index++);
|
entry.setValue(index++);
|
||||||
ProtoKey key = entry.getKey();
|
ProtoRefKey key = entry.getKey();
|
||||||
writer.writeInt(stringSection.getItemIndex(protoSection.getShorty(key)));
|
writer.writeInt(stringSection.getItemIndex(protoSection.getShorty(key)));
|
||||||
writer.writeInt(typeSection.getItemIndex(protoSection.getReturnType(key)));
|
writer.writeInt(typeSection.getItemIndex(protoSection.getReturnType(key)));
|
||||||
writer.writeInt(typeListSection.getNullableItemOffset(protoSection.getParameters(key)));
|
writer.writeInt(typeListSection.getNullableItemOffset(protoSection.getParameters(key)));
|
||||||
@ -946,7 +947,7 @@ public abstract class DexWriter<
|
|||||||
|
|
||||||
InstructionWriter instructionWriter =
|
InstructionWriter instructionWriter =
|
||||||
InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection,
|
InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection,
|
||||||
methodSection);
|
methodSection, protoSection);
|
||||||
|
|
||||||
writer.writeInt(codeUnitCount);
|
writer.writeInt(codeUnitCount);
|
||||||
for (Instruction instruction: instructions) {
|
for (Instruction instruction: instructions) {
|
||||||
@ -1005,9 +1006,6 @@ public abstract class DexWriter<
|
|||||||
case Format23x:
|
case Format23x:
|
||||||
instructionWriter.write((Instruction23x)instruction);
|
instructionWriter.write((Instruction23x)instruction);
|
||||||
break;
|
break;
|
||||||
case Format25x:
|
|
||||||
instructionWriter.write((Instruction25x)instruction);
|
|
||||||
break;
|
|
||||||
case Format30t:
|
case Format30t:
|
||||||
instructionWriter.write((Instruction30t)instruction);
|
instructionWriter.write((Instruction30t)instruction);
|
||||||
break;
|
break;
|
||||||
@ -1029,6 +1027,12 @@ public abstract class DexWriter<
|
|||||||
case Format3rc:
|
case Format3rc:
|
||||||
instructionWriter.write((Instruction3rc)instruction);
|
instructionWriter.write((Instruction3rc)instruction);
|
||||||
break;
|
break;
|
||||||
|
case Format45cc:
|
||||||
|
instructionWriter.write((Instruction45cc) instruction);
|
||||||
|
break;
|
||||||
|
case Format4rcc:
|
||||||
|
instructionWriter.write((Instruction4rcc) instruction);
|
||||||
|
break;
|
||||||
case Format51l:
|
case Format51l:
|
||||||
instructionWriter.write((Instruction51l)instruction);
|
instructionWriter.write((Instruction51l)instruction);
|
||||||
break;
|
break;
|
||||||
|
@ -36,11 +36,14 @@ import com.google.common.primitives.Ints;
|
|||||||
import org.jf.dexlib2.Opcode;
|
import org.jf.dexlib2.Opcode;
|
||||||
import org.jf.dexlib2.Opcodes;
|
import org.jf.dexlib2.Opcodes;
|
||||||
import org.jf.dexlib2.ReferenceType;
|
import org.jf.dexlib2.ReferenceType;
|
||||||
|
import org.jf.dexlib2.iface.instruction.DualReferenceInstruction;
|
||||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
||||||
import org.jf.dexlib2.iface.instruction.SwitchElement;
|
import org.jf.dexlib2.iface.instruction.SwitchElement;
|
||||||
import org.jf.dexlib2.iface.instruction.formats.*;
|
import org.jf.dexlib2.iface.instruction.formats.*;
|
||||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||||
|
import org.jf.dexlib2.iface.reference.MethodProtoReference;
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||||
|
import org.jf.dexlib2.iface.reference.Reference;
|
||||||
import org.jf.dexlib2.iface.reference.StringReference;
|
import org.jf.dexlib2.iface.reference.StringReference;
|
||||||
import org.jf.dexlib2.iface.reference.TypeReference;
|
import org.jf.dexlib2.iface.reference.TypeReference;
|
||||||
import org.jf.util.ExceptionWithContext;
|
import org.jf.util.ExceptionWithContext;
|
||||||
@ -51,25 +54,29 @@ import java.util.Comparator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class InstructionWriter<StringRef extends StringReference, TypeRef extends TypeReference,
|
public class InstructionWriter<StringRef extends StringReference, TypeRef extends TypeReference,
|
||||||
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference> {
|
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
|
||||||
|
ProtoRefKey extends MethodProtoReference> {
|
||||||
@Nonnull private final Opcodes opcodes;
|
@Nonnull private final Opcodes opcodes;
|
||||||
@Nonnull private final DexDataWriter writer;
|
@Nonnull private final DexDataWriter writer;
|
||||||
@Nonnull private final StringSection<?, StringRef> stringSection;
|
@Nonnull private final StringSection<?, StringRef> stringSection;
|
||||||
@Nonnull private final TypeSection<?, ?, TypeRef> typeSection;
|
@Nonnull private final TypeSection<?, ?, TypeRef> typeSection;
|
||||||
@Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
|
@Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
|
||||||
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
|
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
|
||||||
|
@Nonnull private final ProtoSection<?, ?, ProtoRefKey, ?> protoSection;
|
||||||
|
|
||||||
@Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference>
|
@Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, FieldRefKey extends FieldReference,
|
||||||
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey>
|
MethodRefKey extends MethodReference, ProtoRefKey extends MethodProtoReference>
|
||||||
|
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey>
|
||||||
makeInstructionWriter(
|
makeInstructionWriter(
|
||||||
@Nonnull Opcodes opcodes,
|
@Nonnull Opcodes opcodes,
|
||||||
@Nonnull DexDataWriter writer,
|
@Nonnull DexDataWriter writer,
|
||||||
@Nonnull StringSection<?, StringRef> stringSection,
|
@Nonnull StringSection<?, StringRef> stringSection,
|
||||||
@Nonnull TypeSection<?, ?, TypeRef> typeSection,
|
@Nonnull TypeSection<?, ?, TypeRef> typeSection,
|
||||||
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
|
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
|
||||||
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection) {
|
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
|
||||||
return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey>(
|
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection) {
|
||||||
opcodes, writer, stringSection, typeSection, fieldSection, methodSection);
|
return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey>(
|
||||||
|
opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionWriter(@Nonnull Opcodes opcodes,
|
InstructionWriter(@Nonnull Opcodes opcodes,
|
||||||
@ -77,13 +84,15 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
|
|||||||
@Nonnull StringSection<?, StringRef> stringSection,
|
@Nonnull StringSection<?, StringRef> stringSection,
|
||||||
@Nonnull TypeSection<?, ?, TypeRef> typeSection,
|
@Nonnull TypeSection<?, ?, TypeRef> typeSection,
|
||||||
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
|
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
|
||||||
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection) {
|
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
|
||||||
|
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection) {
|
||||||
this.opcodes = opcodes;
|
this.opcodes = opcodes;
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
this.stringSection = stringSection;
|
this.stringSection = stringSection;
|
||||||
this.typeSection = typeSection;
|
this.typeSection = typeSection;
|
||||||
this.fieldSection = fieldSection;
|
this.fieldSection = fieldSection;
|
||||||
this.methodSection = methodSection;
|
this.methodSection = methodSection;
|
||||||
|
this.protoSection = protoSection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private short getOpcodeValue(Opcode opcode) {
|
private short getOpcodeValue(Opcode opcode) {
|
||||||
@ -334,19 +343,6 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(@Nonnull Instruction25x instruction) {
|
|
||||||
try {
|
|
||||||
writer.write(getOpcodeValue(instruction.getOpcode()));
|
|
||||||
writer.write(packNibbles(
|
|
||||||
instruction.getRegisterParameterG(), instruction.getParameterRegisterCount()));
|
|
||||||
writer.write(packNibbles(
|
|
||||||
instruction.getRegisterFixedC(), instruction.getRegisterParameterD()));
|
|
||||||
writer.write(packNibbles(
|
|
||||||
instruction.getRegisterParameterE(), instruction.getRegisterParameterF()));
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void write(@Nonnull Instruction3rc instruction) {
|
public void write(@Nonnull Instruction3rc instruction) {
|
||||||
try {
|
try {
|
||||||
writer.write(getOpcodeValue(instruction.getOpcode()));
|
writer.write(getOpcodeValue(instruction.getOpcode()));
|
||||||
@ -358,6 +354,31 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void write(@Nonnull Instruction45cc instruction) {
|
||||||
|
try {
|
||||||
|
writer.write(getOpcodeValue(instruction.getOpcode()));
|
||||||
|
writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount()));
|
||||||
|
writer.writeUshort(getReferenceIndex(instruction));
|
||||||
|
writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD()));
|
||||||
|
writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF()));
|
||||||
|
writer.writeUshort(getReference2Index(instruction));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(@Nonnull Instruction4rcc instruction) {
|
||||||
|
try {
|
||||||
|
writer.write(getOpcodeValue(instruction.getOpcode()));
|
||||||
|
writer.write(instruction.getRegisterCount());
|
||||||
|
writer.writeUshort(getReferenceIndex(instruction));
|
||||||
|
writer.writeUshort(instruction.getStartRegister());
|
||||||
|
writer.writeUshort(getReference2Index(instruction));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void write(@Nonnull Instruction51l instruction) {
|
public void write(@Nonnull Instruction51l instruction) {
|
||||||
try {
|
try {
|
||||||
writer.write(getOpcodeValue(instruction.getOpcode()));
|
writer.write(getOpcodeValue(instruction.getOpcode()));
|
||||||
@ -452,18 +473,29 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getReferenceIndex(ReferenceInstruction referenceInstruction) {
|
private int getReferenceIndex(ReferenceInstruction referenceInstruction) {
|
||||||
switch (referenceInstruction.getOpcode().referenceType) {
|
return getReferenceIndex(referenceInstruction.getReferenceType(),
|
||||||
|
referenceInstruction.getReference());
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getReference2Index(DualReferenceInstruction referenceInstruction) {
|
||||||
|
return getReferenceIndex(referenceInstruction.getReferenceType2(),
|
||||||
|
referenceInstruction.getReference2());
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getReferenceIndex(int referenceType, Reference reference) {
|
||||||
|
switch (referenceType) {
|
||||||
case ReferenceType.FIELD:
|
case ReferenceType.FIELD:
|
||||||
return fieldSection.getItemIndex((FieldRefKey)referenceInstruction.getReference());
|
return fieldSection.getItemIndex((FieldRefKey) reference);
|
||||||
case ReferenceType.METHOD:
|
case ReferenceType.METHOD:
|
||||||
return methodSection.getItemIndex((MethodRefKey)referenceInstruction.getReference());
|
return methodSection.getItemIndex((MethodRefKey) reference);
|
||||||
case ReferenceType.STRING:
|
case ReferenceType.STRING:
|
||||||
return stringSection.getItemIndex((StringRef)referenceInstruction.getReference());
|
return stringSection.getItemIndex((StringRef) reference);
|
||||||
case ReferenceType.TYPE:
|
case ReferenceType.TYPE:
|
||||||
return typeSection.getItemIndex((TypeRef)referenceInstruction.getReference());
|
return typeSection.getItemIndex((TypeRef) reference);
|
||||||
|
case ReferenceType.METHOD_PROTO:
|
||||||
|
return protoSection.getItemIndex((ProtoRefKey) reference);
|
||||||
default:
|
default:
|
||||||
throw new ExceptionWithContext("Unknown reference type: %d",
|
throw new ExceptionWithContext("Unknown reference type: %d", referenceType);
|
||||||
referenceInstruction.getOpcode().referenceType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,15 +31,17 @@
|
|||||||
|
|
||||||
package org.jf.dexlib2.writer;
|
package org.jf.dexlib2.writer;
|
||||||
|
|
||||||
|
import org.jf.dexlib2.iface.reference.MethodProtoReference;
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public interface MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey extends MethodReference, MethodKey>
|
public interface MethodSection<StringKey, TypeKey, ProtoRefKey extends MethodProtoReference,
|
||||||
|
MethodRefKey extends MethodReference, MethodKey>
|
||||||
extends IndexSection<MethodRefKey> {
|
extends IndexSection<MethodRefKey> {
|
||||||
@Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key);
|
@Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key);
|
||||||
@Nonnull ProtoKey getPrototype(@Nonnull MethodRefKey key);
|
@Nonnull ProtoRefKey getPrototype(@Nonnull MethodRefKey key);
|
||||||
@Nonnull ProtoKey getPrototype(@Nonnull MethodKey key);
|
@Nonnull ProtoRefKey getPrototype(@Nonnull MethodKey key);
|
||||||
@Nonnull StringKey getName(@Nonnull MethodRefKey key);
|
@Nonnull StringKey getName(@Nonnull MethodRefKey key);
|
||||||
int getMethodIndex(@Nonnull MethodKey key);
|
int getMethodIndex(@Nonnull MethodKey key);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ import java.util.Map.Entry;
|
|||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
class BuilderMethodPool implements MethodSection<BuilderStringReference, BuilderTypeReference,
|
class BuilderMethodPool implements MethodSection<BuilderStringReference, BuilderTypeReference,
|
||||||
BuilderProtoReference, BuilderMethodReference, BuilderMethod>{
|
BuilderMethodProtoReference, BuilderMethodReference, BuilderMethod>{
|
||||||
@Nonnull private final BuilderContext context;
|
@Nonnull private final BuilderContext context;
|
||||||
@Nonnull private final ConcurrentMap<MethodReference, BuilderMethodReference> internedItems =
|
@Nonnull private final ConcurrentMap<MethodReference, BuilderMethodReference> internedItems =
|
||||||
Maps.newConcurrentMap();
|
Maps.newConcurrentMap();
|
||||||
@ -61,7 +61,7 @@ class BuilderMethodPool implements MethodSection<BuilderStringReference, Builder
|
|||||||
BuilderMethodReference dexPoolMethodReference = new BuilderMethodReference(
|
BuilderMethodReference dexPoolMethodReference = new BuilderMethodReference(
|
||||||
context.typePool.internType(methodReference.getDefiningClass()),
|
context.typePool.internType(methodReference.getDefiningClass()),
|
||||||
context.stringPool.internString(methodReference.getName()),
|
context.stringPool.internString(methodReference.getName()),
|
||||||
context.protoPool.internProto(methodReference));
|
context.protoPool.internMethodProto(methodReference));
|
||||||
ret = internedItems.putIfAbsent(dexPoolMethodReference, dexPoolMethodReference);
|
ret = internedItems.putIfAbsent(dexPoolMethodReference, dexPoolMethodReference);
|
||||||
return ret==null?dexPoolMethodReference:ret;
|
return ret==null?dexPoolMethodReference:ret;
|
||||||
}
|
}
|
||||||
@ -78,11 +78,11 @@ class BuilderMethodPool implements MethodSection<BuilderStringReference, Builder
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override
|
@Nonnull @Override
|
||||||
public BuilderProtoReference getPrototype(@Nonnull BuilderMethodReference key) {
|
public BuilderMethodProtoReference getPrototype(@Nonnull BuilderMethodReference key) {
|
||||||
return key.proto;
|
return key.proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public BuilderProtoReference getPrototype(@Nonnull BuilderMethod builderMethod) {
|
@Nonnull @Override public BuilderMethodProtoReference getPrototype(@Nonnull BuilderMethod builderMethod) {
|
||||||
return builderMethod.methodReference.proto;
|
return builderMethod.methodReference.proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
package org.jf.dexlib2.writer.builder;
|
package org.jf.dexlib2.writer.builder;
|
||||||
|
|
||||||
import com.google.common.collect.Ordering;
|
import com.google.common.collect.Ordering;
|
||||||
|
import org.jf.dexlib2.base.reference.BaseMethodProtoReference;
|
||||||
|
import org.jf.dexlib2.iface.reference.MethodProtoReference;
|
||||||
import org.jf.dexlib2.writer.DexWriter;
|
import org.jf.dexlib2.writer.DexWriter;
|
||||||
import org.jf.util.CharSequenceUtils;
|
import org.jf.util.CharSequenceUtils;
|
||||||
import org.jf.util.CollectionUtils;
|
import org.jf.util.CollectionUtils;
|
||||||
@ -40,14 +42,15 @@ import javax.annotation.Nonnull;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class BuilderProtoReference implements BuilderProtoPool.ProtoKey, Comparable<BuilderProtoReference> {
|
public class BuilderMethodProtoReference extends BaseMethodProtoReference implements
|
||||||
|
MethodProtoReference, BuilderReference {
|
||||||
@Nonnull final BuilderStringReference shorty;
|
@Nonnull final BuilderStringReference shorty;
|
||||||
@Nonnull final BuilderTypeList parameterTypes;
|
@Nonnull final BuilderTypeList parameterTypes;
|
||||||
@Nonnull final BuilderTypeReference returnType;
|
@Nonnull final BuilderTypeReference returnType;
|
||||||
int index = DexWriter.NO_INDEX;
|
int index = DexWriter.NO_INDEX;
|
||||||
|
|
||||||
public BuilderProtoReference(@Nonnull BuilderStringReference shorty, @Nonnull BuilderTypeList parameterTypes,
|
public BuilderMethodProtoReference(@Nonnull BuilderStringReference shorty, @Nonnull BuilderTypeList parameterTypes,
|
||||||
@Nonnull BuilderTypeReference returnType) {
|
@Nonnull BuilderTypeReference returnType) {
|
||||||
this.shorty = shorty;
|
this.shorty = shorty;
|
||||||
this.parameterTypes = parameterTypes;
|
this.parameterTypes = parameterTypes;
|
||||||
this.returnType = returnType;
|
this.returnType = returnType;
|
||||||
@ -62,25 +65,12 @@ public class BuilderProtoReference implements BuilderProtoPool.ProtoKey, Compara
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int getIndex() {
|
||||||
int hashCode = getReturnType().hashCode();
|
return index;
|
||||||
return hashCode*31 + getParameterTypes().hashCode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object o) {
|
public void setIndex(int index) {
|
||||||
if (o != null && o instanceof BuilderProtoReference) {
|
this.index = index;
|
||||||
BuilderProtoReference other = (BuilderProtoReference)o;
|
|
||||||
return returnType.equals(other.returnType) &&
|
|
||||||
CharSequenceUtils.listEquals(parameterTypes, other.parameterTypes);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(@Nonnull BuilderProtoReference o) {
|
|
||||||
int res = returnType.compareTo(o.returnType);
|
|
||||||
if (res != 0) return res;
|
|
||||||
return CollectionUtils.compareAsIterable(Ordering.usingToString(), parameterTypes, o.parameterTypes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -39,12 +39,12 @@ import javax.annotation.Nonnull;
|
|||||||
public class BuilderMethodReference extends BaseMethodReference implements BuilderReference {
|
public class BuilderMethodReference extends BaseMethodReference implements BuilderReference {
|
||||||
@Nonnull final BuilderTypeReference definingClass;
|
@Nonnull final BuilderTypeReference definingClass;
|
||||||
@Nonnull final BuilderStringReference name;
|
@Nonnull final BuilderStringReference name;
|
||||||
@Nonnull final BuilderProtoReference proto;
|
@Nonnull final BuilderMethodProtoReference proto;
|
||||||
int index = DexWriter.NO_INDEX;
|
int index = DexWriter.NO_INDEX;
|
||||||
|
|
||||||
BuilderMethodReference(@Nonnull BuilderTypeReference definingClass,
|
BuilderMethodReference(@Nonnull BuilderTypeReference definingClass,
|
||||||
@Nonnull BuilderStringReference name,
|
@Nonnull BuilderStringReference name,
|
||||||
@Nonnull BuilderProtoReference proto) {
|
@Nonnull BuilderMethodProtoReference proto) {
|
||||||
this.definingClass = definingClass;
|
this.definingClass = definingClass;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.proto = proto;
|
this.proto = proto;
|
||||||
|
@ -32,114 +32,75 @@
|
|||||||
package org.jf.dexlib2.writer.builder;
|
package org.jf.dexlib2.writer.builder;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
import org.jf.dexlib2.iface.reference.MethodProtoReference;
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||||
|
import org.jf.dexlib2.immutable.reference.ImmutableMethodProtoReference;
|
||||||
import org.jf.dexlib2.util.MethodUtil;
|
import org.jf.dexlib2.util.MethodUtil;
|
||||||
import org.jf.dexlib2.writer.ProtoSection;
|
import org.jf.dexlib2.writer.ProtoSection;
|
||||||
import org.jf.util.CharSequenceUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
class BuilderProtoPool
|
class BuilderProtoPool
|
||||||
implements ProtoSection<BuilderStringReference, BuilderTypeReference, BuilderProtoReference, BuilderTypeList> {
|
implements ProtoSection<BuilderStringReference, BuilderTypeReference, BuilderMethodProtoReference, BuilderTypeList> {
|
||||||
@Nonnull private final BuilderContext context;
|
@Nonnull private final BuilderContext context;
|
||||||
@Nonnull private final ConcurrentMap<ProtoKey, BuilderProtoReference> internedItems =
|
@Nonnull private final ConcurrentMap<MethodProtoReference, BuilderMethodProtoReference> internedItems =
|
||||||
Maps.newConcurrentMap();
|
Maps.newConcurrentMap();
|
||||||
|
|
||||||
BuilderProtoPool(@Nonnull BuilderContext context) {
|
BuilderProtoPool(@Nonnull BuilderContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull public BuilderProtoReference internProto(@Nonnull List<? extends CharSequence> parameters,
|
@Nonnull public BuilderMethodProtoReference internMethodProto(@Nonnull MethodProtoReference methodProto) {
|
||||||
@Nonnull String returnType) {
|
BuilderMethodProtoReference ret = internedItems.get(methodProto);
|
||||||
ProtoKey key = new Key(parameters, returnType);
|
|
||||||
BuilderProtoReference ret = internedItems.get(key);
|
|
||||||
if (ret != null) {
|
if (ret != null) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuilderProtoReference protoReference = new BuilderProtoReference(
|
BuilderMethodProtoReference protoReference = new BuilderMethodProtoReference(
|
||||||
context.stringPool.internString(MethodUtil.getShorty(parameters, returnType)),
|
context.stringPool.internString(MethodUtil.getShorty(
|
||||||
context.typeListPool.internTypeList(parameters),
|
methodProto.getParameterTypes(), methodProto.getReturnType())),
|
||||||
context.typePool.internType(returnType));
|
context.typeListPool.internTypeList(methodProto.getParameterTypes()),
|
||||||
|
context.typePool.internType(methodProto.getReturnType()));
|
||||||
ret = internedItems.putIfAbsent(protoReference, protoReference);
|
ret = internedItems.putIfAbsent(protoReference, protoReference);
|
||||||
return ret==null?protoReference:ret;
|
return ret==null?protoReference:ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull public BuilderProtoReference internProto(@Nonnull MethodReference methodReference) {
|
@Nonnull public BuilderMethodProtoReference internMethodProto(@Nonnull MethodReference methodReference) {
|
||||||
return internProto(methodReference.getParameterTypes(), methodReference.getReturnType());
|
return internMethodProto(new ImmutableMethodProtoReference(
|
||||||
|
methodReference.getParameterTypes(), methodReference.getReturnType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public BuilderStringReference getShorty(@Nonnull BuilderProtoReference key) {
|
@Nonnull @Override public BuilderStringReference getShorty(@Nonnull BuilderMethodProtoReference proto) {
|
||||||
return key.shorty;
|
return proto.shorty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public BuilderTypeReference getReturnType(@Nonnull BuilderProtoReference key) {
|
@Nonnull @Override public BuilderTypeReference getReturnType(@Nonnull BuilderMethodProtoReference proto) {
|
||||||
return key.returnType;
|
return proto.returnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable @Override public BuilderTypeList getParameters(@Nonnull BuilderProtoReference key) {
|
@Nullable @Override public BuilderTypeList getParameters(@Nonnull BuilderMethodProtoReference proto) {
|
||||||
return key.parameterTypes;
|
return proto.parameterTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getItemIndex(@Nonnull BuilderProtoReference key) {
|
@Override public int getItemIndex(@Nonnull BuilderMethodProtoReference proto) {
|
||||||
return key.index;
|
return proto.getIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public Collection<? extends Entry<? extends BuilderProtoReference, Integer>> getItems() {
|
@Nonnull @Override public Collection<? extends Entry<? extends BuilderMethodProtoReference, Integer>> getItems() {
|
||||||
return new BuilderMapEntryCollection<BuilderProtoReference>(internedItems.values()) {
|
return new BuilderMapEntryCollection<BuilderMethodProtoReference>(internedItems.values()) {
|
||||||
@Override protected int getValue(@Nonnull BuilderProtoReference key) {
|
@Override protected int getValue(@Nonnull BuilderMethodProtoReference key) {
|
||||||
return key.index;
|
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;
|
int prev = key.index;
|
||||||
key.index = value;
|
key.index = value;
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// a placeholder interface to unify the temporary probing key and the BuilderProtoReference class
|
|
||||||
interface ProtoKey {
|
|
||||||
@Nonnull List<? extends CharSequence> getParameterTypes();
|
|
||||||
@Nonnull String getReturnType();
|
|
||||||
}
|
|
||||||
|
|
||||||
// a temporary lightweight class to allow a quick probe if the given prototype has already been interned
|
|
||||||
private static class Key implements ProtoKey {
|
|
||||||
@Nonnull private final List<? extends CharSequence> parameters;
|
|
||||||
@Nonnull private final String returnType;
|
|
||||||
|
|
||||||
public Key(@Nonnull List<? extends CharSequence> parameters, @Nonnull String returnType) {
|
|
||||||
this.parameters = parameters;
|
|
||||||
this.returnType = returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull public List<? extends CharSequence> getParameterTypes() {
|
|
||||||
return parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull public String getReturnType() {
|
|
||||||
return returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public int hashCode() {
|
|
||||||
int hashCode = returnType.hashCode();
|
|
||||||
return hashCode*31 + parameters.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public boolean equals(Object o) {
|
|
||||||
if (o != null && o instanceof ProtoKey) {
|
|
||||||
ProtoKey other = (ProtoKey)o;
|
|
||||||
return getReturnType().equals(other.getReturnType()) &&
|
|
||||||
CharSequenceUtils.listEquals(getParameterTypes(), other.getParameterTypes());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringReference, BuilderTypeReference,
|
public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringReference, BuilderTypeReference,
|
||||||
BuilderTypeReference, BuilderProtoReference, BuilderFieldReference, BuilderMethodReference,
|
BuilderTypeReference, BuilderMethodProtoReference, BuilderFieldReference, BuilderMethodReference,
|
||||||
BuilderClassDef, BuilderAnnotation, BuilderAnnotationSet, BuilderTypeList, BuilderField, BuilderMethod,
|
BuilderClassDef, BuilderAnnotation, BuilderAnnotationSet, BuilderTypeList, BuilderField, BuilderMethod,
|
||||||
BuilderEncodedValue, BuilderAnnotationElement> {
|
BuilderEncodedValue, BuilderAnnotationElement> {
|
||||||
|
|
||||||
@ -176,6 +176,10 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
|||||||
return context.methodPool.internMethod(method);
|
return context.methodPool.internMethod(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull public BuilderMethodProtoReference internMethodProtoReference(@Nonnull MethodProtoReference methodProto) {
|
||||||
|
return context.protoPool.internMethodProto(methodProto);
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull public BuilderReference internReference(@Nonnull Reference reference) {
|
@Nonnull public BuilderReference internReference(@Nonnull Reference reference) {
|
||||||
if (reference instanceof StringReference) {
|
if (reference instanceof StringReference) {
|
||||||
return internStringReference(((StringReference)reference).getString());
|
return internStringReference(((StringReference)reference).getString());
|
||||||
@ -189,6 +193,9 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
|||||||
if (reference instanceof FieldReference) {
|
if (reference instanceof FieldReference) {
|
||||||
return internFieldReference((FieldReference)reference);
|
return internFieldReference((FieldReference)reference);
|
||||||
}
|
}
|
||||||
|
if (reference instanceof MethodProtoReference) {
|
||||||
|
return internMethodProtoReference((MethodProtoReference) reference);
|
||||||
|
}
|
||||||
throw new IllegalArgumentException("Could not determine type of reference");
|
throw new IllegalArgumentException("Could not determine type of reference");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,6 @@ import org.jf.dexlib2.iface.value.*;
|
|||||||
import org.jf.dexlib2.writer.DexWriter;
|
import org.jf.dexlib2.writer.DexWriter;
|
||||||
import org.jf.dexlib2.writer.io.DexDataStore;
|
import org.jf.dexlib2.writer.io.DexDataStore;
|
||||||
import org.jf.dexlib2.writer.io.FileDataStore;
|
import org.jf.dexlib2.writer.io.FileDataStore;
|
||||||
import org.jf.dexlib2.writer.pool.ProtoPool.Key;
|
|
||||||
import org.jf.util.ExceptionWithContext;
|
import org.jf.util.ExceptionWithContext;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -51,8 +50,8 @@ import java.io.IOException;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference, Key,
|
public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference,
|
||||||
FieldReference, MethodReference, PoolClassDef,
|
MethodProtoReference, FieldReference, MethodReference, PoolClassDef,
|
||||||
Annotation, Set<? extends Annotation>,
|
Annotation, Set<? extends Annotation>,
|
||||||
TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
|
TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
|
||||||
EncodedValue, AnnotationElement> {
|
EncodedValue, AnnotationElement> {
|
||||||
|
@ -31,13 +31,14 @@
|
|||||||
|
|
||||||
package org.jf.dexlib2.writer.pool;
|
package org.jf.dexlib2.writer.pool;
|
||||||
|
|
||||||
|
import org.jf.dexlib2.iface.reference.MethodProtoReference;
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||||
import org.jf.dexlib2.writer.MethodSection;
|
import org.jf.dexlib2.writer.MethodSection;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class MethodPool extends BaseIndexPool<MethodReference>
|
public class MethodPool extends BaseIndexPool<MethodReference>
|
||||||
implements MethodSection<CharSequence, CharSequence, ProtoPool.Key, MethodReference, PoolMethod> {
|
implements MethodSection<CharSequence, CharSequence, MethodProtoReference, MethodReference, PoolMethod> {
|
||||||
@Nonnull private final StringPool stringPool;
|
@Nonnull private final StringPool stringPool;
|
||||||
@Nonnull private final TypePool typePool;
|
@Nonnull private final TypePool typePool;
|
||||||
@Nonnull private final ProtoPool protoPool;
|
@Nonnull private final ProtoPool protoPool;
|
||||||
@ -53,7 +54,7 @@ public class MethodPool extends BaseIndexPool<MethodReference>
|
|||||||
Integer prev = internedItems.put(method, 0);
|
Integer prev = internedItems.put(method, 0);
|
||||||
if (prev == null) {
|
if (prev == null) {
|
||||||
typePool.intern(method.getDefiningClass());
|
typePool.intern(method.getDefiningClass());
|
||||||
protoPool.intern(method);
|
protoPool.intern(new PoolMethodProto(method));
|
||||||
stringPool.intern(method.getName());
|
stringPool.intern(method.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,12 +63,12 @@ public class MethodPool extends BaseIndexPool<MethodReference>
|
|||||||
return methodReference.getDefiningClass();
|
return methodReference.getDefiningClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull MethodReference methodReference) {
|
@Nonnull @Override public MethodProtoReference getPrototype(@Nonnull MethodReference methodReference) {
|
||||||
return new ProtoPool.Key(methodReference);
|
return new PoolMethodProto(methodReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull PoolMethod poolMethod) {
|
@Nonnull @Override public MethodProtoReference getPrototype(@Nonnull PoolMethod poolMethod) {
|
||||||
return new ProtoPool.Key(poolMethod);
|
return new PoolMethodProto(poolMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public CharSequence getName(@Nonnull MethodReference methodReference) {
|
@Nonnull @Override public CharSequence getName(@Nonnull MethodReference methodReference) {
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -31,21 +31,18 @@
|
|||||||
|
|
||||||
package org.jf.dexlib2.writer.pool;
|
package org.jf.dexlib2.writer.pool;
|
||||||
|
|
||||||
import com.google.common.collect.Ordering;
|
import org.jf.dexlib2.iface.reference.MethodProtoReference;
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
|
||||||
import org.jf.dexlib2.util.MethodUtil;
|
import org.jf.dexlib2.util.MethodUtil;
|
||||||
import org.jf.dexlib2.writer.pool.ProtoPool.Key;
|
|
||||||
import org.jf.dexlib2.writer.ProtoSection;
|
import org.jf.dexlib2.writer.ProtoSection;
|
||||||
import org.jf.util.CharSequenceUtils;
|
|
||||||
import org.jf.util.CollectionUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ProtoPool extends BaseIndexPool<Key>
|
public class ProtoPool extends BaseIndexPool<MethodProtoReference>
|
||||||
implements ProtoSection<CharSequence, CharSequence, Key, TypeListPool.Key<? extends Collection<? extends CharSequence>>> {
|
implements ProtoSection<CharSequence, CharSequence, MethodProtoReference,
|
||||||
|
TypeListPool.Key<? extends Collection<? extends CharSequence>>> {
|
||||||
@Nonnull private final StringPool stringPool;
|
@Nonnull private final StringPool stringPool;
|
||||||
@Nonnull private final TypePool typePool;
|
@Nonnull private final TypePool typePool;
|
||||||
@Nonnull private final TypeListPool typeListPool;
|
@Nonnull private final TypeListPool typeListPool;
|
||||||
@ -57,78 +54,25 @@ public class ProtoPool extends BaseIndexPool<Key>
|
|||||||
this.typeListPool = typeListPool;
|
this.typeListPool = typeListPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void intern(@Nonnull MethodReference method) {
|
public void intern(@Nonnull MethodProtoReference reference) {
|
||||||
// We can't use method directly, because it is likely a full MethodReference. We use a wrapper that computes
|
Integer prev = internedItems.put(reference, 0);
|
||||||
// hashCode and equals based only on the prototype fields
|
|
||||||
Key key = new Key(method);
|
|
||||||
Integer prev = internedItems.put(key, 0);
|
|
||||||
if (prev == null) {
|
if (prev == null) {
|
||||||
stringPool.intern(key.getShorty());
|
stringPool.intern(getShorty(reference));
|
||||||
typePool.intern(method.getReturnType());
|
typePool.intern(reference.getReturnType());
|
||||||
typeListPool.intern(method.getParameterTypes());
|
typeListPool.intern(reference.getParameterTypes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public CharSequence getShorty(@Nonnull Key key) {
|
@Nonnull @Override public CharSequence getShorty(@Nonnull MethodProtoReference reference) {
|
||||||
return key.getShorty();
|
return MethodUtil.getShorty(reference.getParameterTypes(), reference.getReturnType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public CharSequence getReturnType(@Nonnull Key key) {
|
@Nonnull @Override public CharSequence getReturnType(@Nonnull MethodProtoReference protoReference) {
|
||||||
return key.getReturnType();
|
return protoReference.getReturnType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable @Override public TypeListPool.Key<List<? extends CharSequence>> getParameters(@Nonnull Key key) {
|
@Nullable @Override public TypeListPool.Key<List<? extends CharSequence>> getParameters(
|
||||||
return new TypeListPool.Key<List<? extends CharSequence>>(key.getParameters());
|
@Nonnull MethodProtoReference methodProto) {
|
||||||
}
|
return new TypeListPool.Key<List<? extends CharSequence>>(methodProto.getParameterTypes());
|
||||||
|
|
||||||
public static class Key implements Comparable<Key> {
|
|
||||||
@Nonnull private final MethodReference method;
|
|
||||||
|
|
||||||
public Key(@Nonnull MethodReference method) {
|
|
||||||
this.method = method;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull public String getReturnType() { return method.getReturnType(); }
|
|
||||||
@Nonnull public List<? extends CharSequence> getParameters() {
|
|
||||||
return method.getParameterTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getShorty() {
|
|
||||||
return MethodUtil.getShorty(method.getParameterTypes(), method.getReturnType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append('(');
|
|
||||||
for (CharSequence paramType: getParameters()) {
|
|
||||||
sb.append(paramType);
|
|
||||||
}
|
|
||||||
sb.append(')');
|
|
||||||
sb.append(getReturnType());
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int hashCode = getReturnType().hashCode();
|
|
||||||
return hashCode*31 + CharSequenceUtils.listHashCode(getParameters());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(@Nullable Object o) {
|
|
||||||
if (o instanceof Key) {
|
|
||||||
Key other = (Key)o;
|
|
||||||
return getReturnType().equals(other.getReturnType()) &&
|
|
||||||
CharSequenceUtils.listEquals(getParameters(), other.getParameters());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(@Nonnull Key o) {
|
|
||||||
int res = getReturnType().compareTo(o.getReturnType());
|
|
||||||
if (res != 0) return res;
|
|
||||||
return CollectionUtils.compareAsIterable(Ordering.usingToString(), getParameters(), o.getParameters());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
@ -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
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Sun Feb 14 12:35:03 PST 2016
|
#Fri Jul 08 16:46:58 PDT 2016
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip
|
||||||
|
10
gradlew
vendored
10
gradlew
vendored
@ -42,11 +42,6 @@ case "`uname`" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
|
||||||
if $cygwin ; then
|
|
||||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
PRG="$0"
|
||||||
@ -61,9 +56,9 @@ while [ -h "$PRG" ] ; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
SAVED="`pwd`"
|
SAVED="`pwd`"
|
||||||
cd "`dirname \"$PRG\"`/" >&-
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
APP_HOME="`pwd -P`"
|
APP_HOME="`pwd -P`"
|
||||||
cd "$SAVED" >&-
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
@ -114,6 +109,7 @@ fi
|
|||||||
if $cygwin ; then
|
if $cygwin ; then
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
2
gradlew.bat
vendored
2
gradlew.bat
vendored
@ -46,7 +46,7 @@ echo location of your Java installation.
|
|||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
:init
|
||||||
@rem Get command-line arguments, handling Windowz variants
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
apply plugin: 'antlr'
|
apply plugin: 'antlr'
|
||||||
apply plugin: 'jflex'
|
apply plugin: 'org.xbib.gradle.plugin.jflex'
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
@ -46,10 +46,6 @@ configurations {
|
|||||||
// Remove the full antlr library that's added by the antlr plugin. We manually
|
// Remove the full antlr library that's added by the antlr plugin. We manually
|
||||||
// add the smaller antlr_runtime library instead
|
// add the smaller antlr_runtime library instead
|
||||||
compile.exclude group: 'org.antlr', module: 'antlr'
|
compile.exclude group: 'org.antlr', module: 'antlr'
|
||||||
|
|
||||||
// The jflex lexer doesn't have any runtime dependencies, so remove the dependency
|
|
||||||
// that gets added by the jflex plugin
|
|
||||||
compile.exclude group: 'de.jflex', module: 'jflex'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
@ -86,7 +82,6 @@ dependencies {
|
|||||||
testCompile depends.junit
|
testCompile depends.junit
|
||||||
|
|
||||||
antlr depends.antlr
|
antlr depends.antlr
|
||||||
jflex depends.jflex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources.inputs.property('version', version)
|
processResources.inputs.property('version', version)
|
||||||
@ -119,8 +114,8 @@ generateGrammarSource {
|
|||||||
outputDirectory = new File(outputDirectory, 'org/jf/smali')
|
outputDirectory = new File(outputDirectory, 'org/jf/smali')
|
||||||
}
|
}
|
||||||
|
|
||||||
generateJFlexSource {
|
jflex {
|
||||||
outputDirectory = new File(outputDirectory, 'org/jf/smali')
|
generateDir = new File(generateDir, 'org/jf/smali')
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadArchives {
|
uploadArchives {
|
||||||
|
@ -86,8 +86,6 @@ tokens {
|
|||||||
INSTRUCTION_FORMAT21c_FIELD_ODEX;
|
INSTRUCTION_FORMAT21c_FIELD_ODEX;
|
||||||
INSTRUCTION_FORMAT21c_STRING;
|
INSTRUCTION_FORMAT21c_STRING;
|
||||||
INSTRUCTION_FORMAT21c_TYPE;
|
INSTRUCTION_FORMAT21c_TYPE;
|
||||||
INSTRUCTION_FORMAT21c_LAMBDA;
|
|
||||||
INSTRUCTION_FORMAT21c_METHOD;
|
|
||||||
INSTRUCTION_FORMAT21ih;
|
INSTRUCTION_FORMAT21ih;
|
||||||
INSTRUCTION_FORMAT21lh;
|
INSTRUCTION_FORMAT21lh;
|
||||||
INSTRUCTION_FORMAT21s;
|
INSTRUCTION_FORMAT21s;
|
||||||
@ -96,14 +94,12 @@ tokens {
|
|||||||
INSTRUCTION_FORMAT22c_FIELD;
|
INSTRUCTION_FORMAT22c_FIELD;
|
||||||
INSTRUCTION_FORMAT22c_FIELD_ODEX;
|
INSTRUCTION_FORMAT22c_FIELD_ODEX;
|
||||||
INSTRUCTION_FORMAT22c_TYPE;
|
INSTRUCTION_FORMAT22c_TYPE;
|
||||||
INSTRUCTION_FORMAT22c_STRING;
|
|
||||||
INSTRUCTION_FORMAT22cs_FIELD;
|
INSTRUCTION_FORMAT22cs_FIELD;
|
||||||
INSTRUCTION_FORMAT22s;
|
INSTRUCTION_FORMAT22s;
|
||||||
INSTRUCTION_FORMAT22s_OR_ID;
|
INSTRUCTION_FORMAT22s_OR_ID;
|
||||||
INSTRUCTION_FORMAT22t;
|
INSTRUCTION_FORMAT22t;
|
||||||
INSTRUCTION_FORMAT22x;
|
INSTRUCTION_FORMAT22x;
|
||||||
INSTRUCTION_FORMAT23x;
|
INSTRUCTION_FORMAT23x;
|
||||||
INSTRUCTION_FORMAT25x;
|
|
||||||
INSTRUCTION_FORMAT30t;
|
INSTRUCTION_FORMAT30t;
|
||||||
INSTRUCTION_FORMAT31c;
|
INSTRUCTION_FORMAT31c;
|
||||||
INSTRUCTION_FORMAT31i;
|
INSTRUCTION_FORMAT31i;
|
||||||
@ -120,6 +116,8 @@ tokens {
|
|||||||
INSTRUCTION_FORMAT3rc_TYPE;
|
INSTRUCTION_FORMAT3rc_TYPE;
|
||||||
INSTRUCTION_FORMAT3rmi_METHOD;
|
INSTRUCTION_FORMAT3rmi_METHOD;
|
||||||
INSTRUCTION_FORMAT3rms_METHOD;
|
INSTRUCTION_FORMAT3rms_METHOD;
|
||||||
|
INSTRUCTION_FORMAT45cc_METHOD;
|
||||||
|
INSTRUCTION_FORMAT4rcc_METHOD;
|
||||||
INSTRUCTION_FORMAT51l;
|
INSTRUCTION_FORMAT51l;
|
||||||
LINE_COMMENT;
|
LINE_COMMENT;
|
||||||
LINE_DIRECTIVE;
|
LINE_DIRECTIVE;
|
||||||
@ -210,8 +208,6 @@ tokens {
|
|||||||
I_STATEMENT_FORMAT21c_TYPE;
|
I_STATEMENT_FORMAT21c_TYPE;
|
||||||
I_STATEMENT_FORMAT21c_FIELD;
|
I_STATEMENT_FORMAT21c_FIELD;
|
||||||
I_STATEMENT_FORMAT21c_STRING;
|
I_STATEMENT_FORMAT21c_STRING;
|
||||||
I_STATEMENT_FORMAT21c_LAMBDA;
|
|
||||||
I_STATEMENT_FORMAT21c_METHOD;
|
|
||||||
I_STATEMENT_FORMAT21ih;
|
I_STATEMENT_FORMAT21ih;
|
||||||
I_STATEMENT_FORMAT21lh;
|
I_STATEMENT_FORMAT21lh;
|
||||||
I_STATEMENT_FORMAT21s;
|
I_STATEMENT_FORMAT21s;
|
||||||
@ -219,12 +215,10 @@ tokens {
|
|||||||
I_STATEMENT_FORMAT22b;
|
I_STATEMENT_FORMAT22b;
|
||||||
I_STATEMENT_FORMAT22c_FIELD;
|
I_STATEMENT_FORMAT22c_FIELD;
|
||||||
I_STATEMENT_FORMAT22c_TYPE;
|
I_STATEMENT_FORMAT22c_TYPE;
|
||||||
I_STATEMENT_FORMAT22c_STRING;
|
|
||||||
I_STATEMENT_FORMAT22s;
|
I_STATEMENT_FORMAT22s;
|
||||||
I_STATEMENT_FORMAT22t;
|
I_STATEMENT_FORMAT22t;
|
||||||
I_STATEMENT_FORMAT22x;
|
I_STATEMENT_FORMAT22x;
|
||||||
I_STATEMENT_FORMAT23x;
|
I_STATEMENT_FORMAT23x;
|
||||||
I_STATEMENT_FORMAT25x;
|
|
||||||
I_STATEMENT_FORMAT30t;
|
I_STATEMENT_FORMAT30t;
|
||||||
I_STATEMENT_FORMAT31c;
|
I_STATEMENT_FORMAT31c;
|
||||||
I_STATEMENT_FORMAT31i;
|
I_STATEMENT_FORMAT31i;
|
||||||
@ -234,6 +228,8 @@ tokens {
|
|||||||
I_STATEMENT_FORMAT35c_TYPE;
|
I_STATEMENT_FORMAT35c_TYPE;
|
||||||
I_STATEMENT_FORMAT3rc_METHOD;
|
I_STATEMENT_FORMAT3rc_METHOD;
|
||||||
I_STATEMENT_FORMAT3rc_TYPE;
|
I_STATEMENT_FORMAT3rc_TYPE;
|
||||||
|
I_STATEMENT_FORMAT45cc_METHOD;
|
||||||
|
I_STATEMENT_FORMAT4rcc_METHOD;
|
||||||
I_STATEMENT_FORMAT51l;
|
I_STATEMENT_FORMAT51l;
|
||||||
I_STATEMENT_ARRAY_DATA;
|
I_STATEMENT_ARRAY_DATA;
|
||||||
I_STATEMENT_PACKED_SWITCH;
|
I_STATEMENT_PACKED_SWITCH;
|
||||||
@ -562,18 +558,14 @@ simple_name
|
|||||||
| INSTRUCTION_FORMAT21c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD_ODEX]
|
| INSTRUCTION_FORMAT21c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD_ODEX]
|
||||||
| INSTRUCTION_FORMAT21c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_STRING]
|
| INSTRUCTION_FORMAT21c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_STRING]
|
||||||
| INSTRUCTION_FORMAT21c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_TYPE]
|
| INSTRUCTION_FORMAT21c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_TYPE]
|
||||||
| INSTRUCTION_FORMAT21c_LAMBDA -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_LAMBDA]
|
|
||||||
| INSTRUCTION_FORMAT21c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_METHOD]
|
|
||||||
| INSTRUCTION_FORMAT21t -> SIMPLE_NAME[$INSTRUCTION_FORMAT21t]
|
| INSTRUCTION_FORMAT21t -> SIMPLE_NAME[$INSTRUCTION_FORMAT21t]
|
||||||
| INSTRUCTION_FORMAT22c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD]
|
| INSTRUCTION_FORMAT22c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD]
|
||||||
| INSTRUCTION_FORMAT22c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD_ODEX]
|
| INSTRUCTION_FORMAT22c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD_ODEX]
|
||||||
| INSTRUCTION_FORMAT22c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_TYPE]
|
| INSTRUCTION_FORMAT22c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_TYPE]
|
||||||
| INSTRUCTION_FORMAT22c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_STRING]
|
|
||||||
| INSTRUCTION_FORMAT22cs_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22cs_FIELD]
|
| INSTRUCTION_FORMAT22cs_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22cs_FIELD]
|
||||||
| INSTRUCTION_FORMAT22s_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT22s_OR_ID]
|
| INSTRUCTION_FORMAT22s_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT22s_OR_ID]
|
||||||
| INSTRUCTION_FORMAT22t -> SIMPLE_NAME[$INSTRUCTION_FORMAT22t]
|
| INSTRUCTION_FORMAT22t -> SIMPLE_NAME[$INSTRUCTION_FORMAT22t]
|
||||||
| INSTRUCTION_FORMAT23x -> SIMPLE_NAME[$INSTRUCTION_FORMAT23x]
|
| INSTRUCTION_FORMAT23x -> SIMPLE_NAME[$INSTRUCTION_FORMAT23x]
|
||||||
| INSTRUCTION_FORMAT25x -> SIMPLE_NAME[$INSTRUCTION_FORMAT25x]
|
|
||||||
| INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID]
|
| INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID]
|
||||||
| INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t]
|
| INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t]
|
||||||
| INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD]
|
| INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD]
|
||||||
@ -581,6 +573,8 @@ simple_name
|
|||||||
| INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE]
|
| INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE]
|
||||||
| INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD]
|
| INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD]
|
||||||
| INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD]
|
| INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD]
|
||||||
|
| INSTRUCTION_FORMAT45cc_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT45cc_METHOD]
|
||||||
|
| INSTRUCTION_FORMAT4rcc_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT4rcc_METHOD]
|
||||||
| INSTRUCTION_FORMAT51l -> SIMPLE_NAME[$INSTRUCTION_FORMAT51l];
|
| INSTRUCTION_FORMAT51l -> SIMPLE_NAME[$INSTRUCTION_FORMAT51l];
|
||||||
|
|
||||||
member_name
|
member_name
|
||||||
@ -817,8 +811,6 @@ instruction
|
|||||||
| insn_format21c_field_odex
|
| insn_format21c_field_odex
|
||||||
| insn_format21c_string
|
| insn_format21c_string
|
||||||
| insn_format21c_type
|
| insn_format21c_type
|
||||||
| insn_format21c_lambda
|
|
||||||
| insn_format21c_method
|
|
||||||
| insn_format21ih
|
| insn_format21ih
|
||||||
| insn_format21lh
|
| insn_format21lh
|
||||||
| insn_format21s
|
| insn_format21s
|
||||||
@ -827,13 +819,11 @@ instruction
|
|||||||
| insn_format22c_field
|
| insn_format22c_field
|
||||||
| insn_format22c_field_odex
|
| insn_format22c_field_odex
|
||||||
| insn_format22c_type
|
| insn_format22c_type
|
||||||
| insn_format22c_string
|
|
||||||
| insn_format22cs_field
|
| insn_format22cs_field
|
||||||
| insn_format22s
|
| insn_format22s
|
||||||
| insn_format22t
|
| insn_format22t
|
||||||
| insn_format22x
|
| insn_format22x
|
||||||
| insn_format23x
|
| insn_format23x
|
||||||
| insn_format25x
|
|
||||||
| insn_format30t
|
| insn_format30t
|
||||||
| insn_format31c
|
| insn_format31c
|
||||||
| insn_format31i
|
| insn_format31i
|
||||||
@ -849,6 +839,8 @@ instruction
|
|||||||
| insn_format3rc_type
|
| insn_format3rc_type
|
||||||
| insn_format3rmi_method
|
| insn_format3rmi_method
|
||||||
| insn_format3rms_method
|
| insn_format3rms_method
|
||||||
|
| insn_format45cc_method
|
||||||
|
| insn_format4rcc_method
|
||||||
| insn_format51l
|
| insn_format51l
|
||||||
| insn_array_data_directive
|
| insn_array_data_directive
|
||||||
| insn_packed_switch_directive
|
| insn_packed_switch_directive
|
||||||
@ -927,16 +919,6 @@ insn_format21c_type
|
|||||||
INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA nonvoid_type_descriptor
|
INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA nonvoid_type_descriptor
|
||||||
-> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER nonvoid_type_descriptor);
|
-> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER nonvoid_type_descriptor);
|
||||||
|
|
||||||
insn_format21c_lambda
|
|
||||||
: //e.g. capture-variable v1, "foobar"
|
|
||||||
INSTRUCTION_FORMAT21c_LAMBDA REGISTER COMMA STRING_LITERAL
|
|
||||||
-> ^(I_STATEMENT_FORMAT21c_LAMBDA[$start, "I_STATEMENT_FORMAT21c_LAMBDA"] INSTRUCTION_FORMAT21c_LAMBDA REGISTER STRING_LITERAL);
|
|
||||||
|
|
||||||
insn_format21c_method
|
|
||||||
: //e.g. create-lambda v1, java/io/PrintStream/print(Ljava/lang/Stream;)V
|
|
||||||
INSTRUCTION_FORMAT21c_METHOD REGISTER COMMA method_reference
|
|
||||||
-> ^(I_STATEMENT_FORMAT21c_METHOD[$start, "I_STATEMENT_FORMAT21c_METHOD"] INSTRUCTION_FORMAT21c_METHOD REGISTER method_reference);
|
|
||||||
|
|
||||||
insn_format21ih
|
insn_format21ih
|
||||||
: //e.g. const/high16 v1, 1234
|
: //e.g. const/high16 v1, 1234
|
||||||
INSTRUCTION_FORMAT21ih REGISTER COMMA fixed_32bit_literal
|
INSTRUCTION_FORMAT21ih REGISTER COMMA fixed_32bit_literal
|
||||||
@ -982,11 +964,6 @@ insn_format22c_type
|
|||||||
INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor
|
INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor
|
||||||
-> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor);
|
-> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor);
|
||||||
|
|
||||||
insn_format22c_string
|
|
||||||
: //e.g. liberate-variable v0, v1, "baz"
|
|
||||||
INSTRUCTION_FORMAT22c_STRING REGISTER COMMA REGISTER COMMA STRING_LITERAL
|
|
||||||
-> ^(I_STATEMENT_FORMAT22c_STRING[$start, "I_STATEMENT_FORMAT22c_STRING"] INSTRUCTION_FORMAT22c_STRING REGISTER REGISTER STRING_LITERAL);
|
|
||||||
|
|
||||||
insn_format22cs_field
|
insn_format22cs_field
|
||||||
: //e.g. iget-quick v0, v1, field@0xc
|
: //e.g. iget-quick v0, v1, field@0xc
|
||||||
INSTRUCTION_FORMAT22cs_FIELD REGISTER COMMA REGISTER COMMA FIELD_OFFSET
|
INSTRUCTION_FORMAT22cs_FIELD REGISTER COMMA REGISTER COMMA FIELD_OFFSET
|
||||||
@ -1014,11 +991,6 @@ insn_format23x
|
|||||||
INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER
|
INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER
|
||||||
-> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER);
|
-> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER);
|
||||||
|
|
||||||
insn_format25x
|
|
||||||
: //e.g. invoke-lambda vClosure, {vA, vB, vC, vD} -- up to 4 parameters + the closure.
|
|
||||||
INSTRUCTION_FORMAT25x REGISTER COMMA OPEN_BRACE register_list CLOSE_BRACE
|
|
||||||
-> ^(I_STATEMENT_FORMAT25x[$start, "I_STATEMENT_FORMAT25x"] INSTRUCTION_FORMAT25x REGISTER register_list);
|
|
||||||
|
|
||||||
insn_format30t
|
insn_format30t
|
||||||
: //e.g. goto/32 endloop:
|
: //e.g. goto/32 endloop:
|
||||||
INSTRUCTION_FORMAT30t label_ref
|
INSTRUCTION_FORMAT30t label_ref
|
||||||
@ -1106,6 +1078,16 @@ insn_format3rms_method
|
|||||||
throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rms_METHOD.text);
|
throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rms_METHOD.text);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
insn_format45cc_method
|
||||||
|
: //e.g. invoke-polymorphic {v0..v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J
|
||||||
|
INSTRUCTION_FORMAT45cc_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA method_reference COMMA method_prototype
|
||||||
|
-> ^(I_STATEMENT_FORMAT45cc_METHOD[$start, "I_STATEMENT_FORMAT45cc_METHOD"] INSTRUCTION_FORMAT45cc_METHOD register_list method_reference method_prototype);
|
||||||
|
|
||||||
|
insn_format4rcc_method
|
||||||
|
: //e.g. invoke-polymorphic/range {v0,v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J
|
||||||
|
INSTRUCTION_FORMAT4rcc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA method_reference COMMA method_prototype
|
||||||
|
-> ^(I_STATEMENT_FORMAT4rcc_METHOD[$start, "I_STATEMENT_FORMAT4rcc_METHOD"] INSTRUCTION_FORMAT4rcc_METHOD register_range method_reference method_prototype);
|
||||||
|
|
||||||
insn_format51l
|
insn_format51l
|
||||||
: //e.g. const-wide v0, 5000000000L
|
: //e.g. const-wide v0, 5000000000L
|
||||||
INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal
|
INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal
|
||||||
@ -1141,4 +1123,4 @@ insn_sparse_switch_directive
|
|||||||
(fixed_32bit_literal ARROW label_ref)*
|
(fixed_32bit_literal ARROW label_ref)*
|
||||||
END_SPARSE_SWITCH_DIRECTIVE
|
END_SPARSE_SWITCH_DIRECTIVE
|
||||||
-> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"]
|
-> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"]
|
||||||
^(I_SPARSE_SWITCH_ELEMENTS[$start, "I_SPARSE_SWITCH_ELEMENTS"] (fixed_32bit_literal label_ref)*));
|
^(I_SPARSE_SWITCH_ELEMENTS[$start, "I_SPARSE_SWITCH_ELEMENTS"] (fixed_32bit_literal label_ref)*));
|
||||||
|
@ -62,6 +62,7 @@ import org.jf.dexlib2.immutable.ImmutableAnnotation;
|
|||||||
import org.jf.dexlib2.immutable.ImmutableAnnotationElement;
|
import org.jf.dexlib2.immutable.ImmutableAnnotationElement;
|
||||||
import org.jf.dexlib2.immutable.reference.ImmutableFieldReference;
|
import org.jf.dexlib2.immutable.reference.ImmutableFieldReference;
|
||||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
|
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
|
||||||
|
import org.jf.dexlib2.immutable.reference.ImmutableMethodProtoReference;
|
||||||
import org.jf.dexlib2.immutable.reference.ImmutableReference;
|
import org.jf.dexlib2.immutable.reference.ImmutableReference;
|
||||||
import org.jf.dexlib2.immutable.reference.ImmutableTypeReference;
|
import org.jf.dexlib2.immutable.reference.ImmutableTypeReference;
|
||||||
import org.jf.dexlib2.immutable.value.*;
|
import org.jf.dexlib2.immutable.value.*;
|
||||||
@ -674,22 +675,6 @@ register_list returns[byte[\] registers, byte registerCount]
|
|||||||
$registers[$registerCount++] = parseRegister_nibble($REGISTER.text);
|
$registers[$registerCount++] = parseRegister_nibble($REGISTER.text);
|
||||||
})*);
|
})*);
|
||||||
|
|
||||||
register_list4 returns[byte[\] registers, byte registerCount]
|
|
||||||
@init
|
|
||||||
{
|
|
||||||
$registers = new byte[4];
|
|
||||||
$registerCount = 0;
|
|
||||||
}
|
|
||||||
: ^(I_REGISTER_LIST
|
|
||||||
(REGISTER
|
|
||||||
{
|
|
||||||
if ($registerCount == 4) {
|
|
||||||
throw new SemanticException(input, $I_REGISTER_LIST, "A list4 of registers can only have a maximum of 4 " +
|
|
||||||
"registers. Use the <op>/range alternate opcode instead.");
|
|
||||||
}
|
|
||||||
$registers[$registerCount++] = parseRegister_nibble($REGISTER.text);
|
|
||||||
})*);
|
|
||||||
|
|
||||||
register_range returns[int startRegister, int endRegister]
|
register_range returns[int startRegister, int endRegister]
|
||||||
: ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?)
|
: ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?)
|
||||||
{
|
{
|
||||||
@ -742,8 +727,6 @@ instruction
|
|||||||
| insn_format21c_field
|
| insn_format21c_field
|
||||||
| insn_format21c_string
|
| insn_format21c_string
|
||||||
| insn_format21c_type
|
| insn_format21c_type
|
||||||
| insn_format21c_lambda
|
|
||||||
| insn_format21c_method
|
|
||||||
| insn_format21ih
|
| insn_format21ih
|
||||||
| insn_format21lh
|
| insn_format21lh
|
||||||
| insn_format21s
|
| insn_format21s
|
||||||
@ -751,12 +734,10 @@ instruction
|
|||||||
| insn_format22b
|
| insn_format22b
|
||||||
| insn_format22c_field
|
| insn_format22c_field
|
||||||
| insn_format22c_type
|
| insn_format22c_type
|
||||||
| insn_format22c_string
|
|
||||||
| insn_format22s
|
| insn_format22s
|
||||||
| insn_format22t
|
| insn_format22t
|
||||||
| insn_format22x
|
| insn_format22x
|
||||||
| insn_format23x
|
| insn_format23x
|
||||||
| insn_format25x
|
|
||||||
| insn_format30t
|
| insn_format30t
|
||||||
| insn_format31c
|
| insn_format31c
|
||||||
| insn_format31i
|
| insn_format31i
|
||||||
@ -766,6 +747,8 @@ instruction
|
|||||||
| insn_format35c_type
|
| insn_format35c_type
|
||||||
| insn_format3rc_method
|
| insn_format3rc_method
|
||||||
| insn_format3rc_type
|
| insn_format3rc_type
|
||||||
|
| insn_format45cc_method
|
||||||
|
| insn_format4rcc_method
|
||||||
| insn_format51l_type
|
| insn_format51l_type
|
||||||
| insn_array_data_directive
|
| insn_array_data_directive
|
||||||
| insn_packed_switch_directive
|
| insn_packed_switch_directive
|
||||||
@ -881,30 +864,6 @@ insn_format21c_type
|
|||||||
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
|
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
|
||||||
};
|
};
|
||||||
|
|
||||||
insn_format21c_lambda
|
|
||||||
: //e.g. capture-variable v1, "foobar"
|
|
||||||
^(I_STATEMENT_FORMAT21c_LAMBDA INSTRUCTION_FORMAT21c_LAMBDA REGISTER string_literal)
|
|
||||||
{
|
|
||||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_LAMBDA.text);
|
|
||||||
short regA = parseRegister_byte($REGISTER.text);
|
|
||||||
|
|
||||||
$method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
|
|
||||||
dexBuilder.internStringReference($string_literal.value)));
|
|
||||||
};
|
|
||||||
|
|
||||||
insn_format21c_method
|
|
||||||
: //e.g. create-lambda v1, java/io/PrintStream/print(Ljava/lang/Stream;)V
|
|
||||||
^(I_STATEMENT_FORMAT21c_METHOD INSTRUCTION_FORMAT21c_METHOD REGISTER method_reference)
|
|
||||||
{
|
|
||||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_METHOD.text);
|
|
||||||
short regA = parseRegister_byte($REGISTER.text);
|
|
||||||
|
|
||||||
ImmutableMethodReference methodReference = $method_reference.methodReference;
|
|
||||||
|
|
||||||
$method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
|
|
||||||
dexBuilder.internMethodReference(methodReference)));
|
|
||||||
};
|
|
||||||
|
|
||||||
insn_format21ih
|
insn_format21ih
|
||||||
: //e.g. const/high16 v1, 1234
|
: //e.g. const/high16 v1, 1234
|
||||||
^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal)
|
^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal)
|
||||||
@ -991,18 +950,6 @@ insn_format22c_type
|
|||||||
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
|
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
|
||||||
};
|
};
|
||||||
|
|
||||||
insn_format22c_string
|
|
||||||
: //e.g. liberate-variable v0, v1, "baz"
|
|
||||||
^(I_STATEMENT_FORMAT22c_STRING INSTRUCTION_FORMAT22c_STRING registerA=REGISTER registerB=REGISTER string_literal)
|
|
||||||
{
|
|
||||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22c_STRING.text);
|
|
||||||
byte regA = parseRegister_nibble($registerA.text);
|
|
||||||
byte regB = parseRegister_nibble($registerB.text);
|
|
||||||
|
|
||||||
$method::methodBuilder.addInstruction(new BuilderInstruction22c(opcode, regA, regB,
|
|
||||||
dexBuilder.internStringReference($string_literal.value)));
|
|
||||||
};
|
|
||||||
|
|
||||||
insn_format22s
|
insn_format22s
|
||||||
: //e.g. add-int/lit16 v0, v1, 12345
|
: //e.g. add-int/lit16 v0, v1, 12345
|
||||||
^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal)
|
^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal)
|
||||||
@ -1050,23 +997,6 @@ insn_format23x
|
|||||||
$method::methodBuilder.addInstruction(new BuilderInstruction23x(opcode, regA, regB, regC));
|
$method::methodBuilder.addInstruction(new BuilderInstruction23x(opcode, regA, regB, regC));
|
||||||
};
|
};
|
||||||
|
|
||||||
insn_format25x
|
|
||||||
: //e.g. invoke-lambda vClosure, {vD, vE, vF, vG} -- up to 4 parameters + the closure.
|
|
||||||
^(I_STATEMENT_FORMAT25x INSTRUCTION_FORMAT25x REGISTER register_list4)
|
|
||||||
{
|
|
||||||
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT25x.text);
|
|
||||||
|
|
||||||
byte closureRegister = parseRegister_nibble($REGISTER.text);
|
|
||||||
|
|
||||||
//this depends on the fact that register_list4 returns a byte[4]
|
|
||||||
byte[] registers = $register_list4.registers;
|
|
||||||
int parameterRegisterCount = $register_list4.registerCount; // don't count closure register
|
|
||||||
|
|
||||||
$method::methodBuilder.addInstruction(new BuilderInstruction25x(opcode,
|
|
||||||
parameterRegisterCount, closureRegister, registers[0], registers[1],
|
|
||||||
registers[2], registers[3]));
|
|
||||||
};
|
|
||||||
|
|
||||||
insn_format30t
|
insn_format30t
|
||||||
: //e.g. goto/32 endloop:
|
: //e.g. goto/32 endloop:
|
||||||
^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t label_ref)
|
^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t label_ref)
|
||||||
@ -1181,6 +1111,47 @@ insn_format3rc_type
|
|||||||
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
|
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
insn_format45cc_method
|
||||||
|
: //e.g. invoke-polymorphic {v0, v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J
|
||||||
|
^(I_STATEMENT_FORMAT45cc_METHOD INSTRUCTION_FORMAT45cc_METHOD register_list method_reference method_prototype)
|
||||||
|
{
|
||||||
|
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT45cc_METHOD.text);
|
||||||
|
|
||||||
|
//this depends on the fact that register_list returns a byte[5]
|
||||||
|
byte[] registers = $register_list.registers;
|
||||||
|
byte registerCount = $register_list.registerCount;
|
||||||
|
|
||||||
|
ImmutableMethodReference methodReference = $method_reference.methodReference;
|
||||||
|
ImmutableMethodProtoReference methodProtoReference = new ImmutableMethodProtoReference(
|
||||||
|
$method_prototype.parameters,
|
||||||
|
$method_prototype.returnType);
|
||||||
|
|
||||||
|
$method::methodBuilder.addInstruction(new BuilderInstruction45cc(opcode, registerCount, registers[0], registers[1],
|
||||||
|
registers[2], registers[3], registers[4],
|
||||||
|
dexBuilder.internMethodReference(methodReference),
|
||||||
|
dexBuilder.internMethodProtoReference(methodProtoReference)));
|
||||||
|
};
|
||||||
|
|
||||||
|
insn_format4rcc_method
|
||||||
|
: //e.g. invoke-polymorphic {v0..v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J
|
||||||
|
^(I_STATEMENT_FORMAT4rcc_METHOD INSTRUCTION_FORMAT4rcc_METHOD register_range method_reference method_prototype)
|
||||||
|
{
|
||||||
|
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT4rcc_METHOD.text);
|
||||||
|
int startRegister = $register_range.startRegister;
|
||||||
|
int endRegister = $register_range.endRegister;
|
||||||
|
|
||||||
|
int registerCount = endRegister-startRegister+1;
|
||||||
|
|
||||||
|
ImmutableMethodReference methodReference = $method_reference.methodReference;
|
||||||
|
ImmutableMethodProtoReference methodProtoReference = new ImmutableMethodProtoReference(
|
||||||
|
$method_prototype.parameters,
|
||||||
|
$method_prototype.returnType);
|
||||||
|
|
||||||
|
$method::methodBuilder.addInstruction(new BuilderInstruction4rcc(opcode, startRegister, registerCount,
|
||||||
|
dexBuilder.internMethodReference(methodReference),
|
||||||
|
dexBuilder.internMethodProtoReference(methodProtoReference)));
|
||||||
|
};
|
||||||
|
|
||||||
insn_format51l_type
|
insn_format51l_type
|
||||||
: //e.g. const-wide v0, 5000000000L
|
: //e.g. const-wide v0, 5000000000L
|
||||||
^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal)
|
^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal)
|
||||||
|
@ -476,14 +476,6 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
|
|||||||
return newToken(INSTRUCTION_FORMAT21c_TYPE);
|
return newToken(INSTRUCTION_FORMAT21c_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
"capture-variable" { // e.g. 'capture-variable vB, <string id>'
|
|
||||||
return newToken(INSTRUCTION_FORMAT21c_LAMBDA);
|
|
||||||
}
|
|
||||||
|
|
||||||
"create-lambda" { // e.g. 'create-lambda vClosure, <method id>'
|
|
||||||
return newToken(INSTRUCTION_FORMAT21c_METHOD);
|
|
||||||
}
|
|
||||||
|
|
||||||
"const/high16" {
|
"const/high16" {
|
||||||
return newToken(INSTRUCTION_FORMAT21ih);
|
return newToken(INSTRUCTION_FORMAT21ih);
|
||||||
}
|
}
|
||||||
@ -515,14 +507,10 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
|
|||||||
return newToken(INSTRUCTION_FORMAT22c_FIELD_ODEX);
|
return newToken(INSTRUCTION_FORMAT22c_FIELD_ODEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
"instance-of" | "new-array" | "unbox-lambda" {
|
"instance-of" | "new-array" {
|
||||||
return newToken(INSTRUCTION_FORMAT22c_TYPE);
|
return newToken(INSTRUCTION_FORMAT22c_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
"liberate-variable" {
|
|
||||||
return newToken(INSTRUCTION_FORMAT22c_STRING);
|
|
||||||
}
|
|
||||||
|
|
||||||
"iget-quick" | "iget-wide-quick" | "iget-object-quick" | "iput-quick" | "iput-wide-quick" | "iput-object-quick" |
|
"iget-quick" | "iget-wide-quick" | "iget-object-quick" | "iput-quick" | "iput-wide-quick" | "iput-object-quick" |
|
||||||
"iput-boolean-quick" | "iput-byte-quick" | "iput-char-quick" | "iput-short-quick" {
|
"iput-boolean-quick" | "iput-byte-quick" | "iput-char-quick" | "iput-short-quick" {
|
||||||
return newToken(INSTRUCTION_FORMAT22cs_FIELD);
|
return newToken(INSTRUCTION_FORMAT22cs_FIELD);
|
||||||
@ -541,7 +529,7 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
|
|||||||
return newToken(INSTRUCTION_FORMAT22t);
|
return newToken(INSTRUCTION_FORMAT22t);
|
||||||
}
|
}
|
||||||
|
|
||||||
"move/from16" | "move-wide/from16" | "move-object/from16" | "box-lambda" {
|
"move/from16" | "move-wide/from16" | "move-object/from16" {
|
||||||
return newToken(INSTRUCTION_FORMAT22x);
|
return newToken(INSTRUCTION_FORMAT22x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,10 +543,6 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
|
|||||||
return newToken(INSTRUCTION_FORMAT23x);
|
return newToken(INSTRUCTION_FORMAT23x);
|
||||||
}
|
}
|
||||||
|
|
||||||
"invoke-lambda" { // e.g. invoke-lambda vClosure, {vD, vE, vF, vG} -- at most 4 params
|
|
||||||
return newToken(INSTRUCTION_FORMAT25x);
|
|
||||||
}
|
|
||||||
|
|
||||||
"goto/32" {
|
"goto/32" {
|
||||||
return newToken(INSTRUCTION_FORMAT30t);
|
return newToken(INSTRUCTION_FORMAT30t);
|
||||||
}
|
}
|
||||||
@ -624,6 +608,14 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
|
|||||||
return newToken(INSTRUCTION_FORMAT3rms_METHOD);
|
return newToken(INSTRUCTION_FORMAT3rms_METHOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"invoke-polymorphic" {
|
||||||
|
return newToken(INSTRUCTION_FORMAT45cc_METHOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
"invoke-polymorphic/range" {
|
||||||
|
return newToken(INSTRUCTION_FORMAT4rcc_METHOD);
|
||||||
|
}
|
||||||
|
|
||||||
"const-wide" {
|
"const-wide" {
|
||||||
return newToken(INSTRUCTION_FORMAT51l);
|
return newToken(INSTRUCTION_FORMAT51l);
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
* [The "BSD licence"]
|
* Copyright 2016, Google Inc.
|
||||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions are
|
||||||
* are met:
|
* met:
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
* Redistributions of source code must retain the above copyright
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
* Redistributions in binary form must reproduce the above
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
* in the documentation and/or other materials provided with the
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
* distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.jf.smali.LiteralTools;
|
package org.jf.smali;import org.jf.smali.LiteralTools;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -1,18 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2014, Google Inc.
|
* Copyright 2016, Google Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
* met:
|
* met:
|
||||||
*
|
*
|
||||||
* * Redistributions of source code must retain the above copyright
|
* Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above
|
* Redistributions in binary form must reproduce the above
|
||||||
* copyright notice, this list of conditions and the following disclaimer
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
* in the documentation and/or other materials provided with the
|
* in the documentation and/or other materials provided with the
|
||||||
* distribution.
|
* distribution.
|
||||||
* * Neither the name of Google Inc. nor the names of its
|
* Neither the name of Google Inc. nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from
|
* contributors may be used to endorse or promote products derived from
|
||||||
* this software without specific prior written permission.
|
* this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
@ -29,7 +29,7 @@
|
|||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
package org.jf.smali;import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
import org.antlr.runtime.RecognitionException;
|
import org.antlr.runtime.RecognitionException;
|
@ -1,32 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
* [The "BSD licence"]
|
* Copyright 2016, Google Inc.
|
||||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions are
|
||||||
* are met:
|
* met:
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
* Redistributions of source code must retain the above copyright
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
* Redistributions in binary form must reproduce the above
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
* in the documentation and/or other materials provided with the
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
* distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.jf.smali.LiteralTools;
|
package org.jf.smali;import org.jf.smali.LiteralTools;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -1,39 +1,38 @@
|
|||||||
/*
|
/*
|
||||||
* [The "BSD licence"]
|
* Copyright 2016, Google Inc.
|
||||||
* Copyright (c) 2010 Ben Gruver
|
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions are
|
||||||
* are met:
|
* met:
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
* Redistributions of source code must retain the above copyright
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
* Redistributions in binary form must reproduce the above
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
* in the documentation and/or other materials provided with the
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
* distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.antlr.runtime.ANTLRInputStream;
|
package org.jf.smali;import org.antlr.runtime.ANTLRInputStream;
|
||||||
import org.antlr.runtime.CommonToken;
|
import org.antlr.runtime.CommonToken;
|
||||||
import org.antlr.runtime.CommonTokenStream;
|
import org.antlr.runtime.CommonTokenStream;
|
||||||
import org.antlr.runtime.RecognitionException;
|
import org.antlr.runtime.RecognitionException;
|
||||||
import org.jf.smali.expectedTokensTestGrammarLexer;
|
|
||||||
import org.jf.smali.expectedTokensTestGrammarParser;
|
|
||||||
import org.jf.smali.smaliFlexLexer;
|
|
||||||
import org.jf.smali.smaliParser;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -135,9 +134,9 @@ public class LexerTest {
|
|||||||
String smaliFile = String.format("LexerTest%s%s.smali", File.separatorChar, test);
|
String smaliFile = String.format("LexerTest%s%s.smali", File.separatorChar, test);
|
||||||
String tokensFile = String.format("LexerTest%s%s.tokens", File.separatorChar, test);
|
String tokensFile = String.format("LexerTest%s%s.tokens", File.separatorChar, test);
|
||||||
|
|
||||||
expectedTokensTestGrammarLexer expectedTokensLexer = null;
|
org.jf.smali.expectedTokensTestGrammarLexer expectedTokensLexer = null;
|
||||||
try {
|
try {
|
||||||
expectedTokensLexer = new expectedTokensTestGrammarLexer(new ANTLRInputStream(
|
expectedTokensLexer = new org.jf.smali.expectedTokensTestGrammarLexer(new ANTLRInputStream(
|
||||||
LexerTest.class.getClassLoader().getResourceAsStream(tokensFile)));
|
LexerTest.class.getClassLoader().getResourceAsStream(tokensFile)));
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
@ -145,8 +144,8 @@ public class LexerTest {
|
|||||||
|
|
||||||
CommonTokenStream expectedTokensStream = new CommonTokenStream(expectedTokensLexer);
|
CommonTokenStream expectedTokensStream = new CommonTokenStream(expectedTokensLexer);
|
||||||
|
|
||||||
expectedTokensTestGrammarParser expectedTokensParser =
|
org.jf.smali.expectedTokensTestGrammarParser expectedTokensParser =
|
||||||
new expectedTokensTestGrammarParser(expectedTokensStream);
|
new org.jf.smali.expectedTokensTestGrammarParser(expectedTokensStream);
|
||||||
try {
|
try {
|
||||||
expectedTokensParser.top();
|
expectedTokensParser.top();
|
||||||
} catch (RecognitionException ex) {
|
} catch (RecognitionException ex) {
|
@ -1,32 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
* [The "BSD licence"]
|
* Copyright 2016, Google Inc.
|
||||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions are
|
||||||
* are met:
|
* met:
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
* Redistributions of source code must retain the above copyright
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
* Redistributions in binary form must reproduce the above
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
* in the documentation and/or other materials provided with the
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
* distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.jf.smali.LiteralTools;
|
package org.jf.smali;import org.jf.smali.LiteralTools;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -1,32 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
* [The "BSD licence"]
|
* Copyright 2016, Google Inc.
|
||||||
* Copyright (c) 2010 Ben Gruver (JesusFreke)
|
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions are
|
||||||
* are met:
|
* met:
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
* Redistributions of source code must retain the above copyright
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
* Redistributions in binary form must reproduce the above
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
* in the documentation and/or other materials provided with the
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
* distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.jf.smali.LiteralTools;
|
package org.jf.smali;import org.jf.smali.LiteralTools;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -85,8 +85,6 @@ const-string
|
|||||||
check-cast
|
check-cast
|
||||||
new-instance
|
new-instance
|
||||||
const-class
|
const-class
|
||||||
capture-variable
|
|
||||||
create-lambda
|
|
||||||
const/high16
|
const/high16
|
||||||
const-wide/high16
|
const-wide/high16
|
||||||
const/16
|
const/16
|
||||||
@ -125,8 +123,6 @@ iput-wide-volatile
|
|||||||
iput-object-volatile
|
iput-object-volatile
|
||||||
instance-of
|
instance-of
|
||||||
new-array
|
new-array
|
||||||
unbox-lambda
|
|
||||||
liberate-variable
|
|
||||||
iget-quick
|
iget-quick
|
||||||
iget-wide-quick
|
iget-wide-quick
|
||||||
iget-object-quick
|
iget-object-quick
|
||||||
@ -153,7 +149,6 @@ if-le
|
|||||||
move/from16
|
move/from16
|
||||||
move-wide/from16
|
move-wide/from16
|
||||||
move-object/from16
|
move-object/from16
|
||||||
box-lambda
|
|
||||||
cmpl-float
|
cmpl-float
|
||||||
cmpg-float
|
cmpg-float
|
||||||
cmpl-double
|
cmpl-double
|
||||||
@ -204,7 +199,6 @@ add-double
|
|||||||
sub-double
|
sub-double
|
||||||
mul-double
|
mul-double
|
||||||
div-double
|
div-double
|
||||||
invoke-lambda
|
|
||||||
goto/32
|
goto/32
|
||||||
const-string/jumbo
|
const-string/jumbo
|
||||||
const
|
const
|
||||||
|
@ -85,8 +85,6 @@ INSTRUCTION_FORMAT21c_STRING("const-string")
|
|||||||
INSTRUCTION_FORMAT21c_TYPE("check-cast")
|
INSTRUCTION_FORMAT21c_TYPE("check-cast")
|
||||||
INSTRUCTION_FORMAT21c_TYPE("new-instance")
|
INSTRUCTION_FORMAT21c_TYPE("new-instance")
|
||||||
INSTRUCTION_FORMAT21c_TYPE("const-class")
|
INSTRUCTION_FORMAT21c_TYPE("const-class")
|
||||||
INSTRUCTION_FORMAT21c_LAMBDA("capture-variable")
|
|
||||||
INSTRUCTION_FORMAT21c_METHOD("create-lambda")
|
|
||||||
INSTRUCTION_FORMAT21ih("const/high16")
|
INSTRUCTION_FORMAT21ih("const/high16")
|
||||||
INSTRUCTION_FORMAT21lh("const-wide/high16")
|
INSTRUCTION_FORMAT21lh("const-wide/high16")
|
||||||
INSTRUCTION_FORMAT21s("const/16")
|
INSTRUCTION_FORMAT21s("const/16")
|
||||||
@ -125,8 +123,6 @@ INSTRUCTION_FORMAT22c_FIELD_ODEX("iput-wide-volatile")
|
|||||||
INSTRUCTION_FORMAT22c_FIELD_ODEX("iput-object-volatile")
|
INSTRUCTION_FORMAT22c_FIELD_ODEX("iput-object-volatile")
|
||||||
INSTRUCTION_FORMAT22c_TYPE("instance-of")
|
INSTRUCTION_FORMAT22c_TYPE("instance-of")
|
||||||
INSTRUCTION_FORMAT22c_TYPE("new-array")
|
INSTRUCTION_FORMAT22c_TYPE("new-array")
|
||||||
INSTRUCTION_FORMAT22c_TYPE("unbox-lambda")
|
|
||||||
INSTRUCTION_FORMAT22c_STRING("liberate-variable")
|
|
||||||
INSTRUCTION_FORMAT22cs_FIELD("iget-quick")
|
INSTRUCTION_FORMAT22cs_FIELD("iget-quick")
|
||||||
INSTRUCTION_FORMAT22cs_FIELD("iget-wide-quick")
|
INSTRUCTION_FORMAT22cs_FIELD("iget-wide-quick")
|
||||||
INSTRUCTION_FORMAT22cs_FIELD("iget-object-quick")
|
INSTRUCTION_FORMAT22cs_FIELD("iget-object-quick")
|
||||||
@ -153,7 +149,6 @@ INSTRUCTION_FORMAT22t("if-le")
|
|||||||
INSTRUCTION_FORMAT22x("move/from16")
|
INSTRUCTION_FORMAT22x("move/from16")
|
||||||
INSTRUCTION_FORMAT22x("move-wide/from16")
|
INSTRUCTION_FORMAT22x("move-wide/from16")
|
||||||
INSTRUCTION_FORMAT22x("move-object/from16")
|
INSTRUCTION_FORMAT22x("move-object/from16")
|
||||||
INSTRUCTION_FORMAT22x("box-lambda")
|
|
||||||
INSTRUCTION_FORMAT23x("cmpl-float")
|
INSTRUCTION_FORMAT23x("cmpl-float")
|
||||||
INSTRUCTION_FORMAT23x("cmpg-float")
|
INSTRUCTION_FORMAT23x("cmpg-float")
|
||||||
INSTRUCTION_FORMAT23x("cmpl-double")
|
INSTRUCTION_FORMAT23x("cmpl-double")
|
||||||
@ -204,7 +199,6 @@ INSTRUCTION_FORMAT23x("add-double")
|
|||||||
INSTRUCTION_FORMAT23x("sub-double")
|
INSTRUCTION_FORMAT23x("sub-double")
|
||||||
INSTRUCTION_FORMAT23x("mul-double")
|
INSTRUCTION_FORMAT23x("mul-double")
|
||||||
INSTRUCTION_FORMAT23x("div-double")
|
INSTRUCTION_FORMAT23x("div-double")
|
||||||
INSTRUCTION_FORMAT25x("invoke-lambda")
|
|
||||||
INSTRUCTION_FORMAT30t("goto/32")
|
INSTRUCTION_FORMAT30t("goto/32")
|
||||||
INSTRUCTION_FORMAT31c("const-string/jumbo")
|
INSTRUCTION_FORMAT31c("const-string/jumbo")
|
||||||
INSTRUCTION_FORMAT31i_OR_ID("const")
|
INSTRUCTION_FORMAT31i_OR_ID("const")
|
||||||
|
@ -93,7 +93,7 @@ if (!('idea' in gradle.startParameter.taskNames)) {
|
|||||||
apply plugin: 'org.jetbrains.intellij'
|
apply plugin: 'org.jetbrains.intellij'
|
||||||
|
|
||||||
intellij {
|
intellij {
|
||||||
version 'IC-14.1.4'
|
version 'IC-15.0.6'
|
||||||
pluginName 'smalidea'
|
pluginName 'smalidea'
|
||||||
|
|
||||||
updateSinceUntilBuild false
|
updateSinceUntilBuild false
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -102,13 +102,16 @@ public class LazyValue<T extends Value> implements Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private T getNullableValue() {
|
protected T getNullableValue(boolean allowNull) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
try {
|
try {
|
||||||
if (evaluationContext == null) {
|
if (evaluationContext == null) {
|
||||||
final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(project).getContext();
|
final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(project).getContext();
|
||||||
evaluationContext = debuggerContext.createEvaluationContext();
|
evaluationContext = debuggerContext.createEvaluationContext();
|
||||||
if (evaluationContext == null) {
|
if (evaluationContext == null) {
|
||||||
|
if (!allowNull) {
|
||||||
|
throw new IllegalStateException("Can't create evaluation context");
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,6 +119,9 @@ public class LazyValue<T extends Value> implements Value {
|
|||||||
value = SmaliCodeFragmentFactory.evaluateRegister(evaluationContext, method, registerNumber, type);
|
value = SmaliCodeFragmentFactory.evaluateRegister(evaluationContext, method, registerNumber, type);
|
||||||
evaluationContext = null;
|
evaluationContext = null;
|
||||||
} catch (EvaluateException ex) {
|
} catch (EvaluateException ex) {
|
||||||
|
if (!allowNull) {
|
||||||
|
throw new IllegalStateException(ex);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +130,7 @@ public class LazyValue<T extends Value> implements Value {
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
protected T getValue() {
|
protected T getValue() {
|
||||||
T value = getNullableValue();
|
T value = getNullableValue(false);
|
||||||
assert value != null;
|
assert value != null;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -154,7 +160,7 @@ public class LazyValue<T extends Value> implements Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean equals(Object obj) {
|
@Override public boolean equals(Object obj) {
|
||||||
Value value = getNullableValue();
|
Value value = getNullableValue(true);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return value.equals(obj);
|
return value.equals(obj);
|
||||||
}
|
}
|
||||||
@ -162,7 +168,7 @@ public class LazyValue<T extends Value> implements Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int hashCode() {
|
@Override public int hashCode() {
|
||||||
Value value = getNullableValue();
|
Value value = getNullableValue(true);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return value.hashCode();
|
return value.hashCode();
|
||||||
}
|
}
|
||||||
@ -170,7 +176,7 @@ public class LazyValue<T extends Value> implements Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public String toString() {
|
@Override public String toString() {
|
||||||
Value value = getNullableValue();
|
Value value = getNullableValue(true);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return value.toString();
|
return value.toString();
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.debugger.SourcePosition;
|
import com.intellij.debugger.SourcePosition;
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
|
import com.intellij.navigation.ItemPresentation;
|
||||||
|
import com.intellij.navigation.ItemPresentationProviders;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
@ -86,6 +88,10 @@ public class SmaliClass extends SmaliStubBasedPsiElement<SmaliClassStub> impleme
|
|||||||
return name.substring(lastDot+1);
|
return name.substring(lastDot+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public ItemPresentation getPresentation() {
|
||||||
|
return ItemPresentationProviders.getItemPresentation(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable @Override public String getQualifiedName() {
|
@Nullable @Override public String getQualifiedName() {
|
||||||
SmaliClassStatement classStatement = getStubOrPsiChild(SmaliElementTypes.CLASS_STATEMENT);
|
SmaliClassStatement classStatement = getStubOrPsiChild(SmaliElementTypes.CLASS_STATEMENT);
|
||||||
if (classStatement == null) {
|
if (classStatement == null) {
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
package org.jf.smalidea.util;
|
package org.jf.smalidea.util;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.intellij.openapi.project.DumbService;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.impl.ResolveScopeManager;
|
import com.intellij.psi.impl.ResolveScopeManager;
|
||||||
@ -129,6 +130,10 @@ public class NameUtils {
|
|||||||
|
|
||||||
public static PsiClass resolveSmaliType(@NotNull Project project, @NotNull GlobalSearchScope scope,
|
public static PsiClass resolveSmaliType(@NotNull Project project, @NotNull GlobalSearchScope scope,
|
||||||
@NotNull String smaliType) {
|
@NotNull String smaliType) {
|
||||||
|
if (DumbService.isDumb(project)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||||
|
|
||||||
String javaType = NameUtils.smaliToJavaType(smaliType);
|
String javaType = NameUtils.smaliToJavaType(smaliType);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
]]>
|
]]>
|
||||||
</change-notes>
|
</change-notes>
|
||||||
|
|
||||||
<idea-version since-build="131"/>
|
<idea-version since-build="143"/>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<fileTypeFactory implementation="org.jf.smalidea.SmaliFileTypeFactory"/>
|
<fileTypeFactory implementation="org.jf.smalidea.SmaliFileTypeFactory"/>
|
||||||
@ -23,8 +23,7 @@
|
|||||||
<java.elementFinder implementation="org.jf.smalidea.psi.index.SmaliClassFinder"/>
|
<java.elementFinder implementation="org.jf.smalidea.psi.index.SmaliClassFinder"/>
|
||||||
<stubIndex implementation="org.jf.smalidea.psi.index.SmaliClassNameIndex"/>
|
<stubIndex implementation="org.jf.smalidea.psi.index.SmaliClassNameIndex"/>
|
||||||
<debugger.positionManagerFactory implementation="org.jf.smalidea.debugging.SmaliPositionManagerFactory"/>
|
<debugger.positionManagerFactory implementation="org.jf.smalidea.debugging.SmaliPositionManagerFactory"/>
|
||||||
<xdebugger.debuggerSupport id="SmaliDebuggerSupport" order="first,before XDebuggerSupport"
|
<debugger.jvmSteppingCommandProvider implementation="org.jf.smalidea.debugging.SmaliSteppingCommandProvider"/>
|
||||||
implementation="org.jf.smalidea.debugging.SmaliDebuggerSupport"/>
|
|
||||||
<debugger.codeFragmentFactory implementation="org.jf.smalidea.debugging.SmaliCodeFragmentFactory"/>
|
<debugger.codeFragmentFactory implementation="org.jf.smalidea.debugging.SmaliCodeFragmentFactory"/>
|
||||||
<stubElementTypeHolder class="org.jf.smalidea.psi.SmaliElementTypes" />
|
<stubElementTypeHolder class="org.jf.smalidea.psi.SmaliElementTypes" />
|
||||||
<lang.findUsagesProvider language="smali"
|
<lang.findUsagesProvider language="smali"
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
package org.jf.smalidea;
|
package org.jf.smalidea;
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.DumbServiceImpl;
|
||||||
import com.intellij.openapi.projectRoots.Sdk;
|
import com.intellij.openapi.projectRoots.Sdk;
|
||||||
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
|
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
|
||||||
import com.intellij.psi.JavaResolveResult;
|
import com.intellij.psi.JavaResolveResult;
|
||||||
@ -66,6 +67,24 @@ public class ClassReferenceTest extends ResolveTestCase {
|
|||||||
Assert.assertEquals("java.lang.Object", ((PsiClass)resolveResults[0].getElement()).getQualifiedName());
|
Assert.assertEquals("java.lang.Object", ((PsiClass)resolveResults[0].getElement()).getQualifiedName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a reference to a java class from a smali class, while in dumb mode
|
||||||
|
*/
|
||||||
|
public void testJavaReferenceFromSmaliInDumbMode() throws Exception {
|
||||||
|
SmaliClassTypeElement typeElement = (SmaliClassTypeElement)configureByFileText(
|
||||||
|
".class public Lblah; .super L<ref>java/lang/Object;", "blah.smali");
|
||||||
|
|
||||||
|
Assert.assertNotNull(typeElement);
|
||||||
|
Assert.assertEquals("Object", typeElement.getName());
|
||||||
|
|
||||||
|
DumbServiceImpl.getInstance(getProject()).setDumb(true);
|
||||||
|
|
||||||
|
PsiClass psiClass = typeElement.resolve();
|
||||||
|
Assert.assertNull(psiClass);
|
||||||
|
|
||||||
|
DumbServiceImpl.getInstance(getProject()).setDumb(false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test a reference to a smali class from a smali class
|
* Test a reference to a smali class from a smali class
|
||||||
*/
|
*/
|
||||||
@ -105,6 +124,8 @@ public class ClassReferenceTest extends ResolveTestCase {
|
|||||||
Assert.assertEquals("blarg", smaliClass.getQualifiedName());
|
Assert.assertEquals("blarg", smaliClass.getQualifiedName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Sdk getTestProjectJdk() {
|
protected Sdk getTestProjectJdk() {
|
||||||
return JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();
|
return JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user