blob: 18053c3fb9f7e4cc1248277a5322bc53994ab836 [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"
Ian Rogersd4c4d952014-10-16 20:31:53 -070026#include "base/unix_file/fd_file.h"
Alex Light3470ab42014-06-18 10:35:45 -070027#include "dwarf.h"
Ian Rogersd4c4d952014-10-16 20:31:53 -070028#include "elf_file_impl.h"
29#include "elf_utils.h"
Alex Light3470ab42014-06-18 10:35:45 -070030#include "leb128.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080031#include "utils.h"
Andreas Gampe91268c12014-04-03 17:50:24 -070032#include "instruction_set.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080033
34namespace art {
35
Mark Mendellae9fd932014-02-10 16:14:35 -080036// -------------------------------------------------------------------
37// Binary GDB JIT Interface as described in
38// http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
39extern "C" {
40 typedef enum {
41 JIT_NOACTION = 0,
42 JIT_REGISTER_FN,
43 JIT_UNREGISTER_FN
44 } JITAction;
45
46 struct JITCodeEntry {
47 JITCodeEntry* next_;
48 JITCodeEntry* prev_;
Ian Rogers13735952014-10-08 12:43:28 -070049 const uint8_t *symfile_addr_;
Mark Mendellae9fd932014-02-10 16:14:35 -080050 uint64_t symfile_size_;
51 };
52
53 struct JITDescriptor {
54 uint32_t version_;
55 uint32_t action_flag_;
56 JITCodeEntry* relevant_entry_;
57 JITCodeEntry* first_entry_;
58 };
59
60 // GDB will place breakpoint into this function.
61 // To prevent GCC from inlining or removing it we place noinline attribute
62 // and inline assembler statement inside.
63 void __attribute__((noinline)) __jit_debug_register_code() {
64 __asm__("");
65 }
66
67 // GDB will inspect contents of this descriptor.
68 // Static initialization is necessary to prevent GDB from seeing
69 // uninitialized descriptor.
70 JITDescriptor __jit_debug_descriptor = { 1, JIT_NOACTION, nullptr, nullptr };
71}
72
73
Ian Rogers13735952014-10-08 12:43:28 -070074static JITCodeEntry* CreateCodeEntry(const uint8_t *symfile_addr,
Mark Mendellae9fd932014-02-10 16:14:35 -080075 uintptr_t symfile_size) {
76 JITCodeEntry* entry = new JITCodeEntry;
77 entry->symfile_addr_ = symfile_addr;
78 entry->symfile_size_ = symfile_size;
79 entry->prev_ = nullptr;
80
81 // TODO: Do we need a lock here?
82 entry->next_ = __jit_debug_descriptor.first_entry_;
83 if (entry->next_ != nullptr) {
84 entry->next_->prev_ = entry;
85 }
86 __jit_debug_descriptor.first_entry_ = entry;
87 __jit_debug_descriptor.relevant_entry_ = entry;
88
89 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
90 __jit_debug_register_code();
91 return entry;
92}
93
94
95static void UnregisterCodeEntry(JITCodeEntry* entry) {
96 // TODO: Do we need a lock here?
97 if (entry->prev_ != nullptr) {
98 entry->prev_->next_ = entry->next_;
99 } else {
100 __jit_debug_descriptor.first_entry_ = entry->next_;
101 }
102
103 if (entry->next_ != nullptr) {
104 entry->next_->prev_ = entry->prev_;
105 }
106
107 __jit_debug_descriptor.relevant_entry_ = entry;
108 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
109 __jit_debug_register_code();
110 delete entry;
111}
112
Tong Shen62d1ca32014-09-03 17:24:56 -0700113template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
114 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
115 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
116ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
117 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
118 ::ElfFileImpl(File* file, bool writable, bool program_header_only)
Brian Carlstromc1409452014-02-26 14:06:23 -0800119 : file_(file),
120 writable_(writable),
121 program_header_only_(program_header_only),
Alex Light3470ab42014-06-18 10:35:45 -0700122 header_(nullptr),
123 base_address_(nullptr),
124 program_headers_start_(nullptr),
125 section_headers_start_(nullptr),
126 dynamic_program_header_(nullptr),
127 dynamic_section_start_(nullptr),
128 symtab_section_start_(nullptr),
129 dynsym_section_start_(nullptr),
130 strtab_section_start_(nullptr),
131 dynstr_section_start_(nullptr),
132 hash_section_start_(nullptr),
133 symtab_symbol_table_(nullptr),
134 dynsym_symbol_table_(nullptr),
135 jit_elf_image_(nullptr),
136 jit_gdb_entry_(nullptr) {
137 CHECK(file != nullptr);
Brian Carlstromc1409452014-02-26 14:06:23 -0800138}
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800139
Tong Shen62d1ca32014-09-03 17:24:56 -0700140template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
141 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
142 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
143ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
144 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>*
145 ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
146 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
147 ::Open(File* file, bool writable, bool program_header_only,
148 std::string* error_msg) {
149 std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
150 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
151 elf_file(new ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
152 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
153 (file, writable, program_header_only));
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800154 int prot;
155 int flags;
Alex Light3470ab42014-06-18 10:35:45 -0700156 if (writable) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800157 prot = PROT_READ | PROT_WRITE;
158 flags = MAP_SHARED;
159 } else {
160 prot = PROT_READ;
161 flags = MAP_PRIVATE;
162 }
Alex Light3470ab42014-06-18 10:35:45 -0700163 if (!elf_file->Setup(prot, flags, error_msg)) {
164 return nullptr;
165 }
166 return elf_file.release();
167}
168
Tong Shen62d1ca32014-09-03 17:24:56 -0700169template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
170 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
171 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
172ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
173 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>*
174 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 ::Open(File* file, int prot, int flags, std::string* error_msg) {
177 std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
178 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
179 elf_file(new ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
180 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
181 (file, (prot & PROT_WRITE) == PROT_WRITE, false));
Alex Light3470ab42014-06-18 10:35:45 -0700182 if (!elf_file->Setup(prot, flags, error_msg)) {
183 return nullptr;
184 }
185 return elf_file.release();
186}
187
Tong Shen62d1ca32014-09-03 17:24:56 -0700188template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
189 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
190 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
191bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
192 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
193 ::Setup(int prot, int flags, std::string* error_msg) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800194 int64_t temp_file_length = file_->GetLength();
195 if (temp_file_length < 0) {
196 errno = -temp_file_length;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700197 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
198 file_->GetPath().c_str(), file_->Fd(), strerror(errno));
Brian Carlstrom265091e2013-01-30 14:08:26 -0800199 return false;
200 }
Ian Rogerscdfcf372014-01-23 20:38:36 -0800201 size_t file_length = static_cast<size_t>(temp_file_length);
Tong Shen62d1ca32014-09-03 17:24:56 -0700202 if (file_length < sizeof(Elf_Ehdr)) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800203 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF header of "
Tong Shen62d1ca32014-09-03 17:24:56 -0700204 "%zd bytes: '%s'", file_length, sizeof(Elf_Ehdr),
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700205 file_->GetPath().c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800206 return false;
207 }
208
Brian Carlstromc1409452014-02-26 14:06:23 -0800209 if (program_header_only_) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800210 // first just map ELF header to get program header size information
Tong Shen62d1ca32014-09-03 17:24:56 -0700211 size_t elf_header_size = sizeof(Elf_Ehdr);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700212 if (!SetMap(MemMap::MapFile(elf_header_size, prot, flags, file_->Fd(), 0,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800213 file_->GetPath().c_str(), error_msg),
214 error_msg)) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800215 return false;
216 }
217 // then remap to cover program header
218 size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum);
Brian Carlstrom3a223612013-10-10 17:18:24 -0700219 if (file_length < program_header_size) {
Ian Rogerscdfcf372014-01-23 20:38:36 -0800220 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program "
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700221 "header of %zd bytes: '%s'", file_length,
Tong Shen62d1ca32014-09-03 17:24:56 -0700222 sizeof(Elf_Ehdr), file_->GetPath().c_str());
Brian Carlstrom3a223612013-10-10 17:18:24 -0700223 return false;
224 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700225 if (!SetMap(MemMap::MapFile(program_header_size, prot, flags, file_->Fd(), 0,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800226 file_->GetPath().c_str(), error_msg),
227 error_msg)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700228 *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800229 return false;
230 }
231 } else {
232 // otherwise map entire file
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700233 if (!SetMap(MemMap::MapFile(file_->GetLength(), prot, flags, file_->Fd(), 0,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800234 file_->GetPath().c_str(), error_msg),
235 error_msg)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700236 *error_msg = StringPrintf("Failed to map ELF file: %s", error_msg->c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800237 return false;
238 }
239 }
240
Andreas Gampedaab38c2014-09-12 18:38:24 -0700241 if (program_header_only_) {
242 program_headers_start_ = Begin() + GetHeader().e_phoff;
243 } else {
244 if (!CheckAndSet(GetHeader().e_phoff, "program headers", &program_headers_start_, error_msg)) {
245 return false;
246 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800247
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800248 // Setup section headers.
Andreas Gampedaab38c2014-09-12 18:38:24 -0700249 if (!CheckAndSet(GetHeader().e_shoff, "section headers", &section_headers_start_, error_msg)) {
250 return false;
251 }
252
253 // Find shstrtab.
Tong Shen62d1ca32014-09-03 17:24:56 -0700254 Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700255 if (shstrtab_section_header == nullptr) {
256 *error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'",
257 file_->GetPath().c_str());
258 return false;
259 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800260
261 // Find .dynamic section info from program header
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000262 dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC);
Alex Light3470ab42014-06-18 10:35:45 -0700263 if (dynamic_program_header_ == nullptr) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700264 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
265 file_->GetPath().c_str());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800266 return false;
267 }
268
Andreas Gampedaab38c2014-09-12 18:38:24 -0700269 if (!CheckAndSet(GetDynamicProgramHeader().p_offset, "dynamic section",
Ian Rogers13735952014-10-08 12:43:28 -0700270 reinterpret_cast<uint8_t**>(&dynamic_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700271 return false;
272 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800273
274 // Find other sections from section headers
Tong Shen62d1ca32014-09-03 17:24:56 -0700275 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
276 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700277 if (section_header == nullptr) {
278 *error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'",
279 i, file_->GetPath().c_str());
280 return false;
281 }
282 switch (section_header->sh_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000283 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700284 if (!CheckAndSet(section_header->sh_offset, "symtab",
Ian Rogers13735952014-10-08 12:43:28 -0700285 reinterpret_cast<uint8_t**>(&symtab_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700286 return false;
287 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800288 break;
289 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000290 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700291 if (!CheckAndSet(section_header->sh_offset, "dynsym",
Ian Rogers13735952014-10-08 12:43:28 -0700292 reinterpret_cast<uint8_t**>(&dynsym_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700293 return false;
294 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800295 break;
296 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000297 case SHT_STRTAB: {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800298 // TODO: base these off of sh_link from .symtab and .dynsym above
Andreas Gampedaab38c2014-09-12 18:38:24 -0700299 if ((section_header->sh_flags & SHF_ALLOC) != 0) {
300 // Check that this is named ".dynstr" and ignore otherwise.
301 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
302 if (strncmp(".dynstr", header_name, 8) == 0) {
303 if (!CheckAndSet(section_header->sh_offset, "dynstr",
Ian Rogers13735952014-10-08 12:43:28 -0700304 reinterpret_cast<uint8_t**>(&dynstr_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700305 return false;
306 }
307 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800308 } else {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700309 // Check that this is named ".strtab" and ignore otherwise.
310 const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
311 if (strncmp(".strtab", header_name, 8) == 0) {
312 if (!CheckAndSet(section_header->sh_offset, "strtab",
Ian Rogers13735952014-10-08 12:43:28 -0700313 reinterpret_cast<uint8_t**>(&strtab_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700314 return false;
315 }
316 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800317 }
318 break;
319 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000320 case SHT_DYNAMIC: {
Ian Rogers13735952014-10-08 12:43:28 -0700321 if (reinterpret_cast<uint8_t*>(dynamic_section_start_) !=
Andreas Gampedaab38c2014-09-12 18:38:24 -0700322 Begin() + section_header->sh_offset) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800323 LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in "
Brian Carlstrom265091e2013-01-30 14:08:26 -0800324 << file_->GetPath() << ": " << std::hex
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800325 << reinterpret_cast<void*>(dynamic_section_start_)
Andreas Gampedaab38c2014-09-12 18:38:24 -0700326 << " != " << reinterpret_cast<void*>(Begin() + section_header->sh_offset);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800327 return false;
328 }
329 break;
330 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000331 case SHT_HASH: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700332 if (!CheckAndSet(section_header->sh_offset, "hash section",
Ian Rogers13735952014-10-08 12:43:28 -0700333 reinterpret_cast<uint8_t**>(&hash_section_start_), error_msg)) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700334 return false;
335 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800336 break;
337 }
338 }
339 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700340
341 // Check for the existence of some sections.
342 if (!CheckSectionsExist(error_msg)) {
343 return false;
344 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800345 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700346
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800347 return true;
348}
349
Tong Shen62d1ca32014-09-03 17:24:56 -0700350template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
351 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
352 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
353ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
354 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
355 ::~ElfFileImpl() {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800356 STLDeleteElements(&segments_);
Brian Carlstrom265091e2013-01-30 14:08:26 -0800357 delete symtab_symbol_table_;
358 delete dynsym_symbol_table_;
Mark Mendellae9fd932014-02-10 16:14:35 -0800359 delete jit_elf_image_;
360 if (jit_gdb_entry_) {
361 UnregisterCodeEntry(jit_gdb_entry_);
362 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800363}
364
Tong Shen62d1ca32014-09-03 17:24:56 -0700365template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
366 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
367 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
368bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
369 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
370 ::CheckAndSet(Elf32_Off offset, const char* label,
Ian Rogers13735952014-10-08 12:43:28 -0700371 uint8_t** target, std::string* error_msg) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700372 if (Begin() + offset >= End()) {
373 *error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label,
374 file_->GetPath().c_str());
375 return false;
376 }
377 *target = Begin() + offset;
378 return true;
379}
380
Tong Shen62d1ca32014-09-03 17:24:56 -0700381template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
382 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
383 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
384bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
385 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700386 ::CheckSectionsLinked(const uint8_t* source, const uint8_t* target) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700387 // Only works in whole-program mode, as we need to iterate over the sections.
388 // Note that we normally can't search by type, as duplicates are allowed for most section types.
389 if (program_header_only_) {
390 return true;
391 }
392
Tong Shen62d1ca32014-09-03 17:24:56 -0700393 Elf_Shdr* source_section = nullptr;
394 Elf_Word target_index = 0;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700395 bool target_found = false;
Tong Shen62d1ca32014-09-03 17:24:56 -0700396 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
397 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700398
399 if (Begin() + section_header->sh_offset == source) {
400 // Found the source.
401 source_section = section_header;
402 if (target_index) {
403 break;
404 }
405 } else if (Begin() + section_header->sh_offset == target) {
406 target_index = i;
407 target_found = true;
408 if (source_section != nullptr) {
409 break;
410 }
411 }
412 }
413
414 return target_found && source_section != nullptr && source_section->sh_link == target_index;
415}
416
Tong Shen62d1ca32014-09-03 17:24:56 -0700417template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
418 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
419 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
420bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
421 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
422 ::CheckSectionsExist(std::string* error_msg) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700423 if (!program_header_only_) {
424 // If in full mode, need section headers.
425 if (section_headers_start_ == nullptr) {
426 *error_msg = StringPrintf("No section headers in ELF file: '%s'", file_->GetPath().c_str());
427 return false;
428 }
429 }
430
431 // This is redundant, but defensive.
432 if (dynamic_program_header_ == nullptr) {
433 *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
434 file_->GetPath().c_str());
435 return false;
436 }
437
438 // Need a dynamic section. This is redundant, but defensive.
439 if (dynamic_section_start_ == nullptr) {
440 *error_msg = StringPrintf("Failed to find dynamic section in ELF file: '%s'",
441 file_->GetPath().c_str());
442 return false;
443 }
444
445 // Symtab validation. These is not really a hard failure, as we are currently not using the
446 // symtab internally, but it's nice to be defensive.
447 if (symtab_section_start_ != nullptr) {
448 // When there's a symtab, there should be a strtab.
449 if (strtab_section_start_ == nullptr) {
450 *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file_->GetPath().c_str());
451 return false;
452 }
453
454 // The symtab should link to the strtab.
Ian Rogers13735952014-10-08 12:43:28 -0700455 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(symtab_section_start_),
456 reinterpret_cast<const uint8_t*>(strtab_section_start_))) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700457 *error_msg = StringPrintf("Symtab is not linked to the strtab in ELF file: '%s'",
458 file_->GetPath().c_str());
459 return false;
460 }
461 }
462
463 // We always need a dynstr & dynsym.
464 if (dynstr_section_start_ == nullptr) {
465 *error_msg = StringPrintf("No dynstr in ELF file: '%s'", file_->GetPath().c_str());
466 return false;
467 }
468 if (dynsym_section_start_ == nullptr) {
469 *error_msg = StringPrintf("No dynsym in ELF file: '%s'", file_->GetPath().c_str());
470 return false;
471 }
472
473 // Need a hash section for dynamic symbol lookup.
474 if (hash_section_start_ == nullptr) {
475 *error_msg = StringPrintf("Failed to find hash section in ELF file: '%s'",
476 file_->GetPath().c_str());
477 return false;
478 }
479
480 // And the hash section should be linking to the dynsym.
Ian Rogers13735952014-10-08 12:43:28 -0700481 if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(hash_section_start_),
482 reinterpret_cast<const uint8_t*>(dynsym_section_start_))) {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700483 *error_msg = StringPrintf("Hash section is not linked to the dynstr in ELF file: '%s'",
484 file_->GetPath().c_str());
485 return false;
486 }
487
488 return true;
489}
490
Tong Shen62d1ca32014-09-03 17:24:56 -0700491template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
492 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
493 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
494bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
495 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
496 ::SetMap(MemMap* map, std::string* error_msg) {
Alex Light3470ab42014-06-18 10:35:45 -0700497 if (map == nullptr) {
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800498 // MemMap::Open should have already set an error.
499 DCHECK(!error_msg->empty());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800500 return false;
501 }
502 map_.reset(map);
Alex Light3470ab42014-06-18 10:35:45 -0700503 CHECK(map_.get() != nullptr) << file_->GetPath();
504 CHECK(map_->Begin() != nullptr) << file_->GetPath();
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800505
Tong Shen62d1ca32014-09-03 17:24:56 -0700506 header_ = reinterpret_cast<Elf_Ehdr*>(map_->Begin());
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000507 if ((ELFMAG0 != header_->e_ident[EI_MAG0])
508 || (ELFMAG1 != header_->e_ident[EI_MAG1])
509 || (ELFMAG2 != header_->e_ident[EI_MAG2])
510 || (ELFMAG3 != header_->e_ident[EI_MAG3])) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800511 *error_msg = StringPrintf("Failed to find ELF magic value %d %d %d %d in %s, found %d %d %d %d",
512 ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
Brian Carlstromd0c09dc2013-11-06 18:25:35 -0800513 file_->GetPath().c_str(),
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000514 header_->e_ident[EI_MAG0],
515 header_->e_ident[EI_MAG1],
516 header_->e_ident[EI_MAG2],
517 header_->e_ident[EI_MAG3]);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800518 return false;
519 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700520 uint8_t elf_class = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) ? ELFCLASS64 : ELFCLASS32;
521 if (elf_class != header_->e_ident[EI_CLASS]) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800522 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d in %s, found %d",
Tong Shen62d1ca32014-09-03 17:24:56 -0700523 elf_class,
Brian Carlstromc1409452014-02-26 14:06:23 -0800524 file_->GetPath().c_str(),
525 header_->e_ident[EI_CLASS]);
526 return false;
527 }
528 if (ELFDATA2LSB != header_->e_ident[EI_DATA]) {
529 *error_msg = StringPrintf("Failed to find expected EI_DATA value %d in %s, found %d",
530 ELFDATA2LSB,
531 file_->GetPath().c_str(),
532 header_->e_ident[EI_CLASS]);
533 return false;
534 }
535 if (EV_CURRENT != header_->e_ident[EI_VERSION]) {
536 *error_msg = StringPrintf("Failed to find expected EI_VERSION value %d in %s, found %d",
537 EV_CURRENT,
538 file_->GetPath().c_str(),
539 header_->e_ident[EI_CLASS]);
540 return false;
541 }
542 if (ET_DYN != header_->e_type) {
543 *error_msg = StringPrintf("Failed to find expected e_type value %d in %s, found %d",
544 ET_DYN,
545 file_->GetPath().c_str(),
546 header_->e_type);
547 return false;
548 }
549 if (EV_CURRENT != header_->e_version) {
550 *error_msg = StringPrintf("Failed to find expected e_version value %d in %s, found %d",
551 EV_CURRENT,
552 file_->GetPath().c_str(),
553 header_->e_version);
554 return false;
555 }
556 if (0 != header_->e_entry) {
557 *error_msg = StringPrintf("Failed to find expected e_entry value %d in %s, found %d",
558 0,
559 file_->GetPath().c_str(),
Tong Shen62d1ca32014-09-03 17:24:56 -0700560 static_cast<int32_t>(header_->e_entry));
Brian Carlstromc1409452014-02-26 14:06:23 -0800561 return false;
562 }
563 if (0 == header_->e_phoff) {
564 *error_msg = StringPrintf("Failed to find non-zero e_phoff value in %s",
565 file_->GetPath().c_str());
566 return false;
567 }
568 if (0 == header_->e_shoff) {
569 *error_msg = StringPrintf("Failed to find non-zero e_shoff value in %s",
570 file_->GetPath().c_str());
571 return false;
572 }
573 if (0 == header_->e_ehsize) {
574 *error_msg = StringPrintf("Failed to find non-zero e_ehsize value in %s",
575 file_->GetPath().c_str());
576 return false;
577 }
578 if (0 == header_->e_phentsize) {
579 *error_msg = StringPrintf("Failed to find non-zero e_phentsize value in %s",
580 file_->GetPath().c_str());
581 return false;
582 }
583 if (0 == header_->e_phnum) {
584 *error_msg = StringPrintf("Failed to find non-zero e_phnum value in %s",
585 file_->GetPath().c_str());
586 return false;
587 }
588 if (0 == header_->e_shentsize) {
589 *error_msg = StringPrintf("Failed to find non-zero e_shentsize value in %s",
590 file_->GetPath().c_str());
591 return false;
592 }
593 if (0 == header_->e_shnum) {
594 *error_msg = StringPrintf("Failed to find non-zero e_shnum value in %s",
595 file_->GetPath().c_str());
596 return false;
597 }
598 if (0 == header_->e_shstrndx) {
599 *error_msg = StringPrintf("Failed to find non-zero e_shstrndx value in %s",
600 file_->GetPath().c_str());
601 return false;
602 }
603 if (header_->e_shstrndx >= header_->e_shnum) {
604 *error_msg = StringPrintf("Failed to find e_shnum value %d less than %d in %s",
605 header_->e_shstrndx,
606 header_->e_shnum,
607 file_->GetPath().c_str());
608 return false;
609 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800610
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800611 if (!program_header_only_) {
Brian Carlstromc1409452014-02-26 14:06:23 -0800612 if (header_->e_phoff >= Size()) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700613 *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s",
614 static_cast<uint64_t>(header_->e_phoff),
Brian Carlstromc1409452014-02-26 14:06:23 -0800615 Size(),
616 file_->GetPath().c_str());
617 return false;
618 }
619 if (header_->e_shoff >= Size()) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700620 *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s",
621 static_cast<uint64_t>(header_->e_shoff),
Brian Carlstromc1409452014-02-26 14:06:23 -0800622 Size(),
623 file_->GetPath().c_str());
624 return false;
625 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800626 }
627 return true;
628}
629
Tong Shen62d1ca32014-09-03 17:24:56 -0700630template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
631 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
632 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
633Elf_Ehdr& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
634 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
635 ::GetHeader() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700636 CHECK(header_ != nullptr); // Header has been checked in SetMap. This is a sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800637 return *header_;
638}
639
Tong Shen62d1ca32014-09-03 17:24:56 -0700640template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
641 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
642 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700643uint8_t* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
Tong Shen62d1ca32014-09-03 17:24:56 -0700644 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
645 ::GetProgramHeadersStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700646 CHECK(program_headers_start_ != nullptr); // Header has been set in Setup. This is a sanity
647 // check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800648 return program_headers_start_;
649}
650
Tong Shen62d1ca32014-09-03 17:24:56 -0700651template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
652 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
653 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700654uint8_t* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
Tong Shen62d1ca32014-09-03 17:24:56 -0700655 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
656 ::GetSectionHeadersStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700657 CHECK(!program_header_only_); // Only used in "full" mode.
658 CHECK(section_headers_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800659 return section_headers_start_;
660}
661
Tong Shen62d1ca32014-09-03 17:24:56 -0700662template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
663 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
664 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
665Elf_Phdr& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
666 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
667 ::GetDynamicProgramHeader() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700668 CHECK(dynamic_program_header_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800669 return *dynamic_program_header_;
670}
671
Tong Shen62d1ca32014-09-03 17:24:56 -0700672template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
673 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
674 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
675Elf_Dyn* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
676 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
677 ::GetDynamicSectionStart() const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700678 CHECK(dynamic_section_start_ != nullptr); // Is checked in CheckSectionsExist. Sanity check.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800679 return dynamic_section_start_;
680}
681
Tong Shen62d1ca32014-09-03 17:24:56 -0700682template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
683 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
684 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
685Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
686 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
687 ::GetSymbolSectionStart(Elf_Word section_type) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800688 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800689 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000690 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700691 return symtab_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800692 break;
693 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000694 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700695 return dynsym_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800696 break;
697 }
698 default: {
699 LOG(FATAL) << section_type;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700700 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800701 }
702 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800703}
704
Tong Shen62d1ca32014-09-03 17:24:56 -0700705template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
706 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
707 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
708const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
709 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
710 ::GetStringSectionStart(Elf_Word section_type) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800711 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800712 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000713 case SHT_SYMTAB: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700714 return strtab_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800715 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +0000716 case SHT_DYNSYM: {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700717 return dynstr_section_start_;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800718 }
719 default: {
720 LOG(FATAL) << section_type;
Andreas Gampedaab38c2014-09-12 18:38:24 -0700721 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800722 }
723 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800724}
725
Tong Shen62d1ca32014-09-03 17:24:56 -0700726template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
727 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
728 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
729const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
730 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
731 ::GetString(Elf_Word section_type, Elf_Word i) const {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800732 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
733 if (i == 0) {
Alex Light3470ab42014-06-18 10:35:45 -0700734 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800735 }
736 const char* string_section_start = GetStringSectionStart(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700737 if (string_section_start == nullptr) {
738 return nullptr;
739 }
740 return string_section_start + i;
Brian Carlstrom265091e2013-01-30 14:08:26 -0800741}
742
Andreas Gampedaab38c2014-09-12 18:38:24 -0700743// WARNING: The following methods do not check for an error condition (non-existent hash section).
744// It is the caller's job to do this.
745
Tong Shen62d1ca32014-09-03 17:24:56 -0700746template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
747 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
748 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
749Elf_Word* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
750 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
751 ::GetHashSectionStart() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800752 return hash_section_start_;
753}
754
Tong Shen62d1ca32014-09-03 17:24:56 -0700755template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
756 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
757 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
758Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
759 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
760 ::GetHashBucketNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800761 return GetHashSectionStart()[0];
762}
763
Tong Shen62d1ca32014-09-03 17:24:56 -0700764template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
765 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
766 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
767Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
768 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
769 ::GetHashChainNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800770 return GetHashSectionStart()[1];
771}
772
Tong Shen62d1ca32014-09-03 17:24:56 -0700773template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
774 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
775 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
776Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
777 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
778 ::GetHashBucket(size_t i, bool* ok) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700779 if (i >= GetHashBucketNum()) {
780 *ok = false;
781 return 0;
782 }
783 *ok = true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800784 // 0 is nbucket, 1 is nchain
785 return GetHashSectionStart()[2 + i];
786}
787
Tong Shen62d1ca32014-09-03 17:24:56 -0700788template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
789 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
790 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
791Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
792 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
793 ::GetHashChain(size_t i, bool* ok) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700794 if (i >= GetHashBucketNum()) {
795 *ok = false;
796 return 0;
797 }
798 *ok = true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800799 // 0 is nbucket, 1 is nchain, & chains are after buckets
800 return GetHashSectionStart()[2 + GetHashBucketNum() + i];
801}
802
Tong Shen62d1ca32014-09-03 17:24:56 -0700803template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
804 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
805 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
806Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
807 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
808 ::GetProgramHeaderNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800809 return GetHeader().e_phnum;
810}
811
Tong Shen62d1ca32014-09-03 17:24:56 -0700812template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
813 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
814 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
815Elf_Phdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
816 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
817 ::GetProgramHeader(Elf_Word i) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700818 CHECK_LT(i, GetProgramHeaderNum()) << file_->GetPath(); // Sanity check for caller.
Ian Rogers13735952014-10-08 12:43:28 -0700819 uint8_t* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700820 if (program_header >= End()) {
821 return nullptr; // Failure condition.
822 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700823 return reinterpret_cast<Elf_Phdr*>(program_header);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800824}
825
Tong Shen62d1ca32014-09-03 17:24:56 -0700826template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
827 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
828 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
829Elf_Phdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
830 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
831 ::FindProgamHeaderByType(Elf_Word type) const {
832 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
833 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700834 if (program_header->p_type == type) {
835 return program_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800836 }
837 }
Alex Light3470ab42014-06-18 10:35:45 -0700838 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800839}
840
Tong Shen62d1ca32014-09-03 17:24:56 -0700841template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
842 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
843 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
844Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
845 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
846 ::GetSectionHeaderNum() const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800847 return GetHeader().e_shnum;
848}
849
Tong Shen62d1ca32014-09-03 17:24:56 -0700850template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
851 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
852 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
853Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
854 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
855 ::GetSectionHeader(Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800856 // Can only access arbitrary sections when we have the whole file, not just program header.
857 // Even if we Load(), it doesn't bring in all the sections.
858 CHECK(!program_header_only_) << file_->GetPath();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700859 if (i >= GetSectionHeaderNum()) {
860 return nullptr; // Failure condition.
861 }
Ian Rogers13735952014-10-08 12:43:28 -0700862 uint8_t* section_header = GetSectionHeadersStart() + (i * GetHeader().e_shentsize);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700863 if (section_header >= End()) {
864 return nullptr; // Failure condition.
865 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700866 return reinterpret_cast<Elf_Shdr*>(section_header);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800867}
868
Tong Shen62d1ca32014-09-03 17:24:56 -0700869template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
870 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
871 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
872Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
873 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
874 ::FindSectionByType(Elf_Word type) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800875 // Can only access arbitrary sections when we have the whole file, not just program header.
876 // We could change this to switch on known types if they were detected during loading.
877 CHECK(!program_header_only_) << file_->GetPath();
Tong Shen62d1ca32014-09-03 17:24:56 -0700878 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
879 Elf_Shdr* section_header = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700880 if (section_header->sh_type == type) {
881 return section_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800882 }
883 }
Alex Light3470ab42014-06-18 10:35:45 -0700884 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800885}
886
887// from bionic
Brian Carlstrom265091e2013-01-30 14:08:26 -0800888static unsigned elfhash(const char *_name) {
889 const unsigned char *name = (const unsigned char *) _name;
890 unsigned h = 0, g;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800891
Brian Carlstromdf629502013-07-17 22:39:56 -0700892 while (*name) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800893 h = (h << 4) + *name++;
894 g = h & 0xf0000000;
895 h ^= g;
896 h ^= g >> 24;
897 }
898 return h;
899}
900
Tong Shen62d1ca32014-09-03 17:24:56 -0700901template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
902 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
903 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
904Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
905 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
906 ::GetSectionNameStringSection() const {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800907 return GetSectionHeader(GetHeader().e_shstrndx);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800908}
909
Tong Shen62d1ca32014-09-03 17:24:56 -0700910template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
911 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
912 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -0700913const uint8_t* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
Tong Shen62d1ca32014-09-03 17:24:56 -0700914 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
915 ::FindDynamicSymbolAddress(const std::string& symbol_name) const {
Andreas Gampedaab38c2014-09-12 18:38:24 -0700916 // Check that we have a hash section.
917 if (GetHashSectionStart() == nullptr) {
918 return nullptr; // Failure condition.
919 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700920 const Elf_Sym* sym = FindDynamicSymbol(symbol_name);
Alex Light3470ab42014-06-18 10:35:45 -0700921 if (sym != nullptr) {
922 return base_address_ + sym->st_value;
923 } else {
924 return nullptr;
925 }
926}
927
Andreas Gampedaab38c2014-09-12 18:38:24 -0700928// WARNING: Only called from FindDynamicSymbolAddress. Elides check for hash section.
Tong Shen62d1ca32014-09-03 17:24:56 -0700929template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
930 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
931 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
932const Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
933 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
934 ::FindDynamicSymbol(const std::string& symbol_name) const {
Andreas Gampec48b2062014-09-08 23:39:45 -0700935 if (GetHashBucketNum() == 0) {
936 // No dynamic symbols at all.
937 return nullptr;
938 }
Tong Shen62d1ca32014-09-03 17:24:56 -0700939 Elf_Word hash = elfhash(symbol_name.c_str());
940 Elf_Word bucket_index = hash % GetHashBucketNum();
Andreas Gampedaab38c2014-09-12 18:38:24 -0700941 bool ok;
Tong Shen62d1ca32014-09-03 17:24:56 -0700942 Elf_Word symbol_and_chain_index = GetHashBucket(bucket_index, &ok);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700943 if (!ok) {
944 return nullptr;
945 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800946 while (symbol_and_chain_index != 0 /* STN_UNDEF */) {
Tong Shen62d1ca32014-09-03 17:24:56 -0700947 Elf_Sym* symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700948 if (symbol == nullptr) {
949 return nullptr; // Failure condition.
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800950 }
Andreas Gampedaab38c2014-09-12 18:38:24 -0700951 const char* name = GetString(SHT_DYNSYM, symbol->st_name);
952 if (symbol_name == name) {
953 return symbol;
954 }
955 symbol_and_chain_index = GetHashChain(symbol_and_chain_index, &ok);
956 if (!ok) {
957 return nullptr;
958 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800959 }
Alex Light3470ab42014-06-18 10:35:45 -0700960 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800961}
962
Tong Shen62d1ca32014-09-03 17:24:56 -0700963template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
964 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
965 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
966bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
967 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
968 ::IsSymbolSectionType(Elf_Word section_type) {
969 return ((section_type == SHT_SYMTAB) || (section_type == SHT_DYNSYM));
970}
971
972template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
973 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
974 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
975Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
976 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
977 ::GetSymbolNum(Elf_Shdr& section_header) const {
Brian Carlstromc1409452014-02-26 14:06:23 -0800978 CHECK(IsSymbolSectionType(section_header.sh_type))
979 << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800980 CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath();
981 return section_header.sh_size / section_header.sh_entsize;
982}
983
Tong Shen62d1ca32014-09-03 17:24:56 -0700984template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
985 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
986 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
987Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
988 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
989 ::GetSymbol(Elf_Word section_type,
990 Elf_Word i) const {
991 Elf_Sym* sym_start = GetSymbolSectionStart(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -0700992 if (sym_start == nullptr) {
993 return nullptr;
994 }
995 return sym_start + i;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800996}
997
Tong Shen62d1ca32014-09-03 17:24:56 -0700998template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
999 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1000 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1001typename ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1002 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1003 ::SymbolTable** ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1004 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1005 ::GetSymbolTable(Elf_Word section_type) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001006 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
1007 switch (section_type) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001008 case SHT_SYMTAB: {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001009 return &symtab_symbol_table_;
1010 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001011 case SHT_DYNSYM: {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001012 return &dynsym_symbol_table_;
1013 }
1014 default: {
1015 LOG(FATAL) << section_type;
Alex Light3470ab42014-06-18 10:35:45 -07001016 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001017 }
1018 }
1019}
1020
Tong Shen62d1ca32014-09-03 17:24:56 -07001021template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1022 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1023 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1024Elf_Sym* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1025 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1026 ::FindSymbolByName(Elf_Word section_type,
1027 const std::string& symbol_name,
1028 bool build_map) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001029 CHECK(!program_header_only_) << file_->GetPath();
1030 CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001031
1032 SymbolTable** symbol_table = GetSymbolTable(section_type);
Alex Light3470ab42014-06-18 10:35:45 -07001033 if (*symbol_table != nullptr || build_map) {
1034 if (*symbol_table == nullptr) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001035 DCHECK(build_map);
1036 *symbol_table = new SymbolTable;
Tong Shen62d1ca32014-09-03 17:24:56 -07001037 Elf_Shdr* symbol_section = FindSectionByType(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001038 if (symbol_section == nullptr) {
1039 return nullptr; // Failure condition.
1040 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001041 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001042 if (string_section == nullptr) {
1043 return nullptr; // Failure condition.
1044 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001045 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001046 Elf_Sym* symbol = GetSymbol(section_type, i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001047 if (symbol == nullptr) {
1048 return nullptr; // Failure condition.
1049 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001050 unsigned char type = (sizeof(Elf_Addr) == sizeof(Elf64_Addr))
1051 ? ELF64_ST_TYPE(symbol->st_info)
1052 : ELF32_ST_TYPE(symbol->st_info);
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001053 if (type == STT_NOTYPE) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001054 continue;
1055 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001056 const char* name = GetString(*string_section, symbol->st_name);
Alex Light3470ab42014-06-18 10:35:45 -07001057 if (name == nullptr) {
Brian Carlstrom265091e2013-01-30 14:08:26 -08001058 continue;
1059 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001060 std::pair<typename SymbolTable::iterator, bool> result =
Andreas Gampedaab38c2014-09-12 18:38:24 -07001061 (*symbol_table)->insert(std::make_pair(name, symbol));
Brian Carlstrom265091e2013-01-30 14:08:26 -08001062 if (!result.second) {
1063 // If a duplicate, make sure it has the same logical value. Seen on x86.
Andreas Gampedaab38c2014-09-12 18:38:24 -07001064 if ((symbol->st_value != result.first->second->st_value) ||
1065 (symbol->st_size != result.first->second->st_size) ||
1066 (symbol->st_info != result.first->second->st_info) ||
1067 (symbol->st_other != result.first->second->st_other) ||
1068 (symbol->st_shndx != result.first->second->st_shndx)) {
1069 return nullptr; // Failure condition.
1070 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001071 }
1072 }
1073 }
Alex Light3470ab42014-06-18 10:35:45 -07001074 CHECK(*symbol_table != nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07001075 typename SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001076 if (it == (*symbol_table)->end()) {
Alex Light3470ab42014-06-18 10:35:45 -07001077 return nullptr;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001078 }
1079 return it->second;
1080 }
1081
1082 // Fall back to linear search
Tong Shen62d1ca32014-09-03 17:24:56 -07001083 Elf_Shdr* symbol_section = FindSectionByType(section_type);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001084 if (symbol_section == nullptr) {
1085 return nullptr;
1086 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001087 Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001088 if (string_section == nullptr) {
1089 return nullptr;
1090 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001091 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001092 Elf_Sym* symbol = GetSymbol(section_type, i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001093 if (symbol == nullptr) {
1094 return nullptr; // Failure condition.
1095 }
1096 const char* name = GetString(*string_section, symbol->st_name);
Alex Light3470ab42014-06-18 10:35:45 -07001097 if (name == nullptr) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001098 continue;
1099 }
1100 if (symbol_name == name) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001101 return symbol;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001102 }
1103 }
Alex Light3470ab42014-06-18 10:35:45 -07001104 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001105}
1106
Tong Shen62d1ca32014-09-03 17:24:56 -07001107template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1108 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1109 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1110Elf_Addr ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1111 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1112 ::FindSymbolAddress(Elf_Word section_type,
1113 const std::string& symbol_name,
1114 bool build_map) {
1115 Elf_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
Alex Light3470ab42014-06-18 10:35:45 -07001116 if (symbol == nullptr) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001117 return 0;
1118 }
1119 return symbol->st_value;
1120}
1121
Tong Shen62d1ca32014-09-03 17:24:56 -07001122template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1123 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1124 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1125const char* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1126 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1127 ::GetString(Elf_Shdr& string_section, Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001128 CHECK(!program_header_only_) << file_->GetPath();
1129 // TODO: remove this static_cast from enum when using -std=gnu++0x
Tong Shen62d1ca32014-09-03 17:24:56 -07001130 if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001131 return nullptr; // Failure condition.
1132 }
1133 if (i >= string_section.sh_size) {
1134 return nullptr;
1135 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001136 if (i == 0) {
Alex Light3470ab42014-06-18 10:35:45 -07001137 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001138 }
Ian Rogers13735952014-10-08 12:43:28 -07001139 uint8_t* strings = Begin() + string_section.sh_offset;
1140 uint8_t* string = strings + i;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001141 if (string >= End()) {
1142 return nullptr;
1143 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001144 return reinterpret_cast<const char*>(string);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001145}
1146
Tong Shen62d1ca32014-09-03 17:24:56 -07001147template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1148 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1149 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1150Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1151 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1152 ::GetDynamicNum() const {
1153 return GetDynamicProgramHeader().p_filesz / sizeof(Elf_Dyn);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001154}
1155
Tong Shen62d1ca32014-09-03 17:24:56 -07001156template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1157 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1158 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1159Elf_Dyn& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1160 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1161 ::GetDynamic(Elf_Word i) const {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001162 CHECK_LT(i, GetDynamicNum()) << file_->GetPath();
1163 return *(GetDynamicSectionStart() + i);
1164}
1165
Tong Shen62d1ca32014-09-03 17:24:56 -07001166template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1167 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1168 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1169Elf_Dyn* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1170 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1171 ::FindDynamicByType(Elf_Sword type) const {
1172 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1173 Elf_Dyn* dyn = &GetDynamic(i);
Alex Light53cb16b2014-06-12 11:26:29 -07001174 if (dyn->d_tag == type) {
1175 return dyn;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001176 }
1177 }
Alex Light53cb16b2014-06-12 11:26:29 -07001178 return NULL;
1179}
1180
Tong Shen62d1ca32014-09-03 17:24:56 -07001181template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1182 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1183 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1184Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1185 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1186 ::FindDynamicValueByType(Elf_Sword type) const {
1187 Elf_Dyn* dyn = FindDynamicByType(type);
Alex Light53cb16b2014-06-12 11:26:29 -07001188 if (dyn == NULL) {
1189 return 0;
1190 } else {
1191 return dyn->d_un.d_val;
1192 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001193}
1194
Tong Shen62d1ca32014-09-03 17:24:56 -07001195template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1196 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1197 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1198Elf_Rel* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1199 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1200 ::GetRelSectionStart(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001201 CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Tong Shen62d1ca32014-09-03 17:24:56 -07001202 return reinterpret_cast<Elf_Rel*>(Begin() + section_header.sh_offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001203}
1204
Tong Shen62d1ca32014-09-03 17:24:56 -07001205template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1206 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1207 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1208Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1209 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1210 ::GetRelNum(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001211 CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001212 CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath();
1213 return section_header.sh_size / section_header.sh_entsize;
1214}
1215
Tong Shen62d1ca32014-09-03 17:24:56 -07001216template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1217 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1218 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1219Elf_Rel& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1220 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1221 ::GetRel(Elf_Shdr& section_header, Elf_Word i) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001222 CHECK(SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001223 CHECK_LT(i, GetRelNum(section_header)) << file_->GetPath();
1224 return *(GetRelSectionStart(section_header) + i);
1225}
1226
Tong Shen62d1ca32014-09-03 17:24:56 -07001227template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1228 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1229 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1230Elf_Rela* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1231 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1232 ::GetRelaSectionStart(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001233 CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Tong Shen62d1ca32014-09-03 17:24:56 -07001234 return reinterpret_cast<Elf_Rela*>(Begin() + section_header.sh_offset);
Brian Carlstrom265091e2013-01-30 14:08:26 -08001235}
1236
Tong Shen62d1ca32014-09-03 17:24:56 -07001237template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1238 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1239 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1240Elf_Word ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1241 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1242 ::GetRelaNum(Elf_Shdr& section_header) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001243 CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001244 return section_header.sh_size / section_header.sh_entsize;
1245}
1246
Tong Shen62d1ca32014-09-03 17:24:56 -07001247template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1248 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1249 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1250Elf_Rela& ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1251 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1252 ::GetRela(Elf_Shdr& section_header, Elf_Word i) const {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001253 CHECK(SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
Brian Carlstrom265091e2013-01-30 14:08:26 -08001254 CHECK_LT(i, GetRelaNum(section_header)) << file_->GetPath();
1255 return *(GetRelaSectionStart(section_header) + i);
1256}
1257
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001258// Base on bionic phdr_table_get_load_size
Tong Shen62d1ca32014-09-03 17:24:56 -07001259template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1260 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1261 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1262size_t ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1263 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1264 ::GetLoadedSize() const {
1265 Elf_Addr min_vaddr = 0xFFFFFFFFu;
1266 Elf_Addr max_vaddr = 0x00000000u;
1267 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1268 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001269 if (program_header->p_type != PT_LOAD) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001270 continue;
1271 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001272 Elf_Addr begin_vaddr = program_header->p_vaddr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001273 if (begin_vaddr < min_vaddr) {
1274 min_vaddr = begin_vaddr;
1275 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001276 Elf_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001277 if (end_vaddr > max_vaddr) {
1278 max_vaddr = end_vaddr;
1279 }
1280 }
1281 min_vaddr = RoundDown(min_vaddr, kPageSize);
1282 max_vaddr = RoundUp(max_vaddr, kPageSize);
1283 CHECK_LT(min_vaddr, max_vaddr) << file_->GetPath();
1284 size_t loaded_size = max_vaddr - min_vaddr;
1285 return loaded_size;
1286}
1287
Tong Shen62d1ca32014-09-03 17:24:56 -07001288template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1289 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1290 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1291bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1292 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1293 ::Load(bool executable, std::string* error_msg) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001294 CHECK(program_header_only_) << file_->GetPath();
Andreas Gampe91268c12014-04-03 17:50:24 -07001295
1296 if (executable) {
1297 InstructionSet elf_ISA = kNone;
1298 switch (GetHeader().e_machine) {
1299 case EM_ARM: {
1300 elf_ISA = kArm;
1301 break;
1302 }
1303 case EM_AARCH64: {
1304 elf_ISA = kArm64;
1305 break;
1306 }
1307 case EM_386: {
1308 elf_ISA = kX86;
1309 break;
1310 }
1311 case EM_X86_64: {
1312 elf_ISA = kX86_64;
1313 break;
1314 }
1315 case EM_MIPS: {
1316 elf_ISA = kMips;
1317 break;
1318 }
1319 }
1320
1321 if (elf_ISA != kRuntimeISA) {
1322 std::ostringstream oss;
1323 oss << "Expected ISA " << kRuntimeISA << " but found " << elf_ISA;
1324 *error_msg = oss.str();
1325 return false;
1326 }
1327 }
1328
Jim_Guoa62a5882014-04-28 11:11:57 +08001329 bool reserved = false;
Tong Shen62d1ca32014-09-03 17:24:56 -07001330 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1331 Elf_Phdr* program_header = GetProgramHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001332 if (program_header == nullptr) {
1333 *error_msg = StringPrintf("No program header for entry %d in ELF file %s.",
1334 i, file_->GetPath().c_str());
1335 return false;
1336 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001337
1338 // Record .dynamic header information for later use
Andreas Gampedaab38c2014-09-12 18:38:24 -07001339 if (program_header->p_type == PT_DYNAMIC) {
1340 dynamic_program_header_ = program_header;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001341 continue;
1342 }
1343
1344 // Not something to load, move on.
Andreas Gampedaab38c2014-09-12 18:38:24 -07001345 if (program_header->p_type != PT_LOAD) {
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001346 continue;
1347 }
1348
1349 // Found something to load.
1350
Jim_Guoa62a5882014-04-28 11:11:57 +08001351 // Before load the actual segments, reserve a contiguous chunk
1352 // of required size and address for all segments, but with no
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001353 // permissions. We'll then carve that up with the proper
1354 // permissions as we load the actual segments. If p_vaddr is
1355 // non-zero, the segments require the specific address specified,
1356 // which either was specified in the file because we already set
1357 // base_address_ after the first zero segment).
Ian Rogerscdfcf372014-01-23 20:38:36 -08001358 int64_t temp_file_length = file_->GetLength();
1359 if (temp_file_length < 0) {
1360 errno = -temp_file_length;
1361 *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
1362 file_->GetPath().c_str(), file_->Fd(), strerror(errno));
1363 return false;
1364 }
1365 size_t file_length = static_cast<size_t>(temp_file_length);
Jim_Guoa62a5882014-04-28 11:11:57 +08001366 if (!reserved) {
Ian Rogers13735952014-10-08 12:43:28 -07001367 uint8_t* reserve_base = ((program_header->p_vaddr != 0) ?
1368 reinterpret_cast<uint8_t*>(program_header->p_vaddr) : nullptr);
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001369 std::string reservation_name("ElfFile reservation for ");
1370 reservation_name += file_->GetPath();
Ian Rogers700a4022014-05-19 16:49:03 -07001371 std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
Jim_Guoa62a5882014-04-28 11:11:57 +08001372 reserve_base,
1373 GetLoadedSize(), PROT_NONE, false,
1374 error_msg));
Brian Carlstromc1409452014-02-26 14:06:23 -08001375 if (reserve.get() == nullptr) {
1376 *error_msg = StringPrintf("Failed to allocate %s: %s",
1377 reservation_name.c_str(), error_msg->c_str());
1378 return false;
1379 }
Jim_Guoa62a5882014-04-28 11:11:57 +08001380 reserved = true;
1381 if (reserve_base == nullptr) {
1382 base_address_ = reserve->Begin();
1383 }
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001384 segments_.push_back(reserve.release());
1385 }
1386 // empty segment, nothing to map
Andreas Gampedaab38c2014-09-12 18:38:24 -07001387 if (program_header->p_memsz == 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001388 continue;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001389 }
Ian Rogers13735952014-10-08 12:43:28 -07001390 uint8_t* p_vaddr = base_address_ + program_header->p_vaddr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001391 int prot = 0;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001392 if (executable && ((program_header->p_flags & PF_X) != 0)) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001393 prot |= PROT_EXEC;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001394 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001395 if ((program_header->p_flags & PF_W) != 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001396 prot |= PROT_WRITE;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001397 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001398 if ((program_header->p_flags & PF_R) != 0) {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -07001399 prot |= PROT_READ;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001400 }
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -07001401 int flags = 0;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001402 if (writable_) {
1403 prot |= PROT_WRITE;
1404 flags |= MAP_SHARED;
1405 } else {
1406 flags |= MAP_PRIVATE;
1407 }
Andreas Gampedaab38c2014-09-12 18:38:24 -07001408 if (file_length < (program_header->p_offset + program_header->p_memsz)) {
Ian Rogerscdfcf372014-01-23 20:38:36 -08001409 *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment "
Tong Shen62d1ca32014-09-03 17:24:56 -07001410 "%d of %" PRIu64 " bytes: '%s'", file_length, i,
1411 static_cast<uint64_t>(program_header->p_offset + program_header->p_memsz),
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001412 file_->GetPath().c_str());
Brian Carlstrom3a223612013-10-10 17:18:24 -07001413 return false;
1414 }
Ian Rogers700a4022014-05-19 16:49:03 -07001415 std::unique_ptr<MemMap> segment(MemMap::MapFileAtAddress(p_vaddr,
Andreas Gampedaab38c2014-09-12 18:38:24 -07001416 program_header->p_memsz,
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001417 prot, flags, file_->Fd(),
Andreas Gampedaab38c2014-09-12 18:38:24 -07001418 program_header->p_offset,
Hiroshi Yamauchi4fb5df82014-03-13 15:10:27 -07001419 true, // implies MAP_FIXED
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001420 file_->GetPath().c_str(),
1421 error_msg));
Brian Carlstromc1409452014-02-26 14:06:23 -08001422 if (segment.get() == nullptr) {
1423 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s",
1424 i, file_->GetPath().c_str(), error_msg->c_str());
1425 return false;
1426 }
1427 if (segment->Begin() != p_vaddr) {
1428 *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, "
1429 "instead mapped to %p",
1430 i, file_->GetPath().c_str(), p_vaddr, segment->Begin());
1431 return false;
1432 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001433 segments_.push_back(segment.release());
1434 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001435
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001436 // Now that we are done loading, .dynamic should be in memory to find .dynstr, .dynsym, .hash
Ian Rogers13735952014-10-08 12:43:28 -07001437 uint8_t* dsptr = base_address_ + GetDynamicProgramHeader().p_vaddr;
Andreas Gampedaab38c2014-09-12 18:38:24 -07001438 if ((dsptr < Begin() || dsptr >= End()) && !ValidPointer(dsptr)) {
1439 *error_msg = StringPrintf("dynamic section address invalid in ELF file %s",
1440 file_->GetPath().c_str());
1441 return false;
1442 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001443 dynamic_section_start_ = reinterpret_cast<Elf_Dyn*>(dsptr);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001444
Tong Shen62d1ca32014-09-03 17:24:56 -07001445 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1446 Elf_Dyn& elf_dyn = GetDynamic(i);
Ian Rogers13735952014-10-08 12:43:28 -07001447 uint8_t* d_ptr = base_address_ + elf_dyn.d_un.d_ptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001448 switch (elf_dyn.d_tag) {
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001449 case DT_HASH: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001450 if (!ValidPointer(d_ptr)) {
1451 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1452 d_ptr, file_->GetPath().c_str());
1453 return false;
1454 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001455 hash_section_start_ = reinterpret_cast<Elf_Word*>(d_ptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001456 break;
1457 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001458 case DT_STRTAB: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001459 if (!ValidPointer(d_ptr)) {
1460 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1461 d_ptr, file_->GetPath().c_str());
1462 return false;
1463 }
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001464 dynstr_section_start_ = reinterpret_cast<char*>(d_ptr);
1465 break;
1466 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001467 case DT_SYMTAB: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001468 if (!ValidPointer(d_ptr)) {
1469 *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1470 d_ptr, file_->GetPath().c_str());
1471 return false;
1472 }
Tong Shen62d1ca32014-09-03 17:24:56 -07001473 dynsym_section_start_ = reinterpret_cast<Elf_Sym*>(d_ptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001474 break;
1475 }
Nicolas Geoffray50cfe742014-02-19 13:27:42 +00001476 case DT_NULL: {
Brian Carlstromc1409452014-02-26 14:06:23 -08001477 if (GetDynamicNum() != i+1) {
1478 *error_msg = StringPrintf("DT_NULL found after %d .dynamic entries, "
1479 "expected %d as implied by size of PT_DYNAMIC segment in %s",
1480 i + 1, GetDynamicNum(), file_->GetPath().c_str());
1481 return false;
1482 }
Brian Carlstrom265091e2013-01-30 14:08:26 -08001483 break;
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001484 }
1485 }
1486 }
1487
Andreas Gampedaab38c2014-09-12 18:38:24 -07001488 // Check for the existence of some sections.
1489 if (!CheckSectionsExist(error_msg)) {
1490 return false;
1491 }
1492
Mark Mendellae9fd932014-02-10 16:14:35 -08001493 // Use GDB JIT support to do stack backtrace, etc.
1494 if (executable) {
1495 GdbJITSupport();
1496 }
1497
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001498 return true;
1499}
1500
Tong Shen62d1ca32014-09-03 17:24:56 -07001501template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1502 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1503 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1504bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1505 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
Ian Rogers13735952014-10-08 12:43:28 -07001506 ::ValidPointer(const uint8_t* start) const {
Brian Carlstromc1409452014-02-26 14:06:23 -08001507 for (size_t i = 0; i < segments_.size(); ++i) {
1508 const MemMap* segment = segments_[i];
1509 if (segment->Begin() <= start && start < segment->End()) {
1510 return true;
1511 }
1512 }
1513 return false;
1514}
1515
Alex Light3470ab42014-06-18 10:35:45 -07001516
Tong Shen62d1ca32014-09-03 17:24:56 -07001517template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
1518 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
1519 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
1520Elf_Shdr* ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
1521 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
1522 ::FindSectionByName(const std::string& name) const {
Alex Light3470ab42014-06-18 10:35:45 -07001523 CHECK(!program_header_only_);
Tong Shen62d1ca32014-09-03 17:24:56 -07001524 Elf_Shdr* shstrtab_sec = GetSectionNameStringSection();
Andreas Gampedaab38c2014-09-12 18:38:24 -07001525 if (shstrtab_sec == nullptr) {
1526 return nullptr;
1527 }
Alex Light3470ab42014-06-18 10:35:45 -07001528 for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) {
Tong Shen62d1ca32014-09-03 17:24:56 -07001529 Elf_Shdr* shdr = GetSectionHeader(i);
Andreas Gampedaab38c2014-09-12 18:38:24 -07001530 if (shdr == nullptr) {
1531 return nullptr;
1532 }
1533 const char* sec_name = GetString(*shstrtab_sec, shdr->sh_name);
Alex Light3470ab42014-06-18 10:35:45 -07001534 if (sec_name == nullptr) {
1535 continue;
1536 }
1537 if (name == sec_name) {
Andreas Gampedaab38c2014-09-12 18:38:24 -07001538 return shdr;
Alex Light3470ab42014-06-18 10:35:45 -07001539 }
1540 }
1541 return nullptr;
Mark Mendellae9fd932014-02-10 16:14:35 -08001542}
1543
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001544struct PACKED(1) FDE32 {
Alex Light3470ab42014-06-18 10:35:45 -07001545 uint32_t raw_length_;
1546 uint32_t GetLength() {
1547 return raw_length_ + sizeof(raw_length_);
1548 }
1549 uint32_t CIE_pointer;
1550 uint32_t initial_location;
1551 uint32_t address_range;
1552 uint8_t instructions[0];
1553};
1554
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001555static FDE32* NextFDE(FDE32* frame) {
Ian Rogers13735952014-10-08 12:43:28 -07001556 uint8_t* fde_bytes = reinterpret_cast<uint8_t*>(frame);
Alex Light3470ab42014-06-18 10:35:45 -07001557 fde_bytes += frame->GetLength();
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001558 return reinterpret_cast<FDE32*>(fde_bytes);
Mark Mendellae9fd932014-02-10 16:14:35 -08001559}
1560
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001561static bool IsFDE(FDE32* frame) {
Tong Shen35e1e6a2014-07-30 09:31:22 -07001562 return frame->CIE_pointer != 0;
Alex Light3470ab42014-06-18 10:35:45 -07001563}
1564
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001565struct PACKED(1) FDE64 {
1566 uint32_t raw_length_;
1567 uint64_t extended_length_;
1568 uint64_t GetLength() {
1569 return extended_length_ + sizeof(raw_length_) + sizeof(extended_length_);
1570 }
1571 uint64_t CIE_pointer;
1572 uint64_t initial_location;
1573 uint64_t address_range;
1574 uint8_t instructions[0];
1575};
1576
1577static FDE64* NextFDE(FDE64* frame) {
Ian Rogers13735952014-10-08 12:43:28 -07001578 uint8_t* fde_bytes = reinterpret_cast<uint8_t*>(frame);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001579 fde_bytes += frame->GetLength();
1580 return reinterpret_cast<FDE64*>(fde_bytes);
1581}
1582
1583static bool IsFDE(FDE64* frame) {
1584 return frame->CIE_pointer != 0;
1585}
1586
1587static bool FixupEHFrame(off_t base_address_delta,
Ian Rogers13735952014-10-08 12:43:28 -07001588 uint8_t* eh_frame, size_t eh_frame_size) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001589 if (*(reinterpret_cast<uint32_t*>(eh_frame)) == 0xffffffff) {
1590 FDE64* last_frame = reinterpret_cast<FDE64*>(eh_frame + eh_frame_size);
1591 FDE64* frame = NextFDE(reinterpret_cast<FDE64*>(eh_frame));
1592 for (; frame < last_frame; frame = NextFDE(frame)) {
1593 if (!IsFDE(frame)) {
1594 return false;
1595 }
1596 frame->initial_location += base_address_delta;
1597 }
1598 return true;
1599 } else {
1600 FDE32* last_frame = reinterpret_cast<FDE32*>(eh_frame + eh_frame_size);
1601 FDE32* frame = NextFDE(reinterpret_cast<FDE32*>(eh_frame));
1602 for (; frame < last_frame; frame = NextFDE(frame)) {
1603 if (!IsFDE(frame)) {
1604 return false;
1605 }
1606 frame->initial_location += base_address_delta;
1607 }
1608 return true;
1609 }
1610}
1611
1612static uint8_t* NextLeb128(uint8_t* current) {
1613 DecodeUnsignedLeb128(const_cast<const uint8_t**>(&current));
1614 return current;
1615}
1616
1617struct PACKED(1) DebugLineHeader {
1618 uint32_t unit_length_; // TODO 32-bit specific size
1619 uint16_t version_;
1620 uint32_t header_length_; // TODO 32-bit specific size
1621 uint8_t minimum_instruction_lenght_;
1622 uint8_t maximum_operations_per_instruction_;
1623 uint8_t default_is_stmt_;
1624 int8_t line_base_;
1625 uint8_t line_range_;
1626 uint8_t opcode_base_;
1627 uint8_t remaining_[0];
1628
1629 bool IsStandardOpcode(const uint8_t* op) const {
1630 return *op != 0 && *op < opcode_base_;
1631 }
1632
1633 bool IsExtendedOpcode(const uint8_t* op) const {
1634 return *op == 0;
1635 }
1636
1637 const uint8_t* GetStandardOpcodeLengths() const {
1638 return remaining_;
1639 }
1640
1641 uint8_t* GetNextOpcode(uint8_t* op) const {
1642 if (IsExtendedOpcode(op)) {
1643 uint8_t* length_field = op + 1;
1644 uint32_t length = DecodeUnsignedLeb128(const_cast<const uint8_t**>(&length_field));
1645 return length_field + length;
1646 } else if (!IsStandardOpcode(op)) {
1647 return op + 1;
1648 } else if (*op == DW_LNS_fixed_advance_pc) {
1649 return op + 1 + sizeof(uint16_t);
1650 } else {
1651 uint8_t num_args = GetStandardOpcodeLengths()[*op - 1];
1652 op += 1;
1653 for (int i = 0; i < num_args; i++) {
1654 op = NextLeb128(op);
1655 }
1656 return op;
1657 }
1658 }
1659
1660 uint8_t* GetDebugLineData() const {
1661 const uint8_t* hdr_start =
1662 reinterpret_cast<const uint8_t*>(&header_length_) + sizeof(header_length_);
1663 return const_cast<uint8_t*>(hdr_start + header_length_);
1664 }
1665};
1666
Ian Rogersd4c4d952014-10-16 20:31:53 -07001667class DebugLineInstructionIterator FINAL {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001668 public:
1669 static DebugLineInstructionIterator* Create(DebugLineHeader* header, size_t section_size) {
1670 std::unique_ptr<DebugLineInstructionIterator> line_iter(
1671 new DebugLineInstructionIterator(header, section_size));
1672 if (line_iter.get() == nullptr) {
1673 return nullptr;
1674 } else {
1675 return line_iter.release();
1676 }
1677 }
1678
1679 ~DebugLineInstructionIterator() {}
1680
1681 bool Next() {
1682 if (current_instruction_ == nullptr) {
Alex Light3470ab42014-06-18 10:35:45 -07001683 return false;
1684 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001685 current_instruction_ = header_->GetNextOpcode(current_instruction_);
1686 if (current_instruction_ >= last_instruction_) {
1687 current_instruction_ = nullptr;
1688 return false;
1689 } else {
1690 return true;
1691 }
1692 }
1693
Ian Rogersd4c4d952014-10-16 20:31:53 -07001694 uint8_t* GetInstruction() const {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001695 return current_instruction_;
1696 }
1697
Ian Rogersd4c4d952014-10-16 20:31:53 -07001698 bool IsExtendedOpcode() const {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001699 return header_->IsExtendedOpcode(current_instruction_);
1700 }
1701
1702 uint8_t GetOpcode() {
1703 if (!IsExtendedOpcode()) {
1704 return *current_instruction_;
1705 } else {
1706 uint8_t* len_ptr = current_instruction_ + 1;
1707 return *NextLeb128(len_ptr);
1708 }
1709 }
1710
1711 uint8_t* GetArguments() {
1712 if (!IsExtendedOpcode()) {
1713 return current_instruction_ + 1;
1714 } else {
1715 uint8_t* len_ptr = current_instruction_ + 1;
1716 return NextLeb128(len_ptr) + 1;
1717 }
1718 }
1719
1720 private:
1721 DebugLineInstructionIterator(DebugLineHeader* header, size_t size)
1722 : header_(header), last_instruction_(reinterpret_cast<uint8_t*>(header) + size),
1723 current_instruction_(header->GetDebugLineData()) {}
1724
Ian Rogersd4c4d952014-10-16 20:31:53 -07001725 DebugLineHeader* const header_;
1726 uint8_t* const last_instruction_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07001727 uint8_t* current_instruction_;
1728};
1729
1730static bool FixupDebugLine(off_t base_offset_delta, DebugLineInstructionIterator* iter) {
1731 while (iter->Next()) {
1732 if (iter->IsExtendedOpcode() && iter->GetOpcode() == DW_LNE_set_address) {
1733 *reinterpret_cast<uint32_t*>(iter->GetArguments()) += base_offset_delta;
1734 }
Alex Light3470ab42014-06-18 10:35:45 -07001735 }
1736 return true;
1737}
1738
1739struct PACKED(1) DebugInfoHeader {
1740 uint32_t unit_length; // TODO 32-bit specific size
1741 uint16_t version;
1742 uint32_t debug_abbrev_offset; // TODO 32-bit specific size
1743 uint8_t address_size;
1744};
1745
1746// Returns -1 if it is variable length, which we will just disallow for now.
1747static int32_t FormLength(uint32_t att) {
1748 switch (att) {
1749 case DW_FORM_data1:
1750 case DW_FORM_flag:
1751 case DW_FORM_flag_present:
1752 case DW_FORM_ref1:
1753 return 1;
1754
1755 case DW_FORM_data2:
1756 case DW_FORM_ref2:
1757 return 2;
1758
1759 case DW_FORM_addr: // TODO 32-bit only
1760 case DW_FORM_ref_addr: // TODO 32-bit only
1761 case DW_FORM_sec_offset: // TODO 32-bit only
1762 case DW_FORM_strp: // TODO 32-bit only
1763 case DW_FORM_data4:
1764 case DW_FORM_ref4:
1765 return 4;
1766
1767 case DW_FORM_data8:
1768 case DW_FORM_ref8:
1769 case DW_FORM_ref_sig8:
1770 return 8;
1771
1772 case DW_FORM_block:
1773 case DW_FORM_block1:
1774 case DW_FORM_block2:
1775 case DW_FORM_block4:
1776 case DW_FORM_exprloc:
1777 case DW_FORM_indirect:
1778 case DW_FORM_ref_udata:
1779 case DW_FORM_sdata:
1780 case DW_FORM_string:
1781 case DW_FORM_udata:
1782 default:
1783 return -1;
Mark Mendellae9fd932014-02-10 16:14:35 -08001784 }
1785}
1786
Ian Rogersd4c4d952014-10-16 20:31:53 -07001787class DebugTag FINAL {
Alex Light3470ab42014-06-18 10:35:45 -07001788 public:
Alex Light3470ab42014-06-18 10:35:45 -07001789 ~DebugTag() {}
1790 // Creates a new tag and moves data pointer up to the start of the next one.
1791 // nullptr means error.
Ian Rogers13735952014-10-08 12:43:28 -07001792 static DebugTag* Create(const uint8_t** data_pointer) {
1793 const uint8_t* data = *data_pointer;
Alex Light3470ab42014-06-18 10:35:45 -07001794 uint32_t index = DecodeUnsignedLeb128(&data);
1795 std::unique_ptr<DebugTag> tag(new DebugTag(index));
1796 tag->size_ = static_cast<uint32_t>(
1797 reinterpret_cast<uintptr_t>(data) - reinterpret_cast<uintptr_t>(*data_pointer));
1798 // skip the abbrev
1799 tag->tag_ = DecodeUnsignedLeb128(&data);
1800 tag->has_child_ = (*data == 0);
1801 data++;
1802 while (true) {
1803 uint32_t attr = DecodeUnsignedLeb128(&data);
1804 uint32_t form = DecodeUnsignedLeb128(&data);
1805 if (attr == 0 && form == 0) {
1806 break;
1807 } else if (attr == 0 || form == 0) {
1808 // Bad abbrev.
1809 return nullptr;
1810 }
1811 int32_t size = FormLength(form);
1812 if (size == -1) {
1813 return nullptr;
1814 }
1815 tag->AddAttribute(attr, static_cast<uint32_t>(size));
1816 }
1817 *data_pointer = data;
1818 return tag.release();
1819 }
1820
1821 uint32_t GetSize() const {
1822 return size_;
1823 }
1824
Ian Rogersd4c4d952014-10-16 20:31:53 -07001825 bool HasChild() const {
Alex Light3470ab42014-06-18 10:35:45 -07001826 return has_child_;
1827 }
1828
Ian Rogersd4c4d952014-10-16 20:31:53 -07001829 uint32_t GetTagNumber() const {
Alex Light3470ab42014-06-18 10:35:45 -07001830 return tag_;
1831 }
1832
Ian Rogersd4c4d952014-10-16 20:31:53 -07001833 uint32_t GetIndex() const {
1834 return index_;
1835 }
1836
Alex Light3470ab42014-06-18 10:35:45 -07001837 // Gets the offset of a particular attribute in this tag structure.
1838 // Interpretation of the data is left to the consumer. 0 is returned if the
1839 // tag does not contain the attribute.
1840 uint32_t GetOffsetOf(uint32_t dwarf_attribute) const {
1841 auto it = off_map_.find(dwarf_attribute);
1842 if (it == off_map_.end()) {
1843 return 0;
1844 } else {
1845 return it->second;
1846 }
1847 }
1848
1849 // Gets the size of attribute
1850 uint32_t GetAttrSize(uint32_t dwarf_attribute) const {
1851 auto it = size_map_.find(dwarf_attribute);
1852 if (it == size_map_.end()) {
1853 return 0;
1854 } else {
1855 return it->second;
1856 }
1857 }
1858
1859 private:
Andreas Gampedaab38c2014-09-12 18:38:24 -07001860 explicit DebugTag(uint32_t index) : index_(index), size_(0), tag_(0), has_child_(false) {}
Alex Light3470ab42014-06-18 10:35:45 -07001861 void AddAttribute(uint32_t type, uint32_t attr_size) {
1862 off_map_.insert(std::pair<uint32_t, uint32_t>(type, size_));
1863 size_map_.insert(std::pair<uint32_t, uint32_t>(type, attr_size));
1864 size_ += attr_size;
1865 }
Ian Rogersd4c4d952014-10-16 20:31:53 -07001866
1867 const uint32_t index_;
Alex Light3470ab42014-06-18 10:35:45 -07001868 std::map<uint32_t, uint32_t> off_map_;
1869 std::map<uint32_t, uint32_t> size_map_;
1870 uint32_t size_;
1871 uint32_t tag_;
1872 bool has_child_;
1873};
1874
1875class DebugAbbrev {
1876 public:
1877 ~DebugAbbrev() {}
Ian Rogers13735952014-10-08 12:43:28 -07001878 static DebugAbbrev* Create(const uint8_t* dbg_abbrev, size_t dbg_abbrev_size) {
Alex Lightd338ae02014-08-13 17:15:38 -07001879 std::unique_ptr<DebugAbbrev> abbrev(new DebugAbbrev(dbg_abbrev, dbg_abbrev + dbg_abbrev_size));
1880 if (!abbrev->ReadAtOffset(0)) {
1881 return nullptr;
Alex Light3470ab42014-06-18 10:35:45 -07001882 }
1883 return abbrev.release();
1884 }
1885
Alex Lightd338ae02014-08-13 17:15:38 -07001886 bool ReadAtOffset(uint32_t abbrev_offset) {
1887 tags_.clear();
1888 tag_list_.clear();
Ian Rogers13735952014-10-08 12:43:28 -07001889 const uint8_t* dbg_abbrev = begin_ + abbrev_offset;
Alex Lightd338ae02014-08-13 17:15:38 -07001890 while (dbg_abbrev < end_ && *dbg_abbrev != 0) {
1891 std::unique_ptr<DebugTag> tag(DebugTag::Create(&dbg_abbrev));
1892 if (tag.get() == nullptr) {
1893 return false;
1894 } else {
Ian Rogersd4c4d952014-10-16 20:31:53 -07001895 tags_.insert(std::pair<uint32_t, uint32_t>(tag->GetIndex(), tag_list_.size()));
Alex Lightd338ae02014-08-13 17:15:38 -07001896 tag_list_.push_back(std::move(tag));
1897 }
1898 }
1899 return true;
1900 }
1901
Ian Rogers13735952014-10-08 12:43:28 -07001902 DebugTag* ReadTag(const uint8_t* entry) {
Alex Light3470ab42014-06-18 10:35:45 -07001903 uint32_t tag_num = DecodeUnsignedLeb128(&entry);
1904 auto it = tags_.find(tag_num);
1905 if (it == tags_.end()) {
1906 return nullptr;
1907 } else {
1908 CHECK_GT(tag_list_.size(), it->second);
1909 return tag_list_.at(it->second).get();
1910 }
1911 }
1912
1913 private:
Ian Rogers13735952014-10-08 12:43:28 -07001914 DebugAbbrev(const uint8_t* begin, const uint8_t* end) : begin_(begin), end_(end) {}
Ian Rogersd4c4d952014-10-16 20:31:53 -07001915 const uint8_t* const begin_;
1916 const uint8_t* const end_;
Alex Light3470ab42014-06-18 10:35:45 -07001917 std::map<uint32_t, uint32_t> tags_;
1918 std::vector<std::unique_ptr<DebugTag>> tag_list_;
1919};
1920
1921class DebugInfoIterator {
1922 public:
1923 static DebugInfoIterator* Create(DebugInfoHeader* header, size_t frame_size,
1924 DebugAbbrev* abbrev) {
1925 std::unique_ptr<DebugInfoIterator> iter(new DebugInfoIterator(header, frame_size, abbrev));
1926 if (iter->GetCurrentTag() == nullptr) {
1927 return nullptr;
1928 } else {
1929 return iter.release();
1930 }
1931 }
1932 ~DebugInfoIterator() {}
1933
1934 // Moves to the next DIE. Returns false if at last entry.
1935 // TODO Handle variable length attributes.
1936 bool next() {
1937 if (current_entry_ == nullptr || current_tag_ == nullptr) {
1938 return false;
1939 }
Alex Lightd338ae02014-08-13 17:15:38 -07001940 bool reread_abbrev = false;
Alex Light3470ab42014-06-18 10:35:45 -07001941 current_entry_ += current_tag_->GetSize();
Alex Lightd338ae02014-08-13 17:15:38 -07001942 if (reinterpret_cast<DebugInfoHeader*>(current_entry_) >= next_cu_) {
1943 current_cu_ = next_cu_;
1944 next_cu_ = GetNextCu(current_cu_);
Ian Rogers13735952014-10-08 12:43:28 -07001945 current_entry_ = reinterpret_cast<uint8_t*>(current_cu_) + sizeof(DebugInfoHeader);
Alex Lightd338ae02014-08-13 17:15:38 -07001946 reread_abbrev = true;
1947 }
Alex Light3470ab42014-06-18 10:35:45 -07001948 if (current_entry_ >= last_entry_) {
1949 current_entry_ = nullptr;
1950 return false;
1951 }
Alex Lightd338ae02014-08-13 17:15:38 -07001952 if (reread_abbrev) {
1953 abbrev_->ReadAtOffset(current_cu_->debug_abbrev_offset);
1954 }
Alex Light3470ab42014-06-18 10:35:45 -07001955 current_tag_ = abbrev_->ReadTag(current_entry_);
1956 if (current_tag_ == nullptr) {
1957 current_entry_ = nullptr;
1958 return false;
1959 } else {
1960 return true;
1961 }
1962 }
1963
1964 const DebugTag* GetCurrentTag() {
1965 return const_cast<DebugTag*>(current_tag_);
1966 }
Ian Rogers13735952014-10-08 12:43:28 -07001967 uint8_t* GetPointerToField(uint8_t dwarf_field) {
Alex Light3470ab42014-06-18 10:35:45 -07001968 if (current_tag_ == nullptr || current_entry_ == nullptr || current_entry_ >= last_entry_) {
1969 return nullptr;
1970 }
1971 uint32_t off = current_tag_->GetOffsetOf(dwarf_field);
1972 if (off == 0) {
1973 // tag does not have that field.
1974 return nullptr;
1975 } else {
1976 DCHECK_LT(off, current_tag_->GetSize());
1977 return current_entry_ + off;
1978 }
1979 }
1980
1981 private:
Alex Lightd338ae02014-08-13 17:15:38 -07001982 static DebugInfoHeader* GetNextCu(DebugInfoHeader* hdr) {
Ian Rogers13735952014-10-08 12:43:28 -07001983 uint8_t* hdr_byte = reinterpret_cast<uint8_t*>(hdr);
Alex Lightd338ae02014-08-13 17:15:38 -07001984 return reinterpret_cast<DebugInfoHeader*>(hdr_byte + sizeof(uint32_t) + hdr->unit_length);
1985 }
1986
Alex Light3470ab42014-06-18 10:35:45 -07001987 DebugInfoIterator(DebugInfoHeader* header, size_t frame_size, DebugAbbrev* abbrev)
1988 : abbrev_(abbrev),
Alex Lightd338ae02014-08-13 17:15:38 -07001989 current_cu_(header),
1990 next_cu_(GetNextCu(header)),
Ian Rogers13735952014-10-08 12:43:28 -07001991 last_entry_(reinterpret_cast<uint8_t*>(header) + frame_size),
1992 current_entry_(reinterpret_cast<uint8_t*>(header) + sizeof(DebugInfoHeader)),
Alex Light3470ab42014-06-18 10:35:45 -07001993 current_tag_(abbrev_->ReadTag(current_entry_)) {}
Ian Rogersd4c4d952014-10-16 20:31:53 -07001994 DebugAbbrev* const abbrev_;
Alex Lightd338ae02014-08-13 17:15:38 -07001995 DebugInfoHeader* current_cu_;
1996 DebugInfoHeader* next_cu_;
Ian Rogersd4c4d952014-10-16 20:31:53 -07001997 uint8_t* const last_entry_;
Ian Rogers13735952014-10-08 12:43:28 -07001998 uint8_t* current_entry_;
Alex Light3470ab42014-06-18 10:35:45 -07001999 DebugTag* current_tag_;
2000};
2001
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002002static bool FixupDebugInfo(off_t base_address_delta, DebugInfoIterator* iter) {
Alex Light3470ab42014-06-18 10:35:45 -07002003 do {
2004 if (iter->GetCurrentTag()->GetAttrSize(DW_AT_low_pc) != sizeof(int32_t) ||
2005 iter->GetCurrentTag()->GetAttrSize(DW_AT_high_pc) != sizeof(int32_t)) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002006 LOG(ERROR) << "DWARF information with 64 bit pointers is not supported yet.";
Alex Light3470ab42014-06-18 10:35:45 -07002007 return false;
2008 }
2009 uint32_t* PC_low = reinterpret_cast<uint32_t*>(iter->GetPointerToField(DW_AT_low_pc));
2010 uint32_t* PC_high = reinterpret_cast<uint32_t*>(iter->GetPointerToField(DW_AT_high_pc));
2011 if (PC_low != nullptr && PC_high != nullptr) {
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002012 *PC_low += base_address_delta;
2013 *PC_high += base_address_delta;
Alex Light3470ab42014-06-18 10:35:45 -07002014 }
2015 } while (iter->next());
2016 return true;
2017}
2018
Tong Shen62d1ca32014-09-03 17:24:56 -07002019template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2020 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2021 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2022bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2023 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2024 ::FixupDebugSections(off_t base_address_delta) {
2025 const Elf_Shdr* debug_info = FindSectionByName(".debug_info");
2026 const Elf_Shdr* debug_abbrev = FindSectionByName(".debug_abbrev");
2027 const Elf_Shdr* eh_frame = FindSectionByName(".eh_frame");
2028 const Elf_Shdr* debug_str = FindSectionByName(".debug_str");
2029 const Elf_Shdr* debug_line = FindSectionByName(".debug_line");
2030 const Elf_Shdr* strtab_sec = FindSectionByName(".strtab");
2031 const Elf_Shdr* symtab_sec = FindSectionByName(".symtab");
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002032
2033 if (debug_info == nullptr || debug_abbrev == nullptr ||
2034 debug_str == nullptr || strtab_sec == nullptr || symtab_sec == nullptr) {
2035 // Release version of ART does not generate debug info.
2036 return true;
2037 }
2038 if (base_address_delta == 0) {
2039 return true;
2040 }
2041 if (eh_frame != nullptr &&
2042 !FixupEHFrame(base_address_delta, Begin() + eh_frame->sh_offset, eh_frame->sh_size)) {
2043 return false;
2044 }
2045
2046 std::unique_ptr<DebugAbbrev> abbrev(DebugAbbrev::Create(Begin() + debug_abbrev->sh_offset,
2047 debug_abbrev->sh_size));
Alex Light3470ab42014-06-18 10:35:45 -07002048 if (abbrev.get() == nullptr) {
2049 return false;
2050 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002051 DebugInfoHeader* info_header =
2052 reinterpret_cast<DebugInfoHeader*>(Begin() + debug_info->sh_offset);
2053 std::unique_ptr<DebugInfoIterator> info_iter(DebugInfoIterator::Create(info_header,
2054 debug_info->sh_size,
2055 abbrev.get()));
2056 if (info_iter.get() == nullptr) {
Alex Light3470ab42014-06-18 10:35:45 -07002057 return false;
2058 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002059 if (debug_line != nullptr) {
2060 DebugLineHeader* line_header =
2061 reinterpret_cast<DebugLineHeader*>(Begin() + debug_line->sh_offset);
2062 std::unique_ptr<DebugLineInstructionIterator> line_iter(
2063 DebugLineInstructionIterator::Create(line_header, debug_line->sh_size));
2064 if (line_iter.get() == nullptr) {
2065 return false;
2066 }
2067 if (!FixupDebugLine(base_address_delta, line_iter.get())) {
2068 return false;
2069 }
2070 }
2071 return FixupDebugInfo(base_address_delta, info_iter.get());
Alex Light3470ab42014-06-18 10:35:45 -07002072}
Mark Mendellae9fd932014-02-10 16:14:35 -08002073
Tong Shen62d1ca32014-09-03 17:24:56 -07002074template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2075 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2076 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2077void ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2078 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2079 ::GdbJITSupport() {
Mark Mendellae9fd932014-02-10 16:14:35 -08002080 // We only get here if we only are mapping the program header.
2081 DCHECK(program_header_only_);
2082
2083 // Well, we need the whole file to do this.
2084 std::string error_msg;
Alex Light3470ab42014-06-18 10:35:45 -07002085 // Make it MAP_PRIVATE so we can just give it to gdb if all the necessary
2086 // sections are there.
Tong Shen62d1ca32014-09-03 17:24:56 -07002087 std::unique_ptr<ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2088 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>>
2089 all_ptr(Open(const_cast<File*>(file_), PROT_READ | PROT_WRITE,
2090 MAP_PRIVATE, &error_msg));
Alex Light3470ab42014-06-18 10:35:45 -07002091 if (all_ptr.get() == nullptr) {
Mark Mendellae9fd932014-02-10 16:14:35 -08002092 return;
2093 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002094 ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2095 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>& all = *all_ptr;
Alex Light3470ab42014-06-18 10:35:45 -07002096
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002097 // We need the eh_frame for gdb but debug info might be present without it.
Tong Shen62d1ca32014-09-03 17:24:56 -07002098 const Elf_Shdr* eh_frame = all.FindSectionByName(".eh_frame");
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002099 if (eh_frame == nullptr) {
Mark Mendellae9fd932014-02-10 16:14:35 -08002100 return;
2101 }
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002102
2103 // Do we have interesting sections?
Alex Light3470ab42014-06-18 10:35:45 -07002104 // We need to add in a strtab and symtab to the image.
2105 // all is MAP_PRIVATE so it can be written to freely.
2106 // We also already have strtab and symtab so we are fine there.
Tong Shen62d1ca32014-09-03 17:24:56 -07002107 Elf_Ehdr& elf_hdr = all.GetHeader();
Mark Mendellae9fd932014-02-10 16:14:35 -08002108 elf_hdr.e_entry = 0;
2109 elf_hdr.e_phoff = 0;
2110 elf_hdr.e_phnum = 0;
2111 elf_hdr.e_phentsize = 0;
2112 elf_hdr.e_type = ET_EXEC;
2113
Yevgeny Roubane3ea8382014-08-08 16:29:38 +07002114 // Since base_address_ is 0 if we are actually loaded at a known address (i.e. this is boot.oat)
2115 // and the actual address stuff starts at in regular files this is good.
2116 if (!all.FixupDebugSections(reinterpret_cast<intptr_t>(base_address_))) {
Alex Light3470ab42014-06-18 10:35:45 -07002117 LOG(ERROR) << "Failed to load GDB data";
2118 return;
Mark Mendellae9fd932014-02-10 16:14:35 -08002119 }
2120
Alex Light3470ab42014-06-18 10:35:45 -07002121 jit_gdb_entry_ = CreateCodeEntry(all.Begin(), all.Size());
2122 gdb_file_mapping_.reset(all_ptr.release());
Mark Mendellae9fd932014-02-10 16:14:35 -08002123}
2124
Tong Shen62d1ca32014-09-03 17:24:56 -07002125template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2126 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2127 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2128bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2129 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2130 ::Strip(std::string* error_msg) {
2131 // ELF files produced by MCLinker look roughly like this
2132 //
2133 // +------------+
2134 // | Elf_Ehdr | contains number of Elf_Shdr and offset to first
2135 // +------------+
2136 // | Elf_Phdr | program headers
2137 // | Elf_Phdr |
2138 // | ... |
2139 // | Elf_Phdr |
2140 // +------------+
2141 // | section | mixture of needed and unneeded sections
2142 // +------------+
2143 // | section |
2144 // +------------+
2145 // | ... |
2146 // +------------+
2147 // | section |
2148 // +------------+
2149 // | Elf_Shdr | section headers
2150 // | Elf_Shdr |
2151 // | ... | contains offset to section start
2152 // | Elf_Shdr |
2153 // +------------+
2154 //
2155 // To strip:
2156 // - leave the Elf_Ehdr and Elf_Phdr values in place.
2157 // - walk the sections making a new set of Elf_Shdr section headers for what we want to keep
2158 // - move the sections are keeping up to fill in gaps of sections we want to strip
2159 // - write new Elf_Shdr section headers to end of file, updating Elf_Ehdr
2160 // - truncate rest of file
2161 //
2162
2163 std::vector<Elf_Shdr> section_headers;
2164 std::vector<Elf_Word> section_headers_original_indexes;
2165 section_headers.reserve(GetSectionHeaderNum());
2166
2167
2168 Elf_Shdr* string_section = GetSectionNameStringSection();
2169 CHECK(string_section != nullptr);
2170 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
2171 Elf_Shdr* sh = GetSectionHeader(i);
2172 CHECK(sh != nullptr);
2173 const char* name = GetString(*string_section, sh->sh_name);
2174 if (name == nullptr) {
2175 CHECK_EQ(0U, i);
2176 section_headers.push_back(*sh);
2177 section_headers_original_indexes.push_back(0);
2178 continue;
2179 }
2180 if (StartsWith(name, ".debug")
2181 || (strcmp(name, ".strtab") == 0)
2182 || (strcmp(name, ".symtab") == 0)) {
2183 continue;
2184 }
2185 section_headers.push_back(*sh);
2186 section_headers_original_indexes.push_back(i);
2187 }
2188 CHECK_NE(0U, section_headers.size());
2189 CHECK_EQ(section_headers.size(), section_headers_original_indexes.size());
2190
2191 // section 0 is the NULL section, sections start at offset of first section
2192 CHECK(GetSectionHeader(1) != nullptr);
2193 Elf_Off offset = GetSectionHeader(1)->sh_offset;
2194 for (size_t i = 1; i < section_headers.size(); i++) {
2195 Elf_Shdr& new_sh = section_headers[i];
2196 Elf_Shdr* old_sh = GetSectionHeader(section_headers_original_indexes[i]);
2197 CHECK(old_sh != nullptr);
2198 CHECK_EQ(new_sh.sh_name, old_sh->sh_name);
2199 if (old_sh->sh_addralign > 1) {
2200 offset = RoundUp(offset, old_sh->sh_addralign);
2201 }
2202 if (old_sh->sh_offset == offset) {
2203 // already in place
2204 offset += old_sh->sh_size;
2205 continue;
2206 }
2207 // shift section earlier
2208 memmove(Begin() + offset,
2209 Begin() + old_sh->sh_offset,
2210 old_sh->sh_size);
2211 new_sh.sh_offset = offset;
2212 offset += old_sh->sh_size;
2213 }
2214
2215 Elf_Off shoff = offset;
2216 size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf_Shdr);
2217 memcpy(Begin() + offset, &section_headers[0], section_headers_size_in_bytes);
2218 offset += section_headers_size_in_bytes;
2219
2220 GetHeader().e_shnum = section_headers.size();
2221 GetHeader().e_shoff = shoff;
2222 int result = ftruncate(file_->Fd(), offset);
2223 if (result != 0) {
2224 *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s",
2225 file_->GetPath().c_str(), strerror(errno));
2226 return false;
2227 }
2228 return true;
2229}
2230
2231static const bool DEBUG_FIXUP = false;
2232
2233template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2234 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2235 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2236bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2237 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2238 ::Fixup(uintptr_t base_address) {
2239 if (!FixupDynamic(base_address)) {
2240 LOG(WARNING) << "Failed to fixup .dynamic in " << file_->GetPath();
2241 return false;
2242 }
2243 if (!FixupSectionHeaders(base_address)) {
2244 LOG(WARNING) << "Failed to fixup section headers in " << file_->GetPath();
2245 return false;
2246 }
2247 if (!FixupProgramHeaders(base_address)) {
2248 LOG(WARNING) << "Failed to fixup program headers in " << file_->GetPath();
2249 return false;
2250 }
2251 if (!FixupSymbols(base_address, true)) {
2252 LOG(WARNING) << "Failed to fixup .dynsym in " << file_->GetPath();
2253 return false;
2254 }
2255 if (!FixupSymbols(base_address, false)) {
2256 LOG(WARNING) << "Failed to fixup .symtab in " << file_->GetPath();
2257 return false;
2258 }
2259 if (!FixupRelocations(base_address)) {
2260 LOG(WARNING) << "Failed to fixup .rel.dyn in " << file_->GetPath();
2261 return false;
2262 }
2263 if (!FixupDebugSections(base_address)) {
2264 LOG(WARNING) << "Failed to fixup debug sections in " << file_->GetPath();
2265 return false;
2266 }
2267 return true;
2268}
2269
2270template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2271 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2272 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2273bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2274 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2275 ::FixupDynamic(uintptr_t base_address) {
2276 for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
2277 Elf_Dyn& elf_dyn = GetDynamic(i);
2278 Elf_Word d_tag = elf_dyn.d_tag;
2279 if (IsDynamicSectionPointer(d_tag, GetHeader().e_machine)) {
2280 Elf_Addr d_ptr = elf_dyn.d_un.d_ptr;
2281 if (DEBUG_FIXUP) {
2282 LOG(INFO) << StringPrintf("In %s moving Elf_Dyn[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2283 GetFile().GetPath().c_str(), i,
2284 static_cast<uint64_t>(d_ptr),
2285 static_cast<uint64_t>(d_ptr + base_address));
2286 }
2287 d_ptr += base_address;
2288 elf_dyn.d_un.d_ptr = d_ptr;
2289 }
2290 }
2291 return true;
2292}
2293
2294template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2295 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2296 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2297bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2298 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2299 ::FixupSectionHeaders(uintptr_t base_address) {
2300 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
2301 Elf_Shdr* sh = GetSectionHeader(i);
2302 CHECK(sh != nullptr);
2303 // 0 implies that the section will not exist in the memory of the process
2304 if (sh->sh_addr == 0) {
2305 continue;
2306 }
2307 if (DEBUG_FIXUP) {
2308 LOG(INFO) << StringPrintf("In %s moving Elf_Shdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2309 GetFile().GetPath().c_str(), i,
2310 static_cast<uint64_t>(sh->sh_addr),
2311 static_cast<uint64_t>(sh->sh_addr + base_address));
2312 }
2313 sh->sh_addr += base_address;
2314 }
2315 return true;
2316}
2317
2318template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2319 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2320 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2321bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2322 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2323 ::FixupProgramHeaders(uintptr_t base_address) {
2324 // TODO: ELFObjectFile doesn't have give to Elf_Phdr, so we do that ourselves for now.
2325 for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
2326 Elf_Phdr* ph = GetProgramHeader(i);
2327 CHECK(ph != nullptr);
2328 CHECK_EQ(ph->p_vaddr, ph->p_paddr) << GetFile().GetPath() << " i=" << i;
2329 CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
2330 << GetFile().GetPath() << " i=" << i;
2331 if (DEBUG_FIXUP) {
2332 LOG(INFO) << StringPrintf("In %s moving Elf_Phdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2333 GetFile().GetPath().c_str(), i,
2334 static_cast<uint64_t>(ph->p_vaddr),
2335 static_cast<uint64_t>(ph->p_vaddr + base_address));
2336 }
2337 ph->p_vaddr += base_address;
2338 ph->p_paddr += base_address;
2339 CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
2340 << GetFile().GetPath() << " i=" << i;
2341 }
2342 return true;
2343}
2344
2345template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2346 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2347 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2348bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2349 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2350 ::FixupSymbols(uintptr_t base_address, bool dynamic) {
2351 Elf_Word section_type = dynamic ? SHT_DYNSYM : SHT_SYMTAB;
2352 // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
2353 Elf_Shdr* symbol_section = FindSectionByType(section_type);
2354 if (symbol_section == nullptr) {
2355 // file is missing optional .symtab
2356 CHECK(!dynamic) << GetFile().GetPath();
2357 return true;
2358 }
2359 for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
2360 Elf_Sym* symbol = GetSymbol(section_type, i);
2361 CHECK(symbol != nullptr);
2362 if (symbol->st_value != 0) {
2363 if (DEBUG_FIXUP) {
2364 LOG(INFO) << StringPrintf("In %s moving Elf_Sym[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2365 GetFile().GetPath().c_str(), i,
2366 static_cast<uint64_t>(symbol->st_value),
2367 static_cast<uint64_t>(symbol->st_value + base_address));
2368 }
2369 symbol->st_value += base_address;
2370 }
2371 }
2372 return true;
2373}
2374
2375template <typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr, typename Elf_Word,
2376 typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, typename Elf_Rel,
2377 typename Elf_Rela, typename Elf_Dyn, typename Elf_Off>
2378bool ElfFileImpl<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Word,
2379 Elf_Sword, Elf_Addr, Elf_Sym, Elf_Rel, Elf_Rela, Elf_Dyn, Elf_Off>
2380 ::FixupRelocations(uintptr_t base_address) {
2381 for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
2382 Elf_Shdr* sh = GetSectionHeader(i);
2383 CHECK(sh != nullptr);
2384 if (sh->sh_type == SHT_REL) {
2385 for (uint32_t i = 0; i < GetRelNum(*sh); i++) {
2386 Elf_Rel& rel = GetRel(*sh, i);
2387 if (DEBUG_FIXUP) {
2388 LOG(INFO) << StringPrintf("In %s moving Elf_Rel[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2389 GetFile().GetPath().c_str(), i,
2390 static_cast<uint64_t>(rel.r_offset),
2391 static_cast<uint64_t>(rel.r_offset + base_address));
2392 }
2393 rel.r_offset += base_address;
2394 }
2395 } else if (sh->sh_type == SHT_RELA) {
2396 for (uint32_t i = 0; i < GetRelaNum(*sh); i++) {
2397 Elf_Rela& rela = GetRela(*sh, i);
2398 if (DEBUG_FIXUP) {
2399 LOG(INFO) << StringPrintf("In %s moving Elf_Rela[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
2400 GetFile().GetPath().c_str(), i,
2401 static_cast<uint64_t>(rela.r_offset),
2402 static_cast<uint64_t>(rela.r_offset + base_address));
2403 }
2404 rela.r_offset += base_address;
2405 }
2406 }
2407 }
2408 return true;
2409}
2410
2411// Explicit instantiations
2412template class ElfFileImpl<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Word,
2413 Elf32_Sword, Elf32_Addr, Elf32_Sym, Elf32_Rel, Elf32_Rela, Elf32_Dyn, Elf32_Off>;
2414template class ElfFileImpl<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Word,
2415 Elf64_Sword, Elf64_Addr, Elf64_Sym, Elf64_Rel, Elf64_Rela, Elf64_Dyn, Elf64_Off>;
2416
Ian Rogersd4c4d952014-10-16 20:31:53 -07002417ElfFile::ElfFile(ElfFileImpl32* elf32) : elf32_(elf32), elf64_(nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002418}
2419
Ian Rogersd4c4d952014-10-16 20:31:53 -07002420ElfFile::ElfFile(ElfFileImpl64* elf64) : elf32_(nullptr), elf64_(elf64) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002421}
2422
2423ElfFile::~ElfFile() {
Ian Rogersd4c4d952014-10-16 20:31:53 -07002424 // Should never have 32 and 64-bit impls.
2425 CHECK_NE(elf32_.get() == nullptr, elf64_.get() == nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07002426}
2427
2428ElfFile* ElfFile::Open(File* file, bool writable, bool program_header_only, std::string* error_msg) {
2429 if (file->GetLength() < EI_NIDENT) {
2430 *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
2431 file->GetPath().c_str());
2432 return nullptr;
2433 }
2434 std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT, PROT_READ, MAP_PRIVATE, file->Fd(), 0,
2435 file->GetPath().c_str(), error_msg));
2436 if (map == nullptr && map->Size() != EI_NIDENT) {
2437 return nullptr;
2438 }
Ian Rogers13735952014-10-08 12:43:28 -07002439 uint8_t* header = map->Begin();
Tong Shen62d1ca32014-09-03 17:24:56 -07002440 if (header[EI_CLASS] == ELFCLASS64) {
2441 ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, writable, program_header_only, error_msg);
2442 if (elf_file_impl == nullptr)
2443 return nullptr;
2444 return new ElfFile(elf_file_impl);
2445 } else if (header[EI_CLASS] == ELFCLASS32) {
2446 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, writable, program_header_only, error_msg);
Ian Rogersd4c4d952014-10-16 20:31:53 -07002447 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002448 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002449 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002450 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);
Ian Rogersd4c4d952014-10-16 20:31:53 -07002474 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002475 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002476 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002477 return new ElfFile(elf_file_impl);
2478 } else if (header[EI_CLASS] == ELFCLASS32) {
2479 ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, mmap_prot, mmap_flags, error_msg);
Ian Rogersd4c4d952014-10-16 20:31:53 -07002480 if (elf_file_impl == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002481 return nullptr;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002482 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002483 return new ElfFile(elf_file_impl);
2484 } else {
2485 *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
2486 ELFCLASS32, ELFCLASS64,
2487 file->GetPath().c_str(),
2488 header[EI_CLASS]);
2489 return nullptr;
2490 }
2491}
2492
2493#define DELEGATE_TO_IMPL(func, ...) \
Ian Rogersd4c4d952014-10-16 20:31:53 -07002494 if (elf64_.get() != nullptr) { \
2495 return elf64_->func(__VA_ARGS__); \
Tong Shen62d1ca32014-09-03 17:24:56 -07002496 } else { \
Ian Rogersd4c4d952014-10-16 20:31:53 -07002497 DCHECK(elf32_.get() != nullptr); \
2498 return elf32_->func(__VA_ARGS__); \
Tong Shen62d1ca32014-09-03 17:24:56 -07002499 }
2500
2501bool ElfFile::Load(bool executable, std::string* error_msg) {
2502 DELEGATE_TO_IMPL(Load, executable, error_msg);
2503}
2504
Ian Rogers13735952014-10-08 12:43:28 -07002505const uint8_t* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
Tong Shen62d1ca32014-09-03 17:24:56 -07002506 DELEGATE_TO_IMPL(FindDynamicSymbolAddress, symbol_name);
2507}
2508
2509size_t ElfFile::Size() const {
2510 DELEGATE_TO_IMPL(Size);
2511}
2512
Ian Rogers13735952014-10-08 12:43:28 -07002513uint8_t* ElfFile::Begin() const {
Tong Shen62d1ca32014-09-03 17:24:56 -07002514 DELEGATE_TO_IMPL(Begin);
2515}
2516
Ian Rogers13735952014-10-08 12:43:28 -07002517uint8_t* ElfFile::End() const {
Tong Shen62d1ca32014-09-03 17:24:56 -07002518 DELEGATE_TO_IMPL(End);
2519}
2520
2521const File& ElfFile::GetFile() const {
2522 DELEGATE_TO_IMPL(GetFile);
2523}
2524
2525bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, uint64_t* size) {
Ian Rogersd4c4d952014-10-16 20:31:53 -07002526 if (elf32_.get() == nullptr) {
2527 CHECK(elf64_.get() != nullptr);
Tong Shen62d1ca32014-09-03 17:24:56 -07002528
Ian Rogersd4c4d952014-10-16 20:31:53 -07002529 Elf64_Shdr *shdr = elf64_->FindSectionByName(section_name);
2530 if (shdr == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002531 return false;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002532 }
2533 if (offset != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002534 *offset = shdr->sh_offset;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002535 }
2536 if (size != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002537 *size = shdr->sh_size;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002538 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002539 return true;
2540 } else {
Ian Rogersd4c4d952014-10-16 20:31:53 -07002541 Elf32_Shdr *shdr = elf32_->FindSectionByName(section_name);
2542 if (shdr == nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002543 return false;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002544 }
2545 if (offset != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002546 *offset = shdr->sh_offset;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002547 }
2548 if (size != nullptr) {
Tong Shen62d1ca32014-09-03 17:24:56 -07002549 *size = shdr->sh_size;
Ian Rogersd4c4d952014-10-16 20:31:53 -07002550 }
Tong Shen62d1ca32014-09-03 17:24:56 -07002551 return true;
2552 }
2553}
2554
2555uint64_t ElfFile::FindSymbolAddress(unsigned section_type,
2556 const std::string& symbol_name,
2557 bool build_map) {
2558 DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map);
2559}
2560
2561size_t ElfFile::GetLoadedSize() const {
2562 DELEGATE_TO_IMPL(GetLoadedSize);
2563}
2564
2565bool ElfFile::Strip(File* file, std::string* error_msg) {
2566 std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, error_msg));
2567 if (elf_file.get() == nullptr) {
2568 return false;
2569 }
2570
Ian Rogersd4c4d952014-10-16 20:31:53 -07002571 if (elf_file->elf64_.get() != nullptr)
2572 return elf_file->elf64_->Strip(error_msg);
Tong Shen62d1ca32014-09-03 17:24:56 -07002573 else
Ian Rogersd4c4d952014-10-16 20:31:53 -07002574 return elf_file->elf32_->Strip(error_msg);
Tong Shen62d1ca32014-09-03 17:24:56 -07002575}
2576
2577bool ElfFile::Fixup(uintptr_t base_address) {
2578 DELEGATE_TO_IMPL(Fixup, base_address);
2579}
2580
Brian Carlstrom700c8d32012-11-05 10:42:02 -08002581} // namespace art