blob: c3a25595cd8f15dbdeb21a92cf14dbbd00dda38e [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
Brian Carlstrom700c8d32012-11-05 10:42:02 -080023#include "base/logging.h"
Ian Rogers576ca0c2014-06-06 15:58:22 -070024#include "base/stringprintf.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080025#include "base/stl_util.h"
Alex Light3470ab42014-06-18 10:35:45 -070026#include "dwarf.h"
27#include "leb128.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080028#include "utils.h"
Andreas Gampe91268c12014-04-03 17:50:24 -070029#include "instruction_set.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080030
31namespace art {
32
Mark Mendellae9fd932014-02-10 16:14:35 -080033// -------------------------------------------------------------------
34// Binary GDB JIT Interface as described in
35// http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
36extern "C" {
37 typedef enum {
38 JIT_NOACTION = 0,
39 JIT_REGISTER_FN,
40 JIT_UNREGISTER_FN
41 } JITAction;
42
43 struct JITCodeEntry {
44 JITCodeEntry* next_;
45 JITCodeEntry* prev_;
Ian Rogers13735952014-10-08 12:43:28 -070046 const uint8_t *symfile_addr_;
Mark Mendellae9fd932014-02-10 16:14:35 -080047 uint64_t symfile_size_;
48 };
49
50 struct JITDescriptor {
51 uint32_t version_;
52 uint32_t action_flag_;
53 JITCodeEntry* relevant_entry_;
54 JITCodeEntry* first_entry_;
55 };
56
57 // GDB will place breakpoint into this function.
58 // To prevent GCC from inlining or removing it we place noinline attribute
59 // and inline assembler statement inside.
60 void __attribute__((noinline)) __jit_debug_register_code() {
61 __asm__("");
62 }
63
64 // GDB will inspect contents of this descriptor.
65 // Static initialization is necessary to prevent GDB from seeing
66 // uninitialized descriptor.
67 JITDescriptor __jit_debug_descriptor = { 1, JIT_NOACTION, nullptr, nullptr };
68}
69
70
Ian Rogers13735952014-10-08 12:43:28 -070071static JITCodeEntry* CreateCodeEntry(const uint8_t *symfile_addr,
Mark Mendellae9fd932014-02-10 16:14:35 -080072 uintptr_t symfile_size) {
73 JITCodeEntry* entry = new JITCodeEntry;
74 entry->symfile_addr_ = symfile_addr;
75 entry->symfile_size_ = symfile_size;
76 entry->prev_ = nullptr;
77
78 // TODO: Do we need a lock here?
79 entry->next_ = __jit_debug_descriptor.first_entry_;
80 if (entry->next_ != nullptr) {
81 entry->next_->prev_ = entry;
82 }
83 __jit_debug_descriptor.first_entry_ = entry;
84 __jit_debug_descriptor.relevant_entry_ = entry;
85
86 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
87 __jit_debug_register_code();
88 return entry;
89}
90
91
92static void UnregisterCodeEntry(JITCodeEntry* entry) {
93 // TODO: Do we need a lock here?
94 if (entry->prev_ != nullptr) {
95 entry->prev_->next_ = entry->next_;
96 } else {
97 __jit_debug_descriptor.first_entry_ = entry->next_;
98 }
99
100 if (entry->next_ != nullptr) {
101 entry->next_->prev_ = entry->prev_;
102 }
103
104 __jit_debug_descriptor.relevant_entry_ = entry;
105 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
106 __jit_debug_register_code();
107 delete entry;
108}
109
Tong Shen62d1ca32014-09-03 17:24:56 -0700110template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
111 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
112 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
113ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
114 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
115 ::ElfFileImpl(File* file, bool writable, bool program_header_only)
Brian Carlstromc1409452014-02-26 14:06:23 -0800116 : file_(file),
117 writable_(writable),
118 program_header_only_(program_header_only),
Alex Light3470ab42014-06-18 10:35:45 -0700119 header_(nullptr),
120 base_address_(nullptr),
121 program_headers_start_(nullptr),
122 section_headers_start_(nullptr),
123 dynamic_program_header_(nullptr),
124 dynamic_section_start_(nullptr),
125 symtab_section_start_(nullptr),
126 dynsym_section_start_(nullptr),
127 strtab_section_start_(nullptr),
128 dynstr_section_start_(nullptr),
129 hash_section_start_(nullptr),
130 symtab_symbol_table_(nullptr),
131 dynsym_symbol_table_(nullptr),
132 jit_elf_image_(nullptr),
133 jit_gdb_entry_(nullptr) {
134 CHECK(file != nullptr);
Brian Carlstromc1409452014-02-26 14:06:23 -0800135}
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800136
Tong Shen62d1ca32014-09-03 17:24:56 -0700137template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
138 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
139 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
140ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
141 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>*
142 ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
143 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
144 ::Open(File* file, bool writable, bool program_header_only,
145 std::string* error_msg) {
146 std::unique_ptr<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 elf_file(new ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
149 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
150 (file, writable, program_header_only));
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800151 int prot;
152 int flags;
Alex Light3470ab42014-06-18 10:35:45 -0700153 if (writable) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800154 prot = PROT_READ | PROT_WRITE;
155 flags = MAP_SHARED;
156 } else {
157 prot = PROT_READ;
158 flags = MAP_PRIVATE;
159 }
Alex Light3470ab42014-06-18 10:35:45 -0700160 if (!elf_file->Setup(prot, flags, error_msg)) {
161 return nullptr;
162 }
163 return elf_file.release();
164}
165
Tong Shen62d1ca32014-09-03 17:24:56 -0700166template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
167 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
168 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
169ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
170 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>*
171 ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
172 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
173 ::Open(File* file, int prot, int flags, std::string* error_msg) {
174 std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
175 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
176 elf_file(new ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
177 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
178 (file, (prot & PROT_WRITE) == PROT_WRITE, false));
Alex Light3470ab42014-06-18 10:35:45 -0700179 if (!elf_file->Setup(prot, flags, error_msg)) {
180 return nullptr;
181 }
182 return elf_file.release();
183}
184
Tong Shen62d1ca32014-09-03 17:24:56 -0700185template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
186 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
187 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
188bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
189 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
190 ::Setup(int prot, int flags, std::string* error_msg) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800191 int64_t temp_file_length = file_->GetLength();
192 if (temp_file_length < 0) {
193 errno = -temp_file_length;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700194 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
195 file_->GetPath().c_str(), file_->Fd(), strerror(errno));
Brian Carlstrom265091e2013-01-30 14:08:26 -0800196 return false;
197 }
Ian Rogerscdfcf372014-01-23 20:38:36 -0800198 size_t file_length = static_cast<size_t>(temp_file_length);
Tong Shen62d1ca32014-09-03 17:24:56 -0700199 if (file_length < sizeof(Elf_Ehdr)) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800200 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF header of "
Tong Shen62d1ca32014-09-03 17:24:56 -0700201 "%zd bytes: '%s'", file_length, sizeof(Elf_Ehdr),
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700202 file_->GetPath().c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800203 return false;
204 }
205
Brian Carlstromc1409452014-02-26 14:06:23 -0800206 if (program_header_only_) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800207 // first just map ELF header to get program header size information
Tong Shen62d1ca32014-09-03 17:24:56 -0700208 size_t elf_header_size = sizeof(Elf_Ehdr);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700209 if (!SetMap(MemMap::MapFile(elf_header_size, prot, flags, file_->Fd(), 0,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800210 file_->GetPath().c_str(), error_msg),
211 error_msg)) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800212 return false;
213 }
214 // then remap to cover program header
215 size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum);
Brian Carlstrom3a223612013-10-10 17:18:24 -0700216 if (file_length < program_header_size) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800217 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program "
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700218 "header of %zd bytes: '%s'", file_length,
Tong Shen62d1ca32014-09-03 17:24:56 -0700219 sizeof(Elf_Ehdr), file_->GetPath().c_str());
Brian Carlstrom3a223612013-10-10 17:18:24 -0700220 return false;
221 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700222 if (!SetMap(MemMap::MapFile(program_header_size, prot, flags, file_->Fd(), 0,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800223 file_->GetPath().c_str(), error_msg),
224 error_msg)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700225 *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800226 return false;
227 }
228 } else {
229 // otherwise map entire file
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700230 if (!SetMap(MemMap::MapFile(file_->GetLength(), prot, flags, file_->Fd(), 0,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800231 file_->GetPath().c_str(), error_msg),
232 error_msg)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700233 *error_msg = StringPrintf("Failed to map ELF file: %s", error_msg->c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800234 return false;
235 }
236 }
237
Andreas Gampedaab38c2014-09-12 18:38:24 -0700238 if (program_header_only_) {
239 program_headers_start_ = Begin() + GetHeader().e_phoff;
240 } else {
241 if (!CheckAndSet(GetHeader().e_phoff, "program headers", &program_headers_start_, error_msg)) {
242 return false;
243 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800244
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800245 // Setup section headers.
Andreas Gampedaab38c2014-09-12 18:38:24 -0700246 if (!CheckAndSet(GetHeader().e_shoff, "section headers", &section_headers_start_, error_msg)) {
247 return false;
248 }
249
250 // Find shstrtab.
Tong Shen62d1ca32014-09-03 17:24:56 -0700251 Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700252 if (shstrtab_section_header == nullptr) {
253 *error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'",
254 file_->GetPath().c_str());
255 return false;
256 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800257
258 // Find .dynamic section info from program header
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000259 dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC);
Alex Light3470ab42014-06-18 10:35:45 -0700260 if (dynamic_program_header_ == nullptr) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700261 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
262 file_->GetPath().c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800263 return false;
264 }
265
Andreas Gampedaab38c2014-09-12 18:38:24 -0700266 if (!CheckAndSet(GetDynamicProgramHeader().p_offset, "dynamic section",
Ian Rogers13735952014-10-08 12:43:28 -0700267 reinterpret_cast<uint8_t**>(&dynamic_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700268 return false;
269 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800270
271 // Find other sections from section headers
Tong Shen62d1ca32014-09-03 17:24:56 -0700272 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
273 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700274 if (section_header == nullptr) {
275 *error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'",
276 i, file_->GetPath().c_str());
277 return false;
278 }
279 switch (section_header->sh_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000280 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700281 if (!CheckAndSet(section_header->sh_offset, "symtab",
Ian Rogers13735952014-10-08 12:43:28 -0700282 reinterpret_cast<uint8_t**>(&symtab_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700283 return false;
284 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800285 break;
286 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000287 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700288 if (!CheckAndSet(section_header->sh_offset, "dynsym",
Ian Rogers13735952014-10-08 12:43:28 -0700289 reinterpret_cast<uint8_t**>(&dynsym_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700290 return false;
291 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800292 break;
293 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000294 case SHT_STRTAB: {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800295 // TODO: base these off of sh_link from .symtab and .dynsym above
Andreas Gampedaab38c2014-09-12 18:38:24 -0700296 if ((section_header->sh_flags & SHF_ALLOC) != 0) {
297 // Check that this is named ".dynstr" and ignore otherwise.
298 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
299 if (strncmp(".dynstr", header_name, 8) == 0) {
300 if (!CheckAndSet(section_header->sh_offset, "dynstr",
Ian Rogers13735952014-10-08 12:43:28 -0700301 reinterpret_cast<uint8_t**>(&dynstr_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700302 return false;
303 }
304 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800305 } else {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700306 // Check that this is named ".strtab" and ignore otherwise.
307 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
308 if (strncmp(".strtab", header_name, 8) == 0) {
309 if (!CheckAndSet(section_header->sh_offset, "strtab",
Ian Rogers13735952014-10-08 12:43:28 -0700310 reinterpret_cast<uint8_t**>(&strtab_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700311 return false;
312 }
313 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800314 }
315 break;
316 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000317 case SHT_DYNAMIC: {
Ian Rogers13735952014-10-08 12:43:28 -0700318 if (reinterpret_cast<uint8_t*>(dynamic_section_start_) !=
Andreas Gampedaab38c2014-09-12 18:38:24 -0700319 Begin() + section_header->sh_offset) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800320 LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in "
Brian Carlstrom265091e2013-01-30 14:08:26 -0800321 << file_->GetPath() << ": " << std::hex
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800322 << reinterpret_cast<void*>(dynamic_section_start_)
Andreas Gampedaab38c2014-09-12 18:38:24 -0700323 << " != " << reinterpret_cast<void*>(Begin() + section_header->sh_offset);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800324 return false;
325 }
326 break;
327 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000328 case SHT_HASH: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700329 if (!CheckAndSet(section_header->sh_offset, "hash section",
Ian Rogers13735952014-10-08 12:43:28 -0700330 reinterpret_cast<uint8_t**>(&hash_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700331 return false;
332 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800333 break;
334 }
335 }
336 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700337
338 // Check for the existence of some sections.
339 if (!CheckSectionsExist(error_msg)) {
340 return false;
341 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800342 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700343
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800344 return true;
345}
346
Tong Shen62d1ca32014-09-03 17:24:56 -0700347template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
348 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
349 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
350ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
351 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
352 ::~ElfFileImpl() {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800353 STLDeleteElements(&segments_);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800354 delete symtab_symbol_table_;
355 delete dynsym_symbol_table_;
Mark Mendellae9fd932014-02-10 16:14:35 -0800356 delete jit_elf_image_;
357 if (jit_gdb_entry_) {
358 UnregisterCodeEntry(jit_gdb_entry_);
359 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800360}
361
Tong Shen62d1ca32014-09-03 17:24:56 -0700362template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
363 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
364 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
365bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
366 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
367 ::CheckAndSet(Elf32_Off offset, const char* label,
Ian Rogers13735952014-10-08 12:43:28 -0700368 uint8_t** target, std::string* error_msg) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700369 if (Begin() + offset >= End()) {
370 *error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label,
371 file_->GetPath().c_str());
372 return false;
373 }
374 *target = Begin() + offset;
375 return true;
376}
377
Tong Shen62d1ca32014-09-03 17:24:56 -0700378template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
379 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
380 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
381bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
382 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700383 ::CheckSectionsLinked(const uint8_t* source, const uint8_t* target) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700384 // Only works in whole-program mode, as we need to iterate over the sections.
385 // Note that we normally can't search by type, as duplicates are allowed for most section types.
386 if (program_header_only_) {
387 return true;
388 }
389
Tong Shen62d1ca32014-09-03 17:24:56 -0700390 Elf_Shdr* source_section = nullptr;
391 Elf_Word target_index = 0;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700392 bool target_found = false;
Tong Shen62d1ca32014-09-03 17:24:56 -0700393 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
394 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700395
396 if (Begin() + section_header->sh_offset == source) {
397 // Found the source.
398 source_section = section_header;
399 if (target_index) {
400 break;
401 }
402 } else if (Begin() + section_header->sh_offset == target) {
403 target_index = i;
404 target_found = true;
405 if (source_section != nullptr) {
406 break;
407 }
408 }
409 }
410
411 return target_found && source_section != nullptr && source_section->sh_link == target_index;
412}
413
Tong Shen62d1ca32014-09-03 17:24:56 -0700414template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
415 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
416 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
417bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
418 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
419 ::CheckSectionsExist(std::string* error_msg) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700420 if (!program_header_only_) {
421 // If in full mode, need section headers.
422 if (section_headers_start_ == nullptr) {
423 *error_msg = StringPrintf("No section headers in ELF file: '%s'", file_->GetPath().c_str());
424 return false;
425 }
426 }
427
428 // This is redundant, but defensive.
429 if (dynamic_program_header_ == nullptr) {
430 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
431 file_->GetPath().c_str());
432 return false;
433 }
434
435 // Need a dynamic section. This is redundant, but defensive.
436 if (dynamic_section_start_ == nullptr) {
437 *error_msg = StringPrintf("Failed to find dynamic section in ELF file: '%s'",
438 file_->GetPath().c_str());
439 return false;
440 }
441
442 // Symtab validation. These is not really a hard failure, as we are currently not using the
443 // symtab internally, but it's nice to be defensive.
444 if (symtab_section_start_ != nullptr) {
445 // When there's a symtab, there should be a strtab.
446 if (strtab_section_start_ == nullptr) {
447 *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file_->GetPath().c_str());
448 return false;
449 }
450
451 // The symtab should link to the strtab.
Ian Rogers13735952014-10-08 12:43:28 -0700452 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(symtab_section_start_),
453 reinterpret_cast<const uint8_t*>(strtab_section_start_))) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700454 *error_msg = StringPrintf("Symtab is not linked to the strtab in ELF file: '%s'",
455 file_->GetPath().c_str());
456 return false;
457 }
458 }
459
460 // We always need a dynstr & dynsym.
461 if (dynstr_section_start_ == nullptr) {
462 *error_msg = StringPrintf("No dynstr in ELF file: '%s'", file_->GetPath().c_str());
463 return false;
464 }
465 if (dynsym_section_start_ == nullptr) {
466 *error_msg = StringPrintf("No dynsym in ELF file: '%s'", file_->GetPath().c_str());
467 return false;
468 }
469
470 // Need a hash section for dynamic symbol lookup.
471 if (hash_section_start_ == nullptr) {
472 *error_msg = StringPrintf("Failed to find hash section in ELF file: '%s'",
473 file_->GetPath().c_str());
474 return false;
475 }
476
477 // And the hash section should be linking to the dynsym.
Ian Rogers13735952014-10-08 12:43:28 -0700478 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(hash_section_start_),
479 reinterpret_cast<const uint8_t*>(dynsym_section_start_))) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700480 *error_msg = StringPrintf("Hash section is not linked to the dynstr in ELF file: '%s'",
481 file_->GetPath().c_str());
482 return false;
483 }
484
485 return true;
486}
487
Tong Shen62d1ca32014-09-03 17:24:56 -0700488template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
489 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
490 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
491bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
492 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
493 ::SetMap(MemMap* map, std::string* error_msg) {
Alex Light3470ab42014-06-18 10:35:45 -0700494 if (map == nullptr) {
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800495 // MemMap::Open should have already set an error.
496 DCHECK(!error_msg->empty());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800497 return false;
498 }
499 map_.reset(map);
Alex Light3470ab42014-06-18 10:35:45 -0700500 CHECK(map_.get() != nullptr) << file_->GetPath();
501 CHECK(map_->Begin() != nullptr) << file_->GetPath();
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800502
Tong Shen62d1ca32014-09-03 17:24:56 -0700503 header_ = reinterpret_cast<Elf_Ehdr*>(map_->Begin());
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000504 if ((ELFMAG0 != header_->e_ident[EI_MAG0])
505 || (ELFMAG1 != header_->e_ident[EI_MAG1])
506 || (ELFMAG2 != header_->e_ident[EI_MAG2])
507 || (ELFMAG3 != header_->e_ident[EI_MAG3])) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800508 *error_msg = StringPrintf("Failed to find ELF magic value %d %d %d %d in %s, found %d %d %d %d",
509 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800510 file_->GetPath().c_str(),
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000511 header_->e_ident[EI_MAG0],
512 header_->e_ident[EI_MAG1],
513 header_->e_ident[EI_MAG2],
514 header_->e_ident[EI_MAG3]);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800515 return false;
516 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700517 uint8_t elf_class = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) ? ELFCLASS64 : ELFCLASS32;
518 if (elf_class != header_->e_ident[EI_CLASS]) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800519 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d in %s, found %d",
Tong Shen62d1ca32014-09-03 17:24:56 -0700520 elf_class,
Brian Carlstromc1409452014-02-26 14:06:23 -0800521 file_->GetPath().c_str(),
522 header_->e_ident[EI_CLASS]);
523 return false;
524 }
525 if (ELFDATA2LSB != header_->e_ident[EI_DATA]) {
526 *error_msg = StringPrintf("Failed to find expected EI_DATA value %d in %s, found %d",
527 ELFDATA2LSB,
528 file_->GetPath().c_str(),
529 header_->e_ident[EI_CLASS]);
530 return false;
531 }
532 if (EV_CURRENT != header_->e_ident[EI_VERSION]) {
533 *error_msg = StringPrintf("Failed to find expected EI_VERSION value %d in %s, found %d",
534 EV_CURRENT,
535 file_->GetPath().c_str(),
536 header_->e_ident[EI_CLASS]);
537 return false;
538 }
539 if (ET_DYN != header_->e_type) {
540 *error_msg = StringPrintf("Failed to find expected e_type value %d in %s, found %d",
541 ET_DYN,
542 file_->GetPath().c_str(),
543 header_->e_type);
544 return false;
545 }
546 if (EV_CURRENT != header_->e_version) {
547 *error_msg = StringPrintf("Failed to find expected e_version value %d in %s, found %d",
548 EV_CURRENT,
549 file_->GetPath().c_str(),
550 header_->e_version);
551 return false;
552 }
553 if (0 != header_->e_entry) {
554 *error_msg = StringPrintf("Failed to find expected e_entry value %d in %s, found %d",
555 0,
556 file_->GetPath().c_str(),
Tong Shen62d1ca32014-09-03 17:24:56 -0700557 static_cast<int32_t>(header_->e_entry));
Brian Carlstromc1409452014-02-26 14:06:23 -0800558 return false;
559 }
560 if (0 == header_->e_phoff) {
561 *error_msg = StringPrintf("Failed to find non-zero e_phoff value in %s",
562 file_->GetPath().c_str());
563 return false;
564 }
565 if (0 == header_->e_shoff) {
566 *error_msg = StringPrintf("Failed to find non-zero e_shoff value in %s",
567 file_->GetPath().c_str());
568 return false;
569 }
570 if (0 == header_->e_ehsize) {
571 *error_msg = StringPrintf("Failed to find non-zero e_ehsize value in %s",
572 file_->GetPath().c_str());
573 return false;
574 }
575 if (0 == header_->e_phentsize) {
576 *error_msg = StringPrintf("Failed to find non-zero e_phentsize value in %s",
577 file_->GetPath().c_str());
578 return false;
579 }
580 if (0 == header_->e_phnum) {
581 *error_msg = StringPrintf("Failed to find non-zero e_phnum value in %s",
582 file_->GetPath().c_str());
583 return false;
584 }
585 if (0 == header_->e_shentsize) {
586 *error_msg = StringPrintf("Failed to find non-zero e_shentsize value in %s",
587 file_->GetPath().c_str());
588 return false;
589 }
590 if (0 == header_->e_shnum) {
591 *error_msg = StringPrintf("Failed to find non-zero e_shnum value in %s",
592 file_->GetPath().c_str());
593 return false;
594 }
595 if (0 == header_->e_shstrndx) {
596 *error_msg = StringPrintf("Failed to find non-zero e_shstrndx value in %s",
597 file_->GetPath().c_str());
598 return false;
599 }
600 if (header_->e_shstrndx >= header_->e_shnum) {
601 *error_msg = StringPrintf("Failed to find e_shnum value %d less than %d in %s",
602 header_->e_shstrndx,
603 header_->e_shnum,
604 file_->GetPath().c_str());
605 return false;
606 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800607
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800608 if (!program_header_only_) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800609 if (header_->e_phoff >= Size()) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700610 *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s",
611 static_cast<uint64_t>(header_->e_phoff),
Brian Carlstromc1409452014-02-26 14:06:23 -0800612 Size(),
613 file_->GetPath().c_str());
614 return false;
615 }
616 if (header_->e_shoff >= Size()) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700617 *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s",
618 static_cast<uint64_t>(header_->e_shoff),
Brian Carlstromc1409452014-02-26 14:06:23 -0800619 Size(),
620 file_->GetPath().c_str());
621 return false;
622 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800623 }
624 return true;
625}
626
Tong Shen62d1ca32014-09-03 17:24:56 -0700627template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
628 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
629 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
630Elf_Ehdr& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
631 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
632 ::GetHeader() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700633 CHECK(header_ != nullptr); // Header has been checked in SetMap. This is a sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800634 return *header_;
635}
636
Tong Shen62d1ca32014-09-03 17:24:56 -0700637template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
638 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
639 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700640uint8_t* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
Tong Shen62d1ca32014-09-03 17:24:56 -0700641 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
642 ::GetProgramHeadersStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700643 CHECK(program_headers_start_ != nullptr); // Header has been set in Setup. This is a sanity
644 // check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800645 return program_headers_start_;
646}
647
Tong Shen62d1ca32014-09-03 17:24:56 -0700648template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
649 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
650 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700651uint8_t* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
Tong Shen62d1ca32014-09-03 17:24:56 -0700652 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
653 ::GetSectionHeadersStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700654 CHECK(!program_header_only_); // Only used in "full" mode.
655 CHECK(section_headers_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800656 return section_headers_start_;
657}
658
Tong Shen62d1ca32014-09-03 17:24:56 -0700659template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
660 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
661 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
662Elf_Phdr& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
663 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
664 ::GetDynamicProgramHeader() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700665 CHECK(dynamic_program_header_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800666 return *dynamic_program_header_;
667}
668
Tong Shen62d1ca32014-09-03 17:24:56 -0700669template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
670 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
671 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
672Elf_Dyn* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
673 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
674 ::GetDynamicSectionStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700675 CHECK(dynamic_section_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800676 return dynamic_section_start_;
677}
678
Tong Shen62d1ca32014-09-03 17:24:56 -0700679template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
680 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
681 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
682Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
683 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
684 ::GetSymbolSectionStart(Elf_Word section_type) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800685 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800686 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000687 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700688 return symtab_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800689 break;
690 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000691 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700692 return dynsym_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800693 break;
694 }
695 default: {
696 LOG(FATAL) << section_type;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700697 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800698 }
699 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800700}
701
Tong Shen62d1ca32014-09-03 17:24:56 -0700702template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
703 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
704 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
705const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
706 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
707 ::GetStringSectionStart(Elf_Word section_type) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800708 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800709 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000710 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700711 return strtab_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800712 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000713 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700714 return dynstr_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800715 }
716 default: {
717 LOG(FATAL) << section_type;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700718 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800719 }
720 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800721}
722
Tong Shen62d1ca32014-09-03 17:24:56 -0700723template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
724 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
725 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
726const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
727 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
728 ::GetString(Elf_Word section_type, Elf_Word i) const {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800729 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
730 if (i == 0) {
Alex Light3470ab42014-06-18 10:35:45 -0700731 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800732 }
733 const char* string_section_start = GetStringSectionStart(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700734 if (string_section_start == nullptr) {
735 return nullptr;
736 }
737 return string_section_start + i;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800738}
739
Andreas Gampedaab38c2014-09-12 18:38:24 -0700740// WARNING: The following methods do not check for an error condition (non-existent hash section).
741// It is the caller's job to do this.
742
Tong Shen62d1ca32014-09-03 17:24:56 -0700743template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
744 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
745 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
746Elf_Word* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
747 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
748 ::GetHashSectionStart() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800749 return hash_section_start_;
750}
751
Tong Shen62d1ca32014-09-03 17:24:56 -0700752template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
753 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
754 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
755Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
756 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
757 ::GetHashBucketNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800758 return GetHashSectionStart()[0];
759}
760
Tong Shen62d1ca32014-09-03 17:24:56 -0700761template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
762 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
763 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
764Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
765 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
766 ::GetHashChainNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800767 return GetHashSectionStart()[1];
768}
769
Tong Shen62d1ca32014-09-03 17:24:56 -0700770template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
771 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
772 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
773Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
774 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
775 ::GetHashBucket(size_t i, bool* ok) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700776 if (i >= GetHashBucketNum()) {
777 *ok = false;
778 return 0;
779 }
780 *ok = true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800781 // 0 is nbucket, 1 is nchain
782 return GetHashSectionStart()[2 + i];
783}
784
Tong Shen62d1ca32014-09-03 17:24:56 -0700785template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
786 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
787 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
788Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
789 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
790 ::GetHashChain(size_t i, bool* ok) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700791 if (i >= GetHashBucketNum()) {
792 *ok = false;
793 return 0;
794 }
795 *ok = true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800796 // 0 is nbucket, 1 is nchain, & chains are after buckets
797 return GetHashSectionStart()[2 + GetHashBucketNum() + i];
798}
799
Tong Shen62d1ca32014-09-03 17:24:56 -0700800template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
801 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
802 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
803Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
804 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
805 ::GetProgramHeaderNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800806 return GetHeader().e_phnum;
807}
808
Tong Shen62d1ca32014-09-03 17:24:56 -0700809template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
810 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
811 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
812Elf_Phdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
813 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
814 ::GetProgramHeader(Elf_Word i) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700815 CHECK_LT(i, GetProgramHeaderNum()) << file_->GetPath(); // Sanity check for caller.
Ian Rogers13735952014-10-08 12:43:28 -0700816 uint8_t* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700817 if (program_header >= End()) {
818 return nullptr; // Failure condition.
819 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700820 return reinterpret_cast<Elf_Phdr*>(program_header);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800821}
822
Tong Shen62d1ca32014-09-03 17:24:56 -0700823template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
824 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
825 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
826Elf_Phdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
827 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
828 ::FindProgamHeaderByType(Elf_Word type) const {
829 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
830 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700831 if (program_header->p_type == type) {
832 return program_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800833 }
834 }
Alex Light3470ab42014-06-18 10:35:45 -0700835 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800836}
837
Tong Shen62d1ca32014-09-03 17:24:56 -0700838template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
839 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
840 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
841Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
842 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
843 ::GetSectionHeaderNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800844 return GetHeader().e_shnum;
845}
846
Tong Shen62d1ca32014-09-03 17:24:56 -0700847template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
848 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
849 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
850Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
851 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
852 ::GetSectionHeader(Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800853 // Can only access arbitrary sections when we have the whole file, not just program header.
854 // Even if we Load(), it doesn't bring in all the sections.
855 CHECK(!program_header_only_) << file_->GetPath();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700856 if (i >= GetSectionHeaderNum()) {
857 return nullptr; // Failure condition.
858 }
Ian Rogers13735952014-10-08 12:43:28 -0700859 uint8_t* section_header = GetSectionHeadersStart() + (i * GetHeader().e_shentsize);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700860 if (section_header >= End()) {
861 return nullptr; // Failure condition.
862 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700863 return reinterpret_cast<Elf_Shdr*>(section_header);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800864}
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 ::FindSectionByType(Elf_Word type) 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 // We could change this to switch on known types if they were detected during loading.
874 CHECK(!program_header_only_) << file_->GetPath();
Tong Shen62d1ca32014-09-03 17:24:56 -0700875 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
876 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700877 if (section_header->sh_type == type) {
878 return section_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800879 }
880 }
Alex Light3470ab42014-06-18 10:35:45 -0700881 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800882}
883
884// from bionic
Brian Carlstrom265091e2013-01-30 14:08:26 -0800885static unsigned elfhash(const char *_name) {
886 const unsigned char *name = (const unsigned char *) _name;
887 unsigned h = 0, g;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800888
Brian Carlstromdf629502013-07-17 22:39:56 -0700889 while (*name) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800890 h = (h << 4) + *name++;
891 g = h & 0xf0000000;
892 h ^= g;
893 h ^= g >> 24;
894 }
895 return h;
896}
897
Tong Shen62d1ca32014-09-03 17:24:56 -0700898template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
899 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
900 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
901Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
902 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
903 ::GetSectionNameStringSection() const {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800904 return GetSectionHeader(GetHeader().e_shstrndx);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800905}
906
Tong Shen62d1ca32014-09-03 17:24:56 -0700907template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
908 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
909 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700910const uint8_t* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
Tong Shen62d1ca32014-09-03 17:24:56 -0700911 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
912 ::FindDynamicSymbolAddress(const std::string& symbol_name) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700913 // Check that we have a hash section.
914 if (GetHashSectionStart() == nullptr) {
915 return nullptr; // Failure condition.
916 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700917 const Elf_Sym* sym = FindDynamicSymbol(symbol_name);
Alex Light3470ab42014-06-18 10:35:45 -0700918 if (sym != nullptr) {
919 return base_address_ + sym->st_value;
920 } else {
921 return nullptr;
922 }
923}
924
Andreas Gampedaab38c2014-09-12 18:38:24 -0700925// WARNING: Only called from FindDynamicSymbolAddress. Elides check for hash section.
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>
929const Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
930 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
931 ::FindDynamicSymbol(const std::string& symbol_name) const {
Andreas Gampec48b2062014-09-08 23:39:45 -0700932 if (GetHashBucketNum() == 0) {
933 // No dynamic symbols at all.
934 return nullptr;
935 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700936 Elf_Word hash = elfhash(symbol_name.c_str());
937 Elf_Word bucket_index = hash % GetHashBucketNum();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700938 bool ok;
Tong Shen62d1ca32014-09-03 17:24:56 -0700939 Elf_Word symbol_and_chain_index = GetHashBucket(bucket_index, &ok);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700940 if (!ok) {
941 return nullptr;
942 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800943 while (symbol_and_chain_index != 0 /* STN_UNDEF */) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700944 Elf_Sym* symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700945 if (symbol == nullptr) {
946 return nullptr; // Failure condition.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800947 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700948 const char* name = GetString(SHT_DYNSYM, symbol->st_name);
949 if (symbol_name == name) {
950 return symbol;
951 }
952 symbol_and_chain_index = GetHashChain(symbol_and_chain_index, &ok);
953 if (!ok) {
954 return nullptr;
955 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800956 }
Alex Light3470ab42014-06-18 10:35:45 -0700957 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800958}
959
Tong Shen62d1ca32014-09-03 17:24:56 -0700960template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
961 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
962 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
963bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
964 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
965 ::IsSymbolSectionType(Elf_Word section_type) {
966 return ((section_type == SHT_SYMTAB) || (section_type == SHT_DYNSYM));
967}
968
969template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
970 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
971 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
972Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
973 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
974 ::GetSymbolNum(Elf_Shdr& section_header) const {
Brian Carlstromc1409452014-02-26 14:06:23 -0800975 CHECK(IsSymbolSectionType(section_header.sh_type))
976 << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800977 CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath();
978 return section_header.sh_size / section_header.sh_entsize;
979}
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>
984Elf_Sym* 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 ::GetSymbol(Elf_Word section_type,
987 Elf_Word i) const {
988 Elf_Sym* sym_start = GetSymbolSectionStart(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700989 if (sym_start == nullptr) {
990 return nullptr;
991 }
992 return sym_start + i;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800993}
994
Tong Shen62d1ca32014-09-03 17:24:56 -0700995template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
996 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
997 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
998typename ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
999 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1000 ::SymbolTable** ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1001 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1002 ::GetSymbolTable(Elf_Word section_type) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001003 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
1004 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001005 case SHT_SYMTAB: {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001006 return &symtab_symbol_table_;
1007 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001008 case SHT_DYNSYM: {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001009 return &dynsym_symbol_table_;
1010 }
1011 default: {
1012 LOG(FATAL) << section_type;
Alex Light3470ab42014-06-18 10:35:45 -07001013 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001014 }
1015 }
1016}
1017
Tong Shen62d1ca32014-09-03 17:24:56 -07001018template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1019 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1020 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1021Elf_Sym* 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 ::FindSymbolByName(Elf_Word section_type,
1024 const std::string& symbol_name,
1025 bool build_map) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001026 CHECK(!program_header_only_) << file_->GetPath();
1027 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001028
1029 SymbolTable** symbol_table = GetSymbolTable(section_type);
Alex Light3470ab42014-06-18 10:35:45 -07001030 if (*symbol_table != nullptr || build_map) {
1031 if (*symbol_table == nullptr) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001032 DCHECK(build_map);
1033 *symbol_table = new SymbolTable;
Tong Shen62d1ca32014-09-03 17:24:56 -07001034 Elf_Shdr* symbol_section = FindSectionByType(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001035 if (symbol_section == nullptr) {
1036 return nullptr; // Failure condition.
1037 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001038 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001039 if (string_section == nullptr) {
1040 return nullptr; // Failure condition.
1041 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001042 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001043 Elf_Sym* symbol = GetSymbol(section_type, i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001044 if (symbol == nullptr) {
1045 return nullptr; // Failure condition.
1046 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001047 unsigned char type = (sizeof(Elf_Addr) == sizeof(Elf64_Addr))
1048 ? ELF64_ST_TYPE(symbol->st_info)
1049 : ELF32_ST_TYPE(symbol->st_info);
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001050 if (type == STT_NOTYPE) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001051 continue;
1052 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001053 const char* name = GetString(*string_section, symbol->st_name);
Alex Light3470ab42014-06-18 10:35:45 -07001054 if (name == nullptr) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001055 continue;
1056 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001057 std::pair<typename SymbolTable::iterator, bool> result =
Andreas Gampedaab38c2014-09-12 18:38:24 -07001058 (*symbol_table)->insert(std::make_pair(name, symbol));
Brian Carlstrom265091e2013-01-30 14:08:26 -08001059 if (!result.second) {
1060 // If a duplicate, make sure it has the same logical value. Seen on x86.
Andreas Gampedaab38c2014-09-12 18:38:24 -07001061 if ((symbol->st_value != result.first->second->st_value) ||
1062 (symbol->st_size != result.first->second->st_size) ||
1063 (symbol->st_info != result.first->second->st_info) ||
1064 (symbol->st_other != result.first->second->st_other) ||
1065 (symbol->st_shndx != result.first->second->st_shndx)) {
1066 return nullptr; // Failure condition.
1067 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001068 }
1069 }
1070 }
Alex Light3470ab42014-06-18 10:35:45 -07001071 CHECK(*symbol_table != nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07001072 typename SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001073 if (it == (*symbol_table)->end()) {
Alex Light3470ab42014-06-18 10:35:45 -07001074 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001075 }
1076 return it->second;
1077 }
1078
1079 // Fall back to linear search
Tong Shen62d1ca32014-09-03 17:24:56 -07001080 Elf_Shdr* symbol_section = FindSectionByType(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001081 if (symbol_section == nullptr) {
1082 return nullptr;
1083 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001084 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001085 if (string_section == nullptr) {
1086 return nullptr;
1087 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001088 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001089 Elf_Sym* symbol = GetSymbol(section_type, i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001090 if (symbol == nullptr) {
1091 return nullptr; // Failure condition.
1092 }
1093 const char* name = GetString(*string_section, symbol->st_name);
Alex Light3470ab42014-06-18 10:35:45 -07001094 if (name == nullptr) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001095 continue;
1096 }
1097 if (symbol_name == name) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001098 return symbol;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001099 }
1100 }
Alex Light3470ab42014-06-18 10:35:45 -07001101 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001102}
1103
Tong Shen62d1ca32014-09-03 17:24:56 -07001104template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1105 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1106 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1107Elf_Addr ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1108 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1109 ::FindSymbolAddress(Elf_Word section_type,
1110 const std::string& symbol_name,
1111 bool build_map) {
1112 Elf_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
Alex Light3470ab42014-06-18 10:35:45 -07001113 if (symbol == nullptr) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001114 return 0;
1115 }
1116 return symbol->st_value;
1117}
1118
Tong Shen62d1ca32014-09-03 17:24:56 -07001119template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1120 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1121 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1122const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1123 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1124 ::GetString(Elf_Shdr& string_section, Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001125 CHECK(!program_header_only_) << file_->GetPath();
1126 // TODO: remove this static_cast from enum when using -std=gnu++0x
Tong Shen62d1ca32014-09-03 17:24:56 -07001127 if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001128 return nullptr; // Failure condition.
1129 }
1130 if (i >= string_section.sh_size) {
1131 return nullptr;
1132 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001133 if (i == 0) {
Alex Light3470ab42014-06-18 10:35:45 -07001134 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001135 }
Ian Rogers13735952014-10-08 12:43:28 -07001136 uint8_t* strings = Begin() + string_section.sh_offset;
1137 uint8_t* string = strings + i;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001138 if (string >= End()) {
1139 return nullptr;
1140 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001141 return reinterpret_cast<const char*>(string);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001142}
1143
Tong Shen62d1ca32014-09-03 17:24:56 -07001144template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1145 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1146 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1147Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1148 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1149 ::GetDynamicNum() const {
1150 return GetDynamicProgramHeader().p_filesz / sizeof(Elf_Dyn);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001151}
1152
Tong Shen62d1ca32014-09-03 17:24:56 -07001153template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1154 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1155 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1156Elf_Dyn& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1157 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1158 ::GetDynamic(Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001159 CHECK_LT(i, GetDynamicNum()) << file_->GetPath();
1160 return *(GetDynamicSectionStart() + i);
1161}
1162
Tong Shen62d1ca32014-09-03 17:24:56 -07001163template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1164 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1165 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1166Elf_Dyn* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1167 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1168 ::FindDynamicByType(Elf_Sword type) const {
1169 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1170 Elf_Dyn* dyn = &GetDynamic(i);
Alex Light53cb16b2014-06-12 11:26:29 -07001171 if (dyn->d_tag == type) {
1172 return dyn;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001173 }
1174 }
Alex Light53cb16b2014-06-12 11:26:29 -07001175 return NULL;
1176}
1177
Tong Shen62d1ca32014-09-03 17:24:56 -07001178template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1179 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1180 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1181Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1182 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1183 ::FindDynamicValueByType(Elf_Sword type) const {
1184 Elf_Dyn* dyn = FindDynamicByType(type);
Alex Light53cb16b2014-06-12 11:26:29 -07001185 if (dyn == NULL) {
1186 return 0;
1187 } else {
1188 return dyn->d_un.d_val;
1189 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001190}
1191
Tong Shen62d1ca32014-09-03 17:24:56 -07001192template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1193 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1194 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1195Elf_Rel* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1196 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1197 ::GetRelSectionStart(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001198 CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Tong Shen62d1ca32014-09-03 17:24:56 -07001199 return reinterpret_cast<Elf_Rel*>(Begin() + section_header.sh_offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001200}
1201
Tong Shen62d1ca32014-09-03 17:24:56 -07001202template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1203 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1204 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1205Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1206 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1207 ::GetRelNum(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001208 CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001209 CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath();
1210 return section_header.sh_size / section_header.sh_entsize;
1211}
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 ::GetRel(Elf_Shdr& section_header, Elf_Word i) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001219 CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001220 CHECK_LT(i, GetRelNum(section_header)) << file_->GetPath();
1221 return *(GetRelSectionStart(section_header) + i);
1222}
1223
Tong Shen62d1ca32014-09-03 17:24:56 -07001224template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1225 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1226 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1227Elf_Rela* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1228 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1229 ::GetRelaSectionStart(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001230 CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Tong Shen62d1ca32014-09-03 17:24:56 -07001231 return reinterpret_cast<Elf_Rela*>(Begin() + section_header.sh_offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001232}
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_Word 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 ::GetRelaNum(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001240 CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001241 return section_header.sh_size / section_header.sh_entsize;
1242}
1243
Tong Shen62d1ca32014-09-03 17:24:56 -07001244template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1245 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1246 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1247Elf_Rela& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1248 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1249 ::GetRela(Elf_Shdr& section_header, Elf_Word i) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001250 CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001251 CHECK_LT(i, GetRelaNum(section_header)) << file_->GetPath();
1252 return *(GetRelaSectionStart(section_header) + i);
1253}
1254
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001255// Base on bionic phdr_table_get_load_size
Tong Shen62d1ca32014-09-03 17:24:56 -07001256template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1257 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1258 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1259size_t ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1260 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1261 ::GetLoadedSize() const {
1262 Elf_Addr min_vaddr = 0xFFFFFFFFu;
1263 Elf_Addr max_vaddr = 0x00000000u;
1264 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1265 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001266 if (program_header->p_type != PT_LOAD) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001267 continue;
1268 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001269 Elf_Addr begin_vaddr = program_header->p_vaddr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001270 if (begin_vaddr < min_vaddr) {
1271 min_vaddr = begin_vaddr;
1272 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001273 Elf_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001274 if (end_vaddr > max_vaddr) {
1275 max_vaddr = end_vaddr;
1276 }
1277 }
1278 min_vaddr = RoundDown(min_vaddr, kPageSize);
1279 max_vaddr = RoundUp(max_vaddr, kPageSize);
1280 CHECK_LT(min_vaddr, max_vaddr) << file_->GetPath();
1281 size_t loaded_size = max_vaddr - min_vaddr;
1282 return loaded_size;
1283}
1284
Tong Shen62d1ca32014-09-03 17:24:56 -07001285template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1286 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1287 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1288bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1289 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1290 ::Load(bool executable, std::string* error_msg) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001291 CHECK(program_header_only_) << file_->GetPath();
Andreas Gampe91268c12014-04-03 17:50:24 -07001292
1293 if (executable) {
1294 InstructionSet elf_ISA = kNone;
1295 switch (GetHeader().e_machine) {
1296 case EM_ARM: {
1297 elf_ISA = kArm;
1298 break;
1299 }
1300 case EM_AARCH64: {
1301 elf_ISA = kArm64;
1302 break;
1303 }
1304 case EM_386: {
1305 elf_ISA = kX86;
1306 break;
1307 }
1308 case EM_X86_64: {
1309 elf_ISA = kX86_64;
1310 break;
1311 }
1312 case EM_MIPS: {
1313 elf_ISA = kMips;
1314 break;
1315 }
1316 }
1317
1318 if (elf_ISA != kRuntimeISA) {
1319 std::ostringstream oss;
1320 oss << "Expected ISA " << kRuntimeISA << " but found " << elf_ISA;
1321 *error_msg = oss.str();
1322 return false;
1323 }
1324 }
1325
Jim_Guoa62a5882014-04-28 11:11:57 +08001326 bool reserved = false;
Tong Shen62d1ca32014-09-03 17:24:56 -07001327 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1328 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001329 if (program_header == nullptr) {
1330 *error_msg = StringPrintf("No program header for entry %d in ELF file %s.",
1331 i, file_->GetPath().c_str());
1332 return false;
1333 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001334
1335 // Record .dynamic header information for later use
Andreas Gampedaab38c2014-09-12 18:38:24 -07001336 if (program_header->p_type == PT_DYNAMIC) {
1337 dynamic_program_header_ = program_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001338 continue;
1339 }
1340
1341 // Not something to load, move on.
Andreas Gampedaab38c2014-09-12 18:38:24 -07001342 if (program_header->p_type != PT_LOAD) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001343 continue;
1344 }
1345
1346 // Found something to load.
1347
Jim_Guoa62a5882014-04-28 11:11:57 +08001348 // Before load the actual segments, reserve a contiguous chunk
1349 // of required size and address for all segments, but with no
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001350 // permissions. We'll then carve that up with the proper
1351 // permissions as we load the actual segments. If p_vaddr is
1352 // non-zero, the segments require the specific address specified,
1353 // which either was specified in the file because we already set
1354 // base_address_ after the first zero segment).
Ian Rogerscdfcf372014-01-23 20:38:36 -08001355 int64_t temp_file_length = file_->GetLength();
1356 if (temp_file_length < 0) {
1357 errno = -temp_file_length;
1358 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
1359 file_->GetPath().c_str(), file_->Fd(), strerror(errno));
1360 return false;
1361 }
1362 size_t file_length = static_cast<size_t>(temp_file_length);
Jim_Guoa62a5882014-04-28 11:11:57 +08001363 if (!reserved) {
Ian Rogers13735952014-10-08 12:43:28 -07001364 uint8_t* reserve_base = ((program_header->p_vaddr != 0) ?
1365 reinterpret_cast<uint8_t*>(program_header->p_vaddr) : nullptr);
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001366 std::string reservation_name("ElfFile reservation for ");
1367 reservation_name += file_->GetPath();
Ian Rogers700a4022014-05-19 16:49:03 -07001368 std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
Jim_Guoa62a5882014-04-28 11:11:57 +08001369 reserve_base,
1370 GetLoadedSize(), PROT_NONE, false,
1371 error_msg));
Brian Carlstromc1409452014-02-26 14:06:23 -08001372 if (reserve.get() == nullptr) {
1373 *error_msg = StringPrintf("Failed to allocate %s: %s",
1374 reservation_name.c_str(), error_msg->c_str());
1375 return false;
1376 }
Jim_Guoa62a5882014-04-28 11:11:57 +08001377 reserved = true;
1378 if (reserve_base == nullptr) {
1379 base_address_ = reserve->Begin();
1380 }
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001381 segments_.push_back(reserve.release());
1382 }
1383 // empty segment, nothing to map
Andreas Gampedaab38c2014-09-12 18:38:24 -07001384 if (program_header->p_memsz == 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001385 continue;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001386 }
Ian Rogers13735952014-10-08 12:43:28 -07001387 uint8_t* p_vaddr = base_address_ + program_header->p_vaddr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001388 int prot = 0;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001389 if (executable && ((program_header->p_flags & PF_X) != 0)) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001390 prot |= PROT_EXEC;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001391 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001392 if ((program_header->p_flags & PF_W) != 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001393 prot |= PROT_WRITE;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001394 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001395 if ((program_header->p_flags & PF_R) != 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001396 prot |= PROT_READ;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001397 }
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -07001398 int flags = 0;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001399 if (writable_) {
1400 prot |= PROT_WRITE;
1401 flags |= MAP_SHARED;
1402 } else {
1403 flags |= MAP_PRIVATE;
1404 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001405 if (file_length < (program_header->p_offset + program_header->p_memsz)) {
Ian Rogerscdfcf372014-01-23 20:38:36 -08001406 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment "
Tong Shen62d1ca32014-09-03 17:24:56 -07001407 "%d of %" PRIu64 " bytes: '%s'", file_length, i,
1408 static_cast<uint64_t>(program_header->p_offset + program_header->p_memsz),
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001409 file_->GetPath().c_str());
Brian Carlstrom3a223612013-10-10 17:18:24 -07001410 return false;
1411 }
Ian Rogers700a4022014-05-19 16:49:03 -07001412 std::unique_ptr<MemMap> segment(MemMap::MapFileAtAddress(p_vaddr,
Andreas Gampedaab38c2014-09-12 18:38:24 -07001413 program_header->p_memsz,
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001414 prot, flags, file_->Fd(),
Andreas Gampedaab38c2014-09-12 18:38:24 -07001415 program_header->p_offset,
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -07001416 true, // implies MAP_FIXED
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001417 file_->GetPath().c_str(),
1418 error_msg));
Brian Carlstromc1409452014-02-26 14:06:23 -08001419 if (segment.get() == nullptr) {
1420 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s",
1421 i, file_->GetPath().c_str(), error_msg->c_str());
1422 return false;
1423 }
1424 if (segment->Begin() != p_vaddr) {
1425 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, "
1426 "instead mapped to %p",
1427 i, file_->GetPath().c_str(), p_vaddr, segment->Begin());
1428 return false;
1429 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001430 segments_.push_back(segment.release());
1431 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001432
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001433 // Now that we are done loading, .dynamic should be in memory to find .dynstr, .dynsym, .hash
Ian Rogers13735952014-10-08 12:43:28 -07001434 uint8_t* dsptr = base_address_ + GetDynamicProgramHeader().p_vaddr;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001435 if ((dsptr < Begin() || dsptr >= End()) && !ValidPointer(dsptr)) {
1436 *error_msg = StringPrintf("dynamic section address invalid in ELF file %s",
1437 file_->GetPath().c_str());
1438 return false;
1439 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001440 dynamic_section_start_ = reinterpret_cast<Elf_Dyn*>(dsptr);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001441
Tong Shen62d1ca32014-09-03 17:24:56 -07001442 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1443 Elf_Dyn& elf_dyn = GetDynamic(i);
Ian Rogers13735952014-10-08 12:43:28 -07001444 uint8_t* d_ptr = base_address_ + elf_dyn.d_un.d_ptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001445 switch (elf_dyn.d_tag) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001446 case DT_HASH: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001447 if (!ValidPointer(d_ptr)) {
1448 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1449 d_ptr, file_->GetPath().c_str());
1450 return false;
1451 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001452 hash_section_start_ = reinterpret_cast<Elf_Word*>(d_ptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001453 break;
1454 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001455 case DT_STRTAB: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001456 if (!ValidPointer(d_ptr)) {
1457 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1458 d_ptr, file_->GetPath().c_str());
1459 return false;
1460 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001461 dynstr_section_start_ = reinterpret_cast<char*>(d_ptr);
1462 break;
1463 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001464 case DT_SYMTAB: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001465 if (!ValidPointer(d_ptr)) {
1466 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1467 d_ptr, file_->GetPath().c_str());
1468 return false;
1469 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001470 dynsym_section_start_ = reinterpret_cast<Elf_Sym*>(d_ptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001471 break;
1472 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001473 case DT_NULL: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001474 if (GetDynamicNum() != i+1) {
1475 *error_msg = StringPrintf("DT_NULL found after %d .dynamic entries, "
1476 "expected %d as implied by size of PT_DYNAMIC segment in %s",
1477 i + 1, GetDynamicNum(), file_->GetPath().c_str());
1478 return false;
1479 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001480 break;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001481 }
1482 }
1483 }
1484
Andreas Gampedaab38c2014-09-12 18:38:24 -07001485 // Check for the existence of some sections.
1486 if (!CheckSectionsExist(error_msg)) {
1487 return false;
1488 }
1489
Mark Mendellae9fd932014-02-10 16:14:35 -08001490 // Use GDB JIT support to do stack backtrace, etc.
1491 if (executable) {
1492 GdbJITSupport();
1493 }
1494
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001495 return true;
1496}
1497
Tong Shen62d1ca32014-09-03 17:24:56 -07001498template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1499 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1500 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1501bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1502 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -07001503 ::ValidPointer(const uint8_t* start) const {
Brian Carlstromc1409452014-02-26 14:06:23 -08001504 for (size_t i = 0; i < segments_.size(); ++i) {
1505 const MemMap* segment = segments_[i];
1506 if (segment->Begin() <= start && start < segment->End()) {
1507 return true;
1508 }
1509 }
1510 return false;
1511}
1512
Alex Light3470ab42014-06-18 10:35:45 -07001513
Tong Shen62d1ca32014-09-03 17:24:56 -07001514template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1515 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1516 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1517Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1518 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1519 ::FindSectionByName(const std::string& name) const {
Alex Light3470ab42014-06-18 10:35:45 -07001520 CHECK(!program_header_only_);
Tong Shen62d1ca32014-09-03 17:24:56 -07001521 Elf_Shdr* shstrtab_sec = GetSectionNameStringSection();
Andreas Gampedaab38c2014-09-12 18:38:24 -07001522 if (shstrtab_sec == nullptr) {
1523 return nullptr;
1524 }
Alex Light3470ab42014-06-18 10:35:45 -07001525 for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001526 Elf_Shdr* shdr = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001527 if (shdr == nullptr) {
1528 return nullptr;
1529 }
1530 const char* sec_name = GetString(*shstrtab_sec, shdr->sh_name);
Alex Light3470ab42014-06-18 10:35:45 -07001531 if (sec_name == nullptr) {
1532 continue;
1533 }
1534 if (name == sec_name) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001535 return shdr;
Alex Light3470ab42014-06-18 10:35:45 -07001536 }
1537 }
1538 return nullptr;
Mark Mendellae9fd932014-02-10 16:14:35 -08001539}
1540
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001541struct PACKED(1) FDE32 {
Alex Light3470ab42014-06-18 10:35:45 -07001542 uint32_t raw_length_;
1543 uint32_t GetLength() {
1544 return raw_length_ + sizeof(raw_length_);
1545 }
1546 uint32_t CIE_pointer;
1547 uint32_t initial_location;
1548 uint32_t address_range;
1549 uint8_t instructions[0];
1550};
1551
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001552static FDE32* NextFDE(FDE32* frame) {
Ian Rogers13735952014-10-08 12:43:28 -07001553 uint8_t* fde_bytes = reinterpret_cast<uint8_t*>(frame);
Alex Light3470ab42014-06-18 10:35:45 -07001554 fde_bytes += frame->GetLength();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001555 return reinterpret_cast<FDE32*>(fde_bytes);
Mark Mendellae9fd932014-02-10 16:14:35 -08001556}
1557
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001558static bool IsFDE(FDE32* frame) {
Tong Shen35e1e6a2014-07-30 09:31:22 -07001559 return frame->CIE_pointer != 0;
Alex Light3470ab42014-06-18 10:35:45 -07001560}
1561
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001562struct PACKED(1) FDE64 {
1563 uint32_t raw_length_;
1564 uint64_t extended_length_;
1565 uint64_t GetLength() {
1566 return extended_length_ + sizeof(raw_length_) + sizeof(extended_length_);
1567 }
1568 uint64_t CIE_pointer;
1569 uint64_t initial_location;
1570 uint64_t address_range;
1571 uint8_t instructions[0];
1572};
1573
1574static FDE64* NextFDE(FDE64* frame) {
Ian Rogers13735952014-10-08 12:43:28 -07001575 uint8_t* fde_bytes = reinterpret_cast<uint8_t*>(frame);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001576 fde_bytes += frame->GetLength();
1577 return reinterpret_cast<FDE64*>(fde_bytes);
1578}
1579
1580static bool IsFDE(FDE64* frame) {
1581 return frame->CIE_pointer != 0;
1582}
1583
1584static bool FixupEHFrame(off_t base_address_delta,
Ian Rogers13735952014-10-08 12:43:28 -07001585 uint8_t* eh_frame, size_t eh_frame_size) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001586 if (*(reinterpret_cast<uint32_t*>(eh_frame)) == 0xffffffff) {
1587 FDE64* last_frame = reinterpret_cast<FDE64*>(eh_frame + eh_frame_size);
1588 FDE64* frame = NextFDE(reinterpret_cast<FDE64*>(eh_frame));
1589 for (; frame < last_frame; frame = NextFDE(frame)) {
1590 if (!IsFDE(frame)) {
1591 return false;
1592 }
1593 frame->initial_location += base_address_delta;
1594 }
1595 return true;
1596 } else {
1597 FDE32* last_frame = reinterpret_cast<FDE32*>(eh_frame + eh_frame_size);
1598 FDE32* frame = NextFDE(reinterpret_cast<FDE32*>(eh_frame));
1599 for (; frame < last_frame; frame = NextFDE(frame)) {
1600 if (!IsFDE(frame)) {
1601 return false;
1602 }
1603 frame->initial_location += base_address_delta;
1604 }
1605 return true;
1606 }
1607}
1608
1609static uint8_t* NextLeb128(uint8_t* current) {
1610 DecodeUnsignedLeb128(const_cast<const uint8_t**>(&current));
1611 return current;
1612}
1613
1614struct PACKED(1) DebugLineHeader {
1615 uint32_t unit_length_; // TODO 32-bit specific size
1616 uint16_t version_;
1617 uint32_t header_length_; // TODO 32-bit specific size
1618 uint8_t minimum_instruction_lenght_;
1619 uint8_t maximum_operations_per_instruction_;
1620 uint8_t default_is_stmt_;
1621 int8_t line_base_;
1622 uint8_t line_range_;
1623 uint8_t opcode_base_;
1624 uint8_t remaining_[0];
1625
1626 bool IsStandardOpcode(const uint8_t* op) const {
1627 return *op != 0 && *op < opcode_base_;
1628 }
1629
1630 bool IsExtendedOpcode(const uint8_t* op) const {
1631 return *op == 0;
1632 }
1633
1634 const uint8_t* GetStandardOpcodeLengths() const {
1635 return remaining_;
1636 }
1637
1638 uint8_t* GetNextOpcode(uint8_t* op) const {
1639 if (IsExtendedOpcode(op)) {
1640 uint8_t* length_field = op + 1;
1641 uint32_t length = DecodeUnsignedLeb128(const_cast<const uint8_t**>(&length_field));
1642 return length_field + length;
1643 } else if (!IsStandardOpcode(op)) {
1644 return op + 1;
1645 } else if (*op == DW_LNS_fixed_advance_pc) {
1646 return op + 1 + sizeof(uint16_t);
1647 } else {
1648 uint8_t num_args = GetStandardOpcodeLengths()[*op - 1];
1649 op += 1;
1650 for (int i = 0; i < num_args; i++) {
1651 op = NextLeb128(op);
1652 }
1653 return op;
1654 }
1655 }
1656
1657 uint8_t* GetDebugLineData() const {
1658 const uint8_t* hdr_start =
1659 reinterpret_cast<const uint8_t*>(&header_length_) + sizeof(header_length_);
1660 return const_cast<uint8_t*>(hdr_start + header_length_);
1661 }
1662};
1663
1664class DebugLineInstructionIterator {
1665 public:
1666 static DebugLineInstructionIterator* Create(DebugLineHeader* header, size_t section_size) {
1667 std::unique_ptr<DebugLineInstructionIterator> line_iter(
1668 new DebugLineInstructionIterator(header, section_size));
1669 if (line_iter.get() == nullptr) {
1670 return nullptr;
1671 } else {
1672 return line_iter.release();
1673 }
1674 }
1675
1676 ~DebugLineInstructionIterator() {}
1677
1678 bool Next() {
1679 if (current_instruction_ == nullptr) {
Alex Light3470ab42014-06-18 10:35:45 -07001680 return false;
1681 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001682 current_instruction_ = header_->GetNextOpcode(current_instruction_);
1683 if (current_instruction_ >= last_instruction_) {
1684 current_instruction_ = nullptr;
1685 return false;
1686 } else {
1687 return true;
1688 }
1689 }
1690
1691 uint8_t* GetInstruction() {
1692 return current_instruction_;
1693 }
1694
1695 bool IsExtendedOpcode() {
1696 return header_->IsExtendedOpcode(current_instruction_);
1697 }
1698
1699 uint8_t GetOpcode() {
1700 if (!IsExtendedOpcode()) {
1701 return *current_instruction_;
1702 } else {
1703 uint8_t* len_ptr = current_instruction_ + 1;
1704 return *NextLeb128(len_ptr);
1705 }
1706 }
1707
1708 uint8_t* GetArguments() {
1709 if (!IsExtendedOpcode()) {
1710 return current_instruction_ + 1;
1711 } else {
1712 uint8_t* len_ptr = current_instruction_ + 1;
1713 return NextLeb128(len_ptr) + 1;
1714 }
1715 }
1716
1717 private:
1718 DebugLineInstructionIterator(DebugLineHeader* header, size_t size)
1719 : header_(header), last_instruction_(reinterpret_cast<uint8_t*>(header) + size),
1720 current_instruction_(header->GetDebugLineData()) {}
1721
1722 DebugLineHeader* header_;
1723 uint8_t* last_instruction_;
1724 uint8_t* current_instruction_;
1725};
1726
1727static bool FixupDebugLine(off_t base_offset_delta, DebugLineInstructionIterator* iter) {
1728 while (iter->Next()) {
1729 if (iter->IsExtendedOpcode() && iter->GetOpcode() == DW_LNE_set_address) {
1730 *reinterpret_cast<uint32_t*>(iter->GetArguments()) += base_offset_delta;
1731 }
Alex Light3470ab42014-06-18 10:35:45 -07001732 }
1733 return true;
1734}
1735
1736struct PACKED(1) DebugInfoHeader {
1737 uint32_t unit_length; // TODO 32-bit specific size
1738 uint16_t version;
1739 uint32_t debug_abbrev_offset; // TODO 32-bit specific size
1740 uint8_t address_size;
1741};
1742
1743// Returns -1 if it is variable length, which we will just disallow for now.
1744static int32_t FormLength(uint32_t att) {
1745 switch (att) {
1746 case DW_FORM_data1:
1747 case DW_FORM_flag:
1748 case DW_FORM_flag_present:
1749 case DW_FORM_ref1:
1750 return 1;
1751
1752 case DW_FORM_data2:
1753 case DW_FORM_ref2:
1754 return 2;
1755
1756 case DW_FORM_addr: // TODO 32-bit only
1757 case DW_FORM_ref_addr: // TODO 32-bit only
1758 case DW_FORM_sec_offset: // TODO 32-bit only
1759 case DW_FORM_strp: // TODO 32-bit only
1760 case DW_FORM_data4:
1761 case DW_FORM_ref4:
1762 return 4;
1763
1764 case DW_FORM_data8:
1765 case DW_FORM_ref8:
1766 case DW_FORM_ref_sig8:
1767 return 8;
1768
1769 case DW_FORM_block:
1770 case DW_FORM_block1:
1771 case DW_FORM_block2:
1772 case DW_FORM_block4:
1773 case DW_FORM_exprloc:
1774 case DW_FORM_indirect:
1775 case DW_FORM_ref_udata:
1776 case DW_FORM_sdata:
1777 case DW_FORM_string:
1778 case DW_FORM_udata:
1779 default:
1780 return -1;
Mark Mendellae9fd932014-02-10 16:14:35 -08001781 }
1782}
1783
Alex Light3470ab42014-06-18 10:35:45 -07001784class DebugTag {
1785 public:
1786 const uint32_t index_;
1787 ~DebugTag() {}
1788 // Creates a new tag and moves data pointer up to the start of the next one.
1789 // nullptr means error.
Ian Rogers13735952014-10-08 12:43:28 -07001790 static DebugTag* Create(const uint8_t** data_pointer) {
1791 const uint8_t* data = *data_pointer;
Alex Light3470ab42014-06-18 10:35:45 -07001792 uint32_t index = DecodeUnsignedLeb128(&data);
1793 std::unique_ptr<DebugTag> tag(new DebugTag(index));
1794 tag->size_ = static_cast<uint32_t>(
1795 reinterpret_cast<uintptr_t>(data) - reinterpret_cast<uintptr_t>(*data_pointer));
1796 // skip the abbrev
1797 tag->tag_ = DecodeUnsignedLeb128(&data);
1798 tag->has_child_ = (*data == 0);
1799 data++;
1800 while (true) {
1801 uint32_t attr = DecodeUnsignedLeb128(&data);
1802 uint32_t form = DecodeUnsignedLeb128(&data);
1803 if (attr == 0 && form == 0) {
1804 break;
1805 } else if (attr == 0 || form == 0) {
1806 // Bad abbrev.
1807 return nullptr;
1808 }
1809 int32_t size = FormLength(form);
1810 if (size == -1) {
1811 return nullptr;
1812 }
1813 tag->AddAttribute(attr, static_cast<uint32_t>(size));
1814 }
1815 *data_pointer = data;
1816 return tag.release();
1817 }
1818
1819 uint32_t GetSize() const {
1820 return size_;
1821 }
1822
1823 bool HasChild() {
1824 return has_child_;
1825 }
1826
1827 uint32_t GetTagNumber() {
1828 return tag_;
1829 }
1830
1831 // Gets the offset of a particular attribute in this tag structure.
1832 // Interpretation of the data is left to the consumer. 0 is returned if the
1833 // tag does not contain the attribute.
1834 uint32_t GetOffsetOf(uint32_t dwarf_attribute) const {
1835 auto it = off_map_.find(dwarf_attribute);
1836 if (it == off_map_.end()) {
1837 return 0;
1838 } else {
1839 return it->second;
1840 }
1841 }
1842
1843 // Gets the size of attribute
1844 uint32_t GetAttrSize(uint32_t dwarf_attribute) const {
1845 auto it = size_map_.find(dwarf_attribute);
1846 if (it == size_map_.end()) {
1847 return 0;
1848 } else {
1849 return it->second;
1850 }
1851 }
1852
1853 private:
Andreas Gampedaab38c2014-09-12 18:38:24 -07001854 explicit DebugTag(uint32_t index) : index_(index), size_(0), tag_(0), has_child_(false) {}
Alex Light3470ab42014-06-18 10:35:45 -07001855 void AddAttribute(uint32_t type, uint32_t attr_size) {
1856 off_map_.insert(std::pair<uint32_t, uint32_t>(type, size_));
1857 size_map_.insert(std::pair<uint32_t, uint32_t>(type, attr_size));
1858 size_ += attr_size;
1859 }
1860 std::map<uint32_t, uint32_t> off_map_;
1861 std::map<uint32_t, uint32_t> size_map_;
1862 uint32_t size_;
1863 uint32_t tag_;
1864 bool has_child_;
1865};
1866
1867class DebugAbbrev {
1868 public:
1869 ~DebugAbbrev() {}
Ian Rogers13735952014-10-08 12:43:28 -07001870 static DebugAbbrev* Create(const uint8_t* dbg_abbrev, size_t dbg_abbrev_size) {
Alex Lightd338ae02014-08-13 17:15:38 -07001871 std::unique_ptr<DebugAbbrev> abbrev(new DebugAbbrev(dbg_abbrev, dbg_abbrev + dbg_abbrev_size));
1872 if (!abbrev->ReadAtOffset(0)) {
1873 return nullptr;
Alex Light3470ab42014-06-18 10:35:45 -07001874 }
1875 return abbrev.release();
1876 }
1877
Alex Lightd338ae02014-08-13 17:15:38 -07001878 bool ReadAtOffset(uint32_t abbrev_offset) {
1879 tags_.clear();
1880 tag_list_.clear();
Ian Rogers13735952014-10-08 12:43:28 -07001881 const uint8_t* dbg_abbrev = begin_ + abbrev_offset;
Alex Lightd338ae02014-08-13 17:15:38 -07001882 while (dbg_abbrev < end_ && *dbg_abbrev != 0) {
1883 std::unique_ptr<DebugTag> tag(DebugTag::Create(&dbg_abbrev));
1884 if (tag.get() == nullptr) {
1885 return false;
1886 } else {
1887 tags_.insert(std::pair<uint32_t, uint32_t>(tag->index_, tag_list_.size()));
1888 tag_list_.push_back(std::move(tag));
1889 }
1890 }
1891 return true;
1892 }
1893
Ian Rogers13735952014-10-08 12:43:28 -07001894 DebugTag* ReadTag(const uint8_t* entry) {
Alex Light3470ab42014-06-18 10:35:45 -07001895 uint32_t tag_num = DecodeUnsignedLeb128(&entry);
1896 auto it = tags_.find(tag_num);
1897 if (it == tags_.end()) {
1898 return nullptr;
1899 } else {
1900 CHECK_GT(tag_list_.size(), it->second);
1901 return tag_list_.at(it->second).get();
1902 }
1903 }
1904
1905 private:
Ian Rogers13735952014-10-08 12:43:28 -07001906 DebugAbbrev(const uint8_t* begin, const uint8_t* end) : begin_(begin), end_(end) {}
1907 const uint8_t* begin_;
1908 const uint8_t* end_;
Alex Light3470ab42014-06-18 10:35:45 -07001909 std::map<uint32_t, uint32_t> tags_;
1910 std::vector<std::unique_ptr<DebugTag>> tag_list_;
1911};
1912
1913class DebugInfoIterator {
1914 public:
1915 static DebugInfoIterator* Create(DebugInfoHeader* header, size_t frame_size,
1916 DebugAbbrev* abbrev) {
1917 std::unique_ptr<DebugInfoIterator> iter(new DebugInfoIterator(header, frame_size, abbrev));
1918 if (iter->GetCurrentTag() == nullptr) {
1919 return nullptr;
1920 } else {
1921 return iter.release();
1922 }
1923 }
1924 ~DebugInfoIterator() {}
1925
1926 // Moves to the next DIE. Returns false if at last entry.
1927 // TODO Handle variable length attributes.
1928 bool next() {
1929 if (current_entry_ == nullptr || current_tag_ == nullptr) {
1930 return false;
1931 }
Alex Lightd338ae02014-08-13 17:15:38 -07001932 bool reread_abbrev = false;
Alex Light3470ab42014-06-18 10:35:45 -07001933 current_entry_ += current_tag_->GetSize();
Alex Lightd338ae02014-08-13 17:15:38 -07001934 if (reinterpret_cast<DebugInfoHeader*>(current_entry_) >= next_cu_) {
1935 current_cu_ = next_cu_;
1936 next_cu_ = GetNextCu(current_cu_);
Ian Rogers13735952014-10-08 12:43:28 -07001937 current_entry_ = reinterpret_cast<uint8_t*>(current_cu_) + sizeof(DebugInfoHeader);
Alex Lightd338ae02014-08-13 17:15:38 -07001938 reread_abbrev = true;
1939 }
Alex Light3470ab42014-06-18 10:35:45 -07001940 if (current_entry_ >= last_entry_) {
1941 current_entry_ = nullptr;
1942 return false;
1943 }
Alex Lightd338ae02014-08-13 17:15:38 -07001944 if (reread_abbrev) {
1945 abbrev_->ReadAtOffset(current_cu_->debug_abbrev_offset);
1946 }
Alex Light3470ab42014-06-18 10:35:45 -07001947 current_tag_ = abbrev_->ReadTag(current_entry_);
1948 if (current_tag_ == nullptr) {
1949 current_entry_ = nullptr;
1950 return false;
1951 } else {
1952 return true;
1953 }
1954 }
1955
1956 const DebugTag* GetCurrentTag() {
1957 return const_cast<DebugTag*>(current_tag_);
1958 }
Ian Rogers13735952014-10-08 12:43:28 -07001959 uint8_t* GetPointerToField(uint8_t dwarf_field) {
Alex Light3470ab42014-06-18 10:35:45 -07001960 if (current_tag_ == nullptr || current_entry_ == nullptr || current_entry_ >= last_entry_) {
1961 return nullptr;
1962 }
1963 uint32_t off = current_tag_->GetOffsetOf(dwarf_field);
1964 if (off == 0) {
1965 // tag does not have that field.
1966 return nullptr;
1967 } else {
1968 DCHECK_LT(off, current_tag_->GetSize());
1969 return current_entry_ + off;
1970 }
1971 }
1972
1973 private:
Alex Lightd338ae02014-08-13 17:15:38 -07001974 static DebugInfoHeader* GetNextCu(DebugInfoHeader* hdr) {
Ian Rogers13735952014-10-08 12:43:28 -07001975 uint8_t* hdr_byte = reinterpret_cast<uint8_t*>(hdr);
Alex Lightd338ae02014-08-13 17:15:38 -07001976 return reinterpret_cast<DebugInfoHeader*>(hdr_byte + sizeof(uint32_t) + hdr->unit_length);
1977 }
1978
Alex Light3470ab42014-06-18 10:35:45 -07001979 DebugInfoIterator(DebugInfoHeader* header, size_t frame_size, DebugAbbrev* abbrev)
1980 : abbrev_(abbrev),
Alex Lightd338ae02014-08-13 17:15:38 -07001981 current_cu_(header),
1982 next_cu_(GetNextCu(header)),
Ian Rogers13735952014-10-08 12:43:28 -07001983 last_entry_(reinterpret_cast<uint8_t*>(header) + frame_size),
1984 current_entry_(reinterpret_cast<uint8_t*>(header) + sizeof(DebugInfoHeader)),
Alex Light3470ab42014-06-18 10:35:45 -07001985 current_tag_(abbrev_->ReadTag(current_entry_)) {}
1986 DebugAbbrev* abbrev_;
Alex Lightd338ae02014-08-13 17:15:38 -07001987 DebugInfoHeader* current_cu_;
1988 DebugInfoHeader* next_cu_;
Ian Rogers13735952014-10-08 12:43:28 -07001989 uint8_t* last_entry_;
1990 uint8_t* current_entry_;
Alex Light3470ab42014-06-18 10:35:45 -07001991 DebugTag* current_tag_;
1992};
1993
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001994static bool FixupDebugInfo(off_t base_address_delta, DebugInfoIterator* iter) {
Alex Light3470ab42014-06-18 10:35:45 -07001995 do {
1996 if (iter->GetCurrentTag()->GetAttrSize(DW_AT_low_pc) != sizeof(int32_t) ||
1997 iter->GetCurrentTag()->GetAttrSize(DW_AT_high_pc) != sizeof(int32_t)) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001998 LOG(ERROR) << "DWARF information with 64 bit pointers is not supported yet.";
Alex Light3470ab42014-06-18 10:35:45 -07001999 return false;
2000 }
2001 uint32_t* PC_low = reinterpret_cast<uint32_t*>(iter->GetPointerToField(DW_AT_low_pc));
2002 uint32_t* PC_high = reinterpret_cast<uint32_t*>(iter->GetPointerToField(DW_AT_high_pc));
2003 if (PC_low != nullptr && PC_high != nullptr) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002004 *PC_low += base_address_delta;
2005 *PC_high += base_address_delta;
Alex Light3470ab42014-06-18 10:35:45 -07002006 }
2007 } while (iter->next());
2008 return true;
2009}
2010
Tong Shen62d1ca32014-09-03 17:24:56 -07002011template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2012 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2013 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2014bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2015 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2016 ::FixupDebugSections(off_t base_address_delta) {
2017 const Elf_Shdr* debug_info = FindSectionByName(".debug_info");
2018 const Elf_Shdr* debug_abbrev = FindSectionByName(".debug_abbrev");
2019 const Elf_Shdr* eh_frame = FindSectionByName(".eh_frame");
2020 const Elf_Shdr* debug_str = FindSectionByName(".debug_str");
2021 const Elf_Shdr* debug_line = FindSectionByName(".debug_line");
2022 const Elf_Shdr* strtab_sec = FindSectionByName(".strtab");
2023 const Elf_Shdr* symtab_sec = FindSectionByName(".symtab");
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002024
2025 if (debug_info == nullptr || debug_abbrev == nullptr ||
2026 debug_str == nullptr || strtab_sec == nullptr || symtab_sec == nullptr) {
2027 // Release version of ART does not generate debug info.
2028 return true;
2029 }
2030 if (base_address_delta == 0) {
2031 return true;
2032 }
2033 if (eh_frame != nullptr &&
2034 !FixupEHFrame(base_address_delta, Begin() + eh_frame->sh_offset, eh_frame->sh_size)) {
2035 return false;
2036 }
2037
2038 std::unique_ptr<DebugAbbrev> abbrev(DebugAbbrev::Create(Begin() + debug_abbrev->sh_offset,
2039 debug_abbrev->sh_size));
Alex Light3470ab42014-06-18 10:35:45 -07002040 if (abbrev.get() == nullptr) {
2041 return false;
2042 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002043 DebugInfoHeader* info_header =
2044 reinterpret_cast<DebugInfoHeader*>(Begin() + debug_info->sh_offset);
2045 std::unique_ptr<DebugInfoIterator> info_iter(DebugInfoIterator::Create(info_header,
2046 debug_info->sh_size,
2047 abbrev.get()));
2048 if (info_iter.get() == nullptr) {
Alex Light3470ab42014-06-18 10:35:45 -07002049 return false;
2050 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002051 if (debug_line != nullptr) {
2052 DebugLineHeader* line_header =
2053 reinterpret_cast<DebugLineHeader*>(Begin() + debug_line->sh_offset);
2054 std::unique_ptr<DebugLineInstructionIterator> line_iter(
2055 DebugLineInstructionIterator::Create(line_header, debug_line->sh_size));
2056 if (line_iter.get() == nullptr) {
2057 return false;
2058 }
2059 if (!FixupDebugLine(base_address_delta, line_iter.get())) {
2060 return false;
2061 }
2062 }
2063 return FixupDebugInfo(base_address_delta, info_iter.get());
Alex Light3470ab42014-06-18 10:35:45 -07002064}
Mark Mendellae9fd932014-02-10 16:14:35 -08002065
Tong Shen62d1ca32014-09-03 17:24:56 -07002066template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2067 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2068 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2069void ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2070 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2071 ::GdbJITSupport() {
Mark Mendellae9fd932014-02-10 16:14:35 -08002072 // We only get here if we only are mapping the program header.
2073 DCHECK(program_header_only_);
2074
2075 // Well, we need the whole file to do this.
2076 std::string error_msg;
Alex Light3470ab42014-06-18 10:35:45 -07002077 // Make it MAP_PRIVATE so we can just give it to gdb if all the necessary
2078 // sections are there.
Tong Shen62d1ca32014-09-03 17:24:56 -07002079 std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2080 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
2081 all_ptr(Open(const_cast<File*>(file_), PROT_READ | PROT_WRITE,
2082 MAP_PRIVATE, &error_msg));
Alex Light3470ab42014-06-18 10:35:45 -07002083 if (all_ptr.get() == nullptr) {
Mark Mendellae9fd932014-02-10 16:14:35 -08002084 return;
2085 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002086 ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2087 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>& all = *all_ptr;
Alex Light3470ab42014-06-18 10:35:45 -07002088
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002089 // We need the eh_frame for gdb but debug info might be present without it.
Tong Shen62d1ca32014-09-03 17:24:56 -07002090 const Elf_Shdr* eh_frame = all.FindSectionByName(".eh_frame");
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002091 if (eh_frame == nullptr) {
Mark Mendellae9fd932014-02-10 16:14:35 -08002092 return;
2093 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002094
2095 // Do we have interesting sections?
Alex Light3470ab42014-06-18 10:35:45 -07002096 // We need to add in a strtab and symtab to the image.
2097 // all is MAP_PRIVATE so it can be written to freely.
2098 // We also already have strtab and symtab so we are fine there.
Tong Shen62d1ca32014-09-03 17:24:56 -07002099 Elf_Ehdr& elf_hdr = all.GetHeader();
Mark Mendellae9fd932014-02-10 16:14:35 -08002100 elf_hdr.e_entry = 0;
2101 elf_hdr.e_phoff = 0;
2102 elf_hdr.e_phnum = 0;
2103 elf_hdr.e_phentsize = 0;
2104 elf_hdr.e_type = ET_EXEC;
2105
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002106 // Since base_address_ is 0 if we are actually loaded at a known address (i.e. this is boot.oat)
2107 // and the actual address stuff starts at in regular files this is good.
2108 if (!all.FixupDebugSections(reinterpret_cast<intptr_t>(base_address_))) {
Alex Light3470ab42014-06-18 10:35:45 -07002109 LOG(ERROR) << "Failed to load GDB data";
2110 return;
Mark Mendellae9fd932014-02-10 16:14:35 -08002111 }
2112
Alex Light3470ab42014-06-18 10:35:45 -07002113 jit_gdb_entry_ = CreateCodeEntry(all.Begin(), all.Size());
2114 gdb_file_mapping_.reset(all_ptr.release());
Mark Mendellae9fd932014-02-10 16:14:35 -08002115}
2116
Tong Shen62d1ca32014-09-03 17:24:56 -07002117template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2118 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2119 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2120bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2121 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2122 ::Strip(std::string* error_msg) {
2123 // ELF files produced by MCLinker look roughly like this
2124 //
2125 // +------------+
2126 // | Elf_Ehdr | contains number of Elf_Shdr and offset to first
2127 // +------------+
2128 // | Elf_Phdr | program headers
2129 // | Elf_Phdr |
2130 // | ... |
2131 // | Elf_Phdr |
2132 // +------------+
2133 // | section | mixture of needed and unneeded sections
2134 // +------------+
2135 // | section |
2136 // +------------+
2137 // | ... |
2138 // +------------+
2139 // | section |
2140 // +------------+
2141 // | Elf_Shdr | section headers
2142 // | Elf_Shdr |
2143 // | ... | contains offset to section start
2144 // | Elf_Shdr |
2145 // +------------+
2146 //
2147 // To strip:
2148 // - leave the Elf_Ehdr and Elf_Phdr values in place.
2149 // - walk the sections making a new set of Elf_Shdr section headers for what we want to keep
2150 // - move the sections are keeping up to fill in gaps of sections we want to strip
2151 // - write new Elf_Shdr section headers to end of file, updating Elf_Ehdr
2152 // - truncate rest of file
2153 //
2154
2155 std::vector<Elf_Shdr> section_headers;
2156 std::vector<Elf_Word> section_headers_original_indexes;
2157 section_headers.reserve(GetSectionHeaderNum());
2158
2159
2160 Elf_Shdr* string_section = GetSectionNameStringSection();
2161 CHECK(string_section != nullptr);
2162 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
2163 Elf_Shdr* sh = GetSectionHeader(i);
2164 CHECK(sh != nullptr);
2165 const char* name = GetString(*string_section, sh->sh_name);
2166 if (name == nullptr) {
2167 CHECK_EQ(0U, i);
2168 section_headers.push_back(*sh);
2169 section_headers_original_indexes.push_back(0);
2170 continue;
2171 }
2172 if (StartsWith(name, ".debug")
2173 || (strcmp(name, ".strtab") == 0)
2174 || (strcmp(name, ".symtab") == 0)) {
2175 continue;
2176 }
2177 section_headers.push_back(*sh);
2178 section_headers_original_indexes.push_back(i);
2179 }
2180 CHECK_NE(0U, section_headers.size());
2181 CHECK_EQ(section_headers.size(), section_headers_original_indexes.size());
2182
2183 // section 0 is the NULL section, sections start at offset of first section
2184 CHECK(GetSectionHeader(1) != nullptr);
2185 Elf_Off offset = GetSectionHeader(1)->sh_offset;
2186 for (size_t i = 1; i < section_headers.size(); i++) {
2187 Elf_Shdr& new_sh = section_headers[i];
2188 Elf_Shdr* old_sh = GetSectionHeader(section_headers_original_indexes[i]);
2189 CHECK(old_sh != nullptr);
2190 CHECK_EQ(new_sh.sh_name, old_sh->sh_name);
2191 if (old_sh->sh_addralign > 1) {
2192 offset = RoundUp(offset, old_sh->sh_addralign);
2193 }
2194 if (old_sh->sh_offset == offset) {
2195 // already in place
2196 offset += old_sh->sh_size;
2197 continue;
2198 }
2199 // shift section earlier
2200 memmove(Begin() + offset,
2201 Begin() + old_sh->sh_offset,
2202 old_sh->sh_size);
2203 new_sh.sh_offset = offset;
2204 offset += old_sh->sh_size;
2205 }
2206
2207 Elf_Off shoff = offset;
2208 size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf_Shdr);
2209 memcpy(Begin() + offset, &section_headers[0], section_headers_size_in_bytes);
2210 offset += section_headers_size_in_bytes;
2211
2212 GetHeader().e_shnum = section_headers.size();
2213 GetHeader().e_shoff = shoff;
2214 int result = ftruncate(file_->Fd(), offset);
2215 if (result != 0) {
2216 *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s",
2217 file_->GetPath().c_str(), strerror(errno));
2218 return false;
2219 }
2220 return true;
2221}
2222
2223static const bool DEBUG_FIXUP = false;
2224
2225template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2226 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2227 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2228bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2229 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2230 ::Fixup(uintptr_t base_address) {
2231 if (!FixupDynamic(base_address)) {
2232 LOG(WARNING) << "Failed to fixup .dynamic in " << file_->GetPath();
2233 return false;
2234 }
2235 if (!FixupSectionHeaders(base_address)) {
2236 LOG(WARNING) << "Failed to fixup section headers in " << file_->GetPath();
2237 return false;
2238 }
2239 if (!FixupProgramHeaders(base_address)) {
2240 LOG(WARNING) << "Failed to fixup program headers in " << file_->GetPath();
2241 return false;
2242 }
2243 if (!FixupSymbols(base_address, true)) {
2244 LOG(WARNING) << "Failed to fixup .dynsym in " << file_->GetPath();
2245 return false;
2246 }
2247 if (!FixupSymbols(base_address, false)) {
2248 LOG(WARNING) << "Failed to fixup .symtab in " << file_->GetPath();
2249 return false;
2250 }
2251 if (!FixupRelocations(base_address)) {
2252 LOG(WARNING) << "Failed to fixup .rel.dyn in " << file_->GetPath();
2253 return false;
2254 }
2255 if (!FixupDebugSections(base_address)) {
2256 LOG(WARNING) << "Failed to fixup debug sections in " << file_->GetPath();
2257 return false;
2258 }
2259 return true;
2260}
2261
2262template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2263 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2264 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2265bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2266 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2267 ::FixupDynamic(uintptr_t base_address) {
2268 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
2269 Elf_Dyn& elf_dyn = GetDynamic(i);
2270 Elf_Word d_tag = elf_dyn.d_tag;
2271 if (IsDynamicSectionPointer(d_tag, GetHeader().e_machine)) {
2272 Elf_Addr d_ptr = elf_dyn.d_un.d_ptr;
2273 if (DEBUG_FIXUP) {
2274 LOG(INFO) << StringPrintf("In %s moving Elf_Dyn[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2275 GetFile().GetPath().c_str(), i,
2276 static_cast<uint64_t>(d_ptr),
2277 static_cast<uint64_t>(d_ptr + base_address));
2278 }
2279 d_ptr += base_address;
2280 elf_dyn.d_un.d_ptr = d_ptr;
2281 }
2282 }
2283 return true;
2284}
2285
2286template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2287 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2288 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2289bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2290 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2291 ::FixupSectionHeaders(uintptr_t base_address) {
2292 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
2293 Elf_Shdr* sh = GetSectionHeader(i);
2294 CHECK(sh != nullptr);
2295 // 0 implies that the section will not exist in the memory of the process
2296 if (sh->sh_addr == 0) {
2297 continue;
2298 }
2299 if (DEBUG_FIXUP) {
2300 LOG(INFO) << StringPrintf("In %s moving Elf_Shdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2301 GetFile().GetPath().c_str(), i,
2302 static_cast<uint64_t>(sh->sh_addr),
2303 static_cast<uint64_t>(sh->sh_addr + base_address));
2304 }
2305 sh->sh_addr += base_address;
2306 }
2307 return true;
2308}
2309
2310template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2311 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2312 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2313bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2314 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2315 ::FixupProgramHeaders(uintptr_t base_address) {
2316 // TODO: ELFObjectFile doesn't have give to Elf_Phdr, so we do that ourselves for now.
2317 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
2318 Elf_Phdr* ph = GetProgramHeader(i);
2319 CHECK(ph != nullptr);
2320 CHECK_EQ(ph->p_vaddr, ph->p_paddr) << GetFile().GetPath() << " i=" << i;
2321 CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
2322 << GetFile().GetPath() << " i=" << i;
2323 if (DEBUG_FIXUP) {
2324 LOG(INFO) << StringPrintf("In %s moving Elf_Phdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2325 GetFile().GetPath().c_str(), i,
2326 static_cast<uint64_t>(ph->p_vaddr),
2327 static_cast<uint64_t>(ph->p_vaddr + base_address));
2328 }
2329 ph->p_vaddr += base_address;
2330 ph->p_paddr += base_address;
2331 CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
2332 << GetFile().GetPath() << " i=" << i;
2333 }
2334 return true;
2335}
2336
2337template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2338 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2339 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2340bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2341 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2342 ::FixupSymbols(uintptr_t base_address, bool dynamic) {
2343 Elf_Word section_type = dynamic ? SHT_DYNSYM : SHT_SYMTAB;
2344 // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
2345 Elf_Shdr* symbol_section = FindSectionByType(section_type);
2346 if (symbol_section == nullptr) {
2347 // file is missing optional .symtab
2348 CHECK(!dynamic) << GetFile().GetPath();
2349 return true;
2350 }
2351 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
2352 Elf_Sym* symbol = GetSymbol(section_type, i);
2353 CHECK(symbol != nullptr);
2354 if (symbol->st_value != 0) {
2355 if (DEBUG_FIXUP) {
2356 LOG(INFO) << StringPrintf("In %s moving Elf_Sym[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2357 GetFile().GetPath().c_str(), i,
2358 static_cast<uint64_t>(symbol->st_value),
2359 static_cast<uint64_t>(symbol->st_value + base_address));
2360 }
2361 symbol->st_value += base_address;
2362 }
2363 }
2364 return true;
2365}
2366
2367template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2368 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2369 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2370bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2371 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2372 ::FixupRelocations(uintptr_t base_address) {
2373 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
2374 Elf_Shdr* sh = GetSectionHeader(i);
2375 CHECK(sh != nullptr);
2376 if (sh->sh_type == SHT_REL) {
2377 for (uint32_t i = 0; i < GetRelNum(*sh); i++) {
2378 Elf_Rel& rel = GetRel(*sh, i);
2379 if (DEBUG_FIXUP) {
2380 LOG(INFO) << StringPrintf("In %s moving Elf_Rel[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2381 GetFile().GetPath().c_str(), i,
2382 static_cast<uint64_t>(rel.r_offset),
2383 static_cast<uint64_t>(rel.r_offset + base_address));
2384 }
2385 rel.r_offset += base_address;
2386 }
2387 } else if (sh->sh_type == SHT_RELA) {
2388 for (uint32_t i = 0; i < GetRelaNum(*sh); i++) {
2389 Elf_Rela& rela = GetRela(*sh, i);
2390 if (DEBUG_FIXUP) {
2391 LOG(INFO) << StringPrintf("In %s moving Elf_Rela[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2392 GetFile().GetPath().c_str(), i,
2393 static_cast<uint64_t>(rela.r_offset),
2394 static_cast<uint64_t>(rela.r_offset + base_address));
2395 }
2396 rela.r_offset += base_address;
2397 }
2398 }
2399 }
2400 return true;
2401}
2402
2403// Explicit instantiations
2404template class ElfFileImpl<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Word,
2405 Elf32_Sword, Elf32_Addr, Elf32_Sym, Elf32_Rel, Elf32_Rela, Elf32_Dyn, Elf32_Off>;
2406template class ElfFileImpl<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Word,
2407 Elf64_Sword, Elf64_Addr, Elf64_Sym, Elf64_Rel, Elf64_Rela, Elf64_Dyn, Elf64_Off>;
2408
2409ElfFile::ElfFile(ElfFileImpl32* elf32) : is_elf64_(false) {
2410 CHECK_NE(elf32, static_cast<ElfFileImpl32*>(nullptr));
2411 elf_.elf32_ = elf32;
2412}
2413
2414ElfFile::ElfFile(ElfFileImpl64* elf64) : is_elf64_(true) {
2415 CHECK_NE(elf64, static_cast<ElfFileImpl64*>(nullptr));
2416 elf_.elf64_ = elf64;
2417}
2418
2419ElfFile::~ElfFile() {
2420 if (is_elf64_) {
2421 CHECK_NE(elf_.elf64_, static_cast<ElfFileImpl64*>(nullptr));
2422 delete elf_.elf64_;
2423 } else {
2424 CHECK_NE(elf_.elf32_, static_cast<ElfFileImpl32*>(nullptr));
2425 delete elf_.elf32_;
2426 }
2427}
2428
2429ElfFile* ElfFile::Open(File* file, bool writable, bool program_header_only, std::string* error_msg) {
2430 if (file->GetLength() < EI_NIDENT) {
2431 *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
2432 file->GetPath().c_str());
2433 return nullptr;
2434 }
2435 std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT, PROT_READ, MAP_PRIVATE, file->Fd(), 0,
2436 file->GetPath().c_str(), error_msg));
2437 if (map == nullptr && map->Size() != EI_NIDENT) {
2438 return nullptr;
2439 }
Ian Rogers13735952014-10-08 12:43:28 -07002440 uint8_t* header = map->Begin();
Tong Shen62d1ca32014-09-03 17:24:56 -07002441 if (header[EI_CLASS] == ELFCLASS64) {
2442 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, writable, program_header_only, error_msg);
2443 if (elf_file_impl == nullptr)
2444 return nullptr;
2445 return new ElfFile(elf_file_impl);
2446 } else if (header[EI_CLASS] == ELFCLASS32) {
2447 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, writable, program_header_only, error_msg);
2448 if (elf_file_impl == nullptr)
2449 return nullptr;
2450 return new ElfFile(elf_file_impl);
2451 } else {
2452 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
2453 ELFCLASS32, ELFCLASS64,
2454 file->GetPath().c_str(),
2455 header[EI_CLASS]);
2456 return nullptr;
2457 }
2458}
2459
2460ElfFile* ElfFile::Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg) {
2461 if (file->GetLength() < EI_NIDENT) {
2462 *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
2463 file->GetPath().c_str());
2464 return nullptr;
2465 }
2466 std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT, PROT_READ, MAP_PRIVATE, file->Fd(), 0,
2467 file->GetPath().c_str(), error_msg));
2468 if (map == nullptr && map->Size() != EI_NIDENT) {
2469 return nullptr;
2470 }
Ian Rogers13735952014-10-08 12:43:28 -07002471 uint8_t* header = map->Begin();
Tong Shen62d1ca32014-09-03 17:24:56 -07002472 if (header[EI_CLASS] == ELFCLASS64) {
2473 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, mmap_prot, mmap_flags, error_msg);
2474 if (elf_file_impl == nullptr)
2475 return nullptr;
2476 return new ElfFile(elf_file_impl);
2477 } else if (header[EI_CLASS] == ELFCLASS32) {
2478 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, mmap_prot, mmap_flags, error_msg);
2479 if (elf_file_impl == nullptr)
2480 return nullptr;
2481 return new ElfFile(elf_file_impl);
2482 } else {
2483 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
2484 ELFCLASS32, ELFCLASS64,
2485 file->GetPath().c_str(),
2486 header[EI_CLASS]);
2487 return nullptr;
2488 }
2489}
2490
2491#define DELEGATE_TO_IMPL(func, ...) \
2492 if (is_elf64_) { \
2493 CHECK_NE(elf_.elf64_, static_cast<ElfFileImpl64*>(nullptr)); \
2494 return elf_.elf64_->func(__VA_ARGS__); \
2495 } else { \
2496 CHECK_NE(elf_.elf32_, static_cast<ElfFileImpl32*>(nullptr)); \
2497 return elf_.elf32_->func(__VA_ARGS__); \
2498 }
2499
2500bool ElfFile::Load(bool executable, std::string* error_msg) {
2501 DELEGATE_TO_IMPL(Load, executable, error_msg);
2502}
2503
Ian Rogers13735952014-10-08 12:43:28 -07002504const uint8_t* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
Tong Shen62d1ca32014-09-03 17:24:56 -07002505 DELEGATE_TO_IMPL(FindDynamicSymbolAddress, symbol_name);
2506}
2507
2508size_t ElfFile::Size() const {
2509 DELEGATE_TO_IMPL(Size);
2510}
2511
Ian Rogers13735952014-10-08 12:43:28 -07002512uint8_t* ElfFile::Begin() const {
Tong Shen62d1ca32014-09-03 17:24:56 -07002513 DELEGATE_TO_IMPL(Begin);
2514}
2515
Ian Rogers13735952014-10-08 12:43:28 -07002516uint8_t* ElfFile::End() const {
Tong Shen62d1ca32014-09-03 17:24:56 -07002517 DELEGATE_TO_IMPL(End);
2518}
2519
2520const File& ElfFile::GetFile() const {
2521 DELEGATE_TO_IMPL(GetFile);
2522}
2523
2524bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, uint64_t* size) {
2525 if (is_elf64_) {
2526 CHECK_NE(elf_.elf64_, static_cast<ElfFileImpl64*>(nullptr));
2527
2528 Elf64_Shdr *shdr = elf_.elf64_->FindSectionByName(section_name);
2529 if (shdr == nullptr)
2530 return false;
2531
2532 if (offset != nullptr)
2533 *offset = shdr->sh_offset;
2534 if (size != nullptr)
2535 *size = shdr->sh_size;
2536 return true;
2537 } else {
2538 CHECK_NE(elf_.elf32_, static_cast<ElfFileImpl32*>(nullptr));
2539
2540 Elf32_Shdr *shdr = elf_.elf32_->FindSectionByName(section_name);
2541 if (shdr == nullptr)
2542 return false;
2543
2544 if (offset != nullptr)
2545 *offset = shdr->sh_offset;
2546 if (size != nullptr)
2547 *size = shdr->sh_size;
2548 return true;
2549 }
2550}
2551
2552uint64_t ElfFile::FindSymbolAddress(unsigned section_type,
2553 const std::string& symbol_name,
2554 bool build_map) {
2555 DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map);
2556}
2557
2558size_t ElfFile::GetLoadedSize() const {
2559 DELEGATE_TO_IMPL(GetLoadedSize);
2560}
2561
2562bool ElfFile::Strip(File* file, std::string* error_msg) {
2563 std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, error_msg));
2564 if (elf_file.get() == nullptr) {
2565 return false;
2566 }
2567
2568 if (elf_file->is_elf64_)
2569 return elf_file->elf_.elf64_->Strip(error_msg);
2570 else
2571 return elf_file->elf_.elf32_->Strip(error_msg);
2572}
2573
2574bool ElfFile::Fixup(uintptr_t base_address) {
2575 DELEGATE_TO_IMPL(Fixup, base_address);
2576}
2577
2578ElfFileImpl32* ElfFile::GetImpl32() const {
2579 CHECK(!is_elf64_);
2580 CHECK_NE(elf_.elf32_, static_cast<ElfFileImpl32*>(nullptr));
2581 return elf_.elf32_;
2582}
2583
2584ElfFileImpl64* ElfFile::GetImpl64() const {
2585 CHECK(is_elf64_);
2586 CHECK_NE(elf_.elf64_, static_cast<ElfFileImpl64*>(nullptr));
2587 return elf_.elf64_;
2588}
2589
Brian Carlstrom700c8d32012-11-05 10:42:02 -08002590} // namespace art