1/*
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
19#include <inttypes.h>
20#include <sys/mman.h>  // For the PROT_* and MAP_* constants.
21#include <sys/types.h>
22#include <unistd.h>
23
24#include "android-base/stringprintf.h"
25#include "android-base/strings.h"
26
27#include "arch/instruction_set.h"
28#include "base/logging.h"
29#include "base/stl_util.h"
30#include "base/unix_file/fd_file.h"
31#include "elf_file_impl.h"
32#include "elf_utils.h"
33#include "leb128.h"
34#include "utils.h"
35
36namespace art {
37
38using android::base::StringPrintf;
39
40template <typename ElfTypes>
41ElfFileImpl<ElfTypes>::ElfFileImpl(File* file, bool writable,
42                                   bool program_header_only,
43                                   uint8_t* requested_base)
44  : writable_(writable),
45    program_header_only_(program_header_only),
46    header_(nullptr),
47    base_address_(nullptr),
48    program_headers_start_(nullptr),
49    section_headers_start_(nullptr),
50    dynamic_program_header_(nullptr),
51    dynamic_section_start_(nullptr),
52    symtab_section_start_(nullptr),
53    dynsym_section_start_(nullptr),
54    strtab_section_start_(nullptr),
55    dynstr_section_start_(nullptr),
56    hash_section_start_(nullptr),
57    symtab_symbol_table_(nullptr),
58    dynsym_symbol_table_(nullptr),
59    requested_base_(requested_base) {
60  CHECK(file != nullptr);
61}
62
63template <typename ElfTypes>
64ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file,
65                                                   bool writable,
66                                                   bool program_header_only,
67                                                   bool low_4gb,
68                                                   std::string* error_msg,
69                                                   uint8_t* requested_base) {
70  std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(new ElfFileImpl<ElfTypes>
71      (file, writable, program_header_only, requested_base));
72  int prot;
73  int flags;
74  if (writable) {
75    prot = PROT_READ | PROT_WRITE;
76    flags = MAP_SHARED;
77  } else {
78    prot = PROT_READ;
79    flags = MAP_PRIVATE;
80  }
81  if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) {
82    return nullptr;
83  }
84  return elf_file.release();
85}
86
87template <typename ElfTypes>
88ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file,
89                                                   int prot,
90                                                   int flags,
91                                                   bool low_4gb,
92                                                   std::string* error_msg) {
93  std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(new ElfFileImpl<ElfTypes>
94      (file, (prot & PROT_WRITE) == PROT_WRITE, /*program_header_only*/false,
95      /*requested_base*/nullptr));
96  if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) {
97    return nullptr;
98  }
99  return elf_file.release();
100}
101
102template <typename ElfTypes>
103bool ElfFileImpl<ElfTypes>::Setup(File* file,
104                                  int prot,
105                                  int flags,
106                                  bool low_4gb,
107                                  std::string* error_msg) {
108  int64_t temp_file_length = file->GetLength();
109  if (temp_file_length < 0) {
110    errno = -temp_file_length;
111    *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
112                              file->GetPath().c_str(), file->Fd(), strerror(errno));
113    return false;
114  }
115  size_t file_length = static_cast<size_t>(temp_file_length);
116  if (file_length < sizeof(Elf_Ehdr)) {
117    *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF header of "
118                              "%zd bytes: '%s'", file_length, sizeof(Elf_Ehdr),
119                              file->GetPath().c_str());
120    return false;
121  }
122
123  if (program_header_only_) {
124    // first just map ELF header to get program header size information
125    size_t elf_header_size = sizeof(Elf_Ehdr);
126    if (!SetMap(file,
127                MemMap::MapFile(elf_header_size,
128                                prot,
129                                flags,
130                                file->Fd(),
131                                0,
132                                low_4gb,
133                                file->GetPath().c_str(),
134                                error_msg),
135                error_msg)) {
136      return false;
137    }
138    // then remap to cover program header
139    size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum);
140    if (file_length < program_header_size) {
141      *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program "
142                                "header of %zd bytes: '%s'", file_length,
143                                sizeof(Elf_Ehdr), file->GetPath().c_str());
144      return false;
145    }
146    if (!SetMap(file,
147                MemMap::MapFile(program_header_size,
148                                prot,
149                                flags,
150                                file->Fd(),
151                                0,
152                                low_4gb,
153                                file->GetPath().c_str(),
154                                error_msg),
155                error_msg)) {
156      *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str());
157      return false;
158    }
159  } else {
160    // otherwise map entire file
161    if (!SetMap(file,
162                MemMap::MapFile(file->GetLength(),
163                                prot,
164                                flags,
165                                file->Fd(),
166                                0,
167                                low_4gb,
168                                file->GetPath().c_str(),
169                                error_msg),
170                error_msg)) {
171      *error_msg = StringPrintf("Failed to map ELF file: %s", error_msg->c_str());
172      return false;
173    }
174  }
175
176  if (program_header_only_) {
177    program_headers_start_ = Begin() + GetHeader().e_phoff;
178  } else {
179    if (!CheckAndSet(GetHeader().e_phoff, "program headers", &program_headers_start_, error_msg)) {
180      return false;
181    }
182
183    // Setup section headers.
184    if (!CheckAndSet(GetHeader().e_shoff, "section headers", &section_headers_start_, error_msg)) {
185      return false;
186    }
187
188    // Find shstrtab.
189    Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection();
190    if (shstrtab_section_header == nullptr) {
191      *error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'",
192                                file->GetPath().c_str());
193      return false;
194    }
195
196    // Find .dynamic section info from program header
197    dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC);
198    if (dynamic_program_header_ == nullptr) {
199      *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
200                                file->GetPath().c_str());
201      return false;
202    }
203
204    if (!CheckAndSet(GetDynamicProgramHeader().p_offset, "dynamic section",
205                     reinterpret_cast<uint8_t**>(&dynamic_section_start_), error_msg)) {
206      return false;
207    }
208
209    // Find other sections from section headers
210    for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
211      Elf_Shdr* section_header = GetSectionHeader(i);
212      if (section_header == nullptr) {
213        *error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'",
214                                  i, file->GetPath().c_str());
215        return false;
216      }
217      switch (section_header->sh_type) {
218        case SHT_SYMTAB: {
219          if (!CheckAndSet(section_header->sh_offset, "symtab",
220                           reinterpret_cast<uint8_t**>(&symtab_section_start_), error_msg)) {
221            return false;
222          }
223          break;
224        }
225        case SHT_DYNSYM: {
226          if (!CheckAndSet(section_header->sh_offset, "dynsym",
227                           reinterpret_cast<uint8_t**>(&dynsym_section_start_), error_msg)) {
228            return false;
229          }
230          break;
231        }
232        case SHT_STRTAB: {
233          // TODO: base these off of sh_link from .symtab and .dynsym above
234          if ((section_header->sh_flags & SHF_ALLOC) != 0) {
235            // Check that this is named ".dynstr" and ignore otherwise.
236            const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
237            if (strncmp(".dynstr", header_name, 8) == 0) {
238              if (!CheckAndSet(section_header->sh_offset, "dynstr",
239                               reinterpret_cast<uint8_t**>(&dynstr_section_start_), error_msg)) {
240                return false;
241              }
242            }
243          } else {
244            // Check that this is named ".strtab" and ignore otherwise.
245            const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
246            if (strncmp(".strtab", header_name, 8) == 0) {
247              if (!CheckAndSet(section_header->sh_offset, "strtab",
248                               reinterpret_cast<uint8_t**>(&strtab_section_start_), error_msg)) {
249                return false;
250              }
251            }
252          }
253          break;
254        }
255        case SHT_DYNAMIC: {
256          if (reinterpret_cast<uint8_t*>(dynamic_section_start_) !=
257              Begin() + section_header->sh_offset) {
258            LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in "
259                         << file->GetPath() << ": " << std::hex
260                         << reinterpret_cast<void*>(dynamic_section_start_)
261                         << " != " << reinterpret_cast<void*>(Begin() + section_header->sh_offset);
262            return false;
263          }
264          break;
265        }
266        case SHT_HASH: {
267          if (!CheckAndSet(section_header->sh_offset, "hash section",
268                           reinterpret_cast<uint8_t**>(&hash_section_start_), error_msg)) {
269            return false;
270          }
271          break;
272        }
273      }
274    }
275
276    // Check for the existence of some sections.
277    if (!CheckSectionsExist(file, error_msg)) {
278      return false;
279    }
280  }
281
282  return true;
283}
284
285template <typename ElfTypes>
286ElfFileImpl<ElfTypes>::~ElfFileImpl() {
287  STLDeleteElements(&segments_);
288  delete symtab_symbol_table_;
289  delete dynsym_symbol_table_;
290}
291
292template <typename ElfTypes>
293bool ElfFileImpl<ElfTypes>::CheckAndSet(Elf32_Off offset, const char* label,
294                                        uint8_t** target, std::string* error_msg) {
295  if (Begin() + offset >= End()) {
296    *error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label,
297                              file_path_.c_str());
298    return false;
299  }
300  *target = Begin() + offset;
301  return true;
302}
303
304template <typename ElfTypes>
305bool ElfFileImpl<ElfTypes>::CheckSectionsLinked(const uint8_t* source,
306                                                const uint8_t* target) const {
307  // Only works in whole-program mode, as we need to iterate over the sections.
308  // Note that we normally can't search by type, as duplicates are allowed for most section types.
309  if (program_header_only_) {
310    return true;
311  }
312
313  Elf_Shdr* source_section = nullptr;
314  Elf_Word target_index = 0;
315  bool target_found = false;
316  for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
317    Elf_Shdr* section_header = GetSectionHeader(i);
318
319    if (Begin() + section_header->sh_offset == source) {
320      // Found the source.
321      source_section = section_header;
322      if (target_index) {
323        break;
324      }
325    } else if (Begin() + section_header->sh_offset == target) {
326      target_index = i;
327      target_found = true;
328      if (source_section != nullptr) {
329        break;
330      }
331    }
332  }
333
334  return target_found && source_section != nullptr && source_section->sh_link == target_index;
335}
336
337template <typename ElfTypes>
338  bool ElfFileImpl<ElfTypes>::CheckSectionsExist(File* file, std::string* error_msg) const {
339  if (!program_header_only_) {
340    // If in full mode, need section headers.
341    if (section_headers_start_ == nullptr) {
342      *error_msg = StringPrintf("No section headers in ELF file: '%s'", file->GetPath().c_str());
343      return false;
344    }
345  }
346
347  // This is redundant, but defensive.
348  if (dynamic_program_header_ == nullptr) {
349    *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
350                              file->GetPath().c_str());
351    return false;
352  }
353
354  // Need a dynamic section. This is redundant, but defensive.
355  if (dynamic_section_start_ == nullptr) {
356    *error_msg = StringPrintf("Failed to find dynamic section in ELF file: '%s'",
357                              file->GetPath().c_str());
358    return false;
359  }
360
361  // Symtab validation. These is not really a hard failure, as we are currently not using the
362  // symtab internally, but it's nice to be defensive.
363  if (symtab_section_start_ != nullptr) {
364    // When there's a symtab, there should be a strtab.
365    if (strtab_section_start_ == nullptr) {
366      *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file->GetPath().c_str());
367      return false;
368    }
369
370    // The symtab should link to the strtab.
371    if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(symtab_section_start_),
372                             reinterpret_cast<const uint8_t*>(strtab_section_start_))) {
373      *error_msg = StringPrintf("Symtab is not linked to the strtab in ELF file: '%s'",
374                                file->GetPath().c_str());
375      return false;
376    }
377  }
378
379  // We always need a dynstr & dynsym.
380  if (dynstr_section_start_ == nullptr) {
381    *error_msg = StringPrintf("No dynstr in ELF file: '%s'", file->GetPath().c_str());
382    return false;
383  }
384  if (dynsym_section_start_ == nullptr) {
385    *error_msg = StringPrintf("No dynsym in ELF file: '%s'", file->GetPath().c_str());
386    return false;
387  }
388
389  // Need a hash section for dynamic symbol lookup.
390  if (hash_section_start_ == nullptr) {
391    *error_msg = StringPrintf("Failed to find hash section in ELF file: '%s'",
392                              file->GetPath().c_str());
393    return false;
394  }
395
396  // And the hash section should be linking to the dynsym.
397  if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(hash_section_start_),
398                           reinterpret_cast<const uint8_t*>(dynsym_section_start_))) {
399    *error_msg = StringPrintf("Hash section is not linked to the dynstr in ELF file: '%s'",
400                              file->GetPath().c_str());
401    return false;
402  }
403
404  // We'd also like to confirm a shstrtab in program_header_only_ mode (else Open() does this for
405  // us). This is usually the last in an oat file, and a good indicator of whether writing was
406  // successful (or the process crashed and left garbage).
407  if (program_header_only_) {
408    // It might not be mapped, but we can compare against the file size.
409    int64_t offset = static_cast<int64_t>(GetHeader().e_shoff +
410                                          (GetHeader().e_shstrndx * GetHeader().e_shentsize));
411    if (offset >= file->GetLength()) {
412      *error_msg = StringPrintf("Shstrtab is not in the mapped ELF file: '%s'",
413                                file->GetPath().c_str());
414      return false;
415    }
416  }
417
418  return true;
419}
420
421template <typename ElfTypes>
422bool ElfFileImpl<ElfTypes>::SetMap(File* file, MemMap* map, std::string* error_msg) {
423  if (map == nullptr) {
424    // MemMap::Open should have already set an error.
425    DCHECK(!error_msg->empty());
426    return false;
427  }
428  map_.reset(map);
429  CHECK(map_.get() != nullptr) << file->GetPath();
430  CHECK(map_->Begin() != nullptr) << file->GetPath();
431
432  header_ = reinterpret_cast<Elf_Ehdr*>(map_->Begin());
433  if ((ELFMAG0 != header_->e_ident[EI_MAG0])
434      || (ELFMAG1 != header_->e_ident[EI_MAG1])
435      || (ELFMAG2 != header_->e_ident[EI_MAG2])
436      || (ELFMAG3 != header_->e_ident[EI_MAG3])) {
437    *error_msg = StringPrintf("Failed to find ELF magic value %d %d %d %d in %s, found %d %d %d %d",
438                              ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
439                              file->GetPath().c_str(),
440                              header_->e_ident[EI_MAG0],
441                              header_->e_ident[EI_MAG1],
442                              header_->e_ident[EI_MAG2],
443                              header_->e_ident[EI_MAG3]);
444    return false;
445  }
446  uint8_t elf_class = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) ? ELFCLASS64 : ELFCLASS32;
447  if (elf_class != header_->e_ident[EI_CLASS]) {
448    *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d in %s, found %d",
449                              elf_class,
450                              file->GetPath().c_str(),
451                              header_->e_ident[EI_CLASS]);
452    return false;
453  }
454  if (ELFDATA2LSB != header_->e_ident[EI_DATA]) {
455    *error_msg = StringPrintf("Failed to find expected EI_DATA value %d in %s, found %d",
456                              ELFDATA2LSB,
457                              file->GetPath().c_str(),
458                              header_->e_ident[EI_CLASS]);
459    return false;
460  }
461  if (EV_CURRENT != header_->e_ident[EI_VERSION]) {
462    *error_msg = StringPrintf("Failed to find expected EI_VERSION value %d in %s, found %d",
463                              EV_CURRENT,
464                              file->GetPath().c_str(),
465                              header_->e_ident[EI_CLASS]);
466    return false;
467  }
468  if (ET_DYN != header_->e_type) {
469    *error_msg = StringPrintf("Failed to find expected e_type value %d in %s, found %d",
470                              ET_DYN,
471                              file->GetPath().c_str(),
472                              header_->e_type);
473    return false;
474  }
475  if (EV_CURRENT != header_->e_version) {
476    *error_msg = StringPrintf("Failed to find expected e_version value %d in %s, found %d",
477                              EV_CURRENT,
478                              file->GetPath().c_str(),
479                              header_->e_version);
480    return false;
481  }
482  if (0 != header_->e_entry) {
483    *error_msg = StringPrintf("Failed to find expected e_entry value %d in %s, found %d",
484                              0,
485                              file->GetPath().c_str(),
486                              static_cast<int32_t>(header_->e_entry));
487    return false;
488  }
489  if (0 == header_->e_phoff) {
490    *error_msg = StringPrintf("Failed to find non-zero e_phoff value in %s",
491                              file->GetPath().c_str());
492    return false;
493  }
494  if (0 == header_->e_shoff) {
495    *error_msg = StringPrintf("Failed to find non-zero e_shoff value in %s",
496                              file->GetPath().c_str());
497    return false;
498  }
499  if (0 == header_->e_ehsize) {
500    *error_msg = StringPrintf("Failed to find non-zero e_ehsize value in %s",
501                              file->GetPath().c_str());
502    return false;
503  }
504  if (0 == header_->e_phentsize) {
505    *error_msg = StringPrintf("Failed to find non-zero e_phentsize value in %s",
506                              file->GetPath().c_str());
507    return false;
508  }
509  if (0 == header_->e_phnum) {
510    *error_msg = StringPrintf("Failed to find non-zero e_phnum value in %s",
511                              file->GetPath().c_str());
512    return false;
513  }
514  if (0 == header_->e_shentsize) {
515    *error_msg = StringPrintf("Failed to find non-zero e_shentsize value in %s",
516                              file->GetPath().c_str());
517    return false;
518  }
519  if (0 == header_->e_shnum) {
520    *error_msg = StringPrintf("Failed to find non-zero e_shnum value in %s",
521                              file->GetPath().c_str());
522    return false;
523  }
524  if (0 == header_->e_shstrndx) {
525    *error_msg = StringPrintf("Failed to find non-zero e_shstrndx value in %s",
526                              file->GetPath().c_str());
527    return false;
528  }
529  if (header_->e_shstrndx >= header_->e_shnum) {
530    *error_msg = StringPrintf("Failed to find e_shnum value %d less than %d in %s",
531                              header_->e_shstrndx,
532                              header_->e_shnum,
533                              file->GetPath().c_str());
534    return false;
535  }
536
537  if (!program_header_only_) {
538    if (header_->e_phoff >= Size()) {
539      *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s",
540                                static_cast<uint64_t>(header_->e_phoff),
541                                Size(),
542                                file->GetPath().c_str());
543      return false;
544    }
545    if (header_->e_shoff >= Size()) {
546      *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s",
547                                static_cast<uint64_t>(header_->e_shoff),
548                                Size(),
549                                file->GetPath().c_str());
550      return false;
551    }
552  }
553  return true;
554}
555
556template <typename ElfTypes>
557typename ElfTypes::Ehdr& ElfFileImpl<ElfTypes>::GetHeader() const {
558  CHECK(header_ != nullptr);  // Header has been checked in SetMap. This is a sanity check.
559  return *header_;
560}
561
562template <typename ElfTypes>
563uint8_t* ElfFileImpl<ElfTypes>::GetProgramHeadersStart() const {
564  CHECK(program_headers_start_ != nullptr);  // Header has been set in Setup. This is a sanity
565                                             // check.
566  return program_headers_start_;
567}
568
569template <typename ElfTypes>
570uint8_t* ElfFileImpl<ElfTypes>::GetSectionHeadersStart() const {
571  CHECK(!program_header_only_);              // Only used in "full" mode.
572  CHECK(section_headers_start_ != nullptr);  // Is checked in CheckSectionsExist. Sanity check.
573  return section_headers_start_;
574}
575
576template <typename ElfTypes>
577typename ElfTypes::Phdr& ElfFileImpl<ElfTypes>::GetDynamicProgramHeader() const {
578  CHECK(dynamic_program_header_ != nullptr);  // Is checked in CheckSectionsExist. Sanity check.
579  return *dynamic_program_header_;
580}
581
582template <typename ElfTypes>
583typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::GetDynamicSectionStart() const {
584  CHECK(dynamic_section_start_ != nullptr);  // Is checked in CheckSectionsExist. Sanity check.
585  return dynamic_section_start_;
586}
587
588template <typename ElfTypes>
589typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbolSectionStart(
590    Elf_Word section_type) const {
591  CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
592  switch (section_type) {
593    case SHT_SYMTAB: {
594      return symtab_section_start_;
595      break;
596    }
597    case SHT_DYNSYM: {
598      return dynsym_section_start_;
599      break;
600    }
601    default: {
602      LOG(FATAL) << section_type;
603      return nullptr;
604    }
605  }
606}
607
608template <typename ElfTypes>
609const char* ElfFileImpl<ElfTypes>::GetStringSectionStart(
610    Elf_Word section_type) const {
611  CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
612  switch (section_type) {
613    case SHT_SYMTAB: {
614      return strtab_section_start_;
615    }
616    case SHT_DYNSYM: {
617      return dynstr_section_start_;
618    }
619    default: {
620      LOG(FATAL) << section_type;
621      return nullptr;
622    }
623  }
624}
625
626template <typename ElfTypes>
627const char* ElfFileImpl<ElfTypes>::GetString(Elf_Word section_type,
628                                             Elf_Word i) const {
629  CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
630  if (i == 0) {
631    return nullptr;
632  }
633  const char* string_section_start = GetStringSectionStart(section_type);
634  if (string_section_start == nullptr) {
635    return nullptr;
636  }
637  return string_section_start + i;
638}
639
640// WARNING: The following methods do not check for an error condition (non-existent hash section).
641//          It is the caller's job to do this.
642
643template <typename ElfTypes>
644typename ElfTypes::Word* ElfFileImpl<ElfTypes>::GetHashSectionStart() const {
645  return hash_section_start_;
646}
647
648template <typename ElfTypes>
649typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashBucketNum() const {
650  return GetHashSectionStart()[0];
651}
652
653template <typename ElfTypes>
654typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashChainNum() const {
655  return GetHashSectionStart()[1];
656}
657
658template <typename ElfTypes>
659typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashBucket(size_t i, bool* ok) const {
660  if (i >= GetHashBucketNum()) {
661    *ok = false;
662    return 0;
663  }
664  *ok = true;
665  // 0 is nbucket, 1 is nchain
666  return GetHashSectionStart()[2 + i];
667}
668
669template <typename ElfTypes>
670typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashChain(size_t i, bool* ok) const {
671  if (i >= GetHashChainNum()) {
672    *ok = false;
673    return 0;
674  }
675  *ok = true;
676  // 0 is nbucket, 1 is nchain, & chains are after buckets
677  return GetHashSectionStart()[2 + GetHashBucketNum() + i];
678}
679
680template <typename ElfTypes>
681typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetProgramHeaderNum() const {
682  return GetHeader().e_phnum;
683}
684
685template <typename ElfTypes>
686typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::GetProgramHeader(Elf_Word i) const {
687  CHECK_LT(i, GetProgramHeaderNum()) << file_path_;  // Sanity check for caller.
688  uint8_t* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize);
689  if (program_header >= End()) {
690    return nullptr;  // Failure condition.
691  }
692  return reinterpret_cast<Elf_Phdr*>(program_header);
693}
694
695template <typename ElfTypes>
696typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::FindProgamHeaderByType(Elf_Word type) const {
697  for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
698    Elf_Phdr* program_header = GetProgramHeader(i);
699    if (program_header->p_type == type) {
700      return program_header;
701    }
702  }
703  return nullptr;
704}
705
706template <typename ElfTypes>
707typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSectionHeaderNum() const {
708  return GetHeader().e_shnum;
709}
710
711template <typename ElfTypes>
712typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionHeader(Elf_Word i) const {
713  // Can only access arbitrary sections when we have the whole file, not just program header.
714  // Even if we Load(), it doesn't bring in all the sections.
715  CHECK(!program_header_only_) << file_path_;
716  if (i >= GetSectionHeaderNum()) {
717    return nullptr;  // Failure condition.
718  }
719  uint8_t* section_header = GetSectionHeadersStart() + (i * GetHeader().e_shentsize);
720  if (section_header >= End()) {
721    return nullptr;  // Failure condition.
722  }
723  return reinterpret_cast<Elf_Shdr*>(section_header);
724}
725
726template <typename ElfTypes>
727typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByType(Elf_Word type) const {
728  // Can only access arbitrary sections when we have the whole file, not just program header.
729  // We could change this to switch on known types if they were detected during loading.
730  CHECK(!program_header_only_) << file_path_;
731  for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
732    Elf_Shdr* section_header = GetSectionHeader(i);
733    if (section_header->sh_type == type) {
734      return section_header;
735    }
736  }
737  return nullptr;
738}
739
740// from bionic
741static unsigned elfhash(const char *_name) {
742  const unsigned char *name = (const unsigned char *) _name;
743  unsigned h = 0, g;
744
745  while (*name) {
746    h = (h << 4) + *name++;
747    g = h & 0xf0000000;
748    h ^= g;
749    h ^= g >> 24;
750  }
751  return h;
752}
753
754template <typename ElfTypes>
755typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionNameStringSection() const {
756  return GetSectionHeader(GetHeader().e_shstrndx);
757}
758
759template <typename ElfTypes>
760const uint8_t* ElfFileImpl<ElfTypes>::FindDynamicSymbolAddress(
761    const std::string& symbol_name) const {
762  // Check that we have a hash section.
763  if (GetHashSectionStart() == nullptr) {
764    return nullptr;  // Failure condition.
765  }
766  const Elf_Sym* sym = FindDynamicSymbol(symbol_name);
767  if (sym != nullptr) {
768    // TODO: we need to change this to calculate base_address_ in ::Open,
769    // otherwise it will be wrongly 0 if ::Load has not yet been called.
770    return base_address_ + sym->st_value;
771  } else {
772    return nullptr;
773  }
774}
775
776// WARNING: Only called from FindDynamicSymbolAddress. Elides check for hash section.
777template <typename ElfTypes>
778const typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindDynamicSymbol(
779    const std::string& symbol_name) const {
780  if (GetHashBucketNum() == 0) {
781    // No dynamic symbols at all.
782    return nullptr;
783  }
784  Elf_Word hash = elfhash(symbol_name.c_str());
785  Elf_Word bucket_index = hash % GetHashBucketNum();
786  bool ok;
787  Elf_Word symbol_and_chain_index = GetHashBucket(bucket_index, &ok);
788  if (!ok) {
789    return nullptr;
790  }
791  while (symbol_and_chain_index != 0 /* STN_UNDEF */) {
792    Elf_Sym* symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
793    if (symbol == nullptr) {
794      return nullptr;  // Failure condition.
795    }
796    const char* name = GetString(SHT_DYNSYM, symbol->st_name);
797    if (symbol_name == name) {
798      return symbol;
799    }
800    symbol_and_chain_index = GetHashChain(symbol_and_chain_index, &ok);
801    if (!ok) {
802      return nullptr;
803    }
804  }
805  return nullptr;
806}
807
808template <typename ElfTypes>
809bool ElfFileImpl<ElfTypes>::IsSymbolSectionType(Elf_Word section_type) {
810  return ((section_type == SHT_SYMTAB) || (section_type == SHT_DYNSYM));
811}
812
813template <typename ElfTypes>
814typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSymbolNum(Elf_Shdr& section_header) const {
815  CHECK(IsSymbolSectionType(section_header.sh_type))
816      << file_path_ << " " << section_header.sh_type;
817  CHECK_NE(0U, section_header.sh_entsize) << file_path_;
818  return section_header.sh_size / section_header.sh_entsize;
819}
820
821template <typename ElfTypes>
822typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbol(Elf_Word section_type, Elf_Word i) const {
823  Elf_Sym* sym_start = GetSymbolSectionStart(section_type);
824  if (sym_start == nullptr) {
825    return nullptr;
826  }
827  return sym_start + i;
828}
829
830template <typename ElfTypes>
831typename ElfFileImpl<ElfTypes>::SymbolTable**
832ElfFileImpl<ElfTypes>::GetSymbolTable(Elf_Word section_type) {
833  CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
834  switch (section_type) {
835    case SHT_SYMTAB: {
836      return &symtab_symbol_table_;
837    }
838    case SHT_DYNSYM: {
839      return &dynsym_symbol_table_;
840    }
841    default: {
842      LOG(FATAL) << section_type;
843      return nullptr;
844    }
845  }
846}
847
848template <typename ElfTypes>
849typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindSymbolByName(
850    Elf_Word section_type, const std::string& symbol_name, bool build_map) {
851  CHECK(!program_header_only_) << file_path_;
852  CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
853
854  SymbolTable** symbol_table = GetSymbolTable(section_type);
855  if (*symbol_table != nullptr || build_map) {
856    if (*symbol_table == nullptr) {
857      DCHECK(build_map);
858      *symbol_table = new SymbolTable;
859      Elf_Shdr* symbol_section = FindSectionByType(section_type);
860      if (symbol_section == nullptr) {
861        return nullptr;  // Failure condition.
862      }
863      Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
864      if (string_section == nullptr) {
865        return nullptr;  // Failure condition.
866      }
867      for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
868        Elf_Sym* symbol = GetSymbol(section_type, i);
869        if (symbol == nullptr) {
870          return nullptr;  // Failure condition.
871        }
872        unsigned char type = (sizeof(Elf_Addr) == sizeof(Elf64_Addr))
873                             ? ELF64_ST_TYPE(symbol->st_info)
874                             : ELF32_ST_TYPE(symbol->st_info);
875        if (type == STT_NOTYPE) {
876          continue;
877        }
878        const char* name = GetString(*string_section, symbol->st_name);
879        if (name == nullptr) {
880          continue;
881        }
882        std::pair<typename SymbolTable::iterator, bool> result =
883            (*symbol_table)->insert(std::make_pair(name, symbol));
884        if (!result.second) {
885          // If a duplicate, make sure it has the same logical value. Seen on x86.
886          if ((symbol->st_value != result.first->second->st_value) ||
887              (symbol->st_size != result.first->second->st_size) ||
888              (symbol->st_info != result.first->second->st_info) ||
889              (symbol->st_other != result.first->second->st_other) ||
890              (symbol->st_shndx != result.first->second->st_shndx)) {
891            return nullptr;  // Failure condition.
892          }
893        }
894      }
895    }
896    CHECK(*symbol_table != nullptr);
897    typename SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
898    if (it == (*symbol_table)->end()) {
899      return nullptr;
900    }
901    return it->second;
902  }
903
904  // Fall back to linear search
905  Elf_Shdr* symbol_section = FindSectionByType(section_type);
906  if (symbol_section == nullptr) {
907    return nullptr;
908  }
909  Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
910  if (string_section == nullptr) {
911    return nullptr;
912  }
913  for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
914    Elf_Sym* symbol = GetSymbol(section_type, i);
915    if (symbol == nullptr) {
916      return nullptr;  // Failure condition.
917    }
918    const char* name = GetString(*string_section, symbol->st_name);
919    if (name == nullptr) {
920      continue;
921    }
922    if (symbol_name == name) {
923      return symbol;
924    }
925  }
926  return nullptr;
927}
928
929template <typename ElfTypes>
930typename ElfTypes::Addr ElfFileImpl<ElfTypes>::FindSymbolAddress(
931    Elf_Word section_type, const std::string& symbol_name, bool build_map) {
932  Elf_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
933  if (symbol == nullptr) {
934    return 0;
935  }
936  return symbol->st_value;
937}
938
939template <typename ElfTypes>
940const char* ElfFileImpl<ElfTypes>::GetString(Elf_Shdr& string_section,
941                                             Elf_Word i) const {
942  CHECK(!program_header_only_) << file_path_;
943  // TODO: remove this static_cast from enum when using -std=gnu++0x
944  if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) {
945    return nullptr;  // Failure condition.
946  }
947  if (i >= string_section.sh_size) {
948    return nullptr;
949  }
950  if (i == 0) {
951    return nullptr;
952  }
953  uint8_t* strings = Begin() + string_section.sh_offset;
954  uint8_t* string = strings + i;
955  if (string >= End()) {
956    return nullptr;
957  }
958  return reinterpret_cast<const char*>(string);
959}
960
961template <typename ElfTypes>
962typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetDynamicNum() const {
963  return GetDynamicProgramHeader().p_filesz / sizeof(Elf_Dyn);
964}
965
966template <typename ElfTypes>
967typename ElfTypes::Dyn& ElfFileImpl<ElfTypes>::GetDynamic(Elf_Word i) const {
968  CHECK_LT(i, GetDynamicNum()) << file_path_;
969  return *(GetDynamicSectionStart() + i);
970}
971
972template <typename ElfTypes>
973typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::FindDynamicByType(Elf_Sword type) const {
974  for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
975    Elf_Dyn* dyn = &GetDynamic(i);
976    if (dyn->d_tag == type) {
977      return dyn;
978    }
979  }
980  return nullptr;
981}
982
983template <typename ElfTypes>
984typename ElfTypes::Word ElfFileImpl<ElfTypes>::FindDynamicValueByType(Elf_Sword type) const {
985  Elf_Dyn* dyn = FindDynamicByType(type);
986  if (dyn == nullptr) {
987    return 0;
988  } else {
989    return dyn->d_un.d_val;
990  }
991}
992
993template <typename ElfTypes>
994typename ElfTypes::Rel* ElfFileImpl<ElfTypes>::GetRelSectionStart(Elf_Shdr& section_header) const {
995  CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
996  return reinterpret_cast<Elf_Rel*>(Begin() + section_header.sh_offset);
997}
998
999template <typename ElfTypes>
1000typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelNum(Elf_Shdr& section_header) const {
1001  CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1002  CHECK_NE(0U, section_header.sh_entsize) << file_path_;
1003  return section_header.sh_size / section_header.sh_entsize;
1004}
1005
1006template <typename ElfTypes>
1007typename ElfTypes::Rel& ElfFileImpl<ElfTypes>::GetRel(Elf_Shdr& section_header, Elf_Word i) const {
1008  CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1009  CHECK_LT(i, GetRelNum(section_header)) << file_path_;
1010  return *(GetRelSectionStart(section_header) + i);
1011}
1012
1013template <typename ElfTypes>
1014typename ElfTypes::Rela* ElfFileImpl<ElfTypes>::GetRelaSectionStart(Elf_Shdr& section_header) const {
1015  CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1016  return reinterpret_cast<Elf_Rela*>(Begin() + section_header.sh_offset);
1017}
1018
1019template <typename ElfTypes>
1020typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelaNum(Elf_Shdr& section_header) const {
1021  CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1022  return section_header.sh_size / section_header.sh_entsize;
1023}
1024
1025template <typename ElfTypes>
1026typename ElfTypes::Rela& ElfFileImpl<ElfTypes>::GetRela(Elf_Shdr& section_header, Elf_Word i) const {
1027  CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1028  CHECK_LT(i, GetRelaNum(section_header)) << file_path_;
1029  return *(GetRelaSectionStart(section_header) + i);
1030}
1031
1032// Base on bionic phdr_table_get_load_size
1033template <typename ElfTypes>
1034bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg) const {
1035  Elf_Addr min_vaddr = static_cast<Elf_Addr>(-1);
1036  Elf_Addr max_vaddr = 0u;
1037  for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1038    Elf_Phdr* program_header = GetProgramHeader(i);
1039    if (program_header->p_type != PT_LOAD) {
1040      continue;
1041    }
1042    Elf_Addr begin_vaddr = program_header->p_vaddr;
1043    if (begin_vaddr < min_vaddr) {
1044       min_vaddr = begin_vaddr;
1045    }
1046    Elf_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz;
1047    if (UNLIKELY(begin_vaddr > end_vaddr)) {
1048      std::ostringstream oss;
1049      oss << "Program header #" << i << " has overflow in p_vaddr+p_memsz: 0x" << std::hex
1050          << program_header->p_vaddr << "+0x" << program_header->p_memsz << "=0x" << end_vaddr
1051          << " in ELF file \"" << file_path_ << "\"";
1052      *error_msg = oss.str();
1053      *size = static_cast<size_t>(-1);
1054      return false;
1055    }
1056    if (end_vaddr > max_vaddr) {
1057      max_vaddr = end_vaddr;
1058    }
1059  }
1060  min_vaddr = RoundDown(min_vaddr, kPageSize);
1061  max_vaddr = RoundUp(max_vaddr, kPageSize);
1062  CHECK_LT(min_vaddr, max_vaddr) << file_path_;
1063  Elf_Addr loaded_size = max_vaddr - min_vaddr;
1064  // Check that the loaded_size fits in size_t.
1065  if (UNLIKELY(loaded_size > std::numeric_limits<size_t>::max())) {
1066    std::ostringstream oss;
1067    oss << "Loaded size is 0x" << std::hex << loaded_size << " but maximum size_t is 0x"
1068        << std::numeric_limits<size_t>::max() << " for ELF file \"" << file_path_ << "\"";
1069    *error_msg = oss.str();
1070    *size = static_cast<size_t>(-1);
1071    return false;
1072  }
1073  *size = loaded_size;
1074  return true;
1075}
1076
1077template <typename ElfTypes>
1078bool ElfFileImpl<ElfTypes>::Load(File* file,
1079                                 bool executable,
1080                                 bool low_4gb,
1081                                 std::string* error_msg) {
1082  CHECK(program_header_only_) << file->GetPath();
1083
1084  if (executable) {
1085    InstructionSet elf_ISA = GetInstructionSetFromELF(GetHeader().e_machine, GetHeader().e_flags);
1086    if (elf_ISA != kRuntimeISA) {
1087      std::ostringstream oss;
1088      oss << "Expected ISA " << kRuntimeISA << " but found " << elf_ISA;
1089      *error_msg = oss.str();
1090      return false;
1091    }
1092  }
1093
1094  bool reserved = false;
1095  for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1096    Elf_Phdr* program_header = GetProgramHeader(i);
1097    if (program_header == nullptr) {
1098      *error_msg = StringPrintf("No program header for entry %d in ELF file %s.",
1099                                i, file->GetPath().c_str());
1100      return false;
1101    }
1102
1103    // Record .dynamic header information for later use
1104    if (program_header->p_type == PT_DYNAMIC) {
1105      dynamic_program_header_ = program_header;
1106      continue;
1107    }
1108
1109    // Not something to load, move on.
1110    if (program_header->p_type != PT_LOAD) {
1111      continue;
1112    }
1113
1114    // Found something to load.
1115
1116    // Before load the actual segments, reserve a contiguous chunk
1117    // of required size and address for all segments, but with no
1118    // permissions. We'll then carve that up with the proper
1119    // permissions as we load the actual segments. If p_vaddr is
1120    // non-zero, the segments require the specific address specified,
1121    // which either was specified in the file because we already set
1122    // base_address_ after the first zero segment).
1123    int64_t temp_file_length = file->GetLength();
1124    if (temp_file_length < 0) {
1125      errno = -temp_file_length;
1126      *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
1127                                file->GetPath().c_str(), file->Fd(), strerror(errno));
1128      return false;
1129    }
1130    size_t file_length = static_cast<size_t>(temp_file_length);
1131    if (!reserved) {
1132      uint8_t* reserve_base = reinterpret_cast<uint8_t*>(program_header->p_vaddr);
1133      uint8_t* reserve_base_override = reserve_base;
1134      // Override the base (e.g. when compiling with --compile-pic)
1135      if (requested_base_ != nullptr) {
1136        reserve_base_override = requested_base_;
1137      }
1138      std::string reservation_name("ElfFile reservation for ");
1139      reservation_name += file->GetPath();
1140      size_t loaded_size;
1141      if (!GetLoadedSize(&loaded_size, error_msg)) {
1142        DCHECK(!error_msg->empty());
1143        return false;
1144      }
1145      std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
1146                                                           reserve_base_override,
1147                                                           loaded_size,
1148                                                           PROT_NONE,
1149                                                           low_4gb,
1150                                                           false,
1151                                                           error_msg));
1152      if (reserve.get() == nullptr) {
1153        *error_msg = StringPrintf("Failed to allocate %s: %s",
1154                                  reservation_name.c_str(), error_msg->c_str());
1155        return false;
1156      }
1157      reserved = true;
1158
1159      // Base address is the difference of actual mapped location and the p_vaddr
1160      base_address_ = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(reserve->Begin())
1161                       - reinterpret_cast<uintptr_t>(reserve_base));
1162      // By adding the p_vaddr of a section/symbol to base_address_ we will always get the
1163      // dynamic memory address of where that object is actually mapped
1164      //
1165      // TODO: base_address_ needs to be calculated in ::Open, otherwise
1166      // FindDynamicSymbolAddress returns the wrong values until Load is called.
1167      segments_.push_back(reserve.release());
1168    }
1169    // empty segment, nothing to map
1170    if (program_header->p_memsz == 0) {
1171      continue;
1172    }
1173    uint8_t* p_vaddr = base_address_ + program_header->p_vaddr;
1174    int prot = 0;
1175    if (executable && ((program_header->p_flags & PF_X) != 0)) {
1176      prot |= PROT_EXEC;
1177    }
1178    if ((program_header->p_flags & PF_W) != 0) {
1179      prot |= PROT_WRITE;
1180    }
1181    if ((program_header->p_flags & PF_R) != 0) {
1182      prot |= PROT_READ;
1183    }
1184    int flags = 0;
1185    if (writable_) {
1186      prot |= PROT_WRITE;
1187      flags |= MAP_SHARED;
1188    } else {
1189      flags |= MAP_PRIVATE;
1190    }
1191    if (program_header->p_filesz > program_header->p_memsz) {
1192      *error_msg = StringPrintf("Invalid p_filesz > p_memsz (%" PRIu64 " > %" PRIu64 "): %s",
1193                                static_cast<uint64_t>(program_header->p_filesz),
1194                                static_cast<uint64_t>(program_header->p_memsz),
1195                                file->GetPath().c_str());
1196      return false;
1197    }
1198    if (program_header->p_filesz < program_header->p_memsz &&
1199        !IsAligned<kPageSize>(program_header->p_filesz)) {
1200      *error_msg = StringPrintf("Unsupported unaligned p_filesz < p_memsz (%" PRIu64
1201                                " < %" PRIu64 "): %s",
1202                                static_cast<uint64_t>(program_header->p_filesz),
1203                                static_cast<uint64_t>(program_header->p_memsz),
1204                                file->GetPath().c_str());
1205      return false;
1206    }
1207    if (file_length < (program_header->p_offset + program_header->p_filesz)) {
1208      *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment "
1209                                "%d of %" PRIu64 " bytes: '%s'", file_length, i,
1210                                static_cast<uint64_t>(program_header->p_offset + program_header->p_filesz),
1211                                file->GetPath().c_str());
1212      return false;
1213    }
1214    if (program_header->p_filesz != 0u) {
1215      std::unique_ptr<MemMap> segment(
1216          MemMap::MapFileAtAddress(p_vaddr,
1217                                   program_header->p_filesz,
1218                                   prot,
1219                                   flags,
1220                                   file->Fd(),
1221                                   program_header->p_offset,
1222                                   /*low4_gb*/false,
1223                                   /*reuse*/true,  // implies MAP_FIXED
1224                                   file->GetPath().c_str(),
1225                                   error_msg));
1226      if (segment.get() == nullptr) {
1227        *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s",
1228                                  i, file->GetPath().c_str(), error_msg->c_str());
1229        return false;
1230      }
1231      if (segment->Begin() != p_vaddr) {
1232        *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, "
1233                                  "instead mapped to %p",
1234                                  i, file->GetPath().c_str(), p_vaddr, segment->Begin());
1235        return false;
1236      }
1237      segments_.push_back(segment.release());
1238    }
1239    if (program_header->p_filesz < program_header->p_memsz) {
1240      std::string name = StringPrintf("Zero-initialized segment %" PRIu64 " of ELF file %s",
1241                                      static_cast<uint64_t>(i), file->GetPath().c_str());
1242      std::unique_ptr<MemMap> segment(
1243          MemMap::MapAnonymous(name.c_str(),
1244                               p_vaddr + program_header->p_filesz,
1245                               program_header->p_memsz - program_header->p_filesz,
1246                               prot, false, true /* reuse */, error_msg));
1247      if (segment == nullptr) {
1248        *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s: %s",
1249                                  i, file->GetPath().c_str(), error_msg->c_str());
1250        return false;
1251      }
1252      if (segment->Begin() != p_vaddr) {
1253        *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s "
1254                                  "at expected address %p, instead mapped to %p",
1255                                  i, file->GetPath().c_str(), p_vaddr, segment->Begin());
1256        return false;
1257      }
1258      segments_.push_back(segment.release());
1259    }
1260  }
1261
1262  // Now that we are done loading, .dynamic should be in memory to find .dynstr, .dynsym, .hash
1263  uint8_t* dsptr = base_address_ + GetDynamicProgramHeader().p_vaddr;
1264  if ((dsptr < Begin() || dsptr >= End()) && !ValidPointer(dsptr)) {
1265    *error_msg = StringPrintf("dynamic section address invalid in ELF file %s",
1266                              file->GetPath().c_str());
1267    return false;
1268  }
1269  dynamic_section_start_ = reinterpret_cast<Elf_Dyn*>(dsptr);
1270
1271  for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1272    Elf_Dyn& elf_dyn = GetDynamic(i);
1273    uint8_t* d_ptr = base_address_ + elf_dyn.d_un.d_ptr;
1274    switch (elf_dyn.d_tag) {
1275      case DT_HASH: {
1276        if (!ValidPointer(d_ptr)) {
1277          *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1278                                    d_ptr, file->GetPath().c_str());
1279          return false;
1280        }
1281        hash_section_start_ = reinterpret_cast<Elf_Word*>(d_ptr);
1282        break;
1283      }
1284      case DT_STRTAB: {
1285        if (!ValidPointer(d_ptr)) {
1286          *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1287                                    d_ptr, file->GetPath().c_str());
1288          return false;
1289        }
1290        dynstr_section_start_ = reinterpret_cast<char*>(d_ptr);
1291        break;
1292      }
1293      case DT_SYMTAB: {
1294        if (!ValidPointer(d_ptr)) {
1295          *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1296                                    d_ptr, file->GetPath().c_str());
1297          return false;
1298        }
1299        dynsym_section_start_ = reinterpret_cast<Elf_Sym*>(d_ptr);
1300        break;
1301      }
1302      case DT_NULL: {
1303        if (GetDynamicNum() != i+1) {
1304          *error_msg = StringPrintf("DT_NULL found after %d .dynamic entries, "
1305                                    "expected %d as implied by size of PT_DYNAMIC segment in %s",
1306                                    i + 1, GetDynamicNum(), file->GetPath().c_str());
1307          return false;
1308        }
1309        break;
1310      }
1311    }
1312  }
1313
1314  // Check for the existence of some sections.
1315  if (!CheckSectionsExist(file, error_msg)) {
1316    return false;
1317  }
1318
1319  return true;
1320}
1321
1322template <typename ElfTypes>
1323bool ElfFileImpl<ElfTypes>::ValidPointer(const uint8_t* start) const {
1324  for (size_t i = 0; i < segments_.size(); ++i) {
1325    const MemMap* segment = segments_[i];
1326    if (segment->Begin() <= start && start < segment->End()) {
1327      return true;
1328    }
1329  }
1330  return false;
1331}
1332
1333
1334template <typename ElfTypes>
1335typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByName(
1336    const std::string& name) const {
1337  CHECK(!program_header_only_);
1338  Elf_Shdr* shstrtab_sec = GetSectionNameStringSection();
1339  if (shstrtab_sec == nullptr) {
1340    return nullptr;
1341  }
1342  for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) {
1343    Elf_Shdr* shdr = GetSectionHeader(i);
1344    if (shdr == nullptr) {
1345      return nullptr;
1346    }
1347    const char* sec_name = GetString(*shstrtab_sec, shdr->sh_name);
1348    if (sec_name == nullptr) {
1349      continue;
1350    }
1351    if (name == sec_name) {
1352      return shdr;
1353    }
1354  }
1355  return nullptr;
1356}
1357
1358template <typename ElfTypes>
1359bool ElfFileImpl<ElfTypes>::FixupDebugSections(Elf_Addr base_address_delta) {
1360  if (base_address_delta == 0) {
1361    return true;
1362  }
1363  return ApplyOatPatchesTo(".debug_frame", base_address_delta) &&
1364         ApplyOatPatchesTo(".debug_info", base_address_delta) &&
1365         ApplyOatPatchesTo(".debug_line", base_address_delta);
1366}
1367
1368template <typename ElfTypes>
1369bool ElfFileImpl<ElfTypes>::ApplyOatPatchesTo(
1370    const char* target_section_name, Elf_Addr delta) {
1371  auto target_section = FindSectionByName(target_section_name);
1372  if (target_section == nullptr) {
1373    return true;
1374  }
1375  std::string patches_name = target_section_name + std::string(".oat_patches");
1376  auto patches_section = FindSectionByName(patches_name.c_str());
1377  if (patches_section == nullptr) {
1378    LOG(ERROR) << patches_name << " section not found.";
1379    return false;
1380  }
1381  if (patches_section->sh_type != SHT_OAT_PATCH) {
1382    LOG(ERROR) << "Unexpected type of " << patches_name;
1383    return false;
1384  }
1385  ApplyOatPatches(
1386      Begin() + patches_section->sh_offset,
1387      Begin() + patches_section->sh_offset + patches_section->sh_size,
1388      delta,
1389      Begin() + target_section->sh_offset,
1390      Begin() + target_section->sh_offset + target_section->sh_size);
1391  return true;
1392}
1393
1394// Apply LEB128 encoded patches to given section.
1395template <typename ElfTypes>
1396void ElfFileImpl<ElfTypes>::ApplyOatPatches(
1397    const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
1398    uint8_t* to_patch, const uint8_t* to_patch_end) {
1399  typedef __attribute__((__aligned__(1))) Elf_Addr UnalignedAddress;
1400  while (patches < patches_end) {
1401    to_patch += DecodeUnsignedLeb128(&patches);
1402    DCHECK_LE(patches, patches_end) << "Unexpected end of patch list.";
1403    DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of section.";
1404    *reinterpret_cast<UnalignedAddress*>(to_patch) += delta;
1405  }
1406}
1407
1408template <typename ElfTypes>
1409bool ElfFileImpl<ElfTypes>::Strip(File* file, std::string* error_msg) {
1410  // ELF files produced by MCLinker look roughly like this
1411  //
1412  // +------------+
1413  // | Elf_Ehdr   | contains number of Elf_Shdr and offset to first
1414  // +------------+
1415  // | Elf_Phdr   | program headers
1416  // | Elf_Phdr   |
1417  // | ...        |
1418  // | Elf_Phdr   |
1419  // +------------+
1420  // | section    | mixture of needed and unneeded sections
1421  // +------------+
1422  // | section    |
1423  // +------------+
1424  // | ...        |
1425  // +------------+
1426  // | section    |
1427  // +------------+
1428  // | Elf_Shdr   | section headers
1429  // | Elf_Shdr   |
1430  // | ...        | contains offset to section start
1431  // | Elf_Shdr   |
1432  // +------------+
1433  //
1434  // To strip:
1435  // - leave the Elf_Ehdr and Elf_Phdr values in place.
1436  // - walk the sections making a new set of Elf_Shdr section headers for what we want to keep
1437  // - move the sections are keeping up to fill in gaps of sections we want to strip
1438  // - write new Elf_Shdr section headers to end of file, updating Elf_Ehdr
1439  // - truncate rest of file
1440  //
1441
1442  std::vector<Elf_Shdr> section_headers;
1443  std::vector<Elf_Word> section_headers_original_indexes;
1444  section_headers.reserve(GetSectionHeaderNum());
1445
1446
1447  Elf_Shdr* string_section = GetSectionNameStringSection();
1448  CHECK(string_section != nullptr);
1449  for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1450    Elf_Shdr* sh = GetSectionHeader(i);
1451    CHECK(sh != nullptr);
1452    const char* name = GetString(*string_section, sh->sh_name);
1453    if (name == nullptr) {
1454      CHECK_EQ(0U, i);
1455      section_headers.push_back(*sh);
1456      section_headers_original_indexes.push_back(0);
1457      continue;
1458    }
1459    if (android::base::StartsWith(name, ".debug")
1460        || (strcmp(name, ".strtab") == 0)
1461        || (strcmp(name, ".symtab") == 0)) {
1462      continue;
1463    }
1464    section_headers.push_back(*sh);
1465    section_headers_original_indexes.push_back(i);
1466  }
1467  CHECK_NE(0U, section_headers.size());
1468  CHECK_EQ(section_headers.size(), section_headers_original_indexes.size());
1469
1470  // section 0 is the null section, sections start at offset of first section
1471  CHECK(GetSectionHeader(1) != nullptr);
1472  Elf_Off offset = GetSectionHeader(1)->sh_offset;
1473  for (size_t i = 1; i < section_headers.size(); i++) {
1474    Elf_Shdr& new_sh = section_headers[i];
1475    Elf_Shdr* old_sh = GetSectionHeader(section_headers_original_indexes[i]);
1476    CHECK(old_sh != nullptr);
1477    CHECK_EQ(new_sh.sh_name, old_sh->sh_name);
1478    if (old_sh->sh_addralign > 1) {
1479      offset = RoundUp(offset, old_sh->sh_addralign);
1480    }
1481    if (old_sh->sh_offset == offset) {
1482      // already in place
1483      offset += old_sh->sh_size;
1484      continue;
1485    }
1486    // shift section earlier
1487    memmove(Begin() + offset,
1488            Begin() + old_sh->sh_offset,
1489            old_sh->sh_size);
1490    new_sh.sh_offset = offset;
1491    offset += old_sh->sh_size;
1492  }
1493
1494  Elf_Off shoff = offset;
1495  size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf_Shdr);
1496  memcpy(Begin() + offset, &section_headers[0], section_headers_size_in_bytes);
1497  offset += section_headers_size_in_bytes;
1498
1499  GetHeader().e_shnum = section_headers.size();
1500  GetHeader().e_shoff = shoff;
1501  int result = ftruncate(file->Fd(), offset);
1502  if (result != 0) {
1503    *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s",
1504                              file->GetPath().c_str(), strerror(errno));
1505    return false;
1506  }
1507  return true;
1508}
1509
1510static const bool DEBUG_FIXUP = false;
1511
1512template <typename ElfTypes>
1513bool ElfFileImpl<ElfTypes>::Fixup(Elf_Addr base_address) {
1514  if (!FixupDynamic(base_address)) {
1515    LOG(WARNING) << "Failed to fixup .dynamic in " << file_path_;
1516    return false;
1517  }
1518  if (!FixupSectionHeaders(base_address)) {
1519    LOG(WARNING) << "Failed to fixup section headers in " << file_path_;
1520    return false;
1521  }
1522  if (!FixupProgramHeaders(base_address)) {
1523    LOG(WARNING) << "Failed to fixup program headers in " << file_path_;
1524    return false;
1525  }
1526  if (!FixupSymbols(base_address, true)) {
1527    LOG(WARNING) << "Failed to fixup .dynsym in " << file_path_;
1528    return false;
1529  }
1530  if (!FixupSymbols(base_address, false)) {
1531    LOG(WARNING) << "Failed to fixup .symtab in " << file_path_;
1532    return false;
1533  }
1534  if (!FixupRelocations(base_address)) {
1535    LOG(WARNING) << "Failed to fixup .rel.dyn in " << file_path_;
1536    return false;
1537  }
1538  static_assert(sizeof(Elf_Off) >= sizeof(base_address), "Potentially losing precision.");
1539  if (!FixupDebugSections(static_cast<Elf_Off>(base_address))) {
1540    LOG(WARNING) << "Failed to fixup debug sections in " << file_path_;
1541    return false;
1542  }
1543  return true;
1544}
1545
1546template <typename ElfTypes>
1547bool ElfFileImpl<ElfTypes>::FixupDynamic(Elf_Addr base_address) {
1548  for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1549    Elf_Dyn& elf_dyn = GetDynamic(i);
1550    Elf_Word d_tag = elf_dyn.d_tag;
1551    if (IsDynamicSectionPointer(d_tag, GetHeader().e_machine)) {
1552      Elf_Addr d_ptr = elf_dyn.d_un.d_ptr;
1553      if (DEBUG_FIXUP) {
1554        LOG(INFO) << StringPrintf("In %s moving Elf_Dyn[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
1555                                  file_path_.c_str(), i,
1556                                  static_cast<uint64_t>(d_ptr),
1557                                  static_cast<uint64_t>(d_ptr + base_address));
1558      }
1559      d_ptr += base_address;
1560      elf_dyn.d_un.d_ptr = d_ptr;
1561    }
1562  }
1563  return true;
1564}
1565
1566template <typename ElfTypes>
1567bool ElfFileImpl<ElfTypes>::FixupSectionHeaders(Elf_Addr base_address) {
1568  for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1569    Elf_Shdr* sh = GetSectionHeader(i);
1570    CHECK(sh != nullptr);
1571    // 0 implies that the section will not exist in the memory of the process
1572    if (sh->sh_addr == 0) {
1573      continue;
1574    }
1575    if (DEBUG_FIXUP) {
1576      LOG(INFO) << StringPrintf("In %s moving Elf_Shdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
1577                                file_path_.c_str(), i,
1578                                static_cast<uint64_t>(sh->sh_addr),
1579                                static_cast<uint64_t>(sh->sh_addr + base_address));
1580    }
1581    sh->sh_addr += base_address;
1582  }
1583  return true;
1584}
1585
1586template <typename ElfTypes>
1587bool ElfFileImpl<ElfTypes>::FixupProgramHeaders(Elf_Addr base_address) {
1588  // TODO: ELFObjectFile doesn't have give to Elf_Phdr, so we do that ourselves for now.
1589  for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1590    Elf_Phdr* ph = GetProgramHeader(i);
1591    CHECK(ph != nullptr);
1592    CHECK_EQ(ph->p_vaddr, ph->p_paddr) << file_path_ << " i=" << i;
1593    CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
1594        << file_path_ << " i=" << i;
1595    if (DEBUG_FIXUP) {
1596      LOG(INFO) << StringPrintf("In %s moving Elf_Phdr[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
1597                                file_path_.c_str(), i,
1598                                static_cast<uint64_t>(ph->p_vaddr),
1599                                static_cast<uint64_t>(ph->p_vaddr + base_address));
1600    }
1601    ph->p_vaddr += base_address;
1602    ph->p_paddr += base_address;
1603    CHECK((ph->p_align == 0) || (0 == ((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1))))
1604        << file_path_ << " i=" << i;
1605  }
1606  return true;
1607}
1608
1609template <typename ElfTypes>
1610bool ElfFileImpl<ElfTypes>::FixupSymbols(Elf_Addr base_address, bool dynamic) {
1611  Elf_Word section_type = dynamic ? SHT_DYNSYM : SHT_SYMTAB;
1612  // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
1613  Elf_Shdr* symbol_section = FindSectionByType(section_type);
1614  if (symbol_section == nullptr) {
1615    // file is missing optional .symtab
1616    CHECK(!dynamic) << file_path_;
1617    return true;
1618  }
1619  for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
1620    Elf_Sym* symbol = GetSymbol(section_type, i);
1621    CHECK(symbol != nullptr);
1622    if (symbol->st_value != 0) {
1623      if (DEBUG_FIXUP) {
1624        LOG(INFO) << StringPrintf("In %s moving Elf_Sym[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
1625                                  file_path_.c_str(), i,
1626                                  static_cast<uint64_t>(symbol->st_value),
1627                                  static_cast<uint64_t>(symbol->st_value + base_address));
1628      }
1629      symbol->st_value += base_address;
1630    }
1631  }
1632  return true;
1633}
1634
1635template <typename ElfTypes>
1636bool ElfFileImpl<ElfTypes>::FixupRelocations(Elf_Addr base_address) {
1637  for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1638    Elf_Shdr* sh = GetSectionHeader(i);
1639    CHECK(sh != nullptr);
1640    if (sh->sh_type == SHT_REL) {
1641      for (uint32_t j = 0; j < GetRelNum(*sh); j++) {
1642        Elf_Rel& rel = GetRel(*sh, j);
1643        if (DEBUG_FIXUP) {
1644          LOG(INFO) << StringPrintf("In %s moving Elf_Rel[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
1645                                    file_path_.c_str(), j,
1646                                    static_cast<uint64_t>(rel.r_offset),
1647                                    static_cast<uint64_t>(rel.r_offset + base_address));
1648        }
1649        rel.r_offset += base_address;
1650      }
1651    } else if (sh->sh_type == SHT_RELA) {
1652      for (uint32_t j = 0; j < GetRelaNum(*sh); j++) {
1653        Elf_Rela& rela = GetRela(*sh, j);
1654        if (DEBUG_FIXUP) {
1655          LOG(INFO) << StringPrintf("In %s moving Elf_Rela[%d] from 0x%" PRIx64 " to 0x%" PRIx64,
1656                                    file_path_.c_str(), j,
1657                                    static_cast<uint64_t>(rela.r_offset),
1658                                    static_cast<uint64_t>(rela.r_offset + base_address));
1659        }
1660        rela.r_offset += base_address;
1661      }
1662    }
1663  }
1664  return true;
1665}
1666
1667// Explicit instantiations
1668template class ElfFileImpl<ElfTypes32>;
1669template class ElfFileImpl<ElfTypes64>;
1670
1671ElfFile::ElfFile(ElfFileImpl32* elf32) : elf32_(elf32), elf64_(nullptr) {
1672}
1673
1674ElfFile::ElfFile(ElfFileImpl64* elf64) : elf32_(nullptr), elf64_(elf64) {
1675}
1676
1677ElfFile::~ElfFile() {
1678  // Should never have 32 and 64-bit impls.
1679  CHECK_NE(elf32_.get() == nullptr, elf64_.get() == nullptr);
1680}
1681
1682ElfFile* ElfFile::Open(File* file,
1683                       bool writable,
1684                       bool program_header_only,
1685                       bool low_4gb,
1686                       std::string* error_msg,
1687                       uint8_t* requested_base) {
1688  if (file->GetLength() < EI_NIDENT) {
1689    *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
1690                              file->GetPath().c_str());
1691    return nullptr;
1692  }
1693  std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT,
1694                                              PROT_READ,
1695                                              MAP_PRIVATE,
1696                                              file->Fd(),
1697                                              0,
1698                                              low_4gb,
1699                                              file->GetPath().c_str(),
1700                                              error_msg));
1701  if (map == nullptr && map->Size() != EI_NIDENT) {
1702    return nullptr;
1703  }
1704  uint8_t* header = map->Begin();
1705  if (header[EI_CLASS] == ELFCLASS64) {
1706    ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file,
1707                                                       writable,
1708                                                       program_header_only,
1709                                                       low_4gb,
1710                                                       error_msg,
1711                                                       requested_base);
1712    if (elf_file_impl == nullptr) {
1713      return nullptr;
1714    }
1715    return new ElfFile(elf_file_impl);
1716  } else if (header[EI_CLASS] == ELFCLASS32) {
1717    ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file,
1718                                                       writable,
1719                                                       program_header_only,
1720                                                       low_4gb,
1721                                                       error_msg,
1722                                                       requested_base);
1723    if (elf_file_impl == nullptr) {
1724      return nullptr;
1725    }
1726    return new ElfFile(elf_file_impl);
1727  } else {
1728    *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
1729                              ELFCLASS32, ELFCLASS64,
1730                              file->GetPath().c_str(),
1731                              header[EI_CLASS]);
1732    return nullptr;
1733  }
1734}
1735
1736ElfFile* ElfFile::Open(File* file, int mmap_prot, int mmap_flags, std::string* error_msg) {
1737  // low_4gb support not required for this path.
1738  constexpr bool low_4gb = false;
1739  if (file->GetLength() < EI_NIDENT) {
1740    *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
1741                              file->GetPath().c_str());
1742    return nullptr;
1743  }
1744  std::unique_ptr<MemMap> map(MemMap::MapFile(EI_NIDENT,
1745                                              PROT_READ,
1746                                              MAP_PRIVATE,
1747                                              file->Fd(),
1748                                              0,
1749                                              low_4gb,
1750                                              file->GetPath().c_str(),
1751                                              error_msg));
1752  if (map == nullptr && map->Size() != EI_NIDENT) {
1753    return nullptr;
1754  }
1755  uint8_t* header = map->Begin();
1756  if (header[EI_CLASS] == ELFCLASS64) {
1757    ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file,
1758                                                       mmap_prot,
1759                                                       mmap_flags,
1760                                                       low_4gb,
1761                                                       error_msg);
1762    if (elf_file_impl == nullptr) {
1763      return nullptr;
1764    }
1765    return new ElfFile(elf_file_impl);
1766  } else if (header[EI_CLASS] == ELFCLASS32) {
1767    ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file,
1768                                                       mmap_prot,
1769                                                       mmap_flags,
1770                                                       low_4gb,
1771                                                       error_msg);
1772    if (elf_file_impl == nullptr) {
1773      return nullptr;
1774    }
1775    return new ElfFile(elf_file_impl);
1776  } else {
1777    *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
1778                              ELFCLASS32, ELFCLASS64,
1779                              file->GetPath().c_str(),
1780                              header[EI_CLASS]);
1781    return nullptr;
1782  }
1783}
1784
1785#define DELEGATE_TO_IMPL(func, ...) \
1786  if (elf64_.get() != nullptr) { \
1787    return elf64_->func(__VA_ARGS__); \
1788  } else { \
1789    DCHECK(elf32_.get() != nullptr); \
1790    return elf32_->func(__VA_ARGS__); \
1791  }
1792
1793bool ElfFile::Load(File* file, bool executable, bool low_4gb, std::string* error_msg) {
1794  DELEGATE_TO_IMPL(Load, file, executable, low_4gb, error_msg);
1795}
1796
1797const uint8_t* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
1798  DELEGATE_TO_IMPL(FindDynamicSymbolAddress, symbol_name);
1799}
1800
1801size_t ElfFile::Size() const {
1802  DELEGATE_TO_IMPL(Size);
1803}
1804
1805uint8_t* ElfFile::Begin() const {
1806  DELEGATE_TO_IMPL(Begin);
1807}
1808
1809uint8_t* ElfFile::End() const {
1810  DELEGATE_TO_IMPL(End);
1811}
1812
1813const std::string& ElfFile::GetFilePath() const {
1814  DELEGATE_TO_IMPL(GetFilePath);
1815}
1816
1817bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset,
1818                                      uint64_t* size) const {
1819  if (elf32_.get() == nullptr) {
1820    CHECK(elf64_.get() != nullptr);
1821
1822    Elf64_Shdr *shdr = elf64_->FindSectionByName(section_name);
1823    if (shdr == nullptr) {
1824      return false;
1825    }
1826    if (offset != nullptr) {
1827      *offset = shdr->sh_offset;
1828    }
1829    if (size != nullptr) {
1830      *size = shdr->sh_size;
1831    }
1832    return true;
1833  } else {
1834    Elf32_Shdr *shdr = elf32_->FindSectionByName(section_name);
1835    if (shdr == nullptr) {
1836      return false;
1837    }
1838    if (offset != nullptr) {
1839      *offset = shdr->sh_offset;
1840    }
1841    if (size != nullptr) {
1842      *size = shdr->sh_size;
1843    }
1844    return true;
1845  }
1846}
1847
1848bool ElfFile::HasSection(const std::string& name) const {
1849  if (elf64_.get() != nullptr) {
1850    return elf64_->FindSectionByName(name) != nullptr;
1851  } else {
1852    return elf32_->FindSectionByName(name) != nullptr;
1853  }
1854}
1855
1856uint64_t ElfFile::FindSymbolAddress(unsigned section_type,
1857                                    const std::string& symbol_name,
1858                                    bool build_map) {
1859  DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map);
1860}
1861
1862bool ElfFile::GetLoadedSize(size_t* size, std::string* error_msg) const {
1863  DELEGATE_TO_IMPL(GetLoadedSize, size, error_msg);
1864}
1865
1866bool ElfFile::Strip(File* file, std::string* error_msg) {
1867  std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, /*low_4gb*/false, error_msg));
1868  if (elf_file.get() == nullptr) {
1869    return false;
1870  }
1871
1872  if (elf_file->elf64_.get() != nullptr) {
1873    return elf_file->elf64_->Strip(file, error_msg);
1874  } else {
1875    return elf_file->elf32_->Strip(file, error_msg);
1876  }
1877}
1878
1879bool ElfFile::Fixup(uint64_t base_address) {
1880  if (elf64_.get() != nullptr) {
1881    return elf64_->Fixup(static_cast<Elf64_Addr>(base_address));
1882  } else {
1883    DCHECK(elf32_.get() != nullptr);
1884    CHECK(IsUint<32>(base_address)) << std::hex << base_address;
1885    return elf32_->Fixup(static_cast<Elf32_Addr>(base_address));
1886  }
1887  DELEGATE_TO_IMPL(Fixup, base_address);
1888}
1889
1890}  // namespace art
1891