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.nio.ByteBuffer; 22 import java.util.Arrays; 23 import java.util.Base64; 24 import java.util.HashSet; 25 import java.util.Set; 26 27 public class Test1911 { 28 // Class/dex file containing the following class. 29 // 30 // CLASS_BYTES generated with java version 1.8.0_45: javac -g art/Target.java 31 // DEX_BYTES generated with dx version 1.14: dx --dex --output=./classes.dex art/Target.class 32 // 33 // package art; 34 // import java.util.ArrayList; 35 // public class Target { 36 // public int zzz; 37 // public Target(int xxx) { 38 // int q = xxx * 4; 39 // zzz = q; 40 // } 41 // public static void doNothing(Object... objs) { doNothing(objs); } 42 // public void doSomething(int x) { 43 // doNothing(this); 44 // int y = x + 3; 45 // for (int z = 0; z < y * x; z++) { 46 // float q = y - z; 47 // double i = 0.3d * q; 48 // doNothing(q, i); 49 // } 50 // Object o = new Object(); 51 // ArrayList<Integer> i = new ArrayList<>(); 52 // int p = 4 | x; 53 // long q = 3 * p; 54 // doNothing(p, q, o, i); 55 // } 56 // } 57 public static byte[] CLASS_BYTES = Base64.getDecoder().decode( 58 "yv66vgAAADQARgoABAAuCQANAC8KAA0AMAcAMQY/0zMzMzMzMwoAMgAzCgA0ADUHADYKAAkALgoA" + 59 "NwA4CgA5ADoHADsBAAN6enoBAAFJAQAGPGluaXQ+AQAEKEkpVgEABENvZGUBAA9MaW5lTnVtYmVy" + 60 "VGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAMTGFydC9UYXJnZXQ7AQADeHh4AQAB" + 61 "cQEACWRvTm90aGluZwEAFihbTGphdmEvbGFuZy9PYmplY3Q7KVYBAARvYmpzAQATW0xqYXZhL2xh" + 62 "bmcvT2JqZWN0OwEAC2RvU29tZXRoaW5nAQABRgEAAWkBAAFEAQABegEAAXgBAAF5AQABbwEAEkxq" + 63 "YXZhL2xhbmcvT2JqZWN0OwEAFUxqYXZhL3V0aWwvQXJyYXlMaXN0OwEAAXABAAFKAQAWTG9jYWxW" + 64 "YXJpYWJsZVR5cGVUYWJsZQEAKkxqYXZhL3V0aWwvQXJyYXlMaXN0PExqYXZhL2xhbmcvSW50ZWdl" + 65 "cjs+OwEADVN0YWNrTWFwVGFibGUBAApTb3VyY2VGaWxlAQALVGFyZ2V0LmphdmEMABAAPAwADgAP" + 66 "DAAZABoBABBqYXZhL2xhbmcvT2JqZWN0BwA9DAA+AD8HAEAMAD4AQQEAE2phdmEvdXRpbC9BcnJh" + 67 "eUxpc3QHAEIMAD4AQwcARAwAPgBFAQAKYXJ0L1RhcmdldAEAAygpVgEAD2phdmEvbGFuZy9GbG9h" + 68 "dAEAB3ZhbHVlT2YBABQoRilMamF2YS9sYW5nL0Zsb2F0OwEAEGphdmEvbGFuZy9Eb3VibGUBABUo" + 69 "RClMamF2YS9sYW5nL0RvdWJsZTsBABFqYXZhL2xhbmcvSW50ZWdlcgEAFihJKUxqYXZhL2xhbmcv" + 70 "SW50ZWdlcjsBAA5qYXZhL2xhbmcvTG9uZwEAEyhKKUxqYXZhL2xhbmcvTG9uZzsAIQANAAQAAAAB" + 71 "AAEADgAPAAAAAwABABAAEQABABIAAABYAAIAAwAAAA4qtwABGwdoPSoctQACsQAAAAIAEwAAABIA" + 72 "BAAAAAUABAAGAAgABwANAAgAFAAAACAAAwAAAA4AFQAWAAAAAAAOABcADwABAAgABgAYAA8AAgCJ" + 73 "ABkAGgABABIAAAAvAAEAAQAAAAUquAADsQAAAAIAEwAAAAYAAQAAAAkAFAAAAAwAAQAAAAUAGwAc" + 74 "AAAAAQAdABEAAQASAAABWAAFAAgAAACCBL0ABFkDKlO4AAMbBmA9Az4dHBtoogAvHB1khjgEFAAF" + 75 "FwSNazkFBb0ABFkDFwS4AAdTWQQYBbgACFO4AAOEAwGn/9C7AARZtwABTrsACVm3AAo6BAcbgDYF" + 76 "BhUFaIU3Bge9AARZAxUFuAALU1kEFga4AAxTWQUtU1kGGQRTuAADsQAAAAQAEwAAADYADQAAAAsA" + 77 "CwAMAA8ADQAYAA4AHgAPACcAEAA+AA0ARAASAEwAEwBVABQAWgAVAGEAFgCBABcAFAAAAGYACgAe" + 78 "ACAAGAAeAAQAJwAXAB8AIAAFABEAMwAhAA8AAwAAAIIAFQAWAAAAAACCACIADwABAA8AcwAjAA8A" + 79 "AgBMADYAJAAlAAMAVQAtAB8AJgAEAFoAKAAnAA8ABQBhACEAGAAoAAYAKQAAAAwAAQBVAC0AHwAq" + 80 "AAQAKwAAAAoAAv0AEQEB+gAyAAEALAAAAAIALQ=="); 81 public static byte[] DEX_BYTES = Base64.getDecoder().decode( 82 "ZGV4CjAzNQCQtgjEV631Ma/btYyIy2IzqHWNN+nZiwl0BQAAcAAAAHhWNBIAAAAAAAAAANQEAAAk" + 83 "AAAAcAAAAA0AAAAAAQAABwAAADQBAAABAAAAiAEAAAkAAACQAQAAAQAAANgBAAB8AwAA+AEAAB4D" + 84 "AAAmAwAAKQMAACwDAAAvAwAAMgMAADYDAAA6AwAAPgMAAEIDAABQAwAAZAMAAHcDAACMAwAAngMA" + 85 "ALIDAADJAwAA9QMAAAIEAAAFBAAACQQAAA0EAAAiBAAALQQAADoEAAA9BAAAQAQAAEYEAABJBAAA" + 86 "TAQAAFIEAABbBAAAXgQAAGMEAABmBAAAaQQAAAEAAAACAAAAAwAAAAQAAAAJAAAACgAAAAsAAAAM" + 87 "AAAADQAAAA4AAAAPAAAAEgAAABUAAAAFAAAABQAAAPgCAAAGAAAABgAAAAADAAAHAAAABwAAAAgD" + 88 "AAAIAAAACAAAABADAAASAAAACwAAAAAAAAATAAAACwAAAAgDAAAUAAAACwAAABgDAAAEAAIAIwAA" + 89 "AAQABQAAAAAABAAGABYAAAAEAAUAFwAAAAUAAAAeAAAABgABAB4AAAAHAAIAHgAAAAgAAwAeAAAA" + 90 "CQAEAAAAAAAKAAQAAAAAAAQAAAABAAAACQAAAAAAAAARAAAAAAAAAL4EAAAAAAAAAwACAAEAAABu" + 91 "BAAACAAAAHAQBwABANoAAgRZEAAADgABAAEAAQAAAHsEAAAEAAAAcRABAAAADgAQAAIAAgAAAIEE" + 92 "AABcAAAAEhkjmQwAEgpNDgkKcRABAAkA2AUPAxIIkgkFDzWYJACRCQUIgpYYCjMzMzMzM9M/iWyt" + 93 "AAoMEikjmQwAEgpxEAQABgAMC00LCQoSGnEgAwAQAAwLTQsJCnEQAQAJANgICAEo2yIDCQBwEAcA" + 94 "AwAiAgoAcBAIAAIA3gQPBNoJBAOBlhJJI5kMABIKcRAFAAQADAtNCwkKEhpxIAYAdgAMC00LCQoS" + 95 "Kk0DCQoSOk0CCQpxEAEACQAOAAEAAAAAAAAAAQAAAAEAAAABAAAAAgAAAAEAAAADAAAAAQAAAAwA" + 96 "Bjxpbml0PgABRAABRgABSQABSgACTEQAAkxGAAJMSQACTEoADExhcnQvVGFyZ2V0OwASTGphdmEv" + 97 "bGFuZy9Eb3VibGU7ABFMamF2YS9sYW5nL0Zsb2F0OwATTGphdmEvbGFuZy9JbnRlZ2VyOwAQTGph" + 98 "dmEvbGFuZy9Mb25nOwASTGphdmEvbGFuZy9PYmplY3Q7ABVMamF2YS91dGlsL0FycmF5TGlzdDsA" + 99 "KkxqYXZhL3V0aWwvQXJyYXlMaXN0PExqYXZhL2xhbmcvSW50ZWdlcjs+OwALVGFyZ2V0LmphdmEA" + 100 "AVYAAlZJAAJWTAATW0xqYXZhL2xhbmcvT2JqZWN0OwAJZG9Ob3RoaW5nAAtkb1NvbWV0aGluZwAB" + 101 "aQABbwAEb2JqcwABcAABcQAEdGhpcwAHdmFsdWVPZgABeAADeHh4AAF5AAF6AAN6enoABQEhBw48" + 102 "LQMAHQMtAAkBGwcOAAsBIAcOli0DBSIDAQEDCCMDSzwDBh0ChwMAGQEBFAtABQAFBloDAxoKWgQC" + 103 "GQsRLQMEHAM8AwYdBAEaDwAAAQIBAAEAgYAE+AMBiQGYBAIBsAQADQAAAAAAAAABAAAAAAAAAAEA" + 104 "AAAkAAAAcAAAAAIAAAANAAAAAAEAAAMAAAAHAAAANAEAAAQAAAABAAAAiAEAAAUAAAAJAAAAkAEA" + 105 "AAYAAAABAAAA2AEAAAEgAAADAAAA+AEAAAEQAAAFAAAA+AIAAAIgAAAkAAAAHgMAAAMgAAADAAAA" + 106 "bgQAAAAgAAABAAAAvgQAAAAQAAABAAAA1AQAAA=="); 107 108 109 // The variables of the functions in the above Target class. 110 public static Set<Locals.VariableDescription>[] CONSTRUCTOR_VARIABLES = new Set[] { 111 // RI Local variable table 112 new HashSet<>(Arrays.asList( 113 new Locals.VariableDescription(8, 6, "q", "I", null, 2), 114 new Locals.VariableDescription(0, 14, "xxx", "I", null, 1), 115 new Locals.VariableDescription(0, 14, "this", "Lart/Target;", null, 0))), 116 // ART Local variable table 117 new HashSet<>(Arrays.asList( 118 new Locals.VariableDescription(0, 8, "this", "Lart/Target;", null, 1), 119 new Locals.VariableDescription(5, 3, "q", "I", null, 0), 120 new Locals.VariableDescription(0, 8, "xxx", "I", null, 2))), 121 }; 122 123 public static Set<Locals.VariableDescription>[] DO_NOTHING_VARIABLES = new Set[] { 124 // RI Local variable table 125 new HashSet<>(Arrays.asList( 126 new Locals.VariableDescription(0, 5, "objs", "[Ljava/lang/Object;", null, 0))), 127 // ART Local variable table 128 new HashSet<>(Arrays.asList( 129 new Locals.VariableDescription(0, 4, "objs", "[Ljava/lang/Object;", null, 0))), 130 }; 131 132 public static Set<Locals.VariableDescription>[] DO_SOMETHING_VARIABLES = new Set[] { 133 // RI Local variable table 134 new HashSet<>(Arrays.asList( 135 new Locals.VariableDescription(0, 130, "x", "I", null, 1), 136 new Locals.VariableDescription(76, 54, "o", "Ljava/lang/Object;", null, 3), 137 new Locals.VariableDescription(30, 32, "q", "F", null, 4), 138 new Locals.VariableDescription(39, 23, "i", "D", null, 5), 139 new Locals.VariableDescription(17, 51, "z", "I", null, 3), 140 new Locals.VariableDescription(15, 115, "y", "I", null, 2), 141 new Locals.VariableDescription(90, 40, "p", "I", null, 5), 142 new Locals.VariableDescription(97, 33, "q", "J", null, 6), 143 new Locals.VariableDescription(0, 130, "this", "Lart/Target;", null, 0), 144 new Locals.VariableDescription(85, 145 45, 146 "i", 147 "Ljava/util/ArrayList;", 148 "Ljava/util/ArrayList<Ljava/lang/Integer;>;", 149 4))), 150 // ART Local variable table 151 new HashSet<>(Arrays.asList( 152 new Locals.VariableDescription(19, 31, "q", "F", null, 6), 153 new Locals.VariableDescription(55, 37, "o", "Ljava/lang/Object;", null, 3), 154 new Locals.VariableDescription(0, 92, "this", "Lart/Target;", null, 14), 155 new Locals.VariableDescription(12, 80, "z", "I", null, 8), 156 new Locals.VariableDescription(11, 81, "y", "I", null, 5), 157 new Locals.VariableDescription(62, 30, "p", "I", null, 4), 158 new Locals.VariableDescription(0, 92, "x", "I", null, 15), 159 new Locals.VariableDescription(27, 23, "i", "D", null, 0), 160 new Locals.VariableDescription(65, 27, "q", "J", null, 6), 161 new Locals.VariableDescription(60, 162 32, 163 "i", 164 "Ljava/util/ArrayList;", 165 "Ljava/util/ArrayList<Ljava/lang/Integer;>;", 166 2))), 167 }; 168 169 // Get a classloader that can load the Target class. getClassLoader()170 public static ClassLoader getClassLoader() throws Exception { 171 try { 172 Class<?> class_loader_class = Class.forName("dalvik.system.InMemoryDexClassLoader"); 173 Constructor<?> ctor = class_loader_class.getConstructor(ByteBuffer.class, ClassLoader.class); 174 // We are on art since we got the InMemoryDexClassLoader. 175 return (ClassLoader)ctor.newInstance( 176 ByteBuffer.wrap(DEX_BYTES), Test1911.class.getClassLoader()); 177 } catch (ClassNotFoundException e) { 178 // Running on RI. 179 return new ClassLoader(Test1911.class.getClassLoader()) { 180 protected Class<?> findClass(String name) throws ClassNotFoundException { 181 if (name.equals("art.Target")) { 182 return defineClass(name, CLASS_BYTES, 0, CLASS_BYTES.length); 183 } else { 184 return super.findClass(name); 185 } 186 } 187 }; 188 } 189 } 190 CheckLocalVariableTable(Executable m, Set<Locals.VariableDescription>[] possible_vars)191 public static void CheckLocalVariableTable(Executable m, 192 Set<Locals.VariableDescription>[] possible_vars) { 193 Set<Locals.VariableDescription> real_vars = 194 new HashSet<>(Arrays.asList(Locals.GetLocalVariableTable(m))); 195 for (Set<Locals.VariableDescription> pos : possible_vars) { 196 if (pos.equals(real_vars)) { 197 return; 198 } 199 } 200 System.out.println("Unexpected variables for " + m); 201 System.out.println("Received: " + real_vars); 202 System.out.println("Expected one of:"); 203 for (Object pos : possible_vars) { 204 System.out.println("\t" + pos); 205 } 206 } run()207 public static void run() throws Exception { 208 Locals.EnableLocalVariableAccess(); 209 Class<?> target = getClassLoader().loadClass("art.Target"); 210 CheckLocalVariableTable(target.getDeclaredConstructor(Integer.TYPE), 211 CONSTRUCTOR_VARIABLES); 212 CheckLocalVariableTable(target.getDeclaredMethod("doNothing", (new Object[0]).getClass()), 213 DO_NOTHING_VARIABLES); 214 CheckLocalVariableTable(target.getDeclaredMethod("doSomething", Integer.TYPE), 215 DO_SOMETHING_VARIABLES); 216 } 217 } 218 219