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