1 /* 2 * Copyright (C) 2018 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 <stdint.h> 18 #include <sys/types.h> 19 #include <unistd.h> 20 21 #include <unordered_map> 22 23 #include <android-base/test_utils.h> 24 25 #include <unwindstack/MapInfo.h> 26 #include <unwindstack/Memory.h> 27 28 #include <dex/code_item_accessors-inl.h> 29 #include <dex/standard_dex_file.h> 30 31 #include <gtest/gtest.h> 32 33 #include "DexFile.h" 34 35 #include "DexFileData.h" 36 #include "MemoryFake.h" 37 38 namespace unwindstack { 39 40 TEST(DexFileTest, from_file_open_non_exist) { 41 DexFileFromFile dex_file; 42 ASSERT_FALSE(dex_file.Open(0, "/file/does/not/exist")); 43 } 44 45 TEST(DexFileTest, from_file_open_too_small) { 46 TemporaryFile tf; 47 ASSERT_TRUE(tf.fd != -1); 48 49 ASSERT_EQ(sizeof(art::DexFile::Header) - 2, 50 static_cast<size_t>( 51 TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)) - 2))); 52 53 // Header too small. 54 DexFileFromFile dex_file; 55 ASSERT_FALSE(dex_file.Open(0, tf.path)); 56 57 // Header correct, file too small. 58 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)); 59 ASSERT_EQ(sizeof(art::DexFile::Header), static_cast<size_t>(TEMP_FAILURE_RETRY(write( 60 tf.fd, kDexData, sizeof(art::DexFile::Header))))); 61 ASSERT_FALSE(dex_file.Open(0, tf.path)); 62 } 63 64 TEST(DexFileTest, from_file_open) { 65 TemporaryFile tf; 66 ASSERT_TRUE(tf.fd != -1); 67 68 ASSERT_EQ(sizeof(kDexData), 69 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); 70 71 DexFileFromFile dex_file; 72 ASSERT_TRUE(dex_file.Open(0, tf.path)); 73 } 74 75 TEST(DexFileTest, from_file_open_non_zero_offset) { 76 TemporaryFile tf; 77 ASSERT_TRUE(tf.fd != -1); 78 79 ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET)); 80 ASSERT_EQ(sizeof(kDexData), 81 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); 82 83 DexFileFromFile dex_file; 84 ASSERT_TRUE(dex_file.Open(0x100, tf.path)); 85 } 86 87 TEST(DexFileTest, from_memory_fail_too_small_for_header) { 88 MemoryFake memory; 89 90 memory.SetMemory(0x1000, kDexData, sizeof(art::DexFile::Header) - 1); 91 DexFileFromMemory dex_file; 92 93 ASSERT_FALSE(dex_file.Open(0x1000, &memory)); 94 } 95 96 TEST(DexFileTest, from_memory_fail_too_small_for_data) { 97 MemoryFake memory; 98 99 memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2); 100 DexFileFromMemory dex_file; 101 102 ASSERT_FALSE(dex_file.Open(0x1000, &memory)); 103 } 104 105 TEST(DexFileTest, from_memory_open) { 106 MemoryFake memory; 107 108 memory.SetMemory(0x1000, kDexData, sizeof(kDexData)); 109 DexFileFromMemory dex_file; 110 111 ASSERT_TRUE(dex_file.Open(0x1000, &memory)); 112 } 113 114 TEST(DexFileTest, create_using_file) { 115 TemporaryFile tf; 116 ASSERT_TRUE(tf.fd != -1); 117 118 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET)); 119 ASSERT_EQ(sizeof(kDexData), 120 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); 121 122 MemoryFake memory; 123 MapInfo info(0, 0x10000, 0, 0x5, tf.path); 124 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x500, &memory, &info)); 125 ASSERT_TRUE(dex_file != nullptr); 126 } 127 128 TEST(DexFileTest, create_using_file_non_zero_start) { 129 TemporaryFile tf; 130 ASSERT_TRUE(tf.fd != -1); 131 132 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET)); 133 ASSERT_EQ(sizeof(kDexData), 134 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); 135 136 MemoryFake memory; 137 MapInfo info(0x100, 0x10000, 0, 0x5, tf.path); 138 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x600, &memory, &info)); 139 ASSERT_TRUE(dex_file != nullptr); 140 } 141 142 TEST(DexFileTest, create_using_file_non_zero_offset) { 143 TemporaryFile tf; 144 ASSERT_TRUE(tf.fd != -1); 145 146 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET)); 147 ASSERT_EQ(sizeof(kDexData), 148 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); 149 150 MemoryFake memory; 151 MapInfo info(0x100, 0x10000, 0x200, 0x5, tf.path); 152 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x400, &memory, &info)); 153 ASSERT_TRUE(dex_file != nullptr); 154 } 155 156 TEST(DexFileTest, create_using_memory_empty_file) { 157 MemoryFake memory; 158 memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); 159 MapInfo info(0x100, 0x10000, 0x200, 0x5, ""); 160 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info)); 161 ASSERT_TRUE(dex_file != nullptr); 162 } 163 164 TEST(DexFileTest, create_using_memory_file_does_not_exist) { 165 MemoryFake memory; 166 memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); 167 MapInfo info(0x100, 0x10000, 0x200, 0x5, "/does/not/exist"); 168 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info)); 169 ASSERT_TRUE(dex_file != nullptr); 170 } 171 172 TEST(DexFileTest, create_using_memory_file_is_malformed) { 173 TemporaryFile tf; 174 ASSERT_TRUE(tf.fd != -1); 175 176 ASSERT_EQ(sizeof(kDexData) - 10, 177 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 10)))); 178 179 MemoryFake memory; 180 memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); 181 MapInfo info(0x4000, 0x10000, 0x200, 0x5, "/does/not/exist"); 182 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info)); 183 ASSERT_TRUE(dex_file != nullptr); 184 185 // Check it came from memory by clearing memory and verifying it fails. 186 memory.Clear(); 187 dex_file.reset(DexFile::Create(0x4000, &memory, &info)); 188 ASSERT_TRUE(dex_file == nullptr); 189 } 190 191 TEST(DexFileTest, get_method_not_opened) { 192 std::string method("something"); 193 uint64_t method_offset = 100; 194 DexFile dex_file; 195 dex_file.GetMethodInformation(0x100, &method, &method_offset); 196 EXPECT_EQ("something", method); 197 EXPECT_EQ(100U, method_offset); 198 } 199 200 TEST(DexFileTest, get_method) { 201 MemoryFake memory; 202 memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); 203 MapInfo info(0x100, 0x10000, 0x200, 0x5, ""); 204 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info)); 205 ASSERT_TRUE(dex_file != nullptr); 206 207 std::string method; 208 uint64_t method_offset; 209 dex_file->GetMethodInformation(0x102, &method, &method_offset); 210 EXPECT_EQ("Main.<init>", method); 211 EXPECT_EQ(2U, method_offset); 212 213 method = "not_in_a_method"; 214 method_offset = 0x123; 215 dex_file->GetMethodInformation(0x100000, &method, &method_offset); 216 EXPECT_EQ("not_in_a_method", method); 217 EXPECT_EQ(0x123U, method_offset); 218 } 219 220 } // namespace unwindstack 221