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