mirror of
https://github.com/revanced/smali.git
synced 2025-05-08 10:24:31 +02:00
Changed the "from-scratch" constructor in the format classes to a static emit method
git-svn-id: https://smali.googlecode.com/svn/trunk@410 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
parent
f75a5c351c
commit
83e6f4bb60
@ -31,6 +31,7 @@ package org.jf.dexlib.Code.Format;
|
|||||||
import org.jf.dexlib.Code.Instruction;
|
import org.jf.dexlib.Code.Instruction;
|
||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -44,27 +45,18 @@ public class ArrayDataPseudoInstruction extends Instruction {
|
|||||||
return size + (size & 0x01) + 8;
|
return size + (size & 0x01) + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayDataPseudoInstruction(int elementWidth, byte[] encodedValues) {
|
public static void emit(Output out, int elementWidth, byte[] encodedValues) {
|
||||||
super(Opcode.NOP, encodedValues.length + (encodedValues.length & 1) + 8);
|
|
||||||
|
|
||||||
if (encodedValues.length % elementWidth != 0) {
|
if (encodedValues.length % elementWidth != 0) {
|
||||||
throw new RuntimeException("There are not a whole number of " + elementWidth + " byte elements");
|
throw new RuntimeException("There are not a whole number of " + elementWidth + " byte elements");
|
||||||
}
|
}
|
||||||
|
|
||||||
int elementCount = buffer.length / elementWidth;
|
int elementCount = encodedValues.length / elementWidth;
|
||||||
|
|
||||||
buffer[0] = 0x00;
|
out.writeByte(0x00);
|
||||||
buffer[1] = 0x03; //fill-array-data psuedo-opcode
|
out.writeShort(0x03);
|
||||||
|
out.writeShort(elementWidth);
|
||||||
buffer[2] = (byte) elementWidth;
|
out.writeInt(elementCount);
|
||||||
buffer[3] = (byte) (elementWidth >> 8);
|
out.write(encodedValues);
|
||||||
|
|
||||||
buffer[4] = (byte) elementCount;
|
|
||||||
buffer[5] = (byte) (elementCount >> 8);
|
|
||||||
buffer[6] = (byte) (elementCount >> 16);
|
|
||||||
buffer[7] = (byte) (elementCount >> 24);
|
|
||||||
|
|
||||||
System.arraycopy(encodedValues, 0, buffer, 8, encodedValues.length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayDataPseudoInstruction(byte[] buffer, int bufferIndex) {
|
public ArrayDataPseudoInstruction(byte[] buffer, int bufferIndex) {
|
||||||
|
@ -31,19 +31,18 @@ package org.jf.dexlib.Code.Format;
|
|||||||
import org.jf.dexlib.Code.Instruction;
|
import org.jf.dexlib.Code.Instruction;
|
||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction10t extends Instruction {
|
public class Instruction10t extends Instruction {
|
||||||
public static final InstructionFactory Factory = new Factory();
|
public static final InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction10t(Opcode opcode, byte offA) {
|
public static void emit(Output out, Opcode opcode, byte offA) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (offA == 0) {
|
if (offA == 0) {
|
||||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = offA;
|
out.writeByte(offA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction10t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction10t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -31,14 +31,13 @@ package org.jf.dexlib.Code.Format;
|
|||||||
import org.jf.dexlib.Code.Instruction;
|
import org.jf.dexlib.Code.Instruction;
|
||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction10x extends Instruction {
|
public class Instruction10x extends Instruction {
|
||||||
public static final InstructionFactory Factory = new Factory();
|
public static final InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction10x(Opcode opcode) {
|
public static void emit(Output out, Opcode opcode) {
|
||||||
super(opcode);
|
out.writeByte(opcode.value);
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Instruction10x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
public Instruction10x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,13 +32,12 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction11n extends Instruction {
|
public class Instruction11n extends Instruction {
|
||||||
public static final InstructionFactory Factory = new Factory();
|
public static final InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction11n(Opcode opcode, byte regA, byte litB) {
|
public static void emit(Output out, Opcode opcode, byte regA, byte litB) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 4) {
|
if (regA >= 1 << 4) {
|
||||||
throw new RuntimeException("The register number must be less than v16");
|
throw new RuntimeException("The register number must be less than v16");
|
||||||
}
|
}
|
||||||
@ -48,8 +47,8 @@ public class Instruction11n extends Instruction {
|
|||||||
throw new RuntimeException("The literal value must be between -8 and 7 inclusive");
|
throw new RuntimeException("The literal value must be between -8 and 7 inclusive");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) ((litB << 4) | regA);
|
out.writeByte((litB << 4) | regA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction11n(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction11n(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,19 +32,18 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction11x extends Instruction {
|
public class Instruction11x extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction11x(Opcode opcode, short regA) {
|
public static void emit(Output out, Opcode opcode, short regA) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8) {
|
if (regA >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction11x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction11x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,20 +32,19 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction12x extends Instruction {
|
public class Instruction12x extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction12x(Opcode opcode, byte regA, byte regB) {
|
public static void emit(Output out, Opcode opcode, byte regA, byte regB) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 4 ||
|
if (regA >= 1 << 4 ||
|
||||||
regB >= 1 << 4) {
|
regB >= 1 << 4) {
|
||||||
throw new RuntimeException("The register number must be less than v16");
|
throw new RuntimeException("The register number must be less than v16");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) ((regB << 4) | regA);
|
out.writeByte((regB << 4) | regA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction12x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction12x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,20 +32,18 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction20t extends Instruction {
|
public class Instruction20t extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction20t(Opcode opcode, short offA) {
|
public static void emit(Output out, Opcode opcode, short offA) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (offA == 0) {
|
if (offA == 0) {
|
||||||
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
throw new RuntimeException("The offset cannot be 0. Use goto/32 instead.");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[2] = (byte) offA;
|
out.writeShort(offA);
|
||||||
buffer[3] = (byte) (offA >> 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction20t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction20t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -35,24 +35,26 @@ import org.jf.dexlib.DexFile;
|
|||||||
import org.jf.dexlib.Item;
|
import org.jf.dexlib.Item;
|
||||||
import org.jf.dexlib.TypeIdItem;
|
import org.jf.dexlib.TypeIdItem;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction21c extends InstructionWithReference {
|
public class Instruction21c extends InstructionWithReference {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction21c(Opcode opcode, short regA, Item referencedItem) {
|
public static void emit(Output out, Opcode opcode, short regA, Item referencedItem) {
|
||||||
super(opcode, referencedItem);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8) {
|
if (regA >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode == Opcode.NEW_INSTANCE && ((TypeIdItem) referencedItem).getTypeDescriptor().charAt(0) != 'L') {
|
if (opcode == Opcode.NEW_INSTANCE) {
|
||||||
throw new RuntimeException("Only class references can be used with the new-instance opcode");
|
assert referencedItem instanceof TypeIdItem;
|
||||||
|
if (((TypeIdItem)referencedItem).getTypeDescriptor().charAt(0) != 'L') {
|
||||||
|
throw new RuntimeException("Only class references can be used with the new-instance opcode");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
//the item index will be set later, during placement/writing
|
out.writeShort(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction21c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction21c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,21 +32,19 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction21h extends Instruction {
|
public class Instruction21h extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction21h(Opcode opcode, short regA, short litB) {
|
public static void emit(Output out, Opcode opcode, short regA, short litB) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8) {
|
if (regA >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
buffer[2] = (byte) litB;
|
out.writeShort(litB);
|
||||||
buffer[3] = (byte) (litB >> 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction21h(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction21h(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,21 +32,19 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction21s extends Instruction {
|
public class Instruction21s extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction21s(Opcode opcode, short regA, short litB) {
|
public static void emit(Output out, Opcode opcode, short regA, short litB) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8) {
|
if (regA >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
buffer[2] = (byte) litB;
|
out.writeShort(litB);
|
||||||
buffer[3] = (byte) (litB >> 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction21s(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction21s(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,13 +32,12 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction21t extends Instruction {
|
public class Instruction21t extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction21t(Opcode opcode, short regA, short offB) {
|
public static void emit(Output out, Opcode opcode, short regA, short offB) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8) {
|
if (regA >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
@ -47,10 +46,9 @@ public class Instruction21t extends Instruction {
|
|||||||
throw new RuntimeException("The offset cannot be 0.");
|
throw new RuntimeException("The offset cannot be 0.");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
buffer[2] = (byte) offB;
|
out.writeShort(offB);
|
||||||
buffer[3] = (byte) (offB >> 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction21t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction21t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,22 +32,21 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction22b extends Instruction {
|
public class Instruction22b extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction22b(Opcode opcode, short regA, short regB, byte litC) {
|
public static void emit(Output out, Opcode opcode, short regA, short regB, byte litC) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8 ||
|
if (regA >= 1 << 8 ||
|
||||||
regB >= 1 << 8) {
|
regB >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
buffer[2] = (byte) regB;
|
out.writeByte(regB);
|
||||||
buffer[3] = litC;
|
out.writeByte(litC);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction22b(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction22b(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -34,21 +34,20 @@ import org.jf.dexlib.Code.Opcode;
|
|||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Item;
|
import org.jf.dexlib.Item;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction22c extends InstructionWithReference {
|
public class Instruction22c extends InstructionWithReference {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction22c(Opcode opcode, byte regA, byte regB, Item referencedItem) {
|
public static void emit(Output out, Opcode opcode, byte regA, byte regB) {
|
||||||
super(opcode, referencedItem);
|
|
||||||
|
|
||||||
if (regA >= 1 << 4 ||
|
if (regA >= 1 << 4 ||
|
||||||
regB >= 1 << 4) {
|
regB >= 1 << 4) {
|
||||||
throw new RuntimeException("The register number must be less than v16");
|
throw new RuntimeException("The register number must be less than v16");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) ((regB << 4) | regA);
|
out.writeByte((regB << 4) | regA);
|
||||||
//the item index will be set later, during placement/writing
|
out.writeShort(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction22c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction22c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,22 +32,20 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction22s extends Instruction {
|
public class Instruction22s extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction22s(Opcode opcode, byte regA, byte regB, short litC) {
|
public static void emit(Output out, Opcode opcode, byte regA, byte regB, short litC) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 4 ||
|
if (regA >= 1 << 4 ||
|
||||||
regB >= 1 << 4) {
|
regB >= 1 << 4) {
|
||||||
throw new RuntimeException("The register number must be less than v16");
|
throw new RuntimeException("The register number must be less than v16");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) ((regB << 4) | regA);
|
out.writeByte((regB << 4) | regA);
|
||||||
buffer[2] = (byte) litC;
|
out.writeShort(litC);
|
||||||
buffer[3] = (byte) (litC >> 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction22s(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction22s(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,13 +32,12 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction22t extends Instruction {
|
public class Instruction22t extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction22t(Opcode opcode, byte regA, byte regB, short offC) {
|
public static void emit(Output out, Opcode opcode, byte regA, byte regB, short offC) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 4 ||
|
if (regA >= 1 << 4 ||
|
||||||
regB >= 1 << 4) {
|
regB >= 1 << 4) {
|
||||||
throw new RuntimeException("The register number must be less than v16");
|
throw new RuntimeException("The register number must be less than v16");
|
||||||
@ -48,10 +47,9 @@ public class Instruction22t extends Instruction {
|
|||||||
throw new RuntimeException("The offset cannot be 0.");
|
throw new RuntimeException("The offset cannot be 0.");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) ((regB << 4) | regA);
|
out.writeByte((regB << 4) | regA);
|
||||||
buffer[2] = (byte) offC;
|
out.writeShort(offC);
|
||||||
buffer[3] = (byte) (offC >> 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction22t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction22t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,13 +32,12 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction22x extends Instruction {
|
public class Instruction22x extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction22x(Opcode opcode, short regA, int regB) {
|
public static void emit(Output out, Opcode opcode, short regA, int regB) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8) {
|
if (regA >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v16");
|
throw new RuntimeException("The register number must be less than v16");
|
||||||
}
|
}
|
||||||
@ -47,10 +46,9 @@ public class Instruction22x extends Instruction {
|
|||||||
throw new RuntimeException("The register number must be less than v65536");
|
throw new RuntimeException("The register number must be less than v65536");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
buffer[2] = (byte) regB;
|
out.writeShort(regB);
|
||||||
buffer[3] = (byte) (regB >> 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction22x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction22x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,23 +32,22 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction23x extends Instruction {
|
public class Instruction23x extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction23x(Opcode opcode, short regA, short regB, short regC) {
|
public static void emit(Output out, Opcode opcode, short regA, short regB, short regC) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8 ||
|
if (regA >= 1 << 8 ||
|
||||||
regB >= 1 << 8 ||
|
regB >= 1 << 8 ||
|
||||||
regC >= 1 << 8) {
|
regC >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
buffer[2] = (byte) regB;
|
out.writeByte(regB);
|
||||||
buffer[3] = (byte) regC;
|
out.writeByte(regC);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction23x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction23x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,19 +32,15 @@ import org.jf.dexlib.DexFile;
|
|||||||
import org.jf.dexlib.Code.Instruction;
|
import org.jf.dexlib.Code.Instruction;
|
||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction30t extends Instruction
|
public class Instruction30t extends Instruction
|
||||||
{
|
{
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction30t(Opcode opcode, int offA) {
|
public static void emit(Output out, Opcode opcode, int offA) {
|
||||||
super(opcode);
|
out.writeByte(opcode.value);
|
||||||
|
out.writeInt(offA);
|
||||||
buffer[0] = opcode.value;
|
|
||||||
buffer[2] = (byte)offA;
|
|
||||||
buffer[3] = (byte)(offA >> 8);
|
|
||||||
buffer[4] = (byte)(offA >> 16);
|
|
||||||
buffer[5] = (byte)(offA >> 24);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction30t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction30t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -34,20 +34,19 @@ import org.jf.dexlib.Code.Opcode;
|
|||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Item;
|
import org.jf.dexlib.Item;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction31c extends InstructionWithReference {
|
public class Instruction31c extends InstructionWithReference {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction31c(Opcode opcode, short regA, Item referencedItem) {
|
public static void emit(Output out, Opcode opcode, short regA) {
|
||||||
super(opcode, referencedItem);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8) {
|
if (regA >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
//the item index will be set later, during placement/writing
|
out.writeInt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction31c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction31c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,23 +32,19 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction31i extends Instruction {
|
public class Instruction31i extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction31i(Opcode opcode, short regA, int litB) {
|
public static void emit(Output out, Opcode opcode, short regA, int litB) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8) {
|
if (regA >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
buffer[2] = (byte) litB;
|
out.writeInt(litB);
|
||||||
buffer[3] = (byte) (litB >> 8);
|
|
||||||
buffer[4] = (byte) (litB >> 16);
|
|
||||||
buffer[5] = (byte) (litB >> 24);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction31i(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction31i(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,23 +32,19 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction31t extends Instruction {
|
public class Instruction31t extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction31t(Opcode opcode, short regA, int offB) {
|
public static void emit(Output out, Opcode opcode, short regA, int offB) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8) {
|
if (regA >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
buffer[2] = (byte) offB;
|
out.writeInt(offB);
|
||||||
buffer[3] = (byte) (offB >> 8);
|
|
||||||
buffer[4] = (byte) (offB >> 16);
|
|
||||||
buffer[5] = (byte) (offB >> 24);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction31t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction31t(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -32,24 +32,22 @@ import org.jf.dexlib.DexFile;
|
|||||||
import org.jf.dexlib.Code.Instruction;
|
import org.jf.dexlib.Code.Instruction;
|
||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction32x extends Instruction
|
public class Instruction32x extends Instruction
|
||||||
{
|
{
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction32x(Opcode opcode, int regA, int regB) {
|
public static void emit(Output out, Opcode opcode, int regA, int regB) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1<<16 ||
|
if (regA >= 1<<16 ||
|
||||||
regB >= 1<<16) {
|
regB >= 1<<16) {
|
||||||
throw new RuntimeException("The register number must be less than v65536");
|
throw new RuntimeException("The register number must be less than v65536");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[2] = (byte)regA;
|
out.writeByte(0);
|
||||||
buffer[3] = (byte)(regA >> 8);
|
out.writeShort(regA);
|
||||||
buffer[4] = (byte)regB;
|
out.writeShort(regB);
|
||||||
buffer[5] = (byte)(regB >> 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction32x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction32x(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -37,14 +37,13 @@ import org.jf.dexlib.Item;
|
|||||||
import org.jf.dexlib.MethodIdItem;
|
import org.jf.dexlib.MethodIdItem;
|
||||||
import org.jf.dexlib.TypeIdItem;
|
import org.jf.dexlib.TypeIdItem;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction35c extends InstructionWithReference {
|
public class Instruction35c extends InstructionWithReference {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction35c(Opcode opcode, int regCount, byte regD, byte regE, byte regF, byte regG,
|
public static void emit(Output out, Opcode opcode, int regCount, byte regD, byte regE, byte regF, byte regG,
|
||||||
byte regA, Item referencedItem) {
|
byte regA, Item referencedItem) {
|
||||||
super(opcode, referencedItem);
|
|
||||||
|
|
||||||
if (regCount > 5) {
|
if (regCount > 5) {
|
||||||
throw new RuntimeException("regCount cannot be greater than 5");
|
throw new RuntimeException("regCount cannot be greater than 5");
|
||||||
}
|
}
|
||||||
@ -57,13 +56,13 @@ public class Instruction35c extends InstructionWithReference {
|
|||||||
throw new RuntimeException("All register args must fit in 4 bits");
|
throw new RuntimeException("All register args must fit in 4 bits");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) ((regCount << 4) | regA);
|
out.writeByte((regCount << 4) | regA);
|
||||||
//the item index will be set later, during placement/writing
|
out.writeShort(0);
|
||||||
buffer[4] = (byte) ((regE << 4) | regD);
|
out.writeByte((regE << 4) | regD);
|
||||||
buffer[5] = (byte) ((regG << 4) | regF);
|
out.writeByte((regG << 4) | regF);
|
||||||
|
|
||||||
checkItem();
|
checkItem(opcode, referencedItem, regCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction35c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction35c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
@ -73,7 +72,7 @@ public class Instruction35c extends InstructionWithReference {
|
|||||||
throw new RuntimeException("regCount cannot be greater than 5");
|
throw new RuntimeException("regCount cannot be greater than 5");
|
||||||
}
|
}
|
||||||
|
|
||||||
checkItem();
|
checkItem(opcode, getReferencedItem(), getRegCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format getFormat() {
|
public Format getFormat() {
|
||||||
@ -104,9 +103,7 @@ public class Instruction35c extends InstructionWithReference {
|
|||||||
return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]);
|
return NumberUtils.decodeHighUnsignedNibble(buffer[bufferIndex + 5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkItem() {
|
private static void checkItem(Opcode opcode, Item item, int regCount) {
|
||||||
Item item = getReferencedItem();
|
|
||||||
|
|
||||||
if (opcode == FILLED_NEW_ARRAY) {
|
if (opcode == FILLED_NEW_ARRAY) {
|
||||||
//check data for filled-new-array opcode
|
//check data for filled-new-array opcode
|
||||||
String type = ((TypeIdItem) item).getTypeDescriptor();
|
String type = ((TypeIdItem) item).getTypeDescriptor();
|
||||||
@ -123,7 +120,7 @@ public class Instruction35c extends InstructionWithReference {
|
|||||||
if (opcode != INVOKE_STATIC) {
|
if (opcode != INVOKE_STATIC) {
|
||||||
parameterRegisterCount++;
|
parameterRegisterCount++;
|
||||||
}
|
}
|
||||||
if (parameterRegisterCount != getRegCount()) {
|
if (parameterRegisterCount != regCount) {
|
||||||
throw new RuntimeException("regCount does not match the number of arguments of the method");
|
throw new RuntimeException("regCount does not match the number of arguments of the method");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,13 +37,12 @@ import org.jf.dexlib.Item;
|
|||||||
import org.jf.dexlib.MethodIdItem;
|
import org.jf.dexlib.MethodIdItem;
|
||||||
import org.jf.dexlib.TypeIdItem;
|
import org.jf.dexlib.TypeIdItem;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction3rc extends InstructionWithReference {
|
public class Instruction3rc extends InstructionWithReference {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction3rc(Opcode opcode, short regCount, int startReg, Item referencedItem) {
|
public static void emit(Output out, Opcode opcode, short regCount, int startReg, Item referencedItem) {
|
||||||
super(opcode, referencedItem);
|
|
||||||
|
|
||||||
if (regCount >= 1 << 8) {
|
if (regCount >= 1 << 8) {
|
||||||
throw new RuntimeException("regCount must be less than 256");
|
throw new RuntimeException("regCount must be less than 256");
|
||||||
}
|
}
|
||||||
@ -58,19 +57,18 @@ public class Instruction3rc extends InstructionWithReference {
|
|||||||
throw new RuntimeException("The beginning register of the range cannot be negative");
|
throw new RuntimeException("The beginning register of the range cannot be negative");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regCount;
|
out.writeByte(regCount);
|
||||||
//the item index will be set later, during placement/writing
|
out.writeShort(0);
|
||||||
buffer[4] = (byte) startReg;
|
out.writeShort(startReg);
|
||||||
buffer[5] = (byte) (startReg >> 8);
|
|
||||||
|
|
||||||
checkItem();
|
checkItem(opcode, referencedItem, regCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction3rc(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction3rc(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
super(dexFile, opcode, buffer, bufferIndex);
|
super(dexFile, opcode, buffer, bufferIndex);
|
||||||
|
|
||||||
checkItem();
|
checkItem(opcode, getReferencedItem(), getRegCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format getFormat() {
|
public Format getFormat() {
|
||||||
@ -85,9 +83,7 @@ public class Instruction3rc extends InstructionWithReference {
|
|||||||
return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
|
return NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkItem() {
|
private static void checkItem(Opcode opcode, Item item, int regCount) {
|
||||||
Item item = getReferencedItem();
|
|
||||||
|
|
||||||
if (opcode == FILLED_NEW_ARRAY_RANGE) {
|
if (opcode == FILLED_NEW_ARRAY_RANGE) {
|
||||||
//check data for filled-new-array/range opcode
|
//check data for filled-new-array/range opcode
|
||||||
String type = ((TypeIdItem) item).getTypeDescriptor();
|
String type = ((TypeIdItem) item).getTypeDescriptor();
|
||||||
@ -104,7 +100,7 @@ public class Instruction3rc extends InstructionWithReference {
|
|||||||
if (opcode != INVOKE_STATIC_RANGE) {
|
if (opcode != INVOKE_STATIC_RANGE) {
|
||||||
parameterRegisterCount++;
|
parameterRegisterCount++;
|
||||||
}
|
}
|
||||||
if (parameterRegisterCount != getRegCount()) {
|
if (parameterRegisterCount != regCount) {
|
||||||
throw new RuntimeException("regCount does not match the number of arguments of the method");
|
throw new RuntimeException("regCount does not match the number of arguments of the method");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,27 +32,19 @@ import org.jf.dexlib.Code.Instruction;
|
|||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
|
|
||||||
public class Instruction51l extends Instruction {
|
public class Instruction51l extends Instruction {
|
||||||
public static final Instruction.InstructionFactory Factory = new Factory();
|
public static final Instruction.InstructionFactory Factory = new Factory();
|
||||||
|
|
||||||
public Instruction51l(Opcode opcode, short regA, long litB) {
|
public static void emit(Output out, Opcode opcode, short regA, long litB) {
|
||||||
super(opcode);
|
|
||||||
|
|
||||||
if (regA >= 1 << 8) {
|
if (regA >= 1 << 8) {
|
||||||
throw new RuntimeException("The register number must be less than v256");
|
throw new RuntimeException("The register number must be less than v256");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = opcode.value;
|
out.writeByte(opcode.value);
|
||||||
buffer[1] = (byte) regA;
|
out.writeByte(regA);
|
||||||
buffer[2] = (byte) litB;
|
out.writeLong(litB);
|
||||||
buffer[3] = (byte) (litB >> 8);
|
|
||||||
buffer[4] = (byte) (litB >> 16);
|
|
||||||
buffer[5] = (byte) (litB >> 24);
|
|
||||||
buffer[6] = (byte) (litB >> 32);
|
|
||||||
buffer[7] = (byte) (litB >> 40);
|
|
||||||
buffer[8] = (byte) (litB >> 48);
|
|
||||||
buffer[9] = (byte) (litB >> 56);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction51l(Opcode opcode, byte[] buffer, int bufferIndex) {
|
private Instruction51l(Opcode opcode, byte[] buffer, int bufferIndex) {
|
||||||
|
@ -31,6 +31,7 @@ package org.jf.dexlib.Code.Format;
|
|||||||
import org.jf.dexlib.Code.Instruction;
|
import org.jf.dexlib.Code.Instruction;
|
||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -43,34 +44,19 @@ public class PackedSwitchDataPseudoInstruction extends Instruction {
|
|||||||
return getTargetCount() * 4 + 8;
|
return getTargetCount() * 4 + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PackedSwitchDataPseudoInstruction(int firstKey, int[] targets) {
|
public static void emit(Output out, int firstKey, int[] targets) {
|
||||||
super(Opcode.NOP, targets.length * 4 + 8);
|
|
||||||
|
|
||||||
/*this.firstKey = firstKey;
|
|
||||||
this.targets = targets;*/
|
|
||||||
|
|
||||||
if (targets.length > 0xFFFF) {
|
if (targets.length > 0xFFFF) {
|
||||||
throw new RuntimeException("The packed-switch data contains too many elements. " +
|
throw new RuntimeException("The packed-switch data contains too many elements. " +
|
||||||
"The maximum number of switch elements is 65535");
|
"The maximum number of switch elements is 65535");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = 0x00;
|
out.writeByte(0x00);
|
||||||
buffer[1] = 0x01; //packed-switch pseudo-opcode
|
out.writeByte(0x01);
|
||||||
|
out.writeShort(targets.length);
|
||||||
buffer[2] = (byte) targets.length;
|
out.writeInt(firstKey);
|
||||||
buffer[3] = (byte) (targets.length >> 8);
|
|
||||||
|
|
||||||
buffer[4] = (byte) firstKey;
|
|
||||||
buffer[5] = (byte) (firstKey >> 8);
|
|
||||||
buffer[6] = (byte) (firstKey >> 16);
|
|
||||||
buffer[7] = (byte) (firstKey >> 24);
|
|
||||||
|
|
||||||
int position = 8;
|
|
||||||
for (int target : targets) {
|
for (int target : targets) {
|
||||||
buffer[position++] = (byte) target;
|
out.writeInt(target);
|
||||||
buffer[position++] = (byte) (target >> 8);
|
|
||||||
buffer[position++] = (byte) (target >> 16);
|
|
||||||
buffer[position++] = (byte) (target >> 24);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ package org.jf.dexlib.Code.Format;
|
|||||||
import org.jf.dexlib.Code.Instruction;
|
import org.jf.dexlib.Code.Instruction;
|
||||||
import org.jf.dexlib.Code.Opcode;
|
import org.jf.dexlib.Code.Opcode;
|
||||||
import org.jf.dexlib.Util.NumberUtils;
|
import org.jf.dexlib.Util.NumberUtils;
|
||||||
|
import org.jf.dexlib.Util.Output;
|
||||||
import org.jf.dexlib.DexFile;
|
import org.jf.dexlib.DexFile;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -43,9 +44,7 @@ public class SparseSwitchDataPseudoInstruction extends Instruction {
|
|||||||
return getTargetCount() * 8 + 4;
|
return getTargetCount() * 8 + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SparseSwitchDataPseudoInstruction(int[] keys, int[] targets) {
|
public static void emit(Output out, int[] keys, int[] targets) {
|
||||||
super(Opcode.NOP, keys.length * 8 + 4);
|
|
||||||
|
|
||||||
if (keys.length != targets.length) {
|
if (keys.length != targets.length) {
|
||||||
throw new RuntimeException("The number of keys and offsets don't match");
|
throw new RuntimeException("The number of keys and offsets don't match");
|
||||||
}
|
}
|
||||||
@ -59,20 +58,14 @@ public class SparseSwitchDataPseudoInstruction extends Instruction {
|
|||||||
"The maximum number of switch elements is 65535");
|
"The maximum number of switch elements is 65535");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = 0x00;
|
out.writeByte(0x00);
|
||||||
buffer[1] = 0x02; //sparse-switch psuedo-opcode
|
out.writeByte(0x02);
|
||||||
|
out.writeShort(targets.length);
|
||||||
buffer[2] = (byte) targets.length;
|
|
||||||
buffer[3] = (byte) (targets.length >> 8);
|
|
||||||
|
|
||||||
int position = 8;
|
|
||||||
|
|
||||||
if (targets.length > 0) {
|
if (targets.length > 0) {
|
||||||
int key = keys[0];
|
int key = keys[0];
|
||||||
buffer[4] = (byte) key;
|
|
||||||
buffer[5] = (byte) (key >> 8);
|
out.writeInt(key);
|
||||||
buffer[6] = (byte) (key >> 16);
|
|
||||||
buffer[7] = (byte) (key >> 24);
|
|
||||||
|
|
||||||
for (int i = 1; i < keys.length; i++) {
|
for (int i = 1; i < keys.length; i++) {
|
||||||
key = keys[i];
|
key = keys[i];
|
||||||
@ -80,18 +73,11 @@ public class SparseSwitchDataPseudoInstruction extends Instruction {
|
|||||||
throw new RuntimeException("The targets in a sparse switch block must be sorted in ascending" +
|
throw new RuntimeException("The targets in a sparse switch block must be sorted in ascending" +
|
||||||
"order, by key");
|
"order, by key");
|
||||||
}
|
}
|
||||||
|
out.writeInt(key);
|
||||||
buffer[position++] = (byte) key;
|
|
||||||
buffer[position++] = (byte) (key >> 8);
|
|
||||||
buffer[position++] = (byte) (key >> 16);
|
|
||||||
buffer[position++] = (byte) (key >> 24);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int target : targets) {
|
for (int target : targets) {
|
||||||
buffer[position++] = (byte) target;
|
out.writeInt(target);
|
||||||
buffer[position++] = (byte) (target >> 8);
|
|
||||||
buffer[position++] = (byte) (target >> 16);
|
|
||||||
buffer[position++] = (byte) (target >> 24);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ options {
|
|||||||
package org.jf.smali;
|
package org.jf.smali;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.regex.*;
|
import java.util.regex.*;
|
||||||
import java.lang.Float;
|
import java.lang.Float;
|
||||||
import java.lang.Double;
|
import java.lang.Double;
|
||||||
@ -50,8 +51,7 @@ import org.jf.dexlib.Code.Format.*;
|
|||||||
|
|
||||||
@members {
|
@members {
|
||||||
public DexFile dexFile;
|
public DexFile dexFile;
|
||||||
public ClassDefItem classDefItem;
|
public TypeIdItem classType;
|
||||||
public ClassDataItem classDataItem;
|
|
||||||
|
|
||||||
private byte parseRegister_nibble(String register, int totalMethodRegisters, int methodParameterRegisters)
|
private byte parseRegister_nibble(String register, int totalMethodRegisters, int methodParameterRegisters)
|
||||||
throws SemanticException {
|
throws SemanticException {
|
||||||
@ -151,28 +151,30 @@ smali_file
|
|||||||
: ^(I_CLASS_DEF header methods fields annotations)
|
: ^(I_CLASS_DEF header methods fields annotations)
|
||||||
{
|
{
|
||||||
AnnotationDirectoryItem annotationDirectoryItem = null;
|
AnnotationDirectoryItem annotationDirectoryItem = null;
|
||||||
|
ClassDefItem classDefItem = null;
|
||||||
if ( $methods.methodAnnotationSets != null ||
|
ClassDataItem classDataItem = null;
|
||||||
$methods.parameterAnnotationSets != null ||
|
|
||||||
$fields.fieldAnnotationSets != null ||
|
if ( $methods.methodAnnotations != null ||
|
||||||
|
$methods.parameterAnnotations != null ||
|
||||||
|
$fields.fieldAnnotations != null ||
|
||||||
$annotations.annotationSetItem != null) {
|
$annotations.annotationSetItem != null) {
|
||||||
annotationDirectoryItem = new AnnotationDirectoryItem(
|
annotationDirectoryItem = AnnotationDirectoryItem.getInternedAnnotationDirectoryItem(
|
||||||
dexFile,
|
dexFile,
|
||||||
$annotations.annotationSetItem,
|
$annotations.annotationSetItem,
|
||||||
$fields.fieldAnnotationSets,
|
$fields.fieldAnnotations,
|
||||||
$methods.methodAnnotationSets,
|
$methods.methodAnnotations,
|
||||||
$methods.parameterAnnotationSets);
|
$methods.parameterAnnotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
classDefItem.setAnnotations(annotationDirectoryItem);
|
|
||||||
|
|
||||||
if ((classDataItem.getStaticFields().size() +
|
if ($fields.staticFields.size() != 0 || $fields.instanceFields.size() != 0 ||
|
||||||
classDataItem.getInstanceFields().size() +
|
$methods.directMethods.size() != 0 || $methods.virtualMethods.size()!= 0) {
|
||||||
classDataItem.getDirectMethods().size() +
|
classDataItem = ClassDataItem.getInternedClassDataItem(dexFile, $fields.staticFields, $fields.instanceFields,
|
||||||
classDataItem.getVirtualMethods().size()) == 0) {
|
$methods.directMethods, $methods.virtualMethods);
|
||||||
|
}
|
||||||
classDefItem.setClassDataItem(null);
|
|
||||||
}
|
classDefItem = ClassDefItem.getInternedClassDefItem(dexFile, $header.classType, $header.accessFlags,
|
||||||
|
$header.superType, $header.implementsList, $header.sourceSpec, annotationDirectoryItem,
|
||||||
|
classDataItem, $fields.staticFieldInitialValues);
|
||||||
};
|
};
|
||||||
catch [Exception ex] {
|
catch [Exception ex] {
|
||||||
reportError(new SemanticException(input, ex));
|
reportError(new SemanticException(input, ex));
|
||||||
@ -183,9 +185,12 @@ smali_file
|
|||||||
header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, TypeListItem implementsList, StringIdItem sourceSpec]
|
header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, TypeListItem implementsList, StringIdItem sourceSpec]
|
||||||
: class_spec super_spec? implements_list source_spec
|
: class_spec super_spec? implements_list source_spec
|
||||||
{
|
{
|
||||||
classDataItem = new ClassDataItem(dexFile, 0);
|
classType = $class_spec.type;
|
||||||
classDefItem = new ClassDefItem(dexFile, $class_spec.type, $class_spec.accessFlags,
|
$classType = classType;
|
||||||
$super_spec.type, $implements_list.implementsList, $source_spec.source, classDataItem);
|
$accessFlags = $class_spec.accessFlags;
|
||||||
|
$superType = $super_spec.type;
|
||||||
|
$implementsList = $implements_list.implementsList;
|
||||||
|
$sourceSpec = $source_spec.source;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -210,15 +215,20 @@ implements_spec returns[TypeIdItem type]
|
|||||||
};
|
};
|
||||||
|
|
||||||
implements_list returns[TypeListItem implementsList]
|
implements_list returns[TypeListItem implementsList]
|
||||||
@init { ArrayList<TypeIdItem> typeList; }
|
@init { List<TypeIdItem> typeList; }
|
||||||
: {typeList = new ArrayList<TypeIdItem>();}
|
: {typeList = new LinkedList<TypeIdItem>();}
|
||||||
(implements_spec {typeList.add($implements_spec.type);} )*
|
(implements_spec {typeList.add($implements_spec.type);} )*
|
||||||
{if (typeList.size() > 0) $implementsList = new TypeListItem(dexFile, typeList);
|
{
|
||||||
else $implementsList = null;};
|
if (typeList.size() > 0) {
|
||||||
|
$implementsList = TypeListItem.getInternedTypeListItem(dexFile, typeList);
|
||||||
|
} else {
|
||||||
|
$implementsList = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
source_spec returns[StringIdItem source]
|
source_spec returns[StringIdItem source]
|
||||||
: {$source = null;}
|
: {$source = null;}
|
||||||
^(I_SOURCE string_literal {$source = new StringIdItem(dexFile, $string_literal.value);})
|
^(I_SOURCE string_literal {$source = StringIdItem.getInternedStringIdItem(dexFile, $string_literal.value);})
|
||||||
| ;
|
| ;
|
||||||
|
|
||||||
|
|
||||||
@ -236,51 +246,82 @@ access_list returns [int value]
|
|||||||
}
|
}
|
||||||
)*);
|
)*);
|
||||||
|
|
||||||
fields returns[List<AnnotationDirectoryItem.FieldAnnotation> fieldAnnotationSets]
|
|
||||||
|
fields returns[List<ClassDataItem.EncodedField> staticFields, List<ClassDataItem.EncodedField> instanceFields,
|
||||||
|
List<ClassDefItem.StaticFieldInitializer> staticFieldInitialValues, List<AnnotationDirectoryItem.FieldAnnotation> fieldAnnotations]
|
||||||
|
@init
|
||||||
|
{
|
||||||
|
$staticFields = new LinkedList<ClassDataItem.EncodedField>();
|
||||||
|
$instanceFields = new LinkedList<ClassDataItem.EncodedField>();
|
||||||
|
$staticFieldInitialValues = new LinkedList<ClassDefItem.StaticFieldInitializer>();
|
||||||
|
}
|
||||||
: ^(I_FIELDS
|
: ^(I_FIELDS
|
||||||
(field
|
(field
|
||||||
{
|
{
|
||||||
classDefItem.addField($field.encodedField, $field.encodedValue);
|
if ($field.encodedField.isStatic()) {
|
||||||
|
$staticFields.add($field.encodedField);
|
||||||
|
$staticFieldInitialValues.add(new ClassDefItem.StaticFieldInitializer(
|
||||||
|
$field.encodedValue, $field.encodedField));
|
||||||
|
} else {
|
||||||
|
$instanceFields.add($field.encodedField);
|
||||||
|
}
|
||||||
if ($field.fieldAnnotationSet != null) {
|
if ($field.fieldAnnotationSet != null) {
|
||||||
if ($fieldAnnotationSets == null) {
|
if ($fieldAnnotations == null) {
|
||||||
$fieldAnnotationSets = new ArrayList<AnnotationDirectoryItem.FieldAnnotation>();
|
$fieldAnnotations = new LinkedList<AnnotationDirectoryItem.FieldAnnotation>();
|
||||||
}
|
}
|
||||||
fieldAnnotationSets.add($field.fieldAnnotationSet);
|
AnnotationDirectoryItem.FieldAnnotation fieldAnnotation = new AnnotationDirectoryItem.FieldAnnotation(
|
||||||
|
$field.encodedField.field, $field.fieldAnnotationSet);
|
||||||
|
$fieldAnnotations.add(fieldAnnotation);
|
||||||
}
|
}
|
||||||
})*);
|
})*);
|
||||||
|
|
||||||
methods returns[List<AnnotationDirectoryItem.MethodAnnotation> methodAnnotationSets,
|
methods returns[List<ClassDataItem.EncodedMethod> directMethods,
|
||||||
List<AnnotationDirectoryItem.ParameterAnnotation> parameterAnnotationSets]
|
List<ClassDataItem.EncodedMethod> virtualMethods,
|
||||||
|
List<AnnotationDirectoryItem.MethodAnnotation> methodAnnotations,
|
||||||
|
List<AnnotationDirectoryItem.ParameterAnnotation> parameterAnnotations]
|
||||||
|
@init
|
||||||
|
{
|
||||||
|
$directMethods = new LinkedList<ClassDataItem.EncodedMethod>();
|
||||||
|
$virtualMethods = new LinkedList<ClassDataItem.EncodedMethod>();
|
||||||
|
}
|
||||||
: ^(I_METHODS
|
: ^(I_METHODS
|
||||||
(method
|
(method
|
||||||
{
|
{
|
||||||
classDataItem.addMethod($method.encodedMethod);
|
if ($method.encodedMethod.isDirect()) {
|
||||||
|
$directMethods.add($method.encodedMethod);
|
||||||
|
} else {
|
||||||
|
$virtualMethods.add($method.encodedMethod);
|
||||||
|
}
|
||||||
if ($method.methodAnnotationSet != null) {
|
if ($method.methodAnnotationSet != null) {
|
||||||
if ($methodAnnotationSets == null) {
|
if ($methodAnnotations == null) {
|
||||||
$methodAnnotationSets = new ArrayList<AnnotationDirectoryItem.MethodAnnotation>();
|
$methodAnnotations = new LinkedList<AnnotationDirectoryItem.MethodAnnotation>();
|
||||||
}
|
}
|
||||||
$methodAnnotationSets.add($method.methodAnnotationSet);
|
AnnotationDirectoryItem.MethodAnnotation methodAnnotation =
|
||||||
|
new AnnotationDirectoryItem.MethodAnnotation($method.encodedMethod.method, $method.methodAnnotationSet);
|
||||||
|
$methodAnnotations.add(methodAnnotation);
|
||||||
}
|
}
|
||||||
if ($method.parameterAnnotationSets != null) {
|
if ($method.parameterAnnotationSets != null) {
|
||||||
if ($parameterAnnotationSets == null) {
|
if ($parameterAnnotations == null) {
|
||||||
$parameterAnnotationSets = new ArrayList<AnnotationDirectoryItem.ParameterAnnotation>();
|
$parameterAnnotations = new LinkedList<AnnotationDirectoryItem.ParameterAnnotation>();
|
||||||
}
|
}
|
||||||
$parameterAnnotationSets.add($method.parameterAnnotationSets);
|
AnnotationDirectoryItem.ParameterAnnotation parameterAnnotation =
|
||||||
|
new AnnotationDirectoryItem.ParameterAnnotation($method.encodedMethod.method,
|
||||||
|
$method.parameterAnnotationSets);
|
||||||
|
$parameterAnnotations.add(parameterAnnotation);
|
||||||
}
|
}
|
||||||
})*);
|
})*);
|
||||||
|
|
||||||
field returns[ClassDataItem.EncodedField encodedField, EncodedValue encodedValue, AnnotationDirectoryItem.FieldAnnotation fieldAnnotationSet]
|
field returns [ClassDataItem.EncodedField encodedField, EncodedValue encodedValue, AnnotationSetItem fieldAnnotationSet]
|
||||||
:^(I_FIELD MEMBER_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?)
|
:^(I_FIELD MEMBER_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?)
|
||||||
{
|
{
|
||||||
TypeIdItem classType = classDefItem.getClassType();
|
StringIdItem memberName = StringIdItem.getInternedStringIdItem(dexFile, $MEMBER_NAME.text);
|
||||||
StringIdItem memberName = new StringIdItem(dexFile, $MEMBER_NAME.text);
|
|
||||||
TypeIdItem fieldType = $nonvoid_type_descriptor.type;
|
TypeIdItem fieldType = $nonvoid_type_descriptor.type;
|
||||||
|
|
||||||
FieldIdItem fieldIdItem = new FieldIdItem(dexFile, classType, memberName, fieldType);
|
FieldIdItem fieldIdItem = FieldIdItem.getInternedFieldIdItem(dexFile, classType, fieldType, memberName);
|
||||||
$encodedField = new ClassDataItem.EncodedField(dexFile, fieldIdItem, $access_list.value);
|
$encodedField = new ClassDataItem.EncodedField(fieldIdItem, $access_list.value);
|
||||||
|
|
||||||
if ($field_initial_value.encodedValue != null) {
|
if ($field_initial_value.encodedValue != null) {
|
||||||
if (($access_list.value & AccessFlags.STATIC.getValue()) == 0) {
|
if (!$encodedField.isStatic()) {
|
||||||
throw new SemanticException(input, "Initial field values can only be specified for static fields.");
|
throw new SemanticException(input, "Initial field values can only be specified for static fields.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +331,7 @@ field returns[ClassDataItem.EncodedField encodedField, EncodedValue encodedValue
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($annotations.annotationSetItem != null) {
|
if ($annotations.annotationSetItem != null) {
|
||||||
$fieldAnnotationSet = new AnnotationDirectoryItem.FieldAnnotation(dexFile, fieldIdItem, $annotations.annotationSetItem);
|
$fieldAnnotationSet = $annotations.annotationSetItem;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -300,22 +341,22 @@ field_initial_value returns[EncodedValue encodedValue]
|
|||||||
| ;
|
| ;
|
||||||
|
|
||||||
literal returns[EncodedValue encodedValue]
|
literal returns[EncodedValue encodedValue]
|
||||||
: integer_literal { $encodedValue = new EncodedValue(dexFile, new IntEncodedValueSubField($integer_literal.value)); }
|
: integer_literal { $encodedValue = new IntEncodedValue($integer_literal.value); }
|
||||||
| long_literal { $encodedValue = new EncodedValue(dexFile, new LongEncodedValueSubField($long_literal.value)); }
|
| long_literal { $encodedValue = new LongEncodedValue($long_literal.value); }
|
||||||
| short_literal { $encodedValue = new EncodedValue(dexFile, new ShortEncodedValueSubField($short_literal.value)); }
|
| short_literal { $encodedValue = new ShortEncodedValue($short_literal.value); }
|
||||||
| byte_literal { $encodedValue = new EncodedValue(dexFile, new ByteEncodedValueSubField($byte_literal.value)); }
|
| byte_literal { $encodedValue = new ByteEncodedValue($byte_literal.value); }
|
||||||
| float_literal { $encodedValue = new EncodedValue(dexFile, new FloatEncodedValueSubField($float_literal.value)); }
|
| float_literal { $encodedValue = new FloatEncodedValue($float_literal.value); }
|
||||||
| double_literal { $encodedValue = new EncodedValue(dexFile, new DoubleEncodedValueSubField($double_literal.value)); }
|
| double_literal { $encodedValue = new DoubleEncodedValue($double_literal.value); }
|
||||||
| char_literal { $encodedValue = new EncodedValue(dexFile, new CharEncodedValueSubField($char_literal.value)); }
|
| char_literal { $encodedValue = new CharEncodedValue($char_literal.value); }
|
||||||
| string_literal { $encodedValue = new EncodedValue(dexFile, new EncodedIndexedItemReference(dexFile, new StringIdItem(dexFile, $string_literal.value))); }
|
| string_literal { $encodedValue = new StringEncodedValue(StringIdItem.getInternedStringIdItem(dexFile, $string_literal.value)); }
|
||||||
| bool_literal { $encodedValue = new EncodedValue(dexFile, new BoolEncodedValueSubField($bool_literal.value)); }
|
| bool_literal { $encodedValue = $bool_literal.value?BooleanEncodedValue.TrueValue:BooleanEncodedValue.FalseValue; }
|
||||||
| NULL_LITERAL { $encodedValue = new EncodedValue(dexFile, new NullEncodedValueSubField()); }
|
| NULL_LITERAL { $encodedValue = NullEncodedValue.NullValue; }
|
||||||
| type_descriptor { $encodedValue = new EncodedValue(dexFile, new EncodedIndexedItemReference(dexFile, $type_descriptor.type)); }
|
| type_descriptor { $encodedValue = new TypeEncodedValue($type_descriptor.type); }
|
||||||
| array_literal { $encodedValue = new EncodedValue(dexFile, new ArrayEncodedValueSubField(dexFile, $array_literal.values)); }
|
| array_literal { $encodedValue = new ArrayEncodedValue($array_literal.values); }
|
||||||
| subannotation { $encodedValue = new EncodedValue(dexFile, $subannotation.value); }
|
| subannotation { $encodedValue = new AnnotationEncodedValue($subannotation.annotationType, $subannotation.elementNames, $subannotation.elementValues); }
|
||||||
| field_literal { $encodedValue = new EncodedValue(dexFile, $field_literal.value); }
|
| field_literal { $encodedValue = new FieldEncodedValue($field_literal.value); }
|
||||||
| method_literal { $encodedValue = new EncodedValue(dexFile, $method_literal.value); }
|
| method_literal { $encodedValue = new MethodEncodedValue($method_literal.value); }
|
||||||
| enum_literal { $encodedValue = new EncodedValue(dexFile, $enum_literal.value); };
|
| enum_literal { $encodedValue = new EnumEncodedValue($enum_literal.value); };
|
||||||
|
|
||||||
|
|
||||||
//everything but string
|
//everything but string
|
||||||
@ -407,8 +448,8 @@ sparse_switch_targets[int baseAddress, int targetCount] returns[int[\] targets]
|
|||||||
);
|
);
|
||||||
|
|
||||||
method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
||||||
AnnotationDirectoryItem.MethodAnnotation methodAnnotationSet,
|
AnnotationSetItem methodAnnotationSet,
|
||||||
AnnotationDirectoryItem.ParameterAnnotation parameterAnnotationSets]
|
AnnotationSetRefList parameterAnnotationSets]
|
||||||
scope
|
scope
|
||||||
{
|
{
|
||||||
HashMap<String, Integer> labels;
|
HashMap<String, Integer> labels;
|
||||||
@ -441,7 +482,10 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
|||||||
methodIdItem = $method_name_and_prototype.methodIdItem;
|
methodIdItem = $method_name_and_prototype.methodIdItem;
|
||||||
accessFlags = $access_list.value;
|
accessFlags = $access_list.value;
|
||||||
isStatic = (accessFlags & AccessFlags.STATIC.getValue()) != 0;
|
isStatic = (accessFlags & AccessFlags.STATIC.getValue()) != 0;
|
||||||
methodParameterRegisters = methodIdItem.getParameterRegisterCount(isStatic);
|
methodParameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount();
|
||||||
|
if (!isStatic) {
|
||||||
|
methodParameterRegisters++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
registers_directive
|
registers_directive
|
||||||
{
|
{
|
||||||
@ -457,9 +501,7 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
|||||||
annotations
|
annotations
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ArrayList<InstructionField> instructions = $statements.instructions;
|
Pair<List<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>> temp = $method::tryList.encodeTries();
|
||||||
|
|
||||||
Pair<List<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>> temp = $method::tryList.encodeTries(dexFile);
|
|
||||||
List<CodeItem.TryItem> tries = temp.first;
|
List<CodeItem.TryItem> tries = temp.first;
|
||||||
List<CodeItem.EncodedCatchHandler> handlers = temp.second;
|
List<CodeItem.EncodedCatchHandler> handlers = temp.second;
|
||||||
|
|
||||||
@ -467,9 +509,9 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
|||||||
DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile);
|
DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile);
|
||||||
|
|
||||||
CodeItem codeItem;
|
CodeItem codeItem;
|
||||||
|
|
||||||
if (totalMethodRegisters == 0 &&
|
if (totalMethodRegisters == 0 &&
|
||||||
instructions.size() == 0 &&
|
$statements.encodedInstructions.length == 0 &&
|
||||||
$method::labels.size()== 0 &&
|
$method::labels.size()== 0 &&
|
||||||
(tries == null || tries.size() == 0) &&
|
(tries == null || tries.size() == 0) &&
|
||||||
(handlers == null || handlers.size() == 0) &&
|
(handlers == null || handlers.size() == 0) &&
|
||||||
@ -484,30 +526,32 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
|
|||||||
" registers, for the method parameters");
|
" registers, for the method parameters");
|
||||||
}
|
}
|
||||||
|
|
||||||
int methodParameterCount = methodIdItem.getParameterCount();
|
int methodParameterCount = methodIdItem.getPrototype().getParameterRegisterCount();
|
||||||
if ($method::debugInfo.getParameterNameCount() > methodParameterCount) {
|
if ($method::debugInfo.getParameterNameCount() > methodParameterCount) {
|
||||||
throw new SemanticException(input, "Too many parameter names specified. This method only has " +
|
throw new SemanticException(input, "Too many parameter names specified. This method only has " +
|
||||||
Integer.toString(methodParameterCount) +
|
Integer.toString(methodParameterCount) +
|
||||||
" parameters.");
|
" parameters.");
|
||||||
}
|
}
|
||||||
|
|
||||||
codeItem = new CodeItem(dexFile,
|
codeItem = CodeItem.getInternedCodeItem(dexFile,
|
||||||
totalMethodRegisters,
|
totalMethodRegisters,
|
||||||
methodIdItem.getParameterRegisterCount(isStatic),
|
methodParameterRegisters,
|
||||||
instructions,
|
$statements.maxOutRegisters,
|
||||||
debugInfoItem,
|
debugInfoItem,
|
||||||
|
$statements.encodedInstructions,
|
||||||
|
$statements.referencedItems,
|
||||||
tries,
|
tries,
|
||||||
handlers);
|
handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
$encodedMethod = new ClassDataItem.EncodedMethod(dexFile, methodIdItem, accessFlags, codeItem);
|
$encodedMethod = new ClassDataItem.EncodedMethod(methodIdItem, accessFlags, codeItem);
|
||||||
|
|
||||||
if ($annotations.annotationSetItem != null) {
|
if ($annotations.annotationSetItem != null) {
|
||||||
$methodAnnotationSet = new AnnotationDirectoryItem.MethodAnnotation(dexFile, methodIdItem, $annotations.annotationSetItem);
|
$methodAnnotationSet = $annotations.annotationSetItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($parameters.parameterAnnotations != null) {
|
if ($parameters.parameterAnnotations != null) {
|
||||||
$parameterAnnotationSets = new AnnotationDirectoryItem.ParameterAnnotation(dexFile, methodIdItem, $parameters.parameterAnnotations);
|
$parameterAnnotationSets = $parameters.parameterAnnotations;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -515,26 +559,26 @@ method_prototype returns[ProtoIdItem protoIdItem]
|
|||||||
: ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) field_type_list)
|
: ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) field_type_list)
|
||||||
{
|
{
|
||||||
TypeIdItem returnType = $type_descriptor.type;
|
TypeIdItem returnType = $type_descriptor.type;
|
||||||
ArrayList<TypeIdItem> parameterTypes = $field_type_list.types;
|
List<TypeIdItem> parameterTypes = $field_type_list.types;
|
||||||
|
TypeListItem parameterTypeListItem = TypeListItem.getInternedTypeListItem(dexFile, parameterTypes);
|
||||||
|
|
||||||
$protoIdItem = new ProtoIdItem(dexFile, returnType, parameterTypes);
|
$protoIdItem = ProtoIdItem.getInternedProtoIdItem(dexFile, returnType, parameterTypeListItem);
|
||||||
};
|
};
|
||||||
|
|
||||||
method_name_and_prototype returns[MethodIdItem methodIdItem]
|
method_name_and_prototype returns[MethodIdItem methodIdItem]
|
||||||
: MEMBER_NAME method_prototype
|
: MEMBER_NAME method_prototype
|
||||||
{
|
{
|
||||||
TypeIdItem classType = classDefItem.getClassType();
|
|
||||||
String methodNameString = $MEMBER_NAME.text;
|
String methodNameString = $MEMBER_NAME.text;
|
||||||
StringIdItem methodName = new StringIdItem(dexFile, methodNameString);
|
StringIdItem methodName = StringIdItem.getInternedStringIdItem(dexFile, methodNameString);
|
||||||
ProtoIdItem protoIdItem = $method_prototype.protoIdItem;
|
ProtoIdItem protoIdItem = $method_prototype.protoIdItem;
|
||||||
|
|
||||||
$methodIdItem = new MethodIdItem(dexFile, classType, methodName, protoIdItem);
|
$methodIdItem = MethodIdItem.getInternedMethodIdItem(dexFile, classType, protoIdItem, methodName);
|
||||||
};
|
};
|
||||||
|
|
||||||
field_type_list returns[ArrayList<TypeIdItem> types]
|
field_type_list returns[List<TypeIdItem> types]
|
||||||
@init
|
@init
|
||||||
{
|
{
|
||||||
$types = new ArrayList<TypeIdItem>();
|
$types = new LinkedList<TypeIdItem>();
|
||||||
}
|
}
|
||||||
: (
|
: (
|
||||||
nonvoid_type_descriptor
|
nonvoid_type_descriptor
|
||||||
@ -548,18 +592,18 @@ fully_qualified_method returns[MethodIdItem methodIdItem]
|
|||||||
: reference_type_descriptor MEMBER_NAME method_prototype
|
: reference_type_descriptor MEMBER_NAME method_prototype
|
||||||
{
|
{
|
||||||
TypeIdItem classType = $reference_type_descriptor.type;
|
TypeIdItem classType = $reference_type_descriptor.type;
|
||||||
StringIdItem methodName = new StringIdItem(dexFile, $MEMBER_NAME.text);
|
StringIdItem methodName = StringIdItem.getInternedStringIdItem(dexFile, $MEMBER_NAME.text);
|
||||||
ProtoIdItem prototype = $method_prototype.protoIdItem;
|
ProtoIdItem prototype = $method_prototype.protoIdItem;
|
||||||
$methodIdItem = new MethodIdItem(dexFile, classType, methodName, prototype);
|
$methodIdItem = MethodIdItem.getInternedMethodIdItem(dexFile, classType, prototype, methodName);
|
||||||
};
|
};
|
||||||
|
|
||||||
fully_qualified_field returns[FieldIdItem fieldIdItem]
|
fully_qualified_field returns[FieldIdItem fieldIdItem]
|
||||||
: reference_type_descriptor MEMBER_NAME nonvoid_type_descriptor
|
: reference_type_descriptor MEMBER_NAME nonvoid_type_descriptor
|
||||||
{
|
{
|
||||||
TypeIdItem classType = $reference_type_descriptor.type;
|
TypeIdItem classType = $reference_type_descriptor.type;
|
||||||
StringIdItem fieldName = new StringIdItem(dexFile, $MEMBER_NAME.text);
|
StringIdItem fieldName = StringIdItem.getInternedStringIdItem(dexFile, $MEMBER_NAME.text);
|
||||||
TypeIdItem fieldType = $nonvoid_type_descriptor.type;
|
TypeIdItem fieldType = $nonvoid_type_descriptor.type;
|
||||||
$fieldIdItem = new FieldIdItem(dexFile, classType, fieldName, fieldType);
|
$fieldIdItem = FieldIdItem.getInternedFieldIdItem(dexFile, classType, fieldType, fieldName);
|
||||||
};
|
};
|
||||||
|
|
||||||
registers_directive returns[int registers]
|
registers_directive returns[int registers]
|
||||||
@ -651,7 +695,7 @@ parameters returns[AnnotationSetRefList parameterAnnotations]
|
|||||||
{
|
{
|
||||||
if ($parameter.parameterAnnotationSet != null) {
|
if ($parameter.parameterAnnotationSet != null) {
|
||||||
while (annotationSetItems.size() < parameterCount) {
|
while (annotationSetItems.size() < parameterCount) {
|
||||||
annotationSetItems.add(new AnnotationSetItem(dexFile, -1));
|
annotationSetItems.add(AnnotationSetItem.getInternedAnnotationSetItem(dexFile, null));
|
||||||
}
|
}
|
||||||
annotationSetItems.add($parameter.parameterAnnotationSet);
|
annotationSetItems.add($parameter.parameterAnnotationSet);
|
||||||
}
|
}
|
||||||
@ -662,9 +706,9 @@ parameters returns[AnnotationSetRefList parameterAnnotations]
|
|||||||
{
|
{
|
||||||
if (annotationSetItems.size() > 0) {
|
if (annotationSetItems.size() > 0) {
|
||||||
while (annotationSetItems.size() < parameterCount) {
|
while (annotationSetItems.size() < parameterCount) {
|
||||||
annotationSetItems.add(new AnnotationSetItem(dexFile, -1));
|
annotationSetItems.add(AnnotationSetItem.getInternedAnnotationSetItem(dexFile, null));
|
||||||
}
|
}
|
||||||
$parameterAnnotations = new AnnotationSetRefList(dexFile, annotationSetItems);
|
$parameterAnnotations = AnnotationSetRefList.getInternedAnnotationSetRefList(dexFile, annotationSetItems);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -737,18 +781,23 @@ source
|
|||||||
$method::debugInfo.addSetFile($address.address, $string_literal.value);
|
$method::debugInfo.addSetFile($address.address, $string_literal.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
statements[int totalMethodRegisters, int methodParameterRegisters] returns[ArrayList<InstructionField> instructions]
|
statements[int totalMethodRegisters, int methodParameterRegisters] returns[byte[\] encodedInstructions, List<Item> referencedItems, int maxOutRegisters]
|
||||||
@init
|
@init
|
||||||
{
|
{
|
||||||
$instructions = new ArrayList<InstructionField>();
|
ByteArrayOutput out = new ByteArrayOutput();
|
||||||
|
$referencedItems = new LinkedList<Item>();
|
||||||
|
$maxOutRegisters = 0;
|
||||||
}
|
}
|
||||||
: ^(I_STATEMENTS (instruction[$totalMethodRegisters, $methodParameterRegisters]
|
: ^(I_STATEMENTS (instruction[$totalMethodRegisters, $methodParameterRegisters, out, $referencedItems]
|
||||||
{
|
{
|
||||||
if ($instruction.instruction != null) {
|
$method::currentAddress = out.getCursor() / 2;
|
||||||
$instructions.add($instruction.instruction);
|
if ($maxOutRegisters < $instruction.outRegisters) {
|
||||||
$method::currentAddress += $instruction.instruction.getSize($method::currentAddress * 2) / 2;
|
$maxOutRegisters = $instruction.outRegisters;
|
||||||
}
|
}
|
||||||
})*);
|
})*)
|
||||||
|
{
|
||||||
|
$encodedInstructions = out.toByteArray();
|
||||||
|
};
|
||||||
|
|
||||||
label_ref returns[int labelAddress]
|
label_ref returns[int labelAddress]
|
||||||
: label
|
: label
|
||||||
@ -787,8 +836,37 @@ offset_or_label returns[int offsetValue]
|
|||||||
: offset {$offsetValue = $offset.offsetValue;}
|
: offset {$offsetValue = $offset.offsetValue;}
|
||||||
| label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;};
|
| label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;};
|
||||||
|
|
||||||
instruction[int totalMethodRegisters, int methodParameterRegisters] returns[InstructionField instruction]
|
|
||||||
|
register_list[int totalMethodRegisters, int methodParameterRegisters] returns[byte[\] registers, byte registerCount]
|
||||||
|
@init
|
||||||
|
{
|
||||||
|
$registers = new byte[5];
|
||||||
|
$registerCount = 0;
|
||||||
|
}
|
||||||
|
: ^(I_REGISTER_LIST
|
||||||
|
(REGISTER
|
||||||
|
{
|
||||||
|
if ($registerCount == 5) {
|
||||||
|
throw new SemanticException(input, "A list of registers can only have a maximum of 5 registers. Use the <op>/range alternate opcode instead.");
|
||||||
|
}
|
||||||
|
$registers[$registerCount++] = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
|
})*);
|
||||||
|
|
||||||
|
register_range[int totalMethodRegisters, int methodParameterRegisters] returns[int startRegister, int endRegister]
|
||||||
|
: ^(I_REGISTER_RANGE startReg=REGISTER endReg=REGISTER?)
|
||||||
|
{
|
||||||
|
$startRegister = parseRegister_short($startReg.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
|
if ($endReg == null) {
|
||||||
|
$endRegister = $startRegister;
|
||||||
|
} else {
|
||||||
|
$endRegister = parseRegister_short($endReg.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
instruction[int totalMethodRegisters, int methodParameterRegisters, Output out, List<Item> referencedItems] returns[int outRegisters]
|
||||||
: //e.g. goto endloop:
|
: //e.g. goto endloop:
|
||||||
|
{$outRegisters = 0;}
|
||||||
^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label)
|
^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label)
|
||||||
{
|
{
|
||||||
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text);
|
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text);
|
||||||
@ -799,13 +877,13 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-128, 127].");
|
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-128, 127].");
|
||||||
}
|
}
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction10t(dexFile, opcode, (byte)addressOffset));
|
Instruction10t.emit(out, opcode, (byte)addressOffset);
|
||||||
}
|
}
|
||||||
| //e.g. return
|
| //e.g. return
|
||||||
^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
|
^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
|
||||||
{
|
{
|
||||||
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10x.text);
|
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10x.text);
|
||||||
$instruction = new InstructionField(dexFile, new Instruction10x(dexFile, opcode));
|
Instruction10x.emit(out, opcode);
|
||||||
}
|
}
|
||||||
| //e.g. const/4 v0, 5
|
| //e.g. const/4 v0, 5
|
||||||
^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal)
|
^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal)
|
||||||
@ -816,7 +894,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
short litB = $short_integral_literal.value;
|
short litB = $short_integral_literal.value;
|
||||||
literalTools.checkNibble(litB);
|
literalTools.checkNibble(litB);
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction11n(dexFile, opcode, regA, (byte)litB));
|
Instruction11n.emit(out, opcode, regA, (byte)litB);
|
||||||
}
|
}
|
||||||
| //e.g. move-result-object v1
|
| //e.g. move-result-object v1
|
||||||
^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER)
|
^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER)
|
||||||
@ -824,7 +902,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11x.text);
|
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11x.text);
|
||||||
short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction11x(dexFile, opcode, regA));
|
Instruction11x.emit(out, opcode, regA);
|
||||||
}
|
}
|
||||||
| //e.g. move v1 v2
|
| //e.g. move v1 v2
|
||||||
^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER)
|
^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER)
|
||||||
@ -833,7 +911,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
|
byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction12x(dexFile, opcode, regA, regB));
|
Instruction12x.emit(out, opcode, regA, regB);
|
||||||
}
|
}
|
||||||
| //e.g. goto/16 endloop:
|
| //e.g. goto/16 endloop:
|
||||||
^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t offset_or_label)
|
^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t offset_or_label)
|
||||||
@ -846,7 +924,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
||||||
}
|
}
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction20t(dexFile, opcode, (short)addressOffset));
|
Instruction20t.emit(out, opcode, (short)addressOffset);
|
||||||
}
|
}
|
||||||
| //e.g. sget_object v0 java/lang/System/out LJava/io/PrintStream;
|
| //e.g. sget_object v0 java/lang/System/out LJava/io/PrintStream;
|
||||||
^(I_STATEMENT_FORMAT21c_FIELD INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field)
|
^(I_STATEMENT_FORMAT21c_FIELD INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field)
|
||||||
@ -856,7 +934,8 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
|
|
||||||
FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
|
FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction21c(dexFile, opcode, regA, fieldIdItem));
|
Instruction21c.emit(out, opcode, regA, fieldIdItem);
|
||||||
|
$referencedItems.add(fieldIdItem);
|
||||||
}
|
}
|
||||||
| //e.g. const-string v1 "Hello World!"
|
| //e.g. const-string v1 "Hello World!"
|
||||||
^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal)
|
^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal)
|
||||||
@ -864,9 +943,10 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text);
|
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text);
|
||||||
short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
|
|
||||||
StringIdItem stringIdItem = new StringIdItem(dexFile, $string_literal.value);
|
StringIdItem stringIdItem = StringIdItem.getInternedStringIdItem(dexFile, $string_literal.value);
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction21c(dexFile, opcode, regA, stringIdItem));
|
Instruction21c.emit(out, opcode, regA, stringIdItem);
|
||||||
|
$referencedItems.add(stringIdItem);
|
||||||
}
|
}
|
||||||
| //e.g. const-class v2 org/jf/HelloWorld2/HelloWorld2
|
| //e.g. const-class v2 org/jf/HelloWorld2/HelloWorld2
|
||||||
^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor)
|
^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor)
|
||||||
@ -876,7 +956,8 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
|
|
||||||
TypeIdItem typeIdItem = $reference_type_descriptor.type;
|
TypeIdItem typeIdItem = $reference_type_descriptor.type;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction21c(dexFile, opcode, regA, typeIdItem));
|
Instruction21c.emit(out, opcode, regA, typeIdItem);
|
||||||
|
$referencedItems.add(typeIdItem);
|
||||||
}
|
}
|
||||||
| //e.g. const/high16 v1, 1234
|
| //e.g. const/high16 v1, 1234
|
||||||
^(I_STATEMENT_FORMAT21h INSTRUCTION_FORMAT21h REGISTER short_integral_literal)
|
^(I_STATEMENT_FORMAT21h INSTRUCTION_FORMAT21h REGISTER short_integral_literal)
|
||||||
@ -886,7 +967,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
|
|
||||||
short litB = $short_integral_literal.value;
|
short litB = $short_integral_literal.value;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction21h(dexFile, opcode, regA, litB));
|
Instruction21h.emit(out, opcode, regA, litB);
|
||||||
}
|
}
|
||||||
| //e.g. const/16 v1, 1234
|
| //e.g. const/16 v1, 1234
|
||||||
^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal)
|
^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal)
|
||||||
@ -896,7 +977,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
|
|
||||||
short litB = $short_integral_literal.value;
|
short litB = $short_integral_literal.value;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction21s(dexFile, opcode, regA, litB));
|
Instruction21s.emit(out, opcode, regA, litB);
|
||||||
}
|
}
|
||||||
| //e.g. if-eqz v0, endloop:
|
| //e.g. if-eqz v0, endloop:
|
||||||
^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER offset_or_label)
|
^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER offset_or_label)
|
||||||
@ -910,7 +991,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
||||||
}
|
}
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction21t(dexFile, opcode, regA, (short)addressOffset));
|
Instruction21t.emit(out, opcode, regA, (short)addressOffset);
|
||||||
}
|
}
|
||||||
| //e.g. add-int v0, v1, 123
|
| //e.g. add-int v0, v1, 123
|
||||||
^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal)
|
^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal)
|
||||||
@ -922,7 +1003,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
short litC = $short_integral_literal.value;
|
short litC = $short_integral_literal.value;
|
||||||
literalTools.checkByte(litC);
|
literalTools.checkByte(litC);
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction22b(dexFile, opcode, regA, regB, (byte)litC));
|
Instruction22b.emit(out, opcode, regA, regB, (byte)litC);
|
||||||
}
|
}
|
||||||
| //e.g. iput-object v1 v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
|
| //e.g. iput-object v1 v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
|
||||||
^(I_STATEMENT_FORMAT22c_FIELD INSTRUCTION_FORMAT22c_FIELD registerA=REGISTER registerB=REGISTER fully_qualified_field)
|
^(I_STATEMENT_FORMAT22c_FIELD INSTRUCTION_FORMAT22c_FIELD registerA=REGISTER registerB=REGISTER fully_qualified_field)
|
||||||
@ -933,7 +1014,8 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
|
|
||||||
FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
|
FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction22c(dexFile, opcode, regA, regB, fieldIdItem));
|
Instruction22c.emit(out, opcode, regA, regB);
|
||||||
|
$referencedItems.add(fieldIdItem);
|
||||||
}
|
}
|
||||||
| //e.g. instance-of v0, v1, Ljava/lang/String;
|
| //e.g. instance-of v0, v1, Ljava/lang/String;
|
||||||
^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor)
|
^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor)
|
||||||
@ -944,7 +1026,8 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
|
|
||||||
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction22c(dexFile, opcode, regA, regB, typeIdItem));
|
Instruction22c.emit(out, opcode, regA, regB);
|
||||||
|
$referencedItems.add(typeIdItem);
|
||||||
}
|
}
|
||||||
| //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)
|
||||||
@ -955,7 +1038,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
|
|
||||||
short litC = $short_integral_literal.value;
|
short litC = $short_integral_literal.value;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction22s(dexFile, opcode, regA, regB, litC));
|
Instruction22s.emit(out, opcode, regA, regB, litC);
|
||||||
}
|
}
|
||||||
| //e.g. if-eq v0, v1, endloop:
|
| //e.g. if-eq v0, v1, endloop:
|
||||||
^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER offset_or_label)
|
^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER offset_or_label)
|
||||||
@ -970,7 +1053,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
throw new SemanticException(input, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
|
||||||
}
|
}
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction22t(dexFile, opcode, regA, regB, (short)addressOffset));
|
Instruction22t.emit(out, opcode, regA, regB, (short)addressOffset);
|
||||||
}
|
}
|
||||||
| //e.g. move/from16 v1, v1234
|
| //e.g. move/from16 v1, v1234
|
||||||
^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER)
|
^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER)
|
||||||
@ -979,7 +1062,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
|
short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction22x(dexFile, opcode, regA, regB));
|
Instruction22x.emit(out, opcode, regA, regB);
|
||||||
}
|
}
|
||||||
| //e.g. add-int v1, v2, v3
|
| //e.g. add-int v1, v2, v3
|
||||||
^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER)
|
^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER)
|
||||||
@ -989,7 +1072,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
short regC = parseRegister_byte($registerC.text, $totalMethodRegisters, $methodParameterRegisters);
|
short regC = parseRegister_byte($registerC.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction23x(dexFile, opcode, regA, regB, regC));
|
Instruction23x.emit(out, opcode, regA, regB, regC);
|
||||||
}
|
}
|
||||||
| //e.g. goto/32 endloop:
|
| //e.g. goto/32 endloop:
|
||||||
^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t offset_or_label)
|
^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t offset_or_label)
|
||||||
@ -998,7 +1081,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
|
|
||||||
int addressOffset = $offset_or_label.offsetValue;
|
int addressOffset = $offset_or_label.offsetValue;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction30t(dexFile, opcode, addressOffset));
|
Instruction30t.emit(out, opcode, addressOffset);
|
||||||
}
|
}
|
||||||
| //e.g. const-string/jumbo v1 "Hello World!"
|
| //e.g. const-string/jumbo v1 "Hello World!"
|
||||||
^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal)
|
^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal)
|
||||||
@ -1006,9 +1089,10 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31c.text);
|
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31c.text);
|
||||||
short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
|
|
||||||
StringIdItem stringIdItem = new StringIdItem(dexFile, $string_literal.value);
|
StringIdItem stringIdItem = StringIdItem.getInternedStringIdItem(dexFile, $string_literal.value);
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction31c(dexFile, opcode, regA, stringIdItem));
|
Instruction31c.emit(out, opcode, regA);
|
||||||
|
$referencedItems.add(stringIdItem);
|
||||||
}
|
}
|
||||||
| //e.g. const v0, 123456
|
| //e.g. const v0, 123456
|
||||||
^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
|
^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
|
||||||
@ -1018,7 +1102,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
|
|
||||||
int litB = $fixed_32bit_literal.value;
|
int litB = $fixed_32bit_literal.value;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction31i(dexFile, opcode, regA, litB));
|
Instruction31i.emit(out, opcode, regA, litB);
|
||||||
}
|
}
|
||||||
| //e.g. fill-array-data v0, ArrayData:
|
| //e.g. fill-array-data v0, ArrayData:
|
||||||
^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER offset_or_label)
|
^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER offset_or_label)
|
||||||
@ -1032,7 +1116,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
addressOffset++;
|
addressOffset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction31t(dexFile, opcode, regA, addressOffset));
|
Instruction31t.emit(out, opcode, regA, addressOffset);
|
||||||
}
|
}
|
||||||
| //e.g. move/16 v5678, v1234
|
| //e.g. move/16 v5678, v1234
|
||||||
^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER)
|
^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER)
|
||||||
@ -1041,7 +1125,7 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
|
int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction32x(dexFile, opcode, regA, regB));
|
Instruction32x.emit(out, opcode, regA, regB);
|
||||||
}
|
}
|
||||||
| //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
|
| //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
|
||||||
^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
|
^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
|
||||||
@ -1051,10 +1135,12 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
//this depends on the fact that register_list returns a byte[5]
|
//this depends on the fact that register_list returns a byte[5]
|
||||||
byte[] registers = $register_list.registers;
|
byte[] registers = $register_list.registers;
|
||||||
byte registerCount = $register_list.registerCount;
|
byte registerCount = $register_list.registerCount;
|
||||||
|
$outRegisters = registerCount;
|
||||||
|
|
||||||
MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
|
MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction35c(dexFile, opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem));
|
Instruction35c.emit(out, opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem);
|
||||||
|
$referencedItems.add(methodIdItem);
|
||||||
}
|
}
|
||||||
| //e.g. filled-new-array {v0,v1}, I
|
| //e.g. filled-new-array {v0,v1}, I
|
||||||
^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor)
|
^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor)
|
||||||
@ -1064,10 +1150,12 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
//this depends on the fact that register_list returns a byte[5]
|
//this depends on the fact that register_list returns a byte[5]
|
||||||
byte[] registers = $register_list.registers;
|
byte[] registers = $register_list.registers;
|
||||||
byte registerCount = $register_list.registerCount;
|
byte registerCount = $register_list.registerCount;
|
||||||
|
$outRegisters = registerCount;
|
||||||
|
|
||||||
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction35c(dexFile, opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeIdItem));
|
Instruction35c.emit(out, opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeIdItem);
|
||||||
|
$referencedItems.add(typeIdItem);
|
||||||
}
|
}
|
||||||
| //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
| //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||||
^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
|
^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
|
||||||
@ -1084,10 +1172,12 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
throw new SemanticException(input, "A register range must have the lower register listed first");
|
throw new SemanticException(input, "A register range must have the lower register listed first");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$outRegisters = registerCount;
|
||||||
|
|
||||||
MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
|
MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem;
|
||||||
|
|
||||||
//not supported yet
|
Instruction3rc.emit(out, opcode, (short)registerCount, startRegister, methodIdItem);
|
||||||
$instruction = new InstructionField(dexFile, new Instruction3rc(dexFile, opcode, (short)registerCount, startRegister, methodIdItem));
|
$referencedItems.add(methodIdItem);
|
||||||
}
|
}
|
||||||
| //e.g. filled-new-array/range {v0..v6} I
|
| //e.g. filled-new-array/range {v0..v6} I
|
||||||
^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor)
|
^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor)
|
||||||
@ -1104,10 +1194,12 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
throw new SemanticException(input, "A register range must have the lower register listed first");
|
throw new SemanticException(input, "A register range must have the lower register listed first");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$outRegisters = registerCount;
|
||||||
|
|
||||||
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
|
||||||
|
|
||||||
//not supported yet
|
Instruction3rc.emit(out, opcode, (short)registerCount, startRegister, typeIdItem);
|
||||||
$instruction = new InstructionField(dexFile, new Instruction3rc(dexFile, opcode, (short)registerCount, startRegister, typeIdItem));
|
$referencedItems.add(typeIdItem);
|
||||||
}
|
}
|
||||||
| //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)
|
||||||
@ -1117,38 +1209,55 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
|
|
||||||
long litB = $fixed_64bit_literal.value;
|
long litB = $fixed_64bit_literal.value;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new Instruction51l(dexFile, opcode, regA, litB));
|
Instruction51l.emit(out, opcode, regA, litB);
|
||||||
}
|
}
|
||||||
| //e.g. .array-data 4 1000000 .end array-data
|
| //e.g. .array-data 4 1000000 .end array-data
|
||||||
^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements)
|
^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements)
|
||||||
{
|
{
|
||||||
|
out.alignTo(4);
|
||||||
|
|
||||||
int elementWidth = $short_integral_literal.value;
|
int elementWidth = $short_integral_literal.value;
|
||||||
List<byte[]> byteValues = $array_elements.values;
|
List<byte[]> byteValues = $array_elements.values;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new ArrayDataPseudoInstruction(dexFile, elementWidth, byteValues));
|
int length = 0;
|
||||||
|
for (byte[] byteValue: byteValues) {
|
||||||
|
length+=byteValue.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] encodedValues = new byte[length];
|
||||||
|
int index = 0;
|
||||||
|
for (byte[] byteValue: byteValues) {
|
||||||
|
System.arraycopy(byteValue, 0, encodedValues, index, byteValue.length);
|
||||||
|
index+=byteValue.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayDataPseudoInstruction.emit(out, elementWidth, encodedValues);
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
|
|
||||||
^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal)
|
^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal)
|
||||||
{
|
{
|
||||||
int currentAddress = $method::currentAddress;
|
out.alignTo(4);
|
||||||
Integer baseAddress = $method::packedSwitchDeclarations.get(currentAddress);
|
$method::currentAddress = out.getCursor() / 2;
|
||||||
|
Integer baseAddress = $method::packedSwitchDeclarations.get($method::currentAddress);
|
||||||
if (baseAddress == null) {
|
if (baseAddress == null) {
|
||||||
baseAddress = 0;
|
baseAddress = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
packed_switch_targets[baseAddress])
|
packed_switch_targets[baseAddress])
|
||||||
{
|
{
|
||||||
|
|
||||||
int startKey = $fixed_32bit_literal.value;
|
int startKey = $fixed_32bit_literal.value;
|
||||||
int[] targets = $packed_switch_targets.targets;
|
int[] targets = $packed_switch_targets.targets;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new PackedSwitchDataPseudoInstruction(dexFile, startKey, targets));
|
PackedSwitchDataPseudoInstruction.emit(out, startKey, targets);
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
^(I_STATEMENT_SPARSE_SWITCH sparse_switch_target_count sparse_switch_keys[$sparse_switch_target_count.targetCount]
|
^(I_STATEMENT_SPARSE_SWITCH sparse_switch_target_count sparse_switch_keys[$sparse_switch_target_count.targetCount]
|
||||||
{
|
{
|
||||||
int currentAddress = $method::currentAddress;
|
out.alignTo(4);
|
||||||
Integer baseAddress = $method::sparseSwitchDeclarations.get(currentAddress);
|
$method::currentAddress = out.getCursor() / 2;
|
||||||
|
Integer baseAddress = $method::sparseSwitchDeclarations.get($method::currentAddress);
|
||||||
if (baseAddress == null) {
|
if (baseAddress == null) {
|
||||||
baseAddress = 0;
|
baseAddress = 0;
|
||||||
}
|
}
|
||||||
@ -1159,64 +1268,42 @@ instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Ins
|
|||||||
int[] keys = $sparse_switch_keys.keys;
|
int[] keys = $sparse_switch_keys.keys;
|
||||||
int[] targets = $sparse_switch_targets.targets;
|
int[] targets = $sparse_switch_targets.targets;
|
||||||
|
|
||||||
$instruction = new InstructionField(dexFile, new SparseSwitchDataPseudoInstruction(dexFile, keys, targets));
|
SparseSwitchDataPseudoInstruction.emit(out, keys, targets);
|
||||||
};
|
};
|
||||||
catch [Exception ex] {
|
catch [Exception ex] {
|
||||||
reportError(new SemanticException(input, ex));
|
reportError(new SemanticException(input, ex));
|
||||||
recover(input, null);
|
recover(input, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
register_list[int totalMethodRegisters, int methodParameterRegisters] returns[byte[\] registers, byte registerCount]
|
|
||||||
@init
|
|
||||||
{
|
|
||||||
$registers = new byte[5];
|
|
||||||
$registerCount = 0;
|
|
||||||
}
|
|
||||||
: ^(I_REGISTER_LIST
|
|
||||||
(REGISTER
|
|
||||||
{
|
|
||||||
if ($registerCount == 5) {
|
|
||||||
throw new SemanticException(input, "A list of registers can only have a maximum of 5 registers. Use the <op>/range alternate opcode instead.");
|
|
||||||
}
|
|
||||||
$registers[$registerCount++] = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
|
|
||||||
})*);
|
|
||||||
|
|
||||||
register_range[int totalMethodRegisters, int methodParameterRegisters] returns[int startRegister, int endRegister]
|
|
||||||
: ^(I_REGISTER_RANGE startReg=REGISTER endReg=REGISTER?)
|
|
||||||
{
|
|
||||||
$startRegister = parseRegister_short($startReg.text, $totalMethodRegisters, $methodParameterRegisters);
|
|
||||||
if ($endReg == null) {
|
|
||||||
$endRegister = $startRegister;
|
|
||||||
} else {
|
|
||||||
$endRegister = parseRegister_short($endReg.text, $totalMethodRegisters, $methodParameterRegisters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
nonvoid_type_descriptor returns [TypeIdItem type]
|
nonvoid_type_descriptor returns [TypeIdItem type]
|
||||||
: (PRIMITIVE_TYPE
|
: (PRIMITIVE_TYPE
|
||||||
| CLASS_DESCRIPTOR
|
| CLASS_DESCRIPTOR
|
||||||
| ARRAY_DESCRIPTOR)
|
| ARRAY_DESCRIPTOR)
|
||||||
{
|
{
|
||||||
$type = new TypeIdItem(dexFile, $start.getText());
|
$type = TypeIdItem.getInternedTypeIdItem(dexFile, $start.getText());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
reference_type_descriptor returns [TypeIdItem type]
|
reference_type_descriptor returns [TypeIdItem type]
|
||||||
: (CLASS_DESCRIPTOR
|
: (CLASS_DESCRIPTOR
|
||||||
| ARRAY_DESCRIPTOR)
|
| ARRAY_DESCRIPTOR)
|
||||||
{
|
{
|
||||||
$type = new TypeIdItem(dexFile, $start.getText());
|
$type = TypeIdItem.getInternedTypeIdItem(dexFile, $start.getText());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class_type_descriptor returns [TypeIdItem type]
|
class_type_descriptor returns [TypeIdItem type]
|
||||||
: CLASS_DESCRIPTOR
|
: CLASS_DESCRIPTOR
|
||||||
{
|
{
|
||||||
$type = new TypeIdItem(dexFile, $CLASS_DESCRIPTOR.text);
|
$type = TypeIdItem.getInternedTypeIdItem(dexFile, $CLASS_DESCRIPTOR.text);
|
||||||
};
|
};
|
||||||
|
|
||||||
type_descriptor returns [TypeIdItem type]
|
type_descriptor returns [TypeIdItem type]
|
||||||
: VOID_TYPE {$type = new TypeIdItem(dexFile, "V");}
|
: VOID_TYPE {$type = TypeIdItem.getInternedTypeIdItem(dexFile, "V");}
|
||||||
| nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;}
|
| nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1277,9 +1364,13 @@ string_literal returns[String value]
|
|||||||
bool_literal returns[boolean value]
|
bool_literal returns[boolean value]
|
||||||
: BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); };
|
: BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); };
|
||||||
|
|
||||||
array_literal returns[ArrayList<EncodedValue> values]
|
array_literal returns[EncodedValue[\] values]
|
||||||
: {$values = new ArrayList<EncodedValue>();}
|
: {ArrayList<EncodedValue> valuesList = new ArrayList<EncodedValue>();}
|
||||||
^(I_ENCODED_ARRAY (literal {$values.add($literal.encodedValue);})*);
|
^(I_ENCODED_ARRAY (literal {valuesList.add($literal.encodedValue);})*)
|
||||||
|
{
|
||||||
|
$values = new EncodedValue[valuesList.size()];
|
||||||
|
valuesList.toArray($values);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
annotations returns[AnnotationSetItem annotationSetItem]
|
annotations returns[AnnotationSetItem annotationSetItem]
|
||||||
@ -1287,7 +1378,7 @@ annotations returns[AnnotationSetItem annotationSetItem]
|
|||||||
^(I_ANNOTATIONS (annotation {annotationList.add($annotation.annotationItem);} )*)
|
^(I_ANNOTATIONS (annotation {annotationList.add($annotation.annotationItem);} )*)
|
||||||
{
|
{
|
||||||
if (annotationList.size() > 0) {
|
if (annotationList.size() > 0) {
|
||||||
$annotationSetItem = new AnnotationSetItem(dexFile, annotationList);
|
$annotationSetItem = AnnotationSetItem.getInternedAnnotationSetItem(dexFile, annotationList);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1295,39 +1386,51 @@ annotations returns[AnnotationSetItem annotationSetItem]
|
|||||||
annotation returns[AnnotationItem annotationItem]
|
annotation returns[AnnotationItem annotationItem]
|
||||||
: ^(I_ANNOTATION ANNOTATION_VISIBILITY subannotation)
|
: ^(I_ANNOTATION ANNOTATION_VISIBILITY subannotation)
|
||||||
{
|
{
|
||||||
AnnotationVisibility visibility = AnnotationVisibility.fromName($ANNOTATION_VISIBILITY.text);
|
AnnotationVisibility visibility = AnnotationVisibility.valueOf($ANNOTATION_VISIBILITY.text.toUpperCase());
|
||||||
$annotationItem = new AnnotationItem(dexFile, visibility, $subannotation.value);
|
AnnotationEncodedSubValue encodedAnnotation = new AnnotationEncodedSubValue($subannotation.annotationType,
|
||||||
|
$subannotation.elementNames, $subannotation.elementValues);
|
||||||
|
$annotationItem = AnnotationItem.getInternedAnnotationItem(dexFile, visibility, encodedAnnotation);
|
||||||
};
|
};
|
||||||
|
|
||||||
annotation_element returns[AnnotationElement element]
|
annotation_element returns[StringIdItem elementName, EncodedValue elementValue]
|
||||||
: ^(I_ANNOTATION_ELEMENT MEMBER_NAME literal)
|
: ^(I_ANNOTATION_ELEMENT MEMBER_NAME literal)
|
||||||
{
|
{
|
||||||
$element = new AnnotationElement(dexFile, new StringIdItem(dexFile, $MEMBER_NAME.text), $literal.encodedValue);
|
$elementName = StringIdItem.getInternedStringIdItem(dexFile, $MEMBER_NAME.text);
|
||||||
|
$elementValue = $literal.encodedValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
subannotation returns[AnnotationEncodedValueSubField value]
|
subannotation returns[TypeIdItem annotationType, StringIdItem[\] elementNames, EncodedValue[\] elementValues]
|
||||||
: {ArrayList<AnnotationElement> elements = new ArrayList<AnnotationElement>();}
|
: {ArrayList<StringIdItem> elementNamesList = new ArrayList<StringIdItem>();
|
||||||
|
ArrayList<EncodedValue> elementValuesList = new ArrayList<EncodedValue>();}
|
||||||
^( I_SUBANNOTATION
|
^( I_SUBANNOTATION
|
||||||
class_type_descriptor
|
class_type_descriptor
|
||||||
(annotation_element {elements.add($annotation_element.element);} )* )
|
(annotation_element
|
||||||
|
{
|
||||||
|
elementNamesList.add($annotation_element.elementName);
|
||||||
|
elementValuesList.add($annotation_element.elementValue);
|
||||||
|
} )* )
|
||||||
{
|
{
|
||||||
$value = new AnnotationEncodedValueSubField(dexFile, $class_type_descriptor.type, elements);
|
$annotationType = $class_type_descriptor.type;
|
||||||
|
$elementNames = new StringIdItem[elementNamesList.size()];
|
||||||
|
elementNamesList.toArray($elementNames);
|
||||||
|
$elementValues = new EncodedValue[elementValuesList.size()];
|
||||||
|
elementValuesList.toArray($elementValues);
|
||||||
};
|
};
|
||||||
|
|
||||||
field_literal returns[EncodedIndexedItemReference<FieldIdItem> value]
|
field_literal returns[FieldIdItem value]
|
||||||
: ^(I_ENCODED_FIELD fully_qualified_field)
|
: ^(I_ENCODED_FIELD fully_qualified_field)
|
||||||
{
|
{
|
||||||
$value = new EncodedIndexedItemReference<FieldIdItem>(dexFile, $fully_qualified_field.fieldIdItem);
|
$value = $fully_qualified_field.fieldIdItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
method_literal returns[EncodedIndexedItemReference<MethodIdItem> value]
|
method_literal returns[MethodIdItem value]
|
||||||
: ^(I_ENCODED_METHOD fully_qualified_method)
|
: ^(I_ENCODED_METHOD fully_qualified_method)
|
||||||
{
|
{
|
||||||
$value = new EncodedIndexedItemReference<MethodIdItem>(dexFile, $fully_qualified_method.methodIdItem);
|
$value = $fully_qualified_method.methodIdItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum_literal returns[EncodedIndexedItemReference<FieldIdItem> value]
|
enum_literal returns[FieldIdItem value]
|
||||||
: ^(I_ENCODED_ENUM fully_qualified_field)
|
: ^(I_ENCODED_ENUM fully_qualified_field)
|
||||||
{
|
{
|
||||||
$value = new EncodedIndexedItemReference<FieldIdItem>(dexFile, $fully_qualified_field.fieldIdItem, true);
|
$value = $fully_qualified_field.fieldIdItem;
|
||||||
};
|
};
|
||||||
|
@ -227,8 +227,7 @@ public class main {
|
|||||||
if (dexGen.getNumberOfSyntaxErrors() > 0) {
|
if (dexGen.getNumberOfSyntaxErrors() > 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dexFile.ClassDefsSection.intern(dexGen.classDefItem);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user