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