blob: 096461984ae1905c2da65c2c744e8de3389c350c [file] [log] [blame]
Jeff Haoc3acfc52016-08-29 14:18:26 -07001/*
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
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070017#include <sstream>
Jeff Haoc3acfc52016-08-29 14:18:26 -070018#include <string>
19#include <vector>
Jeff Haoc3acfc52016-08-29 14:18:26 -070020
21#include <sys/types.h>
22#include <unistd.h>
23
Jeff Hao042e8982016-10-19 11:17:11 -070024#include "base/unix_file/fd_file.h"
David Sehrc431b9d2018-03-02 12:01:51 -080025#include "base/utils.h"
David Sehra8d23cb2019-04-08 11:29:11 -070026#include "base/common_art_test.h"
David Sehr013fd802018-01-11 22:55:24 -080027#include "dex/art_dex_file_loader.h"
David Sehre1123402018-02-01 02:46:18 -080028#include "dex/base64_test_util.h"
Mathieu Chartiera34812c2018-08-01 17:10:43 -070029#include "dex/class_accessor-inl.h"
David Sehr9e734c72018-01-04 17:56:19 -080030#include "dex/code_item_accessors-inl.h"
31#include "dex/dex_file-inl.h"
32#include "dex/dex_file_loader.h"
Mathieu Chartier75175552018-01-25 11:23:01 -080033#include "dexlayout.h"
David Sehr97c381e2017-02-01 15:09:58 -080034#include "exec_utils.h"
David Sehr82d046e2018-04-23 08:14:19 -070035#include "profile/profile_compilation_info.h"
Jeff Haoc3acfc52016-08-29 14:18:26 -070036
37namespace art {
38
Jeff Hao042e8982016-10-19 11:17:11 -070039static 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
Jeff Haoe17f5892017-02-23 16:14:04 -080051// Dex file with catch handler unreferenced by try blocks.
52// Constructed by building a dex file with try/catch blocks and hex editing.
53static 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
Jeff Haoac462712017-03-02 10:59:43 -080071// 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.
73static 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
Jeff Haoa64a64c2017-03-06 15:05:38 -080091// 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.
93static 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
Mathieu Chartier6b0dbef2017-02-21 12:45:30 -0800114// Dex file with multiple code items that have the same debug_info_off_. Constructed by a modified
115// dexlayout on XandY.
116static 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
Jeff Haof914f8e2017-02-21 16:14:23 -0800137// 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.
139static 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
Jeff Haoe17f5892017-02-23 16:14:04 -0800159// 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.
161static 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.
173static const char kUnalignedCodeInfoInputDex[] =
174 "ZGV4CjAzNQDXJzXNb4iWn2SLhmLydW/8h1K9moERIw7UAQAAcAAAAHhWNBIAAAAAAAAAAEwBAAAG"
175 "AAAAcAAAAAMAAACIAAAAAQAAAJQAAAAAAAAAAAAAAAMAAACgAAAAAQAAALgAAAD8AAAA2AAAAAIB"
176 "AAAKAQAAEgEAABcBAAArAQAALgEAAAIAAAADAAAABAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAA"
177 "AAUAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAABAAAAAAAAADsBAAAAAAAAAQABAAEAAAAxAQAA"
178 "BAAAAHAQAgAAAA4AAQABAAAAAAA2AQAAAQAAAA4ABjxpbml0PgAGQS5qYXZhAANMQTsAEkxqYXZh"
179 "L2xhbmcvT2JqZWN0OwABVgABYQABAAcOAAMABw4AAAABAQCBgATYAQEB8AEAAAALAAAAAAAAAAEA"
180 "AAAAAAAAAQAAAAYAAABwAAAAAgAAAAMAAACIAAAAAwAAAAEAAACUAAAABQAAAAMAAACgAAAABgAA"
181 "AAEAAAC4AAAAASAAAAIAAADYAAAAAiAAAAYAAAACAQAAAyAAAAIAAAAxAQAAACAAAAEAAAA7AQAA"
182 "ABAAAAEAAABMAQAA";
Jeff Hao44652a32017-02-22 14:20:41 -0800183
Jeff Hao32a60ab2017-03-01 16:44:50 -0800184// Dex file with class data section preceding code items.
185// Constructed by passing dex file through dexmerger tool and hex editing.
186static 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
Jeff Haod9be7682017-04-05 09:29:43 -0700199// 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.
202static const char kUnknownTypeDebugInfoInputDex[] =
203 "ZGV4CjAzNQBtKqZfzjHLNSNwW2A6Bz9FuCEX0sL+FF38AQAAcAAAAHhWNBIAAAAAAAAAAHQBAAAI"
204 "AAAAcAAAAAQAAACQAAAAAgAAAKAAAAAAAAAAAAAAAAMAAAC4AAAAAQAAANAAAAAMAQAA8AAAABwB"
205 "AAAkAQAALAEAAC8BAAA0AQAASAEAAEsBAABOAQAAAgAAAAMAAAAEAAAABQAAAAIAAAAAAAAAAAAA"
206 "AAUAAAADAAAAAAAAAAEAAQAAAAAAAQAAAAYAAAACAAEAAAAAAAEAAAABAAAAAgAAAAAAAAABAAAA"
207 "AAAAAGMBAAAAAAAAAQABAAEAAABUAQAABAAAAHAQAgAAAA4AAgABAAAAAABZAQAAAgAAABIQDwAG"
208 "PGluaXQ+AAZBLmphdmEAAUkAA0xBOwASTGphdmEvbGFuZy9PYmplY3Q7AAFWAAFhAAR0aGlzAAEA"
209 "Bw4AAwAHDh4GAAYAAAAAAQEAgYAE8AEBAYgCAAAACwAAAAAAAAABAAAAAAAAAAEAAAAIAAAAcAAA"
210 "AAIAAAAEAAAAkAAAAAMAAAACAAAAoAAAAAUAAAADAAAAuAAAAAYAAAABAAAA0AAAAAEgAAACAAAA"
211 "8AAAAAIgAAAIAAAAHAEAAAMgAAACAAAAVAEAAAAgAAABAAAAYwEAAAAQAAABAAAAdAEAAA==";
212
Jeff Haod212d5b2017-04-26 12:09:06 -0700213// Dex file with multiple class data items pointing to the same code item.
214// Constructed by hex editing.
215static const char kDuplicateCodeItemInputDex[] =
216 "ZGV4CjAzNQCwKtVglQOmLWuHwldN5jkBOInC7mTMhJMAAgAAcAAAAHhWNBIAAAAAAAAAAHgBAAAH"
217 "AAAAcAAAAAMAAACMAAAAAQAAAJgAAAAAAAAAAAAAAAQAAACkAAAAAQAAAMQAAAAcAQAA5AAAACQB"
218 "AAAsAQAANAEAADkBAABNAQAAUAEAAFMBAAACAAAAAwAAAAQAAAAEAAAAAgAAAAAAAAAAAAAAAAAA"
219 "AAAAAAAFAAAAAAAAAAYAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAABAAAAAAAAAGUBAAAAAAAA"
220 "AQABAAEAAABWAQAABAAAAHAQAwAAAA4AAQABAAAAAABbAQAAAQAAAA4AAAABAAEAAAAAAGABAAAB"
221 "AAAADgAAAAY8aW5pdD4ABkEuamF2YQADTEE7ABJMamF2YS9sYW5nL09iamVjdDsAAVYAAWEAAWIA"
222 "AQAHDgADAAcOAAUABw4AAAABAgCBgATkAQEA/AEBAPwBAAsAAAAAAAAAAQAAAAAAAAABAAAABwAA"
223 "AHAAAAACAAAAAwAAAIwAAAADAAAAAQAAAJgAAAAFAAAABAAAAKQAAAAGAAAAAQAAAMQAAAABIAAA"
224 "AwAAAOQAAAACIAAABwAAACQBAAADIAAAAwAAAFYBAAAAIAAAAQAAAGUBAAAAEAAAAQAAAHgBAAA=";
225
Mathieu Chartiera27af082018-02-03 16:12:23 -0800226// Returns the default compact dex option for dexlayout based on kDefaultCompactDexLevel.
227static 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
Mathieu Chartier6b0dbef2017-02-21 12:45:30 -0800232static void WriteBase64ToFile(const char* base64, File* file) {
Jeff Hao042e8982016-10-19 11:17:11 -0700233 // Decode base64.
234 CHECK(base64 != nullptr);
235 size_t length;
236 std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
Mathieu Chartier6b0dbef2017-02-21 12:45:30 -0800237 CHECK(bytes != nullptr);
Jeff Hao042e8982016-10-19 11:17:11 -0700238 if (!file->WriteFully(bytes.get(), length)) {
239 PLOG(FATAL) << "Failed to write base64 as file";
240 }
Mathieu Chartier6b0dbef2017-02-21 12:45:30 -0800241}
242
243static 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());
Jeff Hao042e8982016-10-19 11:17:11 -0700248 if (file->FlushCloseOrErase() != 0) {
249 PLOG(FATAL) << "Could not flush and close test file.";
250 }
251}
252
David Sehra8d23cb2019-04-08 11:29:11 -0700253class DexLayoutTest : public CommonArtTest {
Jeff Haoc3acfc52016-08-29 14:18:26 -0700254 protected:
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800255 std::string GetDexLayoutPath() {
256 return GetTestAndroidRoot() + "/bin/dexlayoutd";
Jeff Haoc3acfc52016-08-29 14:18:26 -0700257 }
258
Jeff Haoa8621002016-10-04 18:13:44 +0000259 // Runs FullPlainOutput test.
260 bool FullPlainOutputExec(std::string* error_msg) {
Jeff Haoc3acfc52016-08-29 14:18:26 -0700261 ScratchFile dexdump_output;
Andreas Gampeca620d72016-11-08 08:09:33 -0800262 const std::string& dexdump_filename = dexdump_output.GetFilename();
David Sehr4f215d12019-04-03 09:28:21 -0700263 std::string dexdump = GetTestAndroidRoot() + "/bin/dexdump";
Jeff Haoc3acfc52016-08-29 14:18:26 -0700264 EXPECT_TRUE(OS::FileExists(dexdump.c_str())) << dexdump << " should be a valid file path";
Jeff Haoc3acfc52016-08-29 14:18:26 -0700265
266 ScratchFile dexlayout_output;
Andreas Gampeca620d72016-11-08 08:09:33 -0800267 const std::string& dexlayout_filename = dexlayout_output.GetFilename();
Jeff Haoc3acfc52016-08-29 14:18:26 -0700268
Mathieu Chartier41468402018-08-29 11:39:00 -0700269 for (const std::string& dex_file : GetLibCoreDexFileNames()) {
Jeff Haoa8621002016-10-04 18:13:44 +0000270 std::vector<std::string> dexdump_exec_argv =
271 { dexdump, "-d", "-f", "-h", "-l", "plain", "-o", dexdump_filename, dex_file };
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800272 std::vector<std::string> dexlayout_args =
273 { "-d", "-f", "-h", "-l", "plain", "-o", dexlayout_filename, dex_file };
Jeff Haoa8621002016-10-04 18:13:44 +0000274 if (!::art::Exec(dexdump_exec_argv, error_msg)) {
275 return false;
276 }
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800277 if (!DexLayoutExec(dexlayout_args, error_msg)) {
Jeff Haoa8621002016-10-04 18:13:44 +0000278 return false;
279 }
280 std::vector<std::string> diff_exec_argv =
281 { "/usr/bin/diff", dexdump_filename, dexlayout_filename };
282 if (!::art::Exec(diff_exec_argv, error_msg)) {
283 return false;
284 }
Jeff Haoc3acfc52016-08-29 14:18:26 -0700285 }
286 return true;
287 }
288
Jeff Haoa8621002016-10-04 18:13:44 +0000289 // Runs DexFileOutput test.
290 bool DexFileOutputExec(std::string* error_msg) {
291 ScratchFile tmp_file;
Andreas Gampeca620d72016-11-08 08:09:33 -0800292 const std::string& tmp_name = tmp_file.GetFilename();
293 size_t tmp_last_slash = tmp_name.rfind('/');
Jeff Haoa8621002016-10-04 18:13:44 +0000294 std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
Mathieu Chartier41468402018-08-29 11:39:00 -0700295 std::string unzip_dir = tmp_dir + "unzip/";
Jeff Haoa8621002016-10-04 18:13:44 +0000296
Mathieu Chartier41468402018-08-29 11:39:00 -0700297 for (const std::string& dex_file : GetLibCoreDexFileNames()) {
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800298 std::vector<std::string> dexlayout_args =
299 { "-w", tmp_dir, "-o", tmp_name, dex_file };
Andreas Gampe9b031f72018-10-04 11:03:34 -0700300 if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option=*/ false)) {
Jeff Haoa8621002016-10-04 18:13:44 +0000301 return false;
302 }
Mathieu Chartier41468402018-08-29 11:39:00 -0700303 std::string dex_file_name = "classes.dex";
Jeff Haoa8621002016-10-04 18:13:44 +0000304 std::vector<std::string> unzip_exec_argv =
Mathieu Chartier41468402018-08-29 11:39:00 -0700305 { "/usr/bin/unzip", dex_file, "classes.dex", "-d", unzip_dir};
Jeff Haoa8621002016-10-04 18:13:44 +0000306 if (!::art::Exec(unzip_exec_argv, error_msg)) {
307 return false;
308 }
309 std::vector<std::string> diff_exec_argv =
Mathieu Chartier41468402018-08-29 11:39:00 -0700310 { "/usr/bin/diff", tmp_dir + "classes.dex" , unzip_dir + dex_file_name };
Jeff Haoa8621002016-10-04 18:13:44 +0000311 if (!::art::Exec(diff_exec_argv, error_msg)) {
312 return false;
313 }
Mathieu Chartier41468402018-08-29 11:39:00 -0700314 if (!UnlinkFile(unzip_dir + "classes.dex")) {
Jeff Haoa8621002016-10-04 18:13:44 +0000315 return false;
316 }
Orion Hodson98273672018-02-06 11:50:27 +0000317 if (!UnlinkFile(tmp_dir + dex_file_name)) {
Jeff Haoa8621002016-10-04 18:13:44 +0000318 return false;
319 }
Mathieu Chartier41468402018-08-29 11:39:00 -0700320 // Remove the unzip temp directory so that unlinking android_data doesn't fail.
321 EXPECT_EQ(rmdir(unzip_dir.c_str()), 0);
Jeff Haoa8621002016-10-04 18:13:44 +0000322 }
Jeff Hao042e8982016-10-19 11:17:11 -0700323 return true;
324 }
Jeff Haoa8621002016-10-04 18:13:44 +0000325
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700326 // Create a profile with some subset of methods and classes.
327 void CreateProfile(const std::string& input_dex,
328 const std::string& out_profile,
329 const std::string& dex_location) {
330 std::vector<std::unique_ptr<const DexFile>> dex_files;
331 std::string error_msg;
David Sehr013fd802018-01-11 22:55:24 -0800332 const ArtDexFileLoader dex_file_loader;
333 bool result = dex_file_loader.Open(input_dex.c_str(),
334 input_dex,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700335 /*verify=*/ true,
336 /*verify_checksum=*/ false,
David Sehr013fd802018-01-11 22:55:24 -0800337 &error_msg,
338 &dex_files);
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700339
340 ASSERT_TRUE(result) << error_msg;
341 ASSERT_GE(dex_files.size(), 1u);
342
343 size_t profile_methods = 0;
344 size_t profile_classes = 0;
345 ProfileCompilationInfo pfi;
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700346 std::set<DexCacheResolvedClasses> classes;
347 for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
348 for (uint32_t i = 0; i < dex_file->NumMethodIds(); i += 2) {
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700349 uint8_t flags = 0u;
350
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700351 if ((i & 3) != 0) {
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700352 flags |= ProfileCompilationInfo::MethodHotness::kFlagHot;
Mathieu Chartierea650f32017-05-24 12:04:13 -0700353 ++profile_methods;
354 } else if ((i & 2) != 0) {
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700355 flags |= ProfileCompilationInfo::MethodHotness::kFlagStartup;
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700356 ++profile_methods;
357 }
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700358 pfi.AddMethodIndex(static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
359 dex_location,
360 dex_file->GetLocationChecksum(),
Andreas Gampe9b031f72018-10-04 11:03:34 -0700361 /*method_idx=*/i,
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700362 dex_file->NumMethodIds());
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700363 }
364 DexCacheResolvedClasses cur_classes(dex_location,
365 dex_location,
Mathieu Chartierea650f32017-05-24 12:04:13 -0700366 dex_file->GetLocationChecksum(),
367 dex_file->NumMethodIds());
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700368 // Add every even class too.
369 for (uint32_t i = 0; i < dex_file->NumClassDefs(); i += 1) {
Mathieu Chartierea650f32017-05-24 12:04:13 -0700370 if ((i & 2) == 0) {
371 cur_classes.AddClass(dex_file->GetClassDef(i).class_idx_);
372 ++profile_classes;
373 }
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700374 }
Mathieu Chartierea650f32017-05-24 12:04:13 -0700375 classes.insert(cur_classes);
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700376 }
Mathieu Chartierbbe3a5e2017-06-13 16:36:17 -0700377 pfi.AddClasses(classes);
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700378 // Write to provided file.
379 std::unique_ptr<File> file(OS::CreateEmptyFile(out_profile.c_str()));
380 ASSERT_TRUE(file != nullptr);
381 pfi.Save(file->Fd());
382 if (file->FlushCloseOrErase() != 0) {
383 PLOG(FATAL) << "Could not flush and close test file.";
384 }
385 EXPECT_GE(profile_methods, 0u);
386 EXPECT_GE(profile_classes, 0u);
387 }
388
Jeff Haod9be7682017-04-05 09:29:43 -0700389 // Runs DexFileLayout test.
Jeff Hao042e8982016-10-19 11:17:11 -0700390 bool DexFileLayoutExec(std::string* error_msg) {
391 ScratchFile tmp_file;
Andreas Gampe641a4732017-08-24 13:21:35 -0700392 const std::string& tmp_name = tmp_file.GetFilename();
Andreas Gampe5555dd12017-08-24 13:50:21 -0700393 size_t tmp_last_slash = tmp_name.rfind('/');
Jeff Hao042e8982016-10-19 11:17:11 -0700394 std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
395
396 // Write inputs and expected outputs.
397 std::string dex_file = tmp_dir + "classes.dex";
398 WriteFileBase64(kDexFileLayoutInputDex, dex_file.c_str());
399 std::string profile_file = tmp_dir + "primary.prof";
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700400 CreateProfile(dex_file, profile_file, dex_file);
401 // WriteFileBase64(kDexFileLayoutInputProfile, profile_file.c_str());
Jeff Hao042e8982016-10-19 11:17:11 -0700402 std::string output_dex = tmp_dir + "classes.dex.new";
403
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800404 std::vector<std::string> dexlayout_args =
405 { "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, dex_file };
406 if (!DexLayoutExec(dexlayout_args, error_msg)) {
Jeff Hao042e8982016-10-19 11:17:11 -0700407 return false;
408 }
Mathieu Chartierfa0aa092017-03-27 15:43:54 -0700409
410 // -v makes sure that the layout did not corrupt the dex file.
Orion Hodson98273672018-02-06 11:50:27 +0000411 if (!UnlinkFile(dex_file) || !UnlinkFile(profile_file) || !UnlinkFile(output_dex)) {
Jeff Hao042e8982016-10-19 11:17:11 -0700412 return false;
413 }
Jeff Haoa8621002016-10-04 18:13:44 +0000414 return true;
415 }
Jeff Hao44652a32017-02-22 14:20:41 -0800416
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700417 // Runs DexFileLayout test twice (second time is run on output of first time)
418 // for behavior consistency.
419 bool DexFileLayoutFixedPointExec(std::string* error_msg) {
420 ScratchFile tmp_file;
Andreas Gampe641a4732017-08-24 13:21:35 -0700421 const std::string& tmp_name = tmp_file.GetFilename();
Andreas Gampe5555dd12017-08-24 13:50:21 -0700422 size_t tmp_last_slash = tmp_name.rfind('/');
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700423 std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
424
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700425 // Unzip the test dex file to the classes.dex destination. It is required to unzip since
426 // opening from jar recalculates the dex location checksum.
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700427 std::string dex_file = tmp_dir + "classes.dex";
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700428
429 std::vector<std::string> unzip_args = {
430 "/usr/bin/unzip",
431 GetTestDexFileName("ManyMethods"),
432 "classes.dex",
433 "-d",
434 tmp_dir,
435 };
436 if (!art::Exec(unzip_args, error_msg)) {
437 LOG(ERROR) << "Failed to unzip dex";
438 return false;
439 }
440
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700441 std::string profile_file = tmp_dir + "primary.prof";
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700442 CreateProfile(dex_file, profile_file, dex_file);
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700443 std::string output_dex = tmp_dir + "classes.dex.new";
444 std::string second_output_dex = tmp_dir + "classes.dex.new.new";
445
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700446 // -v makes sure that the layout did not corrupt the dex file.
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800447 std::vector<std::string> dexlayout_args =
448 { "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, dex_file };
Andreas Gampe9b031f72018-10-04 11:03:34 -0700449 if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option=*/ false)) {
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700450 return false;
451 }
452
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700453 // Recreate the profile with the new dex location. This is required so that the profile dex
454 // location matches.
455 CreateProfile(dex_file, profile_file, output_dex);
456
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700457 // -v makes sure that the layout did not corrupt the dex file.
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700458 // -i since the checksum won't match from the first layout.
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800459 std::vector<std::string> second_dexlayout_args =
460 { "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, output_dex };
Andreas Gampe9b031f72018-10-04 11:03:34 -0700461 if (!DexLayoutExec(second_dexlayout_args, error_msg, /*pass_default_cdex_option=*/ false)) {
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700462 return false;
463 }
464
465 bool diff_result = true;
466 std::vector<std::string> diff_exec_argv =
467 { "/usr/bin/diff", output_dex, second_output_dex };
468 if (!::art::Exec(diff_exec_argv, error_msg)) {
469 diff_result = false;
470 }
471
Orion Hodson98273672018-02-06 11:50:27 +0000472 std::vector<std::string> test_files = { dex_file, profile_file, output_dex, second_output_dex };
Andreas Gampebc802de2018-06-20 17:24:11 -0700473 for (const std::string& test_file : test_files) {
Orion Hodson98273672018-02-06 11:50:27 +0000474 if (!UnlinkFile(test_file)) {
475 return false;
476 }
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700477 }
478
479 return diff_result;
480 }
481
Jeff Haoac462712017-03-02 10:59:43 -0800482 // Runs UnreferencedCatchHandlerTest & Unreferenced0SizeCatchHandlerTest.
483 bool UnreferencedCatchHandlerExec(std::string* error_msg, const char* filename) {
Jeff Hao44652a32017-02-22 14:20:41 -0800484 ScratchFile tmp_file;
Andreas Gampe641a4732017-08-24 13:21:35 -0700485 const std::string& tmp_name = tmp_file.GetFilename();
Andreas Gampe5555dd12017-08-24 13:50:21 -0700486 size_t tmp_last_slash = tmp_name.rfind('/');
Jeff Hao44652a32017-02-22 14:20:41 -0800487 std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
488
489 // Write inputs and expected outputs.
490 std::string input_dex = tmp_dir + "classes.dex";
Jeff Haoac462712017-03-02 10:59:43 -0800491 WriteFileBase64(filename, input_dex.c_str());
Jeff Hao44652a32017-02-22 14:20:41 -0800492 std::string output_dex = tmp_dir + "classes.dex.new";
493
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800494 std::vector<std::string> dexlayout_args = { "-w", tmp_dir, "-o", "/dev/null", input_dex };
Andreas Gampe9b031f72018-10-04 11:03:34 -0700495 if (!DexLayoutExec(dexlayout_args, error_msg, /*pass_default_cdex_option=*/ false)) {
Jeff Hao44652a32017-02-22 14:20:41 -0800496 return false;
497 }
498
499 // Diff input and output. They should be the same.
500 std::vector<std::string> diff_exec_argv = { "/usr/bin/diff", input_dex, output_dex };
501 if (!::art::Exec(diff_exec_argv, error_msg)) {
502 return false;
503 }
504
Orion Hodson98273672018-02-06 11:50:27 +0000505 std::vector<std::string> dex_files = { input_dex, output_dex };
Andreas Gampebc802de2018-06-20 17:24:11 -0700506 for (const std::string& dex_file : dex_files) {
Orion Hodson98273672018-02-06 11:50:27 +0000507 if (!UnlinkFile(dex_file)) {
508 return false;
509 }
Jeff Hao44652a32017-02-22 14:20:41 -0800510 }
511 return true;
512 }
Jeff Haod9be7682017-04-05 09:29:43 -0700513
514 bool DexLayoutExec(ScratchFile* dex_file,
515 const char* dex_filename,
516 ScratchFile* profile_file,
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800517 const std::vector<std::string>& dexlayout_args) {
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700518 if (dex_filename != nullptr) {
519 WriteBase64ToFile(dex_filename, dex_file->GetFile());
520 EXPECT_EQ(dex_file->GetFile()->Flush(), 0);
521 }
Jeff Haod9be7682017-04-05 09:29:43 -0700522 if (profile_file != nullptr) {
Mathieu Chartierd00e02b2017-05-24 12:04:13 -0700523 CreateProfile(dex_file->GetFilename(), profile_file->GetFilename(), dex_file->GetFilename());
Jeff Haod9be7682017-04-05 09:29:43 -0700524 }
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800525
Jeff Haod9be7682017-04-05 09:29:43 -0700526 std::string error_msg;
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800527 const bool result = DexLayoutExec(dexlayout_args, &error_msg);
Jeff Haod9be7682017-04-05 09:29:43 -0700528 if (!result) {
529 LOG(ERROR) << "Error: " << error_msg;
530 return false;
531 }
532 return true;
533 }
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800534
Mathieu Chartiera27af082018-02-03 16:12:23 -0800535 bool DexLayoutExec(const std::vector<std::string>& dexlayout_args,
536 std::string* error_msg,
537 bool pass_default_cdex_option = true) {
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800538 std::vector<std::string> argv;
539
540 std::string dexlayout = GetDexLayoutPath();
541 CHECK(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
542 argv.push_back(dexlayout);
Mathieu Chartiera27af082018-02-03 16:12:23 -0800543 if (pass_default_cdex_option) {
544 std::vector<std::string> cdex_level = DefaultCompactDexOption();
545 argv.insert(argv.end(), cdex_level.begin(), cdex_level.end());
546 }
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800547
548 argv.insert(argv.end(), dexlayout_args.begin(), dexlayout_args.end());
549
550 return ::art::Exec(argv, error_msg);
551 }
Orion Hodson98273672018-02-06 11:50:27 +0000552
553 bool UnlinkFile(const std::string& file_path) {
554 return unix_file::FdFile(file_path, 0, false).Unlink();
555 }
Jeff Haoc3acfc52016-08-29 14:18:26 -0700556};
557
558
559TEST_F(DexLayoutTest, FullPlainOutput) {
Jeff Hao0f7eaeb2016-08-31 17:56:13 -0700560 // Disable test on target.
561 TEST_DISABLED_FOR_TARGET();
Jeff Haoc3acfc52016-08-29 14:18:26 -0700562 std::string error_msg;
Jeff Haoa8621002016-10-04 18:13:44 +0000563 ASSERT_TRUE(FullPlainOutputExec(&error_msg)) << error_msg;
564}
565
566TEST_F(DexLayoutTest, DexFileOutput) {
567 // Disable test on target.
568 TEST_DISABLED_FOR_TARGET();
569 std::string error_msg;
570 ASSERT_TRUE(DexFileOutputExec(&error_msg)) << error_msg;
Jeff Haoc3acfc52016-08-29 14:18:26 -0700571}
572
Jeff Hao042e8982016-10-19 11:17:11 -0700573TEST_F(DexLayoutTest, DexFileLayout) {
574 // Disable test on target.
575 TEST_DISABLED_FOR_TARGET();
576 std::string error_msg;
577 ASSERT_TRUE(DexFileLayoutExec(&error_msg)) << error_msg;
578}
579
Bharadwaj Kalandhabhatta02ef6402017-05-17 17:13:39 -0700580TEST_F(DexLayoutTest, DexFileLayoutFixedPoint) {
581 // Disable test on target.
582 TEST_DISABLED_FOR_TARGET();
583 std::string error_msg;
584 ASSERT_TRUE(DexFileLayoutFixedPointExec(&error_msg)) << error_msg;
585}
586
Jeff Haoe17f5892017-02-23 16:14:04 -0800587TEST_F(DexLayoutTest, UnreferencedCatchHandler) {
588 // Disable test on target.
589 TEST_DISABLED_FOR_TARGET();
590 std::string error_msg;
Jeff Haoac462712017-03-02 10:59:43 -0800591 ASSERT_TRUE(UnreferencedCatchHandlerExec(&error_msg,
592 kUnreferencedCatchHandlerInputDex)) << error_msg;
Jeff Haoe17f5892017-02-23 16:14:04 -0800593}
Jeff Haoac462712017-03-02 10:59:43 -0800594
595TEST_F(DexLayoutTest, Unreferenced0SizeCatchHandler) {
596 // Disable test on target.
597 TEST_DISABLED_FOR_TARGET();
598 std::string error_msg;
599 ASSERT_TRUE(UnreferencedCatchHandlerExec(&error_msg,
600 kUnreferenced0SizeCatchHandlerInputDex)) << error_msg;
601}
602
Jeff Haoa64a64c2017-03-06 15:05:38 -0800603TEST_F(DexLayoutTest, UnreferencedEndingCatchHandler) {
604 // Disable test on target.
605 TEST_DISABLED_FOR_TARGET();
606 std::string error_msg;
607 ASSERT_TRUE(UnreferencedCatchHandlerExec(&error_msg,
608 kUnreferencedEndingCatchHandlerInputDex)) << error_msg;
609}
610
Mathieu Chartier6b0dbef2017-02-21 12:45:30 -0800611TEST_F(DexLayoutTest, DuplicateOffset) {
Jeff Haod9be7682017-04-05 09:29:43 -0700612 ScratchFile temp_dex;
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800613 std::vector<std::string> dexlayout_args =
614 { "-a", "-i", "-o", "/dev/null", temp_dex.GetFilename() };
Jeff Haod9be7682017-04-05 09:29:43 -0700615 ASSERT_TRUE(DexLayoutExec(&temp_dex,
616 kDexFileDuplicateOffset,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700617 /* profile_file= */ nullptr,
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800618 dexlayout_args));
Mathieu Chartier6b0dbef2017-02-21 12:45:30 -0800619}
620
Jeff Haof914f8e2017-02-21 16:14:23 -0800621TEST_F(DexLayoutTest, NullSetRefListElement) {
Jeff Haod9be7682017-04-05 09:29:43 -0700622 ScratchFile temp_dex;
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800623 std::vector<std::string> dexlayout_args = { "-o", "/dev/null", temp_dex.GetFilename() };
Jeff Haod9be7682017-04-05 09:29:43 -0700624 ASSERT_TRUE(DexLayoutExec(&temp_dex,
625 kNullSetRefListElementInputDex,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700626 /* profile_file= */ nullptr,
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800627 dexlayout_args));
Jeff Haof914f8e2017-02-21 16:14:23 -0800628}
629
Jeff Haoe17f5892017-02-23 16:14:04 -0800630TEST_F(DexLayoutTest, MultiClassData) {
Jeff Haod9be7682017-04-05 09:29:43 -0700631 ScratchFile temp_dex;
632 ScratchFile temp_profile;
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800633 std::vector<std::string> dexlayout_args =
634 { "-p", temp_profile.GetFilename(), "-o", "/dev/null", temp_dex.GetFilename() };
Jeff Haod9be7682017-04-05 09:29:43 -0700635 ASSERT_TRUE(DexLayoutExec(&temp_dex,
636 kMultiClassDataInputDex,
637 &temp_profile,
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800638 dexlayout_args));
Jeff Haoe17f5892017-02-23 16:14:04 -0800639}
640
641TEST_F(DexLayoutTest, UnalignedCodeInfo) {
Jeff Haod9be7682017-04-05 09:29:43 -0700642 ScratchFile temp_dex;
643 ScratchFile temp_profile;
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800644 std::vector<std::string> dexlayout_args =
645 { "-p", temp_profile.GetFilename(), "-o", "/dev/null", temp_dex.GetFilename() };
Jeff Haod9be7682017-04-05 09:29:43 -0700646 ASSERT_TRUE(DexLayoutExec(&temp_dex,
647 kUnalignedCodeInfoInputDex,
648 &temp_profile,
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800649 dexlayout_args));
Jeff Hao44652a32017-02-22 14:20:41 -0800650}
651
Jeff Hao32a60ab2017-03-01 16:44:50 -0800652TEST_F(DexLayoutTest, ClassDataBeforeCode) {
Jeff Haod9be7682017-04-05 09:29:43 -0700653 ScratchFile temp_dex;
654 ScratchFile temp_profile;
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800655 std::vector<std::string> dexlayout_args =
656 { "-p", temp_profile.GetFilename(), "-o", "/dev/null", temp_dex.GetFilename() };
Jeff Haod9be7682017-04-05 09:29:43 -0700657 ASSERT_TRUE(DexLayoutExec(&temp_dex,
658 kClassDataBeforeCodeInputDex,
659 &temp_profile,
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800660 dexlayout_args));
Jeff Haod9be7682017-04-05 09:29:43 -0700661}
662
663TEST_F(DexLayoutTest, UnknownTypeDebugInfo) {
664 ScratchFile temp_dex;
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800665 std::vector<std::string> dexlayout_args = { "-o", "/dev/null", temp_dex.GetFilename() };
Jeff Haod9be7682017-04-05 09:29:43 -0700666 ASSERT_TRUE(DexLayoutExec(&temp_dex,
667 kUnknownTypeDebugInfoInputDex,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700668 /* profile_file= */ nullptr,
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800669 dexlayout_args));
Jeff Hao32a60ab2017-03-01 16:44:50 -0800670}
671
Jeff Haod212d5b2017-04-26 12:09:06 -0700672TEST_F(DexLayoutTest, DuplicateCodeItem) {
673 ScratchFile temp_dex;
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800674 std::vector<std::string> dexlayout_args = { "-o", "/dev/null", temp_dex.GetFilename() };
Jeff Haod212d5b2017-04-26 12:09:06 -0700675 ASSERT_TRUE(DexLayoutExec(&temp_dex,
676 kDuplicateCodeItemInputDex,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700677 /* profile_file= */ nullptr,
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800678 dexlayout_args));
Jeff Haod212d5b2017-04-26 12:09:06 -0700679}
680
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700681// Test that instructions that go past the end of the code items don't cause crashes.
682TEST_F(DexLayoutTest, CodeItemOverrun) {
683 ScratchFile temp_dex;
684 MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [] (DexFile* dex) {
685 bool mutated_successfully = false;
686 // Change the dex instructions to make an opcode that spans past the end of the code item.
Mathieu Chartiera34812c2018-08-01 17:10:43 -0700687 for (ClassAccessor accessor : dex->GetClasses()) {
688 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800689 dex::CodeItem* item = const_cast<dex::CodeItem*>(method.GetCodeItem());
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700690 if (item != nullptr) {
Mathieu Chartier698ebbc2018-01-05 11:00:42 -0800691 CodeItemInstructionAccessor instructions(*dex, item);
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700692 if (instructions.begin() != instructions.end()) {
693 DexInstructionIterator last_instruction = instructions.begin();
694 for (auto dex_it = instructions.begin(); dex_it != instructions.end(); ++dex_it) {
695 last_instruction = dex_it;
696 }
697 if (last_instruction->SizeInCodeUnits() == 1) {
698 // Set the opcode to something that will go past the end of the code item.
Mathieu Chartier2b2bef22017-10-26 17:10:19 -0700699 const_cast<Instruction&>(last_instruction.Inst()).SetOpcode(
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700700 Instruction::CONST_STRING_JUMBO);
701 mutated_successfully = true;
Mathieu Chartier176190c2017-10-31 09:58:07 -0700702 // Test that the safe iterator doesn't go past the end.
703 SafeDexInstructionIterator it2(instructions.begin(), instructions.end());
704 while (!it2.IsErrorState()) {
705 ++it2;
706 }
707 EXPECT_TRUE(it2 == last_instruction);
708 EXPECT_TRUE(it2 < instructions.end());
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700709 }
710 }
711 }
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700712 }
713 }
714 CHECK(mutated_successfully)
715 << "Failed to find candidate code item with only one code unit in last instruction.";
716 });
Mathieu Chartiera27af082018-02-03 16:12:23 -0800717
718 std::string error_msg;
719
720 ScratchFile tmp_file;
721 const std::string& tmp_name = tmp_file.GetFilename();
722 size_t tmp_last_slash = tmp_name.rfind('/');
723 std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
724 ScratchFile profile_file;
725
726 std::vector<std::string> dexlayout_args =
727 { "-i",
728 "-v",
729 "-w", tmp_dir,
730 "-o", tmp_name,
731 "-p", profile_file.GetFilename(),
732 temp_dex.GetFilename()
733 };
734 // -v makes sure that the layout did not corrupt the dex file.
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700735 ASSERT_TRUE(DexLayoutExec(&temp_dex,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700736 /*dex_filename=*/ nullptr,
Mathieu Chartiera27af082018-02-03 16:12:23 -0800737 &profile_file,
Andreas Gampe693bfbf2017-11-10 12:23:31 -0800738 dexlayout_args));
Orion Hodson98273672018-02-06 11:50:27 +0000739 ASSERT_TRUE(UnlinkFile(temp_dex.GetFilename() + ".new"));
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700740}
741
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800742// Test that link data is written out (or at least the header is updated).
743TEST_F(DexLayoutTest, LinkData) {
Mathieu Chartierfe9185a2017-11-21 19:01:10 -0800744 TEST_DISABLED_FOR_TARGET();
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800745 ScratchFile temp_dex;
746 size_t file_size = 0;
747 MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [&] (DexFile* dex) {
748 DexFile::Header& header = const_cast<DexFile::Header&>(dex->GetHeader());
749 header.link_off_ = header.file_size_;
750 header.link_size_ = 16 * KB;
751 header.file_size_ += header.link_size_;
752 file_size = header.file_size_;
753 });
754 TEMP_FAILURE_RETRY(temp_dex.GetFile()->SetLength(file_size));
755
756 std::string error_msg;
757
758 ScratchFile tmp_file;
759 const std::string& tmp_name = tmp_file.GetFilename();
760 size_t tmp_last_slash = tmp_name.rfind('/');
761 std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
762 ScratchFile profile_file;
763
764 std::vector<std::string> dexlayout_args =
765 { "-i",
766 "-v",
767 "-w", tmp_dir,
768 "-o", tmp_name,
769 "-p", profile_file.GetFilename(),
770 temp_dex.GetFilename()
771 };
772 // -v makes sure that the layout did not corrupt the dex file.
773 ASSERT_TRUE(DexLayoutExec(&temp_dex,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700774 /*dex_filename=*/ nullptr,
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800775 &profile_file,
776 dexlayout_args));
Orion Hodson98273672018-02-06 11:50:27 +0000777 ASSERT_TRUE(UnlinkFile(temp_dex.GetFilename() + ".new"));
Mathieu Chartier2f36d2f2017-11-20 15:45:25 -0800778}
779
Mathieu Chartier75175552018-01-25 11:23:01 -0800780TEST_F(DexLayoutTest, ClassFilter) {
781 std::vector<std::unique_ptr<const DexFile>> dex_files;
782 std::string error_msg;
783 const ArtDexFileLoader dex_file_loader;
784 const std::string input_jar = GetTestDexFileName("ManyMethods");
785 CHECK(dex_file_loader.Open(input_jar.c_str(),
786 input_jar.c_str(),
Andreas Gampe9b031f72018-10-04 11:03:34 -0700787 /*verify=*/ true,
788 /*verify_checksum=*/ true,
Mathieu Chartier75175552018-01-25 11:23:01 -0800789 &error_msg,
790 &dex_files)) << error_msg;
791 ASSERT_EQ(dex_files.size(), 1u);
792 for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
793 EXPECT_GT(dex_file->NumClassDefs(), 1u);
794 for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800795 const dex::ClassDef& class_def = dex_file->GetClassDef(i);
Mathieu Chartier75175552018-01-25 11:23:01 -0800796 LOG(INFO) << dex_file->GetClassDescriptor(class_def);
797 }
798 Options options;
799 // Filter out all the classes other than the one below based on class descriptor.
800 options.class_filter_.insert("LManyMethods$Strings;");
801 DexLayout dexlayout(options,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700802 /*info=*/ nullptr,
803 /*out_file=*/ nullptr,
804 /*header=*/ nullptr);
Mathieu Chartier75175552018-01-25 11:23:01 -0800805 std::unique_ptr<DexContainer> out;
Mathieu Chartier05f90d12018-02-07 13:47:17 -0800806 bool result = dexlayout.ProcessDexFile(
807 dex_file->GetLocation().c_str(),
808 dex_file.get(),
Andreas Gampe9b031f72018-10-04 11:03:34 -0700809 /*dex_file_index=*/ 0,
Mathieu Chartier05f90d12018-02-07 13:47:17 -0800810 &out,
811 &error_msg);
812 ASSERT_TRUE(result) << "Failed to run dexlayout " << error_msg;
Mathieu Chartier75175552018-01-25 11:23:01 -0800813 std::unique_ptr<const DexFile> output_dex_file(
814 dex_file_loader.OpenWithDataSection(
815 out->GetMainSection()->Begin(),
816 out->GetMainSection()->Size(),
817 out->GetDataSection()->Begin(),
818 out->GetDataSection()->Size(),
819 dex_file->GetLocation().c_str(),
Andreas Gampe9b031f72018-10-04 11:03:34 -0700820 /* location_checksum= */ 0,
821 /*oat_dex_file=*/ nullptr,
822 /* verify= */ true,
823 /*verify_checksum=*/ false,
Mathieu Chartier75175552018-01-25 11:23:01 -0800824 &error_msg));
825 ASSERT_TRUE(output_dex_file != nullptr);
826
Mathieu Chartier807b21b2018-01-29 05:18:24 -0800827 ASSERT_EQ(output_dex_file->NumClassDefs(), options.class_filter_.size());
Mathieu Chartier75175552018-01-25 11:23:01 -0800828 for (uint32_t i = 0; i < output_dex_file->NumClassDefs(); ++i) {
Mathieu Chartier807b21b2018-01-29 05:18:24 -0800829 // Check that every class in the output dex file is in the filter.
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800830 const dex::ClassDef& class_def = output_dex_file->GetClassDef(i);
Mathieu Chartier75175552018-01-25 11:23:01 -0800831 ASSERT_TRUE(options.class_filter_.find(output_dex_file->GetClassDescriptor(class_def)) !=
832 options.class_filter_.end());
833 }
834 }
835}
836
Jeff Haoc3acfc52016-08-29 14:18:26 -0700837} // namespace art