674 lines
32 KiB
C++
674 lines
32 KiB
C++
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <sstream>
|
|
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include "base/unix_file/fd_file.h"
|
|
#include "common_runtime_test.h"
|
|
#include "dex_file-inl.h"
|
|
#include "exec_utils.h"
|
|
#include "jit/profile_compilation_info.h"
|
|
#include "utils.h"
|
|
|
|
namespace art {
|
|
|
|
static const char kDexFileLayoutInputDex[] =
|
|
"ZGV4CjAzNQD1KW3+B8NAB0f2A/ZVIBJ0aHrGIqcpVTAUAgAAcAAAAHhWNBIAAAAAAAAAAIwBAAAH"
|
|
"AAAAcAAAAAQAAACMAAAAAQAAAJwAAAAAAAAAAAAAAAMAAACoAAAAAgAAAMAAAAAUAQAAAAEAADAB"
|
|
"AAA4AQAAQAEAAEgBAABNAQAAUgEAAGYBAAADAAAABAAAAAUAAAAGAAAABgAAAAMAAAAAAAAAAAAA"
|
|
"AAAAAAABAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAAAAAAAdQEAAAAAAAABAAAA"
|
|
"AAAAAAIAAAAAAAAAAgAAAAAAAAB/AQAAAAAAAAEAAQABAAAAaQEAAAQAAABwEAIAAAAOAAEAAQAB"
|
|
"AAAAbwEAAAQAAABwEAIAAAAOAAY8aW5pdD4ABkEuamF2YQAGQi5qYXZhAANMQTsAA0xCOwASTGph"
|
|
"dmEvbGFuZy9PYmplY3Q7AAFWAAQABw48AAQABw48AAAAAQAAgIAEgAIAAAEAAYCABJgCAAAACwAA"
|
|
"AAAAAAABAAAAAAAAAAEAAAAHAAAAcAAAAAIAAAAEAAAAjAAAAAMAAAABAAAAnAAAAAUAAAADAAAA"
|
|
"qAAAAAYAAAACAAAAwAAAAAEgAAACAAAAAAEAAAIgAAAHAAAAMAEAAAMgAAACAAAAaQEAAAAgAAAC"
|
|
"AAAAdQEAAAAQAAABAAAAjAEAAA==";
|
|
|
|
// Dex file with catch handler unreferenced by try blocks.
|
|
// Constructed by building a dex file with try/catch blocks and hex editing.
|
|
static const char kUnreferencedCatchHandlerInputDex[] =
|
|
"ZGV4CjAzNQD+exd52Y0f9nY5x5GmInXq5nXrO6Kl2RV4AwAAcAAAAHhWNBIAAAAAAAAAANgCAAAS"
|
|
"AAAAcAAAAAgAAAC4AAAAAwAAANgAAAABAAAA/AAAAAQAAAAEAQAAAQAAACQBAAA0AgAARAEAANYB"
|
|
"AADeAQAA5gEAAO4BAAAAAgAADwIAACYCAAA9AgAAUQIAAGUCAAB5AgAAfwIAAIUCAACIAgAAjAIA"
|
|
"AKECAACnAgAArAIAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAwAAAAOAAAADAAAAAYAAAAAAAAA"
|
|
"DQAAAAYAAADIAQAADQAAAAYAAADQAQAABQABABAAAAAAAAAAAAAAAAAAAgAPAAAAAQABABEAAAAD"
|
|
"AAAAAAAAAAAAAAABAAAAAwAAAAAAAAADAAAAAAAAAMgCAAAAAAAAAQABAAEAAAC1AgAABAAAAHAQ"
|
|
"AwAAAA4AAwABAAIAAgC6AgAAIQAAAGIAAAAaAQoAbiACABAAYgAAABoBCwBuIAIAEAAOAA0AYgAA"
|
|
"ABoBAQBuIAIAEAAo8A0AYgAAABoBAgBuIAIAEAAo7gAAAAAAAAcAAQAHAAAABwABAAIBAg8BAhgA"
|
|
"AQAAAAQAAAABAAAABwAGPGluaXQ+AAZDYXRjaDEABkNhdGNoMgAQSGFuZGxlclRlc3QuamF2YQAN"
|
|
"TEhhbmRsZXJUZXN0OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABVMamF2YS9sYW5nL0V4Y2VwdGlv"
|
|
"bjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABJMamF2YS9sYW5nL1N5"
|
|
"c3RlbTsABFRyeTEABFRyeTIAAVYAAlZMABNbTGphdmEvbGFuZy9TdHJpbmc7AARtYWluAANvdXQA"
|
|
"B3ByaW50bG4AAQAHDgAEAQAHDn17AncdHoseAAAAAgAAgYAExAIBCdwCAAANAAAAAAAAAAEAAAAA"
|
|
"AAAAAQAAABIAAABwAAAAAgAAAAgAAAC4AAAAAwAAAAMAAADYAAAABAAAAAEAAAD8AAAABQAAAAQA"
|
|
"AAAEAQAABgAAAAEAAAAkAQAAASAAAAIAAABEAQAAARAAAAIAAADIAQAAAiAAABIAAADWAQAAAyAA"
|
|
"AAIAAAC1AgAAACAAAAEAAADIAgAAABAAAAEAAADYAgAA";
|
|
|
|
// Dex file with 0-size (catch all only) catch handler unreferenced by try blocks.
|
|
// Constructed by building a dex file with try/catch blocks and hex editing.
|
|
static const char kUnreferenced0SizeCatchHandlerInputDex[] =
|
|
"ZGV4CjAzNQCEbEEvMstSNpQpjPdfMEfUBS48cis2QRJoAwAAcAAAAHhWNBIAAAAAAAAAAMgCAAAR"
|
|
"AAAAcAAAAAcAAAC0AAAAAwAAANAAAAABAAAA9AAAAAQAAAD8AAAAAQAAABwBAAAsAgAAPAEAAOoB"
|
|
"AADyAQAABAIAABMCAAAqAgAAPgIAAFICAABmAgAAaQIAAG0CAACCAgAAhgIAAIoCAACQAgAAlQIA"
|
|
"AJ4CAACiAgAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACQAAAAcAAAAFAAAAAAAAAAgAAAAFAAAA"
|
|
"3AEAAAgAAAAFAAAA5AEAAAQAAQANAAAAAAAAAAAAAAAAAAIADAAAAAEAAQAOAAAAAgAAAAAAAAAA"
|
|
"AAAAAQAAAAIAAAAAAAAAAQAAAAAAAAC5AgAAAAAAAAEAAQABAAAApgIAAAQAAABwEAMAAAAOAAQA"
|
|
"AQACAAIAqwIAAC8AAABiAAAAGgEPAG4gAgAQAGIAAAAaAQoAbiACABAAYgAAABoBEABuIAIAEABi"
|
|
"AAAAGgELAG4gAgAQAA4ADQBiAQAAGgIKAG4gAgAhACcADQBiAQAAGgILAG4gAgAhACcAAAAAAAAA"
|
|
"BwABAA4AAAAHAAEAAgAdACYAAAABAAAAAwAAAAEAAAAGAAY8aW5pdD4AEEhhbmRsZXJUZXN0Lmph"
|
|
"dmEADUxIYW5kbGVyVGVzdDsAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwASTGphdmEvbGFuZy9PYmpl"
|
|
"Y3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xhbmcvU3lzdGVtOwABVgACVkwAE1tMamF2"
|
|
"YS9sYW5nL1N0cmluZzsAAmYxAAJmMgAEbWFpbgADb3V0AAdwcmludGxuAAJ0MQACdDIAAQAHDgAE"
|
|
"AQAHDnl7eXkCeB2bAAAAAgAAgYAEvAIBCdQCAA0AAAAAAAAAAQAAAAAAAAABAAAAEQAAAHAAAAAC"
|
|
"AAAABwAAALQAAAADAAAAAwAAANAAAAAEAAAAAQAAAPQAAAAFAAAABAAAAPwAAAAGAAAAAQAAABwB"
|
|
"AAABIAAAAgAAADwBAAABEAAAAgAAANwBAAACIAAAEQAAAOoBAAADIAAAAgAAAKYCAAAAIAAAAQAA"
|
|
"ALkCAAAAEAAAAQAAAMgCAAA=";
|
|
|
|
// Dex file with an unreferenced catch handler at end of code item.
|
|
// Constructed by building a dex file with try/catch blocks and hex editing.
|
|
static const char kUnreferencedEndingCatchHandlerInputDex[] =
|
|
"ZGV4CjAzNQCEflufI6xGTDDRmLpbfYi6ujPrDLIwvYcEBAAAcAAAAHhWNBIAAAAAAAAAAGQDAAAT"
|
|
"AAAAcAAAAAgAAAC8AAAAAwAAANwAAAABAAAAAAEAAAUAAAAIAQAAAQAAADABAAC0AgAAUAEAAE4C"
|
|
"AABWAgAAXgIAAGYCAAB4AgAAhwIAAJ4CAAC1AgAAyQIAAN0CAADxAgAA9wIAAP0CAAAAAwAABAMA"
|
|
"ABkDAAAcAwAAIgMAACcDAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAMAAAADgAAAAwAAAAGAAAA"
|
|
"AAAAAA0AAAAGAAAAQAIAAA0AAAAGAAAASAIAAAUAAQARAAAAAAAAAAAAAAAAAAAADwAAAAAAAgAQ"
|
|
"AAAAAQABABIAAAADAAAAAAAAAAAAAAABAAAAAwAAAAAAAAADAAAAAAAAAFADAAAAAAAAAQABAAEA"
|
|
"AAAwAwAABAAAAHAQBAAAAA4AAgAAAAIAAgA1AwAAIQAAAGIAAAAaAQoAbiADABAAYgAAABoBCwBu"
|
|
"IAMAEAAOAA0AYgAAABoBAQBuIAMAEAAo8A0AYgAAABoBAgBuIAMAEAAo7gAAAAAAAAcAAQAHAAAA"
|
|
"BwABAAIBAg8BAhgAAwABAAIAAgBCAwAAIQAAAGIAAAAaAQoAbiADABAAYgAAABoBCwBuIAMAEAAO"
|
|
"AA0AYgAAABoBAQBuIAMAEAAo8A0AYgAAABoBAgBuIAMAEAAo7gAAAAAAAAcAAQAHAAAABwABAAIB"
|
|
"Ag8BAhgAAQAAAAQAAAABAAAABwAGPGluaXQ+AAZDYXRjaDEABkNhdGNoMgAQSGFuZGxlclRlc3Qu"
|
|
"amF2YQANTEhhbmRsZXJUZXN0OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABVMamF2YS9sYW5nL0V4"
|
|
"Y2VwdGlvbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABJMamF2YS9s"
|
|
"YW5nL1N5c3RlbTsABFRyeTEABFRyeTIAAVYAAlZMABNbTGphdmEvbGFuZy9TdHJpbmc7AAFhAARt"
|
|
"YWluAANvdXQAB3ByaW50bG4AAQAHDgAEAAcOfHsCeB0eih4AEQEABw59ewJ3HR6LHgAAAAMAAIGA"
|
|
"BNACAQnoAgEJ1AMAAA0AAAAAAAAAAQAAAAAAAAABAAAAEwAAAHAAAAACAAAACAAAALwAAAADAAAA"
|
|
"AwAAANwAAAAEAAAAAQAAAAABAAAFAAAABQAAAAgBAAAGAAAAAQAAADABAAABIAAAAwAAAFABAAAB"
|
|
"EAAAAgAAAEACAAACIAAAEwAAAE4CAAADIAAAAwAAADADAAAAIAAAAQAAAFADAAAAEAAAAQAAAGQD"
|
|
"AAA=";
|
|
|
|
// Dex file with multiple code items that have the same debug_info_off_. Constructed by a modified
|
|
// dexlayout on XandY.
|
|
static const char kDexFileDuplicateOffset[] =
|
|
"ZGV4CjAzNwAQfXfPCB8qCxo7MqdFhmHZQwCv8+udHD8MBAAAcAAAAHhWNBIAAAAAAAAAAFQDAAAT"
|
|
"AAAAcAAAAAgAAAC8AAAAAQAAANwAAAABAAAA6AAAAAUAAADwAAAAAwAAABgBAACUAgAAeAEAABQC"
|
|
"AAAeAgAAJgIAACsCAAAyAgAANwIAAFsCAAB7AgAAngIAALICAAC1AgAAvQIAAMUCAADIAgAA1QIA"
|
|
"AOkCAADvAgAA9QIAAPwCAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAkAAAAHAAAA"
|
|
"AAAAAAIAAQASAAAAAAAAAAEAAAABAAAAAQAAAAIAAAAAAAAAAgAAAAEAAAAGAAAAAQAAAAAAAAAA"
|
|
"AAAABgAAAAAAAAAKAAAAAAAAACsDAAAAAAAAAQAAAAAAAAAGAAAAAAAAAAsAAAD0AQAANQMAAAAA"
|
|
"AAACAAAAAAAAAAAAAAAAAAAACwAAAAQCAAA/AwAAAAAAAAIAAAAUAwAAGgMAAAEAAAAjAwAAAQAB"
|
|
"AAEAAAAFAAAABAAAAHAQBAAAAA4AAQABAAEAAAAFAAAABAAAAHAQBAAAAA4AAQAAAAEAAAAFAAAA"
|
|
"CAAAACIAAQBwEAEAAABpAAAADgABAAEAAQAAAAUAAAAEAAAAcBAAAAAADgB4AQAAAAAAAAAAAAAA"
|
|
"AAAAhAEAAAAAAAAAAAAAAAAAAAg8Y2xpbml0PgAGPGluaXQ+AANMWDsABUxZJFo7AANMWTsAIkxk"
|
|
"YWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5l"
|
|
"ckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNzZXM7ABJMamF2YS9sYW5nL09i"
|
|
"amVjdDsAAVYABlguamF2YQAGWS5qYXZhAAFaAAthY2Nlc3NGbGFncwASZW1pdHRlcjogamFjay00"
|
|
"LjI1AARuYW1lAAR0aGlzAAV2YWx1ZQABegARAAcOABMABw4AEgAHDnYAEQAHDgACAwERGAICBAIN"
|
|
"BAgPFwwCBQERHAEYAQAAAQAAgIAEjAMAAAEAAYCABKQDAQACAAAIAoiABLwDAYCABNwDAAAADwAA"
|
|
"AAAAAAABAAAAAAAAAAEAAAATAAAAcAAAAAIAAAAIAAAAvAAAAAMAAAABAAAA3AAAAAQAAAABAAAA"
|
|
"6AAAAAUAAAAFAAAA8AAAAAYAAAADAAAAGAEAAAMQAAACAAAAeAEAAAEgAAAEAAAAjAEAAAYgAAAC"
|
|
"AAAA9AEAAAIgAAATAAAAFAIAAAMgAAAEAAAA/wIAAAQgAAADAAAAFAMAAAAgAAADAAAAKwMAAAAQ"
|
|
"AAABAAAAVAMAAA==";
|
|
|
|
// Dex file with null value for annotations_off in the annotation_set_ref_list.
|
|
// Constructed by building a dex file with annotations and hex editing.
|
|
static const char kNullSetRefListElementInputDex[] =
|
|
"ZGV4CjAzNQB1iA+7ZwgkF+7E6ZesYFc2lRAR3qnRAanwAwAAcAAAAHhWNBIAAAAAAAAAACADAAAS"
|
|
"AAAAcAAAAAgAAAC4AAAAAwAAANgAAAABAAAA/AAAAAQAAAAEAQAAAgAAACQBAACMAgAAZAEAAOgB"
|
|
"AADwAQAAAAIAAAMCAAAQAgAAIAIAADQCAABIAgAAawIAAI0CAAC1AgAAyAIAANECAADUAgAA2QIA"
|
|
"ANwCAADjAgAA6QIAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAMAAAAAgAAAAMAAAAAAAAA"
|
|
"DAAAAAcAAAAAAAAADQAAAAcAAADgAQAABgAGAAsAAAAAAAEAAAAAAAAAAgAOAAAAAQAAABAAAAAC"
|
|
"AAEAAAAAAAAAAAAAAAAAAgAAAAAAAAABAAAAsAEAAAgDAAAAAAAAAQAAAAEmAAACAAAA2AEAAAoA"
|
|
"AADIAQAAFgMAAAAAAAACAAAAAAAAAHwBAAABAAAA/AIAAAAAAAABAAAAAgMAAAEAAQABAAAA8AIA"
|
|
"AAQAAABwEAMAAAAOAAIAAgAAAAAA9QIAAAEAAAAOAAAAAAAAAAAAAAAAAAAAAQAAAAEAAABkAQAA"
|
|
"cAEAAAAAAAAAAAAAAAAAAAEAAAAEAAAAAgAAAAMAAwAGPGluaXQ+AA5Bbm5vQ2xhc3MuamF2YQAB"
|
|
"TAALTEFubm9DbGFzczsADkxNeUFubm90YXRpb247ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZh"
|
|
"L2xhbmcvU3RyaW5nOwAhTGphdmEvbGFuZy9hbm5vdGF0aW9uL0Fubm90YXRpb247ACBMamF2YS9s"
|
|
"YW5nL2Fubm90YXRpb24vUmV0ZW50aW9uOwAmTGphdmEvbGFuZy9hbm5vdGF0aW9uL1JldGVudGlv"
|
|
"blBvbGljeTsAEU15QW5ub3RhdGlvbi5qYXZhAAdSVU5USU1FAAFWAANWTEwAAWEABWFOYW1lAARu"
|
|
"YW1lAAV2YWx1ZQABAAcOAAICAAAHDgABBQERGwABAQEQFw8AAAIAAICABIQDAQmcAwAAAAECgQgA"
|
|
"AAARAAAAAAAAAAEAAAAAAAAAAQAAABIAAABwAAAAAgAAAAgAAAC4AAAAAwAAAAMAAADYAAAABAAA"
|
|
"AAEAAAD8AAAABQAAAAQAAAAEAQAABgAAAAIAAAAkAQAAAhAAAAEAAABkAQAAAxAAAAMAAABwAQAA"
|
|
"ASAAAAIAAACEAQAABiAAAAIAAACwAQAAARAAAAIAAADYAQAAAiAAABIAAADoAQAAAyAAAAIAAADw"
|
|
"AgAABCAAAAIAAAD8AgAAACAAAAIAAAAIAwAAABAAAAEAAAAgAwAA";
|
|
|
|
// Dex file with shared empty class data item for multiple class defs.
|
|
// Constructing by building a dex file with multiple classes and hex editing.
|
|
static const char kMultiClassDataInputDex[] =
|
|
"ZGV4CjAzNQALJgF9TtnLq748xVe/+wyxETrT9lTEiW6YAQAAcAAAAHhWNBIAAAAAAAAAADQBAAAI"
|
|
"AAAAcAAAAAQAAACQAAAAAAAAAAAAAAACAAAAoAAAAAAAAAAAAAAAAgAAALAAAACoAAAA8AAAAPAA"
|
|
"AAD4AAAAAAEAAAMBAAAIAQAADQEAACEBAAAkAQAAAgAAAAMAAAAEAAAABQAAAAEAAAAGAAAAAgAA"
|
|
"AAcAAAABAAAAAQYAAAMAAAAAAAAAAAAAAAAAAAAnAQAAAAAAAAIAAAABBgAAAwAAAAAAAAABAAAA"
|
|
"AAAAACcBAAAAAAAABkEuamF2YQAGQi5qYXZhAAFJAANMQTsAA0xCOwASTGphdmEvbGFuZy9PYmpl"
|
|
"Y3Q7AAFhAAFiAAAAAAABAAAAARkAAAAIAAAAAAAAAAEAAAAAAAAAAQAAAAgAAABwAAAAAgAAAAQA"
|
|
"AACQAAAABAAAAAIAAACgAAAABgAAAAIAAACwAAAAAiAAAAgAAADwAAAAACAAAAIAAAAnAQAAABAA"
|
|
"AAEAAAA0AQAA";
|
|
|
|
// Dex file with code info followed by non 4-byte aligned section.
|
|
// Constructed a dex file with code info followed by string data and hex edited.
|
|
static const char kUnalignedCodeInfoInputDex[] =
|
|
"ZGV4CjAzNQDXJzXNb4iWn2SLhmLydW/8h1K9moERIw7UAQAAcAAAAHhWNBIAAAAAAAAAAEwBAAAG"
|
|
"AAAAcAAAAAMAAACIAAAAAQAAAJQAAAAAAAAAAAAAAAMAAACgAAAAAQAAALgAAAD8AAAA2AAAAAIB"
|
|
"AAAKAQAAEgEAABcBAAArAQAALgEAAAIAAAADAAAABAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAA"
|
|
"AAUAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAABAAAAAAAAADsBAAAAAAAAAQABAAEAAAAxAQAA"
|
|
"BAAAAHAQAgAAAA4AAQABAAAAAAA2AQAAAQAAAA4ABjxpbml0PgAGQS5qYXZhAANMQTsAEkxqYXZh"
|
|
"L2xhbmcvT2JqZWN0OwABVgABYQABAAcOAAMABw4AAAABAQCBgATYAQEB8AEAAAALAAAAAAAAAAEA"
|
|
"AAAAAAAAAQAAAAYAAABwAAAAAgAAAAMAAACIAAAAAwAAAAEAAACUAAAABQAAAAMAAACgAAAABgAA"
|
|
"AAEAAAC4AAAAASAAAAIAAADYAAAAAiAAAAYAAAACAQAAAyAAAAIAAAAxAQAAACAAAAEAAAA7AQAA"
|
|
"ABAAAAEAAABMAQAA";
|
|
|
|
// Dex file with class data section preceding code items.
|
|
// Constructed by passing dex file through dexmerger tool and hex editing.
|
|
static const char kClassDataBeforeCodeInputDex[] =
|
|
"ZGV4CjAzNQCZKmCu3XXn4zvxCh5VH0gZNNobEAcsc49EAgAAcAAAAHhWNBIAAAAAAAAAAAQBAAAJ"
|
|
"AAAAcAAAAAQAAACUAAAAAgAAAKQAAAAAAAAAAAAAAAUAAAC8AAAAAQAAAOQAAABAAQAABAEAAPgB"
|
|
"AAAAAgAACAIAAAsCAAAQAgAAJAIAACcCAAAqAgAALQIAAAIAAAADAAAABAAAAAUAAAACAAAAAAAA"
|
|
"AAAAAAAFAAAAAwAAAAAAAAABAAEAAAAAAAEAAAAGAAAAAQAAAAcAAAABAAAACAAAAAIAAQAAAAAA"
|
|
"AQAAAAEAAAACAAAAAAAAAAEAAAAAAAAAjAEAAAAAAAALAAAAAAAAAAEAAAAAAAAAAQAAAAkAAABw"
|
|
"AAAAAgAAAAQAAACUAAAAAwAAAAIAAACkAAAABQAAAAUAAAC8AAAABgAAAAEAAADkAAAAABAAAAEA"
|
|
"AAAEAQAAACAAAAEAAACMAQAAASAAAAQAAACkAQAAAiAAAAkAAAD4AQAAAyAAAAQAAAAwAgAAAAAB"
|
|
"AwCBgASkAwEBvAMBAdADAQHkAwAAAQABAAEAAAAwAgAABAAAAHAQBAAAAA4AAgABAAAAAAA1AgAA"
|
|
"AgAAABIQDwACAAEAAAAAADoCAAACAAAAEiAPAAIAAQAAAAAAPwIAAAIAAAASMA8ABjxpbml0PgAG"
|
|
"QS5qYXZhAAFJAANMQTsAEkxqYXZhL2xhbmcvT2JqZWN0OwABVgABYQABYgABYwABAAcOAAMABw4A"
|
|
"BgAHDgAJAAcOAA==";
|
|
|
|
// Dex file with local info containing a null type descriptor.
|
|
// Constructed a dex file with debug info sequence containing DBG_RESTART_LOCAL without any
|
|
// DBG_START_LOCAL to give it a declared type.
|
|
static const char kUnknownTypeDebugInfoInputDex[] =
|
|
"ZGV4CjAzNQBtKqZfzjHLNSNwW2A6Bz9FuCEX0sL+FF38AQAAcAAAAHhWNBIAAAAAAAAAAHQBAAAI"
|
|
"AAAAcAAAAAQAAACQAAAAAgAAAKAAAAAAAAAAAAAAAAMAAAC4AAAAAQAAANAAAAAMAQAA8AAAABwB"
|
|
"AAAkAQAALAEAAC8BAAA0AQAASAEAAEsBAABOAQAAAgAAAAMAAAAEAAAABQAAAAIAAAAAAAAAAAAA"
|
|
"AAUAAAADAAAAAAAAAAEAAQAAAAAAAQAAAAYAAAACAAEAAAAAAAEAAAABAAAAAgAAAAAAAAABAAAA"
|
|
"AAAAAGMBAAAAAAAAAQABAAEAAABUAQAABAAAAHAQAgAAAA4AAgABAAAAAABZAQAAAgAAABIQDwAG"
|
|
"PGluaXQ+AAZBLmphdmEAAUkAA0xBOwASTGphdmEvbGFuZy9PYmplY3Q7AAFWAAFhAAR0aGlzAAEA"
|
|
"Bw4AAwAHDh4GAAYAAAAAAQEAgYAE8AEBAYgCAAAACwAAAAAAAAABAAAAAAAAAAEAAAAIAAAAcAAA"
|
|
"AAIAAAAEAAAAkAAAAAMAAAACAAAAoAAAAAUAAAADAAAAuAAAAAYAAAABAAAA0AAAAAEgAAACAAAA"
|
|
"8AAAAAIgAAAIAAAAHAEAAAMgAAACAAAAVAEAAAAgAAABAAAAYwEAAAAQAAABAAAAdAEAAA==";
|
|
|
|
// Dex file with multiple class data items pointing to the same code item.
|
|
// Constructed by hex editing.
|
|
static const char kDuplicateCodeItemInputDex[] =
|
|
"ZGV4CjAzNQCwKtVglQOmLWuHwldN5jkBOInC7mTMhJMAAgAAcAAAAHhWNBIAAAAAAAAAAHgBAAAH"
|
|
"AAAAcAAAAAMAAACMAAAAAQAAAJgAAAAAAAAAAAAAAAQAAACkAAAAAQAAAMQAAAAcAQAA5AAAACQB"
|
|
"AAAsAQAANAEAADkBAABNAQAAUAEAAFMBAAACAAAAAwAAAAQAAAAEAAAAAgAAAAAAAAAAAAAAAAAA"
|
|
"AAAAAAAFAAAAAAAAAAYAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAABAAAAAAAAAGUBAAAAAAAA"
|
|
"AQABAAEAAABWAQAABAAAAHAQAwAAAA4AAQABAAAAAABbAQAAAQAAAA4AAAABAAEAAAAAAGABAAAB"
|
|
"AAAADgAAAAY8aW5pdD4ABkEuamF2YQADTEE7ABJMamF2YS9sYW5nL09iamVjdDsAAVYAAWEAAWIA"
|
|
"AQAHDgADAAcOAAUABw4AAAABAgCBgATkAQEA/AEBAPwBAAsAAAAAAAAAAQAAAAAAAAABAAAABwAA"
|
|
"AHAAAAACAAAAAwAAAIwAAAADAAAAAQAAAJgAAAAFAAAABAAAAKQAAAAGAAAAAQAAAMQAAAABIAAA"
|
|
"AwAAAOQAAAACIAAABwAAACQBAAADIAAAAwAAAFYBAAAAIAAAAQAAAGUBAAAAEAAAAQAAAHgBAAA=";
|
|
|
|
static void WriteBase64ToFile(const char* base64, File* file) {
|
|
// Decode base64.
|
|
CHECK(base64 != nullptr);
|
|
size_t length;
|
|
std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
|
|
CHECK(bytes != nullptr);
|
|
if (!file->WriteFully(bytes.get(), length)) {
|
|
PLOG(FATAL) << "Failed to write base64 as file";
|
|
}
|
|
}
|
|
|
|
static void WriteFileBase64(const char* base64, const char* location) {
|
|
// Write to provided file.
|
|
std::unique_ptr<File> file(OS::CreateEmptyFile(location));
|
|
CHECK(file != nullptr);
|
|
WriteBase64ToFile(base64, file.get());
|
|
if (file->FlushCloseOrErase() != 0) {
|
|
PLOG(FATAL) << "Could not flush and close test file.";
|
|
}
|
|
}
|
|
|
|
class DexLayoutTest : public CommonRuntimeTest {
|
|
protected:
|
|
virtual void SetUp() {
|
|
CommonRuntimeTest::SetUp();
|
|
}
|
|
|
|
// Runs FullPlainOutput test.
|
|
bool FullPlainOutputExec(std::string* error_msg) {
|
|
// TODO: dexdump2 -> dexdump ?
|
|
ScratchFile dexdump_output;
|
|
const std::string& dexdump_filename = dexdump_output.GetFilename();
|
|
std::string dexdump = GetTestAndroidRoot() + "/bin/dexdump2";
|
|
EXPECT_TRUE(OS::FileExists(dexdump.c_str())) << dexdump << " should be a valid file path";
|
|
|
|
ScratchFile dexlayout_output;
|
|
const std::string& dexlayout_filename = dexlayout_output.GetFilename();
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
|
|
for (const std::string &dex_file : GetLibCoreDexFileNames()) {
|
|
std::vector<std::string> dexdump_exec_argv =
|
|
{ dexdump, "-d", "-f", "-h", "-l", "plain", "-o", dexdump_filename, dex_file };
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-d", "-f", "-h", "-l", "plain", "-o", dexlayout_filename, dex_file };
|
|
if (!::art::Exec(dexdump_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
if (!::art::Exec(dexlayout_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
std::vector<std::string> diff_exec_argv =
|
|
{ "/usr/bin/diff", dexdump_filename, dexlayout_filename };
|
|
if (!::art::Exec(diff_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Runs DexFileOutput test.
|
|
bool DexFileOutputExec(std::string* error_msg) {
|
|
ScratchFile tmp_file;
|
|
const std::string& tmp_name = tmp_file.GetFilename();
|
|
size_t tmp_last_slash = tmp_name.rfind('/');
|
|
std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
|
|
for (const std::string &dex_file : GetLibCoreDexFileNames()) {
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-w", tmp_dir, "-o", tmp_name, dex_file };
|
|
if (!::art::Exec(dexlayout_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
size_t dex_file_last_slash = dex_file.rfind("/");
|
|
std::string dex_file_name = dex_file.substr(dex_file_last_slash + 1);
|
|
std::vector<std::string> unzip_exec_argv =
|
|
{ "/usr/bin/unzip", dex_file, "classes.dex", "-d", tmp_dir};
|
|
if (!::art::Exec(unzip_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
std::vector<std::string> diff_exec_argv =
|
|
{ "/usr/bin/diff", tmp_dir + "classes.dex" , tmp_dir + dex_file_name };
|
|
if (!::art::Exec(diff_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
std::vector<std::string> rm_zip_exec_argv = { "/bin/rm", tmp_dir + "classes.dex" };
|
|
if (!::art::Exec(rm_zip_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
std::vector<std::string> rm_out_exec_argv = { "/bin/rm", tmp_dir + dex_file_name };
|
|
if (!::art::Exec(rm_out_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Create a profile with some subset of methods and classes.
|
|
void CreateProfile(const std::string& input_dex,
|
|
const std::string& out_profile,
|
|
const std::string& dex_location) {
|
|
std::vector<std::unique_ptr<const DexFile>> dex_files;
|
|
std::string error_msg;
|
|
bool result = DexFile::Open(input_dex.c_str(),
|
|
input_dex,
|
|
false,
|
|
&error_msg,
|
|
&dex_files);
|
|
|
|
ASSERT_TRUE(result) << error_msg;
|
|
ASSERT_GE(dex_files.size(), 1u);
|
|
|
|
size_t profile_methods = 0;
|
|
size_t profile_classes = 0;
|
|
ProfileCompilationInfo pfi;
|
|
std::set<DexCacheResolvedClasses> classes;
|
|
for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
|
|
for (uint32_t i = 0; i < dex_file->NumMethodIds(); i += 2) {
|
|
uint8_t flags = 0u;
|
|
|
|
if ((i & 3) != 0) {
|
|
flags |= ProfileCompilationInfo::MethodHotness::kFlagHot;
|
|
++profile_methods;
|
|
} else if ((i & 2) != 0) {
|
|
flags |= ProfileCompilationInfo::MethodHotness::kFlagStartup;
|
|
++profile_methods;
|
|
}
|
|
pfi.AddMethodIndex(static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags),
|
|
dex_location,
|
|
dex_file->GetLocationChecksum(),
|
|
/*dex_method_idx*/i,
|
|
dex_file->NumMethodIds());
|
|
}
|
|
DexCacheResolvedClasses cur_classes(dex_location,
|
|
dex_location,
|
|
dex_file->GetLocationChecksum(),
|
|
dex_file->NumMethodIds());
|
|
// Add every even class too.
|
|
for (uint32_t i = 0; i < dex_file->NumClassDefs(); i += 1) {
|
|
if ((i & 2) == 0) {
|
|
cur_classes.AddClass(dex_file->GetClassDef(i).class_idx_);
|
|
++profile_classes;
|
|
}
|
|
}
|
|
classes.insert(cur_classes);
|
|
}
|
|
pfi.AddClasses(classes);
|
|
// Write to provided file.
|
|
std::unique_ptr<File> file(OS::CreateEmptyFile(out_profile.c_str()));
|
|
ASSERT_TRUE(file != nullptr);
|
|
pfi.Save(file->Fd());
|
|
if (file->FlushCloseOrErase() != 0) {
|
|
PLOG(FATAL) << "Could not flush and close test file.";
|
|
}
|
|
EXPECT_GE(profile_methods, 0u);
|
|
EXPECT_GE(profile_classes, 0u);
|
|
}
|
|
|
|
// Runs DexFileLayout test.
|
|
bool DexFileLayoutExec(std::string* error_msg) {
|
|
ScratchFile tmp_file;
|
|
std::string tmp_name = tmp_file.GetFilename();
|
|
size_t tmp_last_slash = tmp_name.rfind("/");
|
|
std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
|
|
|
|
// Write inputs and expected outputs.
|
|
std::string dex_file = tmp_dir + "classes.dex";
|
|
WriteFileBase64(kDexFileLayoutInputDex, dex_file.c_str());
|
|
std::string profile_file = tmp_dir + "primary.prof";
|
|
CreateProfile(dex_file, profile_file, dex_file);
|
|
// WriteFileBase64(kDexFileLayoutInputProfile, profile_file.c_str());
|
|
std::string output_dex = tmp_dir + "classes.dex.new";
|
|
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, dex_file };
|
|
if (!::art::Exec(dexlayout_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
|
|
// -v makes sure that the layout did not corrupt the dex file.
|
|
|
|
std::vector<std::string> rm_exec_argv =
|
|
{ "/bin/rm", dex_file, profile_file, output_dex };
|
|
if (!::art::Exec(rm_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Runs DexFileLayout test twice (second time is run on output of first time)
|
|
// for behavior consistency.
|
|
bool DexFileLayoutFixedPointExec(std::string* error_msg) {
|
|
ScratchFile tmp_file;
|
|
std::string tmp_name = tmp_file.GetFilename();
|
|
size_t tmp_last_slash = tmp_name.rfind("/");
|
|
std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
|
|
|
|
// Unzip the test dex file to the classes.dex destination. It is required to unzip since
|
|
// opening from jar recalculates the dex location checksum.
|
|
std::string dex_file = tmp_dir + "classes.dex";
|
|
|
|
std::vector<std::string> unzip_args = {
|
|
"/usr/bin/unzip",
|
|
GetTestDexFileName("ManyMethods"),
|
|
"classes.dex",
|
|
"-d",
|
|
tmp_dir,
|
|
};
|
|
if (!art::Exec(unzip_args, error_msg)) {
|
|
LOG(ERROR) << "Failed to unzip dex";
|
|
return false;
|
|
}
|
|
|
|
std::string profile_file = tmp_dir + "primary.prof";
|
|
CreateProfile(dex_file, profile_file, dex_file);
|
|
std::string output_dex = tmp_dir + "classes.dex.new";
|
|
std::string second_output_dex = tmp_dir + "classes.dex.new.new";
|
|
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
|
|
// -v makes sure that the layout did not corrupt the dex file.
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, dex_file };
|
|
if (!::art::Exec(dexlayout_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
|
|
// Recreate the profile with the new dex location. This is required so that the profile dex
|
|
// location matches.
|
|
CreateProfile(dex_file, profile_file, output_dex);
|
|
|
|
// -v makes sure that the layout did not corrupt the dex file.
|
|
// -i since the checksum won't match from the first layout.
|
|
std::vector<std::string> second_dexlayout_exec_argv =
|
|
{ dexlayout, "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, output_dex };
|
|
if (!::art::Exec(second_dexlayout_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
|
|
bool diff_result = true;
|
|
std::vector<std::string> diff_exec_argv =
|
|
{ "/usr/bin/diff", output_dex, second_output_dex };
|
|
if (!::art::Exec(diff_exec_argv, error_msg)) {
|
|
diff_result = false;
|
|
}
|
|
|
|
std::vector<std::string> rm_exec_argv =
|
|
{ "/bin/rm", dex_file, profile_file, output_dex, second_output_dex };
|
|
if (!::art::Exec(rm_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
|
|
return diff_result;
|
|
}
|
|
|
|
// Runs UnreferencedCatchHandlerTest & Unreferenced0SizeCatchHandlerTest.
|
|
bool UnreferencedCatchHandlerExec(std::string* error_msg, const char* filename) {
|
|
ScratchFile tmp_file;
|
|
std::string tmp_name = tmp_file.GetFilename();
|
|
size_t tmp_last_slash = tmp_name.rfind("/");
|
|
std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1);
|
|
|
|
// Write inputs and expected outputs.
|
|
std::string input_dex = tmp_dir + "classes.dex";
|
|
WriteFileBase64(filename, input_dex.c_str());
|
|
std::string output_dex = tmp_dir + "classes.dex.new";
|
|
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-w", tmp_dir, "-o", "/dev/null", input_dex };
|
|
if (!::art::Exec(dexlayout_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
|
|
// Diff input and output. They should be the same.
|
|
std::vector<std::string> diff_exec_argv = { "/usr/bin/diff", input_dex, output_dex };
|
|
if (!::art::Exec(diff_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
|
|
std::vector<std::string> rm_exec_argv = { "/bin/rm", input_dex, output_dex };
|
|
if (!::art::Exec(rm_exec_argv, error_msg)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool DexLayoutExec(ScratchFile* dex_file,
|
|
const char* dex_filename,
|
|
ScratchFile* profile_file,
|
|
std::vector<std::string>& dexlayout_exec_argv) {
|
|
WriteBase64ToFile(dex_filename, dex_file->GetFile());
|
|
EXPECT_EQ(dex_file->GetFile()->Flush(), 0);
|
|
if (profile_file != nullptr) {
|
|
CreateProfile(dex_file->GetFilename(), profile_file->GetFilename(), dex_file->GetFilename());
|
|
}
|
|
std::string error_msg;
|
|
const bool result = ::art::Exec(dexlayout_exec_argv, &error_msg);
|
|
if (!result) {
|
|
LOG(ERROR) << "Error: " << error_msg;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
|
|
TEST_F(DexLayoutTest, FullPlainOutput) {
|
|
// Disable test on target.
|
|
TEST_DISABLED_FOR_TARGET();
|
|
std::string error_msg;
|
|
ASSERT_TRUE(FullPlainOutputExec(&error_msg)) << error_msg;
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, DexFileOutput) {
|
|
// Disable test on target.
|
|
TEST_DISABLED_FOR_TARGET();
|
|
std::string error_msg;
|
|
ASSERT_TRUE(DexFileOutputExec(&error_msg)) << error_msg;
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, DexFileLayout) {
|
|
// Disable test on target.
|
|
TEST_DISABLED_FOR_TARGET();
|
|
std::string error_msg;
|
|
ASSERT_TRUE(DexFileLayoutExec(&error_msg)) << error_msg;
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, DexFileLayoutFixedPoint) {
|
|
// Disable test on target.
|
|
TEST_DISABLED_FOR_TARGET();
|
|
std::string error_msg;
|
|
ASSERT_TRUE(DexFileLayoutFixedPointExec(&error_msg)) << error_msg;
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, UnreferencedCatchHandler) {
|
|
// Disable test on target.
|
|
TEST_DISABLED_FOR_TARGET();
|
|
std::string error_msg;
|
|
ASSERT_TRUE(UnreferencedCatchHandlerExec(&error_msg,
|
|
kUnreferencedCatchHandlerInputDex)) << error_msg;
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, Unreferenced0SizeCatchHandler) {
|
|
// Disable test on target.
|
|
TEST_DISABLED_FOR_TARGET();
|
|
std::string error_msg;
|
|
ASSERT_TRUE(UnreferencedCatchHandlerExec(&error_msg,
|
|
kUnreferenced0SizeCatchHandlerInputDex)) << error_msg;
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, UnreferencedEndingCatchHandler) {
|
|
// Disable test on target.
|
|
TEST_DISABLED_FOR_TARGET();
|
|
std::string error_msg;
|
|
ASSERT_TRUE(UnreferencedCatchHandlerExec(&error_msg,
|
|
kUnreferencedEndingCatchHandlerInputDex)) << error_msg;
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, DuplicateOffset) {
|
|
ScratchFile temp_dex;
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-a", "-i", "-o", "/dev/null", temp_dex.GetFilename() };
|
|
ASSERT_TRUE(DexLayoutExec(&temp_dex,
|
|
kDexFileDuplicateOffset,
|
|
nullptr /* profile_file */,
|
|
dexlayout_exec_argv));
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, NullSetRefListElement) {
|
|
ScratchFile temp_dex;
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-o", "/dev/null", temp_dex.GetFilename() };
|
|
ASSERT_TRUE(DexLayoutExec(&temp_dex,
|
|
kNullSetRefListElementInputDex,
|
|
nullptr /* profile_file */,
|
|
dexlayout_exec_argv));
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, MultiClassData) {
|
|
ScratchFile temp_dex;
|
|
ScratchFile temp_profile;
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-p", temp_profile.GetFilename(), "-o", "/dev/null", temp_dex.GetFilename() };
|
|
ASSERT_TRUE(DexLayoutExec(&temp_dex,
|
|
kMultiClassDataInputDex,
|
|
&temp_profile,
|
|
dexlayout_exec_argv));
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, UnalignedCodeInfo) {
|
|
ScratchFile temp_dex;
|
|
ScratchFile temp_profile;
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-p", temp_profile.GetFilename(), "-o", "/dev/null", temp_dex.GetFilename() };
|
|
ASSERT_TRUE(DexLayoutExec(&temp_dex,
|
|
kUnalignedCodeInfoInputDex,
|
|
&temp_profile,
|
|
dexlayout_exec_argv));
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, ClassDataBeforeCode) {
|
|
ScratchFile temp_dex;
|
|
ScratchFile temp_profile;
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-p", temp_profile.GetFilename(), "-o", "/dev/null", temp_dex.GetFilename() };
|
|
ASSERT_TRUE(DexLayoutExec(&temp_dex,
|
|
kClassDataBeforeCodeInputDex,
|
|
&temp_profile,
|
|
dexlayout_exec_argv));
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, UnknownTypeDebugInfo) {
|
|
ScratchFile temp_dex;
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-o", "/dev/null", temp_dex.GetFilename() };
|
|
ASSERT_TRUE(DexLayoutExec(&temp_dex,
|
|
kUnknownTypeDebugInfoInputDex,
|
|
nullptr /* profile_file */,
|
|
dexlayout_exec_argv));
|
|
}
|
|
|
|
TEST_F(DexLayoutTest, DuplicateCodeItem) {
|
|
ScratchFile temp_dex;
|
|
std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout";
|
|
EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path";
|
|
std::vector<std::string> dexlayout_exec_argv =
|
|
{ dexlayout, "-o", "/dev/null", temp_dex.GetFilename() };
|
|
ASSERT_TRUE(DexLayoutExec(&temp_dex,
|
|
kDuplicateCodeItemInputDex,
|
|
nullptr /* profile_file */,
|
|
dexlayout_exec_argv));
|
|
}
|
|
|
|
} // namespace art
|