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