blob: 17f801321e8166eec29d9762982ba9d05c85554b [file] [log] [blame]
Ben Gruver83f77f52013-04-17 22:32:08 -07001/*
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;
33
34import com.google.common.collect.Maps;
Ben Gruver3ff884b2015-07-12 12:52:57 -070035import com.google.common.collect.RangeMap;
Ben Gruver83f77f52013-04-17 22:32:08 -070036
Ben Gruver3ff884b2015-07-12 12:52:57 -070037import javax.annotation.Nonnull;
Ben Gruver83f77f52013-04-17 22:32:08 -070038import javax.annotation.Nullable;
Ben Gruver3ff884b2015-07-12 12:52:57 -070039import java.util.EnumMap;
Ben Gruver83f77f52013-04-17 22:32:08 -070040import java.util.HashMap;
41
42public class Opcodes {
Ben Gruver83f77f52013-04-17 22:32:08 -070043
Ben Gruver3ff884b2015-07-12 12:52:57 -070044 /**
45 * Either the api level for dalvik opcodes, or the art version for art opcodes
46 */
47 public final int api;
48 public final int artVersion;
49 @Nonnull private final Opcode[] opcodesByValue = new Opcode[255];
50 @Nonnull private final EnumMap<Opcode, Short> opcodeValues;
51 @Nonnull private final HashMap<String, Opcode> opcodesByName;
52
53 @Nonnull
54 public static Opcodes forApi(int api) {
55 return new Opcodes(api, VersionMap.mapApiToArtVersion(api), false);
56 }
57
58 @Nonnull
59 public static Opcodes forApi(int api, boolean experimental) {
60 return new Opcodes(api, VersionMap.mapApiToArtVersion(api), experimental);
61 }
62
63 @Nonnull
64 public static Opcodes forArtVersion(int artVersion) {
65 return forArtVersion(artVersion, false);
66 }
67
68 @Nonnull
69 public static Opcodes forArtVersion(int artVersion, boolean experimental) {
70 return new Opcodes(VersionMap.mapArtVersionToApi(artVersion), artVersion, experimental);
71 }
72
73 @Deprecated
Ben Gruver3065d6b2015-06-18 17:44:30 -070074 public Opcodes(int api) {
75 this(api, false);
76 }
77
Ben Gruver3ff884b2015-07-12 12:52:57 -070078 @Deprecated
Igor Murashkin144951a2015-02-18 17:38:30 -080079 public Opcodes(int api, boolean experimental) {
Ben Gruver3ff884b2015-07-12 12:52:57 -070080 this(api, VersionMap.mapApiToArtVersion(api), experimental);
81 }
82
83 private Opcodes(int api, int artVersion, boolean experimental) {
84 this.api = api;
85 this.artVersion = artVersion;
86
87 opcodeValues = new EnumMap<Opcode, Short>(Opcode.class);
Ben Gruver83f77f52013-04-17 22:32:08 -070088 opcodesByName = Maps.newHashMap();
89
Ben Gruver3ff884b2015-07-12 12:52:57 -070090 int version;
91 if (isArt()) {
92 version = artVersion;
93 } else {
94 version = api;
95 }
96
Ben Gruver83f77f52013-04-17 22:32:08 -070097 for (Opcode opcode: Opcode.values()) {
Ben Gruver3ff884b2015-07-12 12:52:57 -070098 RangeMap<Integer, Short> versionToValueMap;
99
100 if (isArt()) {
101 versionToValueMap = opcode.artVersionToValueMap;
102 } else {
103 versionToValueMap = opcode.apiToValueMap;
104 }
105
106 Short opcodeValue = versionToValueMap.get(version);
107 if (opcodeValue != null && (!opcode.isExperimental() || experimental)) {
108 if (!opcode.format.isPayloadFormat) {
109 opcodesByValue[opcodeValue] = opcode;
Ben Gruver83f77f52013-04-17 22:32:08 -0700110 }
Ben Gruver3ff884b2015-07-12 12:52:57 -0700111 opcodeValues.put(opcode, opcodeValue);
112 opcodesByName.put(opcode.name.toLowerCase(), opcode);
Ben Gruver83f77f52013-04-17 22:32:08 -0700113 }
114 }
115 }
116
117 @Nullable
Ben Gruver3ff884b2015-07-12 12:52:57 -0700118 public Opcode getOpcodeByName(@Nonnull String opcodeName) {
Ben Gruver83f77f52013-04-17 22:32:08 -0700119 return opcodesByName.get(opcodeName.toLowerCase());
120 }
121
122 @Nullable
123 public Opcode getOpcodeByValue(int opcodeValue) {
124 switch (opcodeValue) {
125 case 0x100:
126 return Opcode.PACKED_SWITCH_PAYLOAD;
127 case 0x200:
128 return Opcode.SPARSE_SWITCH_PAYLOAD;
129 case 0x300:
130 return Opcode.ARRAY_PAYLOAD;
131 default:
Ben Gruverd7cd5232013-11-26 17:34:52 -0800132 if (opcodeValue >= 0 && opcodeValue < opcodesByValue.length) {
133 return opcodesByValue[opcodeValue];
134 }
135 return null;
Ben Gruver83f77f52013-04-17 22:32:08 -0700136 }
137 }
Ben Gruver3ff884b2015-07-12 12:52:57 -0700138
139 @Nullable
140 public Short getOpcodeValue(@Nonnull Opcode opcode) {
141 return opcodeValues.get(opcode);
142 }
143
144 public boolean isArt() {
145 return artVersion != VersionMap.NO_VERSION;
146 }
Ben Gruver83f77f52013-04-17 22:32:08 -0700147}