mirror of
https://github.com/revanced/smali.git
synced 2025-05-07 18:04:32 +02:00
Implement support for new structures in DexWriter
This commit is contained in:
parent
cc34359691
commit
5c5e4ae279
@ -35,10 +35,7 @@ public class VersionMap {
|
||||
public static final int NO_VERSION = -1;
|
||||
|
||||
public static int mapArtVersionToApi(int artVersion) {
|
||||
// NOTE: Art version 87 and api level 26 do not correspond to any
|
||||
// particular android release and represent the current (as of
|
||||
// October 2016) state of aosp/master.
|
||||
if (artVersion >= 87) {
|
||||
if (artVersion >= 124) {
|
||||
return 26;
|
||||
}
|
||||
if (artVersion >= 79) {
|
||||
@ -70,13 +67,15 @@ public class VersionMap {
|
||||
case 24:
|
||||
case 25:
|
||||
return 79;
|
||||
case 26:
|
||||
return 124;
|
||||
}
|
||||
|
||||
// NOTE: Art version 87 and api level 26 do not correspond to any
|
||||
// NOTE: Art version 143 and api level 27 do not correspond to any
|
||||
// particular android release and represent the current (as of
|
||||
// October 2016) state of aosp/master.
|
||||
if (api > 25) {
|
||||
return 87;
|
||||
// May 2018) state of aosp/master.
|
||||
if (api > 26) {
|
||||
return 143;
|
||||
}
|
||||
return NO_VERSION;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class HeaderItem {
|
||||
public static final int ITEM_SIZE = 0x70;
|
||||
|
||||
private static final byte[] MAGIC_VALUE = new byte[] { 0x64, 0x65, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00 };
|
||||
private static final int[] SUPPORTED_DEX_VERSIONS = new int[] { 35, 37 };
|
||||
private static final int[] SUPPORTED_DEX_VERSIONS = new int[] { 35, 37, 38 };
|
||||
|
||||
public static final int LITTLE_ENDIAN_TAG = 0x12345678;
|
||||
public static final int BIG_ENDIAN_TAG = 0x78563412;
|
||||
@ -232,9 +232,11 @@ public class HeaderItem {
|
||||
if (api < 24) {
|
||||
// Prior to Android N we only support dex version 035.
|
||||
return getMagicForDexVersion(35);
|
||||
} else {
|
||||
} if (api < 26) {
|
||||
// On android N and later we support dex version 037.
|
||||
return getMagicForDexVersion(37);
|
||||
} else {
|
||||
return getMagicForDexVersion(38);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,8 @@ public abstract class DexBackedReference {
|
||||
return new DexBackedFieldReference(dexFile, referenceIndex);
|
||||
case ReferenceType.METHOD_PROTO:
|
||||
return new DexBackedMethodProtoReference(dexFile, referenceIndex);
|
||||
case ReferenceType.CALL_SITE:
|
||||
return new DexBackedCallSiteReference(dexFile, referenceIndex);
|
||||
default:
|
||||
throw new ExceptionWithContext("Invalid reference type: %d", referenceType);
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2018, 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;
|
||||
|
||||
import org.jf.dexlib2.iface.reference.CallSiteReference;
|
||||
|
||||
public interface CallSiteSection<CallSiteKey extends CallSiteReference, EncodedArrayKey>
|
||||
extends IndexSection<CallSiteKey> {
|
||||
EncodedArrayKey getEncodedCallSite(CallSiteKey callSiteReference);
|
||||
}
|
@ -35,10 +35,8 @@ import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Ordering;
|
||||
import org.jf.dexlib2.AccessFlags;
|
||||
import org.jf.dexlib2.Opcode;
|
||||
import org.jf.dexlib2.Opcodes;
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import com.google.common.primitives.Ints;
|
||||
import org.jf.dexlib2.*;
|
||||
import org.jf.dexlib2.base.BaseAnnotation;
|
||||
import org.jf.dexlib2.base.BaseAnnotationElement;
|
||||
import org.jf.dexlib2.builder.MutableMethodImplementation;
|
||||
@ -84,6 +82,8 @@ public abstract class DexWriter<
|
||||
TypeRef extends TypeReference, ProtoRefKey extends MethodProtoReference,
|
||||
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
|
||||
ClassKey extends Comparable<? super ClassKey>,
|
||||
CallSiteKey extends CallSiteReference,
|
||||
MethodHandleKey extends MethodHandleReference,
|
||||
AnnotationKey extends Annotation, AnnotationSetKey,
|
||||
TypeListKey,
|
||||
FieldKey, MethodKey,
|
||||
@ -97,6 +97,8 @@ public abstract class DexWriter<
|
||||
MethodSectionType extends MethodSection<StringKey, TypeKey, ProtoRefKey, MethodRefKey, MethodKey>,
|
||||
ClassSectionType extends ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey,
|
||||
AnnotationSetKey, EncodedArrayKey>,
|
||||
CallSiteSectionType extends CallSiteSection<CallSiteKey, EncodedArrayKey>,
|
||||
MethodHandleSectionType extends MethodHandleSection<MethodHandleKey, FieldRefKey, MethodRefKey>,
|
||||
TypeListSectionType extends TypeListSection<TypeKey, TypeListKey>,
|
||||
AnnotationSectionType extends AnnotationSection<StringKey, TypeKey, AnnotationKey, AnnotationElement,
|
||||
EncodedValue>,
|
||||
@ -113,6 +115,8 @@ public abstract class DexWriter<
|
||||
protected int fieldSectionOffset = NO_OFFSET;
|
||||
protected int methodSectionOffset = NO_OFFSET;
|
||||
protected int classIndexSectionOffset = NO_OFFSET;
|
||||
protected int callSiteSectionOffset = NO_OFFSET;
|
||||
protected int methodHandleSectionOffset = NO_OFFSET;
|
||||
|
||||
protected int stringDataSectionOffset = NO_OFFSET;
|
||||
protected int classDataSectionOffset = NO_OFFSET;
|
||||
@ -138,6 +142,8 @@ public abstract class DexWriter<
|
||||
public final FieldSectionType fieldSection;
|
||||
public final MethodSectionType methodSection;
|
||||
public final ClassSectionType classSection;
|
||||
public final CallSiteSectionType callSiteSection;
|
||||
public final MethodHandleSectionType methodHandleSection;
|
||||
|
||||
public final TypeListSectionType typeListSection;
|
||||
public final AnnotationSectionType annotationSection;
|
||||
@ -154,6 +160,8 @@ public abstract class DexWriter<
|
||||
this.fieldSection = sectionProvider.getFieldSection();
|
||||
this.methodSection = sectionProvider.getMethodSection();
|
||||
this.classSection = sectionProvider.getClassSection();
|
||||
this.callSiteSection = sectionProvider.getCallSiteSection();
|
||||
this.methodHandleSection = sectionProvider.getMethodHandleSection();
|
||||
this.typeListSection = sectionProvider.getTypeListSection();
|
||||
this.annotationSection = sectionProvider.getAnnotationSection();
|
||||
this.annotationSetSection = sectionProvider.getAnnotationSetSection();
|
||||
@ -165,6 +173,16 @@ public abstract class DexWriter<
|
||||
protected abstract void writeEncodedValue(@Nonnull InternalEncodedValueWriter writer,
|
||||
@Nonnull EncodedValue encodedValue) throws IOException;
|
||||
|
||||
private Comparator<Map.Entry<? extends CallSiteKey, Integer>> callSiteComparator =
|
||||
new Comparator<Entry<? extends CallSiteKey, Integer>>() {
|
||||
@Override
|
||||
public int compare(Entry<? extends CallSiteKey, Integer> o1, Entry<? extends CallSiteKey, Integer> o2) {
|
||||
int offset1 = encodedArraySection.getItemOffset(callSiteSection.getEncodedCallSite(o1.getKey()));
|
||||
int offset2 = encodedArraySection.getItemOffset(callSiteSection.getEncodedCallSite(o2.getKey()));
|
||||
return Ints.compare(offset1, offset2);
|
||||
}
|
||||
};
|
||||
|
||||
private static Comparator<Map.Entry> toStringKeyComparator =
|
||||
new Comparator<Map.Entry>() {
|
||||
@Override public int compare(Entry o1, Entry o2) {
|
||||
@ -181,9 +199,10 @@ public abstract class DexWriter<
|
||||
}
|
||||
|
||||
protected class InternalEncodedValueWriter extends EncodedValueWriter<StringKey, TypeKey, FieldRefKey, MethodRefKey,
|
||||
AnnotationElement, EncodedValue> {
|
||||
AnnotationElement, ProtoRefKey, MethodHandleKey, EncodedValue> {
|
||||
private InternalEncodedValueWriter(@Nonnull DexDataWriter writer) {
|
||||
super(writer, stringSection, typeSection, fieldSection, methodSection, annotationSection);
|
||||
super(writer, stringSection, typeSection, fieldSection, methodSection, protoSection, methodHandleSection,
|
||||
annotationSection);
|
||||
}
|
||||
|
||||
@Override protected void writeEncodedValue(@Nonnull EncodedValue encodedValue) throws IOException {
|
||||
@ -198,7 +217,9 @@ public abstract class DexWriter<
|
||||
protoSection.getItemCount() * ProtoIdItem.ITEM_SIZE +
|
||||
fieldSection.getItemCount() * FieldIdItem.ITEM_SIZE +
|
||||
methodSection.getItemCount() * MethodIdItem.ITEM_SIZE +
|
||||
classSection.getItemCount() * ClassDefItem.ITEM_SIZE;
|
||||
classSection.getItemCount() * ClassDefItem.ITEM_SIZE +
|
||||
callSiteSection.getItemCount() * CallSiteIdItem.ITEM_SIZE +
|
||||
methodHandleSection.getItemCount() * MethodHandleItem.ITEM_SIZE;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -262,14 +283,36 @@ public abstract class DexWriter<
|
||||
writeProtos(indexWriter);
|
||||
writeFields(indexWriter);
|
||||
writeMethods(indexWriter);
|
||||
|
||||
// encoded arrays depend on method handles..
|
||||
DexDataWriter methodHandleWriter = outputAt(dest, indexWriter.getPosition() +
|
||||
classSection.getItemCount() * ClassDefItem.ITEM_SIZE +
|
||||
callSiteSection.getItemCount() * CallSiteIdItem.ITEM_SIZE);
|
||||
try {
|
||||
writeMethodHandles(methodHandleWriter);
|
||||
} finally {
|
||||
methodHandleWriter.close();
|
||||
}
|
||||
|
||||
// call sites depend on encoded arrays..
|
||||
writeEncodedArrays(offsetWriter);
|
||||
|
||||
// class defs depend on method handles and call sites..
|
||||
DexDataWriter callSiteWriter = outputAt(dest, indexWriter.getPosition() +
|
||||
classSection.getItemCount() * ClassDefItem.ITEM_SIZE);
|
||||
try {
|
||||
writeCallSites(callSiteWriter);
|
||||
} finally {
|
||||
callSiteWriter.close();
|
||||
}
|
||||
|
||||
writeAnnotations(offsetWriter);
|
||||
writeAnnotationSets(offsetWriter);
|
||||
writeAnnotationSetRefs(offsetWriter);
|
||||
writeAnnotationDirectories(offsetWriter);
|
||||
writeDebugAndCodeItems(offsetWriter, tempFactory.makeDeferredOutputStream());
|
||||
writeEncodedArrays(offsetWriter);
|
||||
writeClasses(indexWriter, offsetWriter);
|
||||
|
||||
writeMapItem(offsetWriter);
|
||||
writeHeader(headerWriter, dataSectionOffset, offsetWriter.getPosition());
|
||||
} finally {
|
||||
@ -511,6 +554,55 @@ public abstract class DexWriter<
|
||||
return nextIndex;
|
||||
}
|
||||
|
||||
private void writeCallSites(DexDataWriter writer) throws IOException {
|
||||
callSiteSectionOffset = writer.getPosition();
|
||||
|
||||
List<Map.Entry<? extends CallSiteKey, Integer>> callSiteEntries =
|
||||
Lists.newArrayList(callSiteSection.getItems());
|
||||
Collections.sort(callSiteEntries, callSiteComparator);
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (Map.Entry<? extends CallSiteKey, Integer> callSite: callSiteEntries) {
|
||||
callSite.setValue(index++);
|
||||
writer.writeInt(encodedArraySection.getItemOffset(callSiteSection.getEncodedCallSite(callSite.getKey())));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeMethodHandles(DexDataWriter writer) throws IOException {
|
||||
methodHandleSectionOffset = writer.getPosition();
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (Entry<? extends MethodHandleKey, Integer> entry: methodHandleSection.getItems()) {
|
||||
entry.setValue(index++);
|
||||
MethodHandleKey methodHandleReference = entry.getKey();
|
||||
writer.writeUshort(methodHandleReference.getMethodHandleType());
|
||||
writer.writeUshort(0);
|
||||
int memberIndex;
|
||||
switch (methodHandleReference.getMethodHandleType()) {
|
||||
case MethodHandleType.INSTANCE_GET:
|
||||
case MethodHandleType.INSTANCE_PUT:
|
||||
case MethodHandleType.STATIC_GET:
|
||||
case MethodHandleType.STATIC_PUT:
|
||||
memberIndex = fieldSection.getItemIndex(
|
||||
methodHandleSection.getFieldReference(methodHandleReference));
|
||||
break;
|
||||
case MethodHandleType.INVOKE_INSTANCE:
|
||||
case MethodHandleType.INVOKE_STATIC:
|
||||
memberIndex = methodSection.getItemIndex(
|
||||
methodHandleSection.getMethodReference(methodHandleReference));
|
||||
break;
|
||||
default:
|
||||
throw new ExceptionWithContext("Invalid method handle type: %d",
|
||||
methodHandleReference.getMethodHandleType());
|
||||
}
|
||||
|
||||
writer.writeUshort(memberIndex);
|
||||
writer.writeUshort(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeEncodedFields(@Nonnull DexDataWriter writer, @Nonnull Collection<? extends FieldKey> fields)
|
||||
throws IOException {
|
||||
int prevIndex = 0;
|
||||
@ -1311,6 +1403,8 @@ public abstract class DexWriter<
|
||||
@Nonnull public abstract FieldSectionType getFieldSection();
|
||||
@Nonnull public abstract MethodSectionType getMethodSection();
|
||||
@Nonnull public abstract ClassSectionType getClassSection();
|
||||
@Nonnull public abstract CallSiteSectionType getCallSiteSection();
|
||||
@Nonnull public abstract MethodHandleSectionType getMethodHandleSection();
|
||||
@Nonnull public abstract TypeListSectionType getTypeListSection();
|
||||
@Nonnull public abstract AnnotationSectionType getAnnotationSection();
|
||||
@Nonnull public abstract AnnotationSetSectionType getAnnotationSetSection();
|
||||
|
@ -35,6 +35,7 @@ import com.google.common.collect.Ordering;
|
||||
import org.jf.dexlib2.ValueType;
|
||||
import org.jf.dexlib2.base.BaseAnnotationElement;
|
||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodHandleReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -43,12 +44,14 @@ import java.util.Collection;
|
||||
|
||||
public abstract class EncodedValueWriter<StringKey, TypeKey, FieldRefKey extends FieldReference,
|
||||
MethodRefKey extends MethodReference, AnnotationElement extends org.jf.dexlib2.iface.AnnotationElement,
|
||||
EncodedValue> {
|
||||
ProtoRefKey, MethodHandleKey extends MethodHandleReference, EncodedValue> {
|
||||
@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 ProtoSection<?, ?, ProtoRefKey, ?> protoSection;
|
||||
@Nonnull private final MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection;
|
||||
@Nonnull private final AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection;
|
||||
|
||||
public EncodedValueWriter(
|
||||
@ -57,12 +60,16 @@ public abstract class EncodedValueWriter<StringKey, TypeKey, FieldRefKey extends
|
||||
@Nonnull TypeSection<?, TypeKey, ?> typeSection,
|
||||
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
|
||||
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
|
||||
ProtoSection<?, ?, ProtoRefKey, ?> protoSection,
|
||||
MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection,
|
||||
@Nonnull AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection) {
|
||||
this.writer = writer;
|
||||
this.stringSection = stringSection;
|
||||
this.typeSection = typeSection;
|
||||
this.fieldSection = fieldSection;
|
||||
this.methodSection = methodSection;
|
||||
this.protoSection = protoSection;
|
||||
this.methodHandleSection = methodHandleSection;
|
||||
this.annotationSection = annotationSection;
|
||||
}
|
||||
|
||||
@ -146,4 +153,12 @@ public abstract class EncodedValueWriter<StringKey, TypeKey, FieldRefKey extends
|
||||
public void writeType(@Nonnull TypeKey value) throws IOException {
|
||||
writer.writeEncodedUint(ValueType.TYPE, typeSection.getItemIndex(value));
|
||||
}
|
||||
|
||||
public void writeMethodType(@Nonnull ProtoRefKey value) throws IOException {
|
||||
writer.writeEncodedUint(ValueType.METHOD_TYPE, protoSection.getItemIndex(value));
|
||||
}
|
||||
|
||||
public void writeMethodHandle(@Nonnull MethodHandleKey value) throws IOException {
|
||||
writer.writeEncodedUint(ValueType.METHOD_HANDLE, methodHandleSection.getItemIndex(value));
|
||||
}
|
||||
}
|
||||
|
@ -40,12 +40,7 @@ import org.jf.dexlib2.iface.instruction.DualReferenceInstruction;
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
||||
import org.jf.dexlib2.iface.instruction.SwitchElement;
|
||||
import org.jf.dexlib2.iface.instruction.formats.*;
|
||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodProtoReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
import org.jf.dexlib2.iface.reference.Reference;
|
||||
import org.jf.dexlib2.iface.reference.StringReference;
|
||||
import org.jf.dexlib2.iface.reference.TypeReference;
|
||||
import org.jf.dexlib2.iface.reference.*;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -55,7 +50,7 @@ import java.util.List;
|
||||
|
||||
public class InstructionWriter<StringRef extends StringReference, TypeRef extends TypeReference,
|
||||
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
|
||||
ProtoRefKey extends MethodProtoReference> {
|
||||
ProtoRefKey extends MethodProtoReference, CallSiteKey extends CallSiteReference> {
|
||||
@Nonnull private final Opcodes opcodes;
|
||||
@Nonnull private final DexDataWriter writer;
|
||||
@Nonnull private final StringSection<?, StringRef> stringSection;
|
||||
@ -63,10 +58,12 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
|
||||
@Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
|
||||
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
|
||||
@Nonnull private final ProtoSection<?, ?, ProtoRefKey, ?> protoSection;
|
||||
@Nonnull private final CallSiteSection<CallSiteKey, ?> callSiteSection;
|
||||
|
||||
@Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, FieldRefKey extends FieldReference,
|
||||
MethodRefKey extends MethodReference, ProtoRefKey extends MethodProtoReference>
|
||||
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey>
|
||||
@Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference,
|
||||
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
|
||||
ProtoRefKey extends MethodProtoReference, CallSiteKey extends CallSiteReference>
|
||||
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, CallSiteKey>
|
||||
makeInstructionWriter(
|
||||
@Nonnull Opcodes opcodes,
|
||||
@Nonnull DexDataWriter writer,
|
||||
@ -74,9 +71,10 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
|
||||
@Nonnull TypeSection<?, ?, TypeRef> typeSection,
|
||||
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
|
||||
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
|
||||
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection) {
|
||||
return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey>(
|
||||
opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection);
|
||||
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection,
|
||||
@Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection) {
|
||||
return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, CallSiteKey>(
|
||||
opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection, callSiteSection);
|
||||
}
|
||||
|
||||
InstructionWriter(@Nonnull Opcodes opcodes,
|
||||
@ -85,7 +83,8 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
|
||||
@Nonnull TypeSection<?, ?, TypeRef> typeSection,
|
||||
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
|
||||
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
|
||||
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection) {
|
||||
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection,
|
||||
@Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection) {
|
||||
this.opcodes = opcodes;
|
||||
this.writer = writer;
|
||||
this.stringSection = stringSection;
|
||||
@ -93,6 +92,7 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
|
||||
this.fieldSection = fieldSection;
|
||||
this.methodSection = methodSection;
|
||||
this.protoSection = protoSection;
|
||||
this.callSiteSection = callSiteSection;
|
||||
}
|
||||
|
||||
private short getOpcodeValue(Opcode opcode) {
|
||||
@ -551,6 +551,8 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
|
||||
return typeSection.getItemIndex((TypeRef) reference);
|
||||
case ReferenceType.METHOD_PROTO:
|
||||
return protoSection.getItemIndex((ProtoRefKey) reference);
|
||||
case ReferenceType.CALL_SITE:
|
||||
return callSiteSection.getItemIndex((CallSiteKey) reference);
|
||||
default:
|
||||
throw new ExceptionWithContext("Unknown reference type: %d", referenceType);
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2018, 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;
|
||||
|
||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodHandleReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
|
||||
public interface MethodHandleSection<MethodHandleKey extends MethodHandleReference, FieldRefKey extends FieldReference,
|
||||
MethodRefKey extends MethodReference> extends IndexSection<MethodHandleKey> {
|
||||
FieldRefKey getFieldReference(MethodHandleKey methodHandleReference);
|
||||
MethodRefKey getMethodReference(MethodHandleKey methodHandleReference);
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2018, 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.CallSiteReference;
|
||||
import org.jf.dexlib2.writer.CallSiteSection;
|
||||
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderArrayEncodedValue;
|
||||
import org.jf.dexlib2.writer.util.CallSiteUtil;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class BuilderCallSitePool extends BaseBuilderPool
|
||||
implements CallSiteSection<BuilderCallSiteReference, BuilderArrayEncodedValue> {
|
||||
@Nonnull private final ConcurrentMap<CallSiteReference, BuilderCallSiteReference> internedItems =
|
||||
Maps.newConcurrentMap();
|
||||
|
||||
public BuilderCallSitePool(@Nonnull DexBuilder dexBuilder) {
|
||||
super(dexBuilder);
|
||||
}
|
||||
|
||||
@Nonnull public BuilderCallSiteReference internCallSite(@Nonnull CallSiteReference callSiteReference) {
|
||||
BuilderCallSiteReference internedCallSite = internedItems.get(callSiteReference);
|
||||
if (internedCallSite != null) {
|
||||
return internedCallSite;
|
||||
}
|
||||
BuilderArrayEncodedValue encodedCallSite = dexBuilder.encodedArraySection.internArrayEncodedValue(
|
||||
CallSiteUtil.getEncodedCallSite(callSiteReference));
|
||||
internedCallSite = new BuilderCallSiteReference(callSiteReference.getName(), encodedCallSite);
|
||||
BuilderCallSiteReference existing = internedItems.putIfAbsent(internedCallSite, internedCallSite);
|
||||
return existing == null ? internedCallSite : existing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderArrayEncodedValue getEncodedCallSite(BuilderCallSiteReference callSiteReference) {
|
||||
return callSiteReference.encodedCallSite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemIndex(@Nonnull BuilderCallSiteReference builderCallSite) {
|
||||
return builderCallSite.index;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<? extends Map.Entry<? extends BuilderCallSiteReference, Integer>> getItems() {
|
||||
return new BuilderMapEntryCollection<BuilderCallSiteReference>(internedItems.values()) {
|
||||
@Override
|
||||
protected int getValue(@Nonnull BuilderCallSiteReference builderCallSiteReference) {
|
||||
return builderCallSiteReference.index;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int setValue(@Nonnull BuilderCallSiteReference builderCallSiteReference, int value) {
|
||||
int prev = builderCallSiteReference.index;
|
||||
builderCallSiteReference.index = value;
|
||||
return prev;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return internedItems.size();
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2018, 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.base.reference.BaseCallSiteReference;
|
||||
import org.jf.dexlib2.iface.value.StringEncodedValue;
|
||||
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderArrayEncodedValue;
|
||||
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue;
|
||||
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderMethodHandleEncodedValue;
|
||||
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderMethodTypeEncodedValue;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jf.dexlib2.writer.DexWriter.NO_INDEX;
|
||||
|
||||
public class BuilderCallSiteReference extends BaseCallSiteReference implements BuilderReference {
|
||||
@Nonnull final String name;
|
||||
@Nonnull final BuilderArrayEncodedValue encodedCallSite;
|
||||
int index = NO_INDEX;
|
||||
|
||||
public BuilderCallSiteReference(@Nonnull String name,
|
||||
@Nonnull BuilderArrayEncodedValue encodedCallSite) {
|
||||
this.name = name;
|
||||
this.encodedCallSite = encodedCallSite;
|
||||
}
|
||||
|
||||
@Nonnull @Override public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nonnull @Override public BuilderMethodHandleReference getMethodHandle() {
|
||||
return ((BuilderMethodHandleEncodedValue) encodedCallSite.elements.get(0)).getValue();
|
||||
}
|
||||
|
||||
@Nonnull @Override public String getMethodName() {
|
||||
return ((StringEncodedValue) encodedCallSite.elements.get(1)).getValue();
|
||||
}
|
||||
|
||||
@Nonnull @Override public BuilderMethodProtoReference getMethodProto() {
|
||||
return ((BuilderMethodTypeEncodedValue) encodedCallSite.elements.get(2)).getValue();
|
||||
}
|
||||
|
||||
@Nonnull @Override public List<? extends BuilderEncodedValue> getExtraArguments() {
|
||||
if (encodedCallSite.elements.size() <= 3) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
return encodedCallSite.elements.subList(3, encodedCallSite.elements.size());
|
||||
}
|
||||
|
||||
@Override public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
}
|
@ -241,4 +241,26 @@ public abstract class BuilderEncodedValues {
|
||||
return typeReference.getType();
|
||||
}
|
||||
}
|
||||
|
||||
public static class BuilderMethodTypeEncodedValue extends BaseMethodTypeEncodedValue
|
||||
implements BuilderEncodedValue {
|
||||
@Nonnull final BuilderMethodProtoReference methodProtoReference;
|
||||
|
||||
public BuilderMethodTypeEncodedValue(@Nonnull BuilderMethodProtoReference methodProtoReference) {
|
||||
this.methodProtoReference = methodProtoReference;
|
||||
}
|
||||
|
||||
@Nonnull @Override public BuilderMethodProtoReference getValue() { return methodProtoReference; }
|
||||
}
|
||||
|
||||
public static class BuilderMethodHandleEncodedValue extends BaseMethodHandleEncodedValue
|
||||
implements BuilderEncodedValue {
|
||||
@Nonnull final BuilderMethodHandleReference methodHandleReference;
|
||||
|
||||
public BuilderMethodHandleEncodedValue(@Nonnull BuilderMethodHandleReference methodHandleReference) {
|
||||
this.methodHandleReference = methodHandleReference;
|
||||
}
|
||||
|
||||
@Nonnull @Override public BuilderMethodHandleReference getValue() { return methodHandleReference; }
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2018, 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.MethodHandleType;
|
||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodHandleReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
import org.jf.dexlib2.writer.MethodHandleSection;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class BuilderMethodHandlePool extends BaseBuilderPool
|
||||
implements MethodHandleSection<BuilderMethodHandleReference, BuilderFieldReference, BuilderMethodReference> {
|
||||
@Nonnull private final ConcurrentMap<MethodHandleReference, BuilderMethodHandleReference> internedItems =
|
||||
Maps.newConcurrentMap();
|
||||
|
||||
public BuilderMethodHandlePool(@Nonnull DexBuilder dexBuilder) {
|
||||
super(dexBuilder);
|
||||
}
|
||||
|
||||
public BuilderMethodHandleReference internMethodHandle(MethodHandleReference methodHandleReference) {
|
||||
BuilderMethodHandleReference internedMethodHandle = internedItems.get(methodHandleReference);
|
||||
if (internedMethodHandle != null) {
|
||||
return internedMethodHandle;
|
||||
}
|
||||
|
||||
BuilderReference memberReference;
|
||||
switch (methodHandleReference.getMethodHandleType()) {
|
||||
case MethodHandleType.INSTANCE_GET:
|
||||
case MethodHandleType.INSTANCE_PUT:
|
||||
case MethodHandleType.STATIC_GET:
|
||||
case MethodHandleType.STATIC_PUT:
|
||||
memberReference = dexBuilder.internFieldReference(
|
||||
(FieldReference) methodHandleReference.getMemberReference());
|
||||
break;
|
||||
case MethodHandleType.INVOKE_INSTANCE:
|
||||
case MethodHandleType.INVOKE_STATIC:
|
||||
memberReference = dexBuilder.internMethodReference(
|
||||
(MethodReference) methodHandleReference.getMemberReference());
|
||||
break;
|
||||
default:
|
||||
throw new ExceptionWithContext("Invalid method handle type: %d",
|
||||
methodHandleReference.getMethodHandleType());
|
||||
}
|
||||
|
||||
internedMethodHandle = new BuilderMethodHandleReference(methodHandleReference.getMethodHandleType(),
|
||||
memberReference);
|
||||
BuilderMethodHandleReference prev = internedItems.putIfAbsent(internedMethodHandle, internedMethodHandle);
|
||||
return prev == null ? internedMethodHandle : prev;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderFieldReference getFieldReference(BuilderMethodHandleReference methodHandleReference) {
|
||||
return (BuilderFieldReference) methodHandleReference.getMemberReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderMethodReference getMethodReference(BuilderMethodHandleReference methodHandleReference) {
|
||||
return (BuilderMethodReference) methodHandleReference.getMemberReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemIndex(@Nonnull BuilderMethodHandleReference builderMethodHandleReference) {
|
||||
return builderMethodHandleReference.index;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<? extends Map.Entry<? extends BuilderMethodHandleReference, Integer>> getItems() {
|
||||
return new BuilderMapEntryCollection<BuilderMethodHandleReference>(internedItems.values()) {
|
||||
@Override
|
||||
protected int getValue(@Nonnull BuilderMethodHandleReference builderMethodHandleReference) {
|
||||
return builderMethodHandleReference.index;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int setValue(@Nonnull BuilderMethodHandleReference builderMethodHandleReference, int value) {
|
||||
int prev = builderMethodHandleReference.index;
|
||||
builderMethodHandleReference.index = value;
|
||||
return prev;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return internedItems.size();
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2018, 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.BaseMethodHandleReference;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static org.jf.dexlib2.writer.DexWriter.NO_INDEX;
|
||||
|
||||
public class BuilderMethodHandleReference extends BaseMethodHandleReference implements BuilderReference {
|
||||
final int methodHandleType;
|
||||
@Nonnull final BuilderReference memberReference;
|
||||
int index = NO_INDEX;
|
||||
|
||||
public BuilderMethodHandleReference(int methodHandleType, @Nonnull BuilderReference memberReference) {
|
||||
this.methodHandleType = methodHandleType;
|
||||
this.memberReference = memberReference;
|
||||
}
|
||||
|
||||
@Override public int getMethodHandleType() {
|
||||
return methodHandleType;
|
||||
}
|
||||
|
||||
@Nonnull @Override public BuilderReference getMemberReference() {
|
||||
return memberReference;
|
||||
}
|
||||
|
||||
@Override public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
}
|
@ -56,10 +56,11 @@ import java.util.Set;
|
||||
|
||||
public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringReference, BuilderTypeReference,
|
||||
BuilderTypeReference, BuilderMethodProtoReference, BuilderFieldReference, BuilderMethodReference,
|
||||
BuilderClassDef, BuilderAnnotation, BuilderAnnotationSet, BuilderTypeList, BuilderField, BuilderMethod,
|
||||
BuilderArrayEncodedValue, BuilderEncodedValue, BuilderAnnotationElement, BuilderStringPool, BuilderTypePool,
|
||||
BuilderProtoPool, BuilderFieldPool, BuilderMethodPool, BuilderClassPool, BuilderTypeListPool,
|
||||
BuilderAnnotationPool, BuilderAnnotationSetPool, BuilderEncodedArrayPool> {
|
||||
BuilderClassDef, BuilderCallSiteReference, BuilderMethodHandleReference, BuilderAnnotation, BuilderAnnotationSet, BuilderTypeList,
|
||||
BuilderField, BuilderMethod, BuilderArrayEncodedValue, BuilderEncodedValue, BuilderAnnotationElement,
|
||||
BuilderStringPool, BuilderTypePool, BuilderProtoPool, BuilderFieldPool, BuilderMethodPool, BuilderClassPool,
|
||||
BuilderCallSitePool, BuilderMethodHandlePool, BuilderTypeListPool, BuilderAnnotationPool,
|
||||
BuilderAnnotationSetPool, BuilderEncodedArrayPool> {
|
||||
|
||||
public DexBuilder(@Nonnull Opcodes opcodes) {
|
||||
super(opcodes);
|
||||
@ -145,6 +146,14 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
||||
internedStaticInitializers));
|
||||
}
|
||||
|
||||
public BuilderCallSiteReference internCallSite(@Nonnull CallSiteReference callSiteReference) {
|
||||
return callSiteSection.internCallSite(callSiteReference);
|
||||
}
|
||||
|
||||
public BuilderMethodHandleReference internMethodHandle(@Nonnull MethodHandleReference methodHandleReference) {
|
||||
return methodHandleSection.internMethodHandle(methodHandleReference);
|
||||
}
|
||||
|
||||
@Nonnull public BuilderStringReference internStringReference(@Nonnull String string) {
|
||||
return stringSection.internString(string);
|
||||
}
|
||||
@ -195,6 +204,12 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
||||
if (reference instanceof MethodProtoReference) {
|
||||
return internMethodProtoReference((MethodProtoReference) reference);
|
||||
}
|
||||
if (reference instanceof CallSiteReference) {
|
||||
return internCallSite((CallSiteReference) reference);
|
||||
}
|
||||
if (reference instanceof MethodHandleReference) {
|
||||
return internMethodHandle((MethodHandleReference) reference);
|
||||
}
|
||||
throw new IllegalArgumentException("Could not determine type of reference");
|
||||
}
|
||||
|
||||
@ -271,6 +286,12 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
||||
case ValueType.TYPE:
|
||||
writer.writeType(((BuilderTypeEncodedValue)encodedValue).typeReference);
|
||||
break;
|
||||
case ValueType.METHOD_TYPE:
|
||||
writer.writeMethodType(((BuilderMethodTypeEncodedValue) encodedValue).methodProtoReference);
|
||||
break;
|
||||
case ValueType.METHOD_HANDLE:
|
||||
writer.writeMethodHandle(((BuilderMethodHandleEncodedValue) encodedValue).methodHandleReference);
|
||||
break;
|
||||
default:
|
||||
throw new ExceptionWithContext("Unrecognized value type: %d", encodedValue.getValueType());
|
||||
}
|
||||
@ -335,6 +356,10 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
||||
return internStringEncodedValue((StringEncodedValue)encodedValue);
|
||||
case ValueType.TYPE:
|
||||
return internTypeEncodedValue((TypeEncodedValue)encodedValue);
|
||||
case ValueType.METHOD_TYPE:
|
||||
return internMethodTypeEncodedValue((MethodTypeEncodedValue) encodedValue);
|
||||
case ValueType.METHOD_HANDLE:
|
||||
return internMethodHandleEncodedValue((MethodHandleEncodedValue) encodedValue);
|
||||
default:
|
||||
throw new ExceptionWithContext("Unexpected encoded value type: %d", encodedValue.getValueType());
|
||||
}
|
||||
@ -377,6 +402,16 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
||||
return new BuilderTypeEncodedValue(typeSection.internType(type.getValue()));
|
||||
}
|
||||
|
||||
@Nonnull private BuilderMethodTypeEncodedValue internMethodTypeEncodedValue(
|
||||
@Nonnull MethodTypeEncodedValue methodType) {
|
||||
return new BuilderMethodTypeEncodedValue(protoSection.internMethodProto(methodType.getValue()));
|
||||
}
|
||||
|
||||
@Nonnull private BuilderMethodHandleEncodedValue internMethodHandleEncodedValue(
|
||||
@Nonnull MethodHandleEncodedValue methodHandle) {
|
||||
return new BuilderMethodHandleEncodedValue(methodHandleSection.internMethodHandle(methodHandle.getValue()));
|
||||
}
|
||||
|
||||
protected class DexBuilderSectionProvider extends SectionProvider {
|
||||
@Nonnull @Override public BuilderStringPool getStringSection() {
|
||||
return new BuilderStringPool();
|
||||
@ -402,6 +437,14 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
||||
return new BuilderClassPool(DexBuilder.this);
|
||||
}
|
||||
|
||||
@Nonnull @Override public BuilderCallSitePool getCallSiteSection() {
|
||||
return new BuilderCallSitePool(DexBuilder.this);
|
||||
}
|
||||
|
||||
@Nonnull @Override public BuilderMethodHandlePool getMethodHandleSection() {
|
||||
return new BuilderMethodHandlePool(DexBuilder.this);
|
||||
}
|
||||
|
||||
@Nonnull @Override public BuilderTypeListPool getTypeListSection() {
|
||||
return new BuilderTypeListPool(DexBuilder.this);
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2018, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.dexlib2.writer.pool;
|
||||
|
||||
import org.jf.dexlib2.iface.reference.CallSiteReference;
|
||||
import org.jf.dexlib2.iface.value.ArrayEncodedValue;
|
||||
import org.jf.dexlib2.writer.CallSiteSection;
|
||||
import org.jf.dexlib2.writer.util.CallSiteUtil;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class CallSitePool extends BaseIndexPool<CallSiteReference>
|
||||
implements CallSiteSection<CallSiteReference, ArrayEncodedValue> {
|
||||
|
||||
public CallSitePool(@Nonnull DexPool dexPool) {
|
||||
super(dexPool);
|
||||
}
|
||||
|
||||
public void intern(CallSiteReference callSiteReference) {
|
||||
Integer prev = internedItems.put(callSiteReference, 0);
|
||||
if (prev == null) {
|
||||
dexPool.encodedArraySection.intern(getEncodedCallSite(callSiteReference));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayEncodedValue getEncodedCallSite(CallSiteReference callSiteReference) {
|
||||
return CallSiteUtil.getEncodedCallSite(callSiteReference);
|
||||
}
|
||||
}
|
@ -146,6 +146,9 @@ public class ClassPool extends BasePool<String, PoolClassDef> implements ClassSe
|
||||
case ReferenceType.METHOD:
|
||||
dexPool.methodSection.intern((MethodReference)reference);
|
||||
break;
|
||||
case ReferenceType.CALL_SITE:
|
||||
dexPool.callSiteSection.intern((CallSiteReference) reference);
|
||||
break;
|
||||
default:
|
||||
throw new ExceptionWithContext("Unrecognized reference type: %d",
|
||||
instruction.getOpcode().referenceType);
|
||||
|
@ -52,10 +52,10 @@ import java.util.Set;
|
||||
|
||||
public class DexPool extends DexWriter<CharSequence, StringReference, CharSequence, TypeReference,
|
||||
MethodProtoReference, FieldReference, MethodReference, PoolClassDef,
|
||||
Annotation, Set<? extends Annotation>,
|
||||
CallSiteReference, MethodHandleReference, Annotation, Set<? extends Annotation>,
|
||||
TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
|
||||
ArrayEncodedValue, EncodedValue, AnnotationElement, StringPool, TypePool, ProtoPool, FieldPool, MethodPool,
|
||||
ClassPool, TypeListPool, AnnotationPool, AnnotationSetPool, EncodedArrayPool> {
|
||||
ClassPool, CallSitePool, MethodHandlePool, TypeListPool, AnnotationPool, AnnotationSetPool, EncodedArrayPool> {
|
||||
|
||||
private final Markable[] sections = new Markable[] {
|
||||
stringSection, typeSection, protoSection, fieldSection, methodSection, classSection, typeListSection,
|
||||
@ -170,6 +170,12 @@ public class DexPool extends DexWriter<CharSequence, StringReference, CharSequen
|
||||
case ValueType.TYPE:
|
||||
writer.writeType(((TypeEncodedValue)encodedValue).getValue());
|
||||
break;
|
||||
case ValueType.METHOD_TYPE:
|
||||
writer.writeMethodType(((MethodTypeEncodedValue) encodedValue).getValue());
|
||||
break;
|
||||
case ValueType.METHOD_HANDLE:
|
||||
writer.writeMethodHandle(((MethodHandleEncodedValue) encodedValue).getValue());
|
||||
break;
|
||||
default:
|
||||
throw new ExceptionWithContext("Unrecognized value type: %d", encodedValue.getValueType());
|
||||
}
|
||||
@ -205,6 +211,12 @@ public class DexPool extends DexWriter<CharSequence, StringReference, CharSequen
|
||||
case ValueType.METHOD:
|
||||
methodSection.intern(((MethodEncodedValue)encodedValue).getValue());
|
||||
break;
|
||||
case ValueType.METHOD_HANDLE:
|
||||
methodHandleSection.intern(((MethodHandleEncodedValue)encodedValue).getValue());
|
||||
break;
|
||||
case ValueType.METHOD_TYPE:
|
||||
protoSection.intern(((MethodTypeEncodedValue)encodedValue).getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,6 +245,14 @@ public class DexPool extends DexWriter<CharSequence, StringReference, CharSequen
|
||||
return new ClassPool(DexPool.this);
|
||||
}
|
||||
|
||||
@Nonnull @Override public CallSitePool getCallSiteSection() {
|
||||
return new CallSitePool(DexPool.this);
|
||||
}
|
||||
|
||||
@Nonnull @Override public MethodHandlePool getMethodHandleSection() {
|
||||
return new MethodHandlePool(DexPool.this);
|
||||
}
|
||||
|
||||
@Nonnull @Override public TypeListPool getTypeListSection() {
|
||||
return new TypeListPool(DexPool.this);
|
||||
}
|
||||
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2018, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.dexlib2.writer.pool;
|
||||
|
||||
import org.jf.dexlib2.MethodHandleType;
|
||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodHandleReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
import org.jf.dexlib2.writer.MethodHandleSection;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class MethodHandlePool extends BaseIndexPool<MethodHandleReference>
|
||||
implements MethodHandleSection<MethodHandleReference, FieldReference, MethodReference> {
|
||||
public MethodHandlePool(@Nonnull DexPool dexPool) {
|
||||
super(dexPool);
|
||||
}
|
||||
|
||||
public void intern(MethodHandleReference methodHandleReference) {
|
||||
Integer prev = internedItems.put(methodHandleReference, 0);
|
||||
if (prev == null) {
|
||||
switch (methodHandleReference.getMethodHandleType()) {
|
||||
case MethodHandleType.INSTANCE_GET:
|
||||
case MethodHandleType.INSTANCE_PUT:
|
||||
case MethodHandleType.STATIC_GET:
|
||||
case MethodHandleType.STATIC_PUT:
|
||||
dexPool.fieldSection.intern((FieldReference) methodHandleReference.getMemberReference());
|
||||
break;
|
||||
case MethodHandleType.INVOKE_INSTANCE:
|
||||
case MethodHandleType.INVOKE_STATIC:
|
||||
dexPool.methodSection.intern((MethodReference) methodHandleReference.getMemberReference());
|
||||
break;
|
||||
default:
|
||||
throw new ExceptionWithContext(
|
||||
"Invalid method handle type: %d", methodHandleReference.getMethodHandleType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldReference getFieldReference(MethodHandleReference methodHandleReference) {
|
||||
return (FieldReference) methodHandleReference.getMemberReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodReference getMethodReference(MethodHandleReference methodHandleReference) {
|
||||
return (MethodReference) methodHandleReference.getMemberReference();
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2018, 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.util;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jf.dexlib2.base.value.BaseArrayEncodedValue;
|
||||
import org.jf.dexlib2.base.value.BaseMethodHandleEncodedValue;
|
||||
import org.jf.dexlib2.base.value.BaseMethodTypeEncodedValue;
|
||||
import org.jf.dexlib2.iface.reference.CallSiteReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodHandleReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodProtoReference;
|
||||
import org.jf.dexlib2.iface.value.ArrayEncodedValue;
|
||||
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||
import org.jf.dexlib2.immutable.value.ImmutableStringEncodedValue;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public class CallSiteUtil {
|
||||
public static ArrayEncodedValue getEncodedCallSite(CallSiteReference callSiteReference) {
|
||||
return new BaseArrayEncodedValue() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<? extends EncodedValue> getValue() {
|
||||
List<EncodedValue> encodedCallSite = Lists.newArrayList();
|
||||
|
||||
encodedCallSite.add(new BaseMethodHandleEncodedValue() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public MethodHandleReference getValue() {
|
||||
return callSiteReference.getMethodHandle();
|
||||
}
|
||||
});
|
||||
encodedCallSite.add(new ImmutableStringEncodedValue(callSiteReference.getMethodName()));
|
||||
encodedCallSite.add(new BaseMethodTypeEncodedValue() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public MethodProtoReference getValue() {
|
||||
return callSiteReference.getMethodProto();
|
||||
}
|
||||
});
|
||||
encodedCallSite.addAll(callSiteReference.getExtraArguments());
|
||||
return encodedCallSite;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
135
dexlib2/src/test/java/org/jf/dexlib2/writer/CallSiteTest.java
Normal file
135
dexlib2/src/test/java/org/jf/dexlib2/writer/CallSiteTest.java
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2018, 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;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jf.dexlib2.*;
|
||||
import org.jf.dexlib2.builder.MethodImplementationBuilder;
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.dexlib2.iface.DexFile;
|
||||
import org.jf.dexlib2.iface.Method;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction35c;
|
||||
import org.jf.dexlib2.iface.reference.CallSiteReference;
|
||||
import org.jf.dexlib2.immutable.ImmutableClassDef;
|
||||
import org.jf.dexlib2.immutable.ImmutableDexFile;
|
||||
import org.jf.dexlib2.immutable.ImmutableMethod;
|
||||
import org.jf.dexlib2.immutable.ImmutableMethodImplementation;
|
||||
import org.jf.dexlib2.immutable.instruction.ImmutableInstruction35c;
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableCallSiteReference;
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodHandleReference;
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodProtoReference;
|
||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
|
||||
import org.jf.dexlib2.writer.builder.BuilderCallSiteReference;
|
||||
import org.jf.dexlib2.writer.builder.BuilderMethod;
|
||||
import org.jf.dexlib2.writer.builder.DexBuilder;
|
||||
import org.jf.dexlib2.writer.io.FileDataStore;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class CallSiteTest {
|
||||
@Test
|
||||
public void testPoolCallSite() throws IOException {
|
||||
ClassDef class1 = new ImmutableClassDef("Lcls1;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null,
|
||||
null, null,
|
||||
Lists.<Method>newArrayList(
|
||||
new ImmutableMethod("Lcls1", "method1",
|
||||
ImmutableList.of(), "V", AccessFlags.PUBLIC.getValue(), null,
|
||||
new ImmutableMethodImplementation(10, ImmutableList.of(
|
||||
new ImmutableInstruction35c(Opcode.INVOKE_CUSTOM, 0, 0, 0, 0, 0, 0,
|
||||
new ImmutableCallSiteReference("call_site_1",
|
||||
new ImmutableMethodHandleReference(MethodHandleType.INVOKE_STATIC,
|
||||
new ImmutableMethodReference("Lcls1", "loader",
|
||||
ImmutableList.of("Ljava/lang/invoke/Lookup;",
|
||||
"Ljava/lang/String;",
|
||||
"Ljava/lang/invoke/MethodType;"),
|
||||
"Ljava/lang/invoke/CallSite;")),
|
||||
"someMethod", new ImmutableMethodProtoReference(ImmutableList.of(), "V"), ImmutableList.of()))
|
||||
), null, null))));
|
||||
|
||||
File tempFile = File.createTempFile("dex", ".dex");
|
||||
DexFileFactory.writeDexFile(tempFile.getPath(),
|
||||
new ImmutableDexFile(Opcodes.forArtVersion(111), ImmutableList.of(class1)));
|
||||
|
||||
verifyDexFile(DexFileFactory.loadDexFile(tempFile, Opcodes.forArtVersion(111)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilderCallSite() throws IOException {
|
||||
DexBuilder dexBuilder = new DexBuilder(Opcodes.forArtVersion(111));
|
||||
|
||||
BuilderCallSiteReference callSite = dexBuilder.internCallSite(new ImmutableCallSiteReference("call_site_1",
|
||||
new ImmutableMethodHandleReference(
|
||||
MethodHandleType.INVOKE_STATIC,
|
||||
new ImmutableMethodReference("Lcls1", "loader", ImmutableList.of("Ljava/lang/invoke/Lookup;",
|
||||
"Ljava/lang/String;",
|
||||
"Ljava/lang/invoke/MethodType;"),
|
||||
"Ljava/lang/invoke/CallSite;")),
|
||||
"someMethod",
|
||||
new ImmutableMethodProtoReference(ImmutableList.of(), "V"), ImmutableList.of()));
|
||||
|
||||
MethodImplementationBuilder methodImplementationBuilder = new MethodImplementationBuilder(10);
|
||||
methodImplementationBuilder.addInstruction(new BuilderInstruction35c(Opcode.INVOKE_CUSTOM, 0, 0, 0, 0, 0, 0,
|
||||
callSite));
|
||||
|
||||
BuilderMethod method = dexBuilder.internMethod("Lcls1", "method1", null, "V", 0, ImmutableSet.of(),
|
||||
methodImplementationBuilder.getMethodImplementation());
|
||||
dexBuilder.internClassDef("Lcls1;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null,
|
||||
ImmutableSet.of(), null,
|
||||
ImmutableList.of(method));
|
||||
|
||||
File tempFile = File.createTempFile("dex", ".dex");
|
||||
dexBuilder.writeTo(new FileDataStore(tempFile));
|
||||
|
||||
verifyDexFile(DexFileFactory.loadDexFile(tempFile, Opcodes.forArtVersion(111)));
|
||||
}
|
||||
|
||||
private void verifyDexFile(DexFile dexFile) {
|
||||
Assert.assertEquals(1, dexFile.getClasses().size());
|
||||
ClassDef cls = Lists.newArrayList(dexFile.getClasses()).get(0);
|
||||
Assert.assertEquals("Lcls1;", cls.getType());
|
||||
Assert.assertEquals(1, Lists.newArrayList(cls.getMethods()).size());
|
||||
Method method = Iterators.getNext(cls.getMethods().iterator(), null);
|
||||
Assert.assertEquals("method1", method.getName());
|
||||
Assert.assertEquals(1, Lists.newArrayList(method.getImplementation().getInstructions()).size());
|
||||
Instruction instruction = Lists.newArrayList(method.getImplementation().getInstructions().iterator()).get(0);
|
||||
Assert.assertEquals(Opcode.INVOKE_CUSTOM, instruction.getOpcode());
|
||||
Assert.assertTrue(((Instruction35c) instruction).getReference() instanceof CallSiteReference);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user