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