Home | History | Annotate | Download | only in runtime
      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 "base/logging.h"
     20 #include "base/stl_util.h"
     21 #include "utils.h"
     22 
     23 namespace art {
     24 
     25 ElfFile::ElfFile()
     26   : file_(NULL),
     27     writable_(false),
     28     program_header_only_(false),
     29     header_(NULL),
     30     base_address_(NULL),
     31     program_headers_start_(NULL),
     32     section_headers_start_(NULL),
     33     dynamic_program_header_(NULL),
     34     dynamic_section_start_(NULL),
     35     symtab_section_start_(NULL),
     36     dynsym_section_start_(NULL),
     37     strtab_section_start_(NULL),
     38     dynstr_section_start_(NULL),
     39     hash_section_start_(NULL),
     40     symtab_symbol_table_(NULL),
     41     dynsym_symbol_table_(NULL) {}
     42 
     43 ElfFile* ElfFile::Open(File* file, bool writable, bool program_header_only) {
     44   UniquePtr<ElfFile> elf_file(new ElfFile());
     45   if (!elf_file->Setup(file, writable, program_header_only)) {
     46     return NULL;
     47   }
     48   return elf_file.release();
     49 }
     50 
     51 bool ElfFile::Setup(File* file, bool writable, bool program_header_only) {
     52   CHECK(file != NULL);
     53   file_ = file;
     54   writable_ = writable;
     55   program_header_only_ = program_header_only;
     56 
     57   int prot;
     58   int flags;
     59   if (writable_) {
     60     prot = PROT_READ | PROT_WRITE;
     61     flags = MAP_SHARED;
     62   } else {
     63     prot = PROT_READ;
     64     flags = MAP_PRIVATE;
     65   }
     66   int64_t file_length = file_->GetLength();
     67   if (file_length < 0) {
     68     errno = -file_length;
     69     PLOG(WARNING) << "Failed to get length of file: " << file_->GetPath() << " fd=" << file_->Fd();
     70     return false;
     71   }
     72   if (file_length < sizeof(llvm::ELF::Elf32_Ehdr)) {
     73     if (writable) {
     74       LOG(WARNING) << "File size of " << file_length
     75                    << " bytes not large enough to contain ELF header of "
     76                    << sizeof(llvm::ELF::Elf32_Ehdr) << " bytes: " << file_->GetPath();
     77     }
     78     return false;
     79   }
     80 
     81   if (program_header_only) {
     82     // first just map ELF header to get program header size information
     83     size_t elf_header_size = sizeof(llvm::ELF::Elf32_Ehdr);
     84     if (!SetMap(MemMap::MapFile(elf_header_size, prot, flags, file_->Fd(), 0))) {
     85       return false;
     86     }
     87     // then remap to cover program header
     88     size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum);
     89     if (file_length < program_header_size) {
     90       LOG(WARNING) << "File size of " << file_length
     91                    << " bytes not large enough to contain ELF program header of "
     92                    << program_header_size << " bytes: " << file_->GetPath();
     93       return false;
     94     }
     95     if (!SetMap(MemMap::MapFile(program_header_size, prot, flags, file_->Fd(), 0))) {
     96       LOG(WARNING) << "Failed to map ELF program headers: " << file_->GetPath();
     97       return false;
     98     }
     99   } else {
    100     // otherwise map entire file
    101     if (!SetMap(MemMap::MapFile(file_->GetLength(), prot, flags, file_->Fd(), 0))) {
    102       LOG(WARNING) << "Failed to map ELF file: " << file_->GetPath();
    103       return false;
    104     }
    105   }
    106 
    107   // Either way, the program header is relative to the elf header
    108   program_headers_start_ = Begin() + GetHeader().e_phoff;
    109 
    110   if (!program_header_only) {
    111     // Setup section headers.
    112     section_headers_start_ = Begin() + GetHeader().e_shoff;
    113 
    114     // Find .dynamic section info from program header
    115     dynamic_program_header_ = FindProgamHeaderByType(llvm::ELF::PT_DYNAMIC);
    116     if (dynamic_program_header_ == NULL) {
    117       LOG(WARNING) << "Failed to find PT_DYNAMIC program header in ELF file: " << file_->GetPath();
    118       return false;
    119     }
    120 
    121     dynamic_section_start_
    122         = reinterpret_cast<llvm::ELF::Elf32_Dyn*>(Begin() + GetDynamicProgramHeader().p_offset);
    123 
    124     // Find other sections from section headers
    125     for (llvm::ELF::Elf32_Word i = 0; i < GetSectionHeaderNum(); i++) {
    126       llvm::ELF::Elf32_Shdr& section_header = GetSectionHeader(i);
    127       byte* section_addr = Begin() + section_header.sh_offset;
    128       switch (section_header.sh_type) {
    129         case llvm::ELF::SHT_SYMTAB: {
    130           symtab_section_start_ = reinterpret_cast<llvm::ELF::Elf32_Sym*>(section_addr);
    131           break;
    132         }
    133         case llvm::ELF::SHT_DYNSYM: {
    134           dynsym_section_start_ = reinterpret_cast<llvm::ELF::Elf32_Sym*>(section_addr);
    135           break;
    136         }
    137         case llvm::ELF::SHT_STRTAB: {
    138           // TODO: base these off of sh_link from .symtab and .dynsym above
    139           if ((section_header.sh_flags & llvm::ELF::SHF_ALLOC) != 0) {
    140             dynstr_section_start_ = reinterpret_cast<char*>(section_addr);
    141           } else {
    142             strtab_section_start_ = reinterpret_cast<char*>(section_addr);
    143           }
    144           break;
    145         }
    146         case llvm::ELF::SHT_DYNAMIC: {
    147           if (reinterpret_cast<byte*>(dynamic_section_start_) != section_addr) {
    148             LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in "
    149                          << file_->GetPath() << ": " << std::hex
    150                          << reinterpret_cast<void*>(dynamic_section_start_)
    151                          << " != " << reinterpret_cast<void*>(section_addr);
    152             return false;
    153           }
    154           break;
    155         }
    156         case llvm::ELF::SHT_HASH: {
    157           hash_section_start_ = reinterpret_cast<llvm::ELF::Elf32_Word*>(section_addr);
    158           break;
    159         }
    160       }
    161     }
    162   }
    163   return true;
    164 }
    165 
    166 ElfFile::~ElfFile() {
    167   STLDeleteElements(&segments_);
    168   delete symtab_symbol_table_;
    169   delete dynsym_symbol_table_;
    170 }
    171 
    172 bool ElfFile::SetMap(MemMap* map) {
    173   if (map == NULL) {
    174     // MemMap::Open should have already logged
    175     return false;
    176   }
    177   map_.reset(map);
    178   CHECK(map_.get() != NULL) << file_->GetPath();
    179   CHECK(map_->Begin() != NULL) << file_->GetPath();
    180 
    181   header_ = reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(map_->Begin());
    182   if ((llvm::ELF::ElfMagic[0] != header_->e_ident[llvm::ELF::EI_MAG0])
    183       || (llvm::ELF::ElfMagic[1] != header_->e_ident[llvm::ELF::EI_MAG1])
    184       || (llvm::ELF::ElfMagic[2] != header_->e_ident[llvm::ELF::EI_MAG2])
    185       || (llvm::ELF::ElfMagic[3] != header_->e_ident[llvm::ELF::EI_MAG3])) {
    186     LOG(WARNING) << "Failed to find ELF magic in " << file_->GetPath()
    187                  << ": " << std::hex
    188                  << static_cast<uint8_t>(header_->e_ident[llvm::ELF::EI_MAG0])
    189                  << static_cast<uint8_t>(header_->e_ident[llvm::ELF::EI_MAG1])
    190                  << static_cast<uint8_t>(header_->e_ident[llvm::ELF::EI_MAG2])
    191                  << static_cast<uint8_t>(header_->e_ident[llvm::ELF::EI_MAG3]);
    192     return false;
    193   }
    194 
    195 
    196   // TODO: remove these static_casts from enum when using -std=gnu++0x
    197   CHECK_EQ(static_cast<unsigned char>(llvm::ELF::ELFCLASS32),  header_->e_ident[llvm::ELF::EI_CLASS])   << file_->GetPath();
    198   CHECK_EQ(static_cast<unsigned char>(llvm::ELF::ELFDATA2LSB), header_->e_ident[llvm::ELF::EI_DATA])    << file_->GetPath();
    199   CHECK_EQ(static_cast<unsigned char>(llvm::ELF::EV_CURRENT),  header_->e_ident[llvm::ELF::EI_VERSION]) << file_->GetPath();
    200 
    201   // TODO: remove these static_casts from enum when using -std=gnu++0x
    202   CHECK_EQ(static_cast<llvm::ELF::Elf32_Half>(llvm::ELF::ET_DYN), header_->e_type) << file_->GetPath();
    203   CHECK_EQ(static_cast<llvm::ELF::Elf32_Word>(llvm::ELF::EV_CURRENT), header_->e_version) << file_->GetPath();
    204   CHECK_EQ(0U, header_->e_entry) << file_->GetPath();
    205 
    206   CHECK_NE(0U, header_->e_phoff) << file_->GetPath();
    207   CHECK_NE(0U, header_->e_shoff) << file_->GetPath();
    208   CHECK_NE(0U, header_->e_ehsize) << file_->GetPath();
    209   CHECK_NE(0U, header_->e_phentsize) << file_->GetPath();
    210   CHECK_NE(0U, header_->e_phnum) << file_->GetPath();
    211   CHECK_NE(0U, header_->e_shentsize) << file_->GetPath();
    212   CHECK_NE(0U, header_->e_shnum) << file_->GetPath();
    213   CHECK_NE(0U, header_->e_shstrndx) << file_->GetPath();
    214   CHECK_GE(header_->e_shnum, header_->e_shstrndx) << file_->GetPath();
    215   if (!program_header_only_) {
    216     CHECK_GT(Size(), header_->e_phoff) << file_->GetPath();
    217     CHECK_GT(Size(), header_->e_shoff) << file_->GetPath();
    218   }
    219   return true;
    220 }
    221 
    222 
    223 llvm::ELF::Elf32_Ehdr& ElfFile::GetHeader() {
    224   CHECK(header_ != NULL);
    225   return *header_;
    226 }
    227 
    228 byte* ElfFile::GetProgramHeadersStart() {
    229   CHECK(program_headers_start_ != NULL);
    230   return program_headers_start_;
    231 }
    232 
    233 byte* ElfFile::GetSectionHeadersStart() {
    234   CHECK(section_headers_start_ != NULL);
    235   return section_headers_start_;
    236 }
    237 
    238 llvm::ELF::Elf32_Phdr& ElfFile::GetDynamicProgramHeader() {
    239   CHECK(dynamic_program_header_ != NULL);
    240   return *dynamic_program_header_;
    241 }
    242 
    243 llvm::ELF::Elf32_Dyn* ElfFile::GetDynamicSectionStart() {
    244   CHECK(dynamic_section_start_ != NULL);
    245   return dynamic_section_start_;
    246 }
    247 
    248 llvm::ELF::Elf32_Sym* ElfFile::GetSymbolSectionStart(llvm::ELF::Elf32_Word section_type) {
    249   CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
    250   llvm::ELF::Elf32_Sym* symbol_section_start;
    251   switch (section_type) {
    252     case llvm::ELF::SHT_SYMTAB: {
    253       symbol_section_start = symtab_section_start_;
    254       break;
    255     }
    256     case llvm::ELF::SHT_DYNSYM: {
    257       symbol_section_start = dynsym_section_start_;
    258       break;
    259     }
    260     default: {
    261       LOG(FATAL) << section_type;
    262       symbol_section_start = NULL;
    263     }
    264   }
    265   CHECK(symbol_section_start != NULL);
    266   return symbol_section_start;
    267 }
    268 
    269 const char* ElfFile::GetStringSectionStart(llvm::ELF::Elf32_Word section_type) {
    270   CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
    271   const char* string_section_start;
    272   switch (section_type) {
    273     case llvm::ELF::SHT_SYMTAB: {
    274       string_section_start = strtab_section_start_;
    275       break;
    276     }
    277     case llvm::ELF::SHT_DYNSYM: {
    278       string_section_start = dynstr_section_start_;
    279       break;
    280     }
    281     default: {
    282       LOG(FATAL) << section_type;
    283       string_section_start = NULL;
    284     }
    285   }
    286   CHECK(string_section_start != NULL);
    287   return string_section_start;
    288 }
    289 
    290 const char* ElfFile::GetString(llvm::ELF::Elf32_Word section_type, llvm::ELF::Elf32_Word i) {
    291   CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
    292   if (i == 0) {
    293     return NULL;
    294   }
    295   const char* string_section_start = GetStringSectionStart(section_type);
    296   const char* string = string_section_start + i;
    297   return string;
    298 }
    299 
    300 llvm::ELF::Elf32_Word* ElfFile::GetHashSectionStart() {
    301   CHECK(hash_section_start_ != NULL);
    302   return hash_section_start_;
    303 }
    304 
    305 llvm::ELF::Elf32_Word ElfFile::GetHashBucketNum() {
    306   return GetHashSectionStart()[0];
    307 }
    308 
    309 llvm::ELF::Elf32_Word ElfFile::GetHashChainNum() {
    310   return GetHashSectionStart()[1];
    311 }
    312 
    313 llvm::ELF::Elf32_Word ElfFile::GetHashBucket(size_t i) {
    314   CHECK_LT(i, GetHashBucketNum());
    315   // 0 is nbucket, 1 is nchain
    316   return GetHashSectionStart()[2 + i];
    317 }
    318 
    319 llvm::ELF::Elf32_Word ElfFile::GetHashChain(size_t i) {
    320   CHECK_LT(i, GetHashChainNum());
    321   // 0 is nbucket, 1 is nchain, & chains are after buckets
    322   return GetHashSectionStart()[2 + GetHashBucketNum() + i];
    323 }
    324 
    325 llvm::ELF::Elf32_Word ElfFile::GetProgramHeaderNum() {
    326   return GetHeader().e_phnum;
    327 }
    328 
    329 llvm::ELF::Elf32_Phdr& ElfFile::GetProgramHeader(llvm::ELF::Elf32_Word i) {
    330   CHECK_LT(i, GetProgramHeaderNum()) << file_->GetPath();
    331   byte* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize);
    332   CHECK_LT(program_header, End()) << file_->GetPath();
    333   return *reinterpret_cast<llvm::ELF::Elf32_Phdr*>(program_header);
    334 }
    335 
    336 llvm::ELF::Elf32_Phdr* ElfFile::FindProgamHeaderByType(llvm::ELF::Elf32_Word type) {
    337   for (llvm::ELF::Elf32_Word i = 0; i < GetProgramHeaderNum(); i++) {
    338     llvm::ELF::Elf32_Phdr& program_header = GetProgramHeader(i);
    339     if (program_header.p_type == type) {
    340       return &program_header;
    341     }
    342   }
    343   return NULL;
    344 }
    345 
    346 llvm::ELF::Elf32_Word ElfFile::GetSectionHeaderNum() {
    347   return GetHeader().e_shnum;
    348 }
    349 
    350 llvm::ELF::Elf32_Shdr& ElfFile::GetSectionHeader(llvm::ELF::Elf32_Word i) {
    351   // Can only access arbitrary sections when we have the whole file, not just program header.
    352   // Even if we Load(), it doesn't bring in all the sections.
    353   CHECK(!program_header_only_) << file_->GetPath();
    354   CHECK_LT(i, GetSectionHeaderNum()) << file_->GetPath();
    355   byte* section_header = GetSectionHeadersStart() + (i * GetHeader().e_shentsize);
    356   CHECK_LT(section_header, End()) << file_->GetPath();
    357   return *reinterpret_cast<llvm::ELF::Elf32_Shdr*>(section_header);
    358 }
    359 
    360 llvm::ELF::Elf32_Shdr* ElfFile::FindSectionByType(llvm::ELF::Elf32_Word type) {
    361   // Can only access arbitrary sections when we have the whole file, not just program header.
    362   // We could change this to switch on known types if they were detected during loading.
    363   CHECK(!program_header_only_) << file_->GetPath();
    364   for (llvm::ELF::Elf32_Word i = 0; i < GetSectionHeaderNum(); i++) {
    365     llvm::ELF::Elf32_Shdr& section_header = GetSectionHeader(i);
    366     if (section_header.sh_type == type) {
    367       return &section_header;
    368     }
    369   }
    370   return NULL;
    371 }
    372 
    373 // from bionic
    374 static unsigned elfhash(const char *_name) {
    375   const unsigned char *name = (const unsigned char *) _name;
    376   unsigned h = 0, g;
    377 
    378   while (*name) {
    379     h = (h << 4) + *name++;
    380     g = h & 0xf0000000;
    381     h ^= g;
    382     h ^= g >> 24;
    383   }
    384   return h;
    385 }
    386 
    387 llvm::ELF::Elf32_Shdr& ElfFile::GetSectionNameStringSection() {
    388   return GetSectionHeader(GetHeader().e_shstrndx);
    389 }
    390 
    391 byte* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) {
    392   llvm::ELF::Elf32_Word hash = elfhash(symbol_name.c_str());
    393   llvm::ELF::Elf32_Word bucket_index = hash % GetHashBucketNum();
    394   llvm::ELF::Elf32_Word symbol_and_chain_index = GetHashBucket(bucket_index);
    395   while (symbol_and_chain_index != 0 /* STN_UNDEF */) {
    396     llvm::ELF::Elf32_Sym& symbol = GetSymbol(llvm::ELF::SHT_DYNSYM, symbol_and_chain_index);
    397     const char* name = GetString(llvm::ELF::SHT_DYNSYM, symbol.st_name);
    398     if (symbol_name == name) {
    399       return base_address_ + symbol.st_value;
    400     }
    401     symbol_and_chain_index = GetHashChain(symbol_and_chain_index);
    402   }
    403   return NULL;
    404 }
    405 
    406 bool ElfFile::IsSymbolSectionType(llvm::ELF::Elf32_Word section_type) {
    407   return ((section_type == llvm::ELF::SHT_SYMTAB) || (section_type == llvm::ELF::SHT_DYNSYM));
    408 }
    409 
    410 llvm::ELF::Elf32_Word ElfFile::GetSymbolNum(llvm::ELF::Elf32_Shdr& section_header) {
    411   CHECK(IsSymbolSectionType(section_header.sh_type)) << file_->GetPath() << " " << section_header.sh_type;
    412   CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath();
    413   return section_header.sh_size / section_header.sh_entsize;
    414 }
    415 
    416 llvm::ELF::Elf32_Sym& ElfFile::GetSymbol(llvm::ELF::Elf32_Word section_type,
    417                                          llvm::ELF::Elf32_Word i) {
    418   return *(GetSymbolSectionStart(section_type) + i);
    419 }
    420 
    421 ElfFile::SymbolTable** ElfFile::GetSymbolTable(llvm::ELF::Elf32_Word section_type) {
    422   CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
    423   switch (section_type) {
    424     case llvm::ELF::SHT_SYMTAB: {
    425       return &symtab_symbol_table_;
    426     }
    427     case llvm::ELF::SHT_DYNSYM: {
    428       return &dynsym_symbol_table_;
    429     }
    430     default: {
    431       LOG(FATAL) << section_type;
    432       return NULL;
    433     }
    434   }
    435 }
    436 
    437 llvm::ELF::Elf32_Sym* ElfFile::FindSymbolByName(llvm::ELF::Elf32_Word section_type,
    438                                                 const std::string& symbol_name,
    439                                                 bool build_map) {
    440   CHECK(!program_header_only_) << file_->GetPath();
    441   CHECK(IsSymbolSectionType(section_type)) << file_->GetPath() << " " << section_type;
    442 
    443   SymbolTable** symbol_table = GetSymbolTable(section_type);
    444   if (*symbol_table != NULL || build_map) {
    445     if (*symbol_table == NULL) {
    446       DCHECK(build_map);
    447       *symbol_table = new SymbolTable;
    448       llvm::ELF::Elf32_Shdr* symbol_section = FindSectionByType(section_type);
    449       CHECK(symbol_section != NULL) << file_->GetPath();
    450       llvm::ELF::Elf32_Shdr& string_section = GetSectionHeader(symbol_section->sh_link);
    451       for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
    452         llvm::ELF::Elf32_Sym& symbol = GetSymbol(section_type, i);
    453         unsigned char type = symbol.getType();
    454         if (type == llvm::ELF::STT_NOTYPE) {
    455           continue;
    456         }
    457         const char* name = GetString(string_section, symbol.st_name);
    458         if (name == NULL) {
    459           continue;
    460         }
    461         std::pair<SymbolTable::iterator, bool> result = (*symbol_table)->insert(std::make_pair(name, &symbol));
    462         if (!result.second) {
    463           // If a duplicate, make sure it has the same logical value. Seen on x86.
    464           CHECK_EQ(symbol.st_value, result.first->second->st_value);
    465           CHECK_EQ(symbol.st_size, result.first->second->st_size);
    466           CHECK_EQ(symbol.st_info, result.first->second->st_info);
    467           CHECK_EQ(symbol.st_other, result.first->second->st_other);
    468           CHECK_EQ(symbol.st_shndx, result.first->second->st_shndx);
    469         }
    470       }
    471     }
    472     CHECK(*symbol_table != NULL);
    473     SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
    474     if (it == (*symbol_table)->end()) {
    475       return NULL;
    476     }
    477     return it->second;
    478   }
    479 
    480   // Fall back to linear search
    481   llvm::ELF::Elf32_Shdr* symbol_section = FindSectionByType(section_type);
    482   CHECK(symbol_section != NULL) << file_->GetPath();
    483   llvm::ELF::Elf32_Shdr& string_section = GetSectionHeader(symbol_section->sh_link);
    484   for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
    485     llvm::ELF::Elf32_Sym& symbol = GetSymbol(section_type, i);
    486     const char* name = GetString(string_section, symbol.st_name);
    487     if (name == NULL) {
    488       continue;
    489     }
    490     if (symbol_name == name) {
    491       return &symbol;
    492     }
    493   }
    494   return NULL;
    495 }
    496 
    497 llvm::ELF::Elf32_Addr ElfFile::FindSymbolAddress(llvm::ELF::Elf32_Word section_type,
    498                                                  const std::string& symbol_name,
    499                                                  bool build_map) {
    500   llvm::ELF::Elf32_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
    501   if (symbol == NULL) {
    502     return 0;
    503   }
    504   return symbol->st_value;
    505 }
    506 
    507 const char* ElfFile::GetString(llvm::ELF::Elf32_Shdr& string_section, llvm::ELF::Elf32_Word i) {
    508   CHECK(!program_header_only_) << file_->GetPath();
    509   // TODO: remove this static_cast from enum when using -std=gnu++0x
    510   CHECK_EQ(static_cast<llvm::ELF::Elf32_Word>(llvm::ELF::SHT_STRTAB), string_section.sh_type) << file_->GetPath();
    511   CHECK_LT(i, string_section.sh_size) << file_->GetPath();
    512   if (i == 0) {
    513     return NULL;
    514   }
    515   byte* strings = Begin() + string_section.sh_offset;
    516   byte* string = strings + i;
    517   CHECK_LT(string, End()) << file_->GetPath();
    518   return reinterpret_cast<const char*>(string);
    519 }
    520 
    521 llvm::ELF::Elf32_Word ElfFile::GetDynamicNum() {
    522   return GetDynamicProgramHeader().p_filesz / sizeof(llvm::ELF::Elf32_Dyn);
    523 }
    524 
    525 llvm::ELF::Elf32_Dyn& ElfFile::GetDynamic(llvm::ELF::Elf32_Word i) {
    526   CHECK_LT(i, GetDynamicNum()) << file_->GetPath();
    527   return *(GetDynamicSectionStart() + i);
    528 }
    529 
    530 llvm::ELF::Elf32_Word ElfFile::FindDynamicValueByType(llvm::ELF::Elf32_Sword type) {
    531   for (llvm::ELF::Elf32_Word i = 0; i < GetDynamicNum(); i++) {
    532     llvm::ELF::Elf32_Dyn& elf_dyn = GetDynamic(i);
    533     if (elf_dyn.d_tag == type) {
    534       return elf_dyn.d_un.d_val;
    535     }
    536   }
    537   return 0;
    538 }
    539 
    540 llvm::ELF::Elf32_Rel* ElfFile::GetRelSectionStart(llvm::ELF::Elf32_Shdr& section_header) {
    541   CHECK(llvm::ELF::SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
    542   return reinterpret_cast<llvm::ELF::Elf32_Rel*>(Begin() + section_header.sh_offset);
    543 }
    544 
    545 llvm::ELF::Elf32_Word ElfFile::GetRelNum(llvm::ELF::Elf32_Shdr& section_header) {
    546   CHECK(llvm::ELF::SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
    547   CHECK_NE(0U, section_header.sh_entsize) << file_->GetPath();
    548   return section_header.sh_size / section_header.sh_entsize;
    549 }
    550 
    551 llvm::ELF::Elf32_Rel& ElfFile::GetRel(llvm::ELF::Elf32_Shdr& section_header, llvm::ELF::Elf32_Word i) {
    552   CHECK(llvm::ELF::SHT_REL == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
    553   CHECK_LT(i, GetRelNum(section_header)) << file_->GetPath();
    554   return *(GetRelSectionStart(section_header) + i);
    555 }
    556 
    557 llvm::ELF::Elf32_Rela* ElfFile::GetRelaSectionStart(llvm::ELF::Elf32_Shdr& section_header) {
    558   CHECK(llvm::ELF::SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
    559   return reinterpret_cast<llvm::ELF::Elf32_Rela*>(Begin() + section_header.sh_offset);
    560 }
    561 
    562 llvm::ELF::Elf32_Word ElfFile::GetRelaNum(llvm::ELF::Elf32_Shdr& section_header) {
    563   CHECK(llvm::ELF::SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
    564   return section_header.sh_size / section_header.sh_entsize;
    565 }
    566 
    567 llvm::ELF::Elf32_Rela& ElfFile::GetRela(llvm::ELF::Elf32_Shdr& section_header,
    568                                         llvm::ELF::Elf32_Word i) {
    569   CHECK(llvm::ELF::SHT_RELA == section_header.sh_type) << file_->GetPath() << " " << section_header.sh_type;
    570   CHECK_LT(i, GetRelaNum(section_header)) << file_->GetPath();
    571   return *(GetRelaSectionStart(section_header) + i);
    572 }
    573 
    574 // Base on bionic phdr_table_get_load_size
    575 size_t ElfFile::GetLoadedSize() {
    576   llvm::ELF::Elf32_Addr min_vaddr = 0xFFFFFFFFu;
    577   llvm::ELF::Elf32_Addr max_vaddr = 0x00000000u;
    578   for (llvm::ELF::Elf32_Word i = 0; i < GetProgramHeaderNum(); i++) {
    579     llvm::ELF::Elf32_Phdr& program_header = GetProgramHeader(i);
    580     if (program_header.p_type != llvm::ELF::PT_LOAD) {
    581       continue;
    582     }
    583     llvm::ELF::Elf32_Addr begin_vaddr = program_header.p_vaddr;
    584     if (begin_vaddr < min_vaddr) {
    585        min_vaddr = begin_vaddr;
    586     }
    587     llvm::ELF::Elf32_Addr end_vaddr = program_header.p_vaddr + program_header.p_memsz;
    588     if (end_vaddr > max_vaddr) {
    589       max_vaddr = end_vaddr;
    590     }
    591   }
    592   min_vaddr = RoundDown(min_vaddr, kPageSize);
    593   max_vaddr = RoundUp(max_vaddr, kPageSize);
    594   CHECK_LT(min_vaddr, max_vaddr) << file_->GetPath();
    595   size_t loaded_size = max_vaddr - min_vaddr;
    596   return loaded_size;
    597 }
    598 
    599 bool ElfFile::Load(bool executable) {
    600   // TODO: actually return false error
    601   CHECK(program_header_only_) << file_->GetPath();
    602   for (llvm::ELF::Elf32_Word i = 0; i < GetProgramHeaderNum(); i++) {
    603     llvm::ELF::Elf32_Phdr& program_header = GetProgramHeader(i);
    604 
    605     // Record .dynamic header information for later use
    606     if (program_header.p_type == llvm::ELF::PT_DYNAMIC) {
    607       dynamic_program_header_ = &program_header;
    608       continue;
    609     }
    610 
    611     // Not something to load, move on.
    612     if (program_header.p_type != llvm::ELF::PT_LOAD) {
    613       continue;
    614     }
    615 
    616     // Found something to load.
    617 
    618     // If p_vaddr is zero, it must be the first loadable segment,
    619     // since they must be in order.  Since it is zero, there isn't a
    620     // specific address requested, so first request a contiguous chunk
    621     // of required size for all segments, but with no
    622     // permissions. We'll then carve that up with the proper
    623     // permissions as we load the actual segments. If p_vaddr is
    624     // non-zero, the segments require the specific address specified,
    625     // which either was specified in the file because we already set
    626     // base_address_ after the first zero segment).
    627     int64_t file_length = file_->GetLength();
    628     if (program_header.p_vaddr == 0) {
    629       std::string reservation_name("ElfFile reservation for ");
    630       reservation_name += file_->GetPath();
    631       UniquePtr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
    632                                                      NULL, GetLoadedSize(), PROT_NONE));
    633       CHECK(reserve.get() != NULL) << file_->GetPath();
    634       base_address_ = reserve->Begin();
    635       segments_.push_back(reserve.release());
    636     }
    637     // empty segment, nothing to map
    638     if (program_header.p_memsz == 0) {
    639       continue;
    640     }
    641     byte* p_vaddr = base_address_ + program_header.p_vaddr;
    642     int prot = 0;
    643     if (executable && ((program_header.p_flags & llvm::ELF::PF_X) != 0)) {
    644       prot |= PROT_EXEC;
    645     }
    646     if ((program_header.p_flags & llvm::ELF::PF_W) != 0) {
    647       prot |= PROT_WRITE;
    648     }
    649     if ((program_header.p_flags & llvm::ELF::PF_R) != 0) {
    650       prot |= PROT_READ;
    651     }
    652     int flags = MAP_FIXED;
    653     if (writable_) {
    654       prot |= PROT_WRITE;
    655       flags |= MAP_SHARED;
    656     } else {
    657       flags |= MAP_PRIVATE;
    658     }
    659     if (file_length < (program_header.p_offset + program_header.p_memsz)) {
    660       LOG(WARNING) << "File size of " << file_length
    661                    << " bytes not large enough to contain ELF segment " << i
    662                    << " of " << (program_header.p_offset + program_header.p_memsz)
    663                    << " bytes: " << file_->GetPath();
    664       return false;
    665     }
    666     UniquePtr<MemMap> segment(MemMap::MapFileAtAddress(p_vaddr,
    667                                                        program_header.p_memsz,
    668                                                        prot, flags, file_->Fd(),
    669                                                        program_header.p_offset,
    670                                                        true));
    671     CHECK(segment.get() != NULL) << file_->GetPath();
    672     CHECK_EQ(segment->Begin(), p_vaddr) << file_->GetPath();
    673     segments_.push_back(segment.release());
    674   }
    675 
    676   // Now that we are done loading, .dynamic should be in memory to find .dynstr, .dynsym, .hash
    677   dynamic_section_start_
    678       = reinterpret_cast<llvm::ELF::Elf32_Dyn*>(base_address_ + GetDynamicProgramHeader().p_vaddr);
    679   for (llvm::ELF::Elf32_Word i = 0; i < GetDynamicNum(); i++) {
    680     llvm::ELF::Elf32_Dyn& elf_dyn = GetDynamic(i);
    681     byte* d_ptr = base_address_ + elf_dyn.d_un.d_ptr;
    682     switch (elf_dyn.d_tag) {
    683       case llvm::ELF::DT_HASH: {
    684         hash_section_start_ = reinterpret_cast<llvm::ELF::Elf32_Word*>(d_ptr);
    685         break;
    686       }
    687       case llvm::ELF::DT_STRTAB: {
    688         dynstr_section_start_ = reinterpret_cast<char*>(d_ptr);
    689         break;
    690       }
    691       case llvm::ELF::DT_SYMTAB: {
    692         dynsym_section_start_ = reinterpret_cast<llvm::ELF::Elf32_Sym*>(d_ptr);
    693         break;
    694       }
    695       case llvm::ELF::DT_NULL: {
    696         CHECK_EQ(GetDynamicNum(), i+1);
    697         break;
    698       }
    699     }
    700   }
    701 
    702   return true;
    703 }
    704 
    705 }  // namespace art
    706