1 /* 2 * Copyright 2013, Google LLC 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google LLC nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 package com.android.tools.smali.dexlib2.writer; 32 33 import com.android.tools.smali.dexlib2.ValueType; 34 import com.android.tools.smali.dexlib2.base.BaseAnnotationElement; 35 import com.android.tools.smali.dexlib2.iface.reference.FieldReference; 36 import com.android.tools.smali.dexlib2.iface.reference.MethodHandleReference; 37 import com.android.tools.smali.dexlib2.iface.reference.MethodReference; 38 import com.android.tools.smali.util.CollectionUtils; 39 40 import javax.annotation.Nonnull; 41 import java.io.IOException; 42 import java.util.ArrayList; 43 import java.util.List; 44 import java.util.Collection; 45 import java.util.Collections; 46 47 public abstract class EncodedValueWriter<StringKey, TypeKey, FieldRefKey extends FieldReference, 48 MethodRefKey extends MethodReference, AnnotationElement extends com.android.tools.smali.dexlib2.iface.AnnotationElement, 49 ProtoRefKey, MethodHandleKey extends MethodHandleReference, EncodedValue> { 50 @Nonnull private final DexDataWriter writer; 51 @Nonnull private final StringSection<StringKey, ?> stringSection; 52 @Nonnull private final TypeSection<?, TypeKey, ?> typeSection; 53 @Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection; 54 @Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection; 55 @Nonnull private final ProtoSection<?, ?, ProtoRefKey, ?> protoSection; 56 @Nonnull private final MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection; 57 @Nonnull private final AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection; 58 EncodedValueWriter( @onnull DexDataWriter writer, @Nonnull StringSection<StringKey, ?> stringSection, @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)59 public EncodedValueWriter( 60 @Nonnull DexDataWriter writer, 61 @Nonnull StringSection<StringKey, ?> stringSection, 62 @Nonnull TypeSection<?, TypeKey, ?> typeSection, 63 @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, 64 @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, 65 ProtoSection<?, ?, ProtoRefKey, ?> protoSection, 66 MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection, 67 @Nonnull AnnotationSection<StringKey, TypeKey, ?, AnnotationElement, EncodedValue> annotationSection) { 68 this.writer = writer; 69 this.stringSection = stringSection; 70 this.typeSection = typeSection; 71 this.fieldSection = fieldSection; 72 this.methodSection = methodSection; 73 this.protoSection = protoSection; 74 this.methodHandleSection = methodHandleSection; 75 this.annotationSection = annotationSection; 76 } 77 writeEncodedValue(@onnull EncodedValue encodedValue)78 protected abstract void writeEncodedValue(@Nonnull EncodedValue encodedValue) throws IOException; 79 writeAnnotation(TypeKey annotationType, Collection<? extends AnnotationElement> elements)80 public void writeAnnotation(TypeKey annotationType, 81 Collection<? extends AnnotationElement> elements) throws IOException { 82 writer.writeEncodedValueHeader(ValueType.ANNOTATION, 0); 83 writer.writeUleb128(typeSection.getItemIndex(annotationType)); 84 writer.writeUleb128(elements.size()); 85 86 List<? extends AnnotationElement> sortedElements = CollectionUtils.immutableSortedCopy( 87 elements, BaseAnnotationElement.BY_NAME); 88 89 for (AnnotationElement element: sortedElements) { 90 writer.writeUleb128(stringSection.getItemIndex(annotationSection.getElementName(element))); 91 writeEncodedValue(annotationSection.getElementValue(element)); 92 } 93 } 94 writeArray(Collection<? extends EncodedValue> elements)95 public void writeArray(Collection<? extends EncodedValue> elements) throws IOException { 96 writer.writeEncodedValueHeader(ValueType.ARRAY, 0); 97 writer.writeUleb128(elements.size()); 98 for (EncodedValue element: elements) { 99 writeEncodedValue(element); 100 } 101 } 102 writeBoolean(boolean value)103 public void writeBoolean(boolean value) throws IOException { 104 writer.writeEncodedValueHeader(ValueType.BOOLEAN, value ? 1 : 0); 105 } 106 writeByte(byte value)107 public void writeByte(byte value) throws IOException { 108 writer.writeEncodedInt(ValueType.BYTE, value); 109 } 110 writeChar(char value)111 public void writeChar(char value) throws IOException { 112 writer.writeEncodedUint(ValueType.CHAR, value); 113 } 114 writeDouble(double value)115 public void writeDouble(double value) throws IOException { 116 writer.writeEncodedDouble(ValueType.DOUBLE, value); 117 } 118 writeEnum(@onnull FieldRefKey value)119 public void writeEnum(@Nonnull FieldRefKey value) throws IOException { 120 writer.writeEncodedUint(ValueType.ENUM, fieldSection.getItemIndex(value)); 121 } 122 writeField(@onnull FieldRefKey value)123 public void writeField(@Nonnull FieldRefKey value) throws IOException { 124 writer.writeEncodedUint(ValueType.FIELD, fieldSection.getItemIndex(value)); 125 } 126 writeFloat(float value)127 public void writeFloat(float value) throws IOException { 128 writer.writeEncodedFloat(ValueType.FLOAT, value); 129 } 130 writeInt(int value)131 public void writeInt(int value) throws IOException { 132 writer.writeEncodedInt(ValueType.INT, value); 133 } 134 writeLong(long value)135 public void writeLong(long value) throws IOException { 136 writer.writeEncodedLong(ValueType.LONG, value); 137 } 138 writeMethod(@onnull MethodRefKey value)139 public void writeMethod(@Nonnull MethodRefKey value) throws IOException { 140 writer.writeEncodedUint(ValueType.METHOD, methodSection.getItemIndex(value)); 141 } 142 writeNull()143 public void writeNull() throws IOException { 144 writer.write(ValueType.NULL); 145 } 146 writeShort(int value)147 public void writeShort(int value) throws IOException { 148 writer.writeEncodedInt(ValueType.SHORT, value); 149 } 150 writeString(@onnull StringKey value)151 public void writeString(@Nonnull StringKey value) throws IOException { 152 writer.writeEncodedUint(ValueType.STRING, stringSection.getItemIndex(value)); 153 } 154 writeType(@onnull TypeKey value)155 public void writeType(@Nonnull TypeKey value) throws IOException { 156 writer.writeEncodedUint(ValueType.TYPE, typeSection.getItemIndex(value)); 157 } 158 writeMethodType(@onnull ProtoRefKey value)159 public void writeMethodType(@Nonnull ProtoRefKey value) throws IOException { 160 writer.writeEncodedUint(ValueType.METHOD_TYPE, protoSection.getItemIndex(value)); 161 } 162 writeMethodHandle(@onnull MethodHandleKey value)163 public void writeMethodHandle(@Nonnull MethodHandleKey value) throws IOException { 164 writer.writeEncodedUint(ValueType.METHOD_HANDLE, methodHandleSection.getItemIndex(value)); 165 } 166 } 167