• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012, Google Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package org.jf.dexlib2.dexbacked.value;
33 
34 import org.jf.dexlib2.ValueType;
35 import org.jf.dexlib2.dexbacked.DexReader;
36 import org.jf.dexlib2.iface.value.EncodedValue;
37 import org.jf.dexlib2.immutable.value.*;
38 import org.jf.dexlib2.util.Preconditions;
39 import org.jf.util.ExceptionWithContext;
40 
41 import javax.annotation.Nonnull;
42 
43 public abstract class DexBackedEncodedValue {
44     @Nonnull
readFrom(@onnull DexReader reader)45     public static EncodedValue readFrom(@Nonnull DexReader reader) {
46         int startOffset = reader.getOffset();
47 
48         try {
49             int b = reader.readUbyte();
50             int valueType = b & 0x1f;
51             int valueArg = b >>> 5;
52 
53             switch (valueType) {
54                 case ValueType.BYTE:
55                     Preconditions.checkValueArg(valueArg, 0);
56                     return new ImmutableByteEncodedValue((byte)reader.readByte());
57                 case ValueType.SHORT:
58                     Preconditions.checkValueArg(valueArg, 1);
59                     return new ImmutableShortEncodedValue((short)reader.readSizedInt(valueArg + 1));
60                 case ValueType.CHAR:
61                     Preconditions.checkValueArg(valueArg, 1);
62                     return new ImmutableCharEncodedValue((char)reader.readSizedSmallUint(valueArg + 1));
63                 case ValueType.INT:
64                     Preconditions.checkValueArg(valueArg, 3);
65                     return new ImmutableIntEncodedValue(reader.readSizedInt(valueArg + 1));
66                 case ValueType.LONG:
67                     Preconditions.checkValueArg(valueArg, 7);
68                     return new ImmutableLongEncodedValue(reader.readSizedLong(valueArg + 1));
69                 case ValueType.FLOAT:
70                     Preconditions.checkValueArg(valueArg, 3);
71                     return new ImmutableFloatEncodedValue(Float.intBitsToFloat(
72                             reader.readSizedRightExtendedInt(valueArg + 1)));
73                 case ValueType.DOUBLE:
74                     Preconditions.checkValueArg(valueArg, 7);
75                     return new ImmutableDoubleEncodedValue(Double.longBitsToDouble(
76                             reader.readSizedRightExtendedLong(valueArg + 1)));
77                 case ValueType.STRING:
78                     Preconditions.checkValueArg(valueArg, 3);
79                     return new DexBackedStringEncodedValue(reader, valueArg);
80                 case ValueType.TYPE:
81                     Preconditions.checkValueArg(valueArg, 3);
82                     return new DexBackedTypeEncodedValue(reader, valueArg);
83                 case ValueType.FIELD:
84                     Preconditions.checkValueArg(valueArg, 3);
85                     return new DexBackedFieldEncodedValue(reader, valueArg);
86                 case ValueType.METHOD:
87                     Preconditions.checkValueArg(valueArg, 3);
88                     return new DexBackedMethodEncodedValue(reader, valueArg);
89                 case ValueType.ENUM:
90                     Preconditions.checkValueArg(valueArg, 3);
91                     return new DexBackedEnumEncodedValue(reader, valueArg);
92                 case ValueType.ARRAY:
93                     Preconditions.checkValueArg(valueArg, 0);
94                     return new DexBackedArrayEncodedValue(reader);
95                 case ValueType.ANNOTATION:
96                     Preconditions.checkValueArg(valueArg, 0);
97                     return new DexBackedAnnotationEncodedValue(reader);
98                 case ValueType.NULL:
99                     Preconditions.checkValueArg(valueArg, 0);
100                     return ImmutableNullEncodedValue.INSTANCE;
101                 case ValueType.BOOLEAN:
102                     Preconditions.checkValueArg(valueArg, 1);
103                     return ImmutableBooleanEncodedValue.forBoolean(valueArg == 1);
104                 default:
105                     throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType);
106             }
107         } catch (Exception ex) {
108             throw ExceptionWithContext.withContext(ex, "Error while reading encoded value at offset 0x%x", startOffset);
109         }
110     }
111 
skipFrom(@onnull DexReader reader)112     public static void skipFrom(@Nonnull DexReader reader) {
113         int startOffset = reader.getOffset();
114 
115         try {
116             int b = reader.readUbyte();
117             int valueType = b & 0x1f;
118 
119             switch (valueType) {
120                 case ValueType.BYTE:
121                     reader.skipByte();
122                     break;
123                 case ValueType.SHORT:
124                 case ValueType.CHAR:
125                 case ValueType.INT:
126                 case ValueType.LONG:
127                 case ValueType.FLOAT:
128                 case ValueType.DOUBLE:
129                 case ValueType.STRING:
130                 case ValueType.TYPE:
131                 case ValueType.FIELD:
132                 case ValueType.METHOD:
133                 case ValueType.ENUM:
134                     int valueArg = b >>> 5;
135                     reader.moveRelative(valueArg+1);
136                     break;
137                 case ValueType.ARRAY:
138                     DexBackedArrayEncodedValue.skipFrom(reader);
139                     break;
140                 case ValueType.ANNOTATION:
141                     DexBackedAnnotationEncodedValue.skipFrom(reader);
142                     break;
143                 case ValueType.NULL:
144                 case ValueType.BOOLEAN:
145                     break;
146                 default:
147                     throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType);
148             }
149         } catch (Exception ex) {
150             throw ExceptionWithContext.withContext(ex, "Error while skipping encoded value at offset 0x%x",
151                     startOffset);
152         }
153     }
154 }
155