elf_builder.h revision 6a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866f
1/* 2 * Copyright (C) 2014 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#ifndef ART_COMPILER_ELF_BUILDER_H_ 18#define ART_COMPILER_ELF_BUILDER_H_ 19 20#include "base/stl_util.h" 21#include "base/value_object.h" 22#include "buffered_output_stream.h" 23#include "elf_utils.h" 24#include "file_output_stream.h" 25#include "instruction_set.h" 26 27namespace art { 28 29template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr> 30class ElfSectionBuilder : public ValueObject { 31 public: 32 ElfSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags, 33 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link, Elf_Word info, 34 Elf_Word align, Elf_Word entsize) 35 : section_index_(0), name_(sec_name), link_(link) { 36 memset(§ion_, 0, sizeof(section_)); 37 section_.sh_type = type; 38 section_.sh_flags = flags; 39 section_.sh_info = info; 40 section_.sh_addralign = align; 41 section_.sh_entsize = entsize; 42 } 43 44 ~ElfSectionBuilder() {} 45 46 Elf_Word GetLink() const { 47 return (link_ != nullptr) ? link_->section_index_ : 0; 48 } 49 50 const Elf_Shdr* GetSection() const { 51 return §ion_; 52 } 53 54 Elf_Shdr* GetSection() { 55 return §ion_; 56 } 57 58 Elf_Word GetSectionIndex() const { 59 return section_index_; 60 } 61 62 void SetSectionIndex(Elf_Word section_index) { 63 section_index_ = section_index; 64 } 65 66 const std::string& GetName() const { 67 return name_; 68 } 69 70 private: 71 Elf_Shdr section_; 72 Elf_Word section_index_; 73 const std::string name_; 74 const ElfSectionBuilder* const link_; 75}; 76 77template <typename Elf_Word, typename Elf_Sword, typename Elf_Dyn, typename Elf_Shdr> 78class ElfDynamicBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> { 79 public: 80 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un) { 81 if (tag == DT_NULL) { 82 return; 83 } 84 dynamics_.push_back({nullptr, tag, d_un}); 85 } 86 87 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un, 88 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section) { 89 if (tag == DT_NULL) { 90 return; 91 } 92 dynamics_.push_back({section, tag, d_un}); 93 } 94 95 ElfDynamicBuilder(const std::string& sec_name, 96 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link) 97 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC, 98 link, 0, kPageSize, sizeof(Elf_Dyn)) {} 99 ~ElfDynamicBuilder() {} 100 101 Elf_Word GetSize() const { 102 // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of 103 // these must be added when we actually put the file together because 104 // their values are very dependent on state. 105 return dynamics_.size() + 3; 106 } 107 108 // Create the actual dynamic vector. strsz should be the size of the .dynstr 109 // table and soname_off should be the offset of the soname in .dynstr. 110 // Since niether can be found prior to final layout we will wait until here 111 // to add them. 112 std::vector<Elf_Dyn> GetDynamics(Elf_Word strsz, Elf_Word soname) const { 113 std::vector<Elf_Dyn> ret; 114 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) { 115 if (it->section_ != nullptr) { 116 // We are adding an address relative to a section. 117 ret.push_back( 118 {it->tag_, {it->off_ + it->section_->GetSection()->sh_addr}}); 119 } else { 120 ret.push_back({it->tag_, {it->off_}}); 121 } 122 } 123 ret.push_back({DT_STRSZ, {strsz}}); 124 ret.push_back({DT_SONAME, {soname}}); 125 ret.push_back({DT_NULL, {0}}); 126 return ret; 127 } 128 129 private: 130 struct ElfDynamicState { 131 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_; 132 Elf_Sword tag_; 133 Elf_Word off_; 134 }; 135 std::vector<ElfDynamicState> dynamics_; 136}; 137 138template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr> 139class ElfRawSectionBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> { 140 public: 141 ElfRawSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags, 142 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* link, Elf_Word info, 143 Elf_Word align, Elf_Word entsize) 144 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, link, info, align, 145 entsize) { 146 } 147 148 ~ElfRawSectionBuilder() {} 149 150 std::vector<uint8_t>* GetBuffer() { 151 return &buf_; 152 } 153 154 void SetBuffer(const std::vector<uint8_t>& buf) { 155 buf_ = buf; 156 } 157 158 private: 159 std::vector<uint8_t> buf_; 160}; 161 162template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr> 163class ElfOatSectionBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> { 164 public: 165 ElfOatSectionBuilder(const std::string& sec_name, Elf_Word size, Elf_Word offset, 166 Elf_Word type, Elf_Word flags) 167 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, nullptr, 0, kPageSize, 168 0), 169 offset_(offset), size_(size) { 170 } 171 172 ~ElfOatSectionBuilder() {} 173 174 Elf_Word GetOffset() const { 175 return offset_; 176 } 177 178 Elf_Word GetSize() const { 179 return size_; 180 } 181 182 private: 183 // Offset of the content within the file. 184 Elf_Word offset_; 185 // Size of the content within the file. 186 Elf_Word size_; 187}; 188 189static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) { 190 return ((binding) << 4) + ((type) & 0xf); 191} 192 193// from bionic 194static inline unsigned elfhash(const char *_name) { 195 const unsigned char *name = (const unsigned char *) _name; 196 unsigned h = 0, g; 197 198 while (*name) { 199 h = (h << 4) + *name++; 200 g = h & 0xf0000000; 201 h ^= g; 202 h ^= g >> 24; 203 } 204 return h; 205} 206 207template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Sym, 208 typename Elf_Shdr> 209class ElfSymtabBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> { 210 public: 211 // Add a symbol with given name to this symtab. The symbol refers to 212 // 'relative_addr' within the given section and has the given attributes. 213 void AddSymbol(const std::string& name, 214 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section, 215 Elf_Addr addr, 216 bool is_relative, 217 Elf_Word size, 218 uint8_t binding, 219 uint8_t type, 220 uint8_t other = 0) { 221 CHECK(section); 222 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative, 223 MakeStInfo(binding, type), other, 0}; 224 symbols_.push_back(state); 225 } 226 227 ElfSymtabBuilder(const std::string& sec_name, Elf_Word type, 228 const std::string& str_name, Elf_Word str_type, bool alloc) 229 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, ((alloc) ? SHF_ALLOC : 0U), 230 &strtab_, 0, sizeof(Elf_Word), 231 sizeof(Elf_Sym)), str_name_(str_name), 232 str_type_(str_type), 233 strtab_(str_name, 234 str_type, 235 ((alloc) ? SHF_ALLOC : 0U), 236 nullptr, 0, 1, 1) { 237 } 238 239 ~ElfSymtabBuilder() {} 240 241 std::vector<Elf_Word> GenerateHashContents() const { 242 // Here is how The ELF hash table works. 243 // There are 3 arrays to worry about. 244 // * The symbol table where the symbol information is. 245 // * The bucket array which is an array of indexes into the symtab and chain. 246 // * The chain array which is also an array of indexes into the symtab and chain. 247 // 248 // Lets say the state is something like this. 249 // +--------+ +--------+ +-----------+ 250 // | symtab | | bucket | | chain | 251 // | null | | 1 | | STN_UNDEF | 252 // | <sym1> | | 4 | | 2 | 253 // | <sym2> | | | | 5 | 254 // | <sym3> | | | | STN_UNDEF | 255 // | <sym4> | | | | 3 | 256 // | <sym5> | | | | STN_UNDEF | 257 // +--------+ +--------+ +-----------+ 258 // 259 // The lookup process (in python psudocode) is 260 // 261 // def GetSym(name): 262 // # NB STN_UNDEF == 0 263 // indx = bucket[elfhash(name) % num_buckets] 264 // while indx != STN_UNDEF: 265 // if GetSymbolName(symtab[indx]) == name: 266 // return symtab[indx] 267 // indx = chain[indx] 268 // return SYMBOL_NOT_FOUND 269 // 270 // Between bucket and chain arrays every symtab index must be present exactly 271 // once (except for STN_UNDEF, which must be present 1 + num_bucket times). 272 273 // Select number of buckets. 274 // This is essentially arbitrary. 275 Elf_Word nbuckets; 276 Elf_Word chain_size = GetSize(); 277 if (symbols_.size() < 8) { 278 nbuckets = 2; 279 } else if (symbols_.size() < 32) { 280 nbuckets = 4; 281 } else if (symbols_.size() < 256) { 282 nbuckets = 16; 283 } else { 284 // Have about 32 ids per bucket. 285 nbuckets = RoundUp(symbols_.size()/32, 2); 286 } 287 std::vector<Elf_Word> hash; 288 hash.push_back(nbuckets); 289 hash.push_back(chain_size); 290 uint32_t bucket_offset = hash.size(); 291 uint32_t chain_offset = bucket_offset + nbuckets; 292 hash.resize(hash.size() + nbuckets + chain_size, 0); 293 294 Elf_Word* buckets = hash.data() + bucket_offset; 295 Elf_Word* chain = hash.data() + chain_offset; 296 297 // Set up the actual hash table. 298 for (Elf_Word i = 0; i < symbols_.size(); i++) { 299 // Add 1 since we need to have the null symbol that is not in the symbols 300 // list. 301 Elf_Word index = i + 1; 302 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets; 303 if (buckets[hash_val] == 0) { 304 buckets[hash_val] = index; 305 } else { 306 hash_val = buckets[hash_val]; 307 CHECK_LT(hash_val, chain_size); 308 while (chain[hash_val] != 0) { 309 hash_val = chain[hash_val]; 310 CHECK_LT(hash_val, chain_size); 311 } 312 chain[hash_val] = index; 313 // Check for loops. Works because if this is non-empty then there must be 314 // another cell which already contains the same symbol index as this one, 315 // which means some symbol has more then one name, which isn't allowed. 316 CHECK_EQ(chain[index], static_cast<Elf_Word>(0)); 317 } 318 } 319 320 return hash; 321 } 322 323 std::string GenerateStrtab() { 324 std::string tab; 325 tab += '\0'; 326 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) { 327 it->name_idx_ = tab.size(); 328 tab += it->name_; 329 tab += '\0'; 330 } 331 strtab_.GetSection()->sh_size = tab.size(); 332 return tab; 333 } 334 335 std::vector<Elf_Sym> GenerateSymtab() { 336 std::vector<Elf_Sym> ret; 337 Elf_Sym undef_sym; 338 memset(&undef_sym, 0, sizeof(undef_sym)); 339 undef_sym.st_shndx = SHN_UNDEF; 340 ret.push_back(undef_sym); 341 342 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) { 343 Elf_Sym sym; 344 memset(&sym, 0, sizeof(sym)); 345 sym.st_name = it->name_idx_; 346 if (it->is_relative_) { 347 sym.st_value = it->addr_ + it->section_->GetSection()->sh_offset; 348 } else { 349 sym.st_value = it->addr_; 350 } 351 sym.st_size = it->size_; 352 sym.st_other = it->other_; 353 sym.st_shndx = it->section_->GetSectionIndex(); 354 sym.st_info = it->info_; 355 356 ret.push_back(sym); 357 } 358 return ret; 359 } 360 361 Elf_Word GetSize() const { 362 // 1 is for the implicit NULL symbol. 363 return symbols_.size() + 1; 364 } 365 366 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* GetStrTab() { 367 return &strtab_; 368 } 369 370 private: 371 struct ElfSymbolState { 372 const std::string name_; 373 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_; 374 Elf_Addr addr_; 375 Elf_Word size_; 376 bool is_relative_; 377 uint8_t info_; 378 uint8_t other_; 379 // Used during Write() to temporarially hold name index in the strtab. 380 Elf_Word name_idx_; 381 }; 382 383 // Information for the strsym for dynstr sections. 384 const std::string str_name_; 385 Elf_Word str_type_; 386 // The symbols in the same order they will be in the symbol table. 387 std::vector<ElfSymbolState> symbols_; 388 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> strtab_; 389}; 390 391template <typename Elf_Word> 392class ElfFilePiece { 393 public: 394 virtual ~ElfFilePiece() {} 395 396 virtual bool Write(File* elf_file) { 397 if (static_cast<off_t>(offset_) != lseek(elf_file->Fd(), offset_, SEEK_SET)) { 398 PLOG(ERROR) << "Failed to seek to " << GetDescription() << " offset " << offset_ << " for " 399 << elf_file->GetPath(); 400 return false; 401 } 402 403 return DoActualWrite(elf_file); 404 } 405 406 static bool Compare(ElfFilePiece* a, ElfFilePiece* b) { 407 return a->offset_ < b->offset_; 408 } 409 410 protected: 411 explicit ElfFilePiece(Elf_Word offset) : offset_(offset) {} 412 413 Elf_Word GetOffset() const { 414 return offset_; 415 } 416 417 virtual const char* GetDescription() const = 0; 418 virtual bool DoActualWrite(File* elf_file) = 0; 419 420 private: 421 const Elf_Word offset_; 422 423 DISALLOW_COPY_AND_ASSIGN(ElfFilePiece); 424}; 425 426template <typename Elf_Word> 427class ElfFileMemoryPiece FINAL : public ElfFilePiece<Elf_Word> { 428 public: 429 ElfFileMemoryPiece(const std::string& name, Elf_Word offset, const void* data, Elf_Word size) 430 : ElfFilePiece<Elf_Word>(offset), dbg_name_(name), data_(data), size_(size) {} 431 432 protected: 433 bool DoActualWrite(File* elf_file) OVERRIDE { 434 DCHECK(data_ != nullptr || size_ == 0U) << dbg_name_ << " " << size_; 435 436 if (!elf_file->WriteFully(data_, size_)) { 437 PLOG(ERROR) << "Failed to write " << dbg_name_ << " for " << elf_file->GetPath(); 438 return false; 439 } 440 441 return true; 442 } 443 444 const char* GetDescription() const OVERRIDE { 445 return dbg_name_.c_str(); 446 } 447 448 private: 449 const std::string& dbg_name_; 450 const void *data_; 451 Elf_Word size_; 452}; 453 454class CodeOutput { 455 public: 456 virtual void SetCodeOffset(size_t offset) = 0; 457 virtual bool Write(OutputStream* out) = 0; 458 virtual ~CodeOutput() {} 459}; 460 461template <typename Elf_Word> 462class ElfFileRodataPiece FINAL : public ElfFilePiece<Elf_Word> { 463 public: 464 ElfFileRodataPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset), 465 output_(output) {} 466 467 protected: 468 bool DoActualWrite(File* elf_file) OVERRIDE { 469 output_->SetCodeOffset(this->GetOffset()); 470 std::unique_ptr<BufferedOutputStream> output_stream( 471 new BufferedOutputStream(new FileOutputStream(elf_file))); 472 if (!output_->Write(output_stream.get())) { 473 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file->GetPath(); 474 return false; 475 } 476 477 return true; 478 } 479 480 const char* GetDescription() const OVERRIDE { 481 return ".rodata"; 482 } 483 484 private: 485 CodeOutput* const output_; 486 487 DISALLOW_COPY_AND_ASSIGN(ElfFileRodataPiece); 488}; 489 490template <typename Elf_Word> 491class ElfFileOatTextPiece FINAL : public ElfFilePiece<Elf_Word> { 492 public: 493 ElfFileOatTextPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset), 494 output_(output) {} 495 496 protected: 497 bool DoActualWrite(File* elf_file ATTRIBUTE_UNUSED) OVERRIDE { 498 // All data is written by the ElfFileRodataPiece right now, as the oat writer writes in one 499 // piece. This is for future flexibility. 500 UNUSED(output_); 501 return true; 502 } 503 504 const char* GetDescription() const OVERRIDE { 505 return ".text"; 506 } 507 508 private: 509 CodeOutput* const output_; 510 511 DISALLOW_COPY_AND_ASSIGN(ElfFileOatTextPiece); 512}; 513 514template <typename Elf_Word> 515static bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces, File* elf_file) { 516 // TODO It would be nice if this checked for overlap. 517 for (auto it = pieces.begin(); it != pieces.end(); ++it) { 518 if (!(*it)->Write(elf_file)) { 519 return false; 520 } 521 } 522 return true; 523} 524 525template <typename Elf_Word, typename Elf_Shdr> 526static inline constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) { 527 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign); 528} 529 530template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Dyn, 531 typename Elf_Sym, typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr> 532class ElfBuilder FINAL { 533 public: 534 ElfBuilder(CodeOutput* oat_writer, 535 File* elf_file, 536 InstructionSet isa, 537 Elf_Word rodata_relative_offset, 538 Elf_Word rodata_size, 539 Elf_Word text_relative_offset, 540 Elf_Word text_size, 541 const bool add_symbols, 542 bool debug = false) 543 : oat_writer_(oat_writer), 544 elf_file_(elf_file), 545 add_symbols_(add_symbols), 546 debug_logging_(debug), 547 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS, 548 SHF_ALLOC | SHF_EXECINSTR), 549 rodata_builder_(".rodata", rodata_size, rodata_relative_offset, SHT_PROGBITS, SHF_ALLOC), 550 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true), 551 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false), 552 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0, sizeof(Elf_Word), 553 sizeof(Elf_Word)), 554 dynamic_builder_(".dynamic", &dynsym_builder_), 555 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) { 556 SetupEhdr(); 557 SetupDynamic(); 558 SetupRequiredSymbols(); 559 SetISA(isa); 560 } 561 ~ElfBuilder() {} 562 563 const ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>& GetTextBuilder() const { 564 return text_builder_; 565 } 566 567 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* GetSymtabBuilder() { 568 return &symtab_builder_; 569 } 570 571 bool Init() { 572 // The basic layout of the elf file. Order may be different in final output. 573 // +-------------------------+ 574 // | Elf_Ehdr | 575 // +-------------------------+ 576 // | Elf_Phdr PHDR | 577 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata 578 // | Elf_Phdr LOAD R X | .text 579 // | Elf_Phdr LOAD RW | .dynamic 580 // | Elf_Phdr DYNAMIC | .dynamic 581 // +-------------------------+ 582 // | .dynsym | 583 // | Elf_Sym STN_UNDEF | 584 // | Elf_Sym oatdata | 585 // | Elf_Sym oatexec | 586 // | Elf_Sym oatlastword | 587 // +-------------------------+ 588 // | .dynstr | 589 // | \0 | 590 // | oatdata\0 | 591 // | oatexec\0 | 592 // | oatlastword\0 | 593 // | boot.oat\0 | 594 // +-------------------------+ 595 // | .hash | 596 // | Elf_Word nbucket = b | 597 // | Elf_Word nchain = c | 598 // | Elf_Word bucket[0] | 599 // | ... | 600 // | Elf_Word bucket[b - 1] | 601 // | Elf_Word chain[0] | 602 // | ... | 603 // | Elf_Word chain[c - 1] | 604 // +-------------------------+ 605 // | .rodata | 606 // | oatdata..oatexec-4 | 607 // +-------------------------+ 608 // | .text | 609 // | oatexec..oatlastword | 610 // +-------------------------+ 611 // | .dynamic | 612 // | Elf_Dyn DT_SONAME | 613 // | Elf_Dyn DT_HASH | 614 // | Elf_Dyn DT_SYMTAB | 615 // | Elf_Dyn DT_SYMENT | 616 // | Elf_Dyn DT_STRTAB | 617 // | Elf_Dyn DT_STRSZ | 618 // | Elf_Dyn DT_NULL | 619 // +-------------------------+ (Optional) 620 // | .strtab | (Optional) 621 // | program symbol names | (Optional) 622 // +-------------------------+ (Optional) 623 // | .symtab | (Optional) 624 // | program symbols | (Optional) 625 // +-------------------------+ 626 // | .shstrtab | 627 // | \0 | 628 // | .dynamic\0 | 629 // | .dynsym\0 | 630 // | .dynstr\0 | 631 // | .hash\0 | 632 // | .rodata\0 | 633 // | .text\0 | 634 // | .shstrtab\0 | 635 // | .symtab\0 | (Optional) 636 // | .strtab\0 | (Optional) 637 // | .debug_str\0 | (Optional) 638 // | .debug_info\0 | (Optional) 639 // | .eh_frame\0 | (Optional) 640 // | .debug_line\0 | (Optional) 641 // | .debug_abbrev\0 | (Optional) 642 // +-------------------------+ (Optional) 643 // | .debug_info | (Optional) 644 // +-------------------------+ (Optional) 645 // | .debug_abbrev | (Optional) 646 // +-------------------------+ (Optional) 647 // | .eh_frame | (Optional) 648 // +-------------------------+ (Optional) 649 // | .debug_line | (Optional) 650 // +-------------------------+ (Optional) 651 // | .debug_str | (Optional) 652 // +-------------------------+ (Optional) 653 // | Elf_Shdr NULL | 654 // | Elf_Shdr .dynsym | 655 // | Elf_Shdr .dynstr | 656 // | Elf_Shdr .hash | 657 // | Elf_Shdr .text | 658 // | Elf_Shdr .rodata | 659 // | Elf_Shdr .dynamic | 660 // | Elf_Shdr .shstrtab | 661 // | Elf_Shdr .debug_info | (Optional) 662 // | Elf_Shdr .debug_abbrev | (Optional) 663 // | Elf_Shdr .eh_frame | (Optional) 664 // | Elf_Shdr .debug_line | (Optional) 665 // | Elf_Shdr .debug_str | (Optional) 666 // +-------------------------+ 667 668 if (fatal_error_) { 669 return false; 670 } 671 // Step 1. Figure out all the offsets. 672 673 if (debug_logging_) { 674 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET; 675 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE; 676 } 677 678 memset(&program_headers_, 0, sizeof(program_headers_)); 679 program_headers_[PH_PHDR].p_type = PT_PHDR; 680 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET; 681 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET; 682 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET; 683 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_); 684 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_); 685 program_headers_[PH_PHDR].p_flags = PF_R; 686 program_headers_[PH_PHDR].p_align = sizeof(Elf_Word); 687 688 program_headers_[PH_LOAD_R__].p_type = PT_LOAD; 689 program_headers_[PH_LOAD_R__].p_offset = 0; 690 program_headers_[PH_LOAD_R__].p_vaddr = 0; 691 program_headers_[PH_LOAD_R__].p_paddr = 0; 692 program_headers_[PH_LOAD_R__].p_flags = PF_R; 693 694 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD; 695 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X; 696 697 program_headers_[PH_LOAD_RW_].p_type = PT_LOAD; 698 program_headers_[PH_LOAD_RW_].p_flags = PF_R | PF_W; 699 700 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC; 701 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W; 702 703 // Get the dynstr string. 704 dynstr_ = dynsym_builder_.GenerateStrtab(); 705 706 // Add the SONAME to the dynstr. 707 dynstr_soname_offset_ = dynstr_.size(); 708 std::string file_name(elf_file_->GetPath()); 709 size_t directory_separator_pos = file_name.rfind('/'); 710 if (directory_separator_pos != std::string::npos) { 711 file_name = file_name.substr(directory_separator_pos + 1); 712 } 713 dynstr_ += file_name; 714 dynstr_ += '\0'; 715 if (debug_logging_) { 716 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size() 717 << std::hex << " " << dynstr_.size(); 718 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize() 719 << std::hex << " " << dynsym_builder_.GetSize(); 720 } 721 722 // Get the section header string table. 723 shstrtab_ += '\0'; 724 725 // Setup sym_undef 726 memset(&null_hdr_, 0, sizeof(null_hdr_)); 727 null_hdr_.sh_type = SHT_NULL; 728 null_hdr_.sh_link = SHN_UNDEF; 729 section_ptrs_.push_back(&null_hdr_); 730 731 section_index_ = 1; 732 733 // setup .dynsym 734 section_ptrs_.push_back(dynsym_builder_.GetSection()); 735 AssignSectionStr(&dynsym_builder_, &shstrtab_); 736 dynsym_builder_.SetSectionIndex(section_index_); 737 section_index_++; 738 739 // Setup .dynstr 740 section_ptrs_.push_back(dynsym_builder_.GetStrTab()->GetSection()); 741 AssignSectionStr(dynsym_builder_.GetStrTab(), &shstrtab_); 742 dynsym_builder_.GetStrTab()->SetSectionIndex(section_index_); 743 section_index_++; 744 745 // Setup .hash 746 section_ptrs_.push_back(hash_builder_.GetSection()); 747 AssignSectionStr(&hash_builder_, &shstrtab_); 748 hash_builder_.SetSectionIndex(section_index_); 749 section_index_++; 750 751 // Setup .rodata 752 section_ptrs_.push_back(rodata_builder_.GetSection()); 753 AssignSectionStr(&rodata_builder_, &shstrtab_); 754 rodata_builder_.SetSectionIndex(section_index_); 755 section_index_++; 756 757 // Setup .text 758 section_ptrs_.push_back(text_builder_.GetSection()); 759 AssignSectionStr(&text_builder_, &shstrtab_); 760 text_builder_.SetSectionIndex(section_index_); 761 section_index_++; 762 763 // Setup .dynamic 764 section_ptrs_.push_back(dynamic_builder_.GetSection()); 765 AssignSectionStr(&dynamic_builder_, &shstrtab_); 766 dynamic_builder_.SetSectionIndex(section_index_); 767 section_index_++; 768 769 // Fill in the hash section. 770 hash_ = dynsym_builder_.GenerateHashContents(); 771 772 if (debug_logging_) { 773 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word) 774 << std::hex << " " << hash_.size() * sizeof(Elf_Word); 775 } 776 777 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_); 778 779 // Get the layout in the sections. 780 // 781 // Get the layout of the dynsym section. 782 dynsym_builder_.GetSection()->sh_offset = 783 RoundUp(base_offset, dynsym_builder_.GetSection()->sh_addralign); 784 dynsym_builder_.GetSection()->sh_addr = dynsym_builder_.GetSection()->sh_offset; 785 dynsym_builder_.GetSection()->sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym); 786 dynsym_builder_.GetSection()->sh_link = dynsym_builder_.GetLink(); 787 788 // Get the layout of the dynstr section. 789 dynsym_builder_.GetStrTab()->GetSection()->sh_offset = 790 NextOffset<Elf_Word, Elf_Shdr>(*dynsym_builder_.GetStrTab()->GetSection(), 791 *dynsym_builder_.GetSection()); 792 dynsym_builder_.GetStrTab()->GetSection()->sh_addr = 793 dynsym_builder_.GetStrTab()->GetSection()->sh_offset; 794 dynsym_builder_.GetStrTab()->GetSection()->sh_size = dynstr_.size(); 795 dynsym_builder_.GetStrTab()->GetSection()->sh_link = dynsym_builder_.GetStrTab()->GetLink(); 796 797 // Get the layout of the hash section 798 hash_builder_.GetSection()->sh_offset = 799 NextOffset<Elf_Word, Elf_Shdr>(*hash_builder_.GetSection(), 800 *dynsym_builder_.GetStrTab()->GetSection()); 801 hash_builder_.GetSection()->sh_addr = hash_builder_.GetSection()->sh_offset; 802 hash_builder_.GetSection()->sh_size = hash_.size() * sizeof(Elf_Word); 803 hash_builder_.GetSection()->sh_link = hash_builder_.GetLink(); 804 805 // Get the layout of the rodata section. 806 rodata_builder_.GetSection()->sh_offset = 807 NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(), 808 *hash_builder_.GetSection()); 809 rodata_builder_.GetSection()->sh_addr = rodata_builder_.GetSection()->sh_offset; 810 rodata_builder_.GetSection()->sh_size = rodata_builder_.GetSize(); 811 rodata_builder_.GetSection()->sh_link = rodata_builder_.GetLink(); 812 813 // Get the layout of the text section. 814 text_builder_.GetSection()->sh_offset = 815 NextOffset<Elf_Word, Elf_Shdr>(*text_builder_.GetSection(), 816 *rodata_builder_.GetSection()); 817 text_builder_.GetSection()->sh_addr = text_builder_.GetSection()->sh_offset; 818 text_builder_.GetSection()->sh_size = text_builder_.GetSize(); 819 text_builder_.GetSection()->sh_link = text_builder_.GetLink(); 820 CHECK_ALIGNED(rodata_builder_.GetSection()->sh_offset + 821 rodata_builder_.GetSection()->sh_size, kPageSize); 822 823 // Get the layout of the dynamic section. 824 dynamic_builder_.GetSection()->sh_offset = 825 NextOffset<Elf_Word, Elf_Shdr>(*dynamic_builder_.GetSection(), *text_builder_.GetSection()); 826 dynamic_builder_.GetSection()->sh_addr = dynamic_builder_.GetSection()->sh_offset; 827 dynamic_builder_.GetSection()->sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn); 828 dynamic_builder_.GetSection()->sh_link = dynamic_builder_.GetLink(); 829 830 if (debug_logging_) { 831 LOG(INFO) << "dynsym off=" << dynsym_builder_.GetSection()->sh_offset 832 << " dynsym size=" << dynsym_builder_.GetSection()->sh_size; 833 LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->GetSection()->sh_offset 834 << " dynstr size=" << dynsym_builder_.GetStrTab()->GetSection()->sh_size; 835 LOG(INFO) << "hash off=" << hash_builder_.GetSection()->sh_offset 836 << " hash size=" << hash_builder_.GetSection()->sh_size; 837 LOG(INFO) << "rodata off=" << rodata_builder_.GetSection()->sh_offset 838 << " rodata size=" << rodata_builder_.GetSection()->sh_size; 839 LOG(INFO) << "text off=" << text_builder_.GetSection()->sh_offset 840 << " text size=" << text_builder_.GetSection()->sh_size; 841 LOG(INFO) << "dynamic off=" << dynamic_builder_.GetSection()->sh_offset 842 << " dynamic size=" << dynamic_builder_.GetSection()->sh_size; 843 } 844 845 return true; 846 } 847 848 bool Write() { 849 std::vector<ElfFilePiece<Elf_Word>*> pieces; 850 Elf_Shdr* prev = dynamic_builder_.GetSection(); 851 std::string strtab; 852 853 if (IncludingDebugSymbols()) { 854 // Setup .symtab 855 section_ptrs_.push_back(symtab_builder_.GetSection()); 856 AssignSectionStr(&symtab_builder_, &shstrtab_); 857 symtab_builder_.SetSectionIndex(section_index_); 858 section_index_++; 859 860 // Setup .strtab 861 section_ptrs_.push_back(symtab_builder_.GetStrTab()->GetSection()); 862 AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_); 863 symtab_builder_.GetStrTab()->SetSectionIndex(section_index_); 864 section_index_++; 865 866 strtab = symtab_builder_.GenerateStrtab(); 867 if (debug_logging_) { 868 LOG(INFO) << "strtab size (bytes) =" << strtab.size() 869 << std::hex << " " << strtab.size(); 870 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize() 871 << std::hex << " " << symtab_builder_.GetSize(); 872 } 873 } 874 875 // Setup all the other sections. 876 for (ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder = other_builders_.data(), 877 *end = builder + other_builders_.size(); 878 builder != end; ++builder) { 879 section_ptrs_.push_back(builder->GetSection()); 880 AssignSectionStr(builder, &shstrtab_); 881 builder->SetSectionIndex(section_index_); 882 section_index_++; 883 } 884 885 // Setup shstrtab 886 section_ptrs_.push_back(shstrtab_builder_.GetSection()); 887 AssignSectionStr(&shstrtab_builder_, &shstrtab_); 888 shstrtab_builder_.SetSectionIndex(section_index_); 889 section_index_++; 890 891 if (debug_logging_) { 892 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size() 893 << std::hex << " " << shstrtab_.size(); 894 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size() 895 << std::hex << " " << section_ptrs_.size(); 896 } 897 898 if (IncludingDebugSymbols()) { 899 // Get the layout of the symtab section. 900 symtab_builder_.GetSection()->sh_offset = 901 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetSection(), 902 *dynamic_builder_.GetSection()); 903 symtab_builder_.GetSection()->sh_addr = 0; 904 // Add to leave space for the null symbol. 905 symtab_builder_.GetSection()->sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym); 906 symtab_builder_.GetSection()->sh_link = symtab_builder_.GetLink(); 907 908 // Get the layout of the dynstr section. 909 symtab_builder_.GetStrTab()->GetSection()->sh_offset = 910 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetStrTab()->GetSection(), 911 *symtab_builder_.GetSection()); 912 symtab_builder_.GetStrTab()->GetSection()->sh_addr = 0; 913 symtab_builder_.GetStrTab()->GetSection()->sh_size = strtab.size(); 914 symtab_builder_.GetStrTab()->GetSection()->sh_link = symtab_builder_.GetStrTab()->GetLink(); 915 916 prev = symtab_builder_.GetStrTab()->GetSection(); 917 if (debug_logging_) { 918 LOG(INFO) << "symtab off=" << symtab_builder_.GetSection()->sh_offset 919 << " symtab size=" << symtab_builder_.GetSection()->sh_size; 920 LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->GetSection()->sh_offset 921 << " strtab size=" << symtab_builder_.GetStrTab()->GetSection()->sh_size; 922 } 923 } 924 925 // Get the layout of the extra sections. (This will deal with the debug 926 // sections if they are there) 927 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) { 928 it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev); 929 it->GetSection()->sh_addr = 0; 930 it->GetSection()->sh_size = it->GetBuffer()->size(); 931 it->GetSection()->sh_link = it->GetLink(); 932 933 // We postpone adding an ElfFilePiece to keep the order in "pieces." 934 935 prev = it->GetSection(); 936 if (debug_logging_) { 937 LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset 938 << " size=" << it->GetSection()->sh_size; 939 } 940 } 941 942 // Get the layout of the shstrtab section 943 shstrtab_builder_.GetSection()->sh_offset = 944 NextOffset<Elf_Word, Elf_Shdr>(*shstrtab_builder_.GetSection(), *prev); 945 shstrtab_builder_.GetSection()->sh_addr = 0; 946 shstrtab_builder_.GetSection()->sh_size = shstrtab_.size(); 947 shstrtab_builder_.GetSection()->sh_link = shstrtab_builder_.GetLink(); 948 if (debug_logging_) { 949 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.GetSection()->sh_offset 950 << " shstrtab size=" << shstrtab_builder_.GetSection()->sh_size; 951 } 952 953 // The section list comes after come after. 954 Elf_Word sections_offset = RoundUp( 955 shstrtab_builder_.GetSection()->sh_offset + shstrtab_builder_.GetSection()->sh_size, 956 sizeof(Elf_Word)); 957 958 // Setup the actual symbol arrays. 959 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab(); 960 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.GetSection()->sh_size); 961 std::vector<Elf_Sym> symtab; 962 if (IncludingDebugSymbols()) { 963 symtab = symtab_builder_.GenerateSymtab(); 964 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.GetSection()->sh_size); 965 } 966 967 // Setup the dynamic section. 968 // This will add the 2 values we cannot know until now time, namely the size 969 // and the soname_offset. 970 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(), 971 dynstr_soname_offset_); 972 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.GetSection()->sh_size); 973 974 // Finish setup of the program headers now that we know the layout of the 975 // whole file. 976 Elf_Word load_r_size = 977 rodata_builder_.GetSection()->sh_offset + rodata_builder_.GetSection()->sh_size; 978 program_headers_[PH_LOAD_R__].p_filesz = load_r_size; 979 program_headers_[PH_LOAD_R__].p_memsz = load_r_size; 980 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.GetSection()->sh_addralign; 981 982 Elf_Word load_rx_size = text_builder_.GetSection()->sh_size; 983 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.GetSection()->sh_offset; 984 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.GetSection()->sh_offset; 985 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.GetSection()->sh_offset; 986 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size; 987 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size; 988 program_headers_[PH_LOAD_R_X].p_align = text_builder_.GetSection()->sh_addralign; 989 990 program_headers_[PH_LOAD_RW_].p_offset = dynamic_builder_.GetSection()->sh_offset; 991 program_headers_[PH_LOAD_RW_].p_vaddr = dynamic_builder_.GetSection()->sh_offset; 992 program_headers_[PH_LOAD_RW_].p_paddr = dynamic_builder_.GetSection()->sh_offset; 993 program_headers_[PH_LOAD_RW_].p_filesz = dynamic_builder_.GetSection()->sh_size; 994 program_headers_[PH_LOAD_RW_].p_memsz = dynamic_builder_.GetSection()->sh_size; 995 program_headers_[PH_LOAD_RW_].p_align = dynamic_builder_.GetSection()->sh_addralign; 996 997 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset; 998 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_offset; 999 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_offset; 1000 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size; 1001 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size; 1002 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign; 1003 1004 // Finish setup of the Ehdr values. 1005 elf_header_.e_phoff = PHDR_OFFSET; 1006 elf_header_.e_shoff = sections_offset; 1007 elf_header_.e_phnum = PH_NUM; 1008 elf_header_.e_shnum = section_ptrs_.size(); 1009 elf_header_.e_shstrndx = shstrtab_builder_.GetSectionIndex(); 1010 1011 // Add the rest of the pieces to the list. 1012 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_, 1013 sizeof(elf_header_))); 1014 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET, 1015 &program_headers_, sizeof(program_headers_))); 1016 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic", 1017 dynamic_builder_.GetSection()->sh_offset, 1018 dynamic.data(), 1019 dynamic_builder_.GetSection()->sh_size)); 1020 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.GetSection()->sh_offset, 1021 dynsym.data(), 1022 dynsym.size() * sizeof(Elf_Sym))); 1023 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr", 1024 dynsym_builder_.GetStrTab()->GetSection()->sh_offset, 1025 dynstr_.c_str(), dynstr_.size())); 1026 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.GetSection()->sh_offset, 1027 hash_.data(), 1028 hash_.size() * sizeof(Elf_Word))); 1029 pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.GetSection()->sh_offset, 1030 oat_writer_)); 1031 pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.GetSection()->sh_offset, 1032 oat_writer_)); 1033 if (IncludingDebugSymbols()) { 1034 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab", 1035 symtab_builder_.GetSection()->sh_offset, 1036 symtab.data(), 1037 symtab.size() * sizeof(Elf_Sym))); 1038 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab", 1039 symtab_builder_.GetStrTab()->GetSection()->sh_offset, 1040 strtab.c_str(), strtab.size())); 1041 } 1042 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab", 1043 shstrtab_builder_.GetSection()->sh_offset, 1044 &shstrtab_[0], shstrtab_.size())); 1045 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) { 1046 // Just add all the sections in induvidually since they are all over the 1047 // place on the heap/stack. 1048 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr); 1049 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off, 1050 section_ptrs_[i], sizeof(Elf_Shdr))); 1051 } 1052 1053 // Postponed debug info. 1054 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) { 1055 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->GetName(), it->GetSection()->sh_offset, 1056 it->GetBuffer()->data(), 1057 it->GetBuffer()->size())); 1058 } 1059 1060 if (!WriteOutFile(pieces)) { 1061 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath(); 1062 1063 STLDeleteElements(&pieces); // Have to manually clean pieces. 1064 return false; 1065 } 1066 1067 STLDeleteElements(&pieces); // Have to manually clean pieces. 1068 return true; 1069 } 1070 1071 // Adds the given raw section to the builder. This will copy it. The caller 1072 // is responsible for deallocating their copy. 1073 void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bld) { 1074 other_builders_.push_back(bld); 1075 } 1076 1077 private: 1078 void SetISA(InstructionSet isa) { 1079 switch (isa) { 1080 case kArm: 1081 // Fall through. 1082 case kThumb2: { 1083 elf_header_.e_machine = EM_ARM; 1084 elf_header_.e_flags = EF_ARM_EABI_VER5; 1085 break; 1086 } 1087 case kArm64: { 1088 elf_header_.e_machine = EM_AARCH64; 1089 elf_header_.e_flags = 0; 1090 break; 1091 } 1092 case kX86: { 1093 elf_header_.e_machine = EM_386; 1094 elf_header_.e_flags = 0; 1095 break; 1096 } 1097 case kX86_64: { 1098 elf_header_.e_machine = EM_X86_64; 1099 elf_header_.e_flags = 0; 1100 break; 1101 } 1102 case kMips: { 1103 elf_header_.e_machine = EM_MIPS; 1104 elf_header_.e_flags = (EF_MIPS_NOREORDER | 1105 EF_MIPS_PIC | 1106 EF_MIPS_CPIC | 1107 EF_MIPS_ABI_O32 | 1108 EF_MIPS_ARCH_32R2); 1109 break; 1110 } 1111 default: { 1112 fatal_error_ = true; 1113 LOG(FATAL) << "Unknown instruction set: " << isa; 1114 break; 1115 } 1116 } 1117 } 1118 1119 void SetupEhdr() { 1120 memset(&elf_header_, 0, sizeof(elf_header_)); 1121 elf_header_.e_ident[EI_MAG0] = ELFMAG0; 1122 elf_header_.e_ident[EI_MAG1] = ELFMAG1; 1123 elf_header_.e_ident[EI_MAG2] = ELFMAG2; 1124 elf_header_.e_ident[EI_MAG3] = ELFMAG3; 1125 elf_header_.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr)) 1126 ? ELFCLASS32 : ELFCLASS64;; 1127 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB; 1128 elf_header_.e_ident[EI_VERSION] = EV_CURRENT; 1129 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX; 1130 elf_header_.e_ident[EI_ABIVERSION] = 0; 1131 elf_header_.e_type = ET_DYN; 1132 elf_header_.e_version = 1; 1133 elf_header_.e_entry = 0; 1134 elf_header_.e_ehsize = sizeof(Elf_Ehdr); 1135 elf_header_.e_phentsize = sizeof(Elf_Phdr); 1136 elf_header_.e_shentsize = sizeof(Elf_Shdr); 1137 elf_header_.e_phoff = sizeof(Elf_Ehdr); 1138 } 1139 1140 // Sets up a bunch of the required Dynamic Section entries. 1141 // Namely it will initialize all the mandatory ones that it can. 1142 // Specifically: 1143 // DT_HASH 1144 // DT_STRTAB 1145 // DT_SYMTAB 1146 // DT_SYMENT 1147 // 1148 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later. 1149 void SetupDynamic() { 1150 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_); 1151 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab()); 1152 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_); 1153 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym)); 1154 } 1155 1156 // Sets up the basic dynamic symbols that are needed, namely all those we 1157 // can know already. 1158 // 1159 // Specifically adds: 1160 // oatdata 1161 // oatexec 1162 // oatlastword 1163 void SetupRequiredSymbols() { 1164 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true, 1165 rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT); 1166 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true, 1167 text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT); 1168 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4, 1169 true, 4, STB_GLOBAL, STT_OBJECT); 1170 } 1171 1172 void AssignSectionStr(ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* builder, 1173 std::string* strtab) { 1174 builder->GetSection()->sh_name = strtab->size(); 1175 *strtab += builder->GetName(); 1176 *strtab += '\0'; 1177 if (debug_logging_) { 1178 LOG(INFO) << "adding section name \"" << builder->GetName() << "\" " 1179 << "to shstrtab at offset " << builder->GetSection()->sh_name; 1180 } 1181 } 1182 1183 1184 // Write each of the pieces out to the file. 1185 bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) { 1186 for (auto it = pieces.begin(); it != pieces.end(); ++it) { 1187 if (!(*it)->Write(elf_file_)) { 1188 return false; 1189 } 1190 } 1191 return true; 1192 } 1193 1194 bool IncludingDebugSymbols() const { 1195 return add_symbols_ && symtab_builder_.GetSize() > 1; 1196 } 1197 1198 CodeOutput* const oat_writer_; 1199 File* const elf_file_; 1200 const bool add_symbols_; 1201 const bool debug_logging_; 1202 1203 bool fatal_error_ = false; 1204 1205 // What phdr is. 1206 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr); 1207 enum : uint8_t { 1208 PH_PHDR = 0, 1209 PH_LOAD_R__ = 1, 1210 PH_LOAD_R_X = 2, 1211 PH_LOAD_RW_ = 3, 1212 PH_DYNAMIC = 4, 1213 PH_NUM = 5, 1214 }; 1215 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM; 1216 Elf_Phdr program_headers_[PH_NUM]; 1217 1218 Elf_Ehdr elf_header_; 1219 1220 Elf_Shdr null_hdr_; 1221 std::string shstrtab_; 1222 // The index of the current section being built. The first being 1. 1223 uint32_t section_index_; 1224 std::string dynstr_; 1225 uint32_t dynstr_soname_offset_; 1226 std::vector<const Elf_Shdr*> section_ptrs_; 1227 std::vector<Elf_Word> hash_; 1228 1229 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> text_builder_; 1230 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> rodata_builder_; 1231 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> dynsym_builder_; 1232 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> symtab_builder_; 1233 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> hash_builder_; 1234 ElfDynamicBuilder<Elf_Word, Elf_Sword, Elf_Dyn, Elf_Shdr> dynamic_builder_; 1235 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> shstrtab_builder_; 1236 std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>> other_builders_; 1237 1238 DISALLOW_COPY_AND_ASSIGN(ElfBuilder); 1239}; 1240 1241} // namespace art 1242 1243#endif // ART_COMPILER_ELF_BUILDER_H_ 1244