mirror of
https://github.com/revanced/smali.git
synced 2025-05-06 17:34:34 +02:00
Create separate section for encoded arrays
This commit is contained in:
parent
2d227a7349
commit
cc34359691
@ -45,7 +45,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ClassSection<StringKey extends CharSequence, TypeKey extends CharSequence, TypeListKey, ClassKey,
|
||||
FieldKey, MethodKey, AnnotationSetKey, EncodedValue> extends IndexSection<ClassKey> {
|
||||
FieldKey, MethodKey, AnnotationSetKey, EncodedArrayKey> extends IndexSection<ClassKey> {
|
||||
@Nonnull Collection<? extends ClassKey> getSortedClasses();
|
||||
|
||||
@Nullable Map.Entry<? extends ClassKey, Integer> getClassEntryByType(@Nullable TypeKey key);
|
||||
@ -55,7 +55,7 @@ public interface ClassSection<StringKey extends CharSequence, TypeKey extends Ch
|
||||
@Nullable TypeKey getSuperclass(@Nonnull ClassKey key);
|
||||
@Nullable TypeListKey getInterfaces(@Nonnull ClassKey key);
|
||||
@Nullable StringKey getSourceFile(@Nonnull ClassKey key);
|
||||
@Nullable Collection<? extends EncodedValue> getStaticInitializers(@Nonnull ClassKey key);
|
||||
@Nullable EncodedArrayKey getStaticInitializers(@Nonnull ClassKey key);
|
||||
|
||||
@Nonnull Collection<? extends FieldKey> getSortedStaticFields(@Nonnull ClassKey key);
|
||||
@Nonnull Collection<? extends FieldKey> getSortedInstanceFields(@Nonnull ClassKey key);
|
||||
@ -81,9 +81,6 @@ public interface ClassSection<StringKey extends CharSequence, TypeKey extends Ch
|
||||
@Nullable TypeKey getExceptionType(@Nonnull ExceptionHandler handler);
|
||||
@Nonnull MutableMethodImplementation makeMutableMethodImplementation(@Nonnull MethodKey key);
|
||||
|
||||
void setEncodedArrayOffset(@Nonnull ClassKey key, int offset);
|
||||
int getEncodedArrayOffset(@Nonnull ClassKey key);
|
||||
|
||||
void setAnnotationDirectoryOffset(@Nonnull ClassKey key, int offset);
|
||||
int getAnnotationDirectoryOffset(@Nonnull ClassKey key);
|
||||
|
||||
|
@ -63,7 +63,6 @@ import org.jf.dexlib2.writer.io.DeferredOutputStreamFactory;
|
||||
import org.jf.dexlib2.writer.io.DexDataStore;
|
||||
import org.jf.dexlib2.writer.io.MemoryDeferredOutputStream;
|
||||
import org.jf.dexlib2.writer.util.TryListBuilder;
|
||||
import org.jf.util.CollectionUtils;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -88,6 +87,7 @@ public abstract class DexWriter<
|
||||
AnnotationKey extends Annotation, AnnotationSetKey,
|
||||
TypeListKey,
|
||||
FieldKey, MethodKey,
|
||||
EncodedArrayKey,
|
||||
EncodedValue,
|
||||
AnnotationElement extends org.jf.dexlib2.iface.AnnotationElement,
|
||||
StringSectionType extends StringSection<StringKey, StringRef>,
|
||||
@ -96,11 +96,12 @@ public abstract class DexWriter<
|
||||
FieldSectionType extends FieldSection<StringKey, TypeKey, FieldRefKey, FieldKey>,
|
||||
MethodSectionType extends MethodSection<StringKey, TypeKey, ProtoRefKey, MethodRefKey, MethodKey>,
|
||||
ClassSectionType extends ClassSection<StringKey, TypeKey, TypeListKey, ClassKey, FieldKey, MethodKey,
|
||||
AnnotationSetKey, EncodedValue>,
|
||||
AnnotationSetKey, EncodedArrayKey>,
|
||||
TypeListSectionType extends TypeListSection<TypeKey, TypeListKey>,
|
||||
AnnotationSectionType extends AnnotationSection<StringKey, TypeKey, AnnotationKey, AnnotationElement,
|
||||
EncodedValue>,
|
||||
AnnotationSetSectionType extends AnnotationSetSection<AnnotationKey, AnnotationSetKey>> {
|
||||
AnnotationSetSectionType extends AnnotationSetSection<AnnotationKey, AnnotationSetKey>,
|
||||
EncodedArraySectionType extends EncodedArraySection<EncodedArrayKey, EncodedValue>> {
|
||||
public static final int NO_INDEX = -1;
|
||||
public static final int NO_OFFSET = 0;
|
||||
|
||||
@ -125,7 +126,6 @@ public abstract class DexWriter<
|
||||
protected int codeSectionOffset = NO_OFFSET;
|
||||
protected int mapSectionOffset = NO_OFFSET;
|
||||
|
||||
protected int numEncodedArrayItems = 0;
|
||||
protected int numAnnotationSetRefItems = 0;
|
||||
protected int numAnnotationDirectoryItems = 0;
|
||||
protected int numDebugInfoItems = 0;
|
||||
@ -138,10 +138,11 @@ public abstract class DexWriter<
|
||||
public final FieldSectionType fieldSection;
|
||||
public final MethodSectionType methodSection;
|
||||
public final ClassSectionType classSection;
|
||||
|
||||
|
||||
public final TypeListSectionType typeListSection;
|
||||
public final AnnotationSectionType annotationSection;
|
||||
public final AnnotationSetSectionType annotationSetSection;
|
||||
public final EncodedArraySectionType encodedArraySection;
|
||||
|
||||
protected DexWriter(Opcodes opcodes) {
|
||||
this.opcodes = opcodes;
|
||||
@ -156,6 +157,7 @@ public abstract class DexWriter<
|
||||
this.typeListSection = sectionProvider.getTypeListSection();
|
||||
this.annotationSection = sectionProvider.getAnnotationSection();
|
||||
this.annotationSetSection = sectionProvider.getAnnotationSetSection();
|
||||
this.encodedArraySection = sectionProvider.getEncodedArraySection();
|
||||
}
|
||||
|
||||
@Nonnull protected abstract SectionProvider getSectionProvider();
|
||||
@ -266,6 +268,7 @@ public abstract class DexWriter<
|
||||
writeAnnotationSetRefs(offsetWriter);
|
||||
writeAnnotationDirectories(offsetWriter);
|
||||
writeDebugAndCodeItems(offsetWriter, tempFactory.makeDeferredOutputStream());
|
||||
writeEncodedArrays(offsetWriter);
|
||||
writeClasses(indexWriter, offsetWriter);
|
||||
writeMapItem(offsetWriter);
|
||||
writeHeader(headerWriter, dataSectionOffset, offsetWriter.getPosition());
|
||||
@ -480,10 +483,15 @@ public abstract class DexWriter<
|
||||
if (classHasData) {
|
||||
indexWriter.writeInt(offsetWriter.getPosition());
|
||||
} else {
|
||||
indexWriter.writeInt(0);
|
||||
indexWriter.writeInt(NO_OFFSET);
|
||||
}
|
||||
|
||||
indexWriter.writeInt(classSection.getEncodedArrayOffset(key));
|
||||
EncodedArrayKey staticInitializers = classSection.getStaticInitializers(key);
|
||||
if (staticInitializers != null) {
|
||||
indexWriter.writeInt(encodedArraySection.getItemOffset(staticInitializers));
|
||||
} else {
|
||||
indexWriter.writeInt(NO_OFFSET);
|
||||
}
|
||||
|
||||
// now write the class_data_item
|
||||
if (classHasData) {
|
||||
@ -541,55 +549,16 @@ public abstract class DexWriter<
|
||||
}
|
||||
}
|
||||
|
||||
private static class EncodedArrayKey<EncodedValue> {
|
||||
@Nonnull Collection<? extends EncodedValue> elements;
|
||||
|
||||
public EncodedArrayKey() {
|
||||
}
|
||||
|
||||
@Override public int hashCode() {
|
||||
return CollectionUtils.listHashCode(elements);
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object o) {
|
||||
if (o instanceof EncodedArrayKey) {
|
||||
EncodedArrayKey other = (EncodedArrayKey)o;
|
||||
if (elements.size() != other.elements.size()) {
|
||||
return false;
|
||||
}
|
||||
return Iterables.elementsEqual(elements, other.elements);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeEncodedArrays(@Nonnull DexDataWriter writer) throws IOException {
|
||||
InternalEncodedValueWriter encodedValueWriter = new InternalEncodedValueWriter(writer);
|
||||
encodedArraySectionOffset = writer.getPosition();
|
||||
|
||||
HashMap<EncodedArrayKey<EncodedValue>, Integer> internedItems = Maps.newHashMap();
|
||||
EncodedArrayKey<EncodedValue> key = new EncodedArrayKey<EncodedValue>();
|
||||
|
||||
for (ClassKey classKey: classSection.getSortedClasses()) {
|
||||
Collection <? extends EncodedValue> elements = classSection.getStaticInitializers(classKey);
|
||||
if (elements != null && elements.size() > 0) {
|
||||
key.elements = elements;
|
||||
Integer prev = internedItems.get(key);
|
||||
if (prev != null) {
|
||||
classSection.setEncodedArrayOffset(classKey, prev);
|
||||
} else {
|
||||
int offset = writer.getPosition();
|
||||
internedItems.put(key, offset);
|
||||
classSection.setEncodedArrayOffset(classKey, offset);
|
||||
key = new EncodedArrayKey<EncodedValue>();
|
||||
|
||||
numEncodedArrayItems++;
|
||||
|
||||
writer.writeUleb128(elements.size());
|
||||
for (EncodedValue value: elements) {
|
||||
writeEncodedValue(encodedValueWriter, value);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<? extends EncodedArrayKey, Integer> entry: encodedArraySection.getItems()) {
|
||||
entry.setValue(writer.getPosition());
|
||||
List<? extends EncodedValue> encodedArray = encodedArraySection.getEncodedValueList(entry.getKey());
|
||||
writer.writeUleb128(encodedArray.size());
|
||||
for (EncodedValue value: encodedArray) {
|
||||
writeEncodedValue(encodedValueWriter, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -975,7 +944,7 @@ public abstract class DexWriter<
|
||||
|
||||
InstructionWriter instructionWriter =
|
||||
InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection,
|
||||
methodSection, protoSection);
|
||||
methodSection, protoSection, callSiteSection);
|
||||
|
||||
writer.writeInt(codeUnitCount);
|
||||
int codeOffset = 0;
|
||||
@ -1196,10 +1165,16 @@ public abstract class DexWriter<
|
||||
if (methodSection.getItems().size() > 0) {
|
||||
numItems++;
|
||||
}
|
||||
if (callSiteSection.getItems().size() > 0) {
|
||||
numItems++;
|
||||
}
|
||||
if (methodHandleSection.getItems().size() > 0) {
|
||||
numItems++;
|
||||
}
|
||||
if (typeListSection.getItems().size() > 0) {
|
||||
numItems++;
|
||||
}
|
||||
if (numEncodedArrayItems > 0) {
|
||||
if (encodedArraySection.getItems().size() > 0) {
|
||||
numItems++;
|
||||
}
|
||||
if (annotationSection.getItems().size() > 0) {
|
||||
@ -1247,14 +1222,19 @@ public abstract class DexWriter<
|
||||
writeMapItem(writer, ItemType.FIELD_ID_ITEM, fieldSection.getItems().size(), fieldSectionOffset);
|
||||
writeMapItem(writer, ItemType.METHOD_ID_ITEM, methodSection.getItems().size(), methodSectionOffset);
|
||||
writeMapItem(writer, ItemType.CLASS_DEF_ITEM, classSection.getItems().size(), classIndexSectionOffset);
|
||||
writeMapItem(writer, ItemType.CALL_SITE_ID_ITEM, callSiteSection.getItems().size(), callSiteSectionOffset);
|
||||
writeMapItem(writer, ItemType.METHOD_HANDLE_ITEM, methodHandleSection.getItems().size(),
|
||||
methodHandleSectionOffset);
|
||||
|
||||
// data section
|
||||
writeMapItem(writer, ItemType.STRING_DATA_ITEM, stringSection.getItems().size(), stringDataSectionOffset);
|
||||
writeMapItem(writer, ItemType.TYPE_LIST, typeListSection.getItems().size(), typeListSectionOffset);
|
||||
writeMapItem(writer, ItemType.ENCODED_ARRAY_ITEM, numEncodedArrayItems, encodedArraySectionOffset);
|
||||
writeMapItem(writer, ItemType.ENCODED_ARRAY_ITEM, encodedArraySection.getItems().size(),
|
||||
encodedArraySectionOffset);
|
||||
writeMapItem(writer, ItemType.ANNOTATION_ITEM, annotationSection.getItems().size(), annotationSectionOffset);
|
||||
writeMapItem(writer, ItemType.ANNOTATION_SET_ITEM,
|
||||
annotationSetSection.getItems().size() + (shouldCreateEmptyAnnotationSet() ? 1 : 0), annotationSetSectionOffset);
|
||||
annotationSetSection.getItems().size() + (shouldCreateEmptyAnnotationSet() ? 1 : 0),
|
||||
annotationSetSectionOffset);
|
||||
writeMapItem(writer, ItemType.ANNOTATION_SET_REF_LIST, numAnnotationSetRefItems, annotationSetRefSectionOffset);
|
||||
writeMapItem(writer, ItemType.ANNOTATION_DIRECTORY_ITEM, numAnnotationDirectoryItems,
|
||||
annotationDirectorySectionOffset);
|
||||
@ -1334,5 +1314,6 @@ public abstract class DexWriter<
|
||||
@Nonnull public abstract TypeListSectionType getTypeListSection();
|
||||
@Nonnull public abstract AnnotationSectionType getAnnotationSection();
|
||||
@Nonnull public abstract AnnotationSetSectionType getAnnotationSetSection();
|
||||
@Nonnull public abstract EncodedArraySectionType getEncodedArraySection();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 java.util.List;
|
||||
|
||||
public interface EncodedArraySection<EncodedArrayKey, EncodedValue> extends OffsetSection<EncodedArrayKey> {
|
||||
List<? extends EncodedValue> getEncodedValueList(EncodedArrayKey encodedArrayKey);
|
||||
}
|
@ -35,9 +35,9 @@ 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 org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderArrayEncodedValue;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -54,9 +54,9 @@ public class BuilderClassDef extends BaseTypeReference implements ClassDef {
|
||||
@Nonnull final SortedSet<BuilderField> instanceFields;
|
||||
@Nonnull final SortedSet<BuilderMethod> directMethods;
|
||||
@Nonnull final SortedSet<BuilderMethod> virtualMethods;
|
||||
@Nullable final BuilderArrayEncodedValue staticInitializers;
|
||||
|
||||
int classDefIndex = DexWriter.NO_INDEX;
|
||||
int encodedArrayOffset = DexWriter.NO_OFFSET;
|
||||
int annotationDirectoryOffset = DexWriter.NO_OFFSET;
|
||||
|
||||
BuilderClassDef(@Nonnull BuilderTypeReference type,
|
||||
@ -65,14 +65,19 @@ public class BuilderClassDef extends BaseTypeReference implements ClassDef {
|
||||
@Nonnull BuilderTypeList interfaces,
|
||||
@Nullable BuilderStringReference sourceFile,
|
||||
@Nonnull BuilderAnnotationSet annotations,
|
||||
@Nullable Iterable<? extends BuilderField> fields,
|
||||
@Nullable Iterable<? extends BuilderMethod> methods) {
|
||||
if (fields == null) {
|
||||
fields = ImmutableList.of();
|
||||
}
|
||||
@Nullable SortedSet<BuilderField> staticFields,
|
||||
@Nullable SortedSet<BuilderField> instanceFields,
|
||||
@Nullable Iterable<? extends BuilderMethod> methods,
|
||||
@Nullable BuilderArrayEncodedValue staticInitializers) {
|
||||
if (methods == null) {
|
||||
methods = ImmutableList.of();
|
||||
}
|
||||
if (staticFields == null) {
|
||||
staticFields = ImmutableSortedSet.of();
|
||||
}
|
||||
if (instanceFields == null) {
|
||||
instanceFields = ImmutableSortedSet.of();
|
||||
}
|
||||
|
||||
this.type = type;
|
||||
this.accessFlags = accessFlags;
|
||||
@ -80,10 +85,11 @@ public class BuilderClassDef extends BaseTypeReference implements ClassDef {
|
||||
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.staticFields = staticFields;
|
||||
this.instanceFields = instanceFields;
|
||||
this.directMethods = ImmutableSortedSet.copyOf(Iterables.filter(methods, MethodUtil.METHOD_IS_DIRECT));
|
||||
this.virtualMethods = ImmutableSortedSet.copyOf(Iterables.filter(methods, MethodUtil.METHOD_IS_VIRTUAL));
|
||||
this.staticInitializers = staticInitializers;
|
||||
}
|
||||
|
||||
@Nonnull @Override public String getType() { return type.getType(); }
|
||||
|
@ -48,21 +48,24 @@ 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.BuilderEncodedValues.BuilderArrayEncodedValue;
|
||||
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.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class BuilderClassPool extends BaseBuilderPool implements ClassSection<BuilderStringReference,
|
||||
BuilderTypeReference, BuilderTypeList, BuilderClassDef, BuilderField, BuilderMethod, BuilderAnnotationSet,
|
||||
BuilderEncodedValue> {
|
||||
BuilderArrayEncodedValue> {
|
||||
@Nonnull private final ConcurrentMap<String, BuilderClassDef> internedItems =
|
||||
Maps.newConcurrentMap();
|
||||
|
||||
@ -153,24 +156,8 @@ public class BuilderClassPool extends BaseBuilderPool implements ClassSection<Bu
|
||||
};
|
||||
|
||||
@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;
|
||||
public BuilderArrayEncodedValue getStaticInitializers(@Nonnull BuilderClassDef classDef) {
|
||||
return classDef.staticInitializers;
|
||||
}
|
||||
|
||||
@Nonnull @Override
|
||||
@ -325,14 +312,6 @@ public class BuilderClassPool extends BaseBuilderPool implements ClassSection<Bu
|
||||
return new MutableMethodImplementation(impl);
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.value.ArrayEncodedValue;
|
||||
import org.jf.dexlib2.writer.EncodedArraySection;
|
||||
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderArrayEncodedValue;
|
||||
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class BuilderEncodedArrayPool extends BaseBuilderPool implements
|
||||
EncodedArraySection<BuilderArrayEncodedValue, BuilderEncodedValue> {
|
||||
@Nonnull private final ConcurrentMap<ArrayEncodedValue, BuilderArrayEncodedValue> internedItems =
|
||||
Maps.newConcurrentMap();
|
||||
|
||||
public BuilderEncodedArrayPool(@Nonnull DexBuilder dexBuilder) {
|
||||
super(dexBuilder);
|
||||
}
|
||||
|
||||
@Nonnull public BuilderArrayEncodedValue internArrayEncodedValue(@Nonnull ArrayEncodedValue arrayEncodedValue) {
|
||||
BuilderArrayEncodedValue builderArrayEncodedValue = internedItems.get(arrayEncodedValue);
|
||||
if (builderArrayEncodedValue != null) {
|
||||
return builderArrayEncodedValue;
|
||||
}
|
||||
|
||||
builderArrayEncodedValue = (BuilderArrayEncodedValue)dexBuilder.internEncodedValue(arrayEncodedValue);
|
||||
BuilderArrayEncodedValue previous = internedItems.putIfAbsent(
|
||||
builderArrayEncodedValue, builderArrayEncodedValue);
|
||||
return previous == null ? builderArrayEncodedValue : previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemOffset(@Nonnull BuilderArrayEncodedValue builderArrayEncodedValue) {
|
||||
return builderArrayEncodedValue.offset;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<? extends Map.Entry<? extends BuilderArrayEncodedValue, Integer>> getItems() {
|
||||
return new BuilderMapEntryCollection<BuilderArrayEncodedValue>(internedItems.values()) {
|
||||
@Override
|
||||
protected int getValue(@Nonnull BuilderArrayEncodedValue builderArrayEncodedValue) {
|
||||
return builderArrayEncodedValue.offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int setValue(@Nonnull BuilderArrayEncodedValue key, int value) {
|
||||
int prev = key.offset;
|
||||
key.offset = value;
|
||||
return prev;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends BuilderEncodedValue> getEncodedValueList(BuilderArrayEncodedValue builderArrayEncodedValue) {
|
||||
return builderArrayEncodedValue.elements;
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ 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.dexlib2.writer.DexWriter;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -66,6 +67,7 @@ public abstract class BuilderEncodedValues {
|
||||
|
||||
public static class BuilderArrayEncodedValue extends BaseArrayEncodedValue implements BuilderEncodedValue {
|
||||
@Nonnull final List<? extends BuilderEncodedValue> elements;
|
||||
int offset = DexWriter.NO_OFFSET;
|
||||
|
||||
BuilderArrayEncodedValue(@Nonnull List<? extends BuilderEncodedValue> elements) {
|
||||
this.elements = elements;
|
||||
|
@ -32,10 +32,7 @@
|
||||
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 com.google.common.collect.Sets;
|
||||
import com.google.common.collect.*;
|
||||
import org.jf.dexlib2.Opcodes;
|
||||
import org.jf.dexlib2.ValueType;
|
||||
import org.jf.dexlib2.iface.Annotation;
|
||||
@ -44,8 +41,10 @@ import org.jf.dexlib2.iface.MethodImplementation;
|
||||
import org.jf.dexlib2.iface.MethodParameter;
|
||||
import org.jf.dexlib2.iface.reference.*;
|
||||
import org.jf.dexlib2.iface.value.*;
|
||||
import org.jf.dexlib2.util.FieldUtil;
|
||||
import org.jf.dexlib2.writer.DexWriter;
|
||||
import org.jf.dexlib2.writer.builder.BuilderEncodedValues.*;
|
||||
import org.jf.dexlib2.writer.util.StaticInitializerUtil;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -58,9 +57,9 @@ import java.util.Set;
|
||||
public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringReference, BuilderTypeReference,
|
||||
BuilderTypeReference, BuilderMethodProtoReference, BuilderFieldReference, BuilderMethodReference,
|
||||
BuilderClassDef, BuilderAnnotation, BuilderAnnotationSet, BuilderTypeList, BuilderField, BuilderMethod,
|
||||
BuilderEncodedValue, BuilderAnnotationElement, BuilderStringPool, BuilderTypePool, BuilderProtoPool,
|
||||
BuilderFieldPool, BuilderMethodPool, BuilderClassPool, BuilderTypeListPool, BuilderAnnotationPool,
|
||||
BuilderAnnotationSetPool> {
|
||||
BuilderArrayEncodedValue, BuilderEncodedValue, BuilderAnnotationElement, BuilderStringPool, BuilderTypePool,
|
||||
BuilderProtoPool, BuilderFieldPool, BuilderMethodPool, BuilderClassPool, BuilderTypeListPool,
|
||||
BuilderAnnotationPool, BuilderAnnotationSetPool, BuilderEncodedArrayPool> {
|
||||
|
||||
public DexBuilder(@Nonnull Opcodes opcodes) {
|
||||
super(opcodes);
|
||||
@ -122,14 +121,28 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
||||
}
|
||||
}
|
||||
|
||||
ImmutableSortedSet<BuilderField> staticFields = null;
|
||||
ImmutableSortedSet<BuilderField> instanceFields = null;
|
||||
BuilderArrayEncodedValue internedStaticInitializers = null;
|
||||
if (fields != null) {
|
||||
staticFields = ImmutableSortedSet.copyOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC));
|
||||
instanceFields = ImmutableSortedSet.copyOf(Iterables.filter(fields, FieldUtil.FIELD_IS_INSTANCE));
|
||||
ArrayEncodedValue staticInitializers = StaticInitializerUtil.getStaticInitializers(staticFields);
|
||||
if (staticInitializers != null) {
|
||||
internedStaticInitializers = encodedArraySection.internArrayEncodedValue(staticInitializers);
|
||||
}
|
||||
}
|
||||
|
||||
return classSection.internClass(new BuilderClassDef(typeSection.internType(type),
|
||||
accessFlags,
|
||||
typeSection.internNullableType(superclass),
|
||||
typeListSection.internTypeList(interfaces),
|
||||
stringSection.internNullableString(sourceFile),
|
||||
annotationSetSection.internAnnotationSet(annotations),
|
||||
fields,
|
||||
methods));
|
||||
staticFields,
|
||||
instanceFields,
|
||||
methods,
|
||||
internedStaticInitializers));
|
||||
}
|
||||
|
||||
@Nonnull public BuilderStringReference internStringReference(@Nonnull String string) {
|
||||
@ -287,7 +300,7 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
||||
return internEncodedValue(encodedValue);
|
||||
}
|
||||
|
||||
@Nonnull private BuilderEncodedValue internEncodedValue(@Nonnull EncodedValue encodedValue) {
|
||||
@Nonnull BuilderEncodedValue internEncodedValue(@Nonnull EncodedValue encodedValue) {
|
||||
switch (encodedValue.getValueType()) {
|
||||
case ValueType.ANNOTATION:
|
||||
return internAnnotationEncodedValue((AnnotationEncodedValue)encodedValue);
|
||||
@ -400,5 +413,9 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
||||
@Nonnull @Override public BuilderAnnotationSetPool getAnnotationSetSection() {
|
||||
return new BuilderAnnotationSetPool(DexBuilder.this);
|
||||
}
|
||||
|
||||
@Nonnull @Override public BuilderEncodedArrayPool getEncodedArraySection() {
|
||||
return new BuilderEncodedArrayPool(DexBuilder.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,10 @@ package org.jf.dexlib2.writer.pool;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.*;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Ordering;
|
||||
import org.jf.dexlib2.DebugItemType;
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.builder.MutableMethodImplementation;
|
||||
@ -42,14 +45,13 @@ import org.jf.dexlib2.iface.debug.*;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
||||
import org.jf.dexlib2.iface.reference.*;
|
||||
import org.jf.dexlib2.iface.value.ArrayEncodedValue;
|
||||
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||
import org.jf.dexlib2.immutable.value.ImmutableEncodedValueFactory;
|
||||
import org.jf.dexlib2.util.EncodedValueUtils;
|
||||
import org.jf.dexlib2.util.ReferenceUtil;
|
||||
import org.jf.dexlib2.writer.ClassSection;
|
||||
import org.jf.dexlib2.writer.DebugWriter;
|
||||
import org.jf.dexlib2.writer.util.StaticInitializerUtil;
|
||||
import org.jf.util.AbstractForwardSequentialList;
|
||||
import org.jf.util.CollectionUtils;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -60,7 +62,7 @@ import java.util.Map.Entry;
|
||||
|
||||
public class ClassPool extends BasePool<String, PoolClassDef> implements ClassSection<CharSequence, CharSequence,
|
||||
TypeListPool.Key<? extends Collection<? extends CharSequence>>, PoolClassDef, Field, PoolMethod,
|
||||
Set<? extends Annotation>, EncodedValue> {
|
||||
Set<? extends Annotation>, ArrayEncodedValue> {
|
||||
|
||||
public ClassPool(@Nonnull DexPool dexPool) {
|
||||
super(dexPool);
|
||||
@ -94,6 +96,11 @@ public class ClassPool extends BasePool<String, PoolClassDef> implements ClassSe
|
||||
}
|
||||
|
||||
dexPool.annotationSetSection.intern(field.getAnnotations());
|
||||
|
||||
ArrayEncodedValue staticInitializers = getStaticInitializers(poolClassDef);
|
||||
if (staticInitializers != null) {
|
||||
dexPool.encodedArraySection.intern(staticInitializers);
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<String> methods = new HashSet<String>();
|
||||
@ -240,44 +247,9 @@ public class ClassPool extends BasePool<String, PoolClassDef> implements ClassSe
|
||||
return classDef.getSourceFile();
|
||||
}
|
||||
|
||||
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<Field, EncodedValue> GET_INITIAL_VALUE = new Function<Field, EncodedValue>() {
|
||||
@Override
|
||||
public EncodedValue apply(Field input) {
|
||||
EncodedValue initialValue = input.getInitialValue();
|
||||
if (initialValue == null) {
|
||||
return ImmutableEncodedValueFactory.defaultValueForType(input.getType());
|
||||
}
|
||||
return initialValue;
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable @Override public Collection<? extends EncodedValue> getStaticInitializers(
|
||||
@Nullable @Override public ArrayEncodedValue getStaticInitializers(
|
||||
@Nonnull PoolClassDef classDef) {
|
||||
final SortedSet<Field> sortedStaticFields = classDef.getStaticFields();
|
||||
|
||||
final int lastIndex = CollectionUtils.lastIndexOf(sortedStaticFields, HAS_INITIALIZER);
|
||||
if (lastIndex > -1) {
|
||||
return new AbstractCollection<EncodedValue>() {
|
||||
@Nonnull @Override public Iterator<EncodedValue> iterator() {
|
||||
return FluentIterable.from(sortedStaticFields)
|
||||
.limit(lastIndex+1)
|
||||
.transform(GET_INITIAL_VALUE).iterator();
|
||||
}
|
||||
|
||||
@Override public int size() {
|
||||
return lastIndex+1;
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
return StaticInitializerUtil.getStaticInitializers(classDef.getStaticFields());
|
||||
}
|
||||
|
||||
@Nonnull @Override public Collection<? extends Field> getSortedStaticFields(@Nonnull PoolClassDef classDef) {
|
||||
@ -421,14 +393,6 @@ public class ClassPool extends BasePool<String, PoolClassDef> implements ClassSe
|
||||
return new MutableMethodImplementation(poolMethod.getImplementation());
|
||||
}
|
||||
|
||||
@Override public void setEncodedArrayOffset(@Nonnull PoolClassDef classDef, int offset) {
|
||||
classDef.encodedArrayOffset = offset;
|
||||
}
|
||||
|
||||
@Override public int getEncodedArrayOffset(@Nonnull PoolClassDef classDef) {
|
||||
return classDef.encodedArrayOffset;
|
||||
}
|
||||
|
||||
@Override public void setAnnotationDirectoryOffset(@Nonnull PoolClassDef classDef, int offset) {
|
||||
classDef.annotationDirectoryOffset = offset;
|
||||
}
|
||||
|
@ -54,8 +54,8 @@ public class DexPool extends DexWriter<CharSequence, StringReference, CharSequen
|
||||
MethodProtoReference, FieldReference, MethodReference, PoolClassDef,
|
||||
Annotation, Set<? extends Annotation>,
|
||||
TypeListPool.Key<? extends Collection<? extends CharSequence>>, Field, PoolMethod,
|
||||
EncodedValue, AnnotationElement, StringPool, TypePool, ProtoPool, FieldPool, MethodPool, ClassPool,
|
||||
TypeListPool, AnnotationPool, AnnotationSetPool> {
|
||||
ArrayEncodedValue, EncodedValue, AnnotationElement, StringPool, TypePool, ProtoPool, FieldPool, MethodPool,
|
||||
ClassPool, TypeListPool, AnnotationPool, AnnotationSetPool, EncodedArrayPool> {
|
||||
|
||||
private final Markable[] sections = new Markable[] {
|
||||
stringSection, typeSection, protoSection, fieldSection, methodSection, classSection, typeListSection,
|
||||
@ -244,5 +244,9 @@ public class DexPool extends DexWriter<CharSequence, StringReference, CharSequen
|
||||
@Nonnull @Override public AnnotationSetPool getAnnotationSetSection() {
|
||||
return new AnnotationSetPool(DexPool.this);
|
||||
}
|
||||
|
||||
@Nonnull @Override public EncodedArrayPool getEncodedArraySection() {
|
||||
return new EncodedArrayPool(DexPool.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.value.ArrayEncodedValue;
|
||||
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||
import org.jf.dexlib2.writer.EncodedArraySection;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public class EncodedArrayPool extends BaseOffsetPool<ArrayEncodedValue>
|
||||
implements EncodedArraySection<ArrayEncodedValue, EncodedValue> {
|
||||
|
||||
public EncodedArrayPool(@Nonnull DexPool dexPool) {
|
||||
super(dexPool);
|
||||
}
|
||||
|
||||
public void intern(@Nonnull ArrayEncodedValue arrayEncodedValue) {
|
||||
Integer prev = internedItems.put(arrayEncodedValue, 0);
|
||||
if (prev == null) {
|
||||
for (EncodedValue value: arrayEncodedValue.getValue()) {
|
||||
dexPool.internEncodedValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends EncodedValue> getEncodedValueList(ArrayEncodedValue arrayEncodedValue) {
|
||||
return arrayEncodedValue.getValue();
|
||||
}
|
||||
}
|
@ -50,7 +50,6 @@ class PoolClassDef extends BaseTypeReference implements ClassDef {
|
||||
@Nonnull final ImmutableSortedSet<PoolMethod> virtualMethods;
|
||||
|
||||
int classDefIndex = DexPool.NO_INDEX;
|
||||
int encodedArrayOffset = DexPool.NO_OFFSET;
|
||||
int annotationDirectoryOffset = DexPool.NO_OFFSET;
|
||||
|
||||
PoolClassDef(@Nonnull ClassDef classDef) {
|
||||
|
@ -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.util;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import org.jf.dexlib2.base.value.BaseArrayEncodedValue;
|
||||
import org.jf.dexlib2.iface.Field;
|
||||
import org.jf.dexlib2.iface.value.ArrayEncodedValue;
|
||||
import org.jf.dexlib2.iface.value.EncodedValue;
|
||||
import org.jf.dexlib2.immutable.value.ImmutableEncodedValueFactory;
|
||||
import org.jf.dexlib2.util.EncodedValueUtils;
|
||||
import org.jf.util.AbstractForwardSequentialList;
|
||||
import org.jf.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
|
||||
public class StaticInitializerUtil {
|
||||
|
||||
@Nullable public static ArrayEncodedValue getStaticInitializers(
|
||||
@Nonnull SortedSet<? extends Field> sortedStaticFields) {
|
||||
final int lastIndex = CollectionUtils.lastIndexOf(sortedStaticFields, HAS_INITIALIZER);
|
||||
if (lastIndex > -1) {
|
||||
return new BaseArrayEncodedValue() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<? extends EncodedValue> getValue() {
|
||||
return new AbstractForwardSequentialList<EncodedValue>() {
|
||||
@Nonnull @Override public Iterator<EncodedValue> iterator() {
|
||||
return FluentIterable.from(sortedStaticFields)
|
||||
.limit(lastIndex+1)
|
||||
.transform(GET_INITIAL_VALUE).iterator();
|
||||
}
|
||||
|
||||
@Override public int size() {
|
||||
return lastIndex+1;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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<Field, EncodedValue> GET_INITIAL_VALUE = new Function<Field, EncodedValue>() {
|
||||
@Override
|
||||
public EncodedValue apply(Field input) {
|
||||
EncodedValue initialValue = input.getInitialValue();
|
||||
if (initialValue == null) {
|
||||
return ImmutableEncodedValueFactory.defaultValueForType(input.getType());
|
||||
}
|
||||
return initialValue;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -29,7 +29,9 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.jf.smali;import com.google.common.collect.Lists;
|
||||
package org.jf.smali;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import junit.framework.Assert;
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
@ -47,7 +49,6 @@ import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
import org.jf.dexlib2.iface.value.FieldEncodedValue;
|
||||
import org.jf.dexlib2.iface.value.MethodEncodedValue;
|
||||
import org.jf.dexlib2.iface.value.TypeEncodedValue;
|
||||
import org.jf.smali.SmaliTestUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
Loading…
x
Reference in New Issue
Block a user