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