1be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver/*
2be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * Copyright 2012, Google Inc.
3be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * All rights reserved.
4be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *
5be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * Redistribution and use in source and binary forms, with or without
6be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * modification, are permitted provided that the following conditions are
7be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * met:
8be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *
9be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *     * Redistributions of source code must retain the above copyright
10be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * notice, this list of conditions and the following disclaimer.
11be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *     * Redistributions in binary form must reproduce the above
12be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * copyright notice, this list of conditions and the following disclaimer
13be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * in the documentation and/or other materials provided with the
14be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * distribution.
15be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *     * Neither the name of Google Inc. nor the names of its
16be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * contributors may be used to endorse or promote products derived from
17be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * this software without specific prior written permission.
18be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver *
19be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver */
31be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
32be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruverpackage org.jf.dexlib2.dexbacked.value;
33be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
34f4662586da3c902c3a0ed21a174b814e248c7fb8Ben Gruverimport org.jf.dexlib2.ValueType;
35f4662586da3c902c3a0ed21a174b814e248c7fb8Ben Gruverimport org.jf.dexlib2.dexbacked.DexReader;
36be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruverimport org.jf.dexlib2.iface.value.EncodedValue;
377c71ad420dbdfe2e36f205d335a261435181a25bBen Gruverimport org.jf.dexlib2.immutable.value.*;
387c71ad420dbdfe2e36f205d335a261435181a25bBen Gruverimport org.jf.dexlib2.util.Preconditions;
397c71ad420dbdfe2e36f205d335a261435181a25bBen Gruverimport org.jf.util.ExceptionWithContext;
40be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
4125d385a441b95d56987c81f00f19297d799e1b31Ben Gruverimport javax.annotation.Nonnull;
4225d385a441b95d56987c81f00f19297d799e1b31Ben Gruver
437c71ad420dbdfe2e36f205d335a261435181a25bBen Gruverpublic abstract class DexBackedEncodedValue {
4425d385a441b95d56987c81f00f19297d799e1b31Ben Gruver    @Nonnull
4525d385a441b95d56987c81f00f19297d799e1b31Ben Gruver    public static EncodedValue readFrom(@Nonnull DexReader reader) {
467c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver        int startOffset = reader.getOffset();
47be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
487c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver        try {
497c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            int b = reader.readUbyte();
507c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            int valueType = b & 0x1f;
517c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            int valueArg = b >>> 5;
52be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
537c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            switch (valueType) {
547c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.BYTE:
557c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 0);
567c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    return new ImmutableByteEncodedValue((byte)reader.readByte());
577c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.SHORT:
587c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 1);
597c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    return new ImmutableShortEncodedValue((short)reader.readSizedInt(valueArg + 1));
607c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.CHAR:
617c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 1);
627c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    return new ImmutableCharEncodedValue((char)reader.readSizedSmallUint(valueArg + 1));
637c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.INT:
647c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 3);
657c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    return new ImmutableIntEncodedValue(reader.readSizedInt(valueArg + 1));
667c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.LONG:
677c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 7);
687c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    return new ImmutableLongEncodedValue(reader.readSizedLong(valueArg + 1));
697c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.FLOAT:
707c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 3);
717c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    return new ImmutableFloatEncodedValue(Float.intBitsToFloat(
72a88239d92d47b45f0e2f9637afeacabcb9e4f3aeBen Gruver                            reader.readSizedRightExtendedInt(valueArg + 1)));
737c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.DOUBLE:
747c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 7);
757c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    return new ImmutableDoubleEncodedValue(Double.longBitsToDouble(
76a88239d92d47b45f0e2f9637afeacabcb9e4f3aeBen Gruver                            reader.readSizedRightExtendedLong(valueArg + 1)));
777c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.STRING:
787c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 3);
7922c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruver                    return new DexBackedStringEncodedValue(reader, valueArg);
807c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.TYPE:
817c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 3);
823c3a3c4af82abff185c0699d536dec5002b4406aBen Gruver                    return new DexBackedTypeEncodedValue(reader, valueArg);
837c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.FIELD:
847c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 3);
8522c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruver                    return new DexBackedFieldEncodedValue(reader, valueArg);
867c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.METHOD:
877c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 3);
8822c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruver                    return new DexBackedMethodEncodedValue(reader, valueArg);
897c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.ENUM:
907c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 3);
9122c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruver                    return new DexBackedEnumEncodedValue(reader, valueArg);
927c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.ARRAY:
937c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 0);
947c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    return new DexBackedArrayEncodedValue(reader);
957c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.ANNOTATION:
967c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 0);
977c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    return new DexBackedAnnotationEncodedValue(reader);
987c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.NULL:
9922c3185bb7c8618437eabe6c597549e0989ec4e6Ben Gruver                    Preconditions.checkValueArg(valueArg, 0);
1007c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    return ImmutableNullEncodedValue.INSTANCE;
1017c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.BOOLEAN:
1027c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    Preconditions.checkValueArg(valueArg, 1);
103bddef6af3c39732ba0329c4a8e233f3858226f39Ben Gruver                    return ImmutableBooleanEncodedValue.forBoolean(valueArg == 1);
1047c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                default:
1057c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType);
1067c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            }
1077c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver        } catch (Exception ex) {
1087c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            throw ExceptionWithContext.withContext(ex, "Error while reading encoded value at offset 0x%x", startOffset);
1097c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver        }
110be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    }
111be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver
11225d385a441b95d56987c81f00f19297d799e1b31Ben Gruver    public static void skipFrom(@Nonnull DexReader reader) {
1137c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver        int startOffset = reader.getOffset();
1147c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver
1157c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver        try {
1167c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            int b = reader.readUbyte();
1177c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            int valueType = b & 0x1f;
1187c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver
1197c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            switch (valueType) {
1207c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.BYTE:
1217c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    reader.skipByte();
1227c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    break;
1237c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.SHORT:
1247c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.CHAR:
1257c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.INT:
1267c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.LONG:
1277c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.FLOAT:
1287c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.DOUBLE:
1297c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.STRING:
1307c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.TYPE:
1317c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.FIELD:
1327c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.METHOD:
1337c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.ENUM:
1347c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    int valueArg = b >>> 5;
13568f69b899ff18bf6ced6249d48dd7f059a51255fBen Gruver                    reader.moveRelative(valueArg+1);
1367c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    break;
1377c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.ARRAY:
1387c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    DexBackedArrayEncodedValue.skipFrom(reader);
1397c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    break;
1407c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.ANNOTATION:
1417c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    DexBackedAnnotationEncodedValue.skipFrom(reader);
1427c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    break;
1437c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.NULL:
1447c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                case ValueType.BOOLEAN:
1457c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    break;
1467c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                default:
1477c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType);
1487c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            }
1497c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver        } catch (Exception ex) {
1507c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver            throw ExceptionWithContext.withContext(ex, "Error while skipping encoded value at offset 0x%x",
1517c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver                    startOffset);
1527c71ad420dbdfe2e36f205d335a261435181a25bBen Gruver        }
153be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver    }
154be799799ff8bbc5d86f8cfdc850947ab4f41695fBen Gruver}
155