Home | History | Annotate | Download | only in dexlayout
      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