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