blob: ee0f34002b6f34e40f926cc71be817136532f516 [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>
Nicolas Geoffraya7f198c2014-03-10 11:12:54 +000020#include <sys/types.h>
21#include <unistd.h>
22
Andreas Gampe9186ced2016-12-12 14:28:21 -080023#include "android-base/strings.h"
24
Ian Rogersd582fa42014-11-05 23:46:43 -080025#include "arch/instruction_set.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080026#include "base/logging.h"
Ian Rogers576ca0c2014-06-06 15:58:22 -070027#include "base/stringprintf.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080028#include "base/stl_util.h"
Ian Rogersd4c4d952014-10-16 20:31:53 -070029#include "base/unix_file/fd_file.h"
Ian Rogersd4c4d952014-10-16 20:31:53 -070030#include "elf_file_impl.h"
31#include "elf_utils.h"
Alex Light3470ab42014-06-18 10:35:45 -070032#include "leb128.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080033#include "utils.h"
34
35namespace art {
36
David Srbecky533c2072015-04-22 12:20:22 +010037template <typename ElfTypes>
38ElfFileImpl<ElfTypes>::ElfFileImpl(File* file, bool writable,
39 bool program_header_only,
40 uint8_t* requested_base)
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),
55 dynsym_symbol_table_(nullptr),
Igor Murashkin46774762014-10-22 11:37:02 -070056 requested_base_(requested_base) {
Alex Light3470ab42014-06-18 10:35:45 -070057 CHECK(file != nullptr);
Brian Carlstromc1409452014-02-26 14:06:23 -080058}
Brian Carlstrom700c8d32012-11-05 10:42:02 -080059
David Srbecky533c2072015-04-22 12:20:22 +010060template <typename ElfTypes>
Mathieu Chartierbcb6a722016-03-08 16:49:58 -080061ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file,
62 bool writable,
63 bool program_header_only,
64 bool low_4gb,
65 std::string* error_msg,
66 uint8_t* requested_base) {
David Srbecky533c2072015-04-22 12:20:22 +010067 std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(new ElfFileImpl<ElfTypes>
68 (file, writable, program_header_only, requested_base));
Brian Carlstrom700c8d32012-11-05 10:42:02 -080069 int prot;
70 int flags;
Alex Light3470ab42014-06-18 10:35:45 -070071 if (writable) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -080072 prot = PROT_READ | PROT_WRITE;
73 flags = MAP_SHARED;
74 } else {
75 prot = PROT_READ;
76 flags = MAP_PRIVATE;
77 }
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -070078 if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) {
Alex Light3470ab42014-06-18 10:35:45 -070079 return nullptr;
80 }
81 return elf_file.release();
82}
83
David Srbecky533c2072015-04-22 12:20:22 +010084template <typename ElfTypes>
Mathieu Chartierbcb6a722016-03-08 16:49:58 -080085ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file,
86 int prot,
87 int flags,
88 bool low_4gb,
89 std::string* error_msg) {
David Srbecky533c2072015-04-22 12:20:22 +010090 std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(new ElfFileImpl<ElfTypes>
91 (file, (prot & PROT_WRITE) == PROT_WRITE, /*program_header_only*/false,
92 /*requested_base*/nullptr));
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -070093 if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) {
Alex Light3470ab42014-06-18 10:35:45 -070094 return nullptr;
95 }
96 return elf_file.release();
97}
98
David Srbecky533c2072015-04-22 12:20:22 +010099template <typename ElfTypes>
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700100bool ElfFileImpl<ElfTypes>::Setup(File* file,
101 int prot,
102 int flags,
103 bool low_4gb,
104 std::string* error_msg) {
105 int64_t temp_file_length = file->GetLength();
Ian Rogerscdfcf372014-01-23 20:38:36 -0800106 if (temp_file_length < 0) {
107 errno = -temp_file_length;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700108 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700109 file->GetPath().c_str(), file->Fd(), strerror(errno));
Brian Carlstrom265091e2013-01-30 14:08:26 -0800110 return false;
111 }
Ian Rogerscdfcf372014-01-23 20:38:36 -0800112 size_t file_length = static_cast<size_t>(temp_file_length);
Tong Shen62d1ca32014-09-03 17:24:56 -0700113 if (file_length < sizeof(Elf_Ehdr)) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800114 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF header of "
Tong Shen62d1ca32014-09-03 17:24:56 -0700115 "%zd bytes: '%s'", file_length, sizeof(Elf_Ehdr),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700116 file->GetPath().c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800117 return false;
118 }
119
Brian Carlstromc1409452014-02-26 14:06:23 -0800120 if (program_header_only_) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800121 // first just map ELF header to get program header size information
Tong Shen62d1ca32014-09-03 17:24:56 -0700122 size_t elf_header_size = sizeof(Elf_Ehdr);
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700123 if (!SetMap(file,
124 MemMap::MapFile(elf_header_size,
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800125 prot,
126 flags,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700127 file->Fd(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800128 0,
Mathieu Chartierbcb6a722016-03-08 16:49:58 -0800129 low_4gb,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700130 file->GetPath().c_str(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800131 error_msg),
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800132 error_msg)) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800133 return false;
134 }
135 // then remap to cover program header
136 size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum);
Brian Carlstrom3a223612013-10-10 17:18:24 -0700137 if (file_length < program_header_size) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800138 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program "
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700139 "header of %zd bytes: '%s'", file_length,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700140 sizeof(Elf_Ehdr), file->GetPath().c_str());
Brian Carlstrom3a223612013-10-10 17:18:24 -0700141 return false;
142 }
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700143 if (!SetMap(file,
144 MemMap::MapFile(program_header_size,
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800145 prot,
146 flags,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700147 file->Fd(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800148 0,
Mathieu Chartierbcb6a722016-03-08 16:49:58 -0800149 low_4gb,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700150 file->GetPath().c_str(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800151 error_msg),
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800152 error_msg)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700153 *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800154 return false;
155 }
156 } else {
157 // otherwise map entire file
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700158 if (!SetMap(file,
159 MemMap::MapFile(file->GetLength(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800160 prot,
161 flags,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700162 file->Fd(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800163 0,
Mathieu Chartierbcb6a722016-03-08 16:49:58 -0800164 low_4gb,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700165 file->GetPath().c_str(),
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800166 error_msg),
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800167 error_msg)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700168 *error_msg = StringPrintf("Failed to map ELF file: %s", error_msg->c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800169 return false;
170 }
171 }
172
Andreas Gampedaab38c2014-09-12 18:38:24 -0700173 if (program_header_only_) {
174 program_headers_start_ = Begin() + GetHeader().e_phoff;
175 } else {
176 if (!CheckAndSet(GetHeader().e_phoff, "program headers", &program_headers_start_, error_msg)) {
177 return false;
178 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800179
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800180 // Setup section headers.
Andreas Gampedaab38c2014-09-12 18:38:24 -0700181 if (!CheckAndSet(GetHeader().e_shoff, "section headers", &section_headers_start_, error_msg)) {
182 return false;
183 }
184
185 // Find shstrtab.
Tong Shen62d1ca32014-09-03 17:24:56 -0700186 Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700187 if (shstrtab_section_header == nullptr) {
188 *error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700189 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700190 return false;
191 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800192
193 // Find .dynamic section info from program header
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000194 dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC);
Alex Light3470ab42014-06-18 10:35:45 -0700195 if (dynamic_program_header_ == nullptr) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700196 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700197 file->GetPath().c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800198 return false;
199 }
200
Andreas Gampedaab38c2014-09-12 18:38:24 -0700201 if (!CheckAndSet(GetDynamicProgramHeader().p_offset, "dynamic section",
Ian Rogers13735952014-10-08 12:43:28 -0700202 reinterpret_cast<uint8_t**>(&dynamic_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700203 return false;
204 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800205
206 // Find other sections from section headers
Tong Shen62d1ca32014-09-03 17:24:56 -0700207 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
208 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700209 if (section_header == nullptr) {
210 *error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700211 i, file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700212 return false;
213 }
214 switch (section_header->sh_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000215 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700216 if (!CheckAndSet(section_header->sh_offset, "symtab",
Ian Rogers13735952014-10-08 12:43:28 -0700217 reinterpret_cast<uint8_t**>(&symtab_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700218 return false;
219 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800220 break;
221 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000222 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700223 if (!CheckAndSet(section_header->sh_offset, "dynsym",
Ian Rogers13735952014-10-08 12:43:28 -0700224 reinterpret_cast<uint8_t**>(&dynsym_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700225 return false;
226 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800227 break;
228 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000229 case SHT_STRTAB: {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800230 // TODO: base these off of sh_link from .symtab and .dynsym above
Andreas Gampedaab38c2014-09-12 18:38:24 -0700231 if ((section_header->sh_flags & SHF_ALLOC) != 0) {
232 // Check that this is named ".dynstr" and ignore otherwise.
233 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
234 if (strncmp(".dynstr", header_name, 8) == 0) {
235 if (!CheckAndSet(section_header->sh_offset, "dynstr",
Ian Rogers13735952014-10-08 12:43:28 -0700236 reinterpret_cast<uint8_t**>(&dynstr_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700237 return false;
238 }
239 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800240 } else {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700241 // Check that this is named ".strtab" and ignore otherwise.
242 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
243 if (strncmp(".strtab", header_name, 8) == 0) {
244 if (!CheckAndSet(section_header->sh_offset, "strtab",
Ian Rogers13735952014-10-08 12:43:28 -0700245 reinterpret_cast<uint8_t**>(&strtab_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700246 return false;
247 }
248 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800249 }
250 break;
251 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000252 case SHT_DYNAMIC: {
Ian Rogers13735952014-10-08 12:43:28 -0700253 if (reinterpret_cast<uint8_t*>(dynamic_section_start_) !=
Andreas Gampedaab38c2014-09-12 18:38:24 -0700254 Begin() + section_header->sh_offset) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800255 LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in "
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700256 << file->GetPath() << ": " << std::hex
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800257 << reinterpret_cast<void*>(dynamic_section_start_)
Andreas Gampedaab38c2014-09-12 18:38:24 -0700258 << " != " << reinterpret_cast<void*>(Begin() + section_header->sh_offset);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800259 return false;
260 }
261 break;
262 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000263 case SHT_HASH: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700264 if (!CheckAndSet(section_header->sh_offset, "hash section",
Ian Rogers13735952014-10-08 12:43:28 -0700265 reinterpret_cast<uint8_t**>(&hash_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700266 return false;
267 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800268 break;
269 }
270 }
271 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700272
273 // Check for the existence of some sections.
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700274 if (!CheckSectionsExist(file, error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700275 return false;
276 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800277 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700278
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800279 return true;
280}
281
David Srbecky533c2072015-04-22 12:20:22 +0100282template <typename ElfTypes>
283ElfFileImpl<ElfTypes>::~ElfFileImpl() {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800284 STLDeleteElements(&segments_);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800285 delete symtab_symbol_table_;
286 delete dynsym_symbol_table_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800287}
288
David Srbecky533c2072015-04-22 12:20:22 +0100289template <typename ElfTypes>
290bool ElfFileImpl<ElfTypes>::CheckAndSet(Elf32_Off offset, const char* label,
291 uint8_t** target, std::string* error_msg) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700292 if (Begin() + offset >= End()) {
293 *error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700294 file_path_.c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700295 return false;
296 }
297 *target = Begin() + offset;
298 return true;
299}
300
David Srbecky533c2072015-04-22 12:20:22 +0100301template <typename ElfTypes>
302bool ElfFileImpl<ElfTypes>::CheckSectionsLinked(const uint8_t* source,
303 const uint8_t* target) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700304 // Only works in whole-program mode, as we need to iterate over the sections.
305 // Note that we normally can't search by type, as duplicates are allowed for most section types.
306 if (program_header_only_) {
307 return true;
308 }
309
Tong Shen62d1ca32014-09-03 17:24:56 -0700310 Elf_Shdr* source_section = nullptr;
311 Elf_Word target_index = 0;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700312 bool target_found = false;
Tong Shen62d1ca32014-09-03 17:24:56 -0700313 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
314 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700315
316 if (Begin() + section_header->sh_offset == source) {
317 // Found the source.
318 source_section = section_header;
319 if (target_index) {
320 break;
321 }
322 } else if (Begin() + section_header->sh_offset == target) {
323 target_index = i;
324 target_found = true;
325 if (source_section != nullptr) {
326 break;
327 }
328 }
329 }
330
331 return target_found && source_section != nullptr && source_section->sh_link == target_index;
332}
333
David Srbecky533c2072015-04-22 12:20:22 +0100334template <typename ElfTypes>
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700335 bool ElfFileImpl<ElfTypes>::CheckSectionsExist(File* file, std::string* error_msg) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700336 if (!program_header_only_) {
337 // If in full mode, need section headers.
338 if (section_headers_start_ == nullptr) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700339 *error_msg = StringPrintf("No section headers in ELF file: '%s'", file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700340 return false;
341 }
342 }
343
344 // This is redundant, but defensive.
345 if (dynamic_program_header_ == nullptr) {
346 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700347 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700348 return false;
349 }
350
351 // Need a dynamic section. This is redundant, but defensive.
352 if (dynamic_section_start_ == nullptr) {
353 *error_msg = StringPrintf("Failed to find dynamic section in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700354 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700355 return false;
356 }
357
358 // Symtab validation. These is not really a hard failure, as we are currently not using the
359 // symtab internally, but it's nice to be defensive.
360 if (symtab_section_start_ != nullptr) {
361 // When there's a symtab, there should be a strtab.
362 if (strtab_section_start_ == nullptr) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700363 *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700364 return false;
365 }
366
367 // The symtab should link to the strtab.
Ian Rogers13735952014-10-08 12:43:28 -0700368 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(symtab_section_start_),
369 reinterpret_cast<const uint8_t*>(strtab_section_start_))) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700370 *error_msg = StringPrintf("Symtab is not linked to the strtab in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700371 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700372 return false;
373 }
374 }
375
376 // We always need a dynstr & dynsym.
377 if (dynstr_section_start_ == nullptr) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700378 *error_msg = StringPrintf("No dynstr in ELF file: '%s'", file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700379 return false;
380 }
381 if (dynsym_section_start_ == nullptr) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700382 *error_msg = StringPrintf("No dynsym in ELF file: '%s'", file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700383 return false;
384 }
385
386 // Need a hash section for dynamic symbol lookup.
387 if (hash_section_start_ == nullptr) {
388 *error_msg = StringPrintf("Failed to find hash section in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700389 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700390 return false;
391 }
392
393 // And the hash section should be linking to the dynsym.
Ian Rogers13735952014-10-08 12:43:28 -0700394 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(hash_section_start_),
395 reinterpret_cast<const uint8_t*>(dynsym_section_start_))) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700396 *error_msg = StringPrintf("Hash section is not linked to the dynstr in ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700397 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -0700398 return false;
399 }
400
Andreas Gampea696c0a2014-12-10 20:51:45 -0800401 // We'd also like to confirm a shstrtab in program_header_only_ mode (else Open() does this for
402 // us). This is usually the last in an oat file, and a good indicator of whether writing was
403 // successful (or the process crashed and left garbage).
404 if (program_header_only_) {
405 // It might not be mapped, but we can compare against the file size.
406 int64_t offset = static_cast<int64_t>(GetHeader().e_shoff +
407 (GetHeader().e_shstrndx * GetHeader().e_shentsize));
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700408 if (offset >= file->GetLength()) {
Andreas Gampea696c0a2014-12-10 20:51:45 -0800409 *error_msg = StringPrintf("Shstrtab is not in the mapped ELF file: '%s'",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700410 file->GetPath().c_str());
Andreas Gampea696c0a2014-12-10 20:51:45 -0800411 return false;
412 }
413 }
414
Andreas Gampedaab38c2014-09-12 18:38:24 -0700415 return true;
416}
417
David Srbecky533c2072015-04-22 12:20:22 +0100418template <typename ElfTypes>
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700419bool ElfFileImpl<ElfTypes>::SetMap(File* file, MemMap* map, std::string* error_msg) {
Alex Light3470ab42014-06-18 10:35:45 -0700420 if (map == nullptr) {
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800421 // MemMap::Open should have already set an error.
422 DCHECK(!error_msg->empty());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800423 return false;
424 }
425 map_.reset(map);
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700426 CHECK(map_.get() != nullptr) << file->GetPath();
427 CHECK(map_->Begin() != nullptr) << file->GetPath();
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800428
Tong Shen62d1ca32014-09-03 17:24:56 -0700429 header_ = reinterpret_cast<Elf_Ehdr*>(map_->Begin());
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000430 if ((ELFMAG0 != header_->e_ident[EI_MAG0])
431 || (ELFMAG1 != header_->e_ident[EI_MAG1])
432 || (ELFMAG2 != header_->e_ident[EI_MAG2])
433 || (ELFMAG3 != header_->e_ident[EI_MAG3])) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800434 *error_msg = StringPrintf("Failed to find ELF magic value %d %d %d %d in %s, found %d %d %d %d",
435 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700436 file->GetPath().c_str(),
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000437 header_->e_ident[EI_MAG0],
438 header_->e_ident[EI_MAG1],
439 header_->e_ident[EI_MAG2],
440 header_->e_ident[EI_MAG3]);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800441 return false;
442 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700443 uint8_t elf_class = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) ? ELFCLASS64 : ELFCLASS32;
444 if (elf_class != header_->e_ident[EI_CLASS]) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800445 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d in %s, found %d",
Tong Shen62d1ca32014-09-03 17:24:56 -0700446 elf_class,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700447 file->GetPath().c_str(),
Brian Carlstromc1409452014-02-26 14:06:23 -0800448 header_->e_ident[EI_CLASS]);
449 return false;
450 }
451 if (ELFDATA2LSB != header_->e_ident[EI_DATA]) {
452 *error_msg = StringPrintf("Failed to find expected EI_DATA value %d in %s, found %d",
453 ELFDATA2LSB,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700454 file->GetPath().c_str(),
Brian Carlstromc1409452014-02-26 14:06:23 -0800455 header_->e_ident[EI_CLASS]);
456 return false;
457 }
458 if (EV_CURRENT != header_->e_ident[EI_VERSION]) {
459 *error_msg = StringPrintf("Failed to find expected EI_VERSION value %d in %s, found %d",
460 EV_CURRENT,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700461 file->GetPath().c_str(),
Brian Carlstromc1409452014-02-26 14:06:23 -0800462 header_->e_ident[EI_CLASS]);
463 return false;
464 }
465 if (ET_DYN != header_->e_type) {
466 *error_msg = StringPrintf("Failed to find expected e_type value %d in %s, found %d",
467 ET_DYN,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700468 file->GetPath().c_str(),
Brian Carlstromc1409452014-02-26 14:06:23 -0800469 header_->e_type);
470 return false;
471 }
472 if (EV_CURRENT != header_->e_version) {
473 *error_msg = StringPrintf("Failed to find expected e_version value %d in %s, found %d",
474 EV_CURRENT,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700475 file->GetPath().c_str(),
Brian Carlstromc1409452014-02-26 14:06:23 -0800476 header_->e_version);
477 return false;
478 }
479 if (0 != header_->e_entry) {
480 *error_msg = StringPrintf("Failed to find expected e_entry value %d in %s, found %d",
481 0,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700482 file->GetPath().c_str(),
Tong Shen62d1ca32014-09-03 17:24:56 -0700483 static_cast<int32_t>(header_->e_entry));
Brian Carlstromc1409452014-02-26 14:06:23 -0800484 return false;
485 }
486 if (0 == header_->e_phoff) {
487 *error_msg = StringPrintf("Failed to find non-zero e_phoff value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700488 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800489 return false;
490 }
491 if (0 == header_->e_shoff) {
492 *error_msg = StringPrintf("Failed to find non-zero e_shoff value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700493 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800494 return false;
495 }
496 if (0 == header_->e_ehsize) {
497 *error_msg = StringPrintf("Failed to find non-zero e_ehsize value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700498 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800499 return false;
500 }
501 if (0 == header_->e_phentsize) {
502 *error_msg = StringPrintf("Failed to find non-zero e_phentsize value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700503 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800504 return false;
505 }
506 if (0 == header_->e_phnum) {
507 *error_msg = StringPrintf("Failed to find non-zero e_phnum value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700508 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800509 return false;
510 }
511 if (0 == header_->e_shentsize) {
512 *error_msg = StringPrintf("Failed to find non-zero e_shentsize value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700513 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800514 return false;
515 }
516 if (0 == header_->e_shnum) {
517 *error_msg = StringPrintf("Failed to find non-zero e_shnum value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700518 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800519 return false;
520 }
521 if (0 == header_->e_shstrndx) {
522 *error_msg = StringPrintf("Failed to find non-zero e_shstrndx value in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700523 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800524 return false;
525 }
526 if (header_->e_shstrndx >= header_->e_shnum) {
527 *error_msg = StringPrintf("Failed to find e_shnum value %d less than %d in %s",
528 header_->e_shstrndx,
529 header_->e_shnum,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700530 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800531 return false;
532 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800533
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800534 if (!program_header_only_) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800535 if (header_->e_phoff >= Size()) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700536 *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s",
537 static_cast<uint64_t>(header_->e_phoff),
Brian Carlstromc1409452014-02-26 14:06:23 -0800538 Size(),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700539 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800540 return false;
541 }
542 if (header_->e_shoff >= Size()) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700543 *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s",
544 static_cast<uint64_t>(header_->e_shoff),
Brian Carlstromc1409452014-02-26 14:06:23 -0800545 Size(),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700546 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -0800547 return false;
548 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800549 }
550 return true;
551}
552
David Srbecky533c2072015-04-22 12:20:22 +0100553template <typename ElfTypes>
554typename ElfTypes::Ehdr& ElfFileImpl<ElfTypes>::GetHeader() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700555 CHECK(header_ != nullptr); // Header has been checked in SetMap. This is a sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800556 return *header_;
557}
558
David Srbecky533c2072015-04-22 12:20:22 +0100559template <typename ElfTypes>
560uint8_t* ElfFileImpl<ElfTypes>::GetProgramHeadersStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700561 CHECK(program_headers_start_ != nullptr); // Header has been set in Setup. This is a sanity
562 // check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800563 return program_headers_start_;
564}
565
David Srbecky533c2072015-04-22 12:20:22 +0100566template <typename ElfTypes>
567uint8_t* ElfFileImpl<ElfTypes>::GetSectionHeadersStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700568 CHECK(!program_header_only_); // Only used in "full" mode.
569 CHECK(section_headers_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800570 return section_headers_start_;
571}
572
David Srbecky533c2072015-04-22 12:20:22 +0100573template <typename ElfTypes>
574typename ElfTypes::Phdr& ElfFileImpl<ElfTypes>::GetDynamicProgramHeader() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700575 CHECK(dynamic_program_header_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800576 return *dynamic_program_header_;
577}
578
David Srbecky533c2072015-04-22 12:20:22 +0100579template <typename ElfTypes>
580typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::GetDynamicSectionStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700581 CHECK(dynamic_section_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800582 return dynamic_section_start_;
583}
584
David Srbecky533c2072015-04-22 12:20:22 +0100585template <typename ElfTypes>
586typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbolSectionStart(
587 Elf_Word section_type) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700588 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800589 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000590 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700591 return symtab_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800592 break;
593 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000594 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700595 return dynsym_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800596 break;
597 }
598 default: {
599 LOG(FATAL) << section_type;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700600 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800601 }
602 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800603}
604
David Srbecky533c2072015-04-22 12:20:22 +0100605template <typename ElfTypes>
606const char* ElfFileImpl<ElfTypes>::GetStringSectionStart(
607 Elf_Word section_type) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700608 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800609 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000610 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700611 return strtab_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800612 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000613 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700614 return dynstr_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800615 }
616 default: {
617 LOG(FATAL) << section_type;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700618 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800619 }
620 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800621}
622
David Srbecky533c2072015-04-22 12:20:22 +0100623template <typename ElfTypes>
624const char* ElfFileImpl<ElfTypes>::GetString(Elf_Word section_type,
625 Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700626 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800627 if (i == 0) {
Alex Light3470ab42014-06-18 10:35:45 -0700628 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800629 }
630 const char* string_section_start = GetStringSectionStart(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700631 if (string_section_start == nullptr) {
632 return nullptr;
633 }
634 return string_section_start + i;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800635}
636
Andreas Gampedaab38c2014-09-12 18:38:24 -0700637// WARNING: The following methods do not check for an error condition (non-existent hash section).
638// It is the caller's job to do this.
639
David Srbecky533c2072015-04-22 12:20:22 +0100640template <typename ElfTypes>
641typename ElfTypes::Word* ElfFileImpl<ElfTypes>::GetHashSectionStart() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800642 return hash_section_start_;
643}
644
David Srbecky533c2072015-04-22 12:20:22 +0100645template <typename ElfTypes>
646typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashBucketNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800647 return GetHashSectionStart()[0];
648}
649
David Srbecky533c2072015-04-22 12:20:22 +0100650template <typename ElfTypes>
651typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashChainNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800652 return GetHashSectionStart()[1];
653}
654
David Srbecky533c2072015-04-22 12:20:22 +0100655template <typename ElfTypes>
656typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashBucket(size_t i, bool* ok) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700657 if (i >= GetHashBucketNum()) {
658 *ok = false;
659 return 0;
660 }
661 *ok = true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800662 // 0 is nbucket, 1 is nchain
663 return GetHashSectionStart()[2 + i];
664}
665
David Srbecky533c2072015-04-22 12:20:22 +0100666template <typename ElfTypes>
667typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashChain(size_t i, bool* ok) const {
Yevgeny Roubanacb01382014-11-24 13:40:56 +0600668 if (i >= GetHashChainNum()) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700669 *ok = false;
670 return 0;
671 }
672 *ok = true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800673 // 0 is nbucket, 1 is nchain, & chains are after buckets
674 return GetHashSectionStart()[2 + GetHashBucketNum() + i];
675}
676
David Srbecky533c2072015-04-22 12:20:22 +0100677template <typename ElfTypes>
678typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetProgramHeaderNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800679 return GetHeader().e_phnum;
680}
681
David Srbecky533c2072015-04-22 12:20:22 +0100682template <typename ElfTypes>
683typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::GetProgramHeader(Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700684 CHECK_LT(i, GetProgramHeaderNum()) << file_path_; // Sanity check for caller.
Ian Rogers13735952014-10-08 12:43:28 -0700685 uint8_t* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700686 if (program_header >= End()) {
687 return nullptr; // Failure condition.
688 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700689 return reinterpret_cast<Elf_Phdr*>(program_header);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800690}
691
David Srbecky533c2072015-04-22 12:20:22 +0100692template <typename ElfTypes>
693typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::FindProgamHeaderByType(Elf_Word type) const {
Tong Shen62d1ca32014-09-03 17:24:56 -0700694 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
695 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700696 if (program_header->p_type == type) {
697 return program_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800698 }
699 }
Alex Light3470ab42014-06-18 10:35:45 -0700700 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800701}
702
David Srbecky533c2072015-04-22 12:20:22 +0100703template <typename ElfTypes>
704typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSectionHeaderNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800705 return GetHeader().e_shnum;
706}
707
David Srbecky533c2072015-04-22 12:20:22 +0100708template <typename ElfTypes>
709typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionHeader(Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800710 // Can only access arbitrary sections when we have the whole file, not just program header.
711 // Even if we Load(), it doesn't bring in all the sections.
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700712 CHECK(!program_header_only_) << file_path_;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700713 if (i >= GetSectionHeaderNum()) {
714 return nullptr; // Failure condition.
715 }
Ian Rogers13735952014-10-08 12:43:28 -0700716 uint8_t* section_header = GetSectionHeadersStart() + (i * GetHeader().e_shentsize);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700717 if (section_header >= End()) {
718 return nullptr; // Failure condition.
719 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700720 return reinterpret_cast<Elf_Shdr*>(section_header);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800721}
722
David Srbecky533c2072015-04-22 12:20:22 +0100723template <typename ElfTypes>
724typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByType(Elf_Word type) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800725 // Can only access arbitrary sections when we have the whole file, not just program header.
726 // We could change this to switch on known types if they were detected during loading.
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700727 CHECK(!program_header_only_) << file_path_;
Tong Shen62d1ca32014-09-03 17:24:56 -0700728 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
729 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700730 if (section_header->sh_type == type) {
731 return section_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800732 }
733 }
Alex Light3470ab42014-06-18 10:35:45 -0700734 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800735}
736
737// from bionic
Brian Carlstrom265091e2013-01-30 14:08:26 -0800738static unsigned elfhash(const char *_name) {
739 const unsigned char *name = (const unsigned char *) _name;
740 unsigned h = 0, g;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800741
Brian Carlstromdf629502013-07-17 22:39:56 -0700742 while (*name) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800743 h = (h << 4) + *name++;
744 g = h & 0xf0000000;
745 h ^= g;
746 h ^= g >> 24;
747 }
748 return h;
749}
750
David Srbecky533c2072015-04-22 12:20:22 +0100751template <typename ElfTypes>
752typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionNameStringSection() const {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800753 return GetSectionHeader(GetHeader().e_shstrndx);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800754}
755
David Srbecky533c2072015-04-22 12:20:22 +0100756template <typename ElfTypes>
757const uint8_t* ElfFileImpl<ElfTypes>::FindDynamicSymbolAddress(
758 const std::string& symbol_name) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700759 // Check that we have a hash section.
760 if (GetHashSectionStart() == nullptr) {
761 return nullptr; // Failure condition.
762 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700763 const Elf_Sym* sym = FindDynamicSymbol(symbol_name);
Alex Light3470ab42014-06-18 10:35:45 -0700764 if (sym != nullptr) {
Igor Murashkin46774762014-10-22 11:37:02 -0700765 // TODO: we need to change this to calculate base_address_ in ::Open,
766 // otherwise it will be wrongly 0 if ::Load has not yet been called.
Alex Light3470ab42014-06-18 10:35:45 -0700767 return base_address_ + sym->st_value;
768 } else {
769 return nullptr;
770 }
771}
772
Andreas Gampedaab38c2014-09-12 18:38:24 -0700773// WARNING: Only called from FindDynamicSymbolAddress. Elides check for hash section.
David Srbecky533c2072015-04-22 12:20:22 +0100774template <typename ElfTypes>
775const typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindDynamicSymbol(
776 const std::string& symbol_name) const {
Andreas Gampec48b2062014-09-08 23:39:45 -0700777 if (GetHashBucketNum() == 0) {
778 // No dynamic symbols at all.
779 return nullptr;
780 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700781 Elf_Word hash = elfhash(symbol_name.c_str());
782 Elf_Word bucket_index = hash % GetHashBucketNum();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700783 bool ok;
Tong Shen62d1ca32014-09-03 17:24:56 -0700784 Elf_Word symbol_and_chain_index = GetHashBucket(bucket_index, &ok);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700785 if (!ok) {
786 return nullptr;
787 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800788 while (symbol_and_chain_index != 0 /* STN_UNDEF */) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700789 Elf_Sym* symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700790 if (symbol == nullptr) {
791 return nullptr; // Failure condition.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800792 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700793 const char* name = GetString(SHT_DYNSYM, symbol->st_name);
794 if (symbol_name == name) {
795 return symbol;
796 }
797 symbol_and_chain_index = GetHashChain(symbol_and_chain_index, &ok);
798 if (!ok) {
799 return nullptr;
800 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800801 }
Alex Light3470ab42014-06-18 10:35:45 -0700802 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800803}
804
David Srbecky533c2072015-04-22 12:20:22 +0100805template <typename ElfTypes>
806bool ElfFileImpl<ElfTypes>::IsSymbolSectionType(Elf_Word section_type) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700807 return ((section_type == SHT_SYMTAB) || (section_type == SHT_DYNSYM));
808}
809
David Srbecky533c2072015-04-22 12:20:22 +0100810template <typename ElfTypes>
811typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSymbolNum(Elf_Shdr& section_header) const {
Brian Carlstromc1409452014-02-26 14:06:23 -0800812 CHECK(IsSymbolSectionType(section_header.sh_type))
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700813 << file_path_ << " " << section_header.sh_type;
814 CHECK_NE(0U, section_header.sh_entsize) << file_path_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800815 return section_header.sh_size / section_header.sh_entsize;
816}
817
David Srbecky533c2072015-04-22 12:20:22 +0100818template <typename ElfTypes>
819typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbol(Elf_Word section_type, Elf_Word i) const {
Tong Shen62d1ca32014-09-03 17:24:56 -0700820 Elf_Sym* sym_start = GetSymbolSectionStart(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700821 if (sym_start == nullptr) {
822 return nullptr;
823 }
824 return sym_start + i;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800825}
826
David Srbecky533c2072015-04-22 12:20:22 +0100827template <typename ElfTypes>
828typename ElfFileImpl<ElfTypes>::SymbolTable**
829ElfFileImpl<ElfTypes>::GetSymbolTable(Elf_Word section_type) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700830 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800831 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000832 case SHT_SYMTAB: {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800833 return &symtab_symbol_table_;
834 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000835 case SHT_DYNSYM: {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800836 return &dynsym_symbol_table_;
837 }
838 default: {
839 LOG(FATAL) << section_type;
Alex Light3470ab42014-06-18 10:35:45 -0700840 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800841 }
842 }
843}
844
David Srbecky533c2072015-04-22 12:20:22 +0100845template <typename ElfTypes>
846typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindSymbolByName(
847 Elf_Word section_type, const std::string& symbol_name, bool build_map) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700848 CHECK(!program_header_only_) << file_path_;
849 CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800850
851 SymbolTable** symbol_table = GetSymbolTable(section_type);
Alex Light3470ab42014-06-18 10:35:45 -0700852 if (*symbol_table != nullptr || build_map) {
853 if (*symbol_table == nullptr) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800854 DCHECK(build_map);
855 *symbol_table = new SymbolTable;
Tong Shen62d1ca32014-09-03 17:24:56 -0700856 Elf_Shdr* symbol_section = FindSectionByType(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700857 if (symbol_section == nullptr) {
858 return nullptr; // Failure condition.
859 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700860 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700861 if (string_section == nullptr) {
862 return nullptr; // Failure condition.
863 }
Brian Carlstrom265091e2013-01-30 14:08:26 -0800864 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700865 Elf_Sym* symbol = GetSymbol(section_type, i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700866 if (symbol == nullptr) {
867 return nullptr; // Failure condition.
868 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700869 unsigned char type = (sizeof(Elf_Addr) == sizeof(Elf64_Addr))
870 ? ELF64_ST_TYPE(symbol->st_info)
871 : ELF32_ST_TYPE(symbol->st_info);
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000872 if (type == STT_NOTYPE) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800873 continue;
874 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700875 const char* name = GetString(*string_section, symbol->st_name);
Alex Light3470ab42014-06-18 10:35:45 -0700876 if (name == nullptr) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800877 continue;
878 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700879 std::pair<typename SymbolTable::iterator, bool> result =
Andreas Gampedaab38c2014-09-12 18:38:24 -0700880 (*symbol_table)->insert(std::make_pair(name, symbol));
Brian Carlstrom265091e2013-01-30 14:08:26 -0800881 if (!result.second) {
882 // If a duplicate, make sure it has the same logical value. Seen on x86.
Andreas Gampedaab38c2014-09-12 18:38:24 -0700883 if ((symbol->st_value != result.first->second->st_value) ||
884 (symbol->st_size != result.first->second->st_size) ||
885 (symbol->st_info != result.first->second->st_info) ||
886 (symbol->st_other != result.first->second->st_other) ||
887 (symbol->st_shndx != result.first->second->st_shndx)) {
888 return nullptr; // Failure condition.
889 }
Brian Carlstrom265091e2013-01-30 14:08:26 -0800890 }
891 }
892 }
Alex Light3470ab42014-06-18 10:35:45 -0700893 CHECK(*symbol_table != nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -0700894 typename SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800895 if (it == (*symbol_table)->end()) {
Alex Light3470ab42014-06-18 10:35:45 -0700896 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800897 }
898 return it->second;
899 }
900
901 // Fall back to linear search
Tong Shen62d1ca32014-09-03 17:24:56 -0700902 Elf_Shdr* symbol_section = FindSectionByType(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700903 if (symbol_section == nullptr) {
904 return nullptr;
905 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700906 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700907 if (string_section == nullptr) {
908 return nullptr;
909 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800910 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700911 Elf_Sym* symbol = GetSymbol(section_type, i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700912 if (symbol == nullptr) {
913 return nullptr; // Failure condition.
914 }
915 const char* name = GetString(*string_section, symbol->st_name);
Alex Light3470ab42014-06-18 10:35:45 -0700916 if (name == nullptr) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800917 continue;
918 }
919 if (symbol_name == name) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700920 return symbol;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800921 }
922 }
Alex Light3470ab42014-06-18 10:35:45 -0700923 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800924}
925
David Srbecky533c2072015-04-22 12:20:22 +0100926template <typename ElfTypes>
927typename ElfTypes::Addr ElfFileImpl<ElfTypes>::FindSymbolAddress(
928 Elf_Word section_type, const std::string& symbol_name, bool build_map) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700929 Elf_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
Alex Light3470ab42014-06-18 10:35:45 -0700930 if (symbol == nullptr) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800931 return 0;
932 }
933 return symbol->st_value;
934}
935
David Srbecky533c2072015-04-22 12:20:22 +0100936template <typename ElfTypes>
937const char* ElfFileImpl<ElfTypes>::GetString(Elf_Shdr& string_section,
938 Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700939 CHECK(!program_header_only_) << file_path_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800940 // TODO: remove this static_cast from enum when using -std=gnu++0x
Tong Shen62d1ca32014-09-03 17:24:56 -0700941 if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700942 return nullptr; // Failure condition.
943 }
944 if (i >= string_section.sh_size) {
945 return nullptr;
946 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800947 if (i == 0) {
Alex Light3470ab42014-06-18 10:35:45 -0700948 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800949 }
Ian Rogers13735952014-10-08 12:43:28 -0700950 uint8_t* strings = Begin() + string_section.sh_offset;
951 uint8_t* string = strings + i;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700952 if (string >= End()) {
953 return nullptr;
954 }
Brian Carlstrom265091e2013-01-30 14:08:26 -0800955 return reinterpret_cast<const char*>(string);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800956}
957
David Srbecky533c2072015-04-22 12:20:22 +0100958template <typename ElfTypes>
959typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetDynamicNum() const {
Tong Shen62d1ca32014-09-03 17:24:56 -0700960 return GetDynamicProgramHeader().p_filesz / sizeof(Elf_Dyn);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800961}
962
David Srbecky533c2072015-04-22 12:20:22 +0100963template <typename ElfTypes>
964typename ElfTypes::Dyn& ElfFileImpl<ElfTypes>::GetDynamic(Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700965 CHECK_LT(i, GetDynamicNum()) << file_path_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800966 return *(GetDynamicSectionStart() + i);
967}
968
David Srbecky533c2072015-04-22 12:20:22 +0100969template <typename ElfTypes>
970typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::FindDynamicByType(Elf_Sword type) const {
Tong Shen62d1ca32014-09-03 17:24:56 -0700971 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
972 Elf_Dyn* dyn = &GetDynamic(i);
Alex Light53cb16b2014-06-12 11:26:29 -0700973 if (dyn->d_tag == type) {
974 return dyn;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800975 }
976 }
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700977 return nullptr;
Alex Light53cb16b2014-06-12 11:26:29 -0700978}
979
David Srbecky533c2072015-04-22 12:20:22 +0100980template <typename ElfTypes>
981typename ElfTypes::Word ElfFileImpl<ElfTypes>::FindDynamicValueByType(Elf_Sword type) const {
Tong Shen62d1ca32014-09-03 17:24:56 -0700982 Elf_Dyn* dyn = FindDynamicByType(type);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700983 if (dyn == nullptr) {
Alex Light53cb16b2014-06-12 11:26:29 -0700984 return 0;
985 } else {
986 return dyn->d_un.d_val;
987 }
Brian Carlstrom265091e2013-01-30 14:08:26 -0800988}
989
David Srbecky533c2072015-04-22 12:20:22 +0100990template <typename ElfTypes>
991typename ElfTypes::Rel* ElfFileImpl<ElfTypes>::GetRelSectionStart(Elf_Shdr& section_header) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700992 CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
Tong Shen62d1ca32014-09-03 17:24:56 -0700993 return reinterpret_cast<Elf_Rel*>(Begin() + section_header.sh_offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800994}
995
David Srbecky533c2072015-04-22 12:20:22 +0100996template <typename ElfTypes>
997typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelNum(Elf_Shdr& section_header) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -0700998 CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
999 CHECK_NE(0U, section_header.sh_entsize) << file_path_;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001000 return section_header.sh_size / section_header.sh_entsize;
1001}
1002
David Srbecky533c2072015-04-22 12:20:22 +01001003template <typename ElfTypes>
1004typename ElfTypes::Rel& ElfFileImpl<ElfTypes>::GetRel(Elf_Shdr& section_header, Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001005 CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1006 CHECK_LT(i, GetRelNum(section_header)) << file_path_;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001007 return *(GetRelSectionStart(section_header) + i);
1008}
1009
David Srbecky533c2072015-04-22 12:20:22 +01001010template <typename ElfTypes>
1011typename ElfTypes::Rela* ElfFileImpl<ElfTypes>::GetRelaSectionStart(Elf_Shdr& section_header) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001012 CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
Tong Shen62d1ca32014-09-03 17:24:56 -07001013 return reinterpret_cast<Elf_Rela*>(Begin() + section_header.sh_offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001014}
1015
David Srbecky533c2072015-04-22 12:20:22 +01001016template <typename ElfTypes>
1017typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelaNum(Elf_Shdr& section_header) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001018 CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001019 return section_header.sh_size / section_header.sh_entsize;
1020}
1021
David Srbecky533c2072015-04-22 12:20:22 +01001022template <typename ElfTypes>
1023typename ElfTypes::Rela& ElfFileImpl<ElfTypes>::GetRela(Elf_Shdr& section_header, Elf_Word i) const {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001024 CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1025 CHECK_LT(i, GetRelaNum(section_header)) << file_path_;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001026 return *(GetRelaSectionStart(section_header) + i);
1027}
1028
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001029// Base on bionic phdr_table_get_load_size
David Srbecky533c2072015-04-22 12:20:22 +01001030template <typename ElfTypes>
Vladimir Marko3fc99032015-05-13 19:06:30 +01001031bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg) const {
1032 Elf_Addr min_vaddr = static_cast<Elf_Addr>(-1);
1033 Elf_Addr max_vaddr = 0u;
Tong Shen62d1ca32014-09-03 17:24:56 -07001034 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1035 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001036 if (program_header->p_type != PT_LOAD) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001037 continue;
1038 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001039 Elf_Addr begin_vaddr = program_header->p_vaddr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001040 if (begin_vaddr < min_vaddr) {
1041 min_vaddr = begin_vaddr;
1042 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001043 Elf_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz;
Vladimir Marko3fc99032015-05-13 19:06:30 +01001044 if (UNLIKELY(begin_vaddr > end_vaddr)) {
1045 std::ostringstream oss;
1046 oss << "Program header #" << i << " has overflow in p_vaddr+p_memsz: 0x" << std::hex
1047 << program_header->p_vaddr << "+0x" << program_header->p_memsz << "=0x" << end_vaddr
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001048 << " in ELF file \"" << file_path_ << "\"";
Vladimir Marko3fc99032015-05-13 19:06:30 +01001049 *error_msg = oss.str();
1050 *size = static_cast<size_t>(-1);
1051 return false;
1052 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001053 if (end_vaddr > max_vaddr) {
1054 max_vaddr = end_vaddr;
1055 }
1056 }
1057 min_vaddr = RoundDown(min_vaddr, kPageSize);
1058 max_vaddr = RoundUp(max_vaddr, kPageSize);
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001059 CHECK_LT(min_vaddr, max_vaddr) << file_path_;
Vladimir Marko3fc99032015-05-13 19:06:30 +01001060 Elf_Addr loaded_size = max_vaddr - min_vaddr;
1061 // Check that the loaded_size fits in size_t.
1062 if (UNLIKELY(loaded_size > std::numeric_limits<size_t>::max())) {
1063 std::ostringstream oss;
1064 oss << "Loaded size is 0x" << std::hex << loaded_size << " but maximum size_t is 0x"
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001065 << std::numeric_limits<size_t>::max() << " for ELF file \"" << file_path_ << "\"";
Vladimir Marko3fc99032015-05-13 19:06:30 +01001066 *error_msg = oss.str();
1067 *size = static_cast<size_t>(-1);
1068 return false;
1069 }
1070 *size = loaded_size;
1071 return true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001072}
1073
David Srbecky533c2072015-04-22 12:20:22 +01001074template <typename ElfTypes>
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001075bool ElfFileImpl<ElfTypes>::Load(File* file,
1076 bool executable,
1077 bool low_4gb,
1078 std::string* error_msg) {
1079 CHECK(program_header_only_) << file->GetPath();
Andreas Gampe91268c12014-04-03 17:50:24 -07001080
1081 if (executable) {
Andreas Gampe6f611412015-01-21 22:25:24 -08001082 InstructionSet elf_ISA = GetInstructionSetFromELF(GetHeader().e_machine, GetHeader().e_flags);
Andreas Gampe91268c12014-04-03 17:50:24 -07001083 if (elf_ISA != kRuntimeISA) {
1084 std::ostringstream oss;
1085 oss << "Expected ISA " << kRuntimeISA << " but found " << elf_ISA;
1086 *error_msg = oss.str();
1087 return false;
1088 }
1089 }
1090
Jim_Guoa62a5882014-04-28 11:11:57 +08001091 bool reserved = false;
Tong Shen62d1ca32014-09-03 17:24:56 -07001092 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1093 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001094 if (program_header == nullptr) {
1095 *error_msg = StringPrintf("No program header for entry %d in ELF file %s.",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001096 i, file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -07001097 return false;
1098 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001099
1100 // Record .dynamic header information for later use
Andreas Gampedaab38c2014-09-12 18:38:24 -07001101 if (program_header->p_type == PT_DYNAMIC) {
1102 dynamic_program_header_ = program_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001103 continue;
1104 }
1105
1106 // Not something to load, move on.
Andreas Gampedaab38c2014-09-12 18:38:24 -07001107 if (program_header->p_type != PT_LOAD) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001108 continue;
1109 }
1110
1111 // Found something to load.
1112
Jim_Guoa62a5882014-04-28 11:11:57 +08001113 // Before load the actual segments, reserve a contiguous chunk
1114 // of required size and address for all segments, but with no
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001115 // permissions. We'll then carve that up with the proper
1116 // permissions as we load the actual segments. If p_vaddr is
1117 // non-zero, the segments require the specific address specified,
1118 // which either was specified in the file because we already set
1119 // base_address_ after the first zero segment).
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001120 int64_t temp_file_length = file->GetLength();
Ian Rogerscdfcf372014-01-23 20:38:36 -08001121 if (temp_file_length < 0) {
1122 errno = -temp_file_length;
1123 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001124 file->GetPath().c_str(), file->Fd(), strerror(errno));
Ian Rogerscdfcf372014-01-23 20:38:36 -08001125 return false;
1126 }
1127 size_t file_length = static_cast<size_t>(temp_file_length);
Jim_Guoa62a5882014-04-28 11:11:57 +08001128 if (!reserved) {
Igor Murashkin46774762014-10-22 11:37:02 -07001129 uint8_t* reserve_base = reinterpret_cast<uint8_t*>(program_header->p_vaddr);
1130 uint8_t* reserve_base_override = reserve_base;
1131 // Override the base (e.g. when compiling with --compile-pic)
1132 if (requested_base_ != nullptr) {
1133 reserve_base_override = requested_base_;
1134 }
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001135 std::string reservation_name("ElfFile reservation for ");
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001136 reservation_name += file->GetPath();
Vladimir Marko3fc99032015-05-13 19:06:30 +01001137 size_t loaded_size;
1138 if (!GetLoadedSize(&loaded_size, error_msg)) {
1139 DCHECK(!error_msg->empty());
1140 return false;
1141 }
Ian Rogers700a4022014-05-19 16:49:03 -07001142 std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
Igor Murashkin46774762014-10-22 11:37:02 -07001143 reserve_base_override,
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001144 loaded_size,
1145 PROT_NONE,
1146 low_4gb,
1147 false,
Jim_Guoa62a5882014-04-28 11:11:57 +08001148 error_msg));
Brian Carlstromc1409452014-02-26 14:06:23 -08001149 if (reserve.get() == nullptr) {
1150 *error_msg = StringPrintf("Failed to allocate %s: %s",
1151 reservation_name.c_str(), error_msg->c_str());
1152 return false;
1153 }
Jim_Guoa62a5882014-04-28 11:11:57 +08001154 reserved = true;
Igor Murashkin46774762014-10-22 11:37:02 -07001155
1156 // Base address is the difference of actual mapped location and the p_vaddr
1157 base_address_ = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(reserve->Begin())
1158 - reinterpret_cast<uintptr_t>(reserve_base));
1159 // By adding the p_vaddr of a section/symbol to base_address_ we will always get the
1160 // dynamic memory address of where that object is actually mapped
1161 //
1162 // TODO: base_address_ needs to be calculated in ::Open, otherwise
1163 // FindDynamicSymbolAddress returns the wrong values until Load is called.
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001164 segments_.push_back(reserve.release());
1165 }
1166 // empty segment, nothing to map
Andreas Gampedaab38c2014-09-12 18:38:24 -07001167 if (program_header->p_memsz == 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001168 continue;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001169 }
Ian Rogers13735952014-10-08 12:43:28 -07001170 uint8_t* p_vaddr = base_address_ + program_header->p_vaddr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001171 int prot = 0;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001172 if (executable && ((program_header->p_flags & PF_X) != 0)) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001173 prot |= PROT_EXEC;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001174 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001175 if ((program_header->p_flags & PF_W) != 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001176 prot |= PROT_WRITE;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001177 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001178 if ((program_header->p_flags & PF_R) != 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001179 prot |= PROT_READ;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001180 }
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -07001181 int flags = 0;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001182 if (writable_) {
1183 prot |= PROT_WRITE;
1184 flags |= MAP_SHARED;
1185 } else {
1186 flags |= MAP_PRIVATE;
1187 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001188 if (program_header->p_filesz > program_header->p_memsz) {
1189 *error_msg = StringPrintf("Invalid p_filesz > p_memsz (%" PRIu64 " > %" PRIu64 "): %s",
1190 static_cast<uint64_t>(program_header->p_filesz),
1191 static_cast<uint64_t>(program_header->p_memsz),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001192 file->GetPath().c_str());
Brian Carlstrom3a223612013-10-10 17:18:24 -07001193 return false;
1194 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001195 if (program_header->p_filesz < program_header->p_memsz &&
1196 !IsAligned<kPageSize>(program_header->p_filesz)) {
1197 *error_msg = StringPrintf("Unsupported unaligned p_filesz < p_memsz (%" PRIu64
1198 " < %" PRIu64 "): %s",
1199 static_cast<uint64_t>(program_header->p_filesz),
1200 static_cast<uint64_t>(program_header->p_memsz),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001201 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001202 return false;
1203 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001204 if (file_length < (program_header->p_offset + program_header->p_filesz)) {
1205 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment "
1206 "%d of %" PRIu64 " bytes: '%s'", file_length, i,
1207 static_cast<uint64_t>(program_header->p_offset + program_header->p_filesz),
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001208 file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001209 return false;
1210 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001211 if (program_header->p_filesz != 0u) {
1212 std::unique_ptr<MemMap> segment(
1213 MemMap::MapFileAtAddress(p_vaddr,
1214 program_header->p_filesz,
Mathieu Chartier42bddce2015-11-09 15:16:56 -08001215 prot,
1216 flags,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001217 file->Fd(),
Vladimir Marko5c42c292015-02-25 12:02:49 +00001218 program_header->p_offset,
Mathieu Chartier42bddce2015-11-09 15:16:56 -08001219 /*low4_gb*/false,
1220 /*reuse*/true, // implies MAP_FIXED
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001221 file->GetPath().c_str(),
Vladimir Marko5c42c292015-02-25 12:02:49 +00001222 error_msg));
1223 if (segment.get() == nullptr) {
1224 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001225 i, file->GetPath().c_str(), error_msg->c_str());
Vladimir Marko5c42c292015-02-25 12:02:49 +00001226 return false;
1227 }
1228 if (segment->Begin() != p_vaddr) {
1229 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, "
1230 "instead mapped to %p",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001231 i, file->GetPath().c_str(), p_vaddr, segment->Begin());
Vladimir Marko5c42c292015-02-25 12:02:49 +00001232 return false;
1233 }
1234 segments_.push_back(segment.release());
1235 }
1236 if (program_header->p_filesz < program_header->p_memsz) {
1237 std::string name = StringPrintf("Zero-initialized segment %" PRIu64 " of ELF file %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001238 static_cast<uint64_t>(i), file->GetPath().c_str());
Vladimir Marko5c42c292015-02-25 12:02:49 +00001239 std::unique_ptr<MemMap> segment(
1240 MemMap::MapAnonymous(name.c_str(),
1241 p_vaddr + program_header->p_filesz,
1242 program_header->p_memsz - program_header->p_filesz,
1243 prot, false, true /* reuse */, error_msg));
1244 if (segment == nullptr) {
1245 *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s: %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001246 i, file->GetPath().c_str(), error_msg->c_str());
Vladimir Marko5c42c292015-02-25 12:02:49 +00001247 return false;
1248 }
1249 if (segment->Begin() != p_vaddr) {
1250 *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s "
1251 "at expected address %p, instead mapped to %p",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001252 i, file->GetPath().c_str(), p_vaddr, segment->Begin());
Vladimir Marko5c42c292015-02-25 12:02:49 +00001253 return false;
1254 }
1255 segments_.push_back(segment.release());
1256 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001257 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001258
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001259 // Now that we are done loading, .dynamic should be in memory to find .dynstr, .dynsym, .hash
Ian Rogers13735952014-10-08 12:43:28 -07001260 uint8_t* dsptr = base_address_ + GetDynamicProgramHeader().p_vaddr;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001261 if ((dsptr < Begin() || dsptr >= End()) && !ValidPointer(dsptr)) {
1262 *error_msg = StringPrintf("dynamic section address invalid in ELF file %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001263 file->GetPath().c_str());
Andreas Gampedaab38c2014-09-12 18:38:24 -07001264 return false;
1265 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001266 dynamic_section_start_ = reinterpret_cast<Elf_Dyn*>(dsptr);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001267
Tong Shen62d1ca32014-09-03 17:24:56 -07001268 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1269 Elf_Dyn& elf_dyn = GetDynamic(i);
Ian Rogers13735952014-10-08 12:43:28 -07001270 uint8_t* d_ptr = base_address_ + elf_dyn.d_un.d_ptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001271 switch (elf_dyn.d_tag) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001272 case DT_HASH: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001273 if (!ValidPointer(d_ptr)) {
1274 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001275 d_ptr, file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001276 return false;
1277 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001278 hash_section_start_ = reinterpret_cast<Elf_Word*>(d_ptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001279 break;
1280 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001281 case DT_STRTAB: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001282 if (!ValidPointer(d_ptr)) {
1283 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001284 d_ptr, file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001285 return false;
1286 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001287 dynstr_section_start_ = reinterpret_cast<char*>(d_ptr);
1288 break;
1289 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001290 case DT_SYMTAB: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001291 if (!ValidPointer(d_ptr)) {
1292 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001293 d_ptr, file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001294 return false;
1295 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001296 dynsym_section_start_ = reinterpret_cast<Elf_Sym*>(d_ptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001297 break;
1298 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001299 case DT_NULL: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001300 if (GetDynamicNum() != i+1) {
1301 *error_msg = StringPrintf("DT_NULL found after %d .dynamic entries, "
1302 "expected %d as implied by size of PT_DYNAMIC segment in %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001303 i + 1, GetDynamicNum(), file->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001304 return false;
1305 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001306 break;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001307 }
1308 }
1309 }
1310
Andreas Gampedaab38c2014-09-12 18:38:24 -07001311 // Check for the existence of some sections.
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001312 if (!CheckSectionsExist(file, error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001313 return false;
1314 }
1315
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001316 return true;
1317}
1318
David Srbecky533c2072015-04-22 12:20:22 +01001319template <typename ElfTypes>
1320bool ElfFileImpl<ElfTypes>::ValidPointer(const uint8_t* start) const {
Brian Carlstromc1409452014-02-26 14:06:23 -08001321 for (size_t i = 0; i < segments_.size(); ++i) {
1322 const MemMap* segment = segments_[i];
1323 if (segment->Begin() <= start && start < segment->End()) {
1324 return true;
1325 }
1326 }
1327 return false;
1328}
1329
Alex Light3470ab42014-06-18 10:35:45 -07001330
David Srbecky533c2072015-04-22 12:20:22 +01001331template <typename ElfTypes>
1332typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByName(
1333 const std::string& name) const {
Alex Light3470ab42014-06-18 10:35:45 -07001334 CHECK(!program_header_only_);
Tong Shen62d1ca32014-09-03 17:24:56 -07001335 Elf_Shdr* shstrtab_sec = GetSectionNameStringSection();
Andreas Gampedaab38c2014-09-12 18:38:24 -07001336 if (shstrtab_sec == nullptr) {
1337 return nullptr;
1338 }
Alex Light3470ab42014-06-18 10:35:45 -07001339 for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001340 Elf_Shdr* shdr = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001341 if (shdr == nullptr) {
1342 return nullptr;
1343 }
1344 const char* sec_name = GetString(*shstrtab_sec, shdr->sh_name);
Alex Light3470ab42014-06-18 10:35:45 -07001345 if (sec_name == nullptr) {
1346 continue;
1347 }
1348 if (name == sec_name) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001349 return shdr;
Alex Light3470ab42014-06-18 10:35:45 -07001350 }
1351 }
1352 return nullptr;
Mark Mendellae9fd932014-02-10 16:14:35 -08001353}
1354
David Srbecky533c2072015-04-22 12:20:22 +01001355template <typename ElfTypes>
David Srbeckyf8980872015-05-22 17:04:47 +01001356bool ElfFileImpl<ElfTypes>::FixupDebugSections(Elf_Addr base_address_delta) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001357 if (base_address_delta == 0) {
1358 return true;
1359 }
David Srbeckyf8980872015-05-22 17:04:47 +01001360 return ApplyOatPatchesTo(".debug_frame", base_address_delta) &&
1361 ApplyOatPatchesTo(".debug_info", base_address_delta) &&
1362 ApplyOatPatchesTo(".debug_line", base_address_delta);
David Srbecky2f6cdb02015-04-11 00:17:53 +01001363}
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001364
David Srbecky533c2072015-04-22 12:20:22 +01001365template <typename ElfTypes>
1366bool ElfFileImpl<ElfTypes>::ApplyOatPatchesTo(
David Srbeckyf8980872015-05-22 17:04:47 +01001367 const char* target_section_name, Elf_Addr delta) {
1368 auto target_section = FindSectionByName(target_section_name);
1369 if (target_section == nullptr) {
1370 return true;
1371 }
1372 std::string patches_name = target_section_name + std::string(".oat_patches");
1373 auto patches_section = FindSectionByName(patches_name.c_str());
David Srbecky2f6cdb02015-04-11 00:17:53 +01001374 if (patches_section == nullptr) {
David Srbeckyf8980872015-05-22 17:04:47 +01001375 LOG(ERROR) << patches_name << " section not found.";
Alex Light3470ab42014-06-18 10:35:45 -07001376 return false;
1377 }
David Srbecky2f6cdb02015-04-11 00:17:53 +01001378 if (patches_section->sh_type != SHT_OAT_PATCH) {
David Srbeckyf8980872015-05-22 17:04:47 +01001379 LOG(ERROR) << "Unexpected type of " << patches_name;
Alex Light3470ab42014-06-18 10:35:45 -07001380 return false;
1381 }
David Srbeckyf8980872015-05-22 17:04:47 +01001382 ApplyOatPatches(
David Srbecky2f6cdb02015-04-11 00:17:53 +01001383 Begin() + patches_section->sh_offset,
1384 Begin() + patches_section->sh_offset + patches_section->sh_size,
David Srbeckyf8980872015-05-22 17:04:47 +01001385 delta,
David Srbecky2f6cdb02015-04-11 00:17:53 +01001386 Begin() + target_section->sh_offset,
David Srbeckyf8980872015-05-22 17:04:47 +01001387 Begin() + target_section->sh_offset + target_section->sh_size);
David Srbecky2f6cdb02015-04-11 00:17:53 +01001388 return true;
1389}
1390
David Srbeckyf8980872015-05-22 17:04:47 +01001391// Apply LEB128 encoded patches to given section.
David Srbecky533c2072015-04-22 12:20:22 +01001392template <typename ElfTypes>
David Srbeckyf8980872015-05-22 17:04:47 +01001393void ElfFileImpl<ElfTypes>::ApplyOatPatches(
1394 const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
David Srbecky533c2072015-04-22 12:20:22 +01001395 uint8_t* to_patch, const uint8_t* to_patch_end) {
David Srbeckyf8980872015-05-22 17:04:47 +01001396 typedef __attribute__((__aligned__(1))) Elf_Addr UnalignedAddress;
1397 while (patches < patches_end) {
1398 to_patch += DecodeUnsignedLeb128(&patches);
1399 DCHECK_LE(patches, patches_end) << "Unexpected end of patch list.";
1400 DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of section.";
1401 *reinterpret_cast<UnalignedAddress*>(to_patch) += delta;
David Srbecky2f6cdb02015-04-11 00:17:53 +01001402 }
Alex Light3470ab42014-06-18 10:35:45 -07001403}
Mark Mendellae9fd932014-02-10 16:14:35 -08001404
David Srbecky533c2072015-04-22 12:20:22 +01001405template <typename ElfTypes>
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001406bool ElfFileImpl<ElfTypes>::Strip(File* file, std::string* error_msg) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001407 // ELF files produced by MCLinker look roughly like this
1408 //
1409 // +------------+
1410 // | Elf_Ehdr | contains number of Elf_Shdr and offset to first
1411 // +------------+
1412 // | Elf_Phdr | program headers
1413 // | Elf_Phdr |
1414 // | ... |
1415 // | Elf_Phdr |
1416 // +------------+
1417 // | section | mixture of needed and unneeded sections
1418 // +------------+
1419 // | section |
1420 // +------------+
1421 // | ... |
1422 // +------------+
1423 // | section |
1424 // +------------+
1425 // | Elf_Shdr | section headers
1426 // | Elf_Shdr |
1427 // | ... | contains offset to section start
1428 // | Elf_Shdr |
1429 // +------------+
1430 //
1431 // To strip:
1432 // - leave the Elf_Ehdr and Elf_Phdr values in place.
1433 // - walk the sections making a new set of Elf_Shdr section headers for what we want to keep
1434 // - move the sections are keeping up to fill in gaps of sections we want to strip
1435 // - write new Elf_Shdr section headers to end of file, updating Elf_Ehdr
1436 // - truncate rest of file
1437 //
1438
1439 std::vector<Elf_Shdr> section_headers;
1440 std::vector<Elf_Word> section_headers_original_indexes;
1441 section_headers.reserve(GetSectionHeaderNum());
1442
1443
1444 Elf_Shdr* string_section = GetSectionNameStringSection();
1445 CHECK(string_section != nullptr);
1446 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1447 Elf_Shdr* sh = GetSectionHeader(i);
1448 CHECK(sh != nullptr);
1449 const char* name = GetString(*string_section, sh->sh_name);
1450 if (name == nullptr) {
1451 CHECK_EQ(0U, i);
1452 section_headers.push_back(*sh);
1453 section_headers_original_indexes.push_back(0);
1454 continue;
1455 }
Andreas Gampe9186ced2016-12-12 14:28:21 -08001456 if (android::base::StartsWith(name, ".debug")
Tong Shen62d1ca32014-09-03 17:24:56 -07001457 || (strcmp(name, ".strtab") == 0)
1458 || (strcmp(name, ".symtab") == 0)) {
1459 continue;
1460 }
1461 section_headers.push_back(*sh);
1462 section_headers_original_indexes.push_back(i);
1463 }
1464 CHECK_NE(0U, section_headers.size());
1465 CHECK_EQ(section_headers.size(), section_headers_original_indexes.size());
1466
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001467 // section 0 is the null section, sections start at offset of first section
Tong Shen62d1ca32014-09-03 17:24:56 -07001468 CHECK(GetSectionHeader(1) != nullptr);
1469 Elf_Off offset = GetSectionHeader(1)->sh_offset;
1470 for (size_t i = 1; i < section_headers.size(); i++) {
1471 Elf_Shdr& new_sh = section_headers[i];
1472 Elf_Shdr* old_sh = GetSectionHeader(section_headers_original_indexes[i]);
1473 CHECK(old_sh != nullptr);
1474 CHECK_EQ(new_sh.sh_name, old_sh->sh_name);
1475 if (old_sh->sh_addralign > 1) {
1476 offset = RoundUp(offset, old_sh->sh_addralign);
1477 }
1478 if (old_sh->sh_offset == offset) {
1479 // already in place
1480 offset += old_sh->sh_size;
1481 continue;
1482 }
1483 // shift section earlier
1484 memmove(Begin() + offset,
1485 Begin() + old_sh->sh_offset,
1486 old_sh->sh_size);
1487 new_sh.sh_offset = offset;
1488 offset += old_sh->sh_size;
1489 }
1490
1491 Elf_Off shoff = offset;
1492 size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf_Shdr);
1493 memcpy(Begin() + offset, &section_headers[0], section_headers_size_in_bytes);
1494 offset += section_headers_size_in_bytes;
1495
1496 GetHeader().e_shnum = section_headers.size();
1497 GetHeader().e_shoff = shoff;
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001498 int result = ftruncate(file->Fd(), offset);
Tong Shen62d1ca32014-09-03 17:24:56 -07001499 if (result != 0) {
1500 *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s",
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001501 file->GetPath().c_str(), strerror(errno));
Tong Shen62d1ca32014-09-03 17:24:56 -07001502 return false;
1503 }
1504 return true;
1505}
1506
1507static const bool DEBUG_FIXUP = false;
1508
David Srbecky533c2072015-04-22 12:20:22 +01001509template <typename ElfTypes>
1510bool ElfFileImpl<ElfTypes>::Fixup(Elf_Addr base_address) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001511 if (!FixupDynamic(base_address)) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001512 LOG(WARNING) << "Failed to fixup .dynamic in " << file_path_;
Tong Shen62d1ca32014-09-03 17:24:56 -07001513 return false;
1514 }
1515 if (!FixupSectionHeaders(base_address)) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001516 LOG(WARNING) << "Failed to fixup section headers in " << file_path_;
Tong Shen62d1ca32014-09-03 17:24:56 -07001517 return false;
1518 }
1519 if (!FixupProgramHeaders(base_address)) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001520 LOG(WARNING) << "Failed to fixup program headers in " << file_path_;
Tong Shen62d1ca32014-09-03 17:24:56 -07001521 return false;
1522 }
1523 if (!FixupSymbols(base_address, true)) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001524 LOG(WARNING) << "Failed to fixup .dynsym in " << file_path_;
Tong Shen62d1ca32014-09-03 17:24:56 -07001525 return false;
1526 }
1527 if (!FixupSymbols(base_address, false)) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001528 LOG(WARNING) << "Failed to fixup .symtab in " << file_path_;
Tong Shen62d1ca32014-09-03 17:24:56 -07001529 return false;
1530 }
1531 if (!FixupRelocations(base_address)) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001532 LOG(WARNING) << "Failed to fixup .rel.dyn in " << file_path_;
Tong Shen62d1ca32014-09-03 17:24:56 -07001533 return false;
1534 }
Andreas Gampe3c54b002015-04-07 16:09:30 -07001535 static_assert(sizeof(Elf_Off) >= sizeof(base_address), "Potentially losing precision.");
1536 if (!FixupDebugSections(static_cast<Elf_Off>(base_address))) {
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001537 LOG(WARNING) << "Failed to fixup debug sections in " << file_path_;
Tong Shen62d1ca32014-09-03 17:24:56 -07001538 return false;
1539 }
1540 return true;
1541}
1542
David Srbecky533c2072015-04-22 12:20:22 +01001543template <typename ElfTypes>
1544bool ElfFileImpl<ElfTypes>::FixupDynamic(Elf_Addr base_address) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001545 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1546 Elf_Dyn& elf_dyn = GetDynamic(i);
1547 Elf_Word d_tag = elf_dyn.d_tag;
1548 if (IsDynamicSectionPointer(d_tag, GetHeader().e_machine)) {
1549 Elf_Addr d_ptr = elf_dyn.d_un.d_ptr;
1550 if (DEBUG_FIXUP) {
1551 LOG(INFO) << StringPrintf("In %s moving Elf_Dyn[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001552 file_path_.c_str(), i,
Tong Shen62d1ca32014-09-03 17:24:56 -07001553 static_cast<uint64_t>(d_ptr),
1554 static_cast<uint64_t>(d_ptr + base_address));
1555 }
1556 d_ptr += base_address;
1557 elf_dyn.d_un.d_ptr = d_ptr;
1558 }
1559 }
1560 return true;
1561}
1562
David Srbecky533c2072015-04-22 12:20:22 +01001563template <typename ElfTypes>
1564bool ElfFileImpl<ElfTypes>::FixupSectionHeaders(Elf_Addr base_address) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001565 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1566 Elf_Shdr* sh = GetSectionHeader(i);
1567 CHECK(sh != nullptr);
1568 // 0 implies that the section will not exist in the memory of the process
1569 if (sh->sh_addr == 0) {
1570 continue;
1571 }
1572 if (DEBUG_FIXUP) {
1573 LOG(INFO) << StringPrintf("In %s moving Elf_Shdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001574 file_path_.c_str(), i,
Tong Shen62d1ca32014-09-03 17:24:56 -07001575 static_cast<uint64_t>(sh->sh_addr),
1576 static_cast<uint64_t>(sh->sh_addr + base_address));
1577 }
1578 sh->sh_addr += base_address;
1579 }
1580 return true;
1581}
1582
David Srbecky533c2072015-04-22 12:20:22 +01001583template <typename ElfTypes>
1584bool ElfFileImpl<ElfTypes>::FixupProgramHeaders(Elf_Addr base_address) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001585 // TODO: ELFObjectFile doesn't have give to Elf_Phdr, so we do that ourselves for now.
1586 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1587 Elf_Phdr* ph = GetProgramHeader(i);
1588 CHECK(ph != nullptr);
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001589 CHECK_EQ(ph->p_vaddr, ph->p_paddr) << file_path_ << " i=" << i;
Tong Shen62d1ca32014-09-03 17:24:56 -07001590 CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001591 << file_path_ << " i=" << i;
Tong Shen62d1ca32014-09-03 17:24:56 -07001592 if (DEBUG_FIXUP) {
1593 LOG(INFO) << StringPrintf("In %s moving Elf_Phdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001594 file_path_.c_str(), i,
Tong Shen62d1ca32014-09-03 17:24:56 -07001595 static_cast<uint64_t>(ph->p_vaddr),
1596 static_cast<uint64_t>(ph->p_vaddr + base_address));
1597 }
1598 ph->p_vaddr += base_address;
1599 ph->p_paddr += base_address;
1600 CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001601 << file_path_ << " i=" << i;
Tong Shen62d1ca32014-09-03 17:24:56 -07001602 }
1603 return true;
1604}
1605
David Srbecky533c2072015-04-22 12:20:22 +01001606template <typename ElfTypes>
1607bool ElfFileImpl<ElfTypes>::FixupSymbols(Elf_Addr base_address, bool dynamic) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001608 Elf_Word section_type = dynamic ? SHT_DYNSYM : SHT_SYMTAB;
1609 // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
1610 Elf_Shdr* symbol_section = FindSectionByType(section_type);
1611 if (symbol_section == nullptr) {
1612 // file is missing optional .symtab
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001613 CHECK(!dynamic) << file_path_;
Tong Shen62d1ca32014-09-03 17:24:56 -07001614 return true;
1615 }
1616 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
1617 Elf_Sym* symbol = GetSymbol(section_type, i);
1618 CHECK(symbol != nullptr);
1619 if (symbol->st_value != 0) {
1620 if (DEBUG_FIXUP) {
1621 LOG(INFO) << StringPrintf("In %s moving Elf_Sym[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001622 file_path_.c_str(), i,
Tong Shen62d1ca32014-09-03 17:24:56 -07001623 static_cast<uint64_t>(symbol->st_value),
1624 static_cast<uint64_t>(symbol->st_value + base_address));
1625 }
1626 symbol->st_value += base_address;
1627 }
1628 }
1629 return true;
1630}
1631
David Srbecky533c2072015-04-22 12:20:22 +01001632template <typename ElfTypes>
1633bool ElfFileImpl<ElfTypes>::FixupRelocations(Elf_Addr base_address) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001634 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1635 Elf_Shdr* sh = GetSectionHeader(i);
1636 CHECK(sh != nullptr);
1637 if (sh->sh_type == SHT_REL) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -08001638 for (uint32_t j = 0; j < GetRelNum(*sh); j++) {
1639 Elf_Rel& rel = GetRel(*sh, j);
Tong Shen62d1ca32014-09-03 17:24:56 -07001640 if (DEBUG_FIXUP) {
1641 LOG(INFO) << StringPrintf("In %s moving Elf_Rel[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001642 file_path_.c_str(), j,
Tong Shen62d1ca32014-09-03 17:24:56 -07001643 static_cast<uint64_t>(rel.r_offset),
1644 static_cast<uint64_t>(rel.r_offset + base_address));
1645 }
1646 rel.r_offset += base_address;
1647 }
1648 } else if (sh->sh_type == SHT_RELA) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -08001649 for (uint32_t j = 0; j < GetRelaNum(*sh); j++) {
1650 Elf_Rela& rela = GetRela(*sh, j);
Tong Shen62d1ca32014-09-03 17:24:56 -07001651 if (DEBUG_FIXUP) {
1652 LOG(INFO) << StringPrintf("In %s moving Elf_Rela[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001653 file_path_.c_str(), j,
Tong Shen62d1ca32014-09-03 17:24:56 -07001654 static_cast<uint64_t>(rela.r_offset),
1655 static_cast<uint64_t>(rela.r_offset + base_address));
1656 }
1657 rela.r_offset += base_address;
1658 }
1659 }
1660 }
1661 return true;
1662}
1663
1664// Explicit instantiations
David Srbecky533c2072015-04-22 12:20:22 +01001665template class ElfFileImpl<ElfTypes32>;
1666template class ElfFileImpl<ElfTypes64>;
Tong Shen62d1ca32014-09-03 17:24:56 -07001667
Ian Rogersd4c4d952014-10-16 20:31:53 -07001668ElfFile::ElfFile(ElfFileImpl32* elf32) : elf32_(elf32), elf64_(nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001669}
1670
Ian Rogersd4c4d952014-10-16 20:31:53 -07001671ElfFile::ElfFile(ElfFileImpl64* elf64) : elf32_(nullptr), elf64_(elf64) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001672}
1673
1674ElfFile::~ElfFile() {
Ian Rogersd4c4d952014-10-16 20:31:53 -07001675 // Should never have 32 and 64-bit impls.
1676 CHECK_NE(elf32_.get() == nullptr, elf64_.get() == nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07001677}
1678
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001679ElfFile* ElfFile::Open(File* file,
1680 bool writable,
1681 bool program_header_only,
1682 bool low_4gb,
1683 std::string* error_msg,
Igor Murashkin46774762014-10-22 11:37:02 -07001684 uint8_t* requested_base) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001685 if (file->GetLength() < EI_NIDENT) {
1686 *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
1687 file->GetPath().c_str());
1688 return nullptr;
1689 }
Mathieu Chartier42bddce2015-11-09 15:16:56 -08001690 std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT,
1691 PROT_READ,
1692 MAP_PRIVATE,
1693 file->Fd(),
1694 0,
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001695 low_4gb,
Mathieu Chartier42bddce2015-11-09 15:16:56 -08001696 file->GetPath().c_str(),
1697 error_msg));
Tong Shen62d1ca32014-09-03 17:24:56 -07001698 if (map == nullptr && map->Size() != EI_NIDENT) {
1699 return nullptr;
1700 }
Ian Rogers13735952014-10-08 12:43:28 -07001701 uint8_t* header = map->Begin();
Tong Shen62d1ca32014-09-03 17:24:56 -07001702 if (header[EI_CLASS] == ELFCLASS64) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001703 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file,
1704 writable,
1705 program_header_only,
1706 low_4gb,
1707 error_msg,
1708 requested_base);
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001709 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001710 return nullptr;
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001711 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001712 return new ElfFile(elf_file_impl);
1713 } else if (header[EI_CLASS] == ELFCLASS32) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001714 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file,
1715 writable,
1716 program_header_only,
1717 low_4gb,
1718 error_msg,
1719 requested_base);
Ian Rogersd4c4d952014-10-16 20:31:53 -07001720 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001721 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001722 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001723 return new ElfFile(elf_file_impl);
1724 } else {
1725 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
1726 ELFCLASS32, ELFCLASS64,
1727 file->GetPath().c_str(),
1728 header[EI_CLASS]);
1729 return nullptr;
1730 }
1731}
1732
1733ElfFile* ElfFile::Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001734 // low_4gb support not required for this path.
1735 constexpr bool low_4gb = false;
Tong Shen62d1ca32014-09-03 17:24:56 -07001736 if (file->GetLength() < EI_NIDENT) {
1737 *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
1738 file->GetPath().c_str());
1739 return nullptr;
1740 }
Mathieu Chartier42bddce2015-11-09 15:16:56 -08001741 std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT,
1742 PROT_READ,
1743 MAP_PRIVATE,
1744 file->Fd(),
1745 0,
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001746 low_4gb,
Mathieu Chartier42bddce2015-11-09 15:16:56 -08001747 file->GetPath().c_str(),
1748 error_msg));
Tong Shen62d1ca32014-09-03 17:24:56 -07001749 if (map == nullptr && map->Size() != EI_NIDENT) {
1750 return nullptr;
1751 }
Ian Rogers13735952014-10-08 12:43:28 -07001752 uint8_t* header = map->Begin();
Tong Shen62d1ca32014-09-03 17:24:56 -07001753 if (header[EI_CLASS] == ELFCLASS64) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001754 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file,
1755 mmap_prot,
1756 mmap_flags,
1757 low_4gb,
1758 error_msg);
Ian Rogersd4c4d952014-10-16 20:31:53 -07001759 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001760 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001761 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001762 return new ElfFile(elf_file_impl);
1763 } else if (header[EI_CLASS] == ELFCLASS32) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001764 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file,
1765 mmap_prot,
1766 mmap_flags,
1767 low_4gb,
1768 error_msg);
Ian Rogersd4c4d952014-10-16 20:31:53 -07001769 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001770 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001771 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001772 return new ElfFile(elf_file_impl);
1773 } else {
1774 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
1775 ELFCLASS32, ELFCLASS64,
1776 file->GetPath().c_str(),
1777 header[EI_CLASS]);
1778 return nullptr;
1779 }
1780}
1781
1782#define DELEGATE_TO_IMPL(func, ...) \
Ian Rogersd4c4d952014-10-16 20:31:53 -07001783 if (elf64_.get() != nullptr) { \
1784 return elf64_->func(__VA_ARGS__); \
Tong Shen62d1ca32014-09-03 17:24:56 -07001785 } else { \
Ian Rogersd4c4d952014-10-16 20:31:53 -07001786 DCHECK(elf32_.get() != nullptr); \
1787 return elf32_->func(__VA_ARGS__); \
Tong Shen62d1ca32014-09-03 17:24:56 -07001788 }
1789
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001790bool ElfFile::Load(File* file, bool executable, bool low_4gb, std::string* error_msg) {
1791 DELEGATE_TO_IMPL(Load, file, executable, low_4gb, error_msg);
Tong Shen62d1ca32014-09-03 17:24:56 -07001792}
1793
Ian Rogers13735952014-10-08 12:43:28 -07001794const uint8_t* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
Tong Shen62d1ca32014-09-03 17:24:56 -07001795 DELEGATE_TO_IMPL(FindDynamicSymbolAddress, symbol_name);
1796}
1797
1798size_t ElfFile::Size() const {
1799 DELEGATE_TO_IMPL(Size);
1800}
1801
Ian Rogers13735952014-10-08 12:43:28 -07001802uint8_t* ElfFile::Begin() const {
Tong Shen62d1ca32014-09-03 17:24:56 -07001803 DELEGATE_TO_IMPL(Begin);
1804}
1805
Ian Rogers13735952014-10-08 12:43:28 -07001806uint8_t* ElfFile::End() const {
Tong Shen62d1ca32014-09-03 17:24:56 -07001807 DELEGATE_TO_IMPL(End);
1808}
1809
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001810const std::string& ElfFile::GetFilePath() const {
1811 DELEGATE_TO_IMPL(GetFilePath);
Tong Shen62d1ca32014-09-03 17:24:56 -07001812}
1813
Alex Light0eb76d22015-08-11 18:03:47 -07001814bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset,
1815 uint64_t* size) const {
Ian Rogersd4c4d952014-10-16 20:31:53 -07001816 if (elf32_.get() == nullptr) {
1817 CHECK(elf64_.get() != nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07001818
Ian Rogersd4c4d952014-10-16 20:31:53 -07001819 Elf64_Shdr *shdr = elf64_->FindSectionByName(section_name);
1820 if (shdr == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001821 return false;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001822 }
1823 if (offset != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001824 *offset = shdr->sh_offset;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001825 }
1826 if (size != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001827 *size = shdr->sh_size;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001828 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001829 return true;
1830 } else {
Ian Rogersd4c4d952014-10-16 20:31:53 -07001831 Elf32_Shdr *shdr = elf32_->FindSectionByName(section_name);
1832 if (shdr == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001833 return false;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001834 }
1835 if (offset != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001836 *offset = shdr->sh_offset;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001837 }
1838 if (size != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001839 *size = shdr->sh_size;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001840 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001841 return true;
1842 }
1843}
1844
Jeff Hao24ec0282016-03-17 21:32:45 -07001845bool ElfFile::HasSection(const std::string& name) const {
1846 if (elf64_.get() != nullptr) {
1847 return elf64_->FindSectionByName(name) != nullptr;
1848 } else {
1849 return elf32_->FindSectionByName(name) != nullptr;
1850 }
1851}
1852
Tong Shen62d1ca32014-09-03 17:24:56 -07001853uint64_t ElfFile::FindSymbolAddress(unsigned section_type,
1854 const std::string& symbol_name,
1855 bool build_map) {
1856 DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map);
1857}
1858
Vladimir Marko3fc99032015-05-13 19:06:30 +01001859bool ElfFile::GetLoadedSize(size_t* size, std::string* error_msg) const {
1860 DELEGATE_TO_IMPL(GetLoadedSize, size, error_msg);
Tong Shen62d1ca32014-09-03 17:24:56 -07001861}
1862
1863bool ElfFile::Strip(File* file, std::string* error_msg) {
Mathieu Chartierbcb6a722016-03-08 16:49:58 -08001864 std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, /*low_4gb*/false, error_msg));
Tong Shen62d1ca32014-09-03 17:24:56 -07001865 if (elf_file.get() == nullptr) {
1866 return false;
1867 }
1868
Brian Carlstromf5b0f2c2016-10-14 01:04:26 -07001869 if (elf_file->elf64_.get() != nullptr) {
1870 return elf_file->elf64_->Strip(file, error_msg);
1871 } else {
1872 return elf_file->elf32_->Strip(file, error_msg);
1873 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001874}
1875
Andreas Gampe3c54b002015-04-07 16:09:30 -07001876bool ElfFile::Fixup(uint64_t base_address) {
1877 if (elf64_.get() != nullptr) {
1878 return elf64_->Fixup(static_cast<Elf64_Addr>(base_address));
1879 } else {
1880 DCHECK(elf32_.get() != nullptr);
1881 CHECK(IsUint<32>(base_address)) << std::hex << base_address;
1882 return elf32_->Fixup(static_cast<Elf32_Addr>(base_address));
1883 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001884 DELEGATE_TO_IMPL(Fixup, base_address);
1885}
1886
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001887} // namespace art