blob: 37e391d49fd2d7b273021b48b86cec28bbf2ebc3 [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
Ian Rogersd582fa42014-11-05 23:46:43 -080023#include "arch/instruction_set.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080024#include "base/logging.h"
Ian Rogers576ca0c2014-06-06 15:58:22 -070025#include "base/stringprintf.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080026#include "base/stl_util.h"
Ian Rogersd4c4d952014-10-16 20:31:53 -070027#include "base/unix_file/fd_file.h"
Ian Rogersd4c4d952014-10-16 20:31:53 -070028#include "elf_file_impl.h"
29#include "elf_utils.h"
Alex Light3470ab42014-06-18 10:35:45 -070030#include "leb128.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080031#include "utils.h"
32
33namespace art {
34
Mark Mendellae9fd932014-02-10 16:14:35 -080035// -------------------------------------------------------------------
36// Binary GDB JIT Interface as described in
37// http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
38extern "C" {
39 typedef enum {
40 JIT_NOACTION = 0,
41 JIT_REGISTER_FN,
42 JIT_UNREGISTER_FN
43 } JITAction;
44
45 struct JITCodeEntry {
46 JITCodeEntry* next_;
47 JITCodeEntry* prev_;
Ian Rogers13735952014-10-08 12:43:28 -070048 const uint8_t *symfile_addr_;
Mark Mendellae9fd932014-02-10 16:14:35 -080049 uint64_t symfile_size_;
50 };
51
52 struct JITDescriptor {
53 uint32_t version_;
54 uint32_t action_flag_;
55 JITCodeEntry* relevant_entry_;
56 JITCodeEntry* first_entry_;
57 };
58
59 // GDB will place breakpoint into this function.
60 // To prevent GCC from inlining or removing it we place noinline attribute
61 // and inline assembler statement inside.
Andreas Gampe277ccbd2014-11-03 21:36:10 -080062 void __attribute__((noinline)) __jit_debug_register_code();
Mark Mendellae9fd932014-02-10 16:14:35 -080063 void __attribute__((noinline)) __jit_debug_register_code() {
64 __asm__("");
65 }
66
67 // GDB will inspect contents of this descriptor.
68 // Static initialization is necessary to prevent GDB from seeing
69 // uninitialized descriptor.
70 JITDescriptor __jit_debug_descriptor = { 1, JIT_NOACTION, nullptr, nullptr };
71}
72
73
Ian Rogers13735952014-10-08 12:43:28 -070074static JITCodeEntry* CreateCodeEntry(const uint8_t *symfile_addr,
Mark Mendellae9fd932014-02-10 16:14:35 -080075 uintptr_t symfile_size) {
76 JITCodeEntry* entry = new JITCodeEntry;
77 entry->symfile_addr_ = symfile_addr;
78 entry->symfile_size_ = symfile_size;
79 entry->prev_ = nullptr;
80
81 // TODO: Do we need a lock here?
82 entry->next_ = __jit_debug_descriptor.first_entry_;
83 if (entry->next_ != nullptr) {
84 entry->next_->prev_ = entry;
85 }
86 __jit_debug_descriptor.first_entry_ = entry;
87 __jit_debug_descriptor.relevant_entry_ = entry;
88
89 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
90 __jit_debug_register_code();
91 return entry;
92}
93
94
95static void UnregisterCodeEntry(JITCodeEntry* entry) {
96 // TODO: Do we need a lock here?
97 if (entry->prev_ != nullptr) {
98 entry->prev_->next_ = entry->next_;
99 } else {
100 __jit_debug_descriptor.first_entry_ = entry->next_;
101 }
102
103 if (entry->next_ != nullptr) {
104 entry->next_->prev_ = entry->prev_;
105 }
106
107 __jit_debug_descriptor.relevant_entry_ = entry;
108 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
109 __jit_debug_register_code();
110 delete entry;
111}
112
Tong Shen62d1ca32014-09-03 17:24:56 -0700113template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
114 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
115 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
116ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
117 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Igor Murashkin46774762014-10-22 11:37:02 -0700118 ::ElfFileImpl(File* file, bool writable, bool program_header_only, uint8_t* requested_base)
Brian Carlstromc1409452014-02-26 14:06:23 -0800119 : file_(file),
120 writable_(writable),
121 program_header_only_(program_header_only),
Alex Light3470ab42014-06-18 10:35:45 -0700122 header_(nullptr),
123 base_address_(nullptr),
124 program_headers_start_(nullptr),
125 section_headers_start_(nullptr),
126 dynamic_program_header_(nullptr),
127 dynamic_section_start_(nullptr),
128 symtab_section_start_(nullptr),
129 dynsym_section_start_(nullptr),
130 strtab_section_start_(nullptr),
131 dynstr_section_start_(nullptr),
132 hash_section_start_(nullptr),
133 symtab_symbol_table_(nullptr),
134 dynsym_symbol_table_(nullptr),
135 jit_elf_image_(nullptr),
Igor Murashkin46774762014-10-22 11:37:02 -0700136 jit_gdb_entry_(nullptr),
137 requested_base_(requested_base) {
Alex Light3470ab42014-06-18 10:35:45 -0700138 CHECK(file != nullptr);
Brian Carlstromc1409452014-02-26 14:06:23 -0800139}
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800140
Tong Shen62d1ca32014-09-03 17:24:56 -0700141template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
142 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
143 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
144ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
145 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>*
146 ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
147 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
148 ::Open(File* file, bool writable, bool program_header_only,
Igor Murashkin46774762014-10-22 11:37:02 -0700149 std::string* error_msg, uint8_t* requested_base) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700150 std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
151 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
152 elf_file(new ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
153 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Igor Murashkin46774762014-10-22 11:37:02 -0700154 (file, writable, program_header_only, requested_base));
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800155 int prot;
156 int flags;
Alex Light3470ab42014-06-18 10:35:45 -0700157 if (writable) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800158 prot = PROT_READ | PROT_WRITE;
159 flags = MAP_SHARED;
160 } else {
161 prot = PROT_READ;
162 flags = MAP_PRIVATE;
163 }
Alex Light3470ab42014-06-18 10:35:45 -0700164 if (!elf_file->Setup(prot, flags, error_msg)) {
165 return nullptr;
166 }
167 return elf_file.release();
168}
169
Tong Shen62d1ca32014-09-03 17:24:56 -0700170template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
171 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
172 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
173ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
174 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>*
175 ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
176 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
177 ::Open(File* file, int prot, int flags, std::string* error_msg) {
178 std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
179 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
180 elf_file(new ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
181 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Igor Murashkin46774762014-10-22 11:37:02 -0700182 (file, (prot & PROT_WRITE) == PROT_WRITE, /*program_header_only*/false,
183 /*requested_base*/nullptr));
Alex Light3470ab42014-06-18 10:35:45 -0700184 if (!elf_file->Setup(prot, flags, error_msg)) {
185 return nullptr;
186 }
187 return elf_file.release();
188}
189
Tong Shen62d1ca32014-09-03 17:24:56 -0700190template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
191 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
192 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
193bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
194 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
195 ::Setup(int prot, int flags, std::string* error_msg) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800196 int64_t temp_file_length = file_->GetLength();
197 if (temp_file_length < 0) {
198 errno = -temp_file_length;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700199 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
200 file_->GetPath().c_str(), file_->Fd(), strerror(errno));
Brian Carlstrom265091e2013-01-30 14:08:26 -0800201 return false;
202 }
Ian Rogerscdfcf372014-01-23 20:38:36 -0800203 size_t file_length = static_cast<size_t>(temp_file_length);
Tong Shen62d1ca32014-09-03 17:24:56 -0700204 if (file_length < sizeof(Elf_Ehdr)) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800205 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF header of "
Tong Shen62d1ca32014-09-03 17:24:56 -0700206 "%zd bytes: '%s'", file_length, sizeof(Elf_Ehdr),
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700207 file_->GetPath().c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800208 return false;
209 }
210
Brian Carlstromc1409452014-02-26 14:06:23 -0800211 if (program_header_only_) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800212 // first just map ELF header to get program header size information
Tong Shen62d1ca32014-09-03 17:24:56 -0700213 size_t elf_header_size = sizeof(Elf_Ehdr);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700214 if (!SetMap(MemMap::MapFile(elf_header_size, prot, flags, file_->Fd(), 0,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800215 file_->GetPath().c_str(), error_msg),
216 error_msg)) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800217 return false;
218 }
219 // then remap to cover program header
220 size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum);
Brian Carlstrom3a223612013-10-10 17:18:24 -0700221 if (file_length < program_header_size) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800222 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program "
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700223 "header of %zd bytes: '%s'", file_length,
Tong Shen62d1ca32014-09-03 17:24:56 -0700224 sizeof(Elf_Ehdr), file_->GetPath().c_str());
Brian Carlstrom3a223612013-10-10 17:18:24 -0700225 return false;
226 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700227 if (!SetMap(MemMap::MapFile(program_header_size, prot, flags, file_->Fd(), 0,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800228 file_->GetPath().c_str(), error_msg),
229 error_msg)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700230 *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800231 return false;
232 }
233 } else {
234 // otherwise map entire file
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700235 if (!SetMap(MemMap::MapFile(file_->GetLength(), prot, flags, file_->Fd(), 0,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800236 file_->GetPath().c_str(), error_msg),
237 error_msg)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700238 *error_msg = StringPrintf("Failed to map ELF file: %s", error_msg->c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800239 return false;
240 }
241 }
242
Andreas Gampedaab38c2014-09-12 18:38:24 -0700243 if (program_header_only_) {
244 program_headers_start_ = Begin() + GetHeader().e_phoff;
245 } else {
246 if (!CheckAndSet(GetHeader().e_phoff, "program headers", &program_headers_start_, error_msg)) {
247 return false;
248 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800249
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800250 // Setup section headers.
Andreas Gampedaab38c2014-09-12 18:38:24 -0700251 if (!CheckAndSet(GetHeader().e_shoff, "section headers", &section_headers_start_, error_msg)) {
252 return false;
253 }
254
255 // Find shstrtab.
Tong Shen62d1ca32014-09-03 17:24:56 -0700256 Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700257 if (shstrtab_section_header == nullptr) {
258 *error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'",
259 file_->GetPath().c_str());
260 return false;
261 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800262
263 // Find .dynamic section info from program header
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000264 dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC);
Alex Light3470ab42014-06-18 10:35:45 -0700265 if (dynamic_program_header_ == nullptr) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700266 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
267 file_->GetPath().c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800268 return false;
269 }
270
Andreas Gampedaab38c2014-09-12 18:38:24 -0700271 if (!CheckAndSet(GetDynamicProgramHeader().p_offset, "dynamic section",
Ian Rogers13735952014-10-08 12:43:28 -0700272 reinterpret_cast<uint8_t**>(&dynamic_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700273 return false;
274 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800275
276 // Find other sections from section headers
Tong Shen62d1ca32014-09-03 17:24:56 -0700277 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
278 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700279 if (section_header == nullptr) {
280 *error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'",
281 i, file_->GetPath().c_str());
282 return false;
283 }
284 switch (section_header->sh_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000285 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700286 if (!CheckAndSet(section_header->sh_offset, "symtab",
Ian Rogers13735952014-10-08 12:43:28 -0700287 reinterpret_cast<uint8_t**>(&symtab_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700288 return false;
289 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800290 break;
291 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000292 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700293 if (!CheckAndSet(section_header->sh_offset, "dynsym",
Ian Rogers13735952014-10-08 12:43:28 -0700294 reinterpret_cast<uint8_t**>(&dynsym_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700295 return false;
296 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800297 break;
298 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000299 case SHT_STRTAB: {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800300 // TODO: base these off of sh_link from .symtab and .dynsym above
Andreas Gampedaab38c2014-09-12 18:38:24 -0700301 if ((section_header->sh_flags & SHF_ALLOC) != 0) {
302 // Check that this is named ".dynstr" and ignore otherwise.
303 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
304 if (strncmp(".dynstr", header_name, 8) == 0) {
305 if (!CheckAndSet(section_header->sh_offset, "dynstr",
Ian Rogers13735952014-10-08 12:43:28 -0700306 reinterpret_cast<uint8_t**>(&dynstr_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700307 return false;
308 }
309 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800310 } else {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700311 // Check that this is named ".strtab" and ignore otherwise.
312 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
313 if (strncmp(".strtab", header_name, 8) == 0) {
314 if (!CheckAndSet(section_header->sh_offset, "strtab",
Ian Rogers13735952014-10-08 12:43:28 -0700315 reinterpret_cast<uint8_t**>(&strtab_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700316 return false;
317 }
318 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800319 }
320 break;
321 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000322 case SHT_DYNAMIC: {
Ian Rogers13735952014-10-08 12:43:28 -0700323 if (reinterpret_cast<uint8_t*>(dynamic_section_start_) !=
Andreas Gampedaab38c2014-09-12 18:38:24 -0700324 Begin() + section_header->sh_offset) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800325 LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in "
Brian Carlstrom265091e2013-01-30 14:08:26 -0800326 << file_->GetPath() << ": " << std::hex
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800327 << reinterpret_cast<void*>(dynamic_section_start_)
Andreas Gampedaab38c2014-09-12 18:38:24 -0700328 << " != " << reinterpret_cast<void*>(Begin() + section_header->sh_offset);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800329 return false;
330 }
331 break;
332 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000333 case SHT_HASH: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700334 if (!CheckAndSet(section_header->sh_offset, "hash section",
Ian Rogers13735952014-10-08 12:43:28 -0700335 reinterpret_cast<uint8_t**>(&hash_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700336 return false;
337 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800338 break;
339 }
340 }
341 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700342
343 // Check for the existence of some sections.
344 if (!CheckSectionsExist(error_msg)) {
345 return false;
346 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800347 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700348
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800349 return true;
350}
351
Tong Shen62d1ca32014-09-03 17:24:56 -0700352template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
353 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
354 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
355ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
356 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
357 ::~ElfFileImpl() {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800358 STLDeleteElements(&segments_);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800359 delete symtab_symbol_table_;
360 delete dynsym_symbol_table_;
Mark Mendellae9fd932014-02-10 16:14:35 -0800361 delete jit_elf_image_;
362 if (jit_gdb_entry_) {
363 UnregisterCodeEntry(jit_gdb_entry_);
364 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800365}
366
Tong Shen62d1ca32014-09-03 17:24:56 -0700367template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
368 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
369 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
370bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
371 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
372 ::CheckAndSet(Elf32_Off offset, const char* label,
Ian Rogers13735952014-10-08 12:43:28 -0700373 uint8_t** target, std::string* error_msg) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700374 if (Begin() + offset >= End()) {
375 *error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label,
376 file_->GetPath().c_str());
377 return false;
378 }
379 *target = Begin() + offset;
380 return true;
381}
382
Tong Shen62d1ca32014-09-03 17:24:56 -0700383template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
384 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
385 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
386bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
387 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700388 ::CheckSectionsLinked(const uint8_t* source, const uint8_t* target) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700389 // Only works in whole-program mode, as we need to iterate over the sections.
390 // Note that we normally can't search by type, as duplicates are allowed for most section types.
391 if (program_header_only_) {
392 return true;
393 }
394
Tong Shen62d1ca32014-09-03 17:24:56 -0700395 Elf_Shdr* source_section = nullptr;
396 Elf_Word target_index = 0;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700397 bool target_found = false;
Tong Shen62d1ca32014-09-03 17:24:56 -0700398 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
399 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700400
401 if (Begin() + section_header->sh_offset == source) {
402 // Found the source.
403 source_section = section_header;
404 if (target_index) {
405 break;
406 }
407 } else if (Begin() + section_header->sh_offset == target) {
408 target_index = i;
409 target_found = true;
410 if (source_section != nullptr) {
411 break;
412 }
413 }
414 }
415
416 return target_found && source_section != nullptr && source_section->sh_link == target_index;
417}
418
Tong Shen62d1ca32014-09-03 17:24:56 -0700419template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
420 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
421 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
422bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
423 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
424 ::CheckSectionsExist(std::string* error_msg) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700425 if (!program_header_only_) {
426 // If in full mode, need section headers.
427 if (section_headers_start_ == nullptr) {
428 *error_msg = StringPrintf("No section headers in ELF file: '%s'", file_->GetPath().c_str());
429 return false;
430 }
431 }
432
433 // This is redundant, but defensive.
434 if (dynamic_program_header_ == nullptr) {
435 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
436 file_->GetPath().c_str());
437 return false;
438 }
439
440 // Need a dynamic section. This is redundant, but defensive.
441 if (dynamic_section_start_ == nullptr) {
442 *error_msg = StringPrintf("Failed to find dynamic section in ELF file: '%s'",
443 file_->GetPath().c_str());
444 return false;
445 }
446
447 // Symtab validation. These is not really a hard failure, as we are currently not using the
448 // symtab internally, but it's nice to be defensive.
449 if (symtab_section_start_ != nullptr) {
450 // When there's a symtab, there should be a strtab.
451 if (strtab_section_start_ == nullptr) {
452 *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file_->GetPath().c_str());
453 return false;
454 }
455
456 // The symtab should link to the strtab.
Ian Rogers13735952014-10-08 12:43:28 -0700457 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(symtab_section_start_),
458 reinterpret_cast<const uint8_t*>(strtab_section_start_))) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700459 *error_msg = StringPrintf("Symtab is not linked to the strtab in ELF file: '%s'",
460 file_->GetPath().c_str());
461 return false;
462 }
463 }
464
465 // We always need a dynstr & dynsym.
466 if (dynstr_section_start_ == nullptr) {
467 *error_msg = StringPrintf("No dynstr in ELF file: '%s'", file_->GetPath().c_str());
468 return false;
469 }
470 if (dynsym_section_start_ == nullptr) {
471 *error_msg = StringPrintf("No dynsym in ELF file: '%s'", file_->GetPath().c_str());
472 return false;
473 }
474
475 // Need a hash section for dynamic symbol lookup.
476 if (hash_section_start_ == nullptr) {
477 *error_msg = StringPrintf("Failed to find hash section in ELF file: '%s'",
478 file_->GetPath().c_str());
479 return false;
480 }
481
482 // And the hash section should be linking to the dynsym.
Ian Rogers13735952014-10-08 12:43:28 -0700483 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(hash_section_start_),
484 reinterpret_cast<const uint8_t*>(dynsym_section_start_))) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700485 *error_msg = StringPrintf("Hash section is not linked to the dynstr in ELF file: '%s'",
486 file_->GetPath().c_str());
487 return false;
488 }
489
Andreas Gampea696c0a2014-12-10 20:51:45 -0800490 // We'd also like to confirm a shstrtab in program_header_only_ mode (else Open() does this for
491 // us). This is usually the last in an oat file, and a good indicator of whether writing was
492 // successful (or the process crashed and left garbage).
493 if (program_header_only_) {
494 // It might not be mapped, but we can compare against the file size.
495 int64_t offset = static_cast<int64_t>(GetHeader().e_shoff +
496 (GetHeader().e_shstrndx * GetHeader().e_shentsize));
497 if (offset >= file_->GetLength()) {
498 *error_msg = StringPrintf("Shstrtab is not in the mapped ELF file: '%s'",
499 file_->GetPath().c_str());
500 return false;
501 }
502 }
503
Andreas Gampedaab38c2014-09-12 18:38:24 -0700504 return true;
505}
506
Tong Shen62d1ca32014-09-03 17:24:56 -0700507template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
508 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
509 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
510bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
511 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
512 ::SetMap(MemMap* map, std::string* error_msg) {
Alex Light3470ab42014-06-18 10:35:45 -0700513 if (map == nullptr) {
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800514 // MemMap::Open should have already set an error.
515 DCHECK(!error_msg->empty());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800516 return false;
517 }
518 map_.reset(map);
Alex Light3470ab42014-06-18 10:35:45 -0700519 CHECK(map_.get() != nullptr) << file_->GetPath();
520 CHECK(map_->Begin() != nullptr) << file_->GetPath();
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800521
Tong Shen62d1ca32014-09-03 17:24:56 -0700522 header_ = reinterpret_cast<Elf_Ehdr*>(map_->Begin());
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000523 if ((ELFMAG0 != header_->e_ident[EI_MAG0])
524 || (ELFMAG1 != header_->e_ident[EI_MAG1])
525 || (ELFMAG2 != header_->e_ident[EI_MAG2])
526 || (ELFMAG3 != header_->e_ident[EI_MAG3])) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800527 *error_msg = StringPrintf("Failed to find ELF magic value %d %d %d %d in %s, found %d %d %d %d",
528 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800529 file_->GetPath().c_str(),
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000530 header_->e_ident[EI_MAG0],
531 header_->e_ident[EI_MAG1],
532 header_->e_ident[EI_MAG2],
533 header_->e_ident[EI_MAG3]);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800534 return false;
535 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700536 uint8_t elf_class = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) ? ELFCLASS64 : ELFCLASS32;
537 if (elf_class != header_->e_ident[EI_CLASS]) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800538 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d in %s, found %d",
Tong Shen62d1ca32014-09-03 17:24:56 -0700539 elf_class,
Brian Carlstromc1409452014-02-26 14:06:23 -0800540 file_->GetPath().c_str(),
541 header_->e_ident[EI_CLASS]);
542 return false;
543 }
544 if (ELFDATA2LSB != header_->e_ident[EI_DATA]) {
545 *error_msg = StringPrintf("Failed to find expected EI_DATA value %d in %s, found %d",
546 ELFDATA2LSB,
547 file_->GetPath().c_str(),
548 header_->e_ident[EI_CLASS]);
549 return false;
550 }
551 if (EV_CURRENT != header_->e_ident[EI_VERSION]) {
552 *error_msg = StringPrintf("Failed to find expected EI_VERSION value %d in %s, found %d",
553 EV_CURRENT,
554 file_->GetPath().c_str(),
555 header_->e_ident[EI_CLASS]);
556 return false;
557 }
558 if (ET_DYN != header_->e_type) {
559 *error_msg = StringPrintf("Failed to find expected e_type value %d in %s, found %d",
560 ET_DYN,
561 file_->GetPath().c_str(),
562 header_->e_type);
563 return false;
564 }
565 if (EV_CURRENT != header_->e_version) {
566 *error_msg = StringPrintf("Failed to find expected e_version value %d in %s, found %d",
567 EV_CURRENT,
568 file_->GetPath().c_str(),
569 header_->e_version);
570 return false;
571 }
572 if (0 != header_->e_entry) {
573 *error_msg = StringPrintf("Failed to find expected e_entry value %d in %s, found %d",
574 0,
575 file_->GetPath().c_str(),
Tong Shen62d1ca32014-09-03 17:24:56 -0700576 static_cast<int32_t>(header_->e_entry));
Brian Carlstromc1409452014-02-26 14:06:23 -0800577 return false;
578 }
579 if (0 == header_->e_phoff) {
580 *error_msg = StringPrintf("Failed to find non-zero e_phoff value in %s",
581 file_->GetPath().c_str());
582 return false;
583 }
584 if (0 == header_->e_shoff) {
585 *error_msg = StringPrintf("Failed to find non-zero e_shoff value in %s",
586 file_->GetPath().c_str());
587 return false;
588 }
589 if (0 == header_->e_ehsize) {
590 *error_msg = StringPrintf("Failed to find non-zero e_ehsize value in %s",
591 file_->GetPath().c_str());
592 return false;
593 }
594 if (0 == header_->e_phentsize) {
595 *error_msg = StringPrintf("Failed to find non-zero e_phentsize value in %s",
596 file_->GetPath().c_str());
597 return false;
598 }
599 if (0 == header_->e_phnum) {
600 *error_msg = StringPrintf("Failed to find non-zero e_phnum value in %s",
601 file_->GetPath().c_str());
602 return false;
603 }
604 if (0 == header_->e_shentsize) {
605 *error_msg = StringPrintf("Failed to find non-zero e_shentsize value in %s",
606 file_->GetPath().c_str());
607 return false;
608 }
609 if (0 == header_->e_shnum) {
610 *error_msg = StringPrintf("Failed to find non-zero e_shnum value in %s",
611 file_->GetPath().c_str());
612 return false;
613 }
614 if (0 == header_->e_shstrndx) {
615 *error_msg = StringPrintf("Failed to find non-zero e_shstrndx value in %s",
616 file_->GetPath().c_str());
617 return false;
618 }
619 if (header_->e_shstrndx >= header_->e_shnum) {
620 *error_msg = StringPrintf("Failed to find e_shnum value %d less than %d in %s",
621 header_->e_shstrndx,
622 header_->e_shnum,
623 file_->GetPath().c_str());
624 return false;
625 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800626
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800627 if (!program_header_only_) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800628 if (header_->e_phoff >= Size()) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700629 *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s",
630 static_cast<uint64_t>(header_->e_phoff),
Brian Carlstromc1409452014-02-26 14:06:23 -0800631 Size(),
632 file_->GetPath().c_str());
633 return false;
634 }
635 if (header_->e_shoff >= Size()) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700636 *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s",
637 static_cast<uint64_t>(header_->e_shoff),
Brian Carlstromc1409452014-02-26 14:06:23 -0800638 Size(),
639 file_->GetPath().c_str());
640 return false;
641 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800642 }
643 return true;
644}
645
Tong Shen62d1ca32014-09-03 17:24:56 -0700646template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
647 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
648 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
649Elf_Ehdr& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
650 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
651 ::GetHeader() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700652 CHECK(header_ != nullptr); // Header has been checked in SetMap. This is a sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800653 return *header_;
654}
655
Tong Shen62d1ca32014-09-03 17:24:56 -0700656template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
657 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
658 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700659uint8_t* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
Tong Shen62d1ca32014-09-03 17:24:56 -0700660 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
661 ::GetProgramHeadersStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700662 CHECK(program_headers_start_ != nullptr); // Header has been set in Setup. This is a sanity
663 // check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800664 return program_headers_start_;
665}
666
Tong Shen62d1ca32014-09-03 17:24:56 -0700667template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
668 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
669 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700670uint8_t* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
Tong Shen62d1ca32014-09-03 17:24:56 -0700671 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
672 ::GetSectionHeadersStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700673 CHECK(!program_header_only_); // Only used in "full" mode.
674 CHECK(section_headers_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800675 return section_headers_start_;
676}
677
Tong Shen62d1ca32014-09-03 17:24:56 -0700678template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
679 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
680 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
681Elf_Phdr& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
682 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
683 ::GetDynamicProgramHeader() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700684 CHECK(dynamic_program_header_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800685 return *dynamic_program_header_;
686}
687
Tong Shen62d1ca32014-09-03 17:24:56 -0700688template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
689 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
690 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
691Elf_Dyn* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
692 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
693 ::GetDynamicSectionStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700694 CHECK(dynamic_section_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800695 return dynamic_section_start_;
696}
697
Tong Shen62d1ca32014-09-03 17:24:56 -0700698template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
699 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
700 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
701Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
702 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
703 ::GetSymbolSectionStart(Elf_Word section_type) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800704 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800705 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000706 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700707 return symtab_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800708 break;
709 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000710 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700711 return dynsym_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800712 break;
713 }
714 default: {
715 LOG(FATAL) << section_type;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700716 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800717 }
718 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800719}
720
Tong Shen62d1ca32014-09-03 17:24:56 -0700721template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
722 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
723 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
724const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
725 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
726 ::GetStringSectionStart(Elf_Word section_type) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800727 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800728 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000729 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700730 return strtab_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800731 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000732 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700733 return dynstr_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800734 }
735 default: {
736 LOG(FATAL) << section_type;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700737 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800738 }
739 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800740}
741
Tong Shen62d1ca32014-09-03 17:24:56 -0700742template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
743 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
744 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
745const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
746 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
747 ::GetString(Elf_Word section_type, Elf_Word i) const {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800748 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
749 if (i == 0) {
Alex Light3470ab42014-06-18 10:35:45 -0700750 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800751 }
752 const char* string_section_start = GetStringSectionStart(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700753 if (string_section_start == nullptr) {
754 return nullptr;
755 }
756 return string_section_start + i;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800757}
758
Andreas Gampedaab38c2014-09-12 18:38:24 -0700759// WARNING: The following methods do not check for an error condition (non-existent hash section).
760// It is the caller's job to do this.
761
Tong Shen62d1ca32014-09-03 17:24:56 -0700762template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
763 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
764 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
765Elf_Word* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
766 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
767 ::GetHashSectionStart() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800768 return hash_section_start_;
769}
770
Tong Shen62d1ca32014-09-03 17:24:56 -0700771template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
772 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
773 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
774Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
775 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
776 ::GetHashBucketNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800777 return GetHashSectionStart()[0];
778}
779
Tong Shen62d1ca32014-09-03 17:24:56 -0700780template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
781 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
782 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
783Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
784 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
785 ::GetHashChainNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800786 return GetHashSectionStart()[1];
787}
788
Tong Shen62d1ca32014-09-03 17:24:56 -0700789template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
790 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
791 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
792Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
793 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
794 ::GetHashBucket(size_t i, bool* ok) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700795 if (i >= GetHashBucketNum()) {
796 *ok = false;
797 return 0;
798 }
799 *ok = true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800800 // 0 is nbucket, 1 is nchain
801 return GetHashSectionStart()[2 + i];
802}
803
Tong Shen62d1ca32014-09-03 17:24:56 -0700804template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
805 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
806 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
807Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
808 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
809 ::GetHashChain(size_t i, bool* ok) const {
Yevgeny Roubanacb01382014-11-24 13:40:56 +0600810 if (i >= GetHashChainNum()) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700811 *ok = false;
812 return 0;
813 }
814 *ok = true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800815 // 0 is nbucket, 1 is nchain, & chains are after buckets
816 return GetHashSectionStart()[2 + GetHashBucketNum() + i];
817}
818
Tong Shen62d1ca32014-09-03 17:24:56 -0700819template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
820 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
821 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
822Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
823 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
824 ::GetProgramHeaderNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800825 return GetHeader().e_phnum;
826}
827
Tong Shen62d1ca32014-09-03 17:24:56 -0700828template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
829 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
830 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
831Elf_Phdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
832 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
833 ::GetProgramHeader(Elf_Word i) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700834 CHECK_LT(i, GetProgramHeaderNum()) << file_->GetPath(); // Sanity check for caller.
Ian Rogers13735952014-10-08 12:43:28 -0700835 uint8_t* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700836 if (program_header >= End()) {
837 return nullptr; // Failure condition.
838 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700839 return reinterpret_cast<Elf_Phdr*>(program_header);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800840}
841
Tong Shen62d1ca32014-09-03 17:24:56 -0700842template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
843 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
844 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
845Elf_Phdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
846 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
847 ::FindProgamHeaderByType(Elf_Word type) const {
848 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
849 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700850 if (program_header->p_type == type) {
851 return program_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800852 }
853 }
Alex Light3470ab42014-06-18 10:35:45 -0700854 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800855}
856
Tong Shen62d1ca32014-09-03 17:24:56 -0700857template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
858 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
859 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
860Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
861 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
862 ::GetSectionHeaderNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800863 return GetHeader().e_shnum;
864}
865
Tong Shen62d1ca32014-09-03 17:24:56 -0700866template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
867 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
868 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
869Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
870 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
871 ::GetSectionHeader(Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800872 // Can only access arbitrary sections when we have the whole file, not just program header.
873 // Even if we Load(), it doesn't bring in all the sections.
874 CHECK(!program_header_only_) << file_->GetPath();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700875 if (i >= GetSectionHeaderNum()) {
876 return nullptr; // Failure condition.
877 }
Ian Rogers13735952014-10-08 12:43:28 -0700878 uint8_t* section_header = GetSectionHeadersStart() + (i * GetHeader().e_shentsize);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700879 if (section_header >= End()) {
880 return nullptr; // Failure condition.
881 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700882 return reinterpret_cast<Elf_Shdr*>(section_header);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800883}
884
Tong Shen62d1ca32014-09-03 17:24:56 -0700885template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
886 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
887 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
888Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
889 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
890 ::FindSectionByType(Elf_Word type) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800891 // Can only access arbitrary sections when we have the whole file, not just program header.
892 // We could change this to switch on known types if they were detected during loading.
893 CHECK(!program_header_only_) << file_->GetPath();
Tong Shen62d1ca32014-09-03 17:24:56 -0700894 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
895 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700896 if (section_header->sh_type == type) {
897 return section_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800898 }
899 }
Alex Light3470ab42014-06-18 10:35:45 -0700900 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800901}
902
903// from bionic
Brian Carlstrom265091e2013-01-30 14:08:26 -0800904static unsigned elfhash(const char *_name) {
905 const unsigned char *name = (const unsigned char *) _name;
906 unsigned h = 0, g;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800907
Brian Carlstromdf629502013-07-17 22:39:56 -0700908 while (*name) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800909 h = (h << 4) + *name++;
910 g = h & 0xf0000000;
911 h ^= g;
912 h ^= g >> 24;
913 }
914 return h;
915}
916
Tong Shen62d1ca32014-09-03 17:24:56 -0700917template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
918 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
919 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
920Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
921 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
922 ::GetSectionNameStringSection() const {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800923 return GetSectionHeader(GetHeader().e_shstrndx);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800924}
925
Tong Shen62d1ca32014-09-03 17:24:56 -0700926template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
927 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
928 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700929const uint8_t* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
Tong Shen62d1ca32014-09-03 17:24:56 -0700930 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
931 ::FindDynamicSymbolAddress(const std::string& symbol_name) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700932 // Check that we have a hash section.
933 if (GetHashSectionStart() == nullptr) {
934 return nullptr; // Failure condition.
935 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700936 const Elf_Sym* sym = FindDynamicSymbol(symbol_name);
Alex Light3470ab42014-06-18 10:35:45 -0700937 if (sym != nullptr) {
Igor Murashkin46774762014-10-22 11:37:02 -0700938 // TODO: we need to change this to calculate base_address_ in ::Open,
939 // otherwise it will be wrongly 0 if ::Load has not yet been called.
Alex Light3470ab42014-06-18 10:35:45 -0700940 return base_address_ + sym->st_value;
941 } else {
942 return nullptr;
943 }
944}
945
Andreas Gampedaab38c2014-09-12 18:38:24 -0700946// WARNING: Only called from FindDynamicSymbolAddress. Elides check for hash section.
Tong Shen62d1ca32014-09-03 17:24:56 -0700947template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
948 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
949 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
950const Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
951 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
952 ::FindDynamicSymbol(const std::string& symbol_name) const {
Andreas Gampec48b2062014-09-08 23:39:45 -0700953 if (GetHashBucketNum() == 0) {
954 // No dynamic symbols at all.
955 return nullptr;
956 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700957 Elf_Word hash = elfhash(symbol_name.c_str());
958 Elf_Word bucket_index = hash % GetHashBucketNum();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700959 bool ok;
Tong Shen62d1ca32014-09-03 17:24:56 -0700960 Elf_Word symbol_and_chain_index = GetHashBucket(bucket_index, &ok);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700961 if (!ok) {
962 return nullptr;
963 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800964 while (symbol_and_chain_index != 0 /* STN_UNDEF */) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700965 Elf_Sym* symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700966 if (symbol == nullptr) {
967 return nullptr; // Failure condition.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800968 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700969 const char* name = GetString(SHT_DYNSYM, symbol->st_name);
970 if (symbol_name == name) {
971 return symbol;
972 }
973 symbol_and_chain_index = GetHashChain(symbol_and_chain_index, &ok);
974 if (!ok) {
975 return nullptr;
976 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800977 }
Alex Light3470ab42014-06-18 10:35:45 -0700978 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800979}
980
Tong Shen62d1ca32014-09-03 17:24:56 -0700981template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
982 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
983 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
984bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
985 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
986 ::IsSymbolSectionType(Elf_Word section_type) {
987 return ((section_type == SHT_SYMTAB) || (section_type == SHT_DYNSYM));
988}
989
990template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
991 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
992 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
993Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
994 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
995 ::GetSymbolNum(Elf_Shdr& section_header) const {
Brian Carlstromc1409452014-02-26 14:06:23 -0800996 CHECK(IsSymbolSectionType(section_header.sh_type))
997 << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800998 CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath();
999 return section_header.sh_size / section_header.sh_entsize;
1000}
1001
Tong Shen62d1ca32014-09-03 17:24:56 -07001002template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1003 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1004 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1005Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1006 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1007 ::GetSymbol(Elf_Word section_type,
1008 Elf_Word i) const {
1009 Elf_Sym* sym_start = GetSymbolSectionStart(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001010 if (sym_start == nullptr) {
1011 return nullptr;
1012 }
1013 return sym_start + i;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001014}
1015
Tong Shen62d1ca32014-09-03 17:24:56 -07001016template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1017 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1018 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1019typename ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1020 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1021 ::SymbolTable** ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1022 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1023 ::GetSymbolTable(Elf_Word section_type) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001024 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
1025 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001026 case SHT_SYMTAB: {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001027 return &symtab_symbol_table_;
1028 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001029 case SHT_DYNSYM: {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001030 return &dynsym_symbol_table_;
1031 }
1032 default: {
1033 LOG(FATAL) << section_type;
Alex Light3470ab42014-06-18 10:35:45 -07001034 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001035 }
1036 }
1037}
1038
Tong Shen62d1ca32014-09-03 17:24:56 -07001039template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1040 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1041 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1042Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1043 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1044 ::FindSymbolByName(Elf_Word section_type,
1045 const std::string& symbol_name,
1046 bool build_map) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001047 CHECK(!program_header_only_) << file_->GetPath();
1048 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001049
1050 SymbolTable** symbol_table = GetSymbolTable(section_type);
Alex Light3470ab42014-06-18 10:35:45 -07001051 if (*symbol_table != nullptr || build_map) {
1052 if (*symbol_table == nullptr) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001053 DCHECK(build_map);
1054 *symbol_table = new SymbolTable;
Tong Shen62d1ca32014-09-03 17:24:56 -07001055 Elf_Shdr* symbol_section = FindSectionByType(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001056 if (symbol_section == nullptr) {
1057 return nullptr; // Failure condition.
1058 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001059 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001060 if (string_section == nullptr) {
1061 return nullptr; // Failure condition.
1062 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001063 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001064 Elf_Sym* symbol = GetSymbol(section_type, i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001065 if (symbol == nullptr) {
1066 return nullptr; // Failure condition.
1067 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001068 unsigned char type = (sizeof(Elf_Addr) == sizeof(Elf64_Addr))
1069 ? ELF64_ST_TYPE(symbol->st_info)
1070 : ELF32_ST_TYPE(symbol->st_info);
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001071 if (type == STT_NOTYPE) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001072 continue;
1073 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001074 const char* name = GetString(*string_section, symbol->st_name);
Alex Light3470ab42014-06-18 10:35:45 -07001075 if (name == nullptr) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001076 continue;
1077 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001078 std::pair<typename SymbolTable::iterator, bool> result =
Andreas Gampedaab38c2014-09-12 18:38:24 -07001079 (*symbol_table)->insert(std::make_pair(name, symbol));
Brian Carlstrom265091e2013-01-30 14:08:26 -08001080 if (!result.second) {
1081 // If a duplicate, make sure it has the same logical value. Seen on x86.
Andreas Gampedaab38c2014-09-12 18:38:24 -07001082 if ((symbol->st_value != result.first->second->st_value) ||
1083 (symbol->st_size != result.first->second->st_size) ||
1084 (symbol->st_info != result.first->second->st_info) ||
1085 (symbol->st_other != result.first->second->st_other) ||
1086 (symbol->st_shndx != result.first->second->st_shndx)) {
1087 return nullptr; // Failure condition.
1088 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001089 }
1090 }
1091 }
Alex Light3470ab42014-06-18 10:35:45 -07001092 CHECK(*symbol_table != nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07001093 typename SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001094 if (it == (*symbol_table)->end()) {
Alex Light3470ab42014-06-18 10:35:45 -07001095 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001096 }
1097 return it->second;
1098 }
1099
1100 // Fall back to linear search
Tong Shen62d1ca32014-09-03 17:24:56 -07001101 Elf_Shdr* symbol_section = FindSectionByType(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001102 if (symbol_section == nullptr) {
1103 return nullptr;
1104 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001105 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001106 if (string_section == nullptr) {
1107 return nullptr;
1108 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001109 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001110 Elf_Sym* symbol = GetSymbol(section_type, i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001111 if (symbol == nullptr) {
1112 return nullptr; // Failure condition.
1113 }
1114 const char* name = GetString(*string_section, symbol->st_name);
Alex Light3470ab42014-06-18 10:35:45 -07001115 if (name == nullptr) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001116 continue;
1117 }
1118 if (symbol_name == name) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001119 return symbol;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001120 }
1121 }
Alex Light3470ab42014-06-18 10:35:45 -07001122 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001123}
1124
Tong Shen62d1ca32014-09-03 17:24:56 -07001125template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1126 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1127 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1128Elf_Addr ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1129 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1130 ::FindSymbolAddress(Elf_Word section_type,
1131 const std::string& symbol_name,
1132 bool build_map) {
1133 Elf_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
Alex Light3470ab42014-06-18 10:35:45 -07001134 if (symbol == nullptr) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001135 return 0;
1136 }
1137 return symbol->st_value;
1138}
1139
Tong Shen62d1ca32014-09-03 17:24:56 -07001140template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1141 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1142 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1143const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1144 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1145 ::GetString(Elf_Shdr& string_section, Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001146 CHECK(!program_header_only_) << file_->GetPath();
1147 // TODO: remove this static_cast from enum when using -std=gnu++0x
Tong Shen62d1ca32014-09-03 17:24:56 -07001148 if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001149 return nullptr; // Failure condition.
1150 }
1151 if (i >= string_section.sh_size) {
1152 return nullptr;
1153 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001154 if (i == 0) {
Alex Light3470ab42014-06-18 10:35:45 -07001155 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001156 }
Ian Rogers13735952014-10-08 12:43:28 -07001157 uint8_t* strings = Begin() + string_section.sh_offset;
1158 uint8_t* string = strings + i;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001159 if (string >= End()) {
1160 return nullptr;
1161 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001162 return reinterpret_cast<const char*>(string);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001163}
1164
Tong Shen62d1ca32014-09-03 17:24:56 -07001165template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1166 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1167 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1168Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1169 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1170 ::GetDynamicNum() const {
1171 return GetDynamicProgramHeader().p_filesz / sizeof(Elf_Dyn);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001172}
1173
Tong Shen62d1ca32014-09-03 17:24:56 -07001174template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1175 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1176 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1177Elf_Dyn& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1178 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1179 ::GetDynamic(Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001180 CHECK_LT(i, GetDynamicNum()) << file_->GetPath();
1181 return *(GetDynamicSectionStart() + i);
1182}
1183
Tong Shen62d1ca32014-09-03 17:24:56 -07001184template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1185 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1186 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1187Elf_Dyn* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1188 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1189 ::FindDynamicByType(Elf_Sword type) const {
1190 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1191 Elf_Dyn* dyn = &GetDynamic(i);
Alex Light53cb16b2014-06-12 11:26:29 -07001192 if (dyn->d_tag == type) {
1193 return dyn;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001194 }
1195 }
Alex Light53cb16b2014-06-12 11:26:29 -07001196 return NULL;
1197}
1198
Tong Shen62d1ca32014-09-03 17:24:56 -07001199template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1200 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1201 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1202Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1203 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1204 ::FindDynamicValueByType(Elf_Sword type) const {
1205 Elf_Dyn* dyn = FindDynamicByType(type);
Alex Light53cb16b2014-06-12 11:26:29 -07001206 if (dyn == NULL) {
1207 return 0;
1208 } else {
1209 return dyn->d_un.d_val;
1210 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001211}
1212
Tong Shen62d1ca32014-09-03 17:24:56 -07001213template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1214 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1215 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1216Elf_Rel* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1217 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1218 ::GetRelSectionStart(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001219 CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Tong Shen62d1ca32014-09-03 17:24:56 -07001220 return reinterpret_cast<Elf_Rel*>(Begin() + section_header.sh_offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001221}
1222
Tong Shen62d1ca32014-09-03 17:24:56 -07001223template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1224 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1225 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1226Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1227 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1228 ::GetRelNum(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001229 CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001230 CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath();
1231 return section_header.sh_size / section_header.sh_entsize;
1232}
1233
Tong Shen62d1ca32014-09-03 17:24:56 -07001234template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1235 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1236 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1237Elf_Rel& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1238 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1239 ::GetRel(Elf_Shdr& section_header, Elf_Word i) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001240 CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001241 CHECK_LT(i, GetRelNum(section_header)) << file_->GetPath();
1242 return *(GetRelSectionStart(section_header) + i);
1243}
1244
Tong Shen62d1ca32014-09-03 17:24:56 -07001245template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1246 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1247 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1248Elf_Rela* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1249 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1250 ::GetRelaSectionStart(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001251 CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Tong Shen62d1ca32014-09-03 17:24:56 -07001252 return reinterpret_cast<Elf_Rela*>(Begin() + section_header.sh_offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001253}
1254
Tong Shen62d1ca32014-09-03 17:24:56 -07001255template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1256 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1257 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1258Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1259 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1260 ::GetRelaNum(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001261 CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001262 return section_header.sh_size / section_header.sh_entsize;
1263}
1264
Tong Shen62d1ca32014-09-03 17:24:56 -07001265template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1266 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1267 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1268Elf_Rela& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1269 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1270 ::GetRela(Elf_Shdr& section_header, Elf_Word i) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001271 CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001272 CHECK_LT(i, GetRelaNum(section_header)) << file_->GetPath();
1273 return *(GetRelaSectionStart(section_header) + i);
1274}
1275
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001276// Base on bionic phdr_table_get_load_size
Tong Shen62d1ca32014-09-03 17:24:56 -07001277template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1278 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1279 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1280size_t ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1281 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1282 ::GetLoadedSize() const {
1283 Elf_Addr min_vaddr = 0xFFFFFFFFu;
1284 Elf_Addr max_vaddr = 0x00000000u;
1285 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1286 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001287 if (program_header->p_type != PT_LOAD) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001288 continue;
1289 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001290 Elf_Addr begin_vaddr = program_header->p_vaddr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001291 if (begin_vaddr < min_vaddr) {
1292 min_vaddr = begin_vaddr;
1293 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001294 Elf_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001295 if (end_vaddr > max_vaddr) {
1296 max_vaddr = end_vaddr;
1297 }
1298 }
1299 min_vaddr = RoundDown(min_vaddr, kPageSize);
1300 max_vaddr = RoundUp(max_vaddr, kPageSize);
1301 CHECK_LT(min_vaddr, max_vaddr) << file_->GetPath();
1302 size_t loaded_size = max_vaddr - min_vaddr;
1303 return loaded_size;
1304}
1305
Tong Shen62d1ca32014-09-03 17:24:56 -07001306template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1307 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1308 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1309bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1310 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1311 ::Load(bool executable, std::string* error_msg) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001312 CHECK(program_header_only_) << file_->GetPath();
Andreas Gampe91268c12014-04-03 17:50:24 -07001313
1314 if (executable) {
Andreas Gampe6f611412015-01-21 22:25:24 -08001315 InstructionSet elf_ISA = GetInstructionSetFromELF(GetHeader().e_machine, GetHeader().e_flags);
Andreas Gampe91268c12014-04-03 17:50:24 -07001316 if (elf_ISA != kRuntimeISA) {
1317 std::ostringstream oss;
1318 oss << "Expected ISA " << kRuntimeISA << " but found " << elf_ISA;
1319 *error_msg = oss.str();
1320 return false;
1321 }
1322 }
1323
Jim_Guoa62a5882014-04-28 11:11:57 +08001324 bool reserved = false;
Tong Shen62d1ca32014-09-03 17:24:56 -07001325 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1326 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001327 if (program_header == nullptr) {
1328 *error_msg = StringPrintf("No program header for entry %d in ELF file %s.",
1329 i, file_->GetPath().c_str());
1330 return false;
1331 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001332
1333 // Record .dynamic header information for later use
Andreas Gampedaab38c2014-09-12 18:38:24 -07001334 if (program_header->p_type == PT_DYNAMIC) {
1335 dynamic_program_header_ = program_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001336 continue;
1337 }
1338
1339 // Not something to load, move on.
Andreas Gampedaab38c2014-09-12 18:38:24 -07001340 if (program_header->p_type != PT_LOAD) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001341 continue;
1342 }
1343
1344 // Found something to load.
1345
Jim_Guoa62a5882014-04-28 11:11:57 +08001346 // Before load the actual segments, reserve a contiguous chunk
1347 // of required size and address for all segments, but with no
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001348 // permissions. We'll then carve that up with the proper
1349 // permissions as we load the actual segments. If p_vaddr is
1350 // non-zero, the segments require the specific address specified,
1351 // which either was specified in the file because we already set
1352 // base_address_ after the first zero segment).
Ian Rogerscdfcf372014-01-23 20:38:36 -08001353 int64_t temp_file_length = file_->GetLength();
1354 if (temp_file_length < 0) {
1355 errno = -temp_file_length;
1356 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
1357 file_->GetPath().c_str(), file_->Fd(), strerror(errno));
1358 return false;
1359 }
1360 size_t file_length = static_cast<size_t>(temp_file_length);
Jim_Guoa62a5882014-04-28 11:11:57 +08001361 if (!reserved) {
Igor Murashkin46774762014-10-22 11:37:02 -07001362 uint8_t* reserve_base = reinterpret_cast<uint8_t*>(program_header->p_vaddr);
1363 uint8_t* reserve_base_override = reserve_base;
1364 // Override the base (e.g. when compiling with --compile-pic)
1365 if (requested_base_ != nullptr) {
1366 reserve_base_override = requested_base_;
1367 }
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001368 std::string reservation_name("ElfFile reservation for ");
1369 reservation_name += file_->GetPath();
Ian Rogers700a4022014-05-19 16:49:03 -07001370 std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
Igor Murashkin46774762014-10-22 11:37:02 -07001371 reserve_base_override,
Vladimir Marko5c42c292015-02-25 12:02:49 +00001372 GetLoadedSize(), PROT_NONE, false, false,
Jim_Guoa62a5882014-04-28 11:11:57 +08001373 error_msg));
Brian Carlstromc1409452014-02-26 14:06:23 -08001374 if (reserve.get() == nullptr) {
1375 *error_msg = StringPrintf("Failed to allocate %s: %s",
1376 reservation_name.c_str(), error_msg->c_str());
1377 return false;
1378 }
Jim_Guoa62a5882014-04-28 11:11:57 +08001379 reserved = true;
Igor Murashkin46774762014-10-22 11:37:02 -07001380
1381 // Base address is the difference of actual mapped location and the p_vaddr
1382 base_address_ = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(reserve->Begin())
1383 - reinterpret_cast<uintptr_t>(reserve_base));
1384 // By adding the p_vaddr of a section/symbol to base_address_ we will always get the
1385 // dynamic memory address of where that object is actually mapped
1386 //
1387 // TODO: base_address_ needs to be calculated in ::Open, otherwise
1388 // FindDynamicSymbolAddress returns the wrong values until Load is called.
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001389 segments_.push_back(reserve.release());
1390 }
1391 // empty segment, nothing to map
Andreas Gampedaab38c2014-09-12 18:38:24 -07001392 if (program_header->p_memsz == 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001393 continue;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001394 }
Ian Rogers13735952014-10-08 12:43:28 -07001395 uint8_t* p_vaddr = base_address_ + program_header->p_vaddr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001396 int prot = 0;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001397 if (executable && ((program_header->p_flags & PF_X) != 0)) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001398 prot |= PROT_EXEC;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001399 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001400 if ((program_header->p_flags & PF_W) != 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001401 prot |= PROT_WRITE;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001402 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001403 if ((program_header->p_flags & PF_R) != 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001404 prot |= PROT_READ;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001405 }
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -07001406 int flags = 0;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001407 if (writable_) {
1408 prot |= PROT_WRITE;
1409 flags |= MAP_SHARED;
1410 } else {
1411 flags |= MAP_PRIVATE;
1412 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001413 if (program_header->p_filesz > program_header->p_memsz) {
1414 *error_msg = StringPrintf("Invalid p_filesz > p_memsz (%" PRIu64 " > %" PRIu64 "): %s",
1415 static_cast<uint64_t>(program_header->p_filesz),
1416 static_cast<uint64_t>(program_header->p_memsz),
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001417 file_->GetPath().c_str());
Brian Carlstrom3a223612013-10-10 17:18:24 -07001418 return false;
1419 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001420 if (program_header->p_filesz < program_header->p_memsz &&
1421 !IsAligned<kPageSize>(program_header->p_filesz)) {
1422 *error_msg = StringPrintf("Unsupported unaligned p_filesz < p_memsz (%" PRIu64
1423 " < %" PRIu64 "): %s",
1424 static_cast<uint64_t>(program_header->p_filesz),
1425 static_cast<uint64_t>(program_header->p_memsz),
1426 file_->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001427 return false;
1428 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001429 if (file_length < (program_header->p_offset + program_header->p_filesz)) {
1430 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment "
1431 "%d of %" PRIu64 " bytes: '%s'", file_length, i,
1432 static_cast<uint64_t>(program_header->p_offset + program_header->p_filesz),
1433 file_->GetPath().c_str());
Brian Carlstromc1409452014-02-26 14:06:23 -08001434 return false;
1435 }
Vladimir Marko5c42c292015-02-25 12:02:49 +00001436 if (program_header->p_filesz != 0u) {
1437 std::unique_ptr<MemMap> segment(
1438 MemMap::MapFileAtAddress(p_vaddr,
1439 program_header->p_filesz,
1440 prot, flags, file_->Fd(),
1441 program_header->p_offset,
1442 true, // implies MAP_FIXED
1443 file_->GetPath().c_str(),
1444 error_msg));
1445 if (segment.get() == nullptr) {
1446 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s",
1447 i, file_->GetPath().c_str(), error_msg->c_str());
1448 return false;
1449 }
1450 if (segment->Begin() != p_vaddr) {
1451 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, "
1452 "instead mapped to %p",
1453 i, file_->GetPath().c_str(), p_vaddr, segment->Begin());
1454 return false;
1455 }
1456 segments_.push_back(segment.release());
1457 }
1458 if (program_header->p_filesz < program_header->p_memsz) {
1459 std::string name = StringPrintf("Zero-initialized segment %" PRIu64 " of ELF file %s",
1460 static_cast<uint64_t>(i), file_->GetPath().c_str());
1461 std::unique_ptr<MemMap> segment(
1462 MemMap::MapAnonymous(name.c_str(),
1463 p_vaddr + program_header->p_filesz,
1464 program_header->p_memsz - program_header->p_filesz,
1465 prot, false, true /* reuse */, error_msg));
1466 if (segment == nullptr) {
1467 *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s: %s",
1468 i, file_->GetPath().c_str(), error_msg->c_str());
1469 return false;
1470 }
1471 if (segment->Begin() != p_vaddr) {
1472 *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s "
1473 "at expected address %p, instead mapped to %p",
1474 i, file_->GetPath().c_str(), p_vaddr, segment->Begin());
1475 return false;
1476 }
1477 segments_.push_back(segment.release());
1478 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001479 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001480
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001481 // Now that we are done loading, .dynamic should be in memory to find .dynstr, .dynsym, .hash
Ian Rogers13735952014-10-08 12:43:28 -07001482 uint8_t* dsptr = base_address_ + GetDynamicProgramHeader().p_vaddr;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001483 if ((dsptr < Begin() || dsptr >= End()) && !ValidPointer(dsptr)) {
1484 *error_msg = StringPrintf("dynamic section address invalid in ELF file %s",
1485 file_->GetPath().c_str());
1486 return false;
1487 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001488 dynamic_section_start_ = reinterpret_cast<Elf_Dyn*>(dsptr);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001489
Tong Shen62d1ca32014-09-03 17:24:56 -07001490 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1491 Elf_Dyn& elf_dyn = GetDynamic(i);
Ian Rogers13735952014-10-08 12:43:28 -07001492 uint8_t* d_ptr = base_address_ + elf_dyn.d_un.d_ptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001493 switch (elf_dyn.d_tag) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001494 case DT_HASH: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001495 if (!ValidPointer(d_ptr)) {
1496 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1497 d_ptr, file_->GetPath().c_str());
1498 return false;
1499 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001500 hash_section_start_ = reinterpret_cast<Elf_Word*>(d_ptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001501 break;
1502 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001503 case DT_STRTAB: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001504 if (!ValidPointer(d_ptr)) {
1505 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1506 d_ptr, file_->GetPath().c_str());
1507 return false;
1508 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001509 dynstr_section_start_ = reinterpret_cast<char*>(d_ptr);
1510 break;
1511 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001512 case DT_SYMTAB: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001513 if (!ValidPointer(d_ptr)) {
1514 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1515 d_ptr, file_->GetPath().c_str());
1516 return false;
1517 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001518 dynsym_section_start_ = reinterpret_cast<Elf_Sym*>(d_ptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001519 break;
1520 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001521 case DT_NULL: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001522 if (GetDynamicNum() != i+1) {
1523 *error_msg = StringPrintf("DT_NULL found after %d .dynamic entries, "
1524 "expected %d as implied by size of PT_DYNAMIC segment in %s",
1525 i + 1, GetDynamicNum(), file_->GetPath().c_str());
1526 return false;
1527 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001528 break;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001529 }
1530 }
1531 }
1532
Andreas Gampedaab38c2014-09-12 18:38:24 -07001533 // Check for the existence of some sections.
1534 if (!CheckSectionsExist(error_msg)) {
1535 return false;
1536 }
1537
Mark Mendellae9fd932014-02-10 16:14:35 -08001538 // Use GDB JIT support to do stack backtrace, etc.
1539 if (executable) {
1540 GdbJITSupport();
1541 }
1542
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001543 return true;
1544}
1545
Tong Shen62d1ca32014-09-03 17:24:56 -07001546template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1547 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1548 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1549bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1550 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -07001551 ::ValidPointer(const uint8_t* start) const {
Brian Carlstromc1409452014-02-26 14:06:23 -08001552 for (size_t i = 0; i < segments_.size(); ++i) {
1553 const MemMap* segment = segments_[i];
1554 if (segment->Begin() <= start && start < segment->End()) {
1555 return true;
1556 }
1557 }
1558 return false;
1559}
1560
Alex Light3470ab42014-06-18 10:35:45 -07001561
Tong Shen62d1ca32014-09-03 17:24:56 -07001562template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1563 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1564 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1565Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1566 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1567 ::FindSectionByName(const std::string& name) const {
Alex Light3470ab42014-06-18 10:35:45 -07001568 CHECK(!program_header_only_);
Tong Shen62d1ca32014-09-03 17:24:56 -07001569 Elf_Shdr* shstrtab_sec = GetSectionNameStringSection();
Andreas Gampedaab38c2014-09-12 18:38:24 -07001570 if (shstrtab_sec == nullptr) {
1571 return nullptr;
1572 }
Alex Light3470ab42014-06-18 10:35:45 -07001573 for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001574 Elf_Shdr* shdr = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001575 if (shdr == nullptr) {
1576 return nullptr;
1577 }
1578 const char* sec_name = GetString(*shstrtab_sec, shdr->sh_name);
Alex Light3470ab42014-06-18 10:35:45 -07001579 if (sec_name == nullptr) {
1580 continue;
1581 }
1582 if (name == sec_name) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001583 return shdr;
Alex Light3470ab42014-06-18 10:35:45 -07001584 }
1585 }
1586 return nullptr;
Mark Mendellae9fd932014-02-10 16:14:35 -08001587}
1588
Tong Shen62d1ca32014-09-03 17:24:56 -07001589template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1590 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1591 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1592bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1593 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Andreas Gampe3c54b002015-04-07 16:09:30 -07001594 ::FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001595 const Elf_Shdr* debug_info = FindSectionByName(".debug_info");
1596 const Elf_Shdr* debug_abbrev = FindSectionByName(".debug_abbrev");
Tong Shen62d1ca32014-09-03 17:24:56 -07001597 const Elf_Shdr* debug_str = FindSectionByName(".debug_str");
Tong Shen62d1ca32014-09-03 17:24:56 -07001598 const Elf_Shdr* strtab_sec = FindSectionByName(".strtab");
1599 const Elf_Shdr* symtab_sec = FindSectionByName(".symtab");
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001600
1601 if (debug_info == nullptr || debug_abbrev == nullptr ||
1602 debug_str == nullptr || strtab_sec == nullptr || symtab_sec == nullptr) {
1603 // Release version of ART does not generate debug info.
1604 return true;
1605 }
1606 if (base_address_delta == 0) {
1607 return true;
1608 }
David Srbecky2f6cdb02015-04-11 00:17:53 +01001609 if (!ApplyOatPatchesTo(".debug_info", base_address_delta)) {
1610 return false;
1611 }
1612 if (!ApplyOatPatchesTo(".debug_line", base_address_delta)) {
1613 return false;
1614 }
1615 return true;
1616}
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001617
David Srbecky2f6cdb02015-04-11 00:17:53 +01001618template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1619 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1620 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1621bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1622 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1623 ::ApplyOatPatchesTo(const char* target_section_name,
1624 typename std::make_signed<Elf_Off>::type delta) {
1625 auto patches_section = FindSectionByName(".oat_patches");
1626 if (patches_section == nullptr) {
1627 LOG(ERROR) << ".oat_patches section not found.";
Alex Light3470ab42014-06-18 10:35:45 -07001628 return false;
1629 }
David Srbecky2f6cdb02015-04-11 00:17:53 +01001630 if (patches_section->sh_type != SHT_OAT_PATCH) {
1631 LOG(ERROR) << "Unexpected type of .oat_patches.";
Alex Light3470ab42014-06-18 10:35:45 -07001632 return false;
1633 }
David Srbecky2f6cdb02015-04-11 00:17:53 +01001634 auto target_section = FindSectionByName(target_section_name);
1635 if (target_section == nullptr) {
1636 LOG(ERROR) << target_section_name << " section not found.";
1637 return false;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001638 }
David Srbecky2f6cdb02015-04-11 00:17:53 +01001639 if (!ApplyOatPatches(
1640 Begin() + patches_section->sh_offset,
1641 Begin() + patches_section->sh_offset + patches_section->sh_size,
1642 target_section_name, delta,
1643 Begin() + target_section->sh_offset,
1644 Begin() + target_section->sh_offset + target_section->sh_size)) {
1645 LOG(ERROR) << target_section_name << " section not found in .oat_patches.";
1646 }
1647 return true;
1648}
1649
1650// Apply .oat_patches to given section.
1651template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1652 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1653 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1654bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1655 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1656 ::ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end,
1657 const char* target_section_name,
1658 typename std::make_signed<Elf_Off>::type delta,
1659 uint8_t* to_patch, const uint8_t* to_patch_end) {
1660 // Read null-terminated section name.
1661 const char* section_name;
1662 while ((section_name = reinterpret_cast<const char*>(patches))[0] != '\0') {
1663 patches += strlen(section_name) + 1;
1664 uint32_t length = DecodeUnsignedLeb128(&patches);
1665 const uint8_t* next_section = patches + length;
1666 // Is it the section we want to patch?
1667 if (strcmp(section_name, target_section_name) == 0) {
1668 // Read LEB128 encoded list of advances.
1669 while (patches < next_section) {
1670 DCHECK_LT(patches, patches_end) << "Unexpected end of .oat_patches.";
1671 to_patch += DecodeUnsignedLeb128(&patches);
1672 DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of " << section_name;
1673 // TODO: 32-bit vs 64-bit. What is the right type to use here?
1674 auto* patch_loc = reinterpret_cast<typename std::make_signed<Elf_Off>::type*>(to_patch);
1675 *patch_loc += delta;
1676 }
1677 return true;
1678 }
1679 patches = next_section;
1680 }
1681 return false;
Alex Light3470ab42014-06-18 10:35:45 -07001682}
Mark Mendellae9fd932014-02-10 16:14:35 -08001683
Tong Shen62d1ca32014-09-03 17:24:56 -07001684template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1685 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1686 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1687void ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1688 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1689 ::GdbJITSupport() {
Mark Mendellae9fd932014-02-10 16:14:35 -08001690 // We only get here if we only are mapping the program header.
1691 DCHECK(program_header_only_);
1692
1693 // Well, we need the whole file to do this.
1694 std::string error_msg;
Alex Light3470ab42014-06-18 10:35:45 -07001695 // Make it MAP_PRIVATE so we can just give it to gdb if all the necessary
1696 // sections are there.
Tong Shen62d1ca32014-09-03 17:24:56 -07001697 std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1698 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
1699 all_ptr(Open(const_cast<File*>(file_), PROT_READ | PROT_WRITE,
1700 MAP_PRIVATE, &error_msg));
Alex Light3470ab42014-06-18 10:35:45 -07001701 if (all_ptr.get() == nullptr) {
Mark Mendellae9fd932014-02-10 16:14:35 -08001702 return;
1703 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001704 ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1705 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>& all = *all_ptr;
Alex Light3470ab42014-06-18 10:35:45 -07001706
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001707 // We need the eh_frame for gdb but debug info might be present without it.
Tong Shen62d1ca32014-09-03 17:24:56 -07001708 const Elf_Shdr* eh_frame = all.FindSectionByName(".eh_frame");
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001709 if (eh_frame == nullptr) {
Mark Mendellae9fd932014-02-10 16:14:35 -08001710 return;
1711 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001712
1713 // Do we have interesting sections?
Alex Light3470ab42014-06-18 10:35:45 -07001714 // We need to add in a strtab and symtab to the image.
1715 // all is MAP_PRIVATE so it can be written to freely.
1716 // We also already have strtab and symtab so we are fine there.
Tong Shen62d1ca32014-09-03 17:24:56 -07001717 Elf_Ehdr& elf_hdr = all.GetHeader();
Mark Mendellae9fd932014-02-10 16:14:35 -08001718 elf_hdr.e_entry = 0;
1719 elf_hdr.e_phoff = 0;
1720 elf_hdr.e_phnum = 0;
1721 elf_hdr.e_phentsize = 0;
1722 elf_hdr.e_type = ET_EXEC;
1723
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001724 // Since base_address_ is 0 if we are actually loaded at a known address (i.e. this is boot.oat)
1725 // and the actual address stuff starts at in regular files this is good.
1726 if (!all.FixupDebugSections(reinterpret_cast<intptr_t>(base_address_))) {
Alex Light3470ab42014-06-18 10:35:45 -07001727 LOG(ERROR) << "Failed to load GDB data";
1728 return;
Mark Mendellae9fd932014-02-10 16:14:35 -08001729 }
1730
Alex Light3470ab42014-06-18 10:35:45 -07001731 jit_gdb_entry_ = CreateCodeEntry(all.Begin(), all.Size());
1732 gdb_file_mapping_.reset(all_ptr.release());
Mark Mendellae9fd932014-02-10 16:14:35 -08001733}
1734
Tong Shen62d1ca32014-09-03 17:24:56 -07001735template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1736 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1737 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1738bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1739 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1740 ::Strip(std::string* error_msg) {
1741 // ELF files produced by MCLinker look roughly like this
1742 //
1743 // +------------+
1744 // | Elf_Ehdr | contains number of Elf_Shdr and offset to first
1745 // +------------+
1746 // | Elf_Phdr | program headers
1747 // | Elf_Phdr |
1748 // | ... |
1749 // | Elf_Phdr |
1750 // +------------+
1751 // | section | mixture of needed and unneeded sections
1752 // +------------+
1753 // | section |
1754 // +------------+
1755 // | ... |
1756 // +------------+
1757 // | section |
1758 // +------------+
1759 // | Elf_Shdr | section headers
1760 // | Elf_Shdr |
1761 // | ... | contains offset to section start
1762 // | Elf_Shdr |
1763 // +------------+
1764 //
1765 // To strip:
1766 // - leave the Elf_Ehdr and Elf_Phdr values in place.
1767 // - walk the sections making a new set of Elf_Shdr section headers for what we want to keep
1768 // - move the sections are keeping up to fill in gaps of sections we want to strip
1769 // - write new Elf_Shdr section headers to end of file, updating Elf_Ehdr
1770 // - truncate rest of file
1771 //
1772
1773 std::vector<Elf_Shdr> section_headers;
1774 std::vector<Elf_Word> section_headers_original_indexes;
1775 section_headers.reserve(GetSectionHeaderNum());
1776
1777
1778 Elf_Shdr* string_section = GetSectionNameStringSection();
1779 CHECK(string_section != nullptr);
1780 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1781 Elf_Shdr* sh = GetSectionHeader(i);
1782 CHECK(sh != nullptr);
1783 const char* name = GetString(*string_section, sh->sh_name);
1784 if (name == nullptr) {
1785 CHECK_EQ(0U, i);
1786 section_headers.push_back(*sh);
1787 section_headers_original_indexes.push_back(0);
1788 continue;
1789 }
1790 if (StartsWith(name, ".debug")
1791 || (strcmp(name, ".strtab") == 0)
1792 || (strcmp(name, ".symtab") == 0)) {
1793 continue;
1794 }
1795 section_headers.push_back(*sh);
1796 section_headers_original_indexes.push_back(i);
1797 }
1798 CHECK_NE(0U, section_headers.size());
1799 CHECK_EQ(section_headers.size(), section_headers_original_indexes.size());
1800
1801 // section 0 is the NULL section, sections start at offset of first section
1802 CHECK(GetSectionHeader(1) != nullptr);
1803 Elf_Off offset = GetSectionHeader(1)->sh_offset;
1804 for (size_t i = 1; i < section_headers.size(); i++) {
1805 Elf_Shdr& new_sh = section_headers[i];
1806 Elf_Shdr* old_sh = GetSectionHeader(section_headers_original_indexes[i]);
1807 CHECK(old_sh != nullptr);
1808 CHECK_EQ(new_sh.sh_name, old_sh->sh_name);
1809 if (old_sh->sh_addralign > 1) {
1810 offset = RoundUp(offset, old_sh->sh_addralign);
1811 }
1812 if (old_sh->sh_offset == offset) {
1813 // already in place
1814 offset += old_sh->sh_size;
1815 continue;
1816 }
1817 // shift section earlier
1818 memmove(Begin() + offset,
1819 Begin() + old_sh->sh_offset,
1820 old_sh->sh_size);
1821 new_sh.sh_offset = offset;
1822 offset += old_sh->sh_size;
1823 }
1824
1825 Elf_Off shoff = offset;
1826 size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf_Shdr);
1827 memcpy(Begin() + offset, &section_headers[0], section_headers_size_in_bytes);
1828 offset += section_headers_size_in_bytes;
1829
1830 GetHeader().e_shnum = section_headers.size();
1831 GetHeader().e_shoff = shoff;
1832 int result = ftruncate(file_->Fd(), offset);
1833 if (result != 0) {
1834 *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s",
1835 file_->GetPath().c_str(), strerror(errno));
1836 return false;
1837 }
1838 return true;
1839}
1840
1841static const bool DEBUG_FIXUP = false;
1842
1843template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1844 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1845 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1846bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1847 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Andreas Gampe3c54b002015-04-07 16:09:30 -07001848 ::Fixup(Elf_Addr base_address) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001849 if (!FixupDynamic(base_address)) {
1850 LOG(WARNING) << "Failed to fixup .dynamic in " << file_->GetPath();
1851 return false;
1852 }
1853 if (!FixupSectionHeaders(base_address)) {
1854 LOG(WARNING) << "Failed to fixup section headers in " << file_->GetPath();
1855 return false;
1856 }
1857 if (!FixupProgramHeaders(base_address)) {
1858 LOG(WARNING) << "Failed to fixup program headers in " << file_->GetPath();
1859 return false;
1860 }
1861 if (!FixupSymbols(base_address, true)) {
1862 LOG(WARNING) << "Failed to fixup .dynsym in " << file_->GetPath();
1863 return false;
1864 }
1865 if (!FixupSymbols(base_address, false)) {
1866 LOG(WARNING) << "Failed to fixup .symtab in " << file_->GetPath();
1867 return false;
1868 }
1869 if (!FixupRelocations(base_address)) {
1870 LOG(WARNING) << "Failed to fixup .rel.dyn in " << file_->GetPath();
1871 return false;
1872 }
Andreas Gampe3c54b002015-04-07 16:09:30 -07001873 static_assert(sizeof(Elf_Off) >= sizeof(base_address), "Potentially losing precision.");
1874 if (!FixupDebugSections(static_cast<Elf_Off>(base_address))) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001875 LOG(WARNING) << "Failed to fixup debug sections in " << file_->GetPath();
1876 return false;
1877 }
1878 return true;
1879}
1880
1881template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1882 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1883 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1884bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1885 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Andreas Gampe3c54b002015-04-07 16:09:30 -07001886 ::FixupDynamic(Elf_Addr base_address) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001887 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1888 Elf_Dyn& elf_dyn = GetDynamic(i);
1889 Elf_Word d_tag = elf_dyn.d_tag;
1890 if (IsDynamicSectionPointer(d_tag, GetHeader().e_machine)) {
1891 Elf_Addr d_ptr = elf_dyn.d_un.d_ptr;
1892 if (DEBUG_FIXUP) {
1893 LOG(INFO) << StringPrintf("In %s moving Elf_Dyn[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
1894 GetFile().GetPath().c_str(), i,
1895 static_cast<uint64_t>(d_ptr),
1896 static_cast<uint64_t>(d_ptr + base_address));
1897 }
1898 d_ptr += base_address;
1899 elf_dyn.d_un.d_ptr = d_ptr;
1900 }
1901 }
1902 return true;
1903}
1904
1905template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1906 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1907 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1908bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1909 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Andreas Gampe3c54b002015-04-07 16:09:30 -07001910 ::FixupSectionHeaders(Elf_Addr base_address) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001911 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1912 Elf_Shdr* sh = GetSectionHeader(i);
1913 CHECK(sh != nullptr);
1914 // 0 implies that the section will not exist in the memory of the process
1915 if (sh->sh_addr == 0) {
1916 continue;
1917 }
1918 if (DEBUG_FIXUP) {
1919 LOG(INFO) << StringPrintf("In %s moving Elf_Shdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
1920 GetFile().GetPath().c_str(), i,
1921 static_cast<uint64_t>(sh->sh_addr),
1922 static_cast<uint64_t>(sh->sh_addr + base_address));
1923 }
1924 sh->sh_addr += base_address;
1925 }
1926 return true;
1927}
1928
1929template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1930 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1931 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1932bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1933 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Andreas Gampe3c54b002015-04-07 16:09:30 -07001934 ::FixupProgramHeaders(Elf_Addr base_address) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001935 // TODO: ELFObjectFile doesn't have give to Elf_Phdr, so we do that ourselves for now.
1936 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1937 Elf_Phdr* ph = GetProgramHeader(i);
1938 CHECK(ph != nullptr);
1939 CHECK_EQ(ph->p_vaddr, ph->p_paddr) << GetFile().GetPath() << " i=" << i;
1940 CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
1941 << GetFile().GetPath() << " i=" << i;
1942 if (DEBUG_FIXUP) {
1943 LOG(INFO) << StringPrintf("In %s moving Elf_Phdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
1944 GetFile().GetPath().c_str(), i,
1945 static_cast<uint64_t>(ph->p_vaddr),
1946 static_cast<uint64_t>(ph->p_vaddr + base_address));
1947 }
1948 ph->p_vaddr += base_address;
1949 ph->p_paddr += base_address;
1950 CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
1951 << GetFile().GetPath() << " i=" << i;
1952 }
1953 return true;
1954}
1955
1956template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1957 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1958 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1959bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1960 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Andreas Gampe3c54b002015-04-07 16:09:30 -07001961 ::FixupSymbols(Elf_Addr base_address, bool dynamic) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001962 Elf_Word section_type = dynamic ? SHT_DYNSYM : SHT_SYMTAB;
1963 // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
1964 Elf_Shdr* symbol_section = FindSectionByType(section_type);
1965 if (symbol_section == nullptr) {
1966 // file is missing optional .symtab
1967 CHECK(!dynamic) << GetFile().GetPath();
1968 return true;
1969 }
1970 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
1971 Elf_Sym* symbol = GetSymbol(section_type, i);
1972 CHECK(symbol != nullptr);
1973 if (symbol->st_value != 0) {
1974 if (DEBUG_FIXUP) {
1975 LOG(INFO) << StringPrintf("In %s moving Elf_Sym[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
1976 GetFile().GetPath().c_str(), i,
1977 static_cast<uint64_t>(symbol->st_value),
1978 static_cast<uint64_t>(symbol->st_value + base_address));
1979 }
1980 symbol->st_value += base_address;
1981 }
1982 }
1983 return true;
1984}
1985
1986template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1987 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1988 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1989bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1990 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Andreas Gampe3c54b002015-04-07 16:09:30 -07001991 ::FixupRelocations(Elf_Addr base_address) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001992 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1993 Elf_Shdr* sh = GetSectionHeader(i);
1994 CHECK(sh != nullptr);
1995 if (sh->sh_type == SHT_REL) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -08001996 for (uint32_t j = 0; j < GetRelNum(*sh); j++) {
1997 Elf_Rel& rel = GetRel(*sh, j);
Tong Shen62d1ca32014-09-03 17:24:56 -07001998 if (DEBUG_FIXUP) {
1999 LOG(INFO) << StringPrintf("In %s moving Elf_Rel[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
Andreas Gampe277ccbd2014-11-03 21:36:10 -08002000 GetFile().GetPath().c_str(), j,
Tong Shen62d1ca32014-09-03 17:24:56 -07002001 static_cast<uint64_t>(rel.r_offset),
2002 static_cast<uint64_t>(rel.r_offset + base_address));
2003 }
2004 rel.r_offset += base_address;
2005 }
2006 } else if (sh->sh_type == SHT_RELA) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -08002007 for (uint32_t j = 0; j < GetRelaNum(*sh); j++) {
2008 Elf_Rela& rela = GetRela(*sh, j);
Tong Shen62d1ca32014-09-03 17:24:56 -07002009 if (DEBUG_FIXUP) {
2010 LOG(INFO) << StringPrintf("In %s moving Elf_Rela[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
Andreas Gampe277ccbd2014-11-03 21:36:10 -08002011 GetFile().GetPath().c_str(), j,
Tong Shen62d1ca32014-09-03 17:24:56 -07002012 static_cast<uint64_t>(rela.r_offset),
2013 static_cast<uint64_t>(rela.r_offset + base_address));
2014 }
2015 rela.r_offset += base_address;
2016 }
2017 }
2018 }
2019 return true;
2020}
2021
2022// Explicit instantiations
2023template class ElfFileImpl<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Word,
2024 Elf32_Sword, Elf32_Addr, Elf32_Sym, Elf32_Rel, Elf32_Rela, Elf32_Dyn, Elf32_Off>;
2025template class ElfFileImpl<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Word,
2026 Elf64_Sword, Elf64_Addr, Elf64_Sym, Elf64_Rel, Elf64_Rela, Elf64_Dyn, Elf64_Off>;
2027
Ian Rogersd4c4d952014-10-16 20:31:53 -07002028ElfFile::ElfFile(ElfFileImpl32* elf32) : elf32_(elf32), elf64_(nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002029}
2030
Ian Rogersd4c4d952014-10-16 20:31:53 -07002031ElfFile::ElfFile(ElfFileImpl64* elf64) : elf32_(nullptr), elf64_(elf64) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002032}
2033
2034ElfFile::~ElfFile() {
Ian Rogersd4c4d952014-10-16 20:31:53 -07002035 // Should never have 32 and 64-bit impls.
2036 CHECK_NE(elf32_.get() == nullptr, elf64_.get() == nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07002037}
2038
Igor Murashkin46774762014-10-22 11:37:02 -07002039ElfFile* ElfFile::Open(File* file, bool writable, bool program_header_only, std::string* error_msg,
2040 uint8_t* requested_base) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002041 if (file->GetLength() < EI_NIDENT) {
2042 *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
2043 file->GetPath().c_str());
2044 return nullptr;
2045 }
2046 std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT, PROT_READ, MAP_PRIVATE, file->Fd(), 0,
2047 file->GetPath().c_str(), error_msg));
2048 if (map == nullptr && map->Size() != EI_NIDENT) {
2049 return nullptr;
2050 }
Ian Rogers13735952014-10-08 12:43:28 -07002051 uint8_t* header = map->Begin();
Tong Shen62d1ca32014-09-03 17:24:56 -07002052 if (header[EI_CLASS] == ELFCLASS64) {
Igor Murashkin46774762014-10-22 11:37:02 -07002053 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, writable, program_header_only,
2054 error_msg, requested_base);
Tong Shen62d1ca32014-09-03 17:24:56 -07002055 if (elf_file_impl == nullptr)
2056 return nullptr;
2057 return new ElfFile(elf_file_impl);
2058 } else if (header[EI_CLASS] == ELFCLASS32) {
Igor Murashkin46774762014-10-22 11:37:02 -07002059 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, writable, program_header_only,
2060 error_msg, requested_base);
Ian Rogersd4c4d952014-10-16 20:31:53 -07002061 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002062 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002063 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002064 return new ElfFile(elf_file_impl);
2065 } else {
2066 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
2067 ELFCLASS32, ELFCLASS64,
2068 file->GetPath().c_str(),
2069 header[EI_CLASS]);
2070 return nullptr;
2071 }
2072}
2073
2074ElfFile* ElfFile::Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg) {
2075 if (file->GetLength() < EI_NIDENT) {
2076 *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
2077 file->GetPath().c_str());
2078 return nullptr;
2079 }
2080 std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT, PROT_READ, MAP_PRIVATE, file->Fd(), 0,
2081 file->GetPath().c_str(), error_msg));
2082 if (map == nullptr && map->Size() != EI_NIDENT) {
2083 return nullptr;
2084 }
Ian Rogers13735952014-10-08 12:43:28 -07002085 uint8_t* header = map->Begin();
Tong Shen62d1ca32014-09-03 17:24:56 -07002086 if (header[EI_CLASS] == ELFCLASS64) {
2087 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, mmap_prot, mmap_flags, error_msg);
Ian Rogersd4c4d952014-10-16 20:31:53 -07002088 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002089 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002090 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002091 return new ElfFile(elf_file_impl);
2092 } else if (header[EI_CLASS] == ELFCLASS32) {
2093 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, mmap_prot, mmap_flags, error_msg);
Ian Rogersd4c4d952014-10-16 20:31:53 -07002094 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002095 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002096 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002097 return new ElfFile(elf_file_impl);
2098 } else {
2099 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
2100 ELFCLASS32, ELFCLASS64,
2101 file->GetPath().c_str(),
2102 header[EI_CLASS]);
2103 return nullptr;
2104 }
2105}
2106
2107#define DELEGATE_TO_IMPL(func, ...) \
Ian Rogersd4c4d952014-10-16 20:31:53 -07002108 if (elf64_.get() != nullptr) { \
2109 return elf64_->func(__VA_ARGS__); \
Tong Shen62d1ca32014-09-03 17:24:56 -07002110 } else { \
Ian Rogersd4c4d952014-10-16 20:31:53 -07002111 DCHECK(elf32_.get() != nullptr); \
2112 return elf32_->func(__VA_ARGS__); \
Tong Shen62d1ca32014-09-03 17:24:56 -07002113 }
2114
2115bool ElfFile::Load(bool executable, std::string* error_msg) {
2116 DELEGATE_TO_IMPL(Load, executable, error_msg);
2117}
2118
Ian Rogers13735952014-10-08 12:43:28 -07002119const uint8_t* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
Tong Shen62d1ca32014-09-03 17:24:56 -07002120 DELEGATE_TO_IMPL(FindDynamicSymbolAddress, symbol_name);
2121}
2122
2123size_t ElfFile::Size() const {
2124 DELEGATE_TO_IMPL(Size);
2125}
2126
Ian Rogers13735952014-10-08 12:43:28 -07002127uint8_t* ElfFile::Begin() const {
Tong Shen62d1ca32014-09-03 17:24:56 -07002128 DELEGATE_TO_IMPL(Begin);
2129}
2130
Ian Rogers13735952014-10-08 12:43:28 -07002131uint8_t* ElfFile::End() const {
Tong Shen62d1ca32014-09-03 17:24:56 -07002132 DELEGATE_TO_IMPL(End);
2133}
2134
2135const File& ElfFile::GetFile() const {
2136 DELEGATE_TO_IMPL(GetFile);
2137}
2138
2139bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, uint64_t* size) {
Ian Rogersd4c4d952014-10-16 20:31:53 -07002140 if (elf32_.get() == nullptr) {
2141 CHECK(elf64_.get() != nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07002142
Ian Rogersd4c4d952014-10-16 20:31:53 -07002143 Elf64_Shdr *shdr = elf64_->FindSectionByName(section_name);
2144 if (shdr == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002145 return false;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002146 }
2147 if (offset != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002148 *offset = shdr->sh_offset;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002149 }
2150 if (size != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002151 *size = shdr->sh_size;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002152 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002153 return true;
2154 } else {
Ian Rogersd4c4d952014-10-16 20:31:53 -07002155 Elf32_Shdr *shdr = elf32_->FindSectionByName(section_name);
2156 if (shdr == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002157 return false;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002158 }
2159 if (offset != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002160 *offset = shdr->sh_offset;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002161 }
2162 if (size != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002163 *size = shdr->sh_size;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002164 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002165 return true;
2166 }
2167}
2168
2169uint64_t ElfFile::FindSymbolAddress(unsigned section_type,
2170 const std::string& symbol_name,
2171 bool build_map) {
2172 DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map);
2173}
2174
2175size_t ElfFile::GetLoadedSize() const {
2176 DELEGATE_TO_IMPL(GetLoadedSize);
2177}
2178
2179bool ElfFile::Strip(File* file, std::string* error_msg) {
2180 std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, error_msg));
2181 if (elf_file.get() == nullptr) {
2182 return false;
2183 }
2184
Ian Rogersd4c4d952014-10-16 20:31:53 -07002185 if (elf_file->elf64_.get() != nullptr)
2186 return elf_file->elf64_->Strip(error_msg);
Tong Shen62d1ca32014-09-03 17:24:56 -07002187 else
Ian Rogersd4c4d952014-10-16 20:31:53 -07002188 return elf_file->elf32_->Strip(error_msg);
Tong Shen62d1ca32014-09-03 17:24:56 -07002189}
2190
Andreas Gampe3c54b002015-04-07 16:09:30 -07002191bool ElfFile::Fixup(uint64_t base_address) {
2192 if (elf64_.get() != nullptr) {
2193 return elf64_->Fixup(static_cast<Elf64_Addr>(base_address));
2194 } else {
2195 DCHECK(elf32_.get() != nullptr);
2196 CHECK(IsUint<32>(base_address)) << std::hex << base_address;
2197 return elf32_->Fixup(static_cast<Elf32_Addr>(base_address));
2198 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002199 DELEGATE_TO_IMPL(Fixup, base_address);
2200}
2201
Brian Carlstrom700c8d32012-11-05 10:42:02 -08002202} // namespace art