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 java.util.List;
public class ImmutableInstructionFactory implements InstructionFactory<ImmutableInstruction> {
public class ImmutableInstructionFactory implements InstructionFactory<ImmutableInstruction, Reference> {
public static final ImmutableInstructionFactory INSTANCE = new ImmutableInstructionFactory();
private ImmutableInstructionFactory() {

View File

@ -93,5 +93,21 @@ public final class MethodUtil {
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() {}
}

View File

@ -33,7 +33,9 @@ package org.jf.dexlib2.util;
import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.ReferenceType;
import org.jf.dexlib2.VerificationError;
import org.jf.dexlib2.iface.reference.*;
public class Preconditions {
public static void checkFormat(Opcode opcode, Format expectedFormat) {
@ -185,4 +187,32 @@ public class Preconditions {
}
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.instruction.Instruction;
import org.jf.dexlib2.iface.instruction.formats.*;
import org.jf.dexlib2.iface.reference.FieldReference;
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.reference.*;
import org.jf.dexlib2.util.MethodUtil;
import org.jf.dexlib2.writer.util.InstructionWriteUtil;
import org.jf.dexlib2.writer.util.TryListBuilder;
@ -72,10 +69,11 @@ public abstract class DexWriter<
StringKey extends CharSequence, StringRef extends StringReference, TypeKey extends CharSequence,
TypeRef extends TypeReference, ProtoKey extends Comparable<ProtoKey>,
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
BaseReference extends Reference,
ClassKey extends Comparable<? super ClassKey>,
AnnotationKey extends Annotation, AnnotationSetKey,
TypeListKey,
FieldKey extends FieldRefKey, MethodKey extends MethodRefKey,
FieldKey, MethodKey,
EncodedValue, AnnotationElement,
DebugItem extends org.jf.dexlib2.iface.debug.DebugItem,
Insn extends Instruction, ExceptionHandler extends org.jf.dexlib2.iface.ExceptionHandler> {
@ -108,26 +106,26 @@ public abstract class DexWriter<
protected int numCodeItemItems = 0;
protected int numClassDataItems = 0;
protected InstructionFactory<? extends Insn> instructionFactory;
protected final InstructionFactory<? extends Insn, BaseReference> instructionFactory;
protected StringSection<StringKey, StringRef> stringSection;
protected TypeSection<StringKey, TypeKey, TypeRef> typeSection;
protected ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection;
protected FieldSection<StringKey, TypeKey, FieldRefKey> fieldSection;
protected MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey> methodSection;
protected ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
protected final StringSection<StringKey, StringRef> stringSection;
protected final TypeSection<StringKey, TypeKey, TypeRef> typeSection;
protected final ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection;
protected final FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection;
protected final MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey, MethodKey> methodSection;
protected final ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
EncodedValue, DebugItem, Insn, ExceptionHandler> classSection;
protected TypeListSection<TypeKey, TypeListKey> typeListSection;
protected AnnotationSection<StringKey, TypeKey, AnnotationKey, AnnotationElement, EncodedValue> annotationSection;
protected AnnotationSetSection<AnnotationKey, AnnotationSetKey> annotationSetSection;
protected final TypeListSection<TypeKey, TypeListKey> typeListSection;
protected final AnnotationSection<StringKey, TypeKey, AnnotationKey, AnnotationElement, EncodedValue> annotationSection;
protected final AnnotationSetSection<AnnotationKey, AnnotationSetKey> annotationSetSection;
protected DexWriter(InstructionFactory<? extends Insn> instructionFactory,
protected DexWriter(InstructionFactory<? extends Insn, BaseReference> instructionFactory,
StringSection<StringKey, StringRef> stringSection,
TypeSection<StringKey, TypeKey, TypeRef> typeSection,
ProtoSection<StringKey, TypeKey, ProtoKey, TypeListKey> protoSection,
FieldSection<StringKey, TypeKey, FieldRefKey> fieldSection,
MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey> methodSection,
FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey> fieldSection,
MethodSection<StringKey, TypeKey, ProtoKey, MethodRefKey, MethodKey> methodSection,
ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey, AnnotationSetKey,
EncodedValue, DebugItem, Insn, ExceptionHandler> classSection,
TypeListSection<TypeKey, TypeListKey> typeListSection,
@ -394,7 +392,7 @@ public abstract class DexWriter<
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);
// first, try to write the superclass
@ -459,7 +457,7 @@ public abstract class DexWriter<
throws IOException {
int prevIndex = 0;
for (FieldKey key: fields) {
int index = fieldSection.getItemIndex(key);
int index = fieldSection.getFieldIndex(key);
writer.writeUleb128(index-prevIndex);
writer.writeUleb128(classSection.getFieldAccessFlags(key));
prevIndex = index;
@ -470,7 +468,7 @@ public abstract class DexWriter<
throws IOException {
int prevIndex = 0;
for (MethodKey key: methods) {
int index = methodSection.getItemIndex(key);
int index = methodSection.getMethodIndex(key);
writer.writeUleb128(index-prevIndex);
writer.writeUleb128(classSection.getMethodAccessFlags(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
// 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> instanceFields = classSection.getSortedInstanceFields(key);
Collection<? extends MethodKey> directMethods = classSection.getSortedDirectMethods(key);
Collection<? extends MethodKey> virtualMethods = classSection.getSortedVirtualMethods(key);
Collection<? extends FieldKey> fields = classSection.getSortedFields(key);
Collection<? extends MethodKey> methods = classSection.getSortedMethods(key);
// this is how much space we'll need if every field and method has annotations.
int maxSize = (staticFields.size() + instanceFields.size()) * 8 +
(directMethods.size() + virtualMethods.size()) * 16;
int maxSize = fields.size() * 8 + methods.size() * 16;
if (maxSize > tempBuffer.capacity()) {
tempBuffer = ByteBuffer.allocate(maxSize);
tempBuffer.order(ByteOrder.LITTLE_ENDIAN);
@ -646,29 +641,29 @@ public abstract class DexWriter<
int methodAnnotations = 0;
int parameterAnnotations = 0;
for (FieldKey field: classSection.getSortedFields(key)) {
for (FieldKey field: fields) {
AnnotationSetKey fieldAnnotationsKey = classSection.getFieldAnnotations(field);
if (fieldAnnotationsKey != null) {
fieldAnnotations++;
tempBuffer.putInt(fieldSection.getItemIndex(field));
tempBuffer.putInt(fieldSection.getFieldIndex(field));
tempBuffer.putInt(annotationSetSection.getItemOffset(fieldAnnotationsKey));
}
}
for (MethodKey method: classSection.getSortedMethods(key)) {
for (MethodKey method: methods) {
AnnotationSetKey methodAnnotationsKey = classSection.getMethodAnnotations(method);
if (methodAnnotationsKey != null) {
methodAnnotations++;
tempBuffer.putInt(methodSection.getItemIndex(method));
tempBuffer.putInt(methodSection.getMethodIndex(method));
tempBuffer.putInt(annotationSetSection.getItemOffset(methodAnnotationsKey));
}
}
for (MethodKey method: classSection.getSortedMethods(key)) {
for (MethodKey method: methods) {
int offset = classSection.getAnnotationSetRefListOffset(method);
if (offset != DexWriter.NO_OFFSET) {
methodAnnotations++;
tempBuffer.putInt(methodSection.getItemIndex(method));
tempBuffer.putInt(methodSection.getMethodIndex(method));
tempBuffer.putInt(offset);
}
}
@ -809,8 +804,8 @@ public abstract class DexWriter<
if (instructions != null) {
tryBlocks = TryListBuilder.massageTryBlocks(tryBlocks);
InstructionWriteUtil<Insn, StringRef> instrWriteUtil =
new InstructionWriteUtil<Insn, StringRef>(instructions, stringSection, instructionFactory);
InstructionWriteUtil<Insn, StringRef, BaseReference> instrWriteUtil =
new InstructionWriteUtil<Insn, StringRef, BaseReference>(instructions, stringSection, instructionFactory);
writer.writeUshort(instrWriteUtil.getOutParamCount());
writer.writeUshort(tryBlocks.size());
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 StringSection<StringKey, ?> stringSection;
@Nonnull private final TypeSection<?, TypeKey, ?> typeSection;
@Nonnull private final FieldSection<?, ?, FieldRefKey> fieldSection;
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey> methodSection;
@Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
@Nonnull private final AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection;
public EncodedValueWriter(
@Nonnull DexDataWriter writer,
@Nonnull StringSection<StringKey, ?> stringSection,
@Nonnull TypeSection<?, TypeKey, ?> typeSection,
@Nonnull FieldSection<?, ?, FieldRefKey> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey> methodSection,
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
@Nonnull AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection) {
this.writer = writer;
this.stringSection = stringSection;

View File

@ -35,9 +35,10 @@ import org.jf.dexlib2.iface.reference.FieldReference;
import javax.annotation.Nonnull;
public interface FieldSection<StringKey, TypeKey, FieldRefKey extends FieldReference>
public interface FieldSection<StringKey, TypeKey, FieldRefKey extends FieldReference, FieldKey>
extends IndexSection<FieldRefKey> {
@Nonnull TypeKey getDefiningClass(@Nonnull FieldRefKey key);
@Nonnull TypeKey getFieldType(@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 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 makeInstruction10x(@Nonnull Opcode opcode);
Insn makeInstruction11n(@Nonnull Opcode opcode, int registerA, int literal);
Insn makeInstruction11x(@Nonnull Opcode opcode, int registerA);
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 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 makeInstruction21lh(@Nonnull Opcode opcode, int registerA, long literal);
Insn makeInstruction21s(@Nonnull Opcode opcode, int registerA, int literal);
Insn makeInstruction21t(@Nonnull Opcode opcode, int registerA, int codeOffset);
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 makeInstruction22t(@Nonnull Opcode opcode, int registerA, int registerB, int codeOffset);
Insn makeInstruction22x(@Nonnull Opcode opcode, int registerA, int registerB);
Insn makeInstruction23x(@Nonnull Opcode opcode, int registerA, int registerB, int registerC);
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 makeInstruction31t(@Nonnull Opcode opcode, int registerA, int codeOffset);
Insn makeInstruction32x(@Nonnull Opcode opcode, int registerA, int registerB);
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,
@Nonnull Reference reference);
@Nonnull Ref reference);
Insn makeInstruction51l(@Nonnull Opcode opcode, int registerA, long literal);
Insn makeSparseSwitchPayload(@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 StringSection<?, StringRef> stringSection;
@Nonnull private final TypeSection<?, ?, TypeRef> typeSection;
@Nonnull private final FieldSection<?, ?, FieldRefKey> fieldSection;
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey> methodSection;
@Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
@Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference>
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey>
@ -59,8 +59,8 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
@Nonnull DexDataWriter writer,
@Nonnull StringSection<?, StringRef> stringSection,
@Nonnull TypeSection<?, ?, TypeRef> typeSection,
@Nonnull FieldSection<?, ?, FieldRefKey> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey> methodSection) {
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection) {
return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey>(
writer, stringSection, typeSection, fieldSection, methodSection);
}
@ -68,8 +68,8 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
InstructionWriter(@Nonnull DexDataWriter writer,
@Nonnull StringSection<?, StringRef> stringSection,
@Nonnull TypeSection<?, ?, TypeRef> typeSection,
@Nonnull FieldSection<?, ?, FieldRefKey> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey> methodSection) {
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection) {
this.writer = writer;
this.stringSection = stringSection;
this.typeSection = typeSection;

View File

@ -35,9 +35,11 @@ import org.jf.dexlib2.iface.reference.MethodReference;
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> {
@Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key);
@Nonnull ProtoKey getPrototype(@Nonnull MethodRefKey key);
@Nonnull ProtoKey getPrototype(@Nonnull MethodKey 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> {
@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.debug.DebugItem;
import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.dexlib2.iface.reference.FieldReference;
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.reference.*;
import org.jf.dexlib2.iface.value.*;
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.pool.ProtoPool.Key;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
@ -51,7 +48,7 @@ import java.util.Collection;
import java.util.Set;
public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference, Key,
FieldReference, MethodReference, PoolClassDef,
FieldReference, MethodReference, Reference, PoolClassDef,
Annotation, Set<? extends Annotation>,
TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
EncodedValue, AnnotationElement, DebugItem, Instruction, ExceptionHandler> {

View File

@ -31,13 +31,14 @@
package org.jf.dexlib2.writer.pool;
import org.jf.dexlib2.iface.Field;
import org.jf.dexlib2.iface.reference.FieldReference;
import org.jf.dexlib2.writer.FieldSection;
import javax.annotation.Nonnull;
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 TypePool typePool;
@ -66,4 +67,8 @@ public class FieldPool extends BaseIndexPool<FieldReference>
@Nonnull @Override public CharSequence getName(@Nonnull FieldReference fieldReference) {
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;
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 TypePool typePool;
@Nonnull private final ProtoPool protoPool;
@ -66,7 +66,15 @@ public class MethodPool extends BaseIndexPool<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) {
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 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.ProtoSection;
import org.jf.util.CharSequenceUtils;
@ -80,22 +81,6 @@ public class ProtoPool extends BaseIndexPool<Key>
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> {
@Nonnull private final MethodReference method;
@ -109,7 +94,7 @@ public class ProtoPool extends BaseIndexPool<Key>
}
public String getShorty() {
return ProtoPool.getShorty(method.getParameterTypes(), method.getReturnType());
return MethodUtil.getShorty(method.getParameterTypes(), method.getReturnType());
}
public String toString() {

View File

@ -52,9 +52,10 @@ import java.util.ArrayList;
import java.util.HashMap;
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 InstructionFactory<? extends Insn> instructionFactory;
private final InstructionFactory<? extends Insn, BaseReference> instructionFactory;
private final Iterable<? extends Insn> originalInstructions;
private List<Insn> instructions;
@ -70,7 +71,7 @@ public class InstructionWriteUtil<Insn extends Instruction, StringRef extends St
public InstructionWriteUtil(@Nonnull Iterable<? extends Insn> instructions,
@Nonnull StringIndexProvider<StringRef> stringIndexProvider,
@Nonnull InstructionFactory<? extends Insn> instructionFactory) {
@Nonnull InstructionFactory<? extends Insn, BaseReference> instructionFactory) {
this.stringIndexProvider = stringIndexProvider;
this.instructionFactory = instructionFactory;
this.originalInstructions = instructions;
@ -271,7 +272,7 @@ public class InstructionWriteUtil<Insn extends Instruction, StringRef extends St
int referenceIndex = stringIndexProvider.getItemIndex((StringRef)instr.getReference());
if (referenceIndex > 0xFFFF) {
modifiedInstruction = instructionFactory.makeInstruction31c(Opcode.CONST_STRING_JUMBO,
instr.getRegisterA(), instr.getReference());
instr.getRegisterA(), (BaseReference)instr.getReference());
}
}
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.SwitchElement;
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.immutable.ImmutableMethodImplementation;
import org.jf.dexlib2.immutable.instruction.*;
@ -55,7 +56,7 @@ public class JumboStringConversionTest {
private MockStringIndexProvider mockStringIndexProvider;
ArrayList<String> mJumboStrings;
private class InsnWriteUtil extends InstructionWriteUtil<Instruction, StringReference> {
private class InsnWriteUtil extends InstructionWriteUtil<Instruction, StringReference, Reference> {
public InsnWriteUtil(@Nonnull MethodImplementation implementation) {
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.reference.*;
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.util.LinearSearch;
}
@members {
@ -70,6 +70,13 @@ import org.jf.util.LinearSearch;
private boolean verboseErrors = false;
private int apiLevel = 15;
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) {
this.opcodes = new Opcodes(apiLevel);
@ -146,7 +153,7 @@ import org.jf.util.LinearSearch;
smali_file returns[ClassDef classDef]
: ^(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);
};
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();}
: ^(I_FIELDS
(field
@ -228,7 +235,7 @@ fields returns[List<Field> fields]
$fields.add($field.field);
})*);
methods returns[List<Method> methods]
methods returns[List<BuilderMethod> methods]
@init {$methods = Lists.newArrayList();}
: ^(I_METHODS
(method
@ -236,7 +243,7 @@ methods returns[List<Method> methods]
$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?)
{
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.");
}
$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);
};
@ -337,7 +344,7 @@ sparse_switch_elements[int baseAddress] returns[List<SwitchElement> elements]
})*
);
method returns[Method ret]
method returns[BuilderMethod ret]
scope
{
HashMap<String, Integer> labels;
@ -388,10 +395,10 @@ method returns[Method ret]
annotations
)
{
List<TryBlock<? extends ExceptionHandler>> tryBlocks = $catches.tryBlocks;
List<DebugItem> debugItems = $ordered_debug_directives.debugItems;
List<BuilderTryBlock> tryBlocks = $catches.tryBlocks;
List<BuilderDebugItem> debugItems = $ordered_debug_directives.debugItems;
MethodImplementation methodImplementation = null;
BuilderMethodImplementation methodImplementation = null;
boolean isAbstract = false;
boolean isNative = false;
@ -451,14 +458,14 @@ method returns[Method ret]
" registers, for the method parameters");
}
methodImplementation = new ImmutableMethodImplementation(
methodImplementation = dexBuilder.internMethodImplementation(
$method::totalMethodRegisters,
$statements.instructions,
tryBlocks,
debugItems);
}
$ret = new ImmutableMethod(
$ret = dexBuilder.internMethod(
classType,
$method_name_and_prototype.name,
$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();}
: ^(I_CATCHES (catch_directive { tryBlocks.add($catch_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]
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
// to a dex file
$tryBlock = new ImmutableTryBlock(startAddress, endAddress-startAddress,
ImmutableList.of(new ImmutableExceptionHandler(type, handlerAddress)));
$tryBlock = new BuilderTryBlock(startAddress, endAddress-startAddress,
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]
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
// to a dex file
$tryBlock = new ImmutableTryBlock(startAddress, endAddress-startAddress,
ImmutableList.of(new ImmutableExceptionHandler(null, handlerAddress)));
$tryBlock = new BuilderTryBlock(startAddress, endAddress-startAddress,
ImmutableList.of(dexBuilder.internExceptionHandler(null, handlerAddress)));
};
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();}
: ^(I_ORDERED_DEBUG_DIRECTIVES
( 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)
{
$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)
{
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);
};
end_local returns[DebugItem debugItem]
end_local returns[BuilderDebugItem debugItem]
: ^(I_END_LOCAL REGISTER address)
{
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)
{
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)
{
$debugItem = new ImmutablePrologueEnd($address.address);
$debugItem = dexBuilder.internPrologueEnd($address.address);
};
epilogue returns[DebugItem debugItem]
epilogue returns[BuilderDebugItem debugItem]
: ^(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)
{
$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
{
$instructions = Lists.newArrayList();
@ -809,7 +816,7 @@ verification_error_type returns[int verificationError]
$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_format10x[$instructions] { $outRegisters = $insn_format10x.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:
{$outRegisters = 0;}
^(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;
$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
^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
{
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
^(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;
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
^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER)
{
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11x.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
^(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 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;
^(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;
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:
^(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;
$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;
^(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;
$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!"
^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal)
{
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text);
short regA = parseRegister_byte($REGISTER.text);
ImmutableStringReference stringReference = new ImmutableStringReference($string_literal.value);
instructions.add(new ImmutableInstruction21c(opcode, regA, stringReference));
instructions.add(instructionFactory.makeInstruction21c(opcode, regA,
dexBuilder.internStringReference($string_literal.value)));
};
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
^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor)
{
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text);
short regA = parseRegister_byte($REGISTER.text);
ImmutableTypeReference typeReference = new ImmutableTypeReference($reference_type_descriptor.type);
$instructions.add(new ImmutableInstruction21c(opcode, regA, typeReference));
$instructions.add(instructionFactory.makeInstruction21c(opcode, regA,
dexBuilder.internTypeReference($reference_type_descriptor.type)));
};
insn_format21ih[List<Instruction> instructions] returns[int outRegisters]
insn_format21ih[List<BuilderInstruction> instructions] returns[int outRegisters]
: //e.g. const/high16 v1, 1234
^(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;
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
^(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;
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
^(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;
$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:
^(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].");
}
$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
^(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;
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;
^(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;
$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;
^(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 regB = parseRegister_nibble($registerB.text);
ImmutableTypeReference typeReference = new ImmutableTypeReference($nonvoid_type_descriptor.type);
$instructions.add(new ImmutableInstruction22c(opcode, regA, regB, typeReference));
$instructions.add(instructionFactory.makeInstruction22c(opcode, regA, regB,
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
};
insn_format22s[List<Instruction> instructions] returns[int outRegisters]
insn_format22s[List<BuilderInstruction> instructions] returns[int outRegisters]
: //e.g. add-int/lit16 v0, v1, 12345
^(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;
$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:
^(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].");
}
$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
^(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);
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
^(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 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:
^(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;
$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!"
^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal)
{
Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31c.text);
short regA = parseRegister_byte($REGISTER.text);
ImmutableStringReference stringReference = new ImmutableStringReference($string_literal.value);
$instructions.add(new ImmutableInstruction31c(opcode, regA, stringReference));
$instructions.add(instructionFactory.makeInstruction31c(opcode, regA,
dexBuilder.internStringReference($string_literal.value)));
};
insn_format31i[List<Instruction> instructions] returns[int outRegisters]
insn_format31i[List<BuilderInstruction> instructions] returns[int outRegisters]
: //e.g. const v0, 123456
^(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;
$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:
^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER offset_or_label)
{
@ -1156,10 +1162,10 @@ insn_format31t[List<Instruction> instructions] returns[int outRegisters]
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
^(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 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
^(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;
$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
^(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;
$outRegisters = registerCount;
ImmutableTypeReference typeReference = new ImmutableTypeReference($nonvoid_type_descriptor.type);
$instructions.add(new ImmutableInstruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeReference));
$instructions.add(instructionFactory.makeInstruction35c(opcode, registerCount, registers[0], registers[1],
registers[2], registers[3], registers[4], dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
};
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;
^(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;
$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
^(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;
$outRegisters = registerCount;
ImmutableTypeReference typeReference = new ImmutableTypeReference($nonvoid_type_descriptor.type);
$instructions.add(new ImmutableInstruction3rc(opcode, startRegister, registerCount, typeReference));
$instructions.add(instructionFactory.makeInstruction3rc(opcode, startRegister, registerCount,
dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
};
insn_format51l_type[List<Instruction> instructions] returns[int outRegisters]
insn_format51l_type[List<BuilderInstruction> instructions] returns[int outRegisters]
: //e.g. const-wide v0, 5000000000L
^(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;
$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
^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements)
{
int elementWidth = $short_integral_literal.value;
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)
{
@ -1268,10 +1274,10 @@ insn_packed_switch_directive[List<Instruction> instructions] returns[int outRegi
}
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);
@ -1281,7 +1287,7 @@ insn_sparse_switch_directive[List<Instruction> instructions] returns[int outRegi
}
^(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]

View File

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