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:
SetUp()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
TEST_F(ElfWriterTest,dlsym)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
TEST_F(ElfWriterTest,CheckBuildIdPresent)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