EncodedValue.java revision d5f47bae4902560746db40e65874db68d95ee742
1/*
2 * Copyright 2013, 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
32package org.jf.dexlib2.dexbacked.raw;
33
34import org.jf.dexlib2.dexbacked.DexReader;
35import org.jf.dexlib2.util.AnnotatedBytes;
36import org.jf.util.ExceptionWithContext;
37
38import javax.annotation.Nonnull;
39
40public class EncodedValue {
41    public static void annotateEncodedValue(@Nonnull AnnotatedBytes out, @Nonnull DexReader reader) {
42        int valueArgType = reader.readUbyte();
43
44        int valueArg = valueArgType >>> 5;
45        int valueType = valueArgType & 0x1f;
46
47        switch (valueType) {
48            case 0x00:
49                out.annotate(1, "valueArg = %d, valueType = 0x%x: byte", valueArg, valueType);
50                int intValue = reader.readByte();
51                out.annotate(1, "value = 0x%x", intValue);
52                break;
53            case 0x02:
54                out.annotate(1, "valueArg = %d, valueType = 0x%x: short", valueArg, valueType);
55                intValue = reader.readSizedInt(valueArg+1);
56                out.annotate(valueArg + 1, "value = 0x%x", intValue);
57                break;
58            case 0x03:
59                out.annotate(1, "valueArg = %d, valueType = 0x%x: char", valueArg, valueType);
60                intValue = reader.readSizedSmallUint(valueArg+1);
61                out.annotate(valueArg+1, "value = 0x%x", intValue);
62                break;
63            case 0x04:
64                out.annotate(1, "valueArg = %d, valueType = 0x%x: int", valueArg, valueType);
65                intValue = reader.readSizedInt(valueArg+1);
66                out.annotate(valueArg+1, "value = 0x%x", intValue);
67                break;
68            case 0x06:
69                out.annotate(1, "valueArg = %d, valueType = 0x%x: long", valueArg, valueType);
70                long longValue = reader.readSizedLong(valueArg+1);
71                out.annotate(valueArg+1, "value = 0x%x", longValue);
72                break;
73            case 0x10:
74                out.annotate(1, "valueArg = %d, valueType = 0x%x: float", valueArg, valueType);
75                float floatValue = Float.intBitsToFloat(reader.readSizedRightExtendedInt(valueArg + 1));
76                out.annotate(valueArg+1, "value = %f", floatValue);
77                break;
78            case 0x11:
79                out.annotate(1, "valueArg = %d, valueType = 0x%x: double", valueArg, valueType);
80                double doubleValue = Double.longBitsToDouble(reader.readSizedRightExtendedLong(valueArg + 1));
81                out.annotate(valueArg+1, "value = %f", doubleValue);
82                break;
83            case 0x17:
84                out.annotate(1, "valueArg = %d, valueType = 0x%x: string", valueArg, valueType);
85                int stringIndex = reader.readSizedSmallUint(valueArg + 1);
86                out.annotate(valueArg+1, "value = %s",
87                        StringIdItem.getReferenceAnnotation(reader.dexBuf, stringIndex, true));
88                break;
89            case 0x18:
90                out.annotate(1, "valueArg = %d, valueType = 0x%x: type", valueArg, valueType);
91                int typeIndex = reader.readSizedSmallUint(valueArg+1);
92                out.annotate(valueArg+1, "value = %s", TypeIdItem.getReferenceAnnotation(reader.dexBuf, typeIndex));
93                break;
94            case 0x19:
95                out.annotate(1, "valueArg = %d, valueType = 0x%x: field", valueArg, valueType);
96                int fieldIndex = reader.readSizedSmallUint(valueArg+1);
97                out.annotate(valueArg+1, "value = %s", FieldIdItem.getReferenceAnnotation(reader.dexBuf, fieldIndex));
98                break;
99            case 0x1a:
100                out.annotate(1, "valueArg = %d, valueType = 0x%x: method", valueArg, valueType);
101                int methodIndex = reader.readSizedSmallUint(valueArg+1);
102                out.annotate(valueArg+1, "value = %s", MethodIdItem.getReferenceAnnotation(reader.dexBuf, methodIndex));
103                break;
104            case 0x1b:
105                out.annotate(1, "valueArg = %d, valueType = 0x%x: enum", valueArg, valueType);
106                fieldIndex = reader.readSizedSmallUint(valueArg+1);
107                out.annotate(valueArg+1, "value = %s", FieldIdItem.getReferenceAnnotation(reader.dexBuf, fieldIndex));
108                break;
109            case 0x1c:
110                out.annotate(1, "valueArg = %d, valueType = 0x%x: array", valueArg, valueType);
111                annotateEncodedArray(out, reader);
112                break;
113            case 0x1d:
114                out.annotate(1, "valueArg = %d, valueType = 0x%x: annotation", valueArg, valueType);
115                annotateEncodedAnnotation(out, reader);
116                break;
117            case 0x1e:
118                out.annotate(1, "valueArg = %d, valueType = 0x%x: null", valueArg, valueType);
119                break;
120            case 0x1f:
121                out.annotate(1, "valueArg = %d, valueType = 0x%x: boolean, value=%s", valueArg, valueType, valueArg==1);
122                break;
123            default:
124                throw new ExceptionWithContext("Invalid encoded value type 0x%x at offset 0x%x", valueType,
125                        out.getCursor());
126        }
127    }
128
129    public static void annotateEncodedAnnotation(@Nonnull AnnotatedBytes out, @Nonnull DexReader reader) {
130        assert out.getCursor() == reader.getOffset();
131
132        int mark = reader.getOffset();
133        int typeIndex = reader.readSmallUleb128();
134        out.annotate(reader.getOffset() - mark, TypeIdItem.getReferenceAnnotation(reader.dexBuf, typeIndex));
135
136        mark = reader.getOffset();
137        int size = reader.readSmallUleb128();
138        out.annotate(reader.getOffset() - mark, "size: %d", size);
139
140        for (int i=0; i<size; i++) {
141            out.annotate(0, "element[%d]", i);
142            out.indent();
143
144            mark = reader.getOffset();
145            int nameIndex = reader.readSmallUleb128();
146            out.annotate(reader.getOffset() - mark, "name = %s",
147                    StringIdItem.getReferenceAnnotation(reader.dexBuf, nameIndex));
148
149            annotateEncodedValue(out, reader);
150
151            out.deindent();
152        }
153    }
154
155    public static void annotateEncodedArray(@Nonnull AnnotatedBytes out, @Nonnull DexReader reader) {
156        assert out.getCursor() == reader.getOffset();
157
158        int mark = reader.getOffset();
159        int size = reader.readSmallUleb128();
160        out.annotate(reader.getOffset() - mark, "size: %d", size);
161
162        for (int i=0; i<size; i++) {
163            out.annotate(0, "element[%d]", i);
164            out.indent();
165
166            annotateEncodedValue(out, reader);
167
168            out.deindent();
169        }
170    }
171}
172