1 /* 2 * Copyright (C) 2011 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 <sys/mman.h> // For the PROT_NONE constant. 18 19 #include "elf_file.h" 20 21 #include "base/file_utils.h" 22 #include "base/mem_map.h" 23 #include "base/unix_file/fd_file.h" 24 #include "base/utils.h" 25 #include "common_compiler_driver_test.h" 26 #include "elf/elf_builder.h" 27 #include "elf_file.h" 28 #include "elf_file_impl.h" 29 #include "elf_writer_quick.h" 30 #include "oat.h" 31 32 namespace art { 33 namespace linker { 34 35 class ElfWriterTest : public CommonCompilerDriverTest { 36 protected: 37 void SetUp() override { 38 ReserveImageSpace(); 39 CommonCompilerTest::SetUp(); 40 } 41 }; 42 43 #define EXPECT_ELF_FILE_ADDRESS(ef, expected_value, symbol_name, build_map) \ 44 do { \ 45 void* addr = reinterpret_cast<void*>((ef)->FindSymbolAddress(SHT_DYNSYM, \ 46 symbol_name, \ 47 build_map)); \ 48 EXPECT_NE(nullptr, addr); \ 49 if ((expected_value) == nullptr) { \ 50 (expected_value) = addr; \ 51 } \ 52 EXPECT_EQ(expected_value, addr); \ 53 EXPECT_EQ(expected_value, (ef)->FindDynamicSymbolAddress(symbol_name)); \ 54 } while (false) 55 56 TEST_F(ElfWriterTest, dlsym) { 57 std::string elf_location = GetCoreOatLocation(); 58 std::string elf_filename = GetSystemImageFilename(elf_location.c_str(), kRuntimeISA); 59 LOG(INFO) << "elf_filename=" << elf_filename; 60 61 UnreserveImageSpace(); 62 void* dl_oatdata = nullptr; 63 void* dl_oatexec = nullptr; 64 void* dl_oatlastword = nullptr; 65 66 std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str())); 67 ASSERT_TRUE(file.get() != nullptr) << elf_filename; 68 { 69 std::string error_msg; 70 std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), 71 /*writable=*/ false, 72 /*program_header_only=*/ false, 73 /*low_4gb=*/false, 74 &error_msg)); 75 CHECK(ef.get() != nullptr) << error_msg; 76 EXPECT_ELF_FILE_ADDRESS(ef, dl_oatdata, "oatdata", false); 77 EXPECT_ELF_FILE_ADDRESS(ef, dl_oatexec, "oatexec", false); 78 EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", false); 79 } 80 { 81 std::string error_msg; 82 std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), 83 /*writable=*/ false, 84 /*program_header_only=*/ false, 85 /*low_4gb=*/ false, 86 &error_msg)); 87 CHECK(ef.get() != nullptr) << error_msg; 88 EXPECT_ELF_FILE_ADDRESS(ef, dl_oatdata, "oatdata", true); 89 EXPECT_ELF_FILE_ADDRESS(ef, dl_oatexec, "oatexec", true); 90 EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", true); 91 } 92 { 93 std::string error_msg; 94 std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), 95 /*writable=*/ false, 96 /*program_header_only=*/ true, 97 /*low_4gb=*/ false, 98 &error_msg)); 99 CHECK(ef.get() != nullptr) << error_msg; 100 size_t size; 101 bool success = ef->GetLoadedSize(&size, &error_msg); 102 CHECK(success) << error_msg; 103 MemMap reservation = MemMap::MapAnonymous("ElfWriterTest#dlsym reservation", 104 RoundUp(size, kPageSize), 105 PROT_NONE, 106 /*low_4gb=*/ true, 107 &error_msg); 108 CHECK(reservation.IsValid()) << error_msg; 109 uint8_t* base = reservation.Begin(); 110 success = 111 ef->Load(file.get(), /*executable=*/ false, /*low_4gb=*/ false, &reservation, &error_msg); 112 CHECK(success) << error_msg; 113 CHECK(!reservation.IsValid()); 114 EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatdata) + reinterpret_cast<uintptr_t>(base), 115 reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatdata"))); 116 EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatexec) + reinterpret_cast<uintptr_t>(base), 117 reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatexec"))); 118 EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatlastword) + reinterpret_cast<uintptr_t>(base), 119 reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatlastword"))); 120 } 121 } 122 123 TEST_F(ElfWriterTest, CheckBuildIdPresent) { 124 std::string elf_location = GetCoreOatLocation(); 125 std::string elf_filename = GetSystemImageFilename(elf_location.c_str(), kRuntimeISA); 126 LOG(INFO) << "elf_filename=" << elf_filename; 127 128 std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str())); 129 ASSERT_TRUE(file.get() != nullptr); 130 { 131 std::string error_msg; 132 std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), 133 /*writable=*/ false, 134 /*program_header_only=*/ false, 135 /*low_4gb=*/ false, 136 &error_msg)); 137 CHECK(ef.get() != nullptr) << error_msg; 138 EXPECT_TRUE(ef->HasSection(".note.gnu.build-id")); 139 } 140 } 141 142 } // namespace linker 143 } // namespace art 144