• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 #include <sstream>
18 #include <string>
19 #include <vector>
20 
21 #include <sys/types.h>
22 #include <unistd.h>
23 
24 #include "base/unix_file/fd_file.h"
25 #include "base/utils.h"
26 #include "common_runtime_test.h"
27 #include "dex/art_dex_file_loader.h"
28 #include "dex/base64_test_util.h"
29 #include "dex/class_accessor-inl.h"
30 #include "dex/code_item_accessors-inl.h"
31 #include "dex/dex_file-inl.h"
32 #include "dex/dex_file_loader.h"
33 #include "dexlayout.h"
34 #include "exec_utils.h"
35 #include "profile/profile_compilation_info.h"
36 
37 namespace art {
38 
39 static const char kDexFileLayoutInputDex[] =
40     "ZGV4CjAzNQD1KW3+B8NAB0f2A/ZVIBJ0aHrGIqcpVTAUAgAAcAAAAHhWNBIAAAAAAAAAAIwBAAAH"
41     "AAAAcAAAAAQAAACMAAAAAQAAAJwAAAAAAAAAAAAAAAMAAACoAAAAAgAAAMAAAAAUAQAAAAEAADAB"
42     "AAA4AQAAQAEAAEgBAABNAQAAUgEAAGYBAAADAAAABAAAAAUAAAAGAAAABgAAAAMAAAAAAAAAAAAA"
43     "AAAAAAABAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAAAAAAAdQEAAAAAAAABAAAA"
44     "AAAAAAIAAAAAAAAAAgAAAAAAAAB/AQAAAAAAAAEAAQABAAAAaQEAAAQAAABwEAIAAAAOAAEAAQAB"
45     "AAAAbwEAAAQAAABwEAIAAAAOAAY8aW5pdD4ABkEuamF2YQAGQi5qYXZhAANMQTsAA0xCOwASTGph"
46     "dmEvbGFuZy9PYmplY3Q7AAFWAAQABw48AAQABw48AAAAAQAAgIAEgAIAAAEAAYCABJgCAAAACwAA"
47     "AAAAAAABAAAAAAAAAAEAAAAHAAAAcAAAAAIAAAAEAAAAjAAAAAMAAAABAAAAnAAAAAUAAAADAAAA"
48     "qAAAAAYAAAACAAAAwAAAAAEgAAACAAAAAAEAAAIgAAAHAAAAMAEAAAMgAAACAAAAaQEAAAAgAAAC"
49     "AAAAdQEAAAAQAAABAAAAjAEAAA==";
50 
51 // Dex file with catch handler unreferenced by try blocks.
52 // Constructed by building a dex file with try/catch blocks and hex editing.
53 static const char kUnreferencedCatchHandlerInputDex[] =
54     "ZGV4CjAzNQD+exd52Y0f9nY5x5GmInXq5nXrO6Kl2RV4AwAAcAAAAHhWNBIAAAAAAAAAANgCAAAS"
55     "AAAAcAAAAAgAAAC4AAAAAwAAANgAAAABAAAA/AAAAAQAAAAEAQAAAQAAACQBAAA0AgAARAEAANYB"
56     "AADeAQAA5gEAAO4BAAAAAgAADwIAACYCAAA9AgAAUQIAAGUCAAB5AgAAfwIAAIUCAACIAgAAjAIA"
57     "AKECAACnAgAArAIAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAwAAAAOAAAADAAAAAYAAAAAAAAA"
58     "DQAAAAYAAADIAQAADQAAAAYAAADQAQAABQABABAAAAAAAAAAAAAAAAAAAgAPAAAAAQABABEAAAAD"
59     "AAAAAAAAAAAAAAABAAAAAwAAAAAAAAADAAAAAAAAAMgCAAAAAAAAAQABAAEAAAC1AgAABAAAAHAQ"
60     "AwAAAA4AAwABAAIAAgC6AgAAIQAAAGIAAAAaAQoAbiACABAAYgAAABoBCwBuIAIAEAAOAA0AYgAA"
61     "ABoBAQBuIAIAEAAo8A0AYgAAABoBAgBuIAIAEAAo7gAAAAAAAAcAAQAHAAAABwABAAIBAg8BAhgA"
62     "AQAAAAQAAAABAAAABwAGPGluaXQ+AAZDYXRjaDEABkNhdGNoMgAQSGFuZGxlclRlc3QuamF2YQAN"
63     "TEhhbmRsZXJUZXN0OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABVMamF2YS9sYW5nL0V4Y2VwdGlv"
64     "bjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABJMamF2YS9sYW5nL1N5"
65     "c3RlbTsABFRyeTEABFRyeTIAAVYAAlZMABNbTGphdmEvbGFuZy9TdHJpbmc7AARtYWluAANvdXQA"
66     "B3ByaW50bG4AAQAHDgAEAQAHDn17AncdHoseAAAAAgAAgYAExAIBCdwCAAANAAAAAAAAAAEAAAAA"
67     "AAAAAQAAABIAAABwAAAAAgAAAAgAAAC4AAAAAwAAAAMAAADYAAAABAAAAAEAAAD8AAAABQAAAAQA"
68     "AAAEAQAABgAAAAEAAAAkAQAAASAAAAIAAABEAQAAARAAAAIAAADIAQAAAiAAABIAAADWAQAAAyAA"
69     "AAIAAAC1AgAAACAAAAEAAADIAgAAABAAAAEAAADYAgAA";
70 
71 // Dex file with 0-size (catch all only) catch handler unreferenced by try blocks.
72 // Constructed by building a dex file with try/catch blocks and hex editing.
73 static const char kUnreferenced0SizeCatchHandlerInputDex[] =
74     "ZGV4CjAzNQCEbEEvMstSNpQpjPdfMEfUBS48cis2QRJoAwAAcAAAAHhWNBIAAAAAAAAAAMgCAAAR"
75     "AAAAcAAAAAcAAAC0AAAAAwAAANAAAAABAAAA9AAAAAQAAAD8AAAAAQAAABwBAAAsAgAAPAEAAOoB"
76     "AADyAQAABAIAABMCAAAqAgAAPgIAAFICAABmAgAAaQIAAG0CAACCAgAAhgIAAIoCAACQAgAAlQIA"
77     "AJ4CAACiAgAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACQAAAAcAAAAFAAAAAAAAAAgAAAAFAAAA"
78     "3AEAAAgAAAAFAAAA5AEAAAQAAQANAAAAAAAAAAAAAAAAAAIADAAAAAEAAQAOAAAAAgAAAAAAAAAA"
79     "AAAAAQAAAAIAAAAAAAAAAQAAAAAAAAC5AgAAAAAAAAEAAQABAAAApgIAAAQAAABwEAMAAAAOAAQA"
80     "AQACAAIAqwIAAC8AAABiAAAAGgEPAG4gAgAQAGIAAAAaAQoAbiACABAAYgAAABoBEABuIAIAEABi"
81     "AAAAGgELAG4gAgAQAA4ADQBiAQAAGgIKAG4gAgAhACcADQBiAQAAGgILAG4gAgAhACcAAAAAAAAA"
82     "BwABAA4AAAAHAAEAAgAdACYAAAABAAAAAwAAAAEAAAAGAAY8aW5pdD4AEEhhbmRsZXJUZXN0Lmph"
83     "dmEADUxIYW5kbGVyVGVzdDsAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwASTGphdmEvbGFuZy9PYmpl"
84     "Y3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xhbmcvU3lzdGVtOwABVgACVkwAE1tMamF2"
85     "YS9sYW5nL1N0cmluZzsAAmYxAAJmMgAEbWFpbgADb3V0AAdwcmludGxuAAJ0MQACdDIAAQAHDgAE"
86     "AQAHDnl7eXkCeB2bAAAAAgAAgYAEvAIBCdQCAA0AAAAAAAAAAQAAAAAAAAABAAAAEQAAAHAAAAAC"
87     "AAAABwAAALQAAAADAAAAAwAAANAAAAAEAAAAAQAAAPQAAAAFAAAABAAAAPwAAAAGAAAAAQAAABwB"
88     "AAABIAAAAgAAADwBAAABEAAAAgAAANwBAAACIAAAEQAAAOoBAAADIAAAAgAAAKYCAAAAIAAAAQAA"
89     "ALkCAAAAEAAAAQAAAMgCAAA=";
90 
91 // Dex file with an unreferenced catch handler at end of code item.
92 // Constructed by building a dex file with try/catch blocks and hex editing.
93 static const char kUnreferencedEndingCatchHandlerInputDex[] =
94     "ZGV4CjAzNQCEflufI6xGTDDRmLpbfYi6ujPrDLIwvYcEBAAAcAAAAHhWNBIAAAAAAAAAAGQDAAAT"
95     "AAAAcAAAAAgAAAC8AAAAAwAAANwAAAABAAAAAAEAAAUAAAAIAQAAAQAAADABAAC0AgAAUAEAAE4C"
96     "AABWAgAAXgIAAGYCAAB4AgAAhwIAAJ4CAAC1AgAAyQIAAN0CAADxAgAA9wIAAP0CAAAAAwAABAMA"
97     "ABkDAAAcAwAAIgMAACcDAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAMAAAADgAAAAwAAAAGAAAA"
98     "AAAAAA0AAAAGAAAAQAIAAA0AAAAGAAAASAIAAAUAAQARAAAAAAAAAAAAAAAAAAAADwAAAAAAAgAQ"
99     "AAAAAQABABIAAAADAAAAAAAAAAAAAAABAAAAAwAAAAAAAAADAAAAAAAAAFADAAAAAAAAAQABAAEA"
100     "AAAwAwAABAAAAHAQBAAAAA4AAgAAAAIAAgA1AwAAIQAAAGIAAAAaAQoAbiADABAAYgAAABoBCwBu"
101     "IAMAEAAOAA0AYgAAABoBAQBuIAMAEAAo8A0AYgAAABoBAgBuIAMAEAAo7gAAAAAAAAcAAQAHAAAA"
102     "BwABAAIBAg8BAhgAAwABAAIAAgBCAwAAIQAAAGIAAAAaAQoAbiADABAAYgAAABoBCwBuIAMAEAAO"
103     "AA0AYgAAABoBAQBuIAMAEAAo8A0AYgAAABoBAgBuIAMAEAAo7gAAAAAAAAcAAQAHAAAABwABAAIB"
104     "Ag8BAhgAAQAAAAQAAAABAAAABwAGPGluaXQ+AAZDYXRjaDEABkNhdGNoMgAQSGFuZGxlclRlc3Qu"
105     "amF2YQANTEhhbmRsZXJUZXN0OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABVMamF2YS9sYW5nL0V4"
106     "Y2VwdGlvbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABJMamF2YS9s"
107     "YW5nL1N5c3RlbTsABFRyeTEABFRyeTIAAVYAAlZMABNbTGphdmEvbGFuZy9TdHJpbmc7AAFhAARt"
108     "YWluAANvdXQAB3ByaW50bG4AAQAHDgAEAAcOfHsCeB0eih4AEQEABw59ewJ3HR6LHgAAAAMAAIGA"
109     "BNACAQnoAgEJ1AMAAA0AAAAAAAAAAQAAAAAAAAABAAAAEwAAAHAAAAACAAAACAAAALwAAAADAAAA"
110     "AwAAANwAAAAEAAAAAQAAAAABAAAFAAAABQAAAAgBAAAGAAAAAQAAADABAAABIAAAAwAAAFABAAAB"
111     "EAAAAgAAAEACAAACIAAAEwAAAE4CAAADIAAAAwAAADADAAAAIAAAAQAAAFADAAAAEAAAAQAAAGQD"
112     "AAA=";
113 
114 // Dex file with multiple code items that have the same debug_info_off_. Constructed by a modified
115 // dexlayout on XandY.
116 static const char kDexFileDuplicateOffset[] =
117     "ZGV4CjAzNwAQfXfPCB8qCxo7MqdFhmHZQwCv8+udHD8MBAAAcAAAAHhWNBIAAAAAAAAAAFQDAAAT"
118     "AAAAcAAAAAgAAAC8AAAAAQAAANwAAAABAAAA6AAAAAUAAADwAAAAAwAAABgBAACUAgAAeAEAABQC"
119     "AAAeAgAAJgIAACsCAAAyAgAANwIAAFsCAAB7AgAAngIAALICAAC1AgAAvQIAAMUCAADIAgAA1QIA"
120     "AOkCAADvAgAA9QIAAPwCAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAkAAAAHAAAA"
121     "AAAAAAIAAQASAAAAAAAAAAEAAAABAAAAAQAAAAIAAAAAAAAAAgAAAAEAAAAGAAAAAQAAAAAAAAAA"
122     "AAAABgAAAAAAAAAKAAAAAAAAACsDAAAAAAAAAQAAAAAAAAAGAAAAAAAAAAsAAAD0AQAANQMAAAAA"
123     "AAACAAAAAAAAAAAAAAAAAAAACwAAAAQCAAA/AwAAAAAAAAIAAAAUAwAAGgMAAAEAAAAjAwAAAQAB"
124     "AAEAAAAFAAAABAAAAHAQBAAAAA4AAQABAAEAAAAFAAAABAAAAHAQBAAAAA4AAQAAAAEAAAAFAAAA"
125     "CAAAACIAAQBwEAEAAABpAAAADgABAAEAAQAAAAUAAAAEAAAAcBAAAAAADgB4AQAAAAAAAAAAAAAA"
126     "AAAAhAEAAAAAAAAAAAAAAAAAAAg8Y2xpbml0PgAGPGluaXQ+AANMWDsABUxZJFo7AANMWTsAIkxk"
127     "YWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5l"
128     "ckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNzZXM7ABJMamF2YS9sYW5nL09i"
129     "amVjdDsAAVYABlguamF2YQAGWS5qYXZhAAFaAAthY2Nlc3NGbGFncwASZW1pdHRlcjogamFjay00"
130     "LjI1AARuYW1lAAR0aGlzAAV2YWx1ZQABegARAAcOABMABw4AEgAHDnYAEQAHDgACAwERGAICBAIN"
131     "BAgPFwwCBQERHAEYAQAAAQAAgIAEjAMAAAEAAYCABKQDAQACAAAIAoiABLwDAYCABNwDAAAADwAA"
132     "AAAAAAABAAAAAAAAAAEAAAATAAAAcAAAAAIAAAAIAAAAvAAAAAMAAAABAAAA3AAAAAQAAAABAAAA"
133     "6AAAAAUAAAAFAAAA8AAAAAYAAAADAAAAGAEAAAMQAAACAAAAeAEAAAEgAAAEAAAAjAEAAAYgAAAC"
134     "AAAA9AEAAAIgAAATAAAAFAIAAAMgAAAEAAAA/wIAAAQgAAADAAAAFAMAAAAgAAADAAAAKwMAAAAQ"
135     "AAABAAAAVAMAAA==";
136 
137 // Dex file with null value for annotations_off in the annotation_set_ref_list.
138 // Constructed by building a dex file with annotations and hex editing.
139 static const char kNullSetRefListElementInputDex[] =
140     "ZGV4CjAzNQB1iA+7ZwgkF+7E6ZesYFc2lRAR3qnRAanwAwAAcAAAAHhWNBIAAAAAAAAAACADAAAS"
141     "AAAAcAAAAAgAAAC4AAAAAwAAANgAAAABAAAA/AAAAAQAAAAEAQAAAgAAACQBAACMAgAAZAEAAOgB"
142     "AADwAQAAAAIAAAMCAAAQAgAAIAIAADQCAABIAgAAawIAAI0CAAC1AgAAyAIAANECAADUAgAA2QIA"
143     "ANwCAADjAgAA6QIAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAMAAAAAgAAAAMAAAAAAAAA"
144     "DAAAAAcAAAAAAAAADQAAAAcAAADgAQAABgAGAAsAAAAAAAEAAAAAAAAAAgAOAAAAAQAAABAAAAAC"
145     "AAEAAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAsAEAAAgDAAAAAAAAAQAAAAEmAAACAAAA2AEAAAoA"
146     "AADIAQAAFgMAAAAAAAACAAAAAAAAAHwBAAABAAAA/AIAAAAAAAABAAAAAgMAAAEAAQABAAAA8AIA"
147     "AAQAAABwEAMAAAAOAAIAAgAAAAAA9QIAAAEAAAAOAAAAAAAAAAAAAAAAAAAAAQAAAAEAAABkAQAA"
148     "cAEAAAAAAAAAAAAAAAAAAAEAAAAEAAAAAgAAAAMAAwAGPGluaXQ+AA5Bbm5vQ2xhc3MuamF2YQAB"
149     "TAALTEFubm9DbGFzczsADkxNeUFubm90YXRpb247ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZh"
150     "L2xhbmcvU3RyaW5nOwAhTGphdmEvbGFuZy9hbm5vdGF0aW9uL0Fubm90YXRpb247ACBMamF2YS9s"
151     "YW5nL2Fubm90YXRpb24vUmV0ZW50aW9uOwAmTGphdmEvbGFuZy9hbm5vdGF0aW9uL1JldGVudGlv"
152     "blBvbGljeTsAEU15QW5ub3RhdGlvbi5qYXZhAAdSVU5USU1FAAFWAANWTEwAAWEABWFOYW1lAARu"
153     "YW1lAAV2YWx1ZQABAAcOAAICAAAHDgABBQERGwABAQEQFw8AAAIAAICABIQDAQmcAwAAAAECgQgA"
154     "AAARAAAAAAAAAAEAAAAAAAAAAQAAABIAAABwAAAAAgAAAAgAAAC4AAAAAwAAAAMAAADYAAAABAAA"
155     "AAEAAAD8AAAABQAAAAQAAAAEAQAABgAAAAIAAAAkAQAAAhAAAAEAAABkAQAAAxAAAAMAAABwAQAA"
156     "ASAAAAIAAACEAQAABiAAAAIAAACwAQAAARAAAAIAAADYAQAAAiAAABIAAADoAQAAAyAAAAIAAADw"
157     "AgAABCAAAAIAAAD8AgAAACAAAAIAAAAIAwAAABAAAAEAAAAgAwAA";
158 
159 // Dex file with shared empty class data item for multiple class defs.
160 // Constructing by building a dex file with multiple classes and hex editing.
161 static const char kMultiClassDataInputDex[] =
162     "ZGV4CjAzNQALJgF9TtnLq748xVe/+wyxETrT9lTEiW6YAQAAcAAAAHhWNBIAAAAAAAAAADQBAAAI"
163     "AAAAcAAAAAQAAACQAAAAAAAAAAAAAAACAAAAoAAAAAAAAAAAAAAAAgAAALAAAACoAAAA8AAAAPAA"
164     "AAD4AAAAAAEAAAMBAAAIAQAADQEAACEBAAAkAQAAAgAAAAMAAAAEAAAABQAAAAEAAAAGAAAAAgAA"
165     "AAcAAAABAAAAAQYAAAMAAAAAAAAAAAAAAAAAAAAnAQAAAAAAAAIAAAABBgAAAwAAAAAAAAABAAAA"
166     "AAAAACcBAAAAAAAABkEuamF2YQAGQi5qYXZhAAFJAANMQTsAA0xCOwASTGphdmEvbGFuZy9PYmpl"
167     "Y3Q7AAFhAAFiAAAAAAABAAAAARkAAAAIAAAAAAAAAAEAAAAAAAAAAQAAAAgAAABwAAAAAgAAAAQA"
168     "AACQAAAABAAAAAIAAACgAAAABgAAAAIAAACwAAAAAiAAAAgAAADwAAAAACAAAAIAAAAnAQAAABAA"
169     "AAEAAAA0AQAA";
170 
171 // Dex file with code info followed by non 4-byte aligned section.
172 // Constructed a dex file with code info followed by string data and hex edited.
173 static const char kUnalignedCodeInfoInputDex[] =
174     "ZGV4CjAzNQDXJzXNb4iWn2SLhmLydW/8h1K9moERIw7UAQAAcAAAAHhWNBIAAAAAAAAAAEwBAAAG"
175     "AAAAcAAAAAMAAACIAAAAAQAAAJQAAAAAAAAAAAAAAAMAAACgAAAAAQAAALgAAAD8AAAA2AAAAAIB"
176     "AAAKAQAAEgEAABcBAAArAQAALgEAAAIAAAADAAAABAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAA"
177     "AAUAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAABAAAAAAAAADsBAAAAAAAAAQABAAEAAAAxAQAA"
178     "BAAAAHAQAgAAAA4AAQABAAAAAAA2AQAAAQAAAA4ABjxpbml0PgAGQS5qYXZhAANMQTsAEkxqYXZh"
179     "L2xhbmcvT2JqZWN0OwABVgABYQABAAcOAAMABw4AAAABAQCBgATYAQEB8AEAAAALAAAAAAAAAAEA"
180     "AAAAAAAAAQAAAAYAAABwAAAAAgAAAAMAAACIAAAAAwAAAAEAAACUAAAABQAAAAMAAACgAAAABgAA"
181     "AAEAAAC4AAAAASAAAAIAAADYAAAAAiAAAAYAAAACAQAAAyAAAAIAAAAxAQAAACAAAAEAAAA7AQAA"
182     "ABAAAAEAAABMAQAA";
183 
184 // Dex file with class data section preceding code items.
185 // Constructed by passing dex file through dexmerger tool and hex editing.
186 static const char kClassDataBeforeCodeInputDex[] =
187     "ZGV4CjAzNQCZKmCu3XXn4zvxCh5VH0gZNNobEAcsc49EAgAAcAAAAHhWNBIAAAAAAAAAAAQBAAAJ"
188     "AAAAcAAAAAQAAACUAAAAAgAAAKQAAAAAAAAAAAAAAAUAAAC8AAAAAQAAAOQAAABAAQAABAEAAPgB"
189     "AAAAAgAACAIAAAsCAAAQAgAAJAIAACcCAAAqAgAALQIAAAIAAAADAAAABAAAAAUAAAACAAAAAAAA"
190     "AAAAAAAFAAAAAwAAAAAAAAABAAEAAAAAAAEAAAAGAAAAAQAAAAcAAAABAAAACAAAAAIAAQAAAAAA"
191     "AQAAAAEAAAACAAAAAAAAAAEAAAAAAAAAjAEAAAAAAAALAAAAAAAAAAEAAAAAAAAAAQAAAAkAAABw"
192     "AAAAAgAAAAQAAACUAAAAAwAAAAIAAACkAAAABQAAAAUAAAC8AAAABgAAAAEAAADkAAAAABAAAAEA"
193     "AAAEAQAAACAAAAEAAACMAQAAASAAAAQAAACkAQAAAiAAAAkAAAD4AQAAAyAAAAQAAAAwAgAAAAAB"
194     "AwCBgASkAwEBvAMBAdADAQHkAwAAAQABAAEAAAAwAgAABAAAAHAQBAAAAA4AAgABAAAAAAA1AgAA"
195     "AgAAABIQDwACAAEAAAAAADoCAAACAAAAEiAPAAIAAQAAAAAAPwIAAAIAAAASMA8ABjxpbml0PgAG"
196     "QS5qYXZhAAFJAANMQTsAEkxqYXZhL2xhbmcvT2JqZWN0OwABVgABYQABYgABYwABAAcOAAMABw4A"
197     "BgAHDgAJAAcOAA==";
198 
199 // Dex file with local info containing a null type descriptor.
200 // Constructed a dex file with debug info sequence containing DBG_RESTART_LOCAL without any
201 // DBG_START_LOCAL to give it a declared type.
202 static const char kUnknownTypeDebugInfoInputDex[] =
203     "ZGV4CjAzNQBtKqZfzjHLNSNwW2A6Bz9FuCEX0sL+FF38AQAAcAAAAHhWNBIAAAAAAAAAAHQBAAAI"
204     "AAAAcAAAAAQAAACQAAAAAgAAAKAAAAAAAAAAAAAAAAMAAAC4AAAAAQAAANAAAAAMAQAA8AAAABwB"
205     "AAAkAQAALAEAAC8BAAA0AQAASAEAAEsBAABOAQAAAgAAAAMAAAAEAAAABQAAAAIAAAAAAAAAAAAA"
206     "AAUAAAADAAAAAAAAAAEAAQAAAAAAAQAAAAYAAAACAAEAAAAAAAEAAAABAAAAAgAAAAAAAAABAAAA"
207     "AAAAAGMBAAAAAAAAAQABAAEAAABUAQAABAAAAHAQAgAAAA4AAgABAAAAAABZAQAAAgAAABIQDwAG"
208     "PGluaXQ+AAZBLmphdmEAAUkAA0xBOwASTGphdmEvbGFuZy9PYmplY3Q7AAFWAAFhAAR0aGlzAAEA"
209     "Bw4AAwAHDh4GAAYAAAAAAQEAgYAE8AEBAYgCAAAACwAAAAAAAAABAAAAAAAAAAEAAAAIAAAAcAAA"
210     "AAIAAAAEAAAAkAAAAAMAAAACAAAAoAAAAAUAAAADAAAAuAAAAAYAAAABAAAA0AAAAAEgAAACAAAA"
211     "8AAAAAIgAAAIAAAAHAEAAAMgAAACAAAAVAEAAAAgAAABAAAAYwEAAAAQAAABAAAAdAEAAA==";
212 
213 // Dex file with multiple class data items pointing to the same code item.
214 // Constructed by hex editing.
215 static const char kDuplicateCodeItemInputDex[] =
216     "ZGV4CjAzNQCwKtVglQOmLWuHwldN5jkBOInC7mTMhJMAAgAAcAAAAHhWNBIAAAAAAAAAAHgBAAAH"
217     "AAAAcAAAAAMAAACMAAAAAQAAAJgAAAAAAAAAAAAAAAQAAACkAAAAAQAAAMQAAAAcAQAA5AAAACQB"
218     "AAAsAQAANAEAADkBAABNAQAAUAEAAFMBAAACAAAAAwAAAAQAAAAEAAAAAgAAAAAAAAAAAAAAAAAA"
219     "AAAAAAAFAAAAAAAAAAYAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAABAAAAAAAAAGUBAAAAAAAA"
220     "AQABAAEAAABWAQAABAAAAHAQAwAAAA4AAQABAAAAAABbAQAAAQAAAA4AAAABAAEAAAAAAGABAAAB"
221     "AAAADgAAAAY8aW5pdD4ABkEuamF2YQADTEE7ABJMamF2YS9sYW5nL09iamVjdDsAAVYAAWEAAWIA"
222     "AQAHDgADAAcOAAUABw4AAAABAgCBgATkAQEA/AEBAPwBAAsAAAAAAAAAAQAAAAAAAAABAAAABwAA"
223     "AHAAAAACAAAAAwAAAIwAAAADAAAAAQAAAJgAAAAFAAAABAAAAKQAAAAGAAAAAQAAAMQAAAABIAAA"
224     "AwAAAOQAAAACIAAABwAAACQBAAADIAAAAwAAAFYBAAAAIAAAAQAAAGUBAAAAEAAAAQAAAHgBAAA=";
225 
226 // Returns the default compact dex option for dexlayout based on kDefaultCompactDexLevel.
DefaultCompactDexOption()227 static std::vector<std::string> DefaultCompactDexOption() {
228   return (kDefaultCompactDexLevel == CompactDexLevel::kCompactDexLevelFast) ?
229       std::vector<std::string>{"-x", "fast"} : std::vector<std::string>{"-x", "none"};
230 }
231 
WriteBase64ToFile(const char * base64,File * file)232 static void WriteBase64ToFile(const char* base64, File* file) {
233   // Decode base64.
234   CHECK(base64 != nullptr);
235   size_t length;
236   std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
237   CHECK(bytes != nullptr);
238   if (!file->WriteFully(bytes.get(), length)) {
239     PLOG(FATAL) << "Failed to write base64 as file";
240   }
241 }
242 
WriteFileBase64(const char * base64,const char * location)243 static void WriteFileBase64(const char* base64, const char* location) {
244   // Write to provided file.
245   std::unique_ptr<File> file(OS::CreateEmptyFile(location));
246   CHECK(file != nullptr);
247   WriteBase64ToFile(base64, file.get());
248   if (file->FlushCloseOrErase() != 0) {
249     PLOG(FATAL) << "Could not flush and close test file.";
250   }
251 }
252 
253 class DexLayoutTest : public CommonRuntimeTest {
254  protected:
GetDexLayoutPath()255   std::string GetDexLayoutPath() {
256     return GetTestAndroidRoot() + "/bin/dexlayoutd";
257   }
258 
259   // Runs FullPlainOutput test.
FullPlainOutputExec(std::string * error_msg)260   bool FullPlainOutputExec(std::string* error_msg) {
261     // TODO: dexdump2 -> dexdump ?
262     ScratchFile dexdump_output;
263     const std::string& dexdump_filename = dexdump_output.GetFilename();
264     std::string dexdump = GetTestAndroidRoot() + "/bin/dexdump2";
265     EXPECT_TRUE(OS::FileExists(dexdump.c_str())) << dexdump << " should be a valid file path";
266 
267     ScratchFile dexlayout_output;
268     const std::string& dexlayout_filename = dexlayout_output.GetFilename();
269 
270     for (const std::string& dex_file : GetLibCoreDexFileNames()) {
271       std::vector<std::string> dexdump_exec_argv =
272           { dexdump, "-d", "-f", "-h", "-l", "plain", "-o", dexdump_filename, dex_file };
273       std::vector<std::string> dexlayout_args =
274           { "-d", "-f", "-h", "-l", "plain", "-o", dexlayout_filename, dex_file };
275       if (!::art::Exec(dexdump_exec_argv, error_msg)) {
276         return false;
277       }
278       if (!DexLayoutExec(dexlayout_args, error_msg)) {
279         return false;
280       }
281       std::vector<std::string> diff_exec_argv =
282           { "/usr/bin/diff", dexdump_filename, dexlayout_filename };
283       if (!::art::Exec(diff_exec_argv, error_msg)) {
284         return false;
285       }
286     }
287     return true;
288   }
289 
290   // Runs DexFileOutput test.
DexFileOutputExec(std::string * error_msg)291   bool DexFileOutputExec(std::string* error_msg) {
292     ScratchFile tmp_file;
293     const std::string& tmp_name = tmp_file.GetFilename();
294     size_t tmp_last_slash = tmp_name.rfind('/');
295     std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
296     std::string unzip_dir = tmp_dir + "unzip/";
297 
298     for (const std::string& dex_file : GetLibCoreDexFileNames()) {
299       std::vector<std::string> dexlayout_args =
300           { "-w", tmp_dir, "-o", tmp_name, dex_file };
301       if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option=*/ false)) {
302         return false;
303       }
304       std::string dex_file_name = "classes.dex";
305       std::vector<std::string> unzip_exec_argv =
306           { "/usr/bin/unzip", dex_file, "classes.dex", "-d", unzip_dir};
307       if (!::art::Exec(unzip_exec_argv, error_msg)) {
308         return false;
309       }
310       std::vector<std::string> diff_exec_argv =
311           { "/usr/bin/diff", tmp_dir + "classes.dex" , unzip_dir + dex_file_name };
312       if (!::art::Exec(diff_exec_argv, error_msg)) {
313         return false;
314       }
315       if (!UnlinkFile(unzip_dir + "classes.dex")) {
316         return false;
317       }
318       if (!UnlinkFile(tmp_dir + dex_file_name)) {
319         return false;
320       }
321       // Remove the unzip temp directory so that unlinking android_data doesn't fail.
322       EXPECT_EQ(rmdir(unzip_dir.c_str()), 0);
323     }
324     return true;
325   }
326 
327   // Create a profile with some subset of methods and classes.
CreateProfile(const std::string & input_dex,const std::string & out_profile,const std::string & dex_location)328   void CreateProfile(const std::string& input_dex,
329                      const std::string& out_profile,
330                      const std::string& dex_location) {
331     std::vector<std::unique_ptr<const DexFile>> dex_files;
332     std::string error_msg;
333     const ArtDexFileLoader dex_file_loader;
334     bool result = dex_file_loader.Open(input_dex.c_str(),
335                                        input_dex,
336                                        /*verify=*/ true,
337                                        /*verify_checksum=*/ false,
338                                        &error_msg,
339                                        &dex_files);
340 
341     ASSERT_TRUE(result) << error_msg;
342     ASSERT_GE(dex_files.size(), 1u);
343 
344     size_t profile_methods = 0;
345     size_t profile_classes = 0;
346     ProfileCompilationInfo pfi;
347     std::set<DexCacheResolvedClasses> classes;
348     for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
349       for (uint32_t i = 0; i < dex_file->NumMethodIds(); i += 2) {
350         uint8_t flags = 0u;
351 
352         if ((i & 3) != 0) {
353           flags |= ProfileCompilationInfo::MethodHotness::kFlagHot;
354           ++profile_methods;
355         } else if ((i & 2) != 0) {
356           flags |= ProfileCompilationInfo::MethodHotness::kFlagStartup;
357           ++profile_methods;
358         }
359         pfi.AddMethodIndex(static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
360                            dex_location,
361                            dex_file->GetLocationChecksum(),
362                            /*method_idx=*/i,
363                            dex_file->NumMethodIds());
364       }
365       DexCacheResolvedClasses cur_classes(dex_location,
366                                           dex_location,
367                                           dex_file->GetLocationChecksum(),
368                                           dex_file->NumMethodIds());
369       // Add every even class too.
370       for (uint32_t i = 0; i < dex_file->NumClassDefs(); i += 1) {
371         if ((i & 2) == 0) {
372           cur_classes.AddClass(dex_file->GetClassDef(i).class_idx_);
373           ++profile_classes;
374         }
375       }
376       classes.insert(cur_classes);
377     }
378     pfi.AddClasses(classes);
379     // Write to provided file.
380     std::unique_ptr<File> file(OS::CreateEmptyFile(out_profile.c_str()));
381     ASSERT_TRUE(file != nullptr);
382     pfi.Save(file->Fd());
383     if (file->FlushCloseOrErase() != 0) {
384       PLOG(FATAL) << "Could not flush and close test file.";
385     }
386     EXPECT_GE(profile_methods, 0u);
387     EXPECT_GE(profile_classes, 0u);
388   }
389 
390   // Runs DexFileLayout test.
DexFileLayoutExec(std::string * error_msg)391   bool DexFileLayoutExec(std::string* error_msg) {
392     ScratchFile tmp_file;
393     const std::string& tmp_name = tmp_file.GetFilename();
394     size_t tmp_last_slash = tmp_name.rfind('/');
395     std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
396 
397     // Write inputs and expected outputs.
398     std::string dex_file = tmp_dir + "classes.dex";
399     WriteFileBase64(kDexFileLayoutInputDex, dex_file.c_str());
400     std::string profile_file = tmp_dir + "primary.prof";
401     CreateProfile(dex_file, profile_file, dex_file);
402     // WriteFileBase64(kDexFileLayoutInputProfile, profile_file.c_str());
403     std::string output_dex = tmp_dir + "classes.dex.new";
404 
405     std::vector<std::string> dexlayout_args =
406         { "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, dex_file };
407     if (!DexLayoutExec(dexlayout_args, error_msg)) {
408       return false;
409     }
410 
411     // -v makes sure that the layout did not corrupt the dex file.
412     if (!UnlinkFile(dex_file) || !UnlinkFile(profile_file) || !UnlinkFile(output_dex)) {
413       return false;
414     }
415     return true;
416   }
417 
418   // Runs DexFileLayout test twice (second time is run on output of first time)
419   // for behavior consistency.
DexFileLayoutFixedPointExec(std::string * error_msg)420   bool DexFileLayoutFixedPointExec(std::string* error_msg) {
421     ScratchFile tmp_file;
422     const std::string& tmp_name = tmp_file.GetFilename();
423     size_t tmp_last_slash = tmp_name.rfind('/');
424     std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
425 
426     // Unzip the test dex file to the classes.dex destination. It is required to unzip since
427     // opening from jar recalculates the dex location checksum.
428     std::string dex_file = tmp_dir + "classes.dex";
429 
430     std::vector<std::string> unzip_args = {
431         "/usr/bin/unzip",
432         GetTestDexFileName("ManyMethods"),
433         "classes.dex",
434         "-d",
435         tmp_dir,
436     };
437     if (!art::Exec(unzip_args, error_msg)) {
438       LOG(ERROR) << "Failed to unzip dex";
439       return false;
440     }
441 
442     std::string profile_file = tmp_dir + "primary.prof";
443     CreateProfile(dex_file, profile_file, dex_file);
444     std::string output_dex = tmp_dir + "classes.dex.new";
445     std::string second_output_dex = tmp_dir + "classes.dex.new.new";
446 
447     // -v makes sure that the layout did not corrupt the dex file.
448     std::vector<std::string> dexlayout_args =
449         { "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, dex_file };
450     if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option=*/ false)) {
451       return false;
452     }
453 
454     // Recreate the profile with the new dex location. This is required so that the profile dex
455     // location matches.
456     CreateProfile(dex_file, profile_file, output_dex);
457 
458     // -v makes sure that the layout did not corrupt the dex file.
459     // -i since the checksum won't match from the first layout.
460     std::vector<std::string> second_dexlayout_args =
461         { "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, output_dex };
462     if (!DexLayoutExec(second_dexlayout_args, error_msg, /*pass_default_cdex_option=*/ false)) {
463       return false;
464     }
465 
466     bool diff_result = true;
467     std::vector<std::string> diff_exec_argv =
468         { "/usr/bin/diff", output_dex, second_output_dex };
469     if (!::art::Exec(diff_exec_argv, error_msg)) {
470       diff_result = false;
471     }
472 
473     std::vector<std::string> test_files = { dex_file, profile_file, output_dex, second_output_dex };
474     for (const std::string& test_file : test_files) {
475       if (!UnlinkFile(test_file)) {
476         return false;
477       }
478     }
479 
480     return diff_result;
481   }
482 
483   // Runs UnreferencedCatchHandlerTest & Unreferenced0SizeCatchHandlerTest.
UnreferencedCatchHandlerExec(std::string * error_msg,const char * filename)484   bool UnreferencedCatchHandlerExec(std::string* error_msg, const char* filename) {
485     ScratchFile tmp_file;
486     const std::string& tmp_name = tmp_file.GetFilename();
487     size_t tmp_last_slash = tmp_name.rfind('/');
488     std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
489 
490     // Write inputs and expected outputs.
491     std::string input_dex = tmp_dir + "classes.dex";
492     WriteFileBase64(filename, input_dex.c_str());
493     std::string output_dex = tmp_dir + "classes.dex.new";
494 
495     std::vector<std::string> dexlayout_args = { "-w", tmp_dir, "-o", "/dev/null", input_dex };
496     if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option=*/ false)) {
497       return false;
498     }
499 
500     // Diff input and output. They should be the same.
501     std::vector<std::string> diff_exec_argv = { "/usr/bin/diff", input_dex, output_dex };
502     if (!::art::Exec(diff_exec_argv, error_msg)) {
503       return false;
504     }
505 
506     std::vector<std::string> dex_files = { input_dex, output_dex };
507     for (const std::string& dex_file : dex_files) {
508       if (!UnlinkFile(dex_file)) {
509         return false;
510       }
511     }
512     return true;
513   }
514 
DexLayoutExec(ScratchFile * dex_file,const char * dex_filename,ScratchFile * profile_file,const std::vector<std::string> & dexlayout_args)515   bool DexLayoutExec(ScratchFile* dex_file,
516                      const char* dex_filename,
517                      ScratchFile* profile_file,
518                      const std::vector<std::string>& dexlayout_args) {
519     if (dex_filename != nullptr) {
520       WriteBase64ToFile(dex_filename, dex_file->GetFile());
521       EXPECT_EQ(dex_file->GetFile()->Flush(), 0);
522     }
523     if (profile_file != nullptr) {
524       CreateProfile(dex_file->GetFilename(), profile_file->GetFilename(), dex_file->GetFilename());
525     }
526 
527     std::string error_msg;
528     const bool result = DexLayoutExec(dexlayout_args, &error_msg);
529     if (!result) {
530       LOG(ERROR) << "Error: " << error_msg;
531       return false;
532     }
533     return true;
534   }
535 
DexLayoutExec(const std::vector<std::string> & dexlayout_args,std::string * error_msg,bool pass_default_cdex_option=true)536   bool DexLayoutExec(const std::vector<std::string>& dexlayout_args,
537                      std::string* error_msg,
538                      bool pass_default_cdex_option = true) {
539     std::vector<std::string> argv;
540 
541     std::string dexlayout = GetDexLayoutPath();
542     CHECK(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
543     argv.push_back(dexlayout);
544     if (pass_default_cdex_option) {
545       std::vector<std::string> cdex_level = DefaultCompactDexOption();
546       argv.insert(argv.end(), cdex_level.begin(), cdex_level.end());
547     }
548 
549     argv.insert(argv.end(), dexlayout_args.begin(), dexlayout_args.end());
550 
551     return ::art::Exec(argv, error_msg);
552   }
553 
UnlinkFile(const std::string & file_path)554   bool UnlinkFile(const std::string& file_path) {
555     return unix_file::FdFile(file_path, 0, false).Unlink();
556   }
557 };
558 
559 
TEST_F(DexLayoutTest,FullPlainOutput)560 TEST_F(DexLayoutTest, FullPlainOutput) {
561   // Disable test on target.
562   TEST_DISABLED_FOR_TARGET();
563   std::string error_msg;
564   ASSERT_TRUE(FullPlainOutputExec(&error_msg)) << error_msg;
565 }
566 
TEST_F(DexLayoutTest,DexFileOutput)567 TEST_F(DexLayoutTest, DexFileOutput) {
568   // Disable test on target.
569   TEST_DISABLED_FOR_TARGET();
570   std::string error_msg;
571   ASSERT_TRUE(DexFileOutputExec(&error_msg)) << error_msg;
572 }
573 
TEST_F(DexLayoutTest,DexFileLayout)574 TEST_F(DexLayoutTest, DexFileLayout) {
575   // Disable test on target.
576   TEST_DISABLED_FOR_TARGET();
577   std::string error_msg;
578   ASSERT_TRUE(DexFileLayoutExec(&error_msg)) << error_msg;
579 }
580 
TEST_F(DexLayoutTest,DexFileLayoutFixedPoint)581 TEST_F(DexLayoutTest, DexFileLayoutFixedPoint) {
582   // Disable test on target.
583   TEST_DISABLED_FOR_TARGET();
584   std::string error_msg;
585   ASSERT_TRUE(DexFileLayoutFixedPointExec(&error_msg)) << error_msg;
586 }
587 
TEST_F(DexLayoutTest,UnreferencedCatchHandler)588 TEST_F(DexLayoutTest, UnreferencedCatchHandler) {
589   // Disable test on target.
590   TEST_DISABLED_FOR_TARGET();
591   std::string error_msg;
592   ASSERT_TRUE(UnreferencedCatchHandlerExec(&error_msg,
593                                            kUnreferencedCatchHandlerInputDex)) << error_msg;
594 }
595 
TEST_F(DexLayoutTest,Unreferenced0SizeCatchHandler)596 TEST_F(DexLayoutTest, Unreferenced0SizeCatchHandler) {
597   // Disable test on target.
598   TEST_DISABLED_FOR_TARGET();
599   std::string error_msg;
600   ASSERT_TRUE(UnreferencedCatchHandlerExec(&error_msg,
601                                            kUnreferenced0SizeCatchHandlerInputDex)) << error_msg;
602 }
603 
TEST_F(DexLayoutTest,UnreferencedEndingCatchHandler)604 TEST_F(DexLayoutTest, UnreferencedEndingCatchHandler) {
605   // Disable test on target.
606   TEST_DISABLED_FOR_TARGET();
607   std::string error_msg;
608   ASSERT_TRUE(UnreferencedCatchHandlerExec(&error_msg,
609                                            kUnreferencedEndingCatchHandlerInputDex)) << error_msg;
610 }
611 
TEST_F(DexLayoutTest,DuplicateOffset)612 TEST_F(DexLayoutTest, DuplicateOffset) {
613   ScratchFile temp_dex;
614   std::vector<std::string> dexlayout_args =
615       { "-a", "-i", "-o", "/dev/null", temp_dex.GetFilename() };
616   ASSERT_TRUE(DexLayoutExec(&temp_dex,
617                             kDexFileDuplicateOffset,
618                             /* profile_file= */ nullptr,
619                             dexlayout_args));
620 }
621 
TEST_F(DexLayoutTest,NullSetRefListElement)622 TEST_F(DexLayoutTest, NullSetRefListElement) {
623   ScratchFile temp_dex;
624   std::vector<std::string> dexlayout_args = { "-o", "/dev/null", temp_dex.GetFilename() };
625   ASSERT_TRUE(DexLayoutExec(&temp_dex,
626                             kNullSetRefListElementInputDex,
627                             /* profile_file= */ nullptr,
628                             dexlayout_args));
629 }
630 
TEST_F(DexLayoutTest,MultiClassData)631 TEST_F(DexLayoutTest, MultiClassData) {
632   ScratchFile temp_dex;
633   ScratchFile temp_profile;
634   std::vector<std::string> dexlayout_args =
635       { "-p", temp_profile.GetFilename(), "-o", "/dev/null", temp_dex.GetFilename() };
636   ASSERT_TRUE(DexLayoutExec(&temp_dex,
637                             kMultiClassDataInputDex,
638                             &temp_profile,
639                             dexlayout_args));
640 }
641 
TEST_F(DexLayoutTest,UnalignedCodeInfo)642 TEST_F(DexLayoutTest, UnalignedCodeInfo) {
643   ScratchFile temp_dex;
644   ScratchFile temp_profile;
645   std::vector<std::string> dexlayout_args =
646       { "-p", temp_profile.GetFilename(), "-o", "/dev/null", temp_dex.GetFilename() };
647   ASSERT_TRUE(DexLayoutExec(&temp_dex,
648                             kUnalignedCodeInfoInputDex,
649                             &temp_profile,
650                             dexlayout_args));
651 }
652 
TEST_F(DexLayoutTest,ClassDataBeforeCode)653 TEST_F(DexLayoutTest, ClassDataBeforeCode) {
654   ScratchFile temp_dex;
655   ScratchFile temp_profile;
656   std::vector<std::string> dexlayout_args =
657       { "-p", temp_profile.GetFilename(), "-o", "/dev/null", temp_dex.GetFilename() };
658   ASSERT_TRUE(DexLayoutExec(&temp_dex,
659                             kClassDataBeforeCodeInputDex,
660                             &temp_profile,
661                             dexlayout_args));
662 }
663 
TEST_F(DexLayoutTest,UnknownTypeDebugInfo)664 TEST_F(DexLayoutTest, UnknownTypeDebugInfo) {
665   ScratchFile temp_dex;
666   std::vector<std::string> dexlayout_args = { "-o", "/dev/null", temp_dex.GetFilename() };
667   ASSERT_TRUE(DexLayoutExec(&temp_dex,
668                             kUnknownTypeDebugInfoInputDex,
669                             /* profile_file= */ nullptr,
670                             dexlayout_args));
671 }
672 
TEST_F(DexLayoutTest,DuplicateCodeItem)673 TEST_F(DexLayoutTest, DuplicateCodeItem) {
674   ScratchFile temp_dex;
675   std::vector<std::string> dexlayout_args = { "-o", "/dev/null", temp_dex.GetFilename() };
676   ASSERT_TRUE(DexLayoutExec(&temp_dex,
677                             kDuplicateCodeItemInputDex,
678                             /* profile_file= */ nullptr,
679                             dexlayout_args));
680 }
681 
682 // Test that instructions that go past the end of the code items don't cause crashes.
TEST_F(DexLayoutTest,CodeItemOverrun)683 TEST_F(DexLayoutTest, CodeItemOverrun) {
684   ScratchFile temp_dex;
685   MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [] (DexFile* dex) {
686     bool mutated_successfully = false;
687     // Change the dex instructions to make an opcode that spans past the end of the code item.
688     for (ClassAccessor accessor : dex->GetClasses()) {
689       for (const ClassAccessor::Method& method : accessor.GetMethods()) {
690         dex::CodeItem* item = const_cast<dex::CodeItem*>(method.GetCodeItem());
691         if (item != nullptr) {
692           CodeItemInstructionAccessor instructions(*dex, item);
693           if (instructions.begin() != instructions.end()) {
694             DexInstructionIterator last_instruction = instructions.begin();
695             for (auto dex_it = instructions.begin(); dex_it != instructions.end(); ++dex_it) {
696               last_instruction = dex_it;
697             }
698             if (last_instruction->SizeInCodeUnits() == 1) {
699               // Set the opcode to something that will go past the end of the code item.
700               const_cast<Instruction&>(last_instruction.Inst()).SetOpcode(
701                   Instruction::CONST_STRING_JUMBO);
702               mutated_successfully = true;
703               // Test that the safe iterator doesn't go past the end.
704               SafeDexInstructionIterator it2(instructions.begin(), instructions.end());
705               while (!it2.IsErrorState()) {
706                 ++it2;
707               }
708               EXPECT_TRUE(it2 == last_instruction);
709               EXPECT_TRUE(it2 < instructions.end());
710             }
711           }
712         }
713       }
714     }
715     CHECK(mutated_successfully)
716         << "Failed to find candidate code item with only one code unit in last instruction.";
717   });
718 
719   std::string error_msg;
720 
721   ScratchFile tmp_file;
722   const std::string& tmp_name = tmp_file.GetFilename();
723   size_t tmp_last_slash = tmp_name.rfind('/');
724   std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
725   ScratchFile profile_file;
726 
727   std::vector<std::string> dexlayout_args =
728       { "-i",
729         "-v",
730         "-w", tmp_dir,
731         "-o", tmp_name,
732         "-p", profile_file.GetFilename(),
733         temp_dex.GetFilename()
734       };
735   // -v makes sure that the layout did not corrupt the dex file.
736   ASSERT_TRUE(DexLayoutExec(&temp_dex,
737                             /*dex_filename=*/ nullptr,
738                             &profile_file,
739                             dexlayout_args));
740   ASSERT_TRUE(UnlinkFile(temp_dex.GetFilename() + ".new"));
741 }
742 
743 // Test that link data is written out (or at least the header is updated).
TEST_F(DexLayoutTest,LinkData)744 TEST_F(DexLayoutTest, LinkData) {
745   TEST_DISABLED_FOR_TARGET();
746   ScratchFile temp_dex;
747   size_t file_size = 0;
748   MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [&] (DexFile* dex) {
749     DexFile::Header& header = const_cast<DexFile::Header&>(dex->GetHeader());
750     header.link_off_ = header.file_size_;
751     header.link_size_ = 16 * KB;
752     header.file_size_ += header.link_size_;
753     file_size = header.file_size_;
754   });
755   TEMP_FAILURE_RETRY(temp_dex.GetFile()->SetLength(file_size));
756 
757   std::string error_msg;
758 
759   ScratchFile tmp_file;
760   const std::string& tmp_name = tmp_file.GetFilename();
761   size_t tmp_last_slash = tmp_name.rfind('/');
762   std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
763   ScratchFile profile_file;
764 
765   std::vector<std::string> dexlayout_args =
766       { "-i",
767         "-v",
768         "-w", tmp_dir,
769         "-o", tmp_name,
770         "-p", profile_file.GetFilename(),
771         temp_dex.GetFilename()
772       };
773   // -v makes sure that the layout did not corrupt the dex file.
774   ASSERT_TRUE(DexLayoutExec(&temp_dex,
775                             /*dex_filename=*/ nullptr,
776                             &profile_file,
777                             dexlayout_args));
778   ASSERT_TRUE(UnlinkFile(temp_dex.GetFilename() + ".new"));
779 }
780 
TEST_F(DexLayoutTest,ClassFilter)781 TEST_F(DexLayoutTest, ClassFilter) {
782   std::vector<std::unique_ptr<const DexFile>> dex_files;
783   std::string error_msg;
784   const ArtDexFileLoader dex_file_loader;
785   const std::string input_jar = GetTestDexFileName("ManyMethods");
786   CHECK(dex_file_loader.Open(input_jar.c_str(),
787                              input_jar.c_str(),
788                              /*verify=*/ true,
789                              /*verify_checksum=*/ true,
790                              &error_msg,
791                              &dex_files)) << error_msg;
792   ASSERT_EQ(dex_files.size(), 1u);
793   for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
794     EXPECT_GT(dex_file->NumClassDefs(), 1u);
795     for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
796       const dex::ClassDef& class_def = dex_file->GetClassDef(i);
797       LOG(INFO) << dex_file->GetClassDescriptor(class_def);
798     }
799     Options options;
800     // Filter out all the classes other than the one below based on class descriptor.
801     options.class_filter_.insert("LManyMethods$Strings;");
802     DexLayout dexlayout(options,
803                         /*info=*/ nullptr,
804                         /*out_file=*/ nullptr,
805                         /*header=*/ nullptr);
806     std::unique_ptr<DexContainer> out;
807     bool result = dexlayout.ProcessDexFile(
808         dex_file->GetLocation().c_str(),
809         dex_file.get(),
810         /*dex_file_index=*/ 0,
811         &out,
812         &error_msg);
813     ASSERT_TRUE(result) << "Failed to run dexlayout " << error_msg;
814     std::unique_ptr<const DexFile> output_dex_file(
815         dex_file_loader.OpenWithDataSection(
816             out->GetMainSection()->Begin(),
817             out->GetMainSection()->Size(),
818             out->GetDataSection()->Begin(),
819             out->GetDataSection()->Size(),
820             dex_file->GetLocation().c_str(),
821             /* location_checksum= */ 0,
822             /*oat_dex_file=*/ nullptr,
823             /* verify= */ true,
824             /*verify_checksum=*/ false,
825             &error_msg));
826     ASSERT_TRUE(output_dex_file != nullptr);
827 
828     ASSERT_EQ(output_dex_file->NumClassDefs(), options.class_filter_.size());
829     for (uint32_t i = 0; i < output_dex_file->NumClassDefs(); ++i) {
830       // Check that every class in the output dex file is in the filter.
831       const dex::ClassDef& class_def = output_dex_file->GetClassDef(i);
832       ASSERT_TRUE(options.class_filter_.find(output_dex_file->GetClassDescriptor(class_def)) !=
833           options.class_filter_.end());
834     }
835   }
836 }
837 
838 }  // namespace art
839