Add new DexBuilder interface

This is a different "front-end" for the existing writer functionality that
is meant to be a more memory efficient method for building a new dex file
from scratch
This commit is contained in:
Ben Gruver 2013-04-29 22:35:03 -07:00
parent 1726f028a8
commit 42627b850c
51 changed files with 4376 additions and 228 deletions

View File

@ -40,7 +40,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
public class ImmutableInstructionFactory implements InstructionFactory<ImmutableInstruction> { public class ImmutableInstructionFactory implements InstructionFactory<ImmutableInstruction, Reference> {
public static final ImmutableInstructionFactory INSTANCE = new ImmutableInstructionFactory(); public static final ImmutableInstructionFactory INSTANCE = new ImmutableInstructionFactory();
private ImmutableInstructionFactory() { private ImmutableInstructionFactory() {

View File

@ -93,5 +93,21 @@ public final class MethodUtil {
return regCount; return regCount;
} }
private static char getShortyType(CharSequence type) {
if (type.length() > 1) {
return 'L';
}
return type.charAt(0);
}
public static String getShorty(Collection<? extends CharSequence> params, String returnType) {
StringBuilder sb = new StringBuilder(params.size() + 1);
sb.append(getShortyType(returnType));
for (CharSequence typeRef: params) {
sb.append(getShortyType(typeRef));
}
return sb.toString();
}
private MethodUtil() {} private MethodUtil() {}
} }

View File

@ -33,7 +33,9 @@ package org.jf.dexlib2.util;
import org.jf.dexlib2.Format; import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode; import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.ReferenceType;
import org.jf.dexlib2.VerificationError; import org.jf.dexlib2.VerificationError;
import org.jf.dexlib2.iface.reference.*;
public class Preconditions { public class Preconditions {
public static void checkFormat(Opcode opcode, Format expectedFormat) { public static void checkFormat(Opcode opcode, Format expectedFormat) {
@ -185,4 +187,32 @@ public class Preconditions {
} }
return verificationError; return verificationError;
} }
public static <T extends Reference> T checkReference(int referenceType, T reference) {
switch (referenceType) {
case ReferenceType.STRING:
if (!(reference instanceof StringReference)) {
throw new IllegalArgumentException("Invalid reference type, expecting a string reference");
}
break;
case ReferenceType.TYPE:
if (!(reference instanceof TypeReference)) {
throw new IllegalArgumentException("Invalid reference type, expecting a type reference");
}
break;
case ReferenceType.FIELD:
if (!(reference instanceof FieldReference)) {
throw new IllegalArgumentException("Invalid reference type, expecting a field reference");
}
break;
case ReferenceType.METHOD:
if (!(reference instanceof MethodReference)) {
throw new IllegalArgumentException("Invalid reference type, expecting a method reference");
}
break;
default:
throw new IllegalArgumentException(String.format("Not a valid reference type: %d", referenceType));
}
return reference;
}
} }

View File

@ -43,10 +43,7 @@ import org.jf.dexlib2.iface.TryBlock;
import org.jf.dexlib2.iface.debug.LineNumber; import org.jf.dexlib2.iface.debug.LineNumber;
import org.jf.dexlib2.iface.instruction.Instruction; import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.formats.*; import org.jf.dexlib2.iface.instruction.formats.*;
import org.jf.dexlib2.iface.reference.FieldReference; import org.jf.dexlib2.iface.reference.*;
import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
import org.jf.dexlib2.util.MethodUtil; import org.jf.dexlib2.util.MethodUtil;
import org.jf.dexlib2.writer.util.InstructionWriteUtil; import org.jf.dexlib2.writer.util.InstructionWriteUtil;
import org.jf.dexlib2.writer.util.TryListBuilder; import org.jf.dexlib2.writer.util.TryListBuilder;
@ -72,10 +69,11 @@ public abstract class DexWriter<
StringKey extends CharSequence, StringRef extends StringReference, TypeKey extends CharSequence, StringKey extends CharSequence, StringRef extends StringReference, TypeKey extends CharSequence,
TypeRef extends TypeReference, ProtoKey extends Comparable<ProtoKey>, TypeRef extends TypeReference, ProtoKey extends Comparable<ProtoKey>,
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
BaseReference extends Reference,
ClassKey extends Comparable<? super ClassKey>, ClassKey extends Comparable<? super ClassKey>,
AnnotationKey extends Annotation, AnnotationSetKey, AnnotationKey extends Annotation, AnnotationSetKey,
TypeListKey, TypeListKey,
FieldKey extends FieldRefKey, MethodKey extends MethodRefKey, FieldKey, MethodKey,
EncodedValue, AnnotationElement, EncodedValue, AnnotationElement,
DebugItem extends org.jf.dexlib2.iface.debug.DebugItem, DebugItem extends org.jf.dexlib2.iface.debug.DebugItem,
Insn extends Instruction, ExceptionHandler extends org.jf.dexlib2.iface.ExceptionHandler> { Insn extends Instruction, ExceptionHandler extends org.jf.dexlib2.iface.ExceptionHandler> {
@ -108,26 +106,26 @@ public abstract class DexWriter<
protected int numCodeItemItems = 0; protected int numCodeItemItems = 0;
protected int numClassDataItems = 0; protected int numClassDataItems = 0;
protected InstructionFactory<? extends Insn> instructionFactory; protected final InstructionFactory<? extends Insn, BaseReference> instructionFactory;
protected StringSection<StringKey, StringRef> stringSection; protected final StringSection<StringKey, StringRef> stringSection;
protected TypeSection<StringKey, TypeKey, TypeRef> typeSection; protected final TypeSection<StringKey, TypeKey, TypeRef> typeSection;
protected ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection; protected final ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection;
protected FieldSection<StringKey, TypeKey, FieldRefKey> fieldSection; protected final FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection;
protected MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey> methodSection; protected final MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey, MethodKey> methodSection;
protected ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey, protected final ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
EncodedValue, DebugItem, Insn, ExceptionHandler> classSection; EncodedValue, DebugItem, Insn, ExceptionHandler> classSection;
protected TypeListSection<TypeKey, TypeListKey> typeListSection; protected final TypeListSection<TypeKey, TypeListKey> typeListSection;
protected AnnotationSection<StringKey, TypeKey, AnnotationKey, AnnotationElement, EncodedValue> annotationSection; protected final AnnotationSection<StringKey, TypeKey, AnnotationKey, AnnotationElement, EncodedValue> annotationSection;
protected AnnotationSetSection<AnnotationKey, AnnotationSetKey> annotationSetSection; protected final AnnotationSetSection<AnnotationKey, AnnotationSetKey> annotationSetSection;
protected DexWriter(InstructionFactory<? extends Insn> instructionFactory, protected DexWriter(InstructionFactory<? extends Insn, BaseReference> instructionFactory,
StringSection<StringKey, StringRef> stringSection, StringSection<StringKey, StringRef> stringSection,
TypeSection<StringKey, TypeKey, TypeRef> typeSection, TypeSection<StringKey, TypeKey, TypeRef> typeSection,
ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection, ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection,
FieldSection<StringKey, TypeKey, FieldRefKey> fieldSection, FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection,
MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey> methodSection, MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey, MethodKey> methodSection,
ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey, ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
EncodedValue, DebugItem, Insn, ExceptionHandler> classSection, EncodedValue, DebugItem, Insn, ExceptionHandler> classSection,
TypeListSection<TypeKey, TypeListKey> typeListSection, TypeListSection<TypeKey, TypeListKey> typeListSection,
@ -394,7 +392,7 @@ public abstract class DexWriter<
ClassKey key = entry.getKey(); ClassKey key = entry.getKey();
// set a bogus index, to make sure we don't recuse and double-write it // set a bogus index, to make sure we don't recurse and double-write it
entry.setValue(0); entry.setValue(0);
// first, try to write the superclass // first, try to write the superclass
@ -459,7 +457,7 @@ public abstract class DexWriter<
throws IOException { throws IOException {
int prevIndex = 0; int prevIndex = 0;
for (FieldKey key: fields) { for (FieldKey key: fields) {
int index = fieldSection.getItemIndex(key); int index = fieldSection.getFieldIndex(key);
writer.writeUleb128(index-prevIndex); writer.writeUleb128(index-prevIndex);
writer.writeUleb128(classSection.getFieldAccessFlags(key)); writer.writeUleb128(classSection.getFieldAccessFlags(key));
prevIndex = index; prevIndex = index;
@ -470,7 +468,7 @@ public abstract class DexWriter<
throws IOException { throws IOException {
int prevIndex = 0; int prevIndex = 0;
for (MethodKey key: methods) { for (MethodKey key: methods) {
int index = methodSection.getItemIndex(key); int index = methodSection.getMethodIndex(key);
writer.writeUleb128(index-prevIndex); writer.writeUleb128(index-prevIndex);
writer.writeUleb128(classSection.getMethodAccessFlags(key)); writer.writeUleb128(classSection.getMethodAccessFlags(key));
writer.writeUleb128(classSection.getCodeItemOffset(key)); writer.writeUleb128(classSection.getCodeItemOffset(key));
@ -627,14 +625,11 @@ public abstract class DexWriter<
// first, we write the field/method/parameter items to a temporary buffer, so that we can get a count // first, we write the field/method/parameter items to a temporary buffer, so that we can get a count
// of each type, and determine if we even need to write an annotation directory for this class // of each type, and determine if we even need to write an annotation directory for this class
Collection<? extends FieldKey> staticFields = classSection.getSortedStaticFields(key); Collection<? extends FieldKey> fields = classSection.getSortedFields(key);
Collection<? extends FieldKey> instanceFields = classSection.getSortedInstanceFields(key); Collection<? extends MethodKey> methods = classSection.getSortedMethods(key);
Collection<? extends MethodKey> directMethods = classSection.getSortedDirectMethods(key);
Collection<? extends MethodKey> virtualMethods = classSection.getSortedVirtualMethods(key);
// this is how much space we'll need if every field and method has annotations. // this is how much space we'll need if every field and method has annotations.
int maxSize = (staticFields.size() + instanceFields.size()) * 8 + int maxSize = fields.size() * 8 + methods.size() * 16;
(directMethods.size() + virtualMethods.size()) * 16;
if (maxSize > tempBuffer.capacity()) { if (maxSize > tempBuffer.capacity()) {
tempBuffer = ByteBuffer.allocate(maxSize); tempBuffer = ByteBuffer.allocate(maxSize);
tempBuffer.order(ByteOrder.LITTLE_ENDIAN); tempBuffer.order(ByteOrder.LITTLE_ENDIAN);
@ -646,29 +641,29 @@ public abstract class DexWriter<
int methodAnnotations = 0; int methodAnnotations = 0;
int parameterAnnotations = 0; int parameterAnnotations = 0;
for (FieldKey field: classSection.getSortedFields(key)) { for (FieldKey field: fields) {
AnnotationSetKey fieldAnnotationsKey = classSection.getFieldAnnotations(field); AnnotationSetKey fieldAnnotationsKey = classSection.getFieldAnnotations(field);
if (fieldAnnotationsKey != null) { if (fieldAnnotationsKey != null) {
fieldAnnotations++; fieldAnnotations++;
tempBuffer.putInt(fieldSection.getItemIndex(field)); tempBuffer.putInt(fieldSection.getFieldIndex(field));
tempBuffer.putInt(annotationSetSection.getItemOffset(fieldAnnotationsKey)); tempBuffer.putInt(annotationSetSection.getItemOffset(fieldAnnotationsKey));
} }
} }
for (MethodKey method: classSection.getSortedMethods(key)) { for (MethodKey method: methods) {
AnnotationSetKey methodAnnotationsKey = classSection.getMethodAnnotations(method); AnnotationSetKey methodAnnotationsKey = classSection.getMethodAnnotations(method);
if (methodAnnotationsKey != null) { if (methodAnnotationsKey != null) {
methodAnnotations++; methodAnnotations++;
tempBuffer.putInt(methodSection.getItemIndex(method)); tempBuffer.putInt(methodSection.getMethodIndex(method));
tempBuffer.putInt(annotationSetSection.getItemOffset(methodAnnotationsKey)); tempBuffer.putInt(annotationSetSection.getItemOffset(methodAnnotationsKey));
} }
} }
for (MethodKey method: classSection.getSortedMethods(key)) { for (MethodKey method: methods) {
int offset = classSection.getAnnotationSetRefListOffset(method); int offset = classSection.getAnnotationSetRefListOffset(method);
if (offset != DexWriter.NO_OFFSET) { if (offset != DexWriter.NO_OFFSET) {
methodAnnotations++; methodAnnotations++;
tempBuffer.putInt(methodSection.getItemIndex(method)); tempBuffer.putInt(methodSection.getMethodIndex(method));
tempBuffer.putInt(offset); tempBuffer.putInt(offset);
} }
} }
@ -809,8 +804,8 @@ public abstract class DexWriter<
if (instructions != null) { if (instructions != null) {
tryBlocks = TryListBuilder.massageTryBlocks(tryBlocks); tryBlocks = TryListBuilder.massageTryBlocks(tryBlocks);
InstructionWriteUtil<Insn, StringRef> instrWriteUtil = InstructionWriteUtil<Insn, StringRef, BaseReference> instrWriteUtil =
new InstructionWriteUtil<Insn, StringRef>(instructions, stringSection, instructionFactory); new InstructionWriteUtil<Insn, StringRef, BaseReference>(instructions, stringSection, instructionFactory);
writer.writeUshort(instrWriteUtil.getOutParamCount()); writer.writeUshort(instrWriteUtil.getOutParamCount());
writer.writeUshort(tryBlocks.size()); writer.writeUshort(tryBlocks.size());
writer.writeInt(debugItemOffset); writer.writeInt(debugItemOffset);

View File

@ -44,16 +44,16 @@ public abstract class EncodedValueWriter<StringKey, TypeKey, FieldRefKey extends
@Nonnull private final DexDataWriter writer; @Nonnull private final DexDataWriter writer;
@Nonnull private final StringSection<StringKey, ?> stringSection; @Nonnull private final StringSection<StringKey, ?> stringSection;
@Nonnull private final TypeSection<?, TypeKey, ?> typeSection; @Nonnull private final TypeSection<?, TypeKey, ?> typeSection;
@Nonnull private final FieldSection<?, ?, FieldRefKey> fieldSection; @Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey> methodSection; @Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
@Nonnull private final AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection; @Nonnull private final AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection;
public EncodedValueWriter( public EncodedValueWriter(
@Nonnull DexDataWriter writer, @Nonnull DexDataWriter writer,
@Nonnull StringSection<StringKey, ?> stringSection, @Nonnull StringSection<StringKey, ?> stringSection,
@Nonnull TypeSection<?, TypeKey, ?> typeSection, @Nonnull TypeSection<?, TypeKey, ?> typeSection,
@Nonnull FieldSection<?, ?, FieldRefKey> fieldSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey> methodSection, @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
@Nonnull AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection) { @Nonnull AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection) {
this.writer = writer; this.writer = writer;
this.stringSection = stringSection; this.stringSection = stringSection;

View File

@ -35,9 +35,10 @@ import org.jf.dexlib2.iface.reference.FieldReference;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public interface FieldSection<StringKey, TypeKey, FieldRefKey extends FieldReference> public interface FieldSection<StringKey, TypeKey, FieldRefKey extends FieldReference, FieldKey>
extends IndexSection<FieldRefKey> { extends IndexSection<FieldRefKey> {
@Nonnull TypeKey getDefiningClass(@Nonnull FieldRefKey key); @Nonnull TypeKey getDefiningClass(@Nonnull FieldRefKey key);
@Nonnull TypeKey getFieldType(@Nonnull FieldRefKey key); @Nonnull TypeKey getFieldType(@Nonnull FieldRefKey key);
@Nonnull StringKey getName(@Nonnull FieldRefKey key); @Nonnull StringKey getName(@Nonnull FieldRefKey key);
int getFieldIndex(@Nonnull FieldKey key);
} }

View File

@ -41,34 +41,34 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
public interface InstructionFactory<Insn extends Instruction> { public interface InstructionFactory<Insn extends Instruction, Ref extends Reference> {
Insn makeInstruction10t(@Nonnull Opcode opcode, int codeOffset); Insn makeInstruction10t(@Nonnull Opcode opcode, int codeOffset);
Insn makeInstruction10x(@Nonnull Opcode opcode); Insn makeInstruction10x(@Nonnull Opcode opcode);
Insn makeInstruction11n(@Nonnull Opcode opcode, int registerA, int literal); Insn makeInstruction11n(@Nonnull Opcode opcode, int registerA, int literal);
Insn makeInstruction11x(@Nonnull Opcode opcode, int registerA); Insn makeInstruction11x(@Nonnull Opcode opcode, int registerA);
Insn makeInstruction12x(@Nonnull Opcode opcode, int registerA, int registerB); Insn makeInstruction12x(@Nonnull Opcode opcode, int registerA, int registerB);
Insn makeInstruction20bc(@Nonnull Opcode opcode, int verificationError, @Nonnull Reference reference); Insn makeInstruction20bc(@Nonnull Opcode opcode, int verificationError, @Nonnull Ref reference);
Insn makeInstruction20t(@Nonnull Opcode opcode, int codeOffset); Insn makeInstruction20t(@Nonnull Opcode opcode, int codeOffset);
Insn makeInstruction21c(@Nonnull Opcode opcode, int registerA, @Nonnull Reference reference); Insn makeInstruction21c(@Nonnull Opcode opcode, int registerA, @Nonnull Ref reference);
Insn makeInstruction21ih(@Nonnull Opcode opcode, int registerA, int literal); Insn makeInstruction21ih(@Nonnull Opcode opcode, int registerA, int literal);
Insn makeInstruction21lh(@Nonnull Opcode opcode, int registerA, long literal); Insn makeInstruction21lh(@Nonnull Opcode opcode, int registerA, long literal);
Insn makeInstruction21s(@Nonnull Opcode opcode, int registerA, int literal); Insn makeInstruction21s(@Nonnull Opcode opcode, int registerA, int literal);
Insn makeInstruction21t(@Nonnull Opcode opcode, int registerA, int codeOffset); Insn makeInstruction21t(@Nonnull Opcode opcode, int registerA, int codeOffset);
Insn makeInstruction22b(@Nonnull Opcode opcode, int registerA, int registerB, int literal); Insn makeInstruction22b(@Nonnull Opcode opcode, int registerA, int registerB, int literal);
Insn makeInstruction22c(@Nonnull Opcode opcode, int registerA, int registerB, @Nonnull Reference reference); Insn makeInstruction22c(@Nonnull Opcode opcode, int registerA, int registerB, @Nonnull Ref reference);
Insn makeInstruction22s(@Nonnull Opcode opcode, int registerA, int registerB, int literal); Insn makeInstruction22s(@Nonnull Opcode opcode, int registerA, int registerB, int literal);
Insn makeInstruction22t(@Nonnull Opcode opcode, int registerA, int registerB, int codeOffset); Insn makeInstruction22t(@Nonnull Opcode opcode, int registerA, int registerB, int codeOffset);
Insn makeInstruction22x(@Nonnull Opcode opcode, int registerA, int registerB); Insn makeInstruction22x(@Nonnull Opcode opcode, int registerA, int registerB);
Insn makeInstruction23x(@Nonnull Opcode opcode, int registerA, int registerB, int registerC); Insn makeInstruction23x(@Nonnull Opcode opcode, int registerA, int registerB, int registerC);
Insn makeInstruction30t(@Nonnull Opcode opcode, int codeOffset); Insn makeInstruction30t(@Nonnull Opcode opcode, int codeOffset);
Insn makeInstruction31c(@Nonnull Opcode opcode, int registerA, @Nonnull Reference reference); Insn makeInstruction31c(@Nonnull Opcode opcode, int registerA, @Nonnull Ref reference);
Insn makeInstruction31i(@Nonnull Opcode opcode, int registerA, int literal); Insn makeInstruction31i(@Nonnull Opcode opcode, int registerA, int literal);
Insn makeInstruction31t(@Nonnull Opcode opcode, int registerA, int codeOffset); Insn makeInstruction31t(@Nonnull Opcode opcode, int registerA, int codeOffset);
Insn makeInstruction32x(@Nonnull Opcode opcode, int registerA, int registerB); Insn makeInstruction32x(@Nonnull Opcode opcode, int registerA, int registerB);
Insn makeInstruction35c(@Nonnull Opcode opcode, int registerCount, int registerC, int registerD, int registerE, Insn makeInstruction35c(@Nonnull Opcode opcode, int registerCount, int registerC, int registerD, int registerE,
int registerF, int registerG, @Nonnull Reference reference); int registerF, int registerG, @Nonnull Ref reference);
Insn makeInstruction3rc(@Nonnull Opcode opcode, int startRegister, int registerCount, Insn makeInstruction3rc(@Nonnull Opcode opcode, int startRegister, int registerCount,
@Nonnull Reference reference); @Nonnull Ref reference);
Insn makeInstruction51l(@Nonnull Opcode opcode, int registerA, long literal); Insn makeInstruction51l(@Nonnull Opcode opcode, int registerA, long literal);
Insn makeSparseSwitchPayload(@Nullable List<? extends SwitchElement> switchElements); Insn makeSparseSwitchPayload(@Nullable List<? extends SwitchElement> switchElements);
Insn makePackedSwitchPayload(@Nullable List<? extends SwitchElement> switchElements); Insn makePackedSwitchPayload(@Nullable List<? extends SwitchElement> switchElements);

View File

@ -50,8 +50,8 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
@Nonnull private final DexDataWriter writer; @Nonnull private final DexDataWriter writer;
@Nonnull private final StringSection<?, StringRef> stringSection; @Nonnull private final StringSection<?, StringRef> stringSection;
@Nonnull private final TypeSection<?, ?, TypeRef> typeSection; @Nonnull private final TypeSection<?, ?, TypeRef> typeSection;
@Nonnull private final FieldSection<?, ?, FieldRefKey> fieldSection; @Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey> methodSection; @Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
@Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference> @Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference>
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey> InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey>
@ -59,8 +59,8 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
@Nonnull DexDataWriter writer, @Nonnull DexDataWriter writer,
@Nonnull StringSection<?, StringRef> stringSection, @Nonnull StringSection<?, StringRef> stringSection,
@Nonnull TypeSection<?, ?, TypeRef> typeSection, @Nonnull TypeSection<?, ?, TypeRef> typeSection,
@Nonnull FieldSection<?, ?, FieldRefKey> fieldSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey> methodSection) { @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection) {
return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey>( return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey>(
writer, stringSection, typeSection, fieldSection, methodSection); writer, stringSection, typeSection, fieldSection, methodSection);
} }
@ -68,8 +68,8 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
InstructionWriter(@Nonnull DexDataWriter writer, InstructionWriter(@Nonnull DexDataWriter writer,
@Nonnull StringSection<?, StringRef> stringSection, @Nonnull StringSection<?, StringRef> stringSection,
@Nonnull TypeSection<?, ?, TypeRef> typeSection, @Nonnull TypeSection<?, ?, TypeRef> typeSection,
@Nonnull FieldSection<?, ?, FieldRefKey> fieldSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey> methodSection) { @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection) {
this.writer = writer; this.writer = writer;
this.stringSection = stringSection; this.stringSection = stringSection;
this.typeSection = typeSection; this.typeSection = typeSection;

View File

@ -35,9 +35,11 @@ import org.jf.dexlib2.iface.reference.MethodReference;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public interface MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey extends MethodReference> public interface MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey extends MethodReference, MethodKey>
extends IndexSection<MethodRefKey> { extends IndexSection<MethodRefKey> {
@Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key); @Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key);
@Nonnull ProtoKey getPrototype(@Nonnull MethodRefKey key); @Nonnull ProtoKey getPrototype(@Nonnull MethodRefKey key);
@Nonnull ProtoKey getPrototype(@Nonnull MethodKey key);
@Nonnull StringKey getName(@Nonnull MethodRefKey key); @Nonnull StringKey getName(@Nonnull MethodRefKey key);
int getMethodIndex(@Nonnull MethodKey key);
} }

View File

@ -37,5 +37,5 @@ import javax.annotation.Nonnull;
public interface TypeSection<StringKey, TypeKey, TypeRef extends TypeReference> extends NullableIndexSection<TypeKey> { public interface TypeSection<StringKey, TypeKey, TypeRef extends TypeReference> extends NullableIndexSection<TypeKey> {
@Nonnull StringKey getString(@Nonnull TypeKey key); @Nonnull StringKey getString(@Nonnull TypeKey key);
int getItemIndex(@Nonnull TypeReference key); int getItemIndex(@Nonnull TypeRef key);
} }

View File

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

View File

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

View File

@ -0,0 +1,108 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.collect.Maps;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.writer.AnnotationSection;
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
class BuilderAnnotationPool implements AnnotationSection<BuilderStringReference, BuilderTypeReference,
BuilderAnnotation, BuilderAnnotationElement, BuilderEncodedValue> {
@Nonnull private final BuilderContext context;
@Nonnull private final ConcurrentMap<Annotation, BuilderAnnotation> internedItems =
Maps.newConcurrentMap();
BuilderAnnotationPool(@Nonnull BuilderContext context) {
this.context = context;
}
@Nonnull public BuilderAnnotation internAnnotation(@Nonnull Annotation annotation) {
BuilderAnnotation ret = internedItems.get(annotation);
if (ret != null) {
return ret;
}
BuilderAnnotation dexBuilderAnnotation = new BuilderAnnotation(
annotation.getVisibility(),
context.typePool.internType(annotation.getType()),
context.internAnnotationElements(annotation.getElements()));
ret = internedItems.putIfAbsent(dexBuilderAnnotation, dexBuilderAnnotation);
return ret==null?dexBuilderAnnotation:ret;
}
@Override public int getVisibility(@Nonnull BuilderAnnotation key) {
return key.visibility;
}
@Nonnull @Override public BuilderTypeReference getType(@Nonnull BuilderAnnotation key) {
return key.type;
}
@Nonnull @Override
public Collection<? extends BuilderAnnotationElement> getElements(@Nonnull BuilderAnnotation key) {
return key.elements;
}
@Nonnull @Override
public BuilderStringReference getElementName(@Nonnull BuilderAnnotationElement element) {
return element.name;
}
@Nonnull @Override
public BuilderEncodedValue getElementValue(@Nonnull BuilderAnnotationElement element) {
return element.value;
}
@Override public int getItemOffset(@Nonnull BuilderAnnotation key) {
return key.offset;
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderAnnotation, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderAnnotation>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderAnnotation key) {
return key.offset;
}
@Override protected int setValue(@Nonnull BuilderAnnotation key, int value) {
int prev = key.offset;
key.offset = value;
return prev;
}
};
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.collect.ImmutableSet;
import org.jf.dexlib2.writer.DexWriter;
import javax.annotation.Nonnull;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Set;
class BuilderAnnotationSet extends AbstractSet<BuilderAnnotation> {
public static final BuilderAnnotationSet EMPTY =
new BuilderAnnotationSet(ImmutableSet.<BuilderAnnotation>of());
@Nonnull final Set<BuilderAnnotation> annotations;
int offset = DexWriter.NO_OFFSET;
public BuilderAnnotationSet(@Nonnull Set<BuilderAnnotation> annotations) {
this.annotations = annotations;
}
@Nonnull @Override public Iterator<BuilderAnnotation> iterator() {
return annotations.iterator();
}
@Override public int size() {
return annotations.size();
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.writer.AnnotationSetSection;
import org.jf.dexlib2.writer.DexWriter;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
class BuilderAnnotationSetPool implements AnnotationSetSection<BuilderAnnotation, BuilderAnnotationSet> {
@Nonnull private final BuilderContext context;
@Nonnull private final ConcurrentMap<Set<? extends Annotation>, BuilderAnnotationSet> internedItems =
Maps.newConcurrentMap();
BuilderAnnotationSetPool(@Nonnull BuilderContext context) {
this.context = context;
}
@Nonnull public BuilderAnnotationSet internAnnotationSet(@Nullable Set<? extends Annotation> annotations) {
if (annotations == null) {
return BuilderAnnotationSet.EMPTY;
}
BuilderAnnotationSet ret = internedItems.get(annotations);
if (ret != null) {
return ret;
}
BuilderAnnotationSet annotationSet = new BuilderAnnotationSet(
ImmutableSet.copyOf(Iterators.transform(annotations.iterator(),
new Function<Annotation, BuilderAnnotation>() {
@Nullable @Override public BuilderAnnotation apply(Annotation input) {
return context.annotationPool.internAnnotation(input);
}
})));
ret = internedItems.putIfAbsent(annotationSet, annotationSet);
return ret==null?annotationSet:ret;
}
@Nonnull @Override
public Collection<? extends BuilderAnnotation> getAnnotations(@Nonnull BuilderAnnotationSet key) {
return key.annotations;
}
@Override public int getNullableItemOffset(@Nullable BuilderAnnotationSet key) {
return key==null?DexWriter.NO_OFFSET:key.offset;
}
@Override public int getItemOffset(@Nonnull BuilderAnnotationSet key) {
return key.offset;
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderAnnotationSet, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderAnnotationSet>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderAnnotationSet key) {
return key.offset;
}
@Override protected int setValue(@Nonnull BuilderAnnotationSet key, int value) {
int prev = key.offset;
key.offset = value;
return prev;
}
};
}
}

View File

@ -0,0 +1,132 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.base.Functions;
import com.google.common.collect.*;
import org.jf.dexlib2.base.reference.BaseTypeReference;
import org.jf.dexlib2.iface.ClassDef;
import org.jf.dexlib2.util.FieldUtil;
import org.jf.dexlib2.util.MethodUtil;
import org.jf.dexlib2.writer.DexWriter;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
public class BuilderClassDef extends BaseTypeReference implements ClassDef {
@Nonnull final BuilderTypeReference type;
final int accessFlags;
@Nullable final BuilderTypeReference superclass;
@Nonnull final BuilderTypeList interfaces;
@Nullable final BuilderStringReference sourceFile;
@Nonnull final BuilderAnnotationSet annotations;
@Nonnull final SortedSet<BuilderField> staticFields;
@Nonnull final SortedSet<BuilderField> instanceFields;
@Nonnull final SortedSet<BuilderMethod> directMethods;
@Nonnull final SortedSet<BuilderMethod> virtualMethods;
int classDefIndex = DexWriter.NO_INDEX;
int encodedArrayOffset = DexWriter.NO_OFFSET;
int annotationDirectoryOffset = DexWriter.NO_OFFSET;
BuilderClassDef(@Nonnull BuilderTypeReference type,
int accessFlags,
@Nullable BuilderTypeReference superclass,
@Nonnull BuilderTypeList interfaces,
@Nullable BuilderStringReference sourceFile,
@Nonnull BuilderAnnotationSet annotations,
@Nullable Iterable<? extends BuilderField> fields,
@Nullable Iterable<? extends BuilderMethod> methods) {
this.type = type;
this.accessFlags = accessFlags;
this.superclass = superclass;
this.interfaces = interfaces;
this.sourceFile = sourceFile;
this.annotations = annotations;
this.staticFields = ImmutableSortedSet.copyOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC));
this.instanceFields = ImmutableSortedSet.copyOf(Iterables.filter(fields, FieldUtil.FIELD_IS_INSTANCE));
this.directMethods = ImmutableSortedSet.copyOf(Iterables.filter(methods, MethodUtil.METHOD_IS_DIRECT));
this.virtualMethods = ImmutableSortedSet.copyOf(Iterables.filter(methods, MethodUtil.METHOD_IS_VIRTUAL));
}
@Nonnull @Override public String getType() { return type.getType(); }
@Override public int getAccessFlags() { return accessFlags; }
@Nullable @Override public String getSuperclass() { return superclass==null?null:superclass.getType(); }
@Nullable @Override public String getSourceFile() { return sourceFile==null?null:sourceFile.getString(); }
@Nonnull @Override public BuilderAnnotationSet getAnnotations() { return annotations; }
@Nonnull @Override public SortedSet<BuilderField> getStaticFields() { return staticFields; }
@Nonnull @Override public SortedSet<BuilderField> getInstanceFields() { return instanceFields; }
@Nonnull @Override public SortedSet<BuilderMethod> getDirectMethods() { return directMethods; }
@Nonnull @Override public SortedSet<BuilderMethod> getVirtualMethods() { return virtualMethods; }
@Nonnull @Override
public Set<String> getInterfaces() {
return new AbstractSet<String>() {
@Nonnull @Override public Iterator<String> iterator() {
return Iterators.transform(interfaces.iterator(), Functions.toStringFunction());
}
@Override public int size() {
return interfaces.size();
}
};
}
@Nonnull @Override public Collection<BuilderField> getFields() {
return new AbstractCollection<BuilderField>() {
@Nonnull @Override public Iterator<BuilderField> iterator() {
return Iterators.mergeSorted(
ImmutableList.of(staticFields.iterator(), instanceFields.iterator()),
Ordering.natural());
}
@Override public int size() {
return staticFields.size() + instanceFields.size();
}
};
}
@Nonnull @Override public Collection<BuilderMethod> getMethods() {
return new AbstractCollection<BuilderMethod>() {
@Nonnull @Override public Iterator<BuilderMethod> iterator() {
return Iterators.mergeSorted(
ImmutableList.of(directMethods.iterator(), virtualMethods.iterator()),
Ordering.natural());
}
@Override public int size() {
return directMethods.size() + virtualMethods.size();
}
};
}
}

View File

@ -0,0 +1,418 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.*;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.iface.Field;
import org.jf.dexlib2.iface.TryBlock;
import org.jf.dexlib2.iface.debug.EndLocal;
import org.jf.dexlib2.iface.debug.LineNumber;
import org.jf.dexlib2.iface.debug.RestartLocal;
import org.jf.dexlib2.iface.value.EncodedValue;
import org.jf.dexlib2.util.EncodedValueUtils;
import org.jf.dexlib2.writer.ClassSection;
import org.jf.dexlib2.writer.DebugWriter;
import org.jf.dexlib2.writer.builder.BuilderDebugItem.BuilderSetSourceFile;
import org.jf.dexlib2.writer.builder.BuilderDebugItem.BuilderStartLocal;
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue;
import org.jf.util.AbstractForwardSequentialList;
import org.jf.util.CollectionUtils;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
public class BuilderClassPool implements ClassSection<BuilderStringReference, BuilderTypeReference, BuilderTypeList,
BuilderClassDef, BuilderField, BuilderMethod, BuilderAnnotationSet, BuilderEncodedValue, BuilderDebugItem,
BuilderInstruction, BuilderExceptionHandler> {
@Nonnull private final ConcurrentMap<String, BuilderClassDef> internedItems =
Maps.newConcurrentMap();
BuilderClassPool() {
}
@Nonnull BuilderClassDef internClass(@Nonnull BuilderClassDef classDef) {
BuilderClassDef prev = internedItems.put(classDef.getType(), classDef);
if (prev != null) {
throw new ExceptionWithContext("Class %s has already been interned", classDef.getType());
}
return classDef;
}
private ImmutableList<BuilderClassDef> sortedClasses = null;
@Nonnull @Override public Collection<? extends BuilderClassDef> getSortedClasses() {
if (sortedClasses == null) {
sortedClasses = Ordering.natural().immutableSortedCopy(internedItems.values());
}
return sortedClasses;
}
@Nullable @Override
public Entry<? extends BuilderClassDef, Integer> getClassEntryByType(@Nullable BuilderTypeReference type) {
if (type == null) {
return null;
}
final BuilderClassDef classDef = internedItems.get(type.getType());
if (classDef == null) {
return null;
}
return new Map.Entry<BuilderClassDef, Integer>() {
@Override public BuilderClassDef getKey() {
return classDef;
}
@Override public Integer getValue() {
return classDef.classDefIndex;
}
@Override public Integer setValue(Integer value) {
return classDef.classDefIndex = value;
}
};
}
@Nonnull @Override public BuilderTypeReference getType(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.type;
}
@Override public int getAccessFlags(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.accessFlags;
}
@Nullable @Override public BuilderTypeReference getSuperclass(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.superclass;
}
@Nullable @Override public BuilderTypeList getSortedInterfaces(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.interfaces;
}
@Nullable @Override public BuilderStringReference getSourceFile(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.sourceFile;
}
private static final Predicate<Field> HAS_INITIALIZER = new Predicate<Field>() {
@Override
public boolean apply(Field input) {
EncodedValue encodedValue = input.getInitialValue();
return encodedValue != null && !EncodedValueUtils.isDefaultValue(encodedValue);
}
};
private static final Function<BuilderField, BuilderEncodedValue> GET_INITIAL_VALUE =
new Function<BuilderField, BuilderEncodedValue>() {
@Override
public BuilderEncodedValue apply(BuilderField input) {
BuilderEncodedValue initialValue = input.getInitialValue();
if (initialValue == null) {
return BuilderEncodedValues.defaultValueForType(input.getType());
}
return initialValue;
}
};
@Nullable @Override
public Collection<? extends BuilderEncodedValue> getStaticInitializers(@Nonnull BuilderClassDef classDef) {
final SortedSet<BuilderField> sortedStaticFields = classDef.getStaticFields();
final int lastIndex = CollectionUtils.lastIndexOf(sortedStaticFields, HAS_INITIALIZER);
if (lastIndex > -1) {
return new AbstractCollection<BuilderEncodedValue>() {
@Nonnull @Override public Iterator<BuilderEncodedValue> iterator() {
return FluentIterable.from(sortedStaticFields)
.limit(lastIndex+1)
.transform(GET_INITIAL_VALUE).iterator();
}
@Override public int size() {
return lastIndex+1;
}
};
}
return null;
}
@Nonnull @Override
public Collection<? extends BuilderField> getSortedStaticFields(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.getStaticFields();
}
@Nonnull @Override
public Collection<? extends BuilderField> getSortedInstanceFields(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.getInstanceFields();
}
@Nonnull @Override
public Collection<? extends BuilderField> getSortedFields(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.getFields();
}
@Nonnull @Override
public Collection<? extends BuilderMethod> getSortedDirectMethods(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.getDirectMethods();
}
@Nonnull @Override
public Collection<? extends BuilderMethod> getSortedVirtualMethods(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.getVirtualMethods();
}
@Nonnull @Override
public Collection<? extends BuilderMethod> getSortedMethods(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.getMethods();
}
@Override public int getFieldAccessFlags(@Nonnull BuilderField builderField) {
return builderField.accessFlags;
}
@Override public int getMethodAccessFlags(@Nonnull BuilderMethod builderMethod) {
return builderMethod.accessFlags;
}
@Nullable @Override public BuilderAnnotationSet getClassAnnotations(@Nonnull BuilderClassDef builderClassDef) {
if (builderClassDef.annotations.isEmpty()) {
return null;
}
return builderClassDef.annotations;
}
@Nullable @Override public BuilderAnnotationSet getFieldAnnotations(@Nonnull BuilderField builderField) {
if (builderField.annotations.isEmpty()) {
return null;
}
return builderField.annotations;
}
@Nullable @Override public BuilderAnnotationSet getMethodAnnotations(@Nonnull BuilderMethod builderMethod) {
if (builderMethod.annotations.isEmpty()) {
return null;
}
return builderMethod.annotations;
}
private static final Predicate<BuilderMethodParameter> HAS_PARAMETER_ANNOTATIONS =
new Predicate<BuilderMethodParameter>() {
@Override
public boolean apply(BuilderMethodParameter input) {
return input.getAnnotations().size() > 0;
}
};
private static final Function<BuilderMethodParameter, BuilderAnnotationSet> PARAMETER_ANNOTATIONS =
new Function<BuilderMethodParameter, BuilderAnnotationSet>() {
@Override
public BuilderAnnotationSet apply(BuilderMethodParameter input) {
return input.getAnnotations();
}
};
@Nullable @Override public List<? extends BuilderAnnotationSet> getParameterAnnotations(
@Nonnull final BuilderMethod method) {
final int lastIndex = CollectionUtils.lastIndexOf(method.getParameters(), HAS_PARAMETER_ANNOTATIONS);
if (lastIndex > -1) {
return new AbstractForwardSequentialList<BuilderAnnotationSet>() {
@Nonnull @Override public Iterator<BuilderAnnotationSet> iterator() {
return FluentIterable.from(method.getParameters())
.limit(lastIndex+1)
.transform(PARAMETER_ANNOTATIONS).iterator();
}
@Override public int size() {
return lastIndex+1;
}
};
}
return null;
}
@Nullable @Override
public Iterable<? extends BuilderDebugItem> getDebugItems(@Nonnull BuilderMethod builderMethod) {
BuilderMethodImplementation impl = builderMethod.getImplementation();
if (impl == null) {
return null;
}
return impl.getDebugItems();
}
@Nullable @Override
public Iterable<? extends BuilderStringReference> getParameterNames(@Nonnull BuilderMethod method) {
return Iterables.transform(method.getParameters(), new Function<BuilderMethodParameter, BuilderStringReference>() {
@Nullable @Override public BuilderStringReference apply(BuilderMethodParameter input) {
return input.name;
}
});
}
@Override public int getRegisterCount(@Nonnull BuilderMethod builderMethod) {
BuilderMethodImplementation impl = builderMethod.getImplementation();
if (impl == null) {
return 0;
}
return impl.registerCount;
}
@Nullable @Override
public Iterable<? extends BuilderInstruction> getInstructions(@Nonnull BuilderMethod builderMethod) {
BuilderMethodImplementation impl = builderMethod.getImplementation();
if (impl == null) {
return null;
}
return impl.getInstructions();
}
@Nonnull @Override
public List<? extends TryBlock<? extends BuilderExceptionHandler>> getTryBlocks(@Nonnull BuilderMethod builderMethod) {
BuilderMethodImplementation impl = builderMethod.getImplementation();
if (impl == null) {
return ImmutableList.of();
}
return impl.getTryBlocks();
}
@Nullable @Override public BuilderTypeReference getExceptionType(@Nonnull BuilderExceptionHandler handler) {
return handler.exceptionType;
}
@Override public void setEncodedArrayOffset(@Nonnull BuilderClassDef builderClassDef, int offset) {
builderClassDef.encodedArrayOffset = offset;
}
@Override public int getEncodedArrayOffset(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.encodedArrayOffset;
}
@Override public void setAnnotationDirectoryOffset(@Nonnull BuilderClassDef builderClassDef, int offset) {
builderClassDef.annotationDirectoryOffset = offset;
}
@Override public int getAnnotationDirectoryOffset(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.annotationDirectoryOffset;
}
@Override public void setAnnotationSetRefListOffset(@Nonnull BuilderMethod builderMethod, int offset) {
builderMethod.annotationSetRefListOffset = offset;
}
@Override public int getAnnotationSetRefListOffset(@Nonnull BuilderMethod builderMethod) {
return builderMethod.annotationSetRefListOffset;
}
@Override public void setCodeItemOffset(@Nonnull BuilderMethod builderMethod, int offset) {
builderMethod.codeItemOffset = offset;
}
@Override public int getCodeItemOffset(@Nonnull BuilderMethod builderMethod) {
return builderMethod.codeItemOffset;
}
@Override public void setDebugItemOffset(@Nonnull BuilderMethod builderMethod, int offset) {
builderMethod.debugInfoOffset = offset;
}
@Override public int getDebugItemOffset(@Nonnull BuilderMethod builderMethod) {
return builderMethod.debugInfoOffset;
}
@Override
public void writeDebugItem(@Nonnull DebugWriter<BuilderStringReference, BuilderTypeReference> writer,
BuilderDebugItem debugItem) throws IOException {
switch (debugItem.getDebugItemType()) {
case DebugItemType.START_LOCAL: {
BuilderStartLocal startLocal = (BuilderStartLocal)debugItem;
writer.writeStartLocal(startLocal.getCodeAddress(),
startLocal.register,
startLocal.name,
startLocal.type,
startLocal.signature);
break;
}
case DebugItemType.END_LOCAL: {
EndLocal endLocal = (EndLocal)debugItem;
writer.writeEndLocal(endLocal.getCodeAddress(), endLocal.getRegister());
break;
}
case DebugItemType.RESTART_LOCAL: {
RestartLocal restartLocal = (RestartLocal)debugItem;
writer.writeRestartLocal(restartLocal.getCodeAddress(), restartLocal.getRegister());
break;
}
case DebugItemType.PROLOGUE_END: {
writer.writePrologueEnd(debugItem.getCodeAddress());
break;
}
case DebugItemType.EPILOGUE_BEGIN: {
writer.writeEpilogueBegin(debugItem.getCodeAddress());
break;
}
case DebugItemType.LINE_NUMBER: {
LineNumber lineNumber = (LineNumber)debugItem;
writer.writeLineNumber(lineNumber.getCodeAddress(), lineNumber.getLineNumber());
break;
}
case DebugItemType.SET_SOURCE_FILE: {
BuilderSetSourceFile setSourceFile = (BuilderSetSourceFile)debugItem;
writer.writeSetSourceFile(setSourceFile.getCodeAddress(), setSourceFile.sourceFile);
}
default:
throw new ExceptionWithContext("Unexpected debug item type: %d", debugItem.getDebugItemType());
}
}
@Override public int getItemIndex(@Nonnull BuilderClassDef builderClassDef) {
return builderClassDef.classDefIndex;
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderClassDef, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderClassDef>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderClassDef key) {
return key.classDefIndex;
}
@Override protected int setValue(@Nonnull BuilderClassDef key, int value) {
int prev = key.classDefIndex;
key.classDefIndex = value;
return prev;
}
};
}
}

View File

@ -0,0 +1,175 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import org.jf.dexlib2.ValueType;
import org.jf.dexlib2.iface.AnnotationElement;
import org.jf.dexlib2.iface.value.*;
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.*;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Set;
class BuilderContext {
// keep our own local references to the various pools, using the Builder specific pool type;
@Nonnull final BuilderStringPool stringPool;
@Nonnull final BuilderTypePool typePool;
@Nonnull final BuilderFieldPool fieldPool;
@Nonnull final BuilderMethodPool methodPool;
@Nonnull final BuilderProtoPool protoPool;
@Nonnull final BuilderClassPool classPool;
@Nonnull final BuilderTypeListPool typeListPool;
@Nonnull final BuilderAnnotationPool annotationPool;
@Nonnull final BuilderAnnotationSetPool annotationSetPool;
BuilderContext() {
this.stringPool = new BuilderStringPool();
this.typePool = new BuilderTypePool(this);
this.fieldPool = new BuilderFieldPool(this);
this.methodPool = new BuilderMethodPool(this);
this.protoPool = new BuilderProtoPool(this);
this.classPool = new BuilderClassPool();
this.typeListPool = new BuilderTypeListPool(this);
this.annotationPool = new BuilderAnnotationPool(this);
this.annotationSetPool = new BuilderAnnotationSetPool(this);
}
@Nonnull Set<? extends BuilderAnnotationElement> internAnnotationElements(
@Nonnull Set<? extends AnnotationElement> elements) {
return ImmutableSet.copyOf(
Iterators.transform(elements.iterator(),
new Function<AnnotationElement, BuilderAnnotationElement>() {
@Nullable @Override
public BuilderAnnotationElement apply(AnnotationElement input) {
return internAnnotationElement(input);
}
}));
}
@Nonnull private BuilderAnnotationElement internAnnotationElement(@Nonnull AnnotationElement annotationElement) {
return new BuilderAnnotationElement(stringPool.internString(annotationElement.getName()),
internEncodedValue(annotationElement.getValue()));
}
@Nullable BuilderEncodedValue internNullableEncodedValue(@Nullable EncodedValue encodedValue) {
if (encodedValue == null) {
return null;
}
return internEncodedValue(encodedValue);
}
@Nonnull private BuilderEncodedValue internEncodedValue(@Nonnull EncodedValue encodedValue) {
switch (encodedValue.getValueType()) {
case ValueType.ANNOTATION:
return internAnnotationEncodedValue((AnnotationEncodedValue)encodedValue);
case ValueType.ARRAY:
return internArrayEncodedValue((ArrayEncodedValue)encodedValue);
case ValueType.BOOLEAN:
boolean value = ((BooleanEncodedValue)encodedValue).getValue();
return value?BuilderBooleanEncodedValue.TRUE_VALUE:BuilderBooleanEncodedValue.FALSE_VALUE;
case ValueType.BYTE:
return new BuilderByteEncodedValue(((ByteEncodedValue)encodedValue).getValue());
case ValueType.CHAR:
return new BuilderCharEncodedValue(((CharEncodedValue)encodedValue).getValue());
case ValueType.DOUBLE:
return new BuilderDoubleEncodedValue(((DoubleEncodedValue)encodedValue).getValue());
case ValueType.ENUM:
return internEnumEncodedValue((EnumEncodedValue)encodedValue);
case ValueType.FIELD:
return internFieldEncodedValue((FieldEncodedValue)encodedValue);
case ValueType.FLOAT:
return new BuilderFloatEncodedValue(((FloatEncodedValue)encodedValue).getValue());
case ValueType.INT:
return new BuilderIntEncodedValue(((IntEncodedValue)encodedValue).getValue());
case ValueType.LONG:
return new BuilderLongEncodedValue(((LongEncodedValue)encodedValue).getValue());
case ValueType.METHOD:
return internMethodEncodedValue((MethodEncodedValue)encodedValue);
case ValueType.NULL:
return BuilderNullEncodedValue.INSTANCE;
case ValueType.SHORT:
return new BuilderShortEncodedValue(((ShortEncodedValue)encodedValue).getValue());
case ValueType.STRING:
return internStringEncodedValue((StringEncodedValue)encodedValue);
case ValueType.TYPE:
return internTypeEncodedValue((TypeEncodedValue)encodedValue);
default:
throw new ExceptionWithContext("Unexpected encoded value type: %d", encodedValue.getValueType());
}
}
@Nonnull private BuilderAnnotationEncodedValue internAnnotationEncodedValue(@Nonnull AnnotationEncodedValue value) {
return new BuilderAnnotationEncodedValue(
typePool.internType(value.getType()),
internAnnotationElements(value.getElements()));
}
@Nonnull private BuilderArrayEncodedValue internArrayEncodedValue(@Nonnull ArrayEncodedValue value) {
return new BuilderArrayEncodedValue(
ImmutableList.copyOf(
Iterators.transform(value.getValue().iterator(),
new Function<EncodedValue, BuilderEncodedValue>() {
@Nullable @Override public BuilderEncodedValue apply(EncodedValue input) {
return internEncodedValue(input);
}
})));
}
@Nonnull private BuilderEnumEncodedValue internEnumEncodedValue(@Nonnull EnumEncodedValue value) {
return new BuilderEnumEncodedValue(fieldPool.internField(value.getValue()));
}
@Nonnull private BuilderFieldEncodedValue internFieldEncodedValue(@Nonnull FieldEncodedValue value) {
return new BuilderFieldEncodedValue(fieldPool.internField(value.getValue()));
}
@Nonnull private BuilderMethodEncodedValue internMethodEncodedValue(@Nonnull MethodEncodedValue value) {
return new BuilderMethodEncodedValue(methodPool.internMethod(value.getValue()));
}
@Nonnull private BuilderStringEncodedValue internStringEncodedValue(@Nonnull StringEncodedValue string) {
return new BuilderStringEncodedValue(stringPool.internString(string.getValue()));
}
@Nonnull private BuilderTypeEncodedValue internTypeEncodedValue(@Nonnull TypeEncodedValue type) {
return new BuilderTypeEncodedValue(typePool.internType(type.getValue()));
}
}

View File

@ -0,0 +1,168 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import org.jf.dexlib2.DebugItemType;
import org.jf.dexlib2.iface.debug.*;
import org.jf.dexlib2.immutable.debug.ImmutableEpilogueBegin;
import org.jf.dexlib2.immutable.debug.ImmutableLineNumber;
import org.jf.dexlib2.immutable.debug.ImmutablePrologueEnd;
import javax.annotation.Nullable;
public abstract interface BuilderDebugItem extends DebugItem {
abstract static class BaseBuilderDebugItem implements BuilderDebugItem {
final int codeAddress;
public BaseBuilderDebugItem(int codeAddress) {
this.codeAddress = codeAddress;
}
@Override public int getCodeAddress() { return codeAddress; }
}
public static class BuilderStartLocal extends BaseBuilderDebugItem implements StartLocal {
final int register;
@Nullable final BuilderStringReference name;
@Nullable final BuilderTypeReference type;
@Nullable final BuilderStringReference signature;
BuilderStartLocal(int codeAddress,
int register,
@Nullable BuilderStringReference name,
@Nullable BuilderTypeReference type,
@Nullable BuilderStringReference signature) {
super(codeAddress);
this.register = register;
this.name = name;
this.type = type;
this.signature = signature;
}
@Override public int getRegister() { return register; }
@Nullable @Override public String getName() { return name==null?null:name.getString(); }
@Nullable @Override public String getType() { return type==null?null:type.getType(); }
@Nullable @Override public String getSignature() { return signature==null?null:signature.getString(); }
@Override public int getDebugItemType() { return DebugItemType.START_LOCAL; }
}
public static class BuilderEndLocal extends BaseBuilderDebugItem implements EndLocal {
private final int register;
BuilderEndLocal(int codeAddress, int register) {
super(codeAddress);
this.register = register;
}
@Override public int getRegister() {
return register;
}
@Override public int getDebugItemType() {
return DebugItemType.END_LOCAL;
}
@Nullable @Override public String getName() {
return null;
}
@Nullable @Override public String getType() {
return null;
}
@Nullable @Override public String getSignature() {
return null;
}
}
public static class BuilderRestartLocal extends BaseBuilderDebugItem implements RestartLocal {
private final int register;
BuilderRestartLocal(int codeAddress, int register) {
super(codeAddress);
this.register = register;
}
@Override public int getRegister() {
return register;
}
@Override public int getDebugItemType() {
return DebugItemType.RESTART_LOCAL;
}
@Nullable @Override public String getName() {
return null;
}
@Nullable @Override public String getType() {
return null;
}
@Nullable @Override public String getSignature() {
return null;
}
}
public static class BuilderPrologueEnd extends ImmutablePrologueEnd implements BuilderDebugItem {
BuilderPrologueEnd(int codeAddress) {
super(codeAddress);
}
}
public static class BuilderEpilogueBegin extends ImmutableEpilogueBegin implements BuilderDebugItem {
BuilderEpilogueBegin(int codeAddress) {
super(codeAddress);
}
}
public static class BuilderLineNumber extends ImmutableLineNumber implements BuilderDebugItem {
BuilderLineNumber(int codeAddress, int lineNumber) {
super(codeAddress, lineNumber);
}
}
public static class BuilderSetSourceFile extends BaseBuilderDebugItem implements SetSourceFile {
@Nullable final BuilderStringReference sourceFile;
BuilderSetSourceFile(int codeAddress,
@Nullable BuilderStringReference sourceFile) {
super(codeAddress);
this.sourceFile = sourceFile;
}
@Nullable @Override public String getSourceFile() { return sourceFile==null?null:sourceFile.getString(); }
@Override public int getDebugItemType() { return DebugItemType.SET_SOURCE_FILE; }
}
}

View File

@ -0,0 +1,242 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import org.jf.dexlib2.base.value.*;
import org.jf.dexlib2.iface.value.EncodedValue;
import org.jf.dexlib2.immutable.value.*;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.Set;
public abstract class BuilderEncodedValues {
public static interface BuilderEncodedValue extends EncodedValue {
}
public static class BuilderAnnotationEncodedValue extends BaseAnnotationEncodedValue
implements BuilderEncodedValue {
@Nonnull final BuilderTypeReference typeReference;
@Nonnull final Set<? extends BuilderAnnotationElement> elements;
BuilderAnnotationEncodedValue(@Nonnull BuilderTypeReference typeReference,
@Nonnull Set<? extends BuilderAnnotationElement> elements) {
this.typeReference = typeReference;
this.elements = elements;
}
@Nonnull @Override public String getType() {
return typeReference.getType();
}
@Nonnull @Override public Set<? extends BuilderAnnotationElement> getElements() {
return elements;
}
}
public static class BuilderArrayEncodedValue extends BaseArrayEncodedValue implements BuilderEncodedValue {
@Nonnull final List<? extends BuilderEncodedValue> elements;
BuilderArrayEncodedValue(@Nonnull List<? extends BuilderEncodedValue> elements) {
this.elements = elements;
}
@Nonnull @Override public List<? extends EncodedValue> getValue() {
return elements;
}
}
@Nonnull
public static BuilderEncodedValue defaultValueForType(String type) {
switch (type.charAt(0)) {
case 'Z':
return BuilderBooleanEncodedValue.FALSE_VALUE;
case 'B':
return new BuilderByteEncodedValue((byte)0);
case 'S':
return new BuilderShortEncodedValue((short)0);
case 'C':
return new BuilderCharEncodedValue((char)0);
case 'I':
return new BuilderIntEncodedValue(0);
case 'J':
return new BuilderLongEncodedValue(0);
case 'F':
return new BuilderFloatEncodedValue(0);
case 'D':
return new BuilderDoubleEncodedValue(0);
case 'L':
case '[':
return BuilderNullEncodedValue.INSTANCE;
default:
throw new ExceptionWithContext("Unrecognized type: %s", type);
}
}
public static class BuilderBooleanEncodedValue extends BaseBooleanEncodedValue
implements BuilderEncodedValue {
public static final BuilderBooleanEncodedValue TRUE_VALUE = new BuilderBooleanEncodedValue(true);
public static final BuilderBooleanEncodedValue FALSE_VALUE = new BuilderBooleanEncodedValue(false);
private final boolean value;
private BuilderBooleanEncodedValue(boolean value) {
this.value = value;
}
@Override public boolean getValue() {
return value;
}
}
public static class BuilderByteEncodedValue extends ImmutableByteEncodedValue
implements BuilderEncodedValue {
public BuilderByteEncodedValue(byte value) {
super(value);
}
}
public static class BuilderCharEncodedValue extends ImmutableCharEncodedValue
implements BuilderEncodedValue {
public BuilderCharEncodedValue(char value) {
super(value);
}
}
public static class BuilderDoubleEncodedValue extends ImmutableDoubleEncodedValue
implements BuilderEncodedValue {
public BuilderDoubleEncodedValue(double value) {
super(value);
}
}
public static class BuilderEnumEncodedValue extends BaseEnumEncodedValue
implements BuilderEncodedValue {
@Nonnull final BuilderFieldReference enumReference;
BuilderEnumEncodedValue(@Nonnull BuilderFieldReference enumReference) {
this.enumReference = enumReference;
}
@Nonnull @Override public BuilderFieldReference getValue() {
return enumReference;
}
}
public static class BuilderFieldEncodedValue extends BaseFieldEncodedValue
implements BuilderEncodedValue {
@Nonnull final BuilderFieldReference fieldReference;
BuilderFieldEncodedValue(@Nonnull BuilderFieldReference fieldReference) {
this.fieldReference = fieldReference;
}
@Nonnull @Override public BuilderFieldReference getValue() {
return fieldReference;
}
}
public static class BuilderFloatEncodedValue extends ImmutableFloatEncodedValue
implements BuilderEncodedValue {
public BuilderFloatEncodedValue(float value) {
super(value);
}
}
public static class BuilderIntEncodedValue extends ImmutableIntEncodedValue
implements BuilderEncodedValue {
public BuilderIntEncodedValue(int value) {
super(value);
}
}
public static class BuilderLongEncodedValue extends ImmutableLongEncodedValue
implements BuilderEncodedValue {
public BuilderLongEncodedValue(long value) {
super(value);
}
}
public static class BuilderMethodEncodedValue extends BaseMethodEncodedValue
implements BuilderEncodedValue {
@Nonnull final BuilderMethodReference methodReference;
BuilderMethodEncodedValue(@Nonnull BuilderMethodReference methodReference) {
this.methodReference = methodReference;
}
@Override public BuilderMethodReference getValue() {
return methodReference;
}
}
public static class BuilderNullEncodedValue extends BaseNullEncodedValue
implements BuilderEncodedValue {
public static final BuilderNullEncodedValue INSTANCE = new BuilderNullEncodedValue();
private BuilderNullEncodedValue() {}
}
public static class BuilderShortEncodedValue extends ImmutableShortEncodedValue
implements BuilderEncodedValue {
public BuilderShortEncodedValue(short value) {
super(value);
}
}
public static class BuilderStringEncodedValue extends BaseStringEncodedValue
implements BuilderEncodedValue {
@Nonnull final BuilderStringReference stringReference;
BuilderStringEncodedValue(@Nonnull BuilderStringReference stringReference) {
this.stringReference = stringReference;
}
@Nonnull @Override public String getValue() {
return stringReference.getString();
}
}
public static class BuilderTypeEncodedValue extends BaseTypeEncodedValue
implements BuilderEncodedValue {
@Nonnull final BuilderTypeReference typeReference;
BuilderTypeEncodedValue(@Nonnull BuilderTypeReference typeReference) {
this.typeReference = typeReference;
}
@Nonnull @Override public String getValue() {
return typeReference.getType();
}
}
}

View File

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

View File

@ -0,0 +1,80 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import org.jf.dexlib2.base.reference.BaseFieldReference;
import org.jf.dexlib2.iface.Field;
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BuilderField extends BaseFieldReference implements Field {
@Nonnull final BuilderFieldReference fieldReference;
final int accessFlags;
@Nullable final BuilderEncodedValue initialValue;
@Nonnull final BuilderAnnotationSet annotations;
BuilderField(@Nonnull BuilderFieldReference fieldReference,
int accessFlags,
@Nullable BuilderEncodedValue initialValue,
@Nonnull BuilderAnnotationSet annotations) {
this.fieldReference = fieldReference;
this.accessFlags = accessFlags;
this.initialValue = initialValue;
this.annotations = annotations;
}
@Override public int getAccessFlags() {
return accessFlags;
}
@Nullable @Override public BuilderEncodedValue getInitialValue() {
return initialValue;
}
@Nonnull @Override public BuilderAnnotationSet getAnnotations() {
return annotations;
}
@Nonnull @Override public String getDefiningClass() {
return fieldReference.definingClass.getType();
}
@Nonnull @Override public String getName() {
return fieldReference.name.getString();
}
@Nonnull @Override public String getType() {
return fieldReference.fieldType.getType();
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.collect.Maps;
import org.jf.dexlib2.iface.reference.FieldReference;
import org.jf.dexlib2.immutable.reference.ImmutableFieldReference;
import org.jf.dexlib2.writer.FieldSection;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
public class BuilderFieldPool
implements FieldSection<BuilderStringReference, BuilderTypeReference, BuilderFieldReference, BuilderField> {
@Nonnull private final BuilderContext context;
@Nonnull private final ConcurrentMap<FieldReference, BuilderFieldReference> internedItems =
Maps.newConcurrentMap();
BuilderFieldPool(@Nonnull BuilderContext context) {
this.context = context;
}
@Nonnull BuilderFieldReference internField(@Nonnull String definingClass, String name, String type) {
ImmutableFieldReference fieldReference = new ImmutableFieldReference(definingClass, name, type);
return internField(fieldReference);
}
@Nonnull public BuilderFieldReference internField(@Nonnull FieldReference fieldReference) {
BuilderFieldReference ret = internedItems.get(fieldReference);
if (ret != null) {
return ret;
}
BuilderFieldReference dexPoolFieldReference = new BuilderFieldReference(
context.typePool.internType(fieldReference.getDefiningClass()),
context.stringPool.internString(fieldReference.getName()),
context.typePool.internType(fieldReference.getType()));
ret = internedItems.putIfAbsent(dexPoolFieldReference, dexPoolFieldReference);
return ret==null?dexPoolFieldReference:ret;
}
@Nonnull @Override
public BuilderTypeReference getDefiningClass(@Nonnull BuilderFieldReference key) {
return key.definingClass;
}
@Nonnull @Override public BuilderTypeReference getFieldType(@Nonnull BuilderFieldReference key) {
return key.fieldType;
}
@Nonnull @Override public BuilderStringReference getName(@Nonnull BuilderFieldReference key) {
return key.name;
}
@Override public int getFieldIndex(@Nonnull BuilderField builderField) {
return builderField.fieldReference.getIndex();
}
@Override public int getItemIndex(@Nonnull BuilderFieldReference key) {
return key.index;
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderFieldReference, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderFieldReference>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderFieldReference key) {
return key.index;
}
@Override protected int setValue(@Nonnull BuilderFieldReference key, int value) {
int prev = key.index;
key.index = value;
return prev;
}
};
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import org.jf.dexlib2.base.reference.BaseFieldReference;
import org.jf.dexlib2.writer.DexWriter;
import javax.annotation.Nonnull;
public class BuilderFieldReference extends BaseFieldReference implements BuilderReference {
@Nonnull final BuilderTypeReference definingClass;
@Nonnull final BuilderStringReference name;
@Nonnull final BuilderTypeReference fieldType;
int index = DexWriter.NO_INDEX;
BuilderFieldReference(@Nonnull BuilderTypeReference definingClass,
@Nonnull BuilderStringReference name,
@Nonnull BuilderTypeReference fieldType) {
this.definingClass = definingClass;
this.name = name;
this.fieldType = fieldType;
}
@Nonnull @Override public String getDefiningClass() {
return definingClass.getType();
}
@Nonnull @Override public String getName() {
return name.getString();
}
@Nonnull @Override public String getType() {
return fieldType.getType();
}
@Override public int getIndex() {
return index;
}
@Override public void setIndex(int index) {
this.index = index;
}
}

View File

@ -0,0 +1,432 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.collect.ImmutableList;
import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.SwitchElement;
import org.jf.dexlib2.iface.instruction.formats.*;
import org.jf.dexlib2.immutable.instruction.*;
import org.jf.dexlib2.util.Preconditions;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public interface BuilderInstruction extends Instruction {
static abstract class BaseBuilderInstruction implements BuilderInstruction {
@Nonnull protected final Opcode opcode;
public BaseBuilderInstruction(@Nonnull Opcode opcode) {
this.opcode = opcode;
}
@Nonnull public abstract Format getFormat();
@Nonnull @Override public Opcode getOpcode() {
return opcode;
}
@Override public int getCodeUnits() {
return getFormat().size/2;
}
}
public static class BuilderInstruction10t extends ImmutableInstruction10t implements BuilderInstruction {
public BuilderInstruction10t(@Nonnull Opcode opcode, int codeOffset) {
super(opcode, codeOffset);
}
}
public static class BuilderInstruction10x extends ImmutableInstruction10x implements BuilderInstruction {
public BuilderInstruction10x(@Nonnull Opcode opcode) {
super(opcode);
}
}
public static class BuilderInstruction11n extends ImmutableInstruction11n implements BuilderInstruction {
public BuilderInstruction11n(@Nonnull Opcode opcode, int registerA, int literal) {
super(opcode, registerA, literal);
}
}
public static class BuilderInstruction11x extends ImmutableInstruction11x implements BuilderInstruction {
public BuilderInstruction11x(@Nonnull Opcode opcode, int registerA) {
super(opcode, registerA);
}
}
public static class BuilderInstruction12x extends ImmutableInstruction12x implements BuilderInstruction {
public BuilderInstruction12x(@Nonnull Opcode opcode, int registerA, int registerB) {
super(opcode, registerA, registerB);
}
}
public static class BuilderInstruction20bc extends BaseBuilderInstruction implements Instruction20bc {
public static final Format FORMAT = Format.Format20bc;
protected final int verificationError;
@Nonnull protected final BuilderReference reference;
public BuilderInstruction20bc(@Nonnull Opcode opcode,
int verificationError,
@Nonnull BuilderReference reference) {
super(opcode);
Preconditions.checkFormat(opcode, FORMAT);
this.verificationError = Preconditions.checkVerificationError(verificationError);
this.reference = Preconditions.checkReference(opcode.referenceType, reference);
}
@Override public int getVerificationError() { return verificationError; }
@Nonnull @Override public BuilderReference getReference() { return reference; }
@Nonnull @Override public Format getFormat() { return FORMAT; }
}
public static class BuilderInstruction20t extends ImmutableInstruction20t implements BuilderInstruction {
public BuilderInstruction20t(@Nonnull Opcode opcode, int codeOffset) {
super(opcode, codeOffset);
}
}
public static class BuilderInstruction21c extends BaseBuilderInstruction implements Instruction21c {
public static final Format FORMAT = Format.Format21c;
protected final int registerA;
@Nonnull protected final BuilderReference reference;
public BuilderInstruction21c(@Nonnull Opcode opcode,
int registerA,
@Nonnull BuilderReference reference) {
super(opcode);
Preconditions.checkFormat(opcode, FORMAT);
this.registerA = Preconditions.checkByteRegister(registerA);
this.reference = Preconditions.checkReference(opcode.referenceType, reference);
}
@Override public int getRegisterA() { return registerA; }
@Nonnull @Override public BuilderReference getReference() { return reference; }
@Nonnull @Override public Format getFormat() { return FORMAT; }
}
public static class BuilderInstruction21ih extends ImmutableInstruction21ih implements BuilderInstruction {
public BuilderInstruction21ih(@Nonnull Opcode opcode, int registerA, int literal) {
super(opcode, registerA, literal);
}
}
public static class BuilderInstruction21lh extends ImmutableInstruction21lh implements BuilderInstruction {
public BuilderInstruction21lh(@Nonnull Opcode opcode, int registerA, long literal) {
super(opcode, registerA, literal);
}
}
public static class BuilderInstruction21s extends ImmutableInstruction21s implements BuilderInstruction {
public BuilderInstruction21s(@Nonnull Opcode opcode, int registerA, int literal) {
super(opcode, registerA, literal);
}
}
public static class BuilderInstruction21t extends ImmutableInstruction21t implements BuilderInstruction {
public BuilderInstruction21t(@Nonnull Opcode opcode, int registerA, int codeOffset) {
super(opcode, registerA, codeOffset);
}
}
public static class BuilderInstruction22b extends ImmutableInstruction22b implements BuilderInstruction {
public BuilderInstruction22b(@Nonnull Opcode opcode, int registerA, int registerB, int literal) {
super(opcode, registerA, registerB, literal);
}
}
public static class BuilderInstruction22c extends BaseBuilderInstruction implements Instruction22c {
public static final Format FORMAT = Format.Format22c;
protected final int registerA;
protected final int registerB;
@Nonnull protected final BuilderReference reference;
public BuilderInstruction22c(@Nonnull Opcode opcode,
int registerA,
int registerB,
@Nonnull BuilderReference reference) {
super(opcode);
Preconditions.checkFormat(opcode, FORMAT);
this.registerA = Preconditions.checkNibbleRegister(registerA);
this.registerB = Preconditions.checkNibbleRegister(registerB);
this.reference = Preconditions.checkReference(opcode.referenceType, reference);
}
@Override public int getRegisterA() { return registerA; }
@Override public int getRegisterB() { return registerB; }
@Nonnull @Override public BuilderReference getReference() { return reference; }
@Nonnull @Override public Format getFormat() { return FORMAT; }
}
public static class BuilderInstruction22s extends ImmutableInstruction22s implements BuilderInstruction {
public BuilderInstruction22s(@Nonnull Opcode opcode, int registerA, int registerB, int literal) {
super(opcode, registerA, registerB, literal);
}
}
public static class BuilderInstruction22t extends ImmutableInstruction22t implements BuilderInstruction {
public BuilderInstruction22t(@Nonnull Opcode opcode, int registerA, int registerB, int codeOffset) {
super(opcode, registerA, registerB, codeOffset);
}
}
public static class BuilderInstruction22x extends ImmutableInstruction22x implements BuilderInstruction {
public BuilderInstruction22x(@Nonnull Opcode opcode, int registerA, int registerB) {
super(opcode, registerA, registerB);
}
}
public static class BuilderInstruction23x extends ImmutableInstruction23x implements BuilderInstruction {
public BuilderInstruction23x(@Nonnull Opcode opcode, int registerA, int registerB, int registerC) {
super(opcode, registerA, registerB, registerC);
}
}
public static class BuilderInstruction30t extends ImmutableInstruction30t implements BuilderInstruction {
public BuilderInstruction30t(@Nonnull Opcode opcode, int codeOffset) {
super(opcode, codeOffset);
}
}
public static class BuilderInstruction31c extends BaseBuilderInstruction implements Instruction31c {
public static final Format FORMAT = Format.Format31c;
protected final int registerA;
@Nonnull protected final BuilderReference reference;
public BuilderInstruction31c(@Nonnull Opcode opcode,
int registerA,
@Nonnull BuilderReference reference) {
super(opcode);
Preconditions.checkFormat(opcode, FORMAT);
this.registerA = Preconditions.checkByteRegister(registerA);
this.reference = Preconditions.checkReference(opcode.referenceType, reference);
}
@Override public int getRegisterA() { return registerA; }
@Nonnull @Override public BuilderReference getReference() { return reference; }
@Nonnull @Override public Format getFormat() { return FORMAT; }
}
public static class BuilderInstruction31i extends ImmutableInstruction31i implements BuilderInstruction {
public BuilderInstruction31i(@Nonnull Opcode opcode, int registerA, int literal) {
super(opcode, registerA, literal);
}
}
public static class BuilderInstruction31t extends ImmutableInstruction31t implements BuilderInstruction {
public BuilderInstruction31t(@Nonnull Opcode opcode, int registerA, int codeOffset) {
super(opcode, registerA, codeOffset);
}
}
public static class BuilderInstruction32x extends ImmutableInstruction32x implements BuilderInstruction {
public BuilderInstruction32x(@Nonnull Opcode opcode, int registerA, int registerB) {
super(opcode, registerA, registerB);
}
}
public static class BuilderInstruction35c extends BaseBuilderInstruction implements Instruction35c {
public static final Format FORMAT = Format.Format35c;
protected final int registerCount;
protected final int registerC;
protected final int registerD;
protected final int registerE;
protected final int registerF;
protected final int registerG;
@Nonnull protected final BuilderReference reference;
public BuilderInstruction35c(@Nonnull Opcode opcode,
int registerCount,
int registerC,
int registerD,
int registerE,
int registerF,
int registerG,
@Nonnull BuilderReference reference) {
super(opcode);
Preconditions.checkFormat(opcode, FORMAT);
this.registerCount = Preconditions.check35cRegisterCount(registerCount);
this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0;
this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0;
this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0;
this.registerF = (registerCount>3) ? Preconditions.checkNibbleRegister(registerF) : 0;
this.registerG = (registerCount>4) ? Preconditions.checkNibbleRegister(registerG) : 0;
this.reference = Preconditions.checkReference(opcode.referenceType, reference);
}
@Override public int getRegisterCount() { return registerCount; }
@Override public int getRegisterC() { return registerC; }
@Override public int getRegisterD() { return registerD; }
@Override public int getRegisterE() { return registerE; }
@Override public int getRegisterF() { return registerF; }
@Override public int getRegisterG() { return registerG; }
@Nonnull @Override public BuilderReference getReference() { return reference; }
@Nonnull @Override public Format getFormat() { return FORMAT; }
}
public static class BuilderInstruction3rc extends BaseBuilderInstruction implements Instruction3rc {
public static final Format FORMAT = Format.Format3rc;
private final int startRegister;
private final int registerCount;
@Nonnull protected final BuilderReference reference;
public BuilderInstruction3rc(@Nonnull Opcode opcode,
int startRegister,
int registerCount,
@Nonnull BuilderReference reference) {
super(opcode);
Preconditions.checkFormat(opcode, FORMAT);
this.startRegister = Preconditions.checkShortRegister(startRegister);
this.registerCount = Preconditions.checkRegisterRangeCount(registerCount);
this.reference = Preconditions.checkReference(opcode.referenceType, reference);
}
@Nonnull @Override public BuilderReference getReference() {
return reference;
}
@Override public int getStartRegister() {
return startRegister;
}
@Override public int getRegisterCount() {
return registerCount;
}
@Nonnull @Override public Format getFormat() {
return FORMAT;
}
}
public static class BuilderInstruction51l extends ImmutableInstruction51l implements BuilderInstruction {
public BuilderInstruction51l(@Nonnull Opcode opcode, int registerA, long literal) {
super(opcode, registerA, literal);
}
}
public static class BuilderArrayPayload extends BaseBuilderInstruction implements ArrayPayload {
public static final Format FORMAT = Format.ArrayPayload;
private final int elementWidth;
@Nonnull private final List<Number> arrayElements;
public BuilderArrayPayload(int elementWidth, @Nullable List<Number> arrayElements) {
super(Opcode.ARRAY_PAYLOAD);
this.elementWidth = elementWidth;
if (arrayElements == null) {
arrayElements = ImmutableList.of();
}
this.arrayElements = arrayElements;
}
@Override public int getElementWidth() {
return elementWidth;
}
@Nonnull @Override public List<Number> getArrayElements() {
return arrayElements;
}
@Nonnull @Override public Format getFormat() {
return FORMAT;
}
@Override public int getCodeUnits() {
return 4 + (elementWidth * arrayElements.size() + 1) / 2;
}
}
public static class BuilderPackedSwitchPayload extends BaseBuilderInstruction implements PackedSwitchPayload {
public static final Format FORMAT = Format.PackedSwitchPayload;
@Nonnull private final List<? extends SwitchElement> elements;
public BuilderPackedSwitchPayload(@Nullable List<? extends SwitchElement> switchElements) {
super(Opcode.PACKED_SWITCH_PAYLOAD);
if (switchElements == null) {
switchElements = ImmutableList.of();
}
this.elements = switchElements;
}
@Nonnull @Override public List<? extends SwitchElement> getSwitchElements() {
return elements;
}
@Nonnull @Override public Format getFormat() {
return FORMAT;
}
@Override public int getCodeUnits() {
return 4 + elements.size() * 2;
}
}
public static class BuilderSparseSwitchPayload extends BaseBuilderInstruction implements SparseSwitchPayload {
public static final Format FORMAT = Format.SparseSwitchPayload;
@Nonnull private final List<? extends SwitchElement> elements;
public BuilderSparseSwitchPayload(@Nullable List<? extends SwitchElement> switchElements) {
super(Opcode.SPARSE_SWITCH_PAYLOAD);
if (switchElements == null) {
switchElements = ImmutableList.of();
}
this.elements = switchElements;
}
@Nonnull @Override public List<? extends SwitchElement> getSwitchElements() {
return elements;
}
@Nonnull @Override public Format getFormat() {
return FORMAT;
}
@Override public int getCodeUnits() {
return 2 + elements.size() * 4;
}
}
}

View File

@ -0,0 +1,223 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.instruction.SwitchElement;
import org.jf.dexlib2.writer.InstructionFactory;
import org.jf.dexlib2.writer.builder.BuilderInstruction.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class BuilderInstructionFactory implements InstructionFactory<BuilderInstruction, BuilderReference> {
public static final BuilderInstructionFactory INSTANCE = new BuilderInstructionFactory();
private BuilderInstructionFactory() {
}
public BuilderInstruction10t makeInstruction10t(@Nonnull Opcode opcode,
int codeOffset) {
return new BuilderInstruction10t(opcode, codeOffset);
}
public BuilderInstruction10x makeInstruction10x(@Nonnull Opcode opcode) {
return new BuilderInstruction10x(opcode);
}
public BuilderInstruction11n makeInstruction11n(@Nonnull Opcode opcode,
int registerA,
int literal) {
return new BuilderInstruction11n(opcode, registerA, literal);
}
public BuilderInstruction11x makeInstruction11x(@Nonnull Opcode opcode,
int registerA) {
return new BuilderInstruction11x(opcode, registerA);
}
public BuilderInstruction12x makeInstruction12x(@Nonnull Opcode opcode,
int registerA,
int registerB) {
return new BuilderInstruction12x(opcode, registerA, registerB);
}
public BuilderInstruction20bc makeInstruction20bc(@Nonnull Opcode opcode,
int verificationError,
@Nonnull BuilderReference reference) {
return new BuilderInstruction20bc(opcode, verificationError, reference);
}
public BuilderInstruction20t makeInstruction20t(@Nonnull Opcode opcode,
int codeOffset) {
return new BuilderInstruction20t(opcode, codeOffset);
}
public BuilderInstruction21c makeInstruction21c(@Nonnull Opcode opcode,
int registerA,
@Nonnull BuilderReference reference) {
return new BuilderInstruction21c(opcode, registerA, reference);
}
public BuilderInstruction21ih makeInstruction21ih(@Nonnull Opcode opcode,
int registerA,
int literal) {
return new BuilderInstruction21ih(opcode, registerA, literal);
}
public BuilderInstruction21lh makeInstruction21lh(@Nonnull Opcode opcode,
int registerA,
long literal) {
return new BuilderInstruction21lh(opcode, registerA, literal);
}
public BuilderInstruction21s makeInstruction21s(@Nonnull Opcode opcode,
int registerA,
int literal) {
return new BuilderInstruction21s(opcode, registerA, literal);
}
public BuilderInstruction21t makeInstruction21t(@Nonnull Opcode opcode,
int registerA,
int codeOffset) {
return new BuilderInstruction21t(opcode, registerA, codeOffset);
}
public BuilderInstruction22b makeInstruction22b(@Nonnull Opcode opcode,
int registerA,
int registerB,
int literal) {
return new BuilderInstruction22b(opcode, registerA, registerB, literal);
}
public BuilderInstruction22c makeInstruction22c(@Nonnull Opcode opcode,
int registerA,
int registerB,
@Nonnull BuilderReference reference) {
return new BuilderInstruction22c(opcode, registerA, registerB, reference);
}
public BuilderInstruction22s makeInstruction22s(@Nonnull Opcode opcode,
int registerA,
int registerB,
int literal) {
return new BuilderInstruction22s(opcode, registerA, registerB, literal);
}
public BuilderInstruction22t makeInstruction22t(@Nonnull Opcode opcode,
int registerA,
int registerB,
int codeOffset) {
return new BuilderInstruction22t(opcode, registerA, registerB, codeOffset);
}
public BuilderInstruction22x makeInstruction22x(@Nonnull Opcode opcode,
int registerA,
int registerB) {
return new BuilderInstruction22x(opcode, registerA, registerB);
}
public BuilderInstruction23x makeInstruction23x(@Nonnull Opcode opcode,
int registerA,
int registerB,
int registerC) {
return new BuilderInstruction23x(opcode, registerA, registerB, registerC);
}
public BuilderInstruction30t makeInstruction30t(@Nonnull Opcode opcode,
int codeOffset) {
return new BuilderInstruction30t(opcode, codeOffset);
}
public BuilderInstruction31c makeInstruction31c(@Nonnull Opcode opcode,
int registerA,
@Nonnull BuilderReference reference) {
return new BuilderInstruction31c(opcode, registerA, reference);
}
public BuilderInstruction31i makeInstruction31i(@Nonnull Opcode opcode,
int registerA,
int literal) {
return new BuilderInstruction31i(opcode, registerA, literal);
}
public BuilderInstruction31t makeInstruction31t(@Nonnull Opcode opcode,
int registerA,
int codeOffset) {
return new BuilderInstruction31t(opcode, registerA, codeOffset);
}
public BuilderInstruction32x makeInstruction32x(@Nonnull Opcode opcode,
int registerA,
int registerB) {
return new BuilderInstruction32x(opcode, registerA, registerB);
}
public BuilderInstruction35c makeInstruction35c(@Nonnull Opcode opcode,
int registerCount,
int registerC,
int registerD,
int registerE,
int registerF,
int registerG,
@Nonnull BuilderReference reference) {
return new BuilderInstruction35c(opcode, registerCount, registerC, registerD, registerE, registerF, registerG,
reference);
}
public BuilderInstruction3rc makeInstruction3rc(@Nonnull Opcode opcode,
int startRegister,
int registerCount,
@Nonnull BuilderReference reference) {
return new BuilderInstruction3rc(opcode, startRegister, registerCount, reference);
}
public BuilderInstruction51l makeInstruction51l(@Nonnull Opcode opcode,
int registerA,
long literal) {
return new BuilderInstruction51l(opcode, registerA, literal);
}
public BuilderSparseSwitchPayload makeSparseSwitchPayload(@Nullable List<? extends SwitchElement> switchElements) {
return new BuilderSparseSwitchPayload(switchElements);
}
public BuilderPackedSwitchPayload makePackedSwitchPayload(@Nullable List<? extends SwitchElement> switchElements) {
return new BuilderPackedSwitchPayload(switchElements);
}
public BuilderArrayPayload makeArrayPayload(int elementWidth,
@Nullable List<Number> arrayElements) {
return new BuilderArrayPayload(elementWidth, arrayElements);
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import javax.annotation.Nonnull;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
public abstract class BuilderMapEntryCollection<Key> extends AbstractCollection<Map.Entry<Key, Integer>> {
@Nonnull private final Collection<Key> keys;
public BuilderMapEntryCollection(@Nonnull Collection<Key> keys) {
this.keys = keys;
}
private class MapEntry implements Map.Entry<Key, Integer> {
@Nonnull private Key key;
@Nonnull @Override public Key getKey() {
return key;
}
@Override public Integer getValue() {
return BuilderMapEntryCollection.this.getValue(key);
}
@Override public Integer setValue(Integer value) {
return BuilderMapEntryCollection.this.setValue(key, value);
}
}
@Nonnull @Override public Iterator<Map.Entry<Key, Integer>> iterator() {
final Iterator<Key> iter = keys.iterator();
return new Iterator<Map.Entry<Key, Integer>>() {
@Override public boolean hasNext() {
return iter.hasNext();
}
@Override public Map.Entry<Key, Integer> next() {
MapEntry entry = new MapEntry();
entry.key = iter.next();
return entry;
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override public int size() {
return keys.size();
}
protected abstract int getValue(@Nonnull Key key);
protected abstract int setValue(@Nonnull Key key, int value);
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import org.jf.dexlib2.base.reference.BaseMethodReference;
import org.jf.dexlib2.iface.Method;
import org.jf.dexlib2.writer.DexWriter;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class BuilderMethod extends BaseMethodReference implements Method {
@Nonnull final BuilderMethodReference methodReference;
@Nonnull final List<? extends BuilderMethodParameter> parameters;
final int accessFlags;
@Nonnull final BuilderAnnotationSet annotations;
@Nullable final BuilderMethodImplementation methodImplementation;
int annotationSetRefListOffset = DexWriter.NO_OFFSET;
int codeItemOffset = DexWriter.NO_OFFSET;
int debugInfoOffset = DexWriter.NO_OFFSET;
BuilderMethod(@Nonnull BuilderMethodReference methodReference,
@Nonnull List<? extends BuilderMethodParameter> parameters,
int accessFlags,
@Nonnull BuilderAnnotationSet annotations,
@Nullable BuilderMethodImplementation methodImplementation) {
this.methodReference = methodReference;
this.parameters = parameters;
this.accessFlags = accessFlags;
this.annotations = annotations;
this.methodImplementation = methodImplementation;
}
@Override @Nonnull public String getDefiningClass() { return methodReference.definingClass.getType(); }
@Override @Nonnull public String getName() { return methodReference.name.getString(); }
@Override @Nonnull public BuilderTypeList getParameterTypes() { return methodReference.proto.parameterTypes; }
@Nonnull @Override public String getReturnType() { return methodReference.proto.returnType.getType(); }
@Override @Nonnull public List<? extends BuilderMethodParameter> getParameters() { return parameters; }
@Override public int getAccessFlags() { return accessFlags; }
@Override @Nonnull public BuilderAnnotationSet getAnnotations() { return annotations; }
@Override @Nullable public BuilderMethodImplementation getImplementation() { return methodImplementation; }
}

View File

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

View File

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

View File

@ -0,0 +1,145 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.collect.Maps;
import org.jf.dexlib2.base.reference.BaseMethodReference;
import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.writer.MethodSection;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
class BuilderMethodPool implements MethodSection<BuilderStringReference, BuilderTypeReference,
BuilderProtoReference, BuilderMethodReference, BuilderMethod>{
@Nonnull private final BuilderContext context;
@Nonnull private final ConcurrentMap<MethodReference, BuilderMethodReference> internedItems =
Maps.newConcurrentMap();
BuilderMethodPool(@Nonnull BuilderContext context) {
this.context = context;
}
@Nonnull public BuilderMethodReference internMethod(@Nonnull MethodReference methodReference) {
BuilderMethodReference ret = internedItems.get(methodReference);
if (ret != null) {
return ret;
}
BuilderMethodReference dexPoolMethodReference = new BuilderMethodReference(
context.typePool.internType(methodReference.getDefiningClass()),
context.stringPool.internString(methodReference.getName()),
context.protoPool.internProto(methodReference));
ret = internedItems.putIfAbsent(dexPoolMethodReference, dexPoolMethodReference);
return ret==null?dexPoolMethodReference:ret;
}
@Nonnull public BuilderMethodReference internMethod(@Nonnull String definingClass, @Nonnull String name,
@Nonnull List<? extends CharSequence> parameters,
@Nonnull String returnType) {
return internMethod(new MethodKey(definingClass, name, parameters, returnType));
}
@Nonnull @Override
public BuilderTypeReference getDefiningClass(@Nonnull BuilderMethodReference key) {
return key.definingClass;
}
@Nonnull @Override
public BuilderProtoReference getPrototype(@Nonnull BuilderMethodReference key) {
return key.proto;
}
@Nonnull @Override public BuilderProtoReference getPrototype(@Nonnull BuilderMethod builderMethod) {
return builderMethod.methodReference.proto;
}
@Nonnull @Override public BuilderStringReference getName(@Nonnull BuilderMethodReference key) {
return key.name;
}
@Override public int getMethodIndex(@Nonnull BuilderMethod builderMethod) {
return builderMethod.methodReference.index;
}
@Override public int getItemIndex(@Nonnull BuilderMethodReference key) {
return key.index;
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderMethodReference, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderMethodReference>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderMethodReference key) {
return key.index;
}
@Override protected int setValue(@Nonnull BuilderMethodReference key, int value) {
int prev = key.index;
key.index = value;
return prev;
}
};
}
private static class MethodKey extends BaseMethodReference implements MethodReference {
@Nonnull private final String definingClass;
@Nonnull private final String name;
@Nonnull private final List<? extends CharSequence> parameterTypes;
@Nonnull private final String returnType;
public MethodKey(@Nonnull String definingClass, @Nonnull String name,
@Nonnull List<? extends CharSequence> parameterTypes, @Nonnull String returnType) {
this.definingClass = definingClass;
this.name = name;
this.parameterTypes = parameterTypes;
this.returnType = returnType;
}
@Nonnull @Override public String getDefiningClass() {
return definingClass;
}
@Nonnull @Override public String getName() {
return name;
}
@Nonnull @Override public List<? extends CharSequence> getParameterTypes() {
return parameterTypes;
}
@Nonnull @Override public String getReturnType() {
return returnType;
}
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import org.jf.dexlib2.base.reference.BaseMethodReference;
import org.jf.dexlib2.writer.DexWriter;
import javax.annotation.Nonnull;
public class BuilderMethodReference extends BaseMethodReference implements BuilderReference {
@Nonnull final BuilderTypeReference definingClass;
@Nonnull final BuilderStringReference name;
@Nonnull final BuilderProtoReference proto;
int index = DexWriter.NO_INDEX;
BuilderMethodReference(@Nonnull BuilderTypeReference definingClass,
@Nonnull BuilderStringReference name,
@Nonnull BuilderProtoReference proto) {
this.definingClass = definingClass;
this.name = name;
this.proto = proto;
}
@Nonnull @Override public String getDefiningClass() {
return definingClass.getType();
}
@Nonnull @Override public String getName() {
return this.name.getString();
}
@Nonnull @Override public BuilderTypeList getParameterTypes() {
return proto.parameterTypes;
}
@Nonnull @Override public String getReturnType() {
return proto.returnType.getType();
}
@Override public int getIndex() {
return index;
}
@Override public void setIndex(int index) {
this.index = index;
}
}

View File

@ -0,0 +1,145 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.collect.Maps;
import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.util.MethodUtil;
import org.jf.dexlib2.writer.ProtoSection;
import org.jf.util.CharSequenceUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
class BuilderProtoPool
implements ProtoSection<BuilderStringReference, BuilderTypeReference, BuilderProtoReference, BuilderTypeList> {
@Nonnull private final BuilderContext context;
@Nonnull private final ConcurrentMap<ProtoKey, BuilderProtoReference> internedItems =
Maps.newConcurrentMap();
BuilderProtoPool(@Nonnull BuilderContext context) {
this.context = context;
}
@Nonnull public BuilderProtoReference internProto(@Nonnull List<? extends CharSequence> parameters,
@Nonnull String returnType) {
ProtoKey key = new Key(parameters, returnType);
BuilderProtoReference ret = internedItems.get(key);
if (ret != null) {
return ret;
}
BuilderProtoReference protoReference = new BuilderProtoReference(
context.stringPool.internString(MethodUtil.getShorty(parameters, returnType)),
context.typeListPool.internTypeList(parameters),
context.typePool.internType(returnType));
ret = internedItems.putIfAbsent(protoReference, protoReference);
return ret==null?protoReference:ret;
}
@Nonnull public BuilderProtoReference internProto(@Nonnull MethodReference methodReference) {
return internProto(methodReference.getParameterTypes(), methodReference.getReturnType());
}
@Nonnull @Override public BuilderStringReference getShorty(@Nonnull BuilderProtoReference key) {
return key.shorty;
}
@Nonnull @Override public BuilderTypeReference getReturnType(@Nonnull BuilderProtoReference key) {
return key.returnType;
}
@Nullable @Override public BuilderTypeList getParameters(@Nonnull BuilderProtoReference key) {
return key.parameterTypes;
}
@Override public int getItemIndex(@Nonnull BuilderProtoReference key) {
return key.index;
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderProtoReference, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderProtoReference>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderProtoReference key) {
return key.index;
}
@Override protected int setValue(@Nonnull BuilderProtoReference key, int value) {
int prev = key.index;
key.index = value;
return prev;
}
};
}
// a placeholder interface to unify the temporary probing key and the BuilderProtoReference class
interface ProtoKey {
@Nonnull List<? extends CharSequence> getParameterTypes();
@Nonnull String getReturnType();
}
// a temporary lightweight class to allow a quick probe if the given prototype has already been interned
private static class Key implements ProtoKey {
@Nonnull private final List<? extends CharSequence> parameters;
@Nonnull private final String returnType;
public Key(@Nonnull List<? extends CharSequence> parameters, @Nonnull String returnType) {
this.parameters = parameters;
this.returnType = returnType;
}
@Nonnull public List<? extends CharSequence> getParameterTypes() {
return parameters;
}
@Nonnull public String getReturnType() {
return returnType;
}
@Override public int hashCode() {
int hashCode = returnType.hashCode();
return hashCode*31 + parameters.hashCode();
}
@Override public boolean equals(Object o) {
if (o != null && o instanceof ProtoKey) {
ProtoKey other = (ProtoKey)o;
return getReturnType().equals(other.getReturnType()) &&
CharSequenceUtils.listEquals(getParameterTypes(), other.getParameterTypes());
}
return false;
}
}
}

View File

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

View File

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

View File

@ -0,0 +1,86 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.collect.Maps;
import org.jf.dexlib2.writer.DexWriter;
import org.jf.dexlib2.writer.StringSection;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
class BuilderStringPool implements StringSection<BuilderStringReference, BuilderStringReference> {
@Nonnull private final ConcurrentMap<String, BuilderStringReference> internedItems = Maps.newConcurrentMap();
@Nonnull BuilderStringReference internString(@Nonnull String string) {
BuilderStringReference ret = internedItems.get(string);
if (ret != null) {
return ret;
}
BuilderStringReference stringReference = new BuilderStringReference(string);
ret = internedItems.putIfAbsent(string, stringReference);
return ret==null?stringReference:ret;
}
@Nullable BuilderStringReference internNullableString(@Nullable String string) {
if (string == null) {
return null;
}
return internString(string);
}
@Override public int getNullableItemIndex(@Nullable BuilderStringReference key) {
return key==null?DexWriter.NO_INDEX:key.index;
}
@Override public int getItemIndex(@Nonnull BuilderStringReference key) {
return key.index;
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderStringReference, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderStringReference>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderStringReference key) {
// TODO: see what the performance of using key.getIndex() for everything is like
return key.index;
}
@Override protected int setValue(@Nonnull BuilderStringReference key, int value) {
int prev = key.index;
key.index = value;
return prev;
}
};
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,104 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import org.jf.dexlib2.writer.DexWriter;
import org.jf.dexlib2.writer.TypeListSection;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
class BuilderTypeListPool implements TypeListSection<BuilderTypeReference, BuilderTypeList> {
@Nonnull private final BuilderContext context;
@Nonnull private final ConcurrentMap<List<? extends CharSequence>, BuilderTypeList> internedItems =
Maps.newConcurrentMap();
BuilderTypeListPool(@Nonnull BuilderContext context) {
this.context = context;
}
@Nonnull public BuilderTypeList internTypeList(@Nullable List<? extends CharSequence> types) {
if (types == null) {
return BuilderTypeList.EMPTY;
}
BuilderTypeList ret = internedItems.get(types);
if (ret != null) {
return ret;
}
BuilderTypeList typeList = new BuilderTypeList(
ImmutableList.copyOf(Iterables.transform(types, new Function<CharSequence, BuilderTypeReference>() {
@Nonnull @Override public BuilderTypeReference apply(CharSequence input) {
return context.typePool.internType(input.toString());
}
})));
ret = internedItems.putIfAbsent(typeList, typeList);
return ret==null?typeList:ret;
}
@Override public int getNullableItemOffset(@Nullable BuilderTypeList key) {
return key==null?DexWriter.NO_OFFSET:key.offset;
}
@Nonnull @Override
public Collection<? extends BuilderTypeReference> getTypes(@Nullable BuilderTypeList key) {
return key==null?BuilderTypeList.EMPTY:key.types;
}
@Override public int getItemOffset(@Nonnull BuilderTypeList key) {
return key.offset;
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderTypeList, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderTypeList>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderTypeList key) {
return key.offset;
}
@Override protected int setValue(@Nonnull BuilderTypeList key, int value) {
int prev = key.offset;
key.offset = value;
return prev;
}
};
}
}

View File

@ -0,0 +1,95 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.collect.Maps;
import org.jf.dexlib2.writer.DexWriter;
import org.jf.dexlib2.writer.TypeSection;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
class BuilderTypePool implements TypeSection<BuilderStringReference, BuilderTypeReference, BuilderTypeReference> {
@Nonnull private final BuilderContext context;
@Nonnull private final ConcurrentMap<String, BuilderTypeReference> internedItems = Maps.newConcurrentMap();
BuilderTypePool(@Nonnull BuilderContext context) {
this.context = context;
}
@Nonnull public BuilderTypeReference internType(@Nonnull String type) {
BuilderTypeReference ret = internedItems.get(type);
if (ret != null) {
return ret;
}
BuilderStringReference stringRef = context.stringPool.internString(type);
BuilderTypeReference typeReference = new BuilderTypeReference(stringRef);
ret = internedItems.putIfAbsent(type, typeReference);
return ret==null?typeReference:ret;
}
@Nullable public BuilderTypeReference internNullableType(@Nullable String type) {
if (type == null) {
return null;
}
return internType(type);
}
@Nonnull @Override public BuilderStringReference getString(@Nonnull BuilderTypeReference key) {
return key.stringReference;
}
@Override public int getNullableItemIndex(@Nullable BuilderTypeReference key) {
return key==null?DexWriter.NO_INDEX:key.index;
}
@Override public int getItemIndex(@Nonnull BuilderTypeReference key) {
return key.getIndex();
}
@Nonnull @Override public Collection<? extends Entry<? extends BuilderTypeReference, Integer>> getItems() {
return new BuilderMapEntryCollection<BuilderTypeReference>(internedItems.values()) {
@Override protected int getValue(@Nonnull BuilderTypeReference key) {
return key.index;
}
@Override protected int setValue(@Nonnull BuilderTypeReference key, int value) {
int prev = key.index;
key.index = value;
return prev;
}
};
}
}

View File

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

View File

@ -0,0 +1,307 @@
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.writer.builder;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import org.jf.dexlib2.ValueType;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.iface.MethodParameter;
import org.jf.dexlib2.iface.reference.*;
import org.jf.dexlib2.iface.value.*;
import org.jf.dexlib2.writer.DexWriter;
import org.jf.dexlib2.writer.builder.BuilderDebugItem.*;
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.*;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringReference, BuilderTypeReference,
BuilderTypeReference, BuilderProtoReference, BuilderFieldReference, BuilderMethodReference, BuilderReference,
BuilderClassDef, BuilderAnnotation, BuilderAnnotationSet, BuilderTypeList, BuilderField, BuilderMethod,
BuilderEncodedValue, BuilderAnnotationElement, BuilderDebugItem, BuilderInstruction, BuilderExceptionHandler> {
private final BuilderContext context;
public static DexBuilder makeDexBuilder() {
BuilderContext context = new BuilderContext();
return new DexBuilder(context);
}
private DexBuilder(@Nonnull BuilderContext context) {
super(BuilderInstructionFactory.INSTANCE, context.stringPool, context.typePool, context.protoPool,
context.fieldPool, context.methodPool, context.classPool, context.typeListPool, context.annotationPool,
context.annotationSetPool);
this.context = context;
}
@Nonnull public BuilderField internField(@Nonnull String definingClass,
@Nonnull String name,
@Nonnull String type,
int accessFlags,
@Nullable EncodedValue initialValue,
@Nonnull Set<? extends Annotation> annotations) {
return new BuilderField(context.fieldPool.internField(definingClass, name, type),
accessFlags,
context.internNullableEncodedValue(initialValue),
context.annotationSetPool.internAnnotationSet(annotations));
}
@Nonnull public BuilderMethod internMethod(@Nonnull String definingClass,
@Nonnull String name,
@Nullable List<? extends MethodParameter> parameters,
@Nonnull String returnType,
int accessFlags,
@Nonnull Set<? extends Annotation> annotations,
@Nullable BuilderMethodImplementation methodImplementation) {
if (parameters == null) {
parameters = ImmutableList.of();
}
return new BuilderMethod(context.methodPool.internMethod(definingClass, name, parameters, returnType),
internMethodParameters(parameters),
accessFlags,
context.annotationSetPool.internAnnotationSet(annotations),
methodImplementation);
}
@Nonnull public BuilderMethodImplementation internMethodImplementation(
int registerCount,
@Nullable List<? extends BuilderInstruction> instructions,
@Nullable List<? extends BuilderTryBlock> tryBlocks,
@Nullable List<? extends BuilderDebugItem> debugItems) {
if (instructions == null) {
instructions = ImmutableList.of();
}
if (tryBlocks == null) {
tryBlocks = ImmutableList.of();
}
if (debugItems == null) {
debugItems = ImmutableList.of();
}
return new BuilderMethodImplementation(registerCount, instructions, tryBlocks, debugItems);
}
@Nonnull public BuilderClassDef internClassDef(@Nonnull String type,
int accessFlags,
@Nullable String superclass,
@Nullable List<String> interfaces,
@Nullable String sourceFile,
@Nonnull Set<? extends Annotation> annotations,
@Nullable Iterable<? extends BuilderField> fields,
@Nullable Iterable<? extends BuilderMethod> methods) {
if (interfaces == null) {
interfaces = ImmutableList.of();
} else {
interfaces = Lists.newArrayList(interfaces);
Collections.sort(interfaces);
String prev = null;
Iterator<String> interfaceIterator = interfaces.iterator();
while (interfaceIterator.hasNext()) {
String iface = interfaceIterator.next();
if (prev != null && iface.equals(prev)) {
interfaceIterator.remove();
}
prev = iface;
}
}
return context.classPool.internClass(new BuilderClassDef(context.typePool.internType(type),
accessFlags,
context.typePool.internNullableType(superclass),
context.typeListPool.internTypeList(interfaces),
context.stringPool.internNullableString(sourceFile),
context.annotationSetPool.internAnnotationSet(annotations),
fields,
methods));
}
@Nonnull public BuilderStringReference internStringReference(@Nonnull String string) {
return context.stringPool.internString(string);
}
@Nonnull public BuilderTypeReference internTypeReference(@Nonnull String type) {
return context.typePool.internType(type);
}
@Nonnull public BuilderFieldReference internFieldReference(@Nonnull FieldReference field) {
return context.fieldPool.internField(field);
}
@Nonnull public BuilderMethodReference internMethodReference(@Nonnull MethodReference method) {
return context.methodPool.internMethod(method);
}
@Nonnull public BuilderReference internReference(@Nonnull Reference reference) {
if (reference instanceof StringReference) {
return internStringReference(((StringReference)reference).getString());
}
if (reference instanceof TypeReference) {
return internTypeReference(((TypeReference)reference).getType());
}
if (reference instanceof MethodReference) {
return internMethodReference((MethodReference)reference);
}
if (reference instanceof FieldReference) {
return internFieldReference((FieldReference)reference);
}
throw new IllegalArgumentException("Could not determine type of reference");
}
@Nonnull private List<BuilderMethodParameter> internMethodParameters(
@Nullable List<? extends MethodParameter> methodParameters) {
if (methodParameters == null) {
return ImmutableList.of();
}
return ImmutableList.copyOf(Iterators.transform(methodParameters.iterator(),
new Function<MethodParameter, BuilderMethodParameter>() {
@Nullable @Override public BuilderMethodParameter apply(MethodParameter input) {
return internMethodParameter(input);
}
}));
}
@Nonnull private BuilderMethodParameter internMethodParameter(@Nonnull MethodParameter methodParameter) {
return new BuilderMethodParameter(
context.typePool.internType(methodParameter.getType()),
context.stringPool.internNullableString(methodParameter.getName()),
context.annotationSetPool.internAnnotationSet(methodParameter.getAnnotations()));
}
@Nonnull public BuilderExceptionHandler internExceptionHandler(@Nullable String exceptionType,
int handlerCodeAddress) {
return new BuilderExceptionHandler(context.typePool.internNullableType(exceptionType),
handlerCodeAddress);
}
@Nonnull public BuilderStartLocal internStartLocal(int codeAddress, int register, @Nullable String name,
@Nullable String type, @Nullable String signature) {
return new BuilderStartLocal(codeAddress,
register,
context.stringPool.internNullableString(name),
context.typePool.internNullableType(type),
context.stringPool.internNullableString(signature));
}
@Nonnull public BuilderSetSourceFile internSetSourceFile(int codeAddress, @Nullable String sourceFile) {
return new BuilderSetSourceFile(codeAddress,
context.stringPool.internNullableString(sourceFile));
}
@Nonnull public BuilderEndLocal internEndLocal(int codeAddress, int register) {
return new BuilderEndLocal(codeAddress, register);
}
@Nonnull public BuilderRestartLocal internRestartLocal(int codeAddress, int register) {
return new BuilderRestartLocal(codeAddress, register);
}
@Nonnull public BuilderPrologueEnd internPrologueEnd(int codeAddress) {
return new BuilderPrologueEnd(codeAddress);
}
@Nonnull public BuilderEpilogueBegin internEpilogueBegin(int codeAddress) {
return new BuilderEpilogueBegin(codeAddress);
}
@Nonnull public BuilderLineNumber internLineNumber(int codeAddress, int lineNumber) {
return new BuilderLineNumber(codeAddress, lineNumber);
}
@Override protected void writeEncodedValue(@Nonnull InternalEncodedValueWriter writer,
@Nonnull BuilderEncodedValue encodedValue) throws IOException {
switch (encodedValue.getValueType()) {
case ValueType.ANNOTATION:
BuilderAnnotationEncodedValue annotationEncodedValue = (BuilderAnnotationEncodedValue)encodedValue;
writer.writeAnnotation(annotationEncodedValue.typeReference, annotationEncodedValue.elements);
break;
case ValueType.ARRAY:
BuilderArrayEncodedValue arrayEncodedValue = (BuilderArrayEncodedValue)encodedValue;
writer.writeArray(arrayEncodedValue.elements);
break;
case ValueType.BOOLEAN:
writer.writeBoolean(((BooleanEncodedValue)encodedValue).getValue());
break;
case ValueType.BYTE:
writer.writeByte(((ByteEncodedValue)encodedValue).getValue());
break;
case ValueType.CHAR:
writer.writeChar(((CharEncodedValue)encodedValue).getValue());
break;
case ValueType.DOUBLE:
writer.writeDouble(((DoubleEncodedValue)encodedValue).getValue());
break;
case ValueType.ENUM:
writer.writeEnum(((BuilderEnumEncodedValue)encodedValue).getValue());
break;
case ValueType.FIELD:
writer.writeField(((BuilderFieldEncodedValue)encodedValue).fieldReference);
break;
case ValueType.FLOAT:
writer.writeFloat(((FloatEncodedValue)encodedValue).getValue());
break;
case ValueType.INT:
writer.writeInt(((IntEncodedValue)encodedValue).getValue());
break;
case ValueType.LONG:
writer.writeLong(((LongEncodedValue)encodedValue).getValue());
break;
case ValueType.METHOD:
writer.writeMethod(((BuilderMethodEncodedValue)encodedValue).methodReference);
break;
case ValueType.NULL:
writer.writeNull();
break;
case ValueType.SHORT:
writer.writeShort(((ShortEncodedValue)encodedValue).getValue());
break;
case ValueType.STRING:
writer.writeString(((BuilderStringEncodedValue)encodedValue).stringReference);
break;
case ValueType.TYPE:
writer.writeType(((BuilderTypeEncodedValue)encodedValue).typeReference);
break;
default:
throw new ExceptionWithContext("Unrecognized value type: %d", encodedValue.getValueType());
}
}
}

View File

@ -35,14 +35,11 @@ import org.jf.dexlib2.ValueType;
import org.jf.dexlib2.iface.*; import org.jf.dexlib2.iface.*;
import org.jf.dexlib2.iface.debug.DebugItem; import org.jf.dexlib2.iface.debug.DebugItem;
import org.jf.dexlib2.iface.instruction.Instruction; import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.reference.FieldReference; import org.jf.dexlib2.iface.reference.*;
import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.iface.reference.TypeReference;
import org.jf.dexlib2.iface.value.*; import org.jf.dexlib2.iface.value.*;
import org.jf.dexlib2.immutable.instruction.ImmutableInstructionFactory; import org.jf.dexlib2.immutable.instruction.ImmutableInstructionFactory;
import org.jf.dexlib2.writer.pool.ProtoPool.Key;
import org.jf.dexlib2.writer.DexWriter; import org.jf.dexlib2.writer.DexWriter;
import org.jf.dexlib2.writer.pool.ProtoPool.Key;
import org.jf.util.ExceptionWithContext; import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -51,7 +48,7 @@ import java.util.Collection;
import java.util.Set; import java.util.Set;
public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference, Key, public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference, Key,
FieldReference, MethodReference, PoolClassDef, FieldReference, MethodReference, Reference, PoolClassDef,
Annotation, Set<? extends Annotation>, Annotation, Set<? extends Annotation>,
TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod, TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
EncodedValue, AnnotationElement, DebugItem, Instruction, ExceptionHandler> { EncodedValue, AnnotationElement, DebugItem, Instruction, ExceptionHandler> {

View File

@ -31,13 +31,14 @@
package org.jf.dexlib2.writer.pool; package org.jf.dexlib2.writer.pool;
import org.jf.dexlib2.iface.Field;
import org.jf.dexlib2.iface.reference.FieldReference; import org.jf.dexlib2.iface.reference.FieldReference;
import org.jf.dexlib2.writer.FieldSection; import org.jf.dexlib2.writer.FieldSection;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class FieldPool extends BaseIndexPool<FieldReference> public class FieldPool extends BaseIndexPool<FieldReference>
implements FieldSection<CharSequence, CharSequence, FieldReference> { implements FieldSection<CharSequence, CharSequence, FieldReference, Field> {
@Nonnull private final StringPool stringPool; @Nonnull private final StringPool stringPool;
@Nonnull private final TypePool typePool; @Nonnull private final TypePool typePool;
@ -66,4 +67,8 @@ public class FieldPool extends BaseIndexPool<FieldReference>
@Nonnull @Override public CharSequence getName(@Nonnull FieldReference fieldReference) { @Nonnull @Override public CharSequence getName(@Nonnull FieldReference fieldReference) {
return fieldReference.getName(); return fieldReference.getName();
} }
@Override public int getFieldIndex(@Nonnull Field field) {
return getItemIndex(field);
}
} }

View File

@ -37,7 +37,7 @@ import org.jf.dexlib2.writer.MethodSection;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class MethodPool extends BaseIndexPool<MethodReference> public class MethodPool extends BaseIndexPool<MethodReference>
implements MethodSection<CharSequence, CharSequence, ProtoPool.Key, MethodReference> { implements MethodSection<CharSequence, CharSequence, ProtoPool.Key, MethodReference, PoolMethod> {
@Nonnull private final StringPool stringPool; @Nonnull private final StringPool stringPool;
@Nonnull private final TypePool typePool; @Nonnull private final TypePool typePool;
@Nonnull private final ProtoPool protoPool; @Nonnull private final ProtoPool protoPool;
@ -66,7 +66,15 @@ public class MethodPool extends BaseIndexPool<MethodReference>
return new ProtoPool.Key(methodReference); return new ProtoPool.Key(methodReference);
} }
@Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull PoolMethod poolMethod) {
return new ProtoPool.Key(poolMethod);
}
@Nonnull @Override public CharSequence getName(@Nonnull MethodReference methodReference) { @Nonnull @Override public CharSequence getName(@Nonnull MethodReference methodReference) {
return methodReference.getName(); return methodReference.getName();
} }
@Override public int getMethodIndex(@Nonnull PoolMethod poolMethod) {
return getItemIndex(poolMethod);
}
} }

View File

@ -33,6 +33,7 @@ package org.jf.dexlib2.writer.pool;
import com.google.common.collect.Ordering; import com.google.common.collect.Ordering;
import org.jf.dexlib2.iface.reference.MethodReference; import org.jf.dexlib2.iface.reference.MethodReference;
import org.jf.dexlib2.util.MethodUtil;
import org.jf.dexlib2.writer.pool.ProtoPool.Key; import org.jf.dexlib2.writer.pool.ProtoPool.Key;
import org.jf.dexlib2.writer.ProtoSection; import org.jf.dexlib2.writer.ProtoSection;
import org.jf.util.CharSequenceUtils; import org.jf.util.CharSequenceUtils;
@ -80,22 +81,6 @@ public class ProtoPool extends BaseIndexPool<Key>
return new TypeListPool.Key<List<? extends CharSequence>>(key.getParameters()); return new TypeListPool.Key<List<? extends CharSequence>>(key.getParameters());
} }
private static char getShortyType(CharSequence type) {
if (type.length() > 1) {
return 'L';
}
return type.charAt(0);
}
private static String getShorty(Collection<? extends CharSequence> params, CharSequence returnType) {
StringBuilder sb = new StringBuilder(params.size() + 1);
sb.append(getShortyType(returnType));
for (CharSequence typeRef: params) {
sb.append(getShortyType(typeRef));
}
return sb.toString();
}
public static class Key implements Comparable<Key> { public static class Key implements Comparable<Key> {
@Nonnull private final MethodReference method; @Nonnull private final MethodReference method;
@ -109,7 +94,7 @@ public class ProtoPool extends BaseIndexPool<Key>
} }
public String getShorty() { public String getShorty() {
return ProtoPool.getShorty(method.getParameterTypes(), method.getReturnType()); return MethodUtil.getShorty(method.getParameterTypes(), method.getReturnType());
} }
public String toString() { public String toString() {

View File

@ -52,9 +52,10 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
public class InstructionWriteUtil<Insn extends Instruction, StringRef extends StringReference> { public class InstructionWriteUtil<Insn extends Instruction, StringRef extends StringReference,
BaseReference extends Reference> {
private final StringIndexProvider<StringRef> stringIndexProvider; private final StringIndexProvider<StringRef> stringIndexProvider;
private final InstructionFactory<? extends Insn> instructionFactory; private final InstructionFactory<? extends Insn, BaseReference> instructionFactory;
private final Iterable<? extends Insn> originalInstructions; private final Iterable<? extends Insn> originalInstructions;
private List<Insn> instructions; private List<Insn> instructions;
@ -70,7 +71,7 @@ public class InstructionWriteUtil<Insn extends Instruction, StringRef extends St
public InstructionWriteUtil(@Nonnull Iterable<? extends Insn> instructions, public InstructionWriteUtil(@Nonnull Iterable<? extends Insn> instructions,
@Nonnull StringIndexProvider<StringRef> stringIndexProvider, @Nonnull StringIndexProvider<StringRef> stringIndexProvider,
@Nonnull InstructionFactory<? extends Insn> instructionFactory) { @Nonnull InstructionFactory<? extends Insn, BaseReference> instructionFactory) {
this.stringIndexProvider = stringIndexProvider; this.stringIndexProvider = stringIndexProvider;
this.instructionFactory = instructionFactory; this.instructionFactory = instructionFactory;
this.originalInstructions = instructions; this.originalInstructions = instructions;
@ -271,7 +272,7 @@ public class InstructionWriteUtil<Insn extends Instruction, StringRef extends St
int referenceIndex = stringIndexProvider.getItemIndex((StringRef)instr.getReference()); int referenceIndex = stringIndexProvider.getItemIndex((StringRef)instr.getReference());
if (referenceIndex > 0xFFFF) { if (referenceIndex > 0xFFFF) {
modifiedInstruction = instructionFactory.makeInstruction31c(Opcode.CONST_STRING_JUMBO, modifiedInstruction = instructionFactory.makeInstruction31c(Opcode.CONST_STRING_JUMBO,
instr.getRegisterA(), instr.getReference()); instr.getRegisterA(), (BaseReference)instr.getReference());
} }
} }
break; break;

View File

@ -38,6 +38,7 @@ import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.instruction.Instruction; import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.SwitchElement; import org.jf.dexlib2.iface.instruction.SwitchElement;
import org.jf.dexlib2.iface.instruction.formats.*; import org.jf.dexlib2.iface.instruction.formats.*;
import org.jf.dexlib2.iface.reference.Reference;
import org.jf.dexlib2.iface.reference.StringReference; import org.jf.dexlib2.iface.reference.StringReference;
import org.jf.dexlib2.immutable.ImmutableMethodImplementation; import org.jf.dexlib2.immutable.ImmutableMethodImplementation;
import org.jf.dexlib2.immutable.instruction.*; import org.jf.dexlib2.immutable.instruction.*;
@ -55,7 +56,7 @@ public class JumboStringConversionTest {
private MockStringIndexProvider mockStringIndexProvider; private MockStringIndexProvider mockStringIndexProvider;
ArrayList<String> mJumboStrings; ArrayList<String> mJumboStrings;
private class InsnWriteUtil extends InstructionWriteUtil<Instruction, StringReference> { private class InsnWriteUtil extends InstructionWriteUtil<Instruction, StringReference, Reference> {
public InsnWriteUtil(@Nonnull MethodImplementation implementation) { public InsnWriteUtil(@Nonnull MethodImplementation implementation) {
super(implementation.getInstructions(), mockStringIndexProvider, ImmutableInstructionFactory.INSTANCE); super(implementation.getInstructions(), mockStringIndexProvider, ImmutableInstructionFactory.INSTANCE);
} }

View File

@ -59,10 +59,10 @@ import org.jf.dexlib2.immutable.debug.*;
import org.jf.dexlib2.immutable.instruction.*; import org.jf.dexlib2.immutable.instruction.*;
import org.jf.dexlib2.immutable.reference.*; import org.jf.dexlib2.immutable.reference.*;
import org.jf.dexlib2.immutable.value.*; import org.jf.dexlib2.immutable.value.*;
import org.jf.dexlib2.writer.InstructionFactory;
import org.jf.dexlib2.writer.builder.*;
import org.jf.dexlib2.util.MethodUtil; import org.jf.dexlib2.util.MethodUtil;
import org.jf.util.LinearSearch; import org.jf.util.LinearSearch;
} }
@members { @members {
@ -70,6 +70,13 @@ import org.jf.util.LinearSearch;
private boolean verboseErrors = false; private boolean verboseErrors = false;
private int apiLevel = 15; private int apiLevel = 15;
private Opcodes opcodes = new Opcodes(apiLevel); private Opcodes opcodes = new Opcodes(apiLevel);
private DexBuilder dexBuilder;
private InstructionFactory<BuilderInstruction, BuilderReference> instructionFactory =
BuilderInstructionFactory.INSTANCE;
public void setDexBuilder(DexBuilder dexBuilder) {
this.dexBuilder = dexBuilder;
}
public void setApiLevel(int apiLevel) { public void setApiLevel(int apiLevel) {
this.opcodes = new Opcodes(apiLevel); this.opcodes = new Opcodes(apiLevel);
@ -146,7 +153,7 @@ import org.jf.util.LinearSearch;
smali_file returns[ClassDef classDef] smali_file returns[ClassDef classDef]
: ^(I_CLASS_DEF header methods fields annotations) : ^(I_CLASS_DEF header methods fields annotations)
{ {
$classDef = new ImmutableClassDef($header.classType, $header.accessFlags, $header.superType, $classDef = dexBuilder.internClassDef($header.classType, $header.accessFlags, $header.superType,
$header.implementsList, $header.sourceSpec, $annotations.annotations, $fields.fields, $methods.methods); $header.implementsList, $header.sourceSpec, $annotations.annotations, $fields.fields, $methods.methods);
}; };
catch [Exception ex] { catch [Exception ex] {
@ -220,7 +227,7 @@ access_list returns [int value]
)*); )*);
fields returns[List<Field> fields] fields returns[List<BuilderField> fields]
@init {$fields = Lists.newArrayList();} @init {$fields = Lists.newArrayList();}
: ^(I_FIELDS : ^(I_FIELDS
(field (field
@ -228,7 +235,7 @@ fields returns[List<Field> fields]
$fields.add($field.field); $fields.add($field.field);
})*); })*);
methods returns[List<Method> methods] methods returns[List<BuilderMethod> methods]
@init {$methods = Lists.newArrayList();} @init {$methods = Lists.newArrayList();}
: ^(I_METHODS : ^(I_METHODS
(method (method
@ -236,7 +243,7 @@ methods returns[List<Method> methods]
$methods.add($method.ret); $methods.add($method.ret);
})*); })*);
field returns [Field field] field returns [BuilderField field]
:^(I_FIELD SIMPLE_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?) :^(I_FIELD SIMPLE_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?)
{ {
int accessFlags = $access_list.value; int accessFlags = $access_list.value;
@ -246,7 +253,7 @@ field returns [Field field]
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.");
} }
$field = new ImmutableField(classType, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type, $access_list.value, $field = dexBuilder.internField(classType, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type, $access_list.value,
$field_initial_value.encodedValue, $annotations.annotations); $field_initial_value.encodedValue, $annotations.annotations);
}; };
@ -337,7 +344,7 @@ sparse_switch_elements[int baseAddress] returns[List<SwitchElement> elements]
})* })*
); );
method returns[Method ret] method returns[BuilderMethod ret]
scope scope
{ {
HashMap<String, Integer> labels; HashMap<String, Integer> labels;
@ -388,10 +395,10 @@ method returns[Method ret]
annotations annotations
) )
{ {
List<TryBlock<? extends ExceptionHandler>> tryBlocks = $catches.tryBlocks; List<BuilderTryBlock> tryBlocks = $catches.tryBlocks;
List<DebugItem> debugItems = $ordered_debug_directives.debugItems; List<BuilderDebugItem> debugItems = $ordered_debug_directives.debugItems;
MethodImplementation methodImplementation = null; BuilderMethodImplementation methodImplementation = null;
boolean isAbstract = false; boolean isAbstract = false;
boolean isNative = false; boolean isNative = false;
@ -451,14 +458,14 @@ method returns[Method ret]
" registers, for the method parameters"); " registers, for the method parameters");
} }
methodImplementation = new ImmutableMethodImplementation( methodImplementation = dexBuilder.internMethodImplementation(
$method::totalMethodRegisters, $method::totalMethodRegisters,
$statements.instructions, $statements.instructions,
tryBlocks, tryBlocks,
debugItems); debugItems);
} }
$ret = new ImmutableMethod( $ret = dexBuilder.internMethod(
classType, classType,
$method_name_and_prototype.name, $method_name_and_prototype.name,
$method_name_and_prototype.parameters, $method_name_and_prototype.parameters,
@ -568,12 +575,12 @@ sparse_switch_declaration
} }
}; };
catches returns[List<TryBlock<? extends ExceptionHandler>> tryBlocks] catches returns[List<BuilderTryBlock> tryBlocks]
@init {tryBlocks = Lists.newArrayList();} @init {tryBlocks = Lists.newArrayList();}
: ^(I_CATCHES (catch_directive { tryBlocks.add($catch_directive.tryBlock); })* : ^(I_CATCHES (catch_directive { tryBlocks.add($catch_directive.tryBlock); })*
(catchall_directive { tryBlocks.add($catchall_directive.tryBlock); })*); (catchall_directive { tryBlocks.add($catchall_directive.tryBlock); })*);
catch_directive returns[TryBlock<? extends ExceptionHandler> tryBlock] catch_directive returns[BuilderTryBlock tryBlock]
: ^(I_CATCH address nonvoid_type_descriptor from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] : ^(I_CATCH address nonvoid_type_descriptor from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address]
using=offset_or_label_absolute[$address.address]) using=offset_or_label_absolute[$address.address])
{ {
@ -584,11 +591,11 @@ catch_directive returns[TryBlock<? extends ExceptionHandler> tryBlock]
// We always create try blocks with a single exception handler. These will be merged appropriately when written // We always create try blocks with a single exception handler. These will be merged appropriately when written
// to a dex file // to a dex file
$tryBlock = new ImmutableTryBlock(startAddress, endAddress-startAddress, $tryBlock = new BuilderTryBlock(startAddress, endAddress-startAddress,
ImmutableList.of(new ImmutableExceptionHandler(type, handlerAddress))); ImmutableList.of(dexBuilder.internExceptionHandler(type, handlerAddress)));
}; };
catchall_directive returns[TryBlock<? extends ExceptionHandler> tryBlock] catchall_directive returns[BuilderTryBlock tryBlock]
: ^(I_CATCHALL address from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] : ^(I_CATCHALL address from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address]
using=offset_or_label_absolute[$address.address]) using=offset_or_label_absolute[$address.address])
{ {
@ -598,8 +605,8 @@ catchall_directive returns[TryBlock<? extends ExceptionHandler> tryBlock]
// We always create try blocks with a single exception handler. These will be merged appropriately when written // We always create try blocks with a single exception handler. These will be merged appropriately when written
// to a dex file // to a dex file
$tryBlock = new ImmutableTryBlock(startAddress, endAddress-startAddress, $tryBlock = new BuilderTryBlock(startAddress, endAddress-startAddress,
ImmutableList.of(new ImmutableExceptionHandler(null, handlerAddress))); ImmutableList.of(dexBuilder.internExceptionHandler(null, handlerAddress)));
}; };
address returns[int address] address returns[int address]
@ -645,7 +652,7 @@ parameter[List<SmaliMethodParameter> parameters]
} }
}; };
ordered_debug_directives returns[List<DebugItem> debugItems] ordered_debug_directives returns[List<BuilderDebugItem> debugItems]
@init {debugItems = Lists.newArrayList();} @init {debugItems = Lists.newArrayList();}
: ^(I_ORDERED_DEBUG_DIRECTIVES : ^(I_ORDERED_DEBUG_DIRECTIVES
( line { $debugItems.add($line.debugItem); } ( line { $debugItems.add($line.debugItem); }
@ -658,56 +665,56 @@ ordered_debug_directives returns[List<DebugItem> debugItems]
)* )*
); );
line returns[DebugItem debugItem] line returns[BuilderDebugItem debugItem]
: ^(I_LINE integral_literal address) : ^(I_LINE integral_literal address)
{ {
$debugItem = new ImmutableLineNumber($address.address, $integral_literal.value); $debugItem = dexBuilder.internLineNumber($address.address, $integral_literal.value);
}; };
local returns[DebugItem debugItem] local returns[BuilderDebugItem debugItem]
: ^(I_LOCAL REGISTER ((NULL_LITERAL | name=string_literal) nonvoid_type_descriptor? signature=string_literal?)? address) : ^(I_LOCAL REGISTER ((NULL_LITERAL | name=string_literal) nonvoid_type_descriptor? signature=string_literal?)? address)
{ {
int registerNumber = parseRegister_short($REGISTER.text); int registerNumber = parseRegister_short($REGISTER.text);
$debugItem = new ImmutableStartLocal($address.address, registerNumber, $name.value, $debugItem = dexBuilder.internStartLocal($address.address, registerNumber, $name.value,
$nonvoid_type_descriptor.type, $signature.value); $nonvoid_type_descriptor.type, $signature.value);
}; };
end_local returns[DebugItem debugItem] end_local returns[BuilderDebugItem debugItem]
: ^(I_END_LOCAL REGISTER address) : ^(I_END_LOCAL REGISTER address)
{ {
int registerNumber = parseRegister_short($REGISTER.text); int registerNumber = parseRegister_short($REGISTER.text);
$debugItem = new ImmutableEndLocal($address.address, registerNumber); $debugItem = dexBuilder.internEndLocal($address.address, registerNumber);
}; };
restart_local returns[DebugItem debugItem] restart_local returns[BuilderDebugItem debugItem]
: ^(I_RESTART_LOCAL REGISTER address) : ^(I_RESTART_LOCAL REGISTER address)
{ {
int registerNumber = parseRegister_short($REGISTER.text); int registerNumber = parseRegister_short($REGISTER.text);
$debugItem = new ImmutableRestartLocal($address.address, registerNumber); $debugItem = dexBuilder.internRestartLocal($address.address, registerNumber);
}; };
prologue returns[DebugItem debugItem] prologue returns[BuilderDebugItem debugItem]
: ^(I_PROLOGUE address) : ^(I_PROLOGUE address)
{ {
$debugItem = new ImmutablePrologueEnd($address.address); $debugItem = dexBuilder.internPrologueEnd($address.address);
}; };
epilogue returns[DebugItem debugItem] epilogue returns[BuilderDebugItem debugItem]
: ^(I_EPILOGUE address) : ^(I_EPILOGUE address)
{ {
$debugItem = new ImmutableEpilogueBegin($address.address); $debugItem = dexBuilder.internEpilogueBegin($address.address);
}; };
source returns[DebugItem debugItem] source returns[BuilderDebugItem debugItem]
: ^(I_SOURCE string_literal? address) : ^(I_SOURCE string_literal? address)
{ {
$debugItem = new ImmutableSetSourceFile($address.address, $string_literal.value); $debugItem = dexBuilder.internSetSourceFile($address.address, $string_literal.value);
}; };
statements returns[List<Instruction> instructions, int maxOutRegisters] statements returns[List<BuilderInstruction> instructions, int maxOutRegisters]
@init @init
{ {
$instructions = Lists.newArrayList(); $instructions = Lists.newArrayList();
@ -809,7 +816,7 @@ verification_error_type returns[int verificationError]
$verificationError = VerificationError.getVerificationError($VERIFICATION_ERROR_TYPE.text); $verificationError = VerificationError.getVerificationError($VERIFICATION_ERROR_TYPE.text);
}; };
instruction[List<Instruction> instructions] returns[int outRegisters] instruction[List<BuilderInstruction> instructions] returns[int outRegisters]
: insn_format10t[$instructions] { $outRegisters = $insn_format10t.outRegisters; } : insn_format10t[$instructions] { $outRegisters = $insn_format10t.outRegisters; }
| insn_format10x[$instructions] { $outRegisters = $insn_format10x.outRegisters; } | insn_format10x[$instructions] { $outRegisters = $insn_format10x.outRegisters; }
| insn_format11n[$instructions] { $outRegisters = $insn_format11n.outRegisters; } | insn_format11n[$instructions] { $outRegisters = $insn_format11n.outRegisters; }
@ -850,7 +857,7 @@ instruction[List<Instruction> instructions] returns[int outRegisters]
} }
insn_format10t[List<Instruction> instructions] returns[int outRegisters] insn_format10t[List<BuilderInstruction> instructions] returns[int outRegisters]
: //e.g. goto endloop: : //e.g. goto endloop:
{$outRegisters = 0;} {$outRegisters = 0;}
^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label) ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label)
@ -859,18 +866,18 @@ insn_format10t[List<Instruction> instructions] returns[int outRegisters]
int addressOffset = $offset_or_label.offsetValue; int addressOffset = $offset_or_label.offsetValue;
$instructions.add(new ImmutableInstruction10t(opcode, addressOffset)); $instructions.add(instructionFactory.makeInstruction10t(opcode, addressOffset));
}; };
insn_format10x[List<Instruction> instructions] returns[int outRegisters] insn_format10x[List<BuilderInstruction> instructions] returns[int outRegisters]
: //e.g. return : //e.g. return
^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x) ^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
{ {
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10x.text); Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10x.text);
$instructions.add(new ImmutableInstruction10x(opcode)); $instructions.add(instructionFactory.makeInstruction10x(opcode));
}; };
insn_format11n[List<Instruction> instructions] returns[int outRegisters] insn_format11n[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -880,20 +887,20 @@ insn_format11n[List<Instruction> instructions] returns[int outRegisters]
short litB = $short_integral_literal.value; short litB = $short_integral_literal.value;
LiteralTools.checkNibble(litB); LiteralTools.checkNibble(litB);
$instructions.add(new ImmutableInstruction11n(opcode, regA, litB)); $instructions.add(instructionFactory.makeInstruction11n(opcode, regA, litB));
}; };
insn_format11x[List<Instruction> instructions] returns[int outRegisters] insn_format11x[List<BuilderInstruction> instructions] returns[int outRegisters]
: //e.g. move-result-object v1 : //e.g. move-result-object v1
^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER) ^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER)
{ {
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11x.text); Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11x.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text);
$instructions.add(new ImmutableInstruction11x(opcode, regA)); $instructions.add(instructionFactory.makeInstruction11x(opcode, regA));
}; };
insn_format12x[List<Instruction> instructions] returns[int outRegisters] insn_format12x[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -901,10 +908,10 @@ insn_format12x[List<Instruction> instructions] returns[int outRegisters]
byte regA = parseRegister_nibble($registerA.text); byte regA = parseRegister_nibble($registerA.text);
byte regB = parseRegister_nibble($registerB.text); byte regB = parseRegister_nibble($registerB.text);
$instructions.add(new ImmutableInstruction12x(opcode, regA, regB)); $instructions.add(instructionFactory.makeInstruction12x(opcode, regA, regB));
}; };
insn_format20bc[List<Instruction> instructions] returns[int outRegisters] insn_format20bc[List<BuilderInstruction> instructions] returns[int outRegisters]
: //e.g. throw-verification-error generic-error, Lsome/class; : //e.g. throw-verification-error generic-error, Lsome/class;
^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference) ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference)
{ {
@ -913,10 +920,11 @@ insn_format20bc[List<Instruction> instructions] returns[int outRegisters]
int verificationError = $verification_error_type.verificationError; int verificationError = $verification_error_type.verificationError;
ImmutableReference referencedItem = $verification_error_reference.reference; ImmutableReference referencedItem = $verification_error_reference.reference;
$instructions.add(new ImmutableInstruction20bc(opcode, verificationError, referencedItem)); $instructions.add(instructionFactory.makeInstruction20bc(opcode, verificationError,
dexBuilder.internReference(referencedItem)));
}; };
insn_format20t[List<Instruction> instructions] returns[int outRegisters] insn_format20t[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -924,10 +932,10 @@ insn_format20t[List<Instruction> instructions] returns[int outRegisters]
int addressOffset = $offset_or_label.offsetValue; int addressOffset = $offset_or_label.offsetValue;
$instructions.add(new ImmutableInstruction20t(opcode, addressOffset)); $instructions.add(instructionFactory.makeInstruction20t(opcode, addressOffset));
}; };
insn_format21c_field[List<Instruction> instructions] returns[int outRegisters] insn_format21c_field[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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 inst=(INSTRUCTION_FORMAT21c_FIELD | INSTRUCTION_FORMAT21c_FIELD_ODEX) REGISTER fully_qualified_field) ^(I_STATEMENT_FORMAT21c_FIELD inst=(INSTRUCTION_FORMAT21c_FIELD | INSTRUCTION_FORMAT21c_FIELD_ODEX) REGISTER fully_qualified_field)
{ {
@ -936,34 +944,33 @@ insn_format21c_field[List<Instruction> instructions] returns[int outRegisters]
ImmutableFieldReference fieldReference = $fully_qualified_field.fieldReference; ImmutableFieldReference fieldReference = $fully_qualified_field.fieldReference;
$instructions.add(new ImmutableInstruction21c(opcode, regA, fieldReference)); $instructions.add(instructionFactory.makeInstruction21c(opcode, regA,
dexBuilder.internFieldReference(fieldReference)));
}; };
insn_format21c_string[List<Instruction> instructions] returns[int outRegisters] insn_format21c_string[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text); Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text);
ImmutableStringReference stringReference = new ImmutableStringReference($string_literal.value); instructions.add(instructionFactory.makeInstruction21c(opcode, regA,
dexBuilder.internStringReference($string_literal.value)));
instructions.add(new ImmutableInstruction21c(opcode, regA, stringReference));
}; };
insn_format21c_type[List<Instruction> instructions] returns[int outRegisters] insn_format21c_type[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text); Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text);
ImmutableTypeReference typeReference = new ImmutableTypeReference($reference_type_descriptor.type); $instructions.add(instructionFactory.makeInstruction21c(opcode, regA,
dexBuilder.internTypeReference($reference_type_descriptor.type)));
$instructions.add(new ImmutableInstruction21c(opcode, regA, typeReference));
}; };
insn_format21ih[List<Instruction> instructions] returns[int outRegisters] insn_format21ih[List<BuilderInstruction> instructions] returns[int outRegisters]
: //e.g. const/high16 v1, 1234 : //e.g. const/high16 v1, 1234
^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal) ^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal)
{ {
@ -972,10 +979,10 @@ insn_format21ih[List<Instruction> instructions] returns[int outRegisters]
int litB = $fixed_32bit_literal.value; int litB = $fixed_32bit_literal.value;
instructions.add(new ImmutableInstruction21ih(opcode, regA, litB)); instructions.add(instructionFactory.makeInstruction21ih(opcode, regA, litB));
}; };
insn_format21lh[List<Instruction> instructions] returns[int outRegisters] insn_format21lh[List<BuilderInstruction> instructions] returns[int outRegisters]
: //e.g. const-wide/high16 v1, 1234 : //e.g. const-wide/high16 v1, 1234
^(I_STATEMENT_FORMAT21lh INSTRUCTION_FORMAT21lh REGISTER fixed_64bit_literal) ^(I_STATEMENT_FORMAT21lh INSTRUCTION_FORMAT21lh REGISTER fixed_64bit_literal)
{ {
@ -984,10 +991,10 @@ insn_format21lh[List<Instruction> instructions] returns[int outRegisters]
long litB = $fixed_64bit_literal.value; long litB = $fixed_64bit_literal.value;
instructions.add(new ImmutableInstruction21lh(opcode, regA, litB)); instructions.add(instructionFactory.makeInstruction21lh(opcode, regA, litB));
}; };
insn_format21s[List<Instruction> instructions] returns[int outRegisters] insn_format21s[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -996,10 +1003,10 @@ insn_format21s[List<Instruction> instructions] returns[int outRegisters]
short litB = $short_integral_literal.value; short litB = $short_integral_literal.value;
$instructions.add(new ImmutableInstruction21s(opcode, regA, litB)); $instructions.add(instructionFactory.makeInstruction21s(opcode, regA, litB));
}; };
insn_format21t[List<Instruction> instructions] returns[int outRegisters] insn_format21t[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1012,10 +1019,10 @@ insn_format21t[List<Instruction> instructions] returns[int outRegisters]
throw new SemanticException(input, $offset_or_label.start, "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, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
} }
$instructions.add(new ImmutableInstruction21t(opcode, regA, addressOffset)); $instructions.add(instructionFactory.makeInstruction21t(opcode, regA, addressOffset));
}; };
insn_format22b[List<Instruction> instructions] returns[int outRegisters] insn_format22b[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1026,10 +1033,10 @@ insn_format22b[List<Instruction> instructions] returns[int outRegisters]
short litC = $short_integral_literal.value; short litC = $short_integral_literal.value;
LiteralTools.checkByte(litC); LiteralTools.checkByte(litC);
$instructions.add(new ImmutableInstruction22b(opcode, regA, regB, litC)); $instructions.add(instructionFactory.makeInstruction22b(opcode, regA, regB, litC));
}; };
insn_format22c_field[List<Instruction> instructions] returns[int outRegisters] insn_format22c_field[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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 inst=(INSTRUCTION_FORMAT22c_FIELD | INSTRUCTION_FORMAT22c_FIELD_ODEX) registerA=REGISTER registerB=REGISTER fully_qualified_field) ^(I_STATEMENT_FORMAT22c_FIELD inst=(INSTRUCTION_FORMAT22c_FIELD | INSTRUCTION_FORMAT22c_FIELD_ODEX) registerA=REGISTER registerB=REGISTER fully_qualified_field)
{ {
@ -1039,10 +1046,11 @@ insn_format22c_field[List<Instruction> instructions] returns[int outRegisters]
ImmutableFieldReference fieldReference = $fully_qualified_field.fieldReference; ImmutableFieldReference fieldReference = $fully_qualified_field.fieldReference;
$instructions.add(new ImmutableInstruction22c(opcode, regA, regB, fieldReference)); $instructions.add(instructionFactory.makeInstruction22c(opcode, regA, regB,
dexBuilder.internFieldReference(fieldReference)));
}; };
insn_format22c_type[List<Instruction> instructions] returns[int outRegisters] insn_format22c_type[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1050,12 +1058,11 @@ insn_format22c_type[List<Instruction> instructions] returns[int outRegisters]
byte regA = parseRegister_nibble($registerA.text); byte regA = parseRegister_nibble($registerA.text);
byte regB = parseRegister_nibble($registerB.text); byte regB = parseRegister_nibble($registerB.text);
ImmutableTypeReference typeReference = new ImmutableTypeReference($nonvoid_type_descriptor.type); $instructions.add(instructionFactory.makeInstruction22c(opcode, regA, regB,
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
$instructions.add(new ImmutableInstruction22c(opcode, regA, regB, typeReference));
}; };
insn_format22s[List<Instruction> instructions] returns[int outRegisters] insn_format22s[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1065,10 +1072,10 @@ insn_format22s[List<Instruction> instructions] returns[int outRegisters]
short litC = $short_integral_literal.value; short litC = $short_integral_literal.value;
$instructions.add(new ImmutableInstruction22s(opcode, regA, regB, litC)); $instructions.add(instructionFactory.makeInstruction22s(opcode, regA, regB, litC));
}; };
insn_format22t[List<Instruction> instructions] returns[int outRegisters] insn_format22t[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1082,10 +1089,10 @@ insn_format22t[List<Instruction> instructions] returns[int outRegisters]
throw new SemanticException(input, $offset_or_label.start, "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, $offset_or_label.start, "The offset/label is out of range. The offset is " + Integer.toString(addressOffset) + " and the range for this opcode is [-32768, 32767].");
} }
$instructions.add(new ImmutableInstruction22t(opcode, regA, regB, addressOffset)); $instructions.add(instructionFactory.makeInstruction22t(opcode, regA, regB, addressOffset));
}; };
insn_format22x[List<Instruction> instructions] returns[int outRegisters] insn_format22x[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1093,10 +1100,10 @@ insn_format22x[List<Instruction> instructions] returns[int outRegisters]
short regA = parseRegister_byte($registerA.text); short regA = parseRegister_byte($registerA.text);
int regB = parseRegister_short($registerB.text); int regB = parseRegister_short($registerB.text);
$instructions.add(new ImmutableInstruction22x(opcode, regA, regB)); $instructions.add(instructionFactory.makeInstruction22x(opcode, regA, regB));
}; };
insn_format23x[List<Instruction> instructions] returns[int outRegisters] insn_format23x[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1105,10 +1112,10 @@ insn_format23x[List<Instruction> instructions] returns[int outRegisters]
short regB = parseRegister_byte($registerB.text); short regB = parseRegister_byte($registerB.text);
short regC = parseRegister_byte($registerC.text); short regC = parseRegister_byte($registerC.text);
$instructions.add(new ImmutableInstruction23x(opcode, regA, regB, regC)); $instructions.add(instructionFactory.makeInstruction23x(opcode, regA, regB, regC));
}; };
insn_format30t[List<Instruction> instructions] returns[int outRegisters] insn_format30t[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1116,22 +1123,21 @@ insn_format30t[List<Instruction> instructions] returns[int outRegisters]
int addressOffset = $offset_or_label.offsetValue; int addressOffset = $offset_or_label.offsetValue;
$instructions.add(new ImmutableInstruction30t(opcode, addressOffset)); $instructions.add(instructionFactory.makeInstruction30t(opcode, addressOffset));
}; };
insn_format31c[List<Instruction> instructions] returns[int outRegisters] insn_format31c[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31c.text); Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31c.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text);
ImmutableStringReference stringReference = new ImmutableStringReference($string_literal.value); $instructions.add(instructionFactory.makeInstruction31c(opcode, regA,
dexBuilder.internStringReference($string_literal.value)));
$instructions.add(new ImmutableInstruction31c(opcode, regA, stringReference));
}; };
insn_format31i[List<Instruction> instructions] returns[int outRegisters] insn_format31i[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1140,10 +1146,10 @@ insn_format31i[List<Instruction> instructions] returns[int outRegisters]
int litB = $fixed_32bit_literal.value; int litB = $fixed_32bit_literal.value;
$instructions.add(new ImmutableInstruction31i(opcode, regA, litB)); $instructions.add(instructionFactory.makeInstruction31i(opcode, regA, litB));
}; };
insn_format31t[List<Instruction> instructions] returns[int outRegisters] insn_format31t[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1156,10 +1162,10 @@ insn_format31t[List<Instruction> instructions] returns[int outRegisters]
addressOffset++; addressOffset++;
} }
$instructions.add(new ImmutableInstruction31t(opcode, regA, addressOffset)); $instructions.add(instructionFactory.makeInstruction31t(opcode, regA, addressOffset));
}; };
insn_format32x[List<Instruction> instructions] returns[int outRegisters] insn_format32x[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1167,10 +1173,10 @@ insn_format32x[List<Instruction> instructions] returns[int outRegisters]
int regA = parseRegister_short($registerA.text); int regA = parseRegister_short($registerA.text);
int regB = parseRegister_short($registerB.text); int regB = parseRegister_short($registerB.text);
$instructions.add(new ImmutableInstruction32x(opcode, regA, regB)); $instructions.add(instructionFactory.makeInstruction32x(opcode, regA, regB));
}; };
insn_format35c_method[List<Instruction> instructions] returns[int outRegisters] insn_format35c_method[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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 fully_qualified_method) ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list fully_qualified_method)
{ {
@ -1183,10 +1189,11 @@ insn_format35c_method[List<Instruction> instructions] returns[int outRegisters]
ImmutableMethodReference methodReference = $fully_qualified_method.methodReference; ImmutableMethodReference methodReference = $fully_qualified_method.methodReference;
$instructions.add(new ImmutableInstruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodReference)); $instructions.add(instructionFactory.makeInstruction35c(opcode, registerCount, registers[0], registers[1],
registers[2], registers[3], registers[4], dexBuilder.internMethodReference(methodReference)));
}; };
insn_format35c_type[List<Instruction> instructions] returns[int outRegisters] insn_format35c_type[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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 nonvoid_type_descriptor) ^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor)
{ {
@ -1197,12 +1204,11 @@ insn_format35c_type[List<Instruction> instructions] returns[int outRegisters]
byte registerCount = $register_list.registerCount; byte registerCount = $register_list.registerCount;
$outRegisters = registerCount; $outRegisters = registerCount;
ImmutableTypeReference typeReference = new ImmutableTypeReference($nonvoid_type_descriptor.type); $instructions.add(instructionFactory.makeInstruction35c(opcode, registerCount, registers[0], registers[1],
registers[2], registers[3], registers[4], dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
$instructions.add(new ImmutableInstruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeReference));
}; };
insn_format3rc_method[List<Instruction> instructions] returns[int outRegisters] insn_format3rc_method[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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 fully_qualified_method) ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range fully_qualified_method)
{ {
@ -1215,10 +1221,11 @@ insn_format3rc_method[List<Instruction> instructions] returns[int outRegisters]
ImmutableMethodReference methodReference = $fully_qualified_method.methodReference; ImmutableMethodReference methodReference = $fully_qualified_method.methodReference;
$instructions.add(new ImmutableInstruction3rc(opcode, startRegister, registerCount, methodReference)); $instructions.add(instructionFactory.makeInstruction3rc(opcode, startRegister, registerCount,
dexBuilder.internMethodReference(methodReference)));
}; };
insn_format3rc_type[List<Instruction> instructions] returns[int outRegisters] insn_format3rc_type[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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 nonvoid_type_descriptor) ^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor)
{ {
@ -1229,12 +1236,11 @@ insn_format3rc_type[List<Instruction> instructions] returns[int outRegisters]
int registerCount = endRegister-startRegister+1; int registerCount = endRegister-startRegister+1;
$outRegisters = registerCount; $outRegisters = registerCount;
ImmutableTypeReference typeReference = new ImmutableTypeReference($nonvoid_type_descriptor.type); $instructions.add(instructionFactory.makeInstruction3rc(opcode, startRegister, registerCount,
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
$instructions.add(new ImmutableInstruction3rc(opcode, startRegister, registerCount, typeReference));
}; };
insn_format51l_type[List<Instruction> instructions] returns[int outRegisters] insn_format51l_type[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
@ -1243,20 +1249,20 @@ insn_format51l_type[List<Instruction> instructions] returns[int outRegisters]
long litB = $fixed_64bit_literal.value; long litB = $fixed_64bit_literal.value;
$instructions.add(new ImmutableInstruction51l(opcode, regA, litB)); $instructions.add(instructionFactory.makeInstruction51l(opcode, regA, litB));
}; };
insn_array_data_directive[List<Instruction> instructions] returns[int outRegisters] insn_array_data_directive[List<BuilderInstruction> instructions] returns[int outRegisters]
: //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)
{ {
int elementWidth = $short_integral_literal.value; int elementWidth = $short_integral_literal.value;
List<Number> elements = $array_elements.elements; List<Number> elements = $array_elements.elements;
$instructions.add(new ImmutableArrayPayload(elementWidth, $array_elements.elements)); $instructions.add(instructionFactory.makeArrayPayload(elementWidth, $array_elements.elements));
}; };
insn_packed_switch_directive[List<Instruction> instructions] returns[int outRegisters] insn_packed_switch_directive[List<BuilderInstruction> instructions] returns[int outRegisters]
: :
^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal) ^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal)
{ {
@ -1268,10 +1274,10 @@ insn_packed_switch_directive[List<Instruction> instructions] returns[int outRegi
} }
packed_switch_elements[baseAddress, startKey]) packed_switch_elements[baseAddress, startKey])
{ {
$instructions.add(new ImmutablePackedSwitchPayload($packed_switch_elements.elements)); $instructions.add(instructionFactory.makePackedSwitchPayload($packed_switch_elements.elements));
}; };
insn_sparse_switch_directive[List<Instruction> instructions] returns[int outRegisters] insn_sparse_switch_directive[List<BuilderInstruction> instructions] returns[int outRegisters]
: :
{ {
Integer baseAddress = $method::sparseSwitchDeclarations.get($method::currentAddress); Integer baseAddress = $method::sparseSwitchDeclarations.get($method::currentAddress);
@ -1281,7 +1287,7 @@ insn_sparse_switch_directive[List<Instruction> instructions] returns[int outRegi
} }
^(I_STATEMENT_SPARSE_SWITCH sparse_switch_elements[baseAddress]) ^(I_STATEMENT_SPARSE_SWITCH sparse_switch_elements[baseAddress])
{ {
$instructions.add(new ImmutableSparseSwitchPayload($sparse_switch_elements.elements)); $instructions.add(instructionFactory.makeSparseSwitchPayload($sparse_switch_elements.elements));
}; };
nonvoid_type_descriptor returns [String type] nonvoid_type_descriptor returns [String type]

View File

@ -28,21 +28,21 @@
package org.jf.smali; package org.jf.smali;
import com.google.common.collect.Lists;
import org.antlr.runtime.CommonTokenStream; import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.Token; import org.antlr.runtime.Token;
import org.antlr.runtime.TokenSource; import org.antlr.runtime.TokenSource;
import org.antlr.runtime.tree.CommonTree; import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream; import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.apache.commons.cli.*; import org.apache.commons.cli.*;
import org.jf.dexlib2.DexFileFactory; import org.jf.dexlib2.writer.builder.DexBuilder;
import org.jf.dexlib2.iface.ClassDef;
import org.jf.dexlib2.immutable.ImmutableDexFile;
import org.jf.util.ConsoleUtil; import org.jf.util.ConsoleUtil;
import org.jf.util.SmaliHelpFormatter; import org.jf.util.SmaliHelpFormatter;
import java.io.*; import java.io.*;
import java.util.*; import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Properties;
import java.util.Set;
/** /**
* Main class for smali. It recognizes enough options to be able to dispatch * Main class for smali. It recognizes enough options to be able to dispatch
@ -184,8 +184,6 @@ public class main {
} }
} }
List<ClassDef> classes = Lists.newArrayList();
// TODO: uncomment // TODO: uncomment
/*if (apiSet && apiLevel >= 14) { /*if (apiSet && apiLevel >= 14) {
dexFile.HeaderItem.setVersion(36); dexFile.HeaderItem.setVersion(36);
@ -193,8 +191,10 @@ public class main {
boolean errors = false; boolean errors = false;
DexBuilder dexBuilder = DexBuilder.makeDexBuilder();
for (File file: filesToProcess) { for (File file: filesToProcess) {
if (!assembleSmaliFile(file, classes, verboseErrors, printTokens, allowOdex, apiLevel)) { if (!assembleSmaliFile(file, dexBuilder, verboseErrors, printTokens, allowOdex, apiLevel)) {
errors = true; errors = true;
} }
} }
@ -203,7 +203,6 @@ public class main {
System.exit(1); System.exit(1);
} }
// TODO: uncomment // TODO: uncomment
/*if (sort) { /*if (sort) {
dexFile.setSortAllItems(true); dexFile.setSortAllItems(true);
@ -214,8 +213,7 @@ public class main {
fixInstructions(dexFile, fixJumbo, fixGoto); fixInstructions(dexFile, fixJumbo, fixGoto);
}*/ }*/
dexBuilder.writeTo(outputDexFile);
DexFileFactory.writeDexFile(outputDexFile, new ImmutableDexFile(classes));
} catch (RuntimeException ex) { } catch (RuntimeException ex) {
System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:"); System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:");
ex.printStackTrace(); ex.printStackTrace();
@ -229,13 +227,13 @@ public class main {
private static void getSmaliFilesInDir(File dir, Set<File> smaliFiles) { private static void getSmaliFilesInDir(File dir, Set<File> smaliFiles) {
for(File file: dir.listFiles()) { for(File file: dir.listFiles()) {
if (file.isDirectory()) { if (file.isDirectory()) {
getSmaliFilesInDir(file, smaliFiles); getSmaliFilesInDir(file, smaliFiles);
} else if (file.getName().endsWith(".smali")) { } else if (file.getName().endsWith(".smali")) {
smaliFiles.add(file); smaliFiles.add(file);
}
} }
} }
}
// TODO: uncomment // TODO: uncomment
/*private static void fixInstructions(DexFile dexFile, boolean fixJumbo, boolean fixGoto) { /*private static void fixInstructions(DexFile dexFile, boolean fixJumbo, boolean fixGoto) {
@ -243,15 +241,14 @@ public class main {
for (CodeItem codeItem: dexFile.CodeItemsSection.getItems()) { for (CodeItem codeItem: dexFile.CodeItemsSection.getItems()) {
codeItem.fixInstructions(fixJumbo, fixGoto); codeItem.fixInstructions(fixJumbo, fixGoto);
} }
}*/ }*/
private static boolean assembleSmaliFile(File smaliFile, List<ClassDef> classes, boolean verboseErrors, private static boolean assembleSmaliFile(File smaliFile, DexBuilder dexBuilder, boolean verboseErrors,
boolean printTokens, boolean allowOdex, int apiLevel) boolean printTokens, boolean allowOdex, int apiLevel)
throws Exception { throws Exception {
CommonTokenStream tokens; CommonTokenStream tokens;
boolean lexerErrors = false; boolean lexerErrors = false;
LexerErrorInterface lexer; LexerErrorInterface lexer;
@ -293,12 +290,8 @@ public class main {
smaliTreeWalker dexGen = new smaliTreeWalker(treeStream); smaliTreeWalker dexGen = new smaliTreeWalker(treeStream);
dexGen.setVerboseErrors(verboseErrors); dexGen.setVerboseErrors(verboseErrors);
ClassDef classDef = dexGen.smali_file(); dexGen.setDexBuilder(dexBuilder);
dexGen.smali_file();
// TODO: will this ever be null? if so, what should happen?
if (classDef != null) {
classes.add(classDef);
}
if (dexGen.getNumberOfSyntaxErrors() > 0) { if (dexGen.getNumberOfSyntaxErrors() > 0) {
return false; return false;