blob: 0b4f1f3be24248927deb870155b544892fcfe4e7 [file] [log] [blame]
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001/*
2 * Copyright (C) 2012 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 "elf_file.h"
18
Tong Shen62d1ca32014-09-03 17:24:56 -070019#include <inttypes.h>
Andreas Gampe0dfc3152017-04-24 07:58:06 -070020#include <sys/mman.h> // For the PROT_* and MAP_* constants.
Nicolas Geoffraya7f198c2014-03-10 11:12:54 +000021#include <sys/types.h>
22#include <unistd.h>
23
Andreas Gampe46ee31b2016-12-14 10:11:49 -080024#include "android-base/stringprintf.h"
Andreas Gampe9186ced2016-12-12 14:28:21 -080025#include "android-base/strings.h"
26
Ian Rogersd582fa42014-11-05 23:46:43 -080027#include "arch/instruction_set.h"
David Sehr67bf42e2018-02-26 16:43:04 -080028#include "base/leb128.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080029#include "base/stl_util.h"
Ian Rogersd4c4d952014-10-16 20:31:53 -070030#include "base/unix_file/fd_file.h"
David Sehrc431b9d2018-03-02 12:01:51 -080031#include "base/utils.h"
David Srbecky50928112019-03-22 17:06:28 +000032#include "elf/elf_utils.h"
Ian Rogersd4c4d952014-10-16 20:31:53 -070033#include "elf_file_impl.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080034
35namespace art {
36
Andreas Gampe46ee31b2016-12-14 10:11:49 -080037using android::base::StringPrintf;
38
David Srbecky533c2072015-04-22 12:20:22 +010039template <typename ElfTypes>
Vladimir Markoc09cd052018-08-23 16:36:36 +010040ElfFileImpl<ElfTypes>::ElfFileImpl(File* file, bool writable, bool program_header_only)
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -070041 : writable_(writable),
Brian Carlstromc1409452014-02-26 14:06:23 -080042 program_header_only_(program_header_only),
Alex Light3470ab42014-06-18 10:35:45 -070043 header_(nullptr),
44 base_address_(nullptr),
45 program_headers_start_(nullptr),
46 section_headers_start_(nullptr),
47 dynamic_program_header_(nullptr),
48 dynamic_section_start_(nullptr),
49 symtab_section_start_(nullptr),
50 dynsym_section_start_(nullptr),
51 strtab_section_start_(nullptr),
52 dynstr_section_start_(nullptr),
53 hash_section_start_(nullptr),
54 symtab_symbol_table_(nullptr),
Vladimir Markoc09cd052018-08-23 16:36:36 +010055 dynsym_symbol_table_(nullptr) {
Alex Light3470ab42014-06-18 10:35:45 -070056 CHECK(file != nullptr);
Brian Carlstromc1409452014-02-26 14:06:23 -080057}
Brian Carlstrom700c8d32012-11-05 10:42:02 -080058
David Srbecky533c2072015-04-22 12:20:22 +010059template <typename ElfTypes>
Mathieu Chartierbcb6a722016-03-08 16:49:58 -080060ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file,
61 bool writable,
62 bool program_header_only,
63 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +010064 std::string* error_msg) {
65 std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(
66 new ElfFileImpl<ElfTypes>(file, writable, program_header_only));
Brian Carlstrom700c8d32012-11-05 10:42:02 -080067 int prot;
68 int flags;
Alex Light3470ab42014-06-18 10:35:45 -070069 if (writable) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -080070 prot = PROT_READ | PROT_WRITE;
71 flags = MAP_SHARED;
72 } else {
73 prot = PROT_READ;
74 flags = MAP_PRIVATE;
75 }
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -070076 if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) {
Alex Light3470ab42014-06-18 10:35:45 -070077 return nullptr;
78 }
79 return elf_file.release();
80}
81
David Srbecky533c2072015-04-22 12:20:22 +010082template <typename ElfTypes>
Mathieu Chartierbcb6a722016-03-08 16:49:58 -080083ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file,
84 int prot,
85 int flags,
86 bool low_4gb,
87 std::string* error_msg) {
Vladimir Markoc09cd052018-08-23 16:36:36 +010088 std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(
Andreas Gampe98ea9d92018-10-19 14:06:15 -070089 new ElfFileImpl<ElfTypes>(file, (prot & PROT_WRITE) != 0, /* program_header_only= */ false));
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -070090 if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) {
Alex Light3470ab42014-06-18 10:35:45 -070091 return nullptr;
92 }
93 return elf_file.release();
94}
95
David Srbecky533c2072015-04-22 12:20:22 +010096template <typename ElfTypes>
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -070097bool ElfFileImpl<ElfTypes>::Setup(File* file,
98 int prot,
99 int flags,
100 bool low_4gb,
101 std::string* error_msg) {
102 int64_t temp_file_length = file->GetLength();
Ian Rogerscdfcf372014-01-23 20:38:36 -0800103 if (temp_file_length < 0) {
104 errno = -temp_file_length;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700105 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700106 file->GetPath().c_str(), file->Fd(), strerror(errno));
Brian Carlstrom265091e2013-01-30 14:08:26 -0800107 return false;
108 }
Ian Rogerscdfcf372014-01-23 20:38:36 -0800109 size_t file_length = static_cast<size_t>(temp_file_length);
Tong Shen62d1ca32014-09-03 17:24:56 -0700110 if (file_length < sizeof(Elf_Ehdr)) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800111 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF header of "
Tong Shen62d1ca32014-09-03 17:24:56 -0700112 "%zd bytes: '%s'", file_length, sizeof(Elf_Ehdr),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700113 file->GetPath().c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800114 return false;
115 }
116
Brian Carlstromc1409452014-02-26 14:06:23 -0800117 if (program_header_only_) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800118 // first just map ELF header to get program header size information
Tong Shen62d1ca32014-09-03 17:24:56 -0700119 size_t elf_header_size = sizeof(Elf_Ehdr);
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700120 if (!SetMap(file,
121 MemMap::MapFile(elf_header_size,
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800122 prot,
123 flags,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700124 file->Fd(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800125 0,
Mathieu Chartierbcb6a722016-03-08 16:49:58 -0800126 low_4gb,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700127 file->GetPath().c_str(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800128 error_msg),
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800129 error_msg)) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800130 return false;
131 }
132 // then remap to cover program header
133 size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum);
Brian Carlstrom3a223612013-10-10 17:18:24 -0700134 if (file_length < program_header_size) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800135 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program "
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700136 "header of %zd bytes: '%s'", file_length,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700137 sizeof(Elf_Ehdr), file->GetPath().c_str());
Brian Carlstrom3a223612013-10-10 17:18:24 -0700138 return false;
139 }
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700140 if (!SetMap(file,
141 MemMap::MapFile(program_header_size,
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800142 prot,
143 flags,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700144 file->Fd(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800145 0,
Mathieu Chartierbcb6a722016-03-08 16:49:58 -0800146 low_4gb,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700147 file->GetPath().c_str(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800148 error_msg),
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800149 error_msg)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700150 *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800151 return false;
152 }
153 } else {
154 // otherwise map entire file
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700155 if (!SetMap(file,
156 MemMap::MapFile(file->GetLength(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800157 prot,
158 flags,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700159 file->Fd(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800160 0,
Mathieu Chartierbcb6a722016-03-08 16:49:58 -0800161 low_4gb,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700162 file->GetPath().c_str(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800163 error_msg),
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800164 error_msg)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700165 *error_msg = StringPrintf("Failed to map ELF file: %s", error_msg->c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800166 return false;
167 }
168 }
169
Andreas Gampedaab38c2014-09-12 18:38:24 -0700170 if (program_header_only_) {
171 program_headers_start_ = Begin() + GetHeader().e_phoff;
172 } else {
173 if (!CheckAndSet(GetHeader().e_phoff, "program headers", &program_headers_start_, error_msg)) {
174 return false;
175 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800176
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800177 // Setup section headers.
Andreas Gampedaab38c2014-09-12 18:38:24 -0700178 if (!CheckAndSet(GetHeader().e_shoff, "section headers", &section_headers_start_, error_msg)) {
179 return false;
180 }
181
182 // Find shstrtab.
Tong Shen62d1ca32014-09-03 17:24:56 -0700183 Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700184 if (shstrtab_section_header == nullptr) {
185 *error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700186 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700187 return false;
188 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800189
190 // Find .dynamic section info from program header
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000191 dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC);
Alex Light3470ab42014-06-18 10:35:45 -0700192 if (dynamic_program_header_ == nullptr) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700193 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700194 file->GetPath().c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800195 return false;
196 }
197
Andreas Gampedaab38c2014-09-12 18:38:24 -0700198 if (!CheckAndSet(GetDynamicProgramHeader().p_offset, "dynamic section",
Ian Rogers13735952014-10-08 12:43:28 -0700199 reinterpret_cast<uint8_t**>(&dynamic_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700200 return false;
201 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800202
203 // Find other sections from section headers
Tong Shen62d1ca32014-09-03 17:24:56 -0700204 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
205 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700206 if (section_header == nullptr) {
207 *error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700208 i, file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700209 return false;
210 }
211 switch (section_header->sh_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000212 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700213 if (!CheckAndSet(section_header->sh_offset, "symtab",
Ian Rogers13735952014-10-08 12:43:28 -0700214 reinterpret_cast<uint8_t**>(&symtab_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700215 return false;
216 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800217 break;
218 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000219 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700220 if (!CheckAndSet(section_header->sh_offset, "dynsym",
Ian Rogers13735952014-10-08 12:43:28 -0700221 reinterpret_cast<uint8_t**>(&dynsym_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700222 return false;
223 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800224 break;
225 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000226 case SHT_STRTAB: {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800227 // TODO: base these off of sh_link from .symtab and .dynsym above
Andreas Gampedaab38c2014-09-12 18:38:24 -0700228 if ((section_header->sh_flags & SHF_ALLOC) != 0) {
229 // Check that this is named ".dynstr" and ignore otherwise.
230 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
231 if (strncmp(".dynstr", header_name, 8) == 0) {
232 if (!CheckAndSet(section_header->sh_offset, "dynstr",
Ian Rogers13735952014-10-08 12:43:28 -0700233 reinterpret_cast<uint8_t**>(&dynstr_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700234 return false;
235 }
236 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800237 } else {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700238 // Check that this is named ".strtab" and ignore otherwise.
239 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
240 if (strncmp(".strtab", header_name, 8) == 0) {
241 if (!CheckAndSet(section_header->sh_offset, "strtab",
Ian Rogers13735952014-10-08 12:43:28 -0700242 reinterpret_cast<uint8_t**>(&strtab_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700243 return false;
244 }
245 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800246 }
247 break;
248 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000249 case SHT_DYNAMIC: {
Ian Rogers13735952014-10-08 12:43:28 -0700250 if (reinterpret_cast<uint8_t*>(dynamic_section_start_) !=
Andreas Gampedaab38c2014-09-12 18:38:24 -0700251 Begin() + section_header->sh_offset) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800252 LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in "
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700253 << file->GetPath() << ": " << std::hex
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800254 << reinterpret_cast<void*>(dynamic_section_start_)
Andreas Gampedaab38c2014-09-12 18:38:24 -0700255 << " != " << reinterpret_cast<void*>(Begin() + section_header->sh_offset);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800256 return false;
257 }
258 break;
259 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000260 case SHT_HASH: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700261 if (!CheckAndSet(section_header->sh_offset, "hash section",
Ian Rogers13735952014-10-08 12:43:28 -0700262 reinterpret_cast<uint8_t**>(&hash_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700263 return false;
264 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800265 break;
266 }
267 }
268 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700269
270 // Check for the existence of some sections.
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700271 if (!CheckSectionsExist(file, error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700272 return false;
273 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800274 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700275
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800276 return true;
277}
278
David Srbecky533c2072015-04-22 12:20:22 +0100279template <typename ElfTypes>
280ElfFileImpl<ElfTypes>::~ElfFileImpl() {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800281 delete symtab_symbol_table_;
282 delete dynsym_symbol_table_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800283}
284
David Srbecky533c2072015-04-22 12:20:22 +0100285template <typename ElfTypes>
286bool ElfFileImpl<ElfTypes>::CheckAndSet(Elf32_Off offset, const char* label,
287 uint8_t** target, std::string* error_msg) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700288 if (Begin() + offset >= End()) {
289 *error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700290 file_path_.c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700291 return false;
292 }
293 *target = Begin() + offset;
294 return true;
295}
296
David Srbecky533c2072015-04-22 12:20:22 +0100297template <typename ElfTypes>
298bool ElfFileImpl<ElfTypes>::CheckSectionsLinked(const uint8_t* source,
299 const uint8_t* target) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700300 // Only works in whole-program mode, as we need to iterate over the sections.
301 // Note that we normally can't search by type, as duplicates are allowed for most section types.
302 if (program_header_only_) {
303 return true;
304 }
305
Tong Shen62d1ca32014-09-03 17:24:56 -0700306 Elf_Shdr* source_section = nullptr;
307 Elf_Word target_index = 0;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700308 bool target_found = false;
Tong Shen62d1ca32014-09-03 17:24:56 -0700309 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
310 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700311
312 if (Begin() + section_header->sh_offset == source) {
313 // Found the source.
314 source_section = section_header;
315 if (target_index) {
316 break;
317 }
318 } else if (Begin() + section_header->sh_offset == target) {
319 target_index = i;
320 target_found = true;
321 if (source_section != nullptr) {
322 break;
323 }
324 }
325 }
326
327 return target_found && source_section != nullptr && source_section->sh_link == target_index;
328}
329
David Srbecky533c2072015-04-22 12:20:22 +0100330template <typename ElfTypes>
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700331 bool ElfFileImpl<ElfTypes>::CheckSectionsExist(File* file, std::string* error_msg) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700332 if (!program_header_only_) {
333 // If in full mode, need section headers.
334 if (section_headers_start_ == nullptr) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700335 *error_msg = StringPrintf("No section headers in ELF file: '%s'", file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700336 return false;
337 }
338 }
339
340 // This is redundant, but defensive.
341 if (dynamic_program_header_ == nullptr) {
342 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700343 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700344 return false;
345 }
346
347 // Need a dynamic section. This is redundant, but defensive.
348 if (dynamic_section_start_ == nullptr) {
349 *error_msg = StringPrintf("Failed to find dynamic section in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700350 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700351 return false;
352 }
353
354 // Symtab validation. These is not really a hard failure, as we are currently not using the
355 // symtab internally, but it's nice to be defensive.
356 if (symtab_section_start_ != nullptr) {
357 // When there's a symtab, there should be a strtab.
358 if (strtab_section_start_ == nullptr) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700359 *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700360 return false;
361 }
362
363 // The symtab should link to the strtab.
Ian Rogers13735952014-10-08 12:43:28 -0700364 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(symtab_section_start_),
365 reinterpret_cast<const uint8_t*>(strtab_section_start_))) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700366 *error_msg = StringPrintf("Symtab is not linked to the strtab in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700367 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700368 return false;
369 }
370 }
371
372 // We always need a dynstr & dynsym.
373 if (dynstr_section_start_ == nullptr) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700374 *error_msg = StringPrintf("No dynstr in ELF file: '%s'", file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700375 return false;
376 }
377 if (dynsym_section_start_ == nullptr) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700378 *error_msg = StringPrintf("No dynsym in ELF file: '%s'", file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700379 return false;
380 }
381
382 // Need a hash section for dynamic symbol lookup.
383 if (hash_section_start_ == nullptr) {
384 *error_msg = StringPrintf("Failed to find hash section in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700385 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700386 return false;
387 }
388
389 // And the hash section should be linking to the dynsym.
Ian Rogers13735952014-10-08 12:43:28 -0700390 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(hash_section_start_),
391 reinterpret_cast<const uint8_t*>(dynsym_section_start_))) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700392 *error_msg = StringPrintf("Hash section is not linked to the dynstr in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700393 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700394 return false;
395 }
396
Andreas Gampea696c0a2014-12-10 20:51:45 -0800397 // We'd also like to confirm a shstrtab in program_header_only_ mode (else Open() does this for
398 // us). This is usually the last in an oat file, and a good indicator of whether writing was
399 // successful (or the process crashed and left garbage).
400 if (program_header_only_) {
401 // It might not be mapped, but we can compare against the file size.
402 int64_t offset = static_cast<int64_t>(GetHeader().e_shoff +
403 (GetHeader().e_shstrndx * GetHeader().e_shentsize));
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700404 if (offset >= file->GetLength()) {
Andreas Gampea696c0a2014-12-10 20:51:45 -0800405 *error_msg = StringPrintf("Shstrtab is not in the mapped ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700406 file->GetPath().c_str());
Andreas Gampea696c0a2014-12-10 20:51:45 -0800407 return false;
408 }
409 }
410
Andreas Gampedaab38c2014-09-12 18:38:24 -0700411 return true;
412}
413
David Srbecky533c2072015-04-22 12:20:22 +0100414template <typename ElfTypes>
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100415bool ElfFileImpl<ElfTypes>::SetMap(File* file, MemMap&& map, std::string* error_msg) {
416 if (!map.IsValid()) {
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800417 // MemMap::Open should have already set an error.
418 DCHECK(!error_msg->empty());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800419 return false;
420 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100421 map_ = std::move(map);
422 CHECK(map_.IsValid()) << file->GetPath();
423 CHECK(map_.Begin() != nullptr) << file->GetPath();
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800424
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100425 header_ = reinterpret_cast<Elf_Ehdr*>(map_.Begin());
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000426 if ((ELFMAG0 != header_->e_ident[EI_MAG0])
427 || (ELFMAG1 != header_->e_ident[EI_MAG1])
428 || (ELFMAG2 != header_->e_ident[EI_MAG2])
429 || (ELFMAG3 != header_->e_ident[EI_MAG3])) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800430 *error_msg = StringPrintf("Failed to find ELF magic value %d %d %d %d in %s, found %d %d %d %d",
431 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700432 file->GetPath().c_str(),
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000433 header_->e_ident[EI_MAG0],
434 header_->e_ident[EI_MAG1],
435 header_->e_ident[EI_MAG2],
436 header_->e_ident[EI_MAG3]);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800437 return false;
438 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700439 uint8_t elf_class = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) ? ELFCLASS64 : ELFCLASS32;
440 if (elf_class != header_->e_ident[EI_CLASS]) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800441 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d in %s, found %d",
Tong Shen62d1ca32014-09-03 17:24:56 -0700442 elf_class,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700443 file->GetPath().c_str(),
Brian Carlstromc1409452014-02-26 14:06:23 -0800444 header_->e_ident[EI_CLASS]);
445 return false;
446 }
447 if (ELFDATA2LSB != header_->e_ident[EI_DATA]) {
448 *error_msg = StringPrintf("Failed to find expected EI_DATA value %d in %s, found %d",
449 ELFDATA2LSB,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700450 file->GetPath().c_str(),
Brian Carlstromc1409452014-02-26 14:06:23 -0800451 header_->e_ident[EI_CLASS]);
452 return false;
453 }
454 if (EV_CURRENT != header_->e_ident[EI_VERSION]) {
455 *error_msg = StringPrintf("Failed to find expected EI_VERSION value %d in %s, found %d",
456 EV_CURRENT,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700457 file->GetPath().c_str(),
Brian Carlstromc1409452014-02-26 14:06:23 -0800458 header_->e_ident[EI_CLASS]);
459 return false;
460 }
461 if (ET_DYN != header_->e_type) {
462 *error_msg = StringPrintf("Failed to find expected e_type value %d in %s, found %d",
463 ET_DYN,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700464 file->GetPath().c_str(),
Brian Carlstromc1409452014-02-26 14:06:23 -0800465 header_->e_type);
466 return false;
467 }
468 if (EV_CURRENT != header_->e_version) {
469 *error_msg = StringPrintf("Failed to find expected e_version value %d in %s, found %d",
470 EV_CURRENT,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700471 file->GetPath().c_str(),
Brian Carlstromc1409452014-02-26 14:06:23 -0800472 header_->e_version);
473 return false;
474 }
475 if (0 != header_->e_entry) {
476 *error_msg = StringPrintf("Failed to find expected e_entry value %d in %s, found %d",
477 0,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700478 file->GetPath().c_str(),
Tong Shen62d1ca32014-09-03 17:24:56 -0700479 static_cast<int32_t>(header_->e_entry));
Brian Carlstromc1409452014-02-26 14:06:23 -0800480 return false;
481 }
482 if (0 == header_->e_phoff) {
483 *error_msg = StringPrintf("Failed to find non-zero e_phoff value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700484 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800485 return false;
486 }
487 if (0 == header_->e_shoff) {
488 *error_msg = StringPrintf("Failed to find non-zero e_shoff value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700489 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800490 return false;
491 }
492 if (0 == header_->e_ehsize) {
493 *error_msg = StringPrintf("Failed to find non-zero e_ehsize value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700494 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800495 return false;
496 }
497 if (0 == header_->e_phentsize) {
498 *error_msg = StringPrintf("Failed to find non-zero e_phentsize value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700499 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800500 return false;
501 }
502 if (0 == header_->e_phnum) {
503 *error_msg = StringPrintf("Failed to find non-zero e_phnum value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700504 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800505 return false;
506 }
507 if (0 == header_->e_shentsize) {
508 *error_msg = StringPrintf("Failed to find non-zero e_shentsize value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700509 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800510 return false;
511 }
512 if (0 == header_->e_shnum) {
513 *error_msg = StringPrintf("Failed to find non-zero e_shnum value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700514 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800515 return false;
516 }
517 if (0 == header_->e_shstrndx) {
518 *error_msg = StringPrintf("Failed to find non-zero e_shstrndx value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700519 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800520 return false;
521 }
522 if (header_->e_shstrndx >= header_->e_shnum) {
523 *error_msg = StringPrintf("Failed to find e_shnum value %d less than %d in %s",
524 header_->e_shstrndx,
525 header_->e_shnum,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700526 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800527 return false;
528 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800529
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800530 if (!program_header_only_) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800531 if (header_->e_phoff >= Size()) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700532 *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s",
533 static_cast<uint64_t>(header_->e_phoff),
Brian Carlstromc1409452014-02-26 14:06:23 -0800534 Size(),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700535 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800536 return false;
537 }
538 if (header_->e_shoff >= Size()) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700539 *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s",
540 static_cast<uint64_t>(header_->e_shoff),
Brian Carlstromc1409452014-02-26 14:06:23 -0800541 Size(),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700542 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800543 return false;
544 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800545 }
546 return true;
547}
548
David Srbecky533c2072015-04-22 12:20:22 +0100549template <typename ElfTypes>
550typename ElfTypes::Ehdr& ElfFileImpl<ElfTypes>::GetHeader() const {
Ian Pedowitz2d536432020-07-22 14:33:00 -0700551 CHECK(header_ != nullptr); // Header has been checked in SetMap
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800552 return *header_;
553}
554
David Srbecky533c2072015-04-22 12:20:22 +0100555template <typename ElfTypes>
556uint8_t* ElfFileImpl<ElfTypes>::GetProgramHeadersStart() const {
Ian Pedowitz2d536432020-07-22 14:33:00 -0700557 CHECK(program_headers_start_ != nullptr); // Header has been set in Setup
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800558 return program_headers_start_;
559}
560
David Srbecky533c2072015-04-22 12:20:22 +0100561template <typename ElfTypes>
562uint8_t* ElfFileImpl<ElfTypes>::GetSectionHeadersStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700563 CHECK(!program_header_only_); // Only used in "full" mode.
Ian Pedowitz2d536432020-07-22 14:33:00 -0700564 CHECK(section_headers_start_ != nullptr); // Is checked in CheckSectionsExist
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800565 return section_headers_start_;
566}
567
David Srbecky533c2072015-04-22 12:20:22 +0100568template <typename ElfTypes>
569typename ElfTypes::Phdr& ElfFileImpl<ElfTypes>::GetDynamicProgramHeader() const {
Ian Pedowitz2d536432020-07-22 14:33:00 -0700570 CHECK(dynamic_program_header_ != nullptr); // Is checked in CheckSectionsExist
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800571 return *dynamic_program_header_;
572}
573
David Srbecky533c2072015-04-22 12:20:22 +0100574template <typename ElfTypes>
575typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::GetDynamicSectionStart() const {
Ian Pedowitz2d536432020-07-22 14:33:00 -0700576 CHECK(dynamic_section_start_ != nullptr); // Is checked in CheckSectionsExist
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800577 return dynamic_section_start_;
578}
579
David Srbecky533c2072015-04-22 12:20:22 +0100580template <typename ElfTypes>
581typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbolSectionStart(
582 Elf_Word section_type) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700583 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800584 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000585 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700586 return symtab_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800587 break;
588 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000589 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700590 return dynsym_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800591 break;
592 }
593 default: {
594 LOG(FATAL) << section_type;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700595 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800596 }
597 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800598}
599
David Srbecky533c2072015-04-22 12:20:22 +0100600template <typename ElfTypes>
601const char* ElfFileImpl<ElfTypes>::GetStringSectionStart(
602 Elf_Word section_type) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700603 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800604 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000605 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700606 return strtab_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800607 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000608 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700609 return dynstr_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800610 }
611 default: {
612 LOG(FATAL) << section_type;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700613 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800614 }
615 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800616}
617
David Srbecky533c2072015-04-22 12:20:22 +0100618template <typename ElfTypes>
619const char* ElfFileImpl<ElfTypes>::GetString(Elf_Word section_type,
620 Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700621 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800622 if (i == 0) {
Alex Light3470ab42014-06-18 10:35:45 -0700623 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800624 }
625 const char* string_section_start = GetStringSectionStart(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700626 if (string_section_start == nullptr) {
627 return nullptr;
628 }
629 return string_section_start + i;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800630}
631
Andreas Gampedaab38c2014-09-12 18:38:24 -0700632// WARNING: The following methods do not check for an error condition (non-existent hash section).
633// It is the caller's job to do this.
634
David Srbecky533c2072015-04-22 12:20:22 +0100635template <typename ElfTypes>
636typename ElfTypes::Word* ElfFileImpl<ElfTypes>::GetHashSectionStart() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800637 return hash_section_start_;
638}
639
David Srbecky533c2072015-04-22 12:20:22 +0100640template <typename ElfTypes>
641typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashBucketNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800642 return GetHashSectionStart()[0];
643}
644
David Srbecky533c2072015-04-22 12:20:22 +0100645template <typename ElfTypes>
646typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashChainNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800647 return GetHashSectionStart()[1];
648}
649
David Srbecky533c2072015-04-22 12:20:22 +0100650template <typename ElfTypes>
651typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashBucket(size_t i, bool* ok) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700652 if (i >= GetHashBucketNum()) {
653 *ok = false;
654 return 0;
655 }
656 *ok = true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800657 // 0 is nbucket, 1 is nchain
658 return GetHashSectionStart()[2 + i];
659}
660
David Srbecky533c2072015-04-22 12:20:22 +0100661template <typename ElfTypes>
662typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashChain(size_t i, bool* ok) const {
Yevgeny Roubanacb01382014-11-24 13:40:56 +0600663 if (i >= GetHashChainNum()) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700664 *ok = false;
665 return 0;
666 }
667 *ok = true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800668 // 0 is nbucket, 1 is nchain, & chains are after buckets
669 return GetHashSectionStart()[2 + GetHashBucketNum() + i];
670}
671
David Srbecky533c2072015-04-22 12:20:22 +0100672template <typename ElfTypes>
673typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetProgramHeaderNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800674 return GetHeader().e_phnum;
675}
676
David Srbecky533c2072015-04-22 12:20:22 +0100677template <typename ElfTypes>
678typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::GetProgramHeader(Elf_Word i) const {
Ian Pedowitz2d536432020-07-22 14:33:00 -0700679 CHECK_LT(i, GetProgramHeaderNum()) << file_path_; // Validity check for caller.
Ian Rogers13735952014-10-08 12:43:28 -0700680 uint8_t* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize);
Vladimir Markoc09cd052018-08-23 16:36:36 +0100681 CHECK_LT(program_header, End());
Tong Shen62d1ca32014-09-03 17:24:56 -0700682 return reinterpret_cast<Elf_Phdr*>(program_header);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800683}
684
David Srbecky533c2072015-04-22 12:20:22 +0100685template <typename ElfTypes>
686typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::FindProgamHeaderByType(Elf_Word type) const {
Tong Shen62d1ca32014-09-03 17:24:56 -0700687 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
688 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700689 if (program_header->p_type == type) {
690 return program_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800691 }
692 }
Alex Light3470ab42014-06-18 10:35:45 -0700693 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800694}
695
David Srbecky533c2072015-04-22 12:20:22 +0100696template <typename ElfTypes>
697typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSectionHeaderNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800698 return GetHeader().e_shnum;
699}
700
David Srbecky533c2072015-04-22 12:20:22 +0100701template <typename ElfTypes>
702typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionHeader(Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800703 // Can only access arbitrary sections when we have the whole file, not just program header.
704 // Even if we Load(), it doesn't bring in all the sections.
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700705 CHECK(!program_header_only_) << file_path_;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700706 if (i >= GetSectionHeaderNum()) {
707 return nullptr; // Failure condition.
708 }
Ian Rogers13735952014-10-08 12:43:28 -0700709 uint8_t* section_header = GetSectionHeadersStart() + (i * GetHeader().e_shentsize);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700710 if (section_header >= End()) {
711 return nullptr; // Failure condition.
712 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700713 return reinterpret_cast<Elf_Shdr*>(section_header);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800714}
715
David Srbecky533c2072015-04-22 12:20:22 +0100716template <typename ElfTypes>
717typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByType(Elf_Word type) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800718 // Can only access arbitrary sections when we have the whole file, not just program header.
719 // We could change this to switch on known types if they were detected during loading.
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700720 CHECK(!program_header_only_) << file_path_;
Tong Shen62d1ca32014-09-03 17:24:56 -0700721 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
722 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700723 if (section_header->sh_type == type) {
724 return section_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800725 }
726 }
Alex Light3470ab42014-06-18 10:35:45 -0700727 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800728}
729
730// from bionic
Brian Carlstrom265091e2013-01-30 14:08:26 -0800731static unsigned elfhash(const char *_name) {
732 const unsigned char *name = (const unsigned char *) _name;
733 unsigned h = 0, g;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800734
Brian Carlstromdf629502013-07-17 22:39:56 -0700735 while (*name) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800736 h = (h << 4) + *name++;
737 g = h & 0xf0000000;
738 h ^= g;
739 h ^= g >> 24;
740 }
741 return h;
742}
743
David Srbecky533c2072015-04-22 12:20:22 +0100744template <typename ElfTypes>
745typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionNameStringSection() const {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800746 return GetSectionHeader(GetHeader().e_shstrndx);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800747}
748
David Srbecky533c2072015-04-22 12:20:22 +0100749template <typename ElfTypes>
750const uint8_t* ElfFileImpl<ElfTypes>::FindDynamicSymbolAddress(
751 const std::string& symbol_name) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700752 // Check that we have a hash section.
753 if (GetHashSectionStart() == nullptr) {
754 return nullptr; // Failure condition.
755 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700756 const Elf_Sym* sym = FindDynamicSymbol(symbol_name);
Alex Light3470ab42014-06-18 10:35:45 -0700757 if (sym != nullptr) {
Igor Murashkin46774762014-10-22 11:37:02 -0700758 // TODO: we need to change this to calculate base_address_ in ::Open,
759 // otherwise it will be wrongly 0 if ::Load has not yet been called.
Alex Light3470ab42014-06-18 10:35:45 -0700760 return base_address_ + sym->st_value;
761 } else {
762 return nullptr;
763 }
764}
765
Andreas Gampedaab38c2014-09-12 18:38:24 -0700766// WARNING: Only called from FindDynamicSymbolAddress. Elides check for hash section.
David Srbecky533c2072015-04-22 12:20:22 +0100767template <typename ElfTypes>
768const typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindDynamicSymbol(
769 const std::string& symbol_name) const {
Andreas Gampec48b2062014-09-08 23:39:45 -0700770 if (GetHashBucketNum() == 0) {
771 // No dynamic symbols at all.
772 return nullptr;
773 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700774 Elf_Word hash = elfhash(symbol_name.c_str());
775 Elf_Word bucket_index = hash % GetHashBucketNum();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700776 bool ok;
Tong Shen62d1ca32014-09-03 17:24:56 -0700777 Elf_Word symbol_and_chain_index = GetHashBucket(bucket_index, &ok);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700778 if (!ok) {
779 return nullptr;
780 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800781 while (symbol_and_chain_index != 0 /* STN_UNDEF */) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700782 Elf_Sym* symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700783 if (symbol == nullptr) {
784 return nullptr; // Failure condition.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800785 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700786 const char* name = GetString(SHT_DYNSYM, symbol->st_name);
787 if (symbol_name == name) {
788 return symbol;
789 }
790 symbol_and_chain_index = GetHashChain(symbol_and_chain_index, &ok);
791 if (!ok) {
792 return nullptr;
793 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800794 }
Alex Light3470ab42014-06-18 10:35:45 -0700795 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800796}
797
David Srbecky533c2072015-04-22 12:20:22 +0100798template <typename ElfTypes>
799bool ElfFileImpl<ElfTypes>::IsSymbolSectionType(Elf_Word section_type) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700800 return ((section_type == SHT_SYMTAB) || (section_type == SHT_DYNSYM));
801}
802
David Srbecky533c2072015-04-22 12:20:22 +0100803template <typename ElfTypes>
804typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSymbolNum(Elf_Shdr& section_header) const {
Brian Carlstromc1409452014-02-26 14:06:23 -0800805 CHECK(IsSymbolSectionType(section_header.sh_type))
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700806 << file_path_ << " " << section_header.sh_type;
807 CHECK_NE(0U, section_header.sh_entsize) << file_path_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800808 return section_header.sh_size / section_header.sh_entsize;
809}
810
David Srbecky533c2072015-04-22 12:20:22 +0100811template <typename ElfTypes>
812typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbol(Elf_Word section_type, Elf_Word i) const {
Tong Shen62d1ca32014-09-03 17:24:56 -0700813 Elf_Sym* sym_start = GetSymbolSectionStart(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700814 if (sym_start == nullptr) {
815 return nullptr;
816 }
817 return sym_start + i;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800818}
819
David Srbecky533c2072015-04-22 12:20:22 +0100820template <typename ElfTypes>
821typename ElfFileImpl<ElfTypes>::SymbolTable**
822ElfFileImpl<ElfTypes>::GetSymbolTable(Elf_Word section_type) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700823 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800824 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000825 case SHT_SYMTAB: {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800826 return &symtab_symbol_table_;
827 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000828 case SHT_DYNSYM: {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800829 return &dynsym_symbol_table_;
830 }
831 default: {
832 LOG(FATAL) << section_type;
Alex Light3470ab42014-06-18 10:35:45 -0700833 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800834 }
835 }
836}
837
David Srbecky533c2072015-04-22 12:20:22 +0100838template <typename ElfTypes>
839typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindSymbolByName(
840 Elf_Word section_type, const std::string& symbol_name, bool build_map) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700841 CHECK(!program_header_only_) << file_path_;
842 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800843
844 SymbolTable** symbol_table = GetSymbolTable(section_type);
Alex Light3470ab42014-06-18 10:35:45 -0700845 if (*symbol_table != nullptr || build_map) {
846 if (*symbol_table == nullptr) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800847 DCHECK(build_map);
848 *symbol_table = new SymbolTable;
Tong Shen62d1ca32014-09-03 17:24:56 -0700849 Elf_Shdr* symbol_section = FindSectionByType(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700850 if (symbol_section == nullptr) {
851 return nullptr; // Failure condition.
852 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700853 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700854 if (string_section == nullptr) {
855 return nullptr; // Failure condition.
856 }
Brian Carlstrom265091e2013-01-30 14:08:26 -0800857 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700858 Elf_Sym* symbol = GetSymbol(section_type, i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700859 if (symbol == nullptr) {
860 return nullptr; // Failure condition.
861 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700862 unsigned char type = (sizeof(Elf_Addr) == sizeof(Elf64_Addr))
863 ? ELF64_ST_TYPE(symbol->st_info)
864 : ELF32_ST_TYPE(symbol->st_info);
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000865 if (type == STT_NOTYPE) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800866 continue;
867 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700868 const char* name = GetString(*string_section, symbol->st_name);
Alex Light3470ab42014-06-18 10:35:45 -0700869 if (name == nullptr) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800870 continue;
871 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700872 std::pair<typename SymbolTable::iterator, bool> result =
Andreas Gampedaab38c2014-09-12 18:38:24 -0700873 (*symbol_table)->insert(std::make_pair(name, symbol));
Brian Carlstrom265091e2013-01-30 14:08:26 -0800874 if (!result.second) {
875 // If a duplicate, make sure it has the same logical value. Seen on x86.
Andreas Gampedaab38c2014-09-12 18:38:24 -0700876 if ((symbol->st_value != result.first->second->st_value) ||
877 (symbol->st_size != result.first->second->st_size) ||
878 (symbol->st_info != result.first->second->st_info) ||
879 (symbol->st_other != result.first->second->st_other) ||
880 (symbol->st_shndx != result.first->second->st_shndx)) {
881 return nullptr; // Failure condition.
882 }
Brian Carlstrom265091e2013-01-30 14:08:26 -0800883 }
884 }
885 }
Alex Light3470ab42014-06-18 10:35:45 -0700886 CHECK(*symbol_table != nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -0700887 typename SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800888 if (it == (*symbol_table)->end()) {
Alex Light3470ab42014-06-18 10:35:45 -0700889 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800890 }
891 return it->second;
892 }
893
894 // Fall back to linear search
Tong Shen62d1ca32014-09-03 17:24:56 -0700895 Elf_Shdr* symbol_section = FindSectionByType(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700896 if (symbol_section == nullptr) {
897 return nullptr;
898 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700899 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700900 if (string_section == nullptr) {
901 return nullptr;
902 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800903 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700904 Elf_Sym* symbol = GetSymbol(section_type, i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700905 if (symbol == nullptr) {
906 return nullptr; // Failure condition.
907 }
908 const char* name = GetString(*string_section, symbol->st_name);
Alex Light3470ab42014-06-18 10:35:45 -0700909 if (name == nullptr) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800910 continue;
911 }
912 if (symbol_name == name) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700913 return symbol;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800914 }
915 }
Alex Light3470ab42014-06-18 10:35:45 -0700916 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800917}
918
David Srbecky533c2072015-04-22 12:20:22 +0100919template <typename ElfTypes>
920typename ElfTypes::Addr ElfFileImpl<ElfTypes>::FindSymbolAddress(
921 Elf_Word section_type, const std::string& symbol_name, bool build_map) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700922 Elf_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
Alex Light3470ab42014-06-18 10:35:45 -0700923 if (symbol == nullptr) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800924 return 0;
925 }
926 return symbol->st_value;
927}
928
David Srbecky533c2072015-04-22 12:20:22 +0100929template <typename ElfTypes>
930const char* ElfFileImpl<ElfTypes>::GetString(Elf_Shdr& string_section,
931 Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700932 CHECK(!program_header_only_) << file_path_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800933 // TODO: remove this static_cast from enum when using -std=gnu++0x
Tong Shen62d1ca32014-09-03 17:24:56 -0700934 if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700935 return nullptr; // Failure condition.
936 }
937 if (i >= string_section.sh_size) {
938 return nullptr;
939 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800940 if (i == 0) {
Alex Light3470ab42014-06-18 10:35:45 -0700941 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800942 }
Ian Rogers13735952014-10-08 12:43:28 -0700943 uint8_t* strings = Begin() + string_section.sh_offset;
944 uint8_t* string = strings + i;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700945 if (string >= End()) {
946 return nullptr;
947 }
Brian Carlstrom265091e2013-01-30 14:08:26 -0800948 return reinterpret_cast<const char*>(string);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800949}
950
David Srbecky533c2072015-04-22 12:20:22 +0100951template <typename ElfTypes>
952typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetDynamicNum() const {
Tong Shen62d1ca32014-09-03 17:24:56 -0700953 return GetDynamicProgramHeader().p_filesz / sizeof(Elf_Dyn);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800954}
955
David Srbecky533c2072015-04-22 12:20:22 +0100956template <typename ElfTypes>
957typename ElfTypes::Dyn& ElfFileImpl<ElfTypes>::GetDynamic(Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700958 CHECK_LT(i, GetDynamicNum()) << file_path_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800959 return *(GetDynamicSectionStart() + i);
960}
961
David Srbecky533c2072015-04-22 12:20:22 +0100962template <typename ElfTypes>
963typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::FindDynamicByType(Elf_Sword type) const {
Tong Shen62d1ca32014-09-03 17:24:56 -0700964 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
965 Elf_Dyn* dyn = &GetDynamic(i);
Alex Light53cb16b2014-06-12 11:26:29 -0700966 if (dyn->d_tag == type) {
967 return dyn;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800968 }
969 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700970 return nullptr;
Alex Light53cb16b2014-06-12 11:26:29 -0700971}
972
David Srbecky533c2072015-04-22 12:20:22 +0100973template <typename ElfTypes>
974typename ElfTypes::Word ElfFileImpl<ElfTypes>::FindDynamicValueByType(Elf_Sword type) const {
Tong Shen62d1ca32014-09-03 17:24:56 -0700975 Elf_Dyn* dyn = FindDynamicByType(type);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700976 if (dyn == nullptr) {
Alex Light53cb16b2014-06-12 11:26:29 -0700977 return 0;
978 } else {
979 return dyn->d_un.d_val;
980 }
Brian Carlstrom265091e2013-01-30 14:08:26 -0800981}
982
David Srbecky533c2072015-04-22 12:20:22 +0100983template <typename ElfTypes>
984typename ElfTypes::Rel* ElfFileImpl<ElfTypes>::GetRelSectionStart(Elf_Shdr& section_header) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700985 CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
Tong Shen62d1ca32014-09-03 17:24:56 -0700986 return reinterpret_cast<Elf_Rel*>(Begin() + section_header.sh_offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800987}
988
David Srbecky533c2072015-04-22 12:20:22 +0100989template <typename ElfTypes>
990typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelNum(Elf_Shdr& section_header) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700991 CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
992 CHECK_NE(0U, section_header.sh_entsize) << file_path_;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800993 return section_header.sh_size / section_header.sh_entsize;
994}
995
David Srbecky533c2072015-04-22 12:20:22 +0100996template <typename ElfTypes>
997typename ElfTypes::Rel& ElfFileImpl<ElfTypes>::GetRel(Elf_Shdr& section_header, Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700998 CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
999 CHECK_LT(i, GetRelNum(section_header)) << file_path_;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001000 return *(GetRelSectionStart(section_header) + i);
1001}
1002
David Srbecky533c2072015-04-22 12:20:22 +01001003template <typename ElfTypes>
1004typename ElfTypes::Rela* ElfFileImpl<ElfTypes>::GetRelaSectionStart(Elf_Shdr& section_header) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001005 CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
Tong Shen62d1ca32014-09-03 17:24:56 -07001006 return reinterpret_cast<Elf_Rela*>(Begin() + section_header.sh_offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001007}
1008
David Srbecky533c2072015-04-22 12:20:22 +01001009template <typename ElfTypes>
1010typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelaNum(Elf_Shdr& section_header) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001011 CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001012 return section_header.sh_size / section_header.sh_entsize;
1013}
1014
David Srbecky533c2072015-04-22 12:20:22 +01001015template <typename ElfTypes>
1016typename ElfTypes::Rela& ElfFileImpl<ElfTypes>::GetRela(Elf_Shdr& section_header, Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001017 CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1018 CHECK_LT(i, GetRelaNum(section_header)) << file_path_;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001019 return *(GetRelaSectionStart(section_header) + i);
1020}
1021
David Srbecky533c2072015-04-22 12:20:22 +01001022template <typename ElfTypes>
Vladimir Marko3fc99032015-05-13 19:06:30 +01001023bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg) const {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001024 uint8_t* vaddr_begin;
1025 return GetLoadedAddressRange(&vaddr_begin, size, error_msg);
1026}
1027
1028// Base on bionic phdr_table_get_load_size
1029template <typename ElfTypes>
1030bool ElfFileImpl<ElfTypes>::GetLoadedAddressRange(/*out*/uint8_t** vaddr_begin,
1031 /*out*/size_t* vaddr_size,
1032 /*out*/std::string* error_msg) const {
Vladimir Marko3fc99032015-05-13 19:06:30 +01001033 Elf_Addr min_vaddr = static_cast<Elf_Addr>(-1);
1034 Elf_Addr max_vaddr = 0u;
Tong Shen62d1ca32014-09-03 17:24:56 -07001035 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1036 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001037 if (program_header->p_type != PT_LOAD) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001038 continue;
1039 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001040 Elf_Addr begin_vaddr = program_header->p_vaddr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001041 if (begin_vaddr < min_vaddr) {
1042 min_vaddr = begin_vaddr;
1043 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001044 Elf_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz;
Vladimir Marko3fc99032015-05-13 19:06:30 +01001045 if (UNLIKELY(begin_vaddr > end_vaddr)) {
1046 std::ostringstream oss;
1047 oss << "Program header #" << i << " has overflow in p_vaddr+p_memsz: 0x" << std::hex
1048 << program_header->p_vaddr << "+0x" << program_header->p_memsz << "=0x" << end_vaddr
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001049 << " in ELF file \"" << file_path_ << "\"";
Vladimir Marko3fc99032015-05-13 19:06:30 +01001050 *error_msg = oss.str();
Vladimir Markoc09cd052018-08-23 16:36:36 +01001051 *vaddr_begin = nullptr;
1052 *vaddr_size = static_cast<size_t>(-1);
Vladimir Marko3fc99032015-05-13 19:06:30 +01001053 return false;
1054 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001055 if (end_vaddr > max_vaddr) {
1056 max_vaddr = end_vaddr;
1057 }
1058 }
1059 min_vaddr = RoundDown(min_vaddr, kPageSize);
1060 max_vaddr = RoundUp(max_vaddr, kPageSize);
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001061 CHECK_LT(min_vaddr, max_vaddr) << file_path_;
Vladimir Markoc09cd052018-08-23 16:36:36 +01001062 // Check that the range fits into the runtime address space.
1063 if (UNLIKELY(max_vaddr - 1u > std::numeric_limits<size_t>::max())) {
Vladimir Marko3fc99032015-05-13 19:06:30 +01001064 std::ostringstream oss;
Vladimir Markoc09cd052018-08-23 16:36:36 +01001065 oss << "Loaded range is 0x" << std::hex << min_vaddr << "-0x" << max_vaddr
1066 << " but maximum size_t is 0x" << std::numeric_limits<size_t>::max()
1067 << " for ELF file \"" << file_path_ << "\"";
Vladimir Marko3fc99032015-05-13 19:06:30 +01001068 *error_msg = oss.str();
Vladimir Markoc09cd052018-08-23 16:36:36 +01001069 *vaddr_begin = nullptr;
1070 *vaddr_size = static_cast<size_t>(-1);
Vladimir Marko3fc99032015-05-13 19:06:30 +01001071 return false;
1072 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01001073 *vaddr_begin = reinterpret_cast<uint8_t*>(min_vaddr);
1074 *vaddr_size = dchecked_integral_cast<size_t>(max_vaddr - min_vaddr);
Vladimir Marko3fc99032015-05-13 19:06:30 +01001075 return true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001076}
1077
Vladimir Marko41b605c2020-02-12 10:52:22 +00001078static InstructionSet GetInstructionSetFromELF(uint16_t e_machine,
1079 uint32_t e_flags ATTRIBUTE_UNUSED) {
David Sehrc3e18952018-05-11 16:59:31 -07001080 switch (e_machine) {
1081 case EM_ARM:
1082 return InstructionSet::kArm;
1083 case EM_AARCH64:
1084 return InstructionSet::kArm64;
1085 case EM_386:
1086 return InstructionSet::kX86;
1087 case EM_X86_64:
1088 return InstructionSet::kX86_64;
David Sehrc3e18952018-05-11 16:59:31 -07001089 }
1090 return InstructionSet::kNone;
1091}
1092
David Srbecky533c2072015-04-22 12:20:22 +01001093template <typename ElfTypes>
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001094bool ElfFileImpl<ElfTypes>::Load(File* file,
1095 bool executable,
1096 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001097 /*inout*/MemMap* reservation,
1098 /*out*/std::string* error_msg) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001099 CHECK(program_header_only_) << file->GetPath();
Andreas Gampe91268c12014-04-03 17:50:24 -07001100
1101 if (executable) {
Andreas Gampe6f611412015-01-21 22:25:24 -08001102 InstructionSet elf_ISA = GetInstructionSetFromELF(GetHeader().e_machine, GetHeader().e_flags);
Ulya Trafimovich5439f052020-07-29 10:03:46 +01001103 if (elf_ISA != kRuntimeISA) {
Andreas Gampe91268c12014-04-03 17:50:24 -07001104 std::ostringstream oss;
Ulya Trafimovich5439f052020-07-29 10:03:46 +01001105 oss << "Expected ISA " << kRuntimeISA << " but found " << elf_ISA;
Andreas Gampe91268c12014-04-03 17:50:24 -07001106 *error_msg = oss.str();
1107 return false;
1108 }
1109 }
1110
Jim_Guoa62a5882014-04-28 11:11:57 +08001111 bool reserved = false;
Tong Shen62d1ca32014-09-03 17:24:56 -07001112 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1113 Elf_Phdr* program_header = GetProgramHeader(i);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001114
1115 // Record .dynamic header information for later use
Andreas Gampedaab38c2014-09-12 18:38:24 -07001116 if (program_header->p_type == PT_DYNAMIC) {
1117 dynamic_program_header_ = program_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001118 continue;
1119 }
1120
1121 // Not something to load, move on.
Andreas Gampedaab38c2014-09-12 18:38:24 -07001122 if (program_header->p_type != PT_LOAD) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001123 continue;
1124 }
1125
1126 // Found something to load.
1127
Jim_Guoa62a5882014-04-28 11:11:57 +08001128 // Before load the actual segments, reserve a contiguous chunk
1129 // of required size and address for all segments, but with no
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001130 // permissions. We'll then carve that up with the proper
1131 // permissions as we load the actual segments. If p_vaddr is
1132 // non-zero, the segments require the specific address specified,
1133 // which either was specified in the file because we already set
1134 // base_address_ after the first zero segment).
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001135 int64_t temp_file_length = file->GetLength();
Ian Rogerscdfcf372014-01-23 20:38:36 -08001136 if (temp_file_length < 0) {
1137 errno = -temp_file_length;
1138 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001139 file->GetPath().c_str(), file->Fd(), strerror(errno));
Ian Rogerscdfcf372014-01-23 20:38:36 -08001140 return false;
1141 }
1142 size_t file_length = static_cast<size_t>(temp_file_length);
Jim_Guoa62a5882014-04-28 11:11:57 +08001143 if (!reserved) {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001144 uint8_t* vaddr_begin;
1145 size_t vaddr_size;
1146 if (!GetLoadedAddressRange(&vaddr_begin, &vaddr_size, error_msg)) {
Vladimir Marko3fc99032015-05-13 19:06:30 +01001147 DCHECK(!error_msg->empty());
1148 return false;
1149 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01001150 std::string reservation_name = "ElfFile reservation for " + file->GetPath();
1151 MemMap local_reservation = MemMap::MapAnonymous(
1152 reservation_name.c_str(),
1153 (reservation != nullptr) ? reservation->Begin() : nullptr,
1154 vaddr_size,
1155 PROT_NONE,
1156 low_4gb,
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001157 /* reuse= */ false,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001158 reservation,
1159 error_msg);
1160 if (!local_reservation.IsValid()) {
Brian Carlstromc1409452014-02-26 14:06:23 -08001161 *error_msg = StringPrintf("Failed to allocate %s: %s",
Vladimir Markoc09cd052018-08-23 16:36:36 +01001162 reservation_name.c_str(),
1163 error_msg->c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001164 return false;
1165 }
Jim_Guoa62a5882014-04-28 11:11:57 +08001166 reserved = true;
Igor Murashkin46774762014-10-22 11:37:02 -07001167
Vladimir Markoc09cd052018-08-23 16:36:36 +01001168 // Base address is the difference of actual mapped location and the vaddr_begin.
1169 base_address_ = reinterpret_cast<uint8_t*>(
1170 static_cast<uintptr_t>(local_reservation.Begin() - vaddr_begin));
Igor Murashkin46774762014-10-22 11:37:02 -07001171 // By adding the p_vaddr of a section/symbol to base_address_ we will always get the
1172 // dynamic memory address of where that object is actually mapped
1173 //
1174 // TODO: base_address_ needs to be calculated in ::Open, otherwise
1175 // FindDynamicSymbolAddress returns the wrong values until Load is called.
Vladimir Markoc09cd052018-08-23 16:36:36 +01001176 segments_.push_back(std::move(local_reservation));
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001177 }
1178 // empty segment, nothing to map
Andreas Gampedaab38c2014-09-12 18:38:24 -07001179 if (program_header->p_memsz == 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001180 continue;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001181 }
Ian Rogers13735952014-10-08 12:43:28 -07001182 uint8_t* p_vaddr = base_address_ + program_header->p_vaddr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001183 int prot = 0;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001184 if (executable && ((program_header->p_flags & PF_X) != 0)) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001185 prot |= PROT_EXEC;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001186 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001187 if ((program_header->p_flags & PF_W) != 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001188 prot |= PROT_WRITE;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001189 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001190 if ((program_header->p_flags & PF_R) != 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001191 prot |= PROT_READ;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001192 }
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -07001193 int flags = 0;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001194 if (writable_) {
1195 prot |= PROT_WRITE;
1196 flags |= MAP_SHARED;
1197 } else {
1198 flags |= MAP_PRIVATE;
1199 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001200 if (program_header->p_filesz > program_header->p_memsz) {
1201 *error_msg = StringPrintf("Invalid p_filesz > p_memsz (%" PRIu64 " > %" PRIu64 "): %s",
1202 static_cast<uint64_t>(program_header->p_filesz),
1203 static_cast<uint64_t>(program_header->p_memsz),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001204 file->GetPath().c_str());
Brian Carlstrom3a223612013-10-10 17:18:24 -07001205 return false;
1206 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001207 if (program_header->p_filesz < program_header->p_memsz &&
1208 !IsAligned<kPageSize>(program_header->p_filesz)) {
1209 *error_msg = StringPrintf("Unsupported unaligned p_filesz < p_memsz (%" PRIu64
1210 " < %" PRIu64 "): %s",
1211 static_cast<uint64_t>(program_header->p_filesz),
1212 static_cast<uint64_t>(program_header->p_memsz),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001213 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001214 return false;
1215 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001216 if (file_length < (program_header->p_offset + program_header->p_filesz)) {
1217 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment "
1218 "%d of %" PRIu64 " bytes: '%s'", file_length, i,
1219 static_cast<uint64_t>(program_header->p_offset + program_header->p_filesz),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001220 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001221 return false;
1222 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001223 if (program_header->p_filesz != 0u) {
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001224 MemMap segment =
Vladimir Marko5c42c292015-02-25 12:02:49 +00001225 MemMap::MapFileAtAddress(p_vaddr,
1226 program_header->p_filesz,
Mathieu Chartier42bddce2015-11-09 15:16:56 -08001227 prot,
1228 flags,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001229 file->Fd(),
Vladimir Marko5c42c292015-02-25 12:02:49 +00001230 program_header->p_offset,
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001231 /* low_4gb= */ false,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001232 file->GetPath().c_str(),
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001233 /* reuse= */ true, // implies MAP_FIXED
1234 /* reservation= */ nullptr,
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001235 error_msg);
1236 if (!segment.IsValid()) {
Vladimir Marko5c42c292015-02-25 12:02:49 +00001237 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001238 i, file->GetPath().c_str(), error_msg->c_str());
Vladimir Marko5c42c292015-02-25 12:02:49 +00001239 return false;
1240 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001241 if (segment.Begin() != p_vaddr) {
Vladimir Marko5c42c292015-02-25 12:02:49 +00001242 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, "
1243 "instead mapped to %p",
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001244 i, file->GetPath().c_str(), p_vaddr, segment.Begin());
Vladimir Marko5c42c292015-02-25 12:02:49 +00001245 return false;
1246 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001247 segments_.push_back(std::move(segment));
Vladimir Marko5c42c292015-02-25 12:02:49 +00001248 }
1249 if (program_header->p_filesz < program_header->p_memsz) {
1250 std::string name = StringPrintf("Zero-initialized segment %" PRIu64 " of ELF file %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001251 static_cast<uint64_t>(i), file->GetPath().c_str());
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001252 MemMap segment = MemMap::MapAnonymous(name.c_str(),
1253 p_vaddr + program_header->p_filesz,
1254 program_header->p_memsz - program_header->p_filesz,
1255 prot,
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001256 /* low_4gb= */ false,
1257 /* reuse= */ true,
1258 /* reservation= */ nullptr,
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001259 error_msg);
1260 if (!segment.IsValid()) {
Vladimir Marko5c42c292015-02-25 12:02:49 +00001261 *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s: %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001262 i, file->GetPath().c_str(), error_msg->c_str());
Vladimir Marko5c42c292015-02-25 12:02:49 +00001263 return false;
1264 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001265 if (segment.Begin() != p_vaddr) {
Vladimir Marko5c42c292015-02-25 12:02:49 +00001266 *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s "
1267 "at expected address %p, instead mapped to %p",
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001268 i, file->GetPath().c_str(), p_vaddr, segment.Begin());
Vladimir Marko5c42c292015-02-25 12:02:49 +00001269 return false;
1270 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001271 segments_.push_back(std::move(segment));
Vladimir Marko5c42c292015-02-25 12:02:49 +00001272 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001273 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001274
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001275 // Now that we are done loading, .dynamic should be in memory to find .dynstr, .dynsym, .hash
Ian Rogers13735952014-10-08 12:43:28 -07001276 uint8_t* dsptr = base_address_ + GetDynamicProgramHeader().p_vaddr;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001277 if ((dsptr < Begin() || dsptr >= End()) && !ValidPointer(dsptr)) {
1278 *error_msg = StringPrintf("dynamic section address invalid in ELF file %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001279 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -07001280 return false;
1281 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001282 dynamic_section_start_ = reinterpret_cast<Elf_Dyn*>(dsptr);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001283
Tong Shen62d1ca32014-09-03 17:24:56 -07001284 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1285 Elf_Dyn& elf_dyn = GetDynamic(i);
Ian Rogers13735952014-10-08 12:43:28 -07001286 uint8_t* d_ptr = base_address_ + elf_dyn.d_un.d_ptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001287 switch (elf_dyn.d_tag) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001288 case DT_HASH: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001289 if (!ValidPointer(d_ptr)) {
1290 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001291 d_ptr, file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001292 return false;
1293 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001294 hash_section_start_ = reinterpret_cast<Elf_Word*>(d_ptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001295 break;
1296 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001297 case DT_STRTAB: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001298 if (!ValidPointer(d_ptr)) {
1299 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001300 d_ptr, file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001301 return false;
1302 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001303 dynstr_section_start_ = reinterpret_cast<char*>(d_ptr);
1304 break;
1305 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001306 case DT_SYMTAB: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001307 if (!ValidPointer(d_ptr)) {
1308 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001309 d_ptr, file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001310 return false;
1311 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001312 dynsym_section_start_ = reinterpret_cast<Elf_Sym*>(d_ptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001313 break;
1314 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001315 case DT_NULL: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001316 if (GetDynamicNum() != i+1) {
1317 *error_msg = StringPrintf("DT_NULL found after %d .dynamic entries, "
1318 "expected %d as implied by size of PT_DYNAMIC segment in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001319 i + 1, GetDynamicNum(), file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001320 return false;
1321 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001322 break;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001323 }
1324 }
1325 }
1326
Andreas Gampedaab38c2014-09-12 18:38:24 -07001327 // Check for the existence of some sections.
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001328 if (!CheckSectionsExist(file, error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001329 return false;
1330 }
1331
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001332 return true;
1333}
1334
David Srbecky533c2072015-04-22 12:20:22 +01001335template <typename ElfTypes>
1336bool ElfFileImpl<ElfTypes>::ValidPointer(const uint8_t* start) const {
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001337 for (const MemMap& segment : segments_) {
1338 if (segment.Begin() <= start && start < segment.End()) {
Brian Carlstromc1409452014-02-26 14:06:23 -08001339 return true;
1340 }
1341 }
1342 return false;
1343}
1344
Alex Light3470ab42014-06-18 10:35:45 -07001345
David Srbecky533c2072015-04-22 12:20:22 +01001346template <typename ElfTypes>
1347typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByName(
1348 const std::string& name) const {
Alex Light3470ab42014-06-18 10:35:45 -07001349 CHECK(!program_header_only_);
Tong Shen62d1ca32014-09-03 17:24:56 -07001350 Elf_Shdr* shstrtab_sec = GetSectionNameStringSection();
Andreas Gampedaab38c2014-09-12 18:38:24 -07001351 if (shstrtab_sec == nullptr) {
1352 return nullptr;
1353 }
Alex Light3470ab42014-06-18 10:35:45 -07001354 for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001355 Elf_Shdr* shdr = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001356 if (shdr == nullptr) {
1357 return nullptr;
1358 }
1359 const char* sec_name = GetString(*shstrtab_sec, shdr->sh_name);
Alex Light3470ab42014-06-18 10:35:45 -07001360 if (sec_name == nullptr) {
1361 continue;
1362 }
1363 if (name == sec_name) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001364 return shdr;
Alex Light3470ab42014-06-18 10:35:45 -07001365 }
1366 }
1367 return nullptr;
Mark Mendellae9fd932014-02-10 16:14:35 -08001368}
1369
David Srbecky533c2072015-04-22 12:20:22 +01001370template <typename ElfTypes>
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001371bool ElfFileImpl<ElfTypes>::Strip(File* file, std::string* error_msg) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001372 // ELF files produced by MCLinker look roughly like this
1373 //
1374 // +------------+
1375 // | Elf_Ehdr | contains number of Elf_Shdr and offset to first
1376 // +------------+
1377 // | Elf_Phdr | program headers
1378 // | Elf_Phdr |
1379 // | ... |
1380 // | Elf_Phdr |
1381 // +------------+
1382 // | section | mixture of needed and unneeded sections
1383 // +------------+
1384 // | section |
1385 // +------------+
1386 // | ... |
1387 // +------------+
1388 // | section |
1389 // +------------+
1390 // | Elf_Shdr | section headers
1391 // | Elf_Shdr |
1392 // | ... | contains offset to section start
1393 // | Elf_Shdr |
1394 // +------------+
1395 //
1396 // To strip:
1397 // - leave the Elf_Ehdr and Elf_Phdr values in place.
1398 // - walk the sections making a new set of Elf_Shdr section headers for what we want to keep
1399 // - move the sections are keeping up to fill in gaps of sections we want to strip
1400 // - write new Elf_Shdr section headers to end of file, updating Elf_Ehdr
1401 // - truncate rest of file
1402 //
1403
1404 std::vector<Elf_Shdr> section_headers;
1405 std::vector<Elf_Word> section_headers_original_indexes;
1406 section_headers.reserve(GetSectionHeaderNum());
1407
1408
1409 Elf_Shdr* string_section = GetSectionNameStringSection();
1410 CHECK(string_section != nullptr);
1411 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1412 Elf_Shdr* sh = GetSectionHeader(i);
1413 CHECK(sh != nullptr);
1414 const char* name = GetString(*string_section, sh->sh_name);
1415 if (name == nullptr) {
1416 CHECK_EQ(0U, i);
1417 section_headers.push_back(*sh);
1418 section_headers_original_indexes.push_back(0);
1419 continue;
1420 }
Andreas Gampe9186ced2016-12-12 14:28:21 -08001421 if (android::base::StartsWith(name, ".debug")
Tong Shen62d1ca32014-09-03 17:24:56 -07001422 || (strcmp(name, ".strtab") == 0)
1423 || (strcmp(name, ".symtab") == 0)) {
1424 continue;
1425 }
1426 section_headers.push_back(*sh);
1427 section_headers_original_indexes.push_back(i);
1428 }
1429 CHECK_NE(0U, section_headers.size());
1430 CHECK_EQ(section_headers.size(), section_headers_original_indexes.size());
1431
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001432 // section 0 is the null section, sections start at offset of first section
Tong Shen62d1ca32014-09-03 17:24:56 -07001433 CHECK(GetSectionHeader(1) != nullptr);
1434 Elf_Off offset = GetSectionHeader(1)->sh_offset;
1435 for (size_t i = 1; i < section_headers.size(); i++) {
1436 Elf_Shdr& new_sh = section_headers[i];
1437 Elf_Shdr* old_sh = GetSectionHeader(section_headers_original_indexes[i]);
1438 CHECK(old_sh != nullptr);
1439 CHECK_EQ(new_sh.sh_name, old_sh->sh_name);
1440 if (old_sh->sh_addralign > 1) {
1441 offset = RoundUp(offset, old_sh->sh_addralign);
1442 }
1443 if (old_sh->sh_offset == offset) {
1444 // already in place
1445 offset += old_sh->sh_size;
1446 continue;
1447 }
1448 // shift section earlier
1449 memmove(Begin() + offset,
1450 Begin() + old_sh->sh_offset,
1451 old_sh->sh_size);
1452 new_sh.sh_offset = offset;
1453 offset += old_sh->sh_size;
1454 }
1455
1456 Elf_Off shoff = offset;
1457 size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf_Shdr);
1458 memcpy(Begin() + offset, &section_headers[0], section_headers_size_in_bytes);
1459 offset += section_headers_size_in_bytes;
1460
1461 GetHeader().e_shnum = section_headers.size();
1462 GetHeader().e_shoff = shoff;
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001463 int result = ftruncate(file->Fd(), offset);
Tong Shen62d1ca32014-09-03 17:24:56 -07001464 if (result != 0) {
1465 *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001466 file->GetPath().c_str(), strerror(errno));
Tong Shen62d1ca32014-09-03 17:24:56 -07001467 return false;
1468 }
1469 return true;
1470}
1471
Tong Shen62d1ca32014-09-03 17:24:56 -07001472// Explicit instantiations
David Srbecky533c2072015-04-22 12:20:22 +01001473template class ElfFileImpl<ElfTypes32>;
1474template class ElfFileImpl<ElfTypes64>;
Tong Shen62d1ca32014-09-03 17:24:56 -07001475
Ian Rogersd4c4d952014-10-16 20:31:53 -07001476ElfFile::ElfFile(ElfFileImpl32* elf32) : elf32_(elf32), elf64_(nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001477}
1478
Ian Rogersd4c4d952014-10-16 20:31:53 -07001479ElfFile::ElfFile(ElfFileImpl64* elf64) : elf32_(nullptr), elf64_(elf64) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001480}
1481
1482ElfFile::~ElfFile() {
Ian Rogersd4c4d952014-10-16 20:31:53 -07001483 // Should never have 32 and 64-bit impls.
1484 CHECK_NE(elf32_.get() == nullptr, elf64_.get() == nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07001485}
1486
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001487ElfFile* ElfFile::Open(File* file,
1488 bool writable,
1489 bool program_header_only,
1490 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001491 /*out*/std::string* error_msg) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001492 if (file->GetLength() < EI_NIDENT) {
1493 *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
1494 file->GetPath().c_str());
1495 return nullptr;
1496 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001497 MemMap map = MemMap::MapFile(EI_NIDENT,
1498 PROT_READ,
1499 MAP_PRIVATE,
1500 file->Fd(),
1501 0,
1502 low_4gb,
1503 file->GetPath().c_str(),
1504 error_msg);
1505 if (!map.IsValid() || map.Size() != EI_NIDENT) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001506 return nullptr;
1507 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001508 uint8_t* header = map.Begin();
Tong Shen62d1ca32014-09-03 17:24:56 -07001509 if (header[EI_CLASS] == ELFCLASS64) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001510 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file,
1511 writable,
1512 program_header_only,
1513 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001514 error_msg);
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001515 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001516 return nullptr;
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001517 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001518 return new ElfFile(elf_file_impl);
1519 } else if (header[EI_CLASS] == ELFCLASS32) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001520 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file,
1521 writable,
1522 program_header_only,
1523 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001524 error_msg);
Ian Rogersd4c4d952014-10-16 20:31:53 -07001525 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001526 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001527 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001528 return new ElfFile(elf_file_impl);
1529 } else {
1530 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
1531 ELFCLASS32, ELFCLASS64,
1532 file->GetPath().c_str(),
1533 header[EI_CLASS]);
1534 return nullptr;
1535 }
1536}
1537
Vladimir Markoc09cd052018-08-23 16:36:36 +01001538ElfFile* ElfFile::Open(File* file, int mmap_prot, int mmap_flags, /*out*/std::string* error_msg) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001539 // low_4gb support not required for this path.
1540 constexpr bool low_4gb = false;
Tong Shen62d1ca32014-09-03 17:24:56 -07001541 if (file->GetLength() < EI_NIDENT) {
1542 *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
1543 file->GetPath().c_str());
1544 return nullptr;
1545 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001546 MemMap map = MemMap::MapFile(EI_NIDENT,
1547 PROT_READ,
1548 MAP_PRIVATE,
1549 file->Fd(),
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001550 /* start= */ 0,
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001551 low_4gb,
1552 file->GetPath().c_str(),
1553 error_msg);
1554 if (!map.IsValid() || map.Size() != EI_NIDENT) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001555 return nullptr;
1556 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001557 uint8_t* header = map.Begin();
Tong Shen62d1ca32014-09-03 17:24:56 -07001558 if (header[EI_CLASS] == ELFCLASS64) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001559 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file,
1560 mmap_prot,
1561 mmap_flags,
1562 low_4gb,
1563 error_msg);
Ian Rogersd4c4d952014-10-16 20:31:53 -07001564 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001565 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001566 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001567 return new ElfFile(elf_file_impl);
1568 } else if (header[EI_CLASS] == ELFCLASS32) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001569 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file,
1570 mmap_prot,
1571 mmap_flags,
1572 low_4gb,
1573 error_msg);
Ian Rogersd4c4d952014-10-16 20:31:53 -07001574 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001575 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001576 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001577 return new ElfFile(elf_file_impl);
1578 } else {
1579 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
1580 ELFCLASS32, ELFCLASS64,
1581 file->GetPath().c_str(),
1582 header[EI_CLASS]);
1583 return nullptr;
1584 }
1585}
1586
1587#define DELEGATE_TO_IMPL(func, ...) \
Ian Rogersd4c4d952014-10-16 20:31:53 -07001588 if (elf64_.get() != nullptr) { \
1589 return elf64_->func(__VA_ARGS__); \
Tong Shen62d1ca32014-09-03 17:24:56 -07001590 } else { \
Ian Rogersd4c4d952014-10-16 20:31:53 -07001591 DCHECK(elf32_.get() != nullptr); \
1592 return elf32_->func(__VA_ARGS__); \
Tong Shen62d1ca32014-09-03 17:24:56 -07001593 }
1594
Vladimir Markoc09cd052018-08-23 16:36:36 +01001595bool ElfFile::Load(File* file,
1596 bool executable,
1597 bool low_4gb,
1598 /*inout*/MemMap* reservation,
1599 /*out*/std::string* error_msg) {
1600 DELEGATE_TO_IMPL(Load, file, executable, low_4gb, reservation, error_msg);
Tong Shen62d1ca32014-09-03 17:24:56 -07001601}
1602
Ian Rogers13735952014-10-08 12:43:28 -07001603const uint8_t* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
Tong Shen62d1ca32014-09-03 17:24:56 -07001604 DELEGATE_TO_IMPL(FindDynamicSymbolAddress, symbol_name);
1605}
1606
1607size_t ElfFile::Size() const {
1608 DELEGATE_TO_IMPL(Size);
1609}
1610
Ian Rogers13735952014-10-08 12:43:28 -07001611uint8_t* ElfFile::Begin() const {
Tong Shen62d1ca32014-09-03 17:24:56 -07001612 DELEGATE_TO_IMPL(Begin);
1613}
1614
Ian Rogers13735952014-10-08 12:43:28 -07001615uint8_t* ElfFile::End() const {
Tong Shen62d1ca32014-09-03 17:24:56 -07001616 DELEGATE_TO_IMPL(End);
1617}
1618
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001619const std::string& ElfFile::GetFilePath() const {
1620 DELEGATE_TO_IMPL(GetFilePath);
Tong Shen62d1ca32014-09-03 17:24:56 -07001621}
1622
Alex Light0eb76d22015-08-11 18:03:47 -07001623bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset,
1624 uint64_t* size) const {
Ian Rogersd4c4d952014-10-16 20:31:53 -07001625 if (elf32_.get() == nullptr) {
1626 CHECK(elf64_.get() != nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07001627
Ian Rogersd4c4d952014-10-16 20:31:53 -07001628 Elf64_Shdr *shdr = elf64_->FindSectionByName(section_name);
1629 if (shdr == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001630 return false;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001631 }
1632 if (offset != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001633 *offset = shdr->sh_offset;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001634 }
1635 if (size != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001636 *size = shdr->sh_size;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001637 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001638 return true;
1639 } else {
Ian Rogersd4c4d952014-10-16 20:31:53 -07001640 Elf32_Shdr *shdr = elf32_->FindSectionByName(section_name);
1641 if (shdr == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001642 return false;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001643 }
1644 if (offset != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001645 *offset = shdr->sh_offset;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001646 }
1647 if (size != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001648 *size = shdr->sh_size;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001649 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001650 return true;
1651 }
1652}
1653
Jeff Hao24ec0282016-03-17 21:32:45 -07001654bool ElfFile::HasSection(const std::string& name) const {
1655 if (elf64_.get() != nullptr) {
1656 return elf64_->FindSectionByName(name) != nullptr;
1657 } else {
1658 return elf32_->FindSectionByName(name) != nullptr;
1659 }
1660}
1661
Tong Shen62d1ca32014-09-03 17:24:56 -07001662uint64_t ElfFile::FindSymbolAddress(unsigned section_type,
1663 const std::string& symbol_name,
1664 bool build_map) {
1665 DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map);
1666}
1667
Vladimir Marko3fc99032015-05-13 19:06:30 +01001668bool ElfFile::GetLoadedSize(size_t* size, std::string* error_msg) const {
1669 DELEGATE_TO_IMPL(GetLoadedSize, size, error_msg);
Tong Shen62d1ca32014-09-03 17:24:56 -07001670}
1671
1672bool ElfFile::Strip(File* file, std::string* error_msg) {
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001673 std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, /*low_4gb=*/false, error_msg));
Tong Shen62d1ca32014-09-03 17:24:56 -07001674 if (elf_file.get() == nullptr) {
1675 return false;
1676 }
1677
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001678 if (elf_file->elf64_.get() != nullptr) {
1679 return elf_file->elf64_->Strip(file, error_msg);
1680 } else {
1681 return elf_file->elf32_->Strip(file, error_msg);
1682 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001683}
1684
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001685} // namespace art