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