1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package art; 18 19 import java.lang.reflect.Constructor; 20 import java.lang.reflect.Executable; 21 import java.lang.Integer; 22 import java.nio.ByteBuffer; 23 import java.util.Arrays; 24 import java.util.ArrayList; 25 import java.util.Base64; 26 import java.util.HashSet; 27 import java.util.Set; 28 29 public class Test1911 { 30 // Class/dex file containing the following class. 31 // 32 // CLASS_BYTES generated with java version 17.0.4.1: javac -g art/Target.java 33 // DEX_BYTES generated with d8 version 8.3.7-dev: d8 --debug art/Target.class 34 // 35 // package art; 36 // import java.util.ArrayList; 37 // public class Target { 38 // public int zzz; 39 // public Target(int xxx) { 40 // int q = xxx * 4; 41 // zzz = q; 42 // } 43 // public static void doNothing(Object... objs) { doNothing(objs); } 44 // public void doSomething(int x) { 45 // doNothing(this); 46 // int y = x + 3; 47 // for (int z = 0; z < y * x; z++) { 48 // float q = y - z; 49 // double i = 0.3d * q; 50 // doNothing(q, i); 51 // } 52 // Object o = new Object(); 53 // ArrayList<Integer> i = new ArrayList<>(); 54 // int p = 4 | x; 55 // long q = 3 * p; 56 // doNothing(p, q, o, i); 57 // } 58 // public void testGenericParameters(ArrayList<Integer> array, int i, Integer val) { 59 // array.set(i, val); 60 // } 61 // } 62 public static byte[] CLASS_BYTES = Base64.getDecoder().decode( 63 "yv66vgAAADcAUQoABAA2CQAOADcKAA4AOAcAOQY/0zMzMzMzMwoAOgA7CgA8AD0HAD4KAAkANgoA" + 64 "PwBACgBBAEIKAAkAQwcARAEAA3p6egEAAUkBAAY8aW5pdD4BAAQoSSlWAQAEQ29kZQEAD0xpbmVO" + 65 "dW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAAxMYXJ0L1RhcmdldDsBAAN4" + 66 "eHgBAAFxAQAJZG9Ob3RoaW5nAQAWKFtMamF2YS9sYW5nL09iamVjdDspVgEABG9ianMBABNbTGph" + 67 "dmEvbGFuZy9PYmplY3Q7AQALZG9Tb21ldGhpbmcBAAFGAQABaQEAAUQBAAF6AQABeAEAAXkBAAFv" + 68 "AQASTGphdmEvbGFuZy9PYmplY3Q7AQAVTGphdmEvdXRpbC9BcnJheUxpc3Q7AQABcAEAAUoBABZM" + 69 "b2NhbFZhcmlhYmxlVHlwZVRhYmxlAQAqTGphdmEvdXRpbC9BcnJheUxpc3Q8TGphdmEvbGFuZy9J" + 70 "bnRlZ2VyOz47AQANU3RhY2tNYXBUYWJsZQEAFXRlc3RHZW5lcmljUGFyYW1ldGVycwEALChMamF2" + 71 "YS91dGlsL0FycmF5TGlzdDtJTGphdmEvbGFuZy9JbnRlZ2VyOylWAQAFYXJyYXkBAAN2YWwBABNM" + 72 "amF2YS9sYW5nL0ludGVnZXI7AQAJU2lnbmF0dXJlAQBBKExqYXZhL3V0aWwvQXJyYXlMaXN0PExq" + 73 "YXZhL2xhbmcvSW50ZWdlcjs+O0lMamF2YS9sYW5nL0ludGVnZXI7KVYBAApTb3VyY2VGaWxlAQAL" + 74 "VGFyZ2V0LmphdmEMABEARQwADwAQDAAaABsBABBqYXZhL2xhbmcvT2JqZWN0BwBGDABHAEgHAEkM" + 75 "AEcASgEAE2phdmEvdXRpbC9BcnJheUxpc3QHAEsMAEcATAcATQwARwBODABPAFABAAphcnQvVGFy" + 76 "Z2V0AQADKClWAQAPamF2YS9sYW5nL0Zsb2F0AQAHdmFsdWVPZgEAFChGKUxqYXZhL2xhbmcvRmxv" + 77 "YXQ7AQAQamF2YS9sYW5nL0RvdWJsZQEAFShEKUxqYXZhL2xhbmcvRG91YmxlOwEAEWphdmEvbGFu" + 78 "Zy9JbnRlZ2VyAQAWKEkpTGphdmEvbGFuZy9JbnRlZ2VyOwEADmphdmEvbGFuZy9Mb25nAQATKEop" + 79 "TGphdmEvbGFuZy9Mb25nOwEAA3NldAEAJyhJTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcv" + 80 "T2JqZWN0OwAhAA4ABAAAAAEAAQAPABAAAAAEAAEAEQASAAEAEwAAAFgAAgADAAAADiq3AAEbB2g9" + 81 "Khy1AAKxAAAAAgAUAAAAEgAEAAAACAAEAAkACAAKAA0ACwAVAAAAIAADAAAADgAWABcAAAAAAA4A" + 82 "GAAQAAEACAAGABkAEAACAIkAGgAbAAEAEwAAAC8AAQABAAAABSq4AAOxAAAAAgAUAAAABgABAAAA" + 83 "DQAVAAAADAABAAAABQAcAB0AAAABAB4AEgABABMAAAFYAAUACAAAAIIEvQAEWQMqU7gAAxsGYD0D" + 84 "Ph0cG2iiAC8cHWSGOAQUAAUXBI1rOQUFvQAEWQMXBLgAB1NZBBgFuAAIU7gAA4QDAaf/0LsABFm3" + 85 "AAFOuwAJWbcACjoEBxuANgUGFQVohTcGB70ABFkDFQW4AAtTWQQWBrgADFNZBS1TWQYZBFO4AAOx" + 86 "AAAABAAUAAAANgANAAAAEAALABEADwASABgAEwAeABQAJwAVAD4AEgBEABcATAAYAFUAGQBaABoA" + 87 "YQAbAIEAHAAVAAAAZgAKAB4AIAAZAB8ABAAnABcAIAAhAAUAEQAzACIAEAADAAAAggAWABcAAAAA" + 88 "AIIAIwAQAAEADwBzACQAEAACAEwANgAlACYAAwBVAC0AIAAnAAQAWgAoACgAEAAFAGEAIQAZACkA" + 89 "BgAqAAAADAABAFUALQAgACsABAAsAAAACgAC/QARAQH6ADIAAQAtAC4AAgATAAAAZgADAAQAAAAI" + 90 "KxwttgANV7EAAAADABQAAAAKAAIAAAAfAAcAIAAVAAAAKgAEAAAACAAWABcAAAAAAAgALwAnAAEA" + 91 "AAAIACAAEAACAAAACAAwADEAAwAqAAAADAABAAAACAAvACsAAQAyAAAAAgAzAAEANAAAAAIANQ=="); 92 public static byte[] DEX_BYTES = Base64.getDecoder().decode( 93 "ZGV4CjAzNQAALyjG3vy0POIlfGUh9Q7yf3NFwlp6VbWoBwAAcAAAAHhWNBIAAAAAAAAAAOQGAAAz" + 94 "AAAAcAAAAA8AAAA8AQAACgAAAHgBAAABAAAA8AEAAAwAAAD4AQAAAQAAAFgCAAAwBQAAeAIAACIE" + 95 "AAAlBAAAKQQAADEEAAA2BAAAOQQAADwEAAA/BAAAQgQAAEYEAABKBAAATgQAAFMEAABXBAAAZQQA" + 96 "AIQEAACYBAAAqwQAAMAEAADSBAAA5gQAAP0EAAAUBQAAQAUAAE0FAABQBQAAVAUAAFgFAABeBQAA" + 97 "YQUAAGUFAAB6BQAAgQUAAIwFAACZBQAAnAUAAKMFAACmBQAArAUAAK8FAACyBQAAtwUAAM4FAADT" + 98 "BQAA2gUAAOMFAADmBQAA6wUAAO4FAADxBQAA9gUAAAQAAAAFAAAABgAAAAcAAAANAAAADgAAAA8A" + 99 "AAAQAAAAEQAAABIAAAATAAAAFAAAABgAAAAcAAAAHgAAAAgAAAAGAAAA6AMAAAkAAAAHAAAA8AMA" + 100 "AAoAAAAIAAAA+AMAAAwAAAAJAAAAAAQAAAsAAAAKAAAACAQAABgAAAAMAAAAAAAAABkAAAAMAAAA" + 101 "+AMAABsAAAAMAAAAEAQAABoAAAAMAAAAHAQAAB0AAAANAAAA6AMAAAQAAgAxAAAABAAGAAIAAAAE" + 102 "AAgAIAAAAAQABgAhAAAABAAHACkAAAAGAAkAIwAAAAYAAAAsAAAABwABACwAAAAIAAIALAAAAAkA" + 103 "AwAsAAAACgAFAAIAAAALAAUAAgAAAAsABAAoAAAABAAAAAEAAAAKAAAAAAAAABcAAADMBgAApgYA" + 104 "AAAAAAADAAIAAQAAAIwDAAAIAAAAcBAJAAEA2gACBFkQAAAOAAEAAQABAAAAmAMAAAQAAABxEAEA" + 105 "AAAOAA4AAgACAAAAnQMAAFoAAAASECMBDgASAk0MAQJxEAEAAQDYAQ0DEgOSBAENEiU1QyQAkQQB" + 106 "A4JEGAYzMzMzMzPTP4lIcSAEAJgArQgIBnEQBgAEAAwGcSAFAJgADAcjVQ4ATQYFAk0HBQBxEAEA" + 107 "BQDYAwMBKNoiAwoAcBAJAAMAIgQLAHAQCgAEAN4GDQTaBwYDgXdxEAcABgAMCXEgCACHAAwKEksj" + 108 "uw4ATQkLAk0KCwBNAwsFEjBNBAsAcRABAAsADgAEAAQAAwAAANsDAAAEAAAAbjALACEDDgAIAS8O" + 109 "PC0DACgDLQANASYOABABLg6WLQMBMAMBAQMDMQNaPAMEKAK0AwgjAQERCwUEBQhABQNaAwMlC1oE" + 110 "BCMMFy0DBicDPAMHKAQBFw8AHwMAIysOBAEgDBc8AAEAAAAAAAAAAQAAAAEAAAABAAAAAgAAAAEA" + 111 "AAADAAAAAgAAAAIACgADAAAACwACAAgAAAABAAAADgABKAACKVYABjxpbml0PgADPjtJAAFEAAFG" + 112 "AAFJAAFKAAJMRAACTEYAAkxJAANMSUwAAkxKAAxMYXJ0L1RhcmdldDsAHUxkYWx2aWsvYW5ub3Rh" + 113 "dGlvbi9TaWduYXR1cmU7ABJMamF2YS9sYW5nL0RvdWJsZTsAEUxqYXZhL2xhbmcvRmxvYXQ7ABNM" + 114 "amF2YS9sYW5nL0ludGVnZXI7ABBMamF2YS9sYW5nL0xvbmc7ABJMamF2YS9sYW5nL09iamVjdDsA" + 115 "FUxqYXZhL3V0aWwvQXJyYXlMaXN0OwAVTGphdmEvdXRpbC9BcnJheUxpc3Q8ACpMamF2YS91dGls" + 116 "L0FycmF5TGlzdDxMamF2YS9sYW5nL0ludGVnZXI7PjsAC1RhcmdldC5qYXZhAAFWAAJWSQACVkwA" + 117 "BFZMSUwAAVoAAlpEABNbTGphdmEvbGFuZy9PYmplY3Q7AAVhcnJheQAJZG9Ob3RoaW5nAAtkb1Nv" + 118 "bWV0aGluZwABaQAFaXNOYU4AAW8ABG9ianMAAXAAAXEAA3NldAAVdGVzdEdlbmVyaWNQYXJhbWV0" + 119 "ZXJzAAN2YWwABXZhbHVlAAd2YWx1ZU9mAAF4AAN4eHgAAXkAAXoAA3p6egCbAX5+RDh7ImJhY2tl" + 120 "bmQiOiJkZXgiLCJjb21waWxhdGlvbi1tb2RlIjoiZGVidWciLCJoYXMtY2hlY2tzdW1zIjpmYWxz" + 121 "ZSwibWluLWFwaSI6MSwic2hhLTEiOiIzMTAxYWQ2Zjc0ZWUyMzI1MjhkZmM2NmEyNjE3YTkzODM4" + 122 "NGU2NmVhIiwidmVyc2lvbiI6IjguMy43LWRldiJ9AAIFASscBhcAFxUXERcDFxEXAQABAgIAAQCB" + 123 "gAT4BAGJAZgFAgGwBQEB9AYAAAAAAAEAAACUBgAAwAYAAAAAAAABAAAAAAAAAAMAAADEBgAAEAAA" + 124 "AAAAAAABAAAAAAAAAAEAAAAzAAAAcAAAAAIAAAAPAAAAPAEAAAMAAAAKAAAAeAEAAAQAAAABAAAA" + 125 "8AEAAAUAAAAMAAAA+AEAAAYAAAABAAAAWAIAAAEgAAAEAAAAeAIAAAMgAAAEAAAAjAMAAAEQAAAH" + 126 "AAAA6AMAAAIgAAAzAAAAIgQAAAQgAAABAAAAlAYAAAAgAAABAAAApgYAAAMQAAACAAAAwAYAAAYg" + 127 "AAABAAAAzAYAAAAQAAABAAAA5AYAAA=="); 128 129 // The variables of the functions in the above Target class. 130 public static Set<Locals.VariableDescription>[] CONSTRUCTOR_VARIABLES = new Set[] { 131 // RI Local variable table 132 new HashSet<>(Arrays.asList( 133 new Locals.VariableDescription(8, 6, "q", "I", null, 2), 134 new Locals.VariableDescription(0, 14, "xxx", "I", null, 1), 135 new Locals.VariableDescription(0, 14, "this", "Lart/Target;", null, 0))), 136 // ART Local variable table 137 new HashSet<>(Arrays.asList( 138 new Locals.VariableDescription(0, 8, "this", "Lart/Target;", null, 1), 139 new Locals.VariableDescription(5, 3, "q", "I", null, 0), 140 new Locals.VariableDescription(0, 8, "xxx", "I", null, 2))), 141 }; 142 143 public static Set<Locals.VariableDescription>[] DO_NOTHING_VARIABLES = new Set[] { 144 // RI Local variable table 145 new HashSet<>(Arrays.asList( 146 new Locals.VariableDescription(0, 5, "objs", "[Ljava/lang/Object;", null, 0))), 147 // ART Local variable table 148 new HashSet<>(Arrays.asList( 149 new Locals.VariableDescription(0, 4, "objs", "[Ljava/lang/Object;", null, 0))), 150 }; 151 152 public static Set<Locals.VariableDescription>[] DO_SOMETHING_VARIABLES = new Set[] { 153 // RI Local variable table 154 new HashSet<>(Arrays.asList( 155 new Locals.VariableDescription(0, 130, "x", "I", null, 1), 156 new Locals.VariableDescription(76, 54, "o", "Ljava/lang/Object;", null, 3), 157 new Locals.VariableDescription(30, 32, "q", "F", null, 4), 158 new Locals.VariableDescription(39, 23, "i", "D", null, 5), 159 new Locals.VariableDescription(17, 51, "z", "I", null, 3), 160 new Locals.VariableDescription(15, 115, "y", "I", null, 2), 161 new Locals.VariableDescription(90, 40, "p", "I", null, 5), 162 new Locals.VariableDescription(97, 33, "q", "J", null, 6), 163 new Locals.VariableDescription(0, 130, "this", "Lart/Target;", null, 0), 164 new Locals.VariableDescription(85, 165 45, 166 "i", 167 "Ljava/util/ArrayList;", 168 "Ljava/util/ArrayList<Ljava/lang/Integer;>;", 169 4))), 170 // ART Local variable table 171 new HashSet<>(Arrays.asList( 172 new Locals.VariableDescription(20, 28, "q", "F", null, 4), 173 new Locals.VariableDescription(56, 34, "o", "Ljava/lang/Object;", null, 3), 174 new Locals.VariableDescription(0, 90, "this", "Lart/Target;", null, 12), 175 new Locals.VariableDescription(12, 39, "z", "I", null, 3), 176 new Locals.VariableDescription(11, 79, "y", "I", null, 1), 177 new Locals.VariableDescription(63, 27, "p", "I", null, 6), 178 new Locals.VariableDescription(0, 90, "x", "I", null, 13), 179 new Locals.VariableDescription(31, 17, "i", "D", null, 8), 180 new Locals.VariableDescription(66, 24, "q", "J", null, 7), 181 new Locals.VariableDescription(61, 182 29, 183 "i", 184 "Ljava/util/ArrayList;", 185 "Ljava/util/ArrayList<Ljava/lang/Integer;>;", 186 4))), 187 }; 188 189 public static Set<Locals.VariableDescription>[] TEST_GENERIC_PARAMETERS_VARIABLES = new Set[] { 190 // RI Local variable table 191 new HashSet<>(Arrays.asList( 192 new Locals.VariableDescription(0, 8, "this", "Lart/Target;", null, 0), 193 new Locals.VariableDescription(0, 194 8, 195 "array", 196 "Ljava/util/ArrayList;", 197 "Ljava/util/ArrayList<Ljava/lang/Integer;>;", 198 1), 199 new Locals.VariableDescription(0, 8, "i", "I", null, 2), 200 new Locals.VariableDescription(0, 8, "val", "Ljava/lang/Integer;", null, 3))), 201 // ART Local variable table 202 new HashSet<>(Arrays.asList( 203 new Locals.VariableDescription(0, 4, "this", "Lart/Target;", null, 0), 204 new Locals.VariableDescription(0, 205 4, 206 "array", 207 "Ljava/util/ArrayList;", 208 "Ljava/util/ArrayList<Ljava/lang/Integer;>;", 209 1), 210 new Locals.VariableDescription(0, 4, "i", "I", null, 2), 211 new Locals.VariableDescription(0, 4, "val", "Ljava/lang/Integer;", null, 3))), 212 }; 213 214 215 // Get a classloader that can load the Target class. getClassLoader()216 public static ClassLoader getClassLoader() throws Exception { 217 try { 218 Class<?> class_loader_class = Class.forName("dalvik.system.InMemoryDexClassLoader"); 219 Constructor<?> ctor = class_loader_class.getConstructor(ByteBuffer.class, ClassLoader.class); 220 // We are on art since we got the InMemoryDexClassLoader. 221 return (ClassLoader)ctor.newInstance( 222 ByteBuffer.wrap(DEX_BYTES), Test1911.class.getClassLoader()); 223 } catch (ClassNotFoundException e) { 224 // Running on RI. 225 return new ClassLoader(Test1911.class.getClassLoader()) { 226 protected Class<?> findClass(String name) throws ClassNotFoundException { 227 if (name.equals("art.Target")) { 228 return defineClass(name, CLASS_BYTES, 0, CLASS_BYTES.length); 229 } else { 230 return super.findClass(name); 231 } 232 } 233 }; 234 } 235 } 236 CheckLocalVariableTable(Executable m, Set<Locals.VariableDescription>[] possible_vars)237 public static void CheckLocalVariableTable(Executable m, 238 Set<Locals.VariableDescription>[] possible_vars) { 239 Set<Locals.VariableDescription> real_vars = 240 new HashSet<>(Arrays.asList(Locals.GetLocalVariableTable(m))); 241 for (Set<Locals.VariableDescription> pos : possible_vars) { 242 if (pos.equals(real_vars)) { 243 return; 244 } 245 } 246 System.out.println("Unexpected variables for " + m); 247 System.out.println("Received: " + real_vars); 248 System.out.println("Expected one of:"); 249 for (Object pos : possible_vars) { 250 System.out.println("\t" + pos); 251 } 252 } run()253 public static void run() throws Exception { 254 Locals.EnableLocalVariableAccess(); 255 Class<?> target = getClassLoader().loadClass("art.Target"); 256 CheckLocalVariableTable(target.getDeclaredConstructor(Integer.TYPE), 257 CONSTRUCTOR_VARIABLES); 258 CheckLocalVariableTable(target.getDeclaredMethod("doNothing", (new Object[0]).getClass()), 259 DO_NOTHING_VARIABLES); 260 CheckLocalVariableTable(target.getDeclaredMethod("doSomething", Integer.TYPE), 261 DO_SOMETHING_VARIABLES); 262 CheckLocalVariableTable(target.getDeclaredMethod("testGenericParameters", 263 (new ArrayList<Integer>(0)).getClass(), Integer.TYPE, (new Integer(0)).getClass()), 264 TEST_GENERIC_PARAMETERS_VARIABLES); 265 } 266 } 267 268