elf_builder.h revision 527c9c71f0c6e2f9943ac028e7c050500699a44b
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(&section_, 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 &section_;
53  }
54
55  Elf_Shdr* GetSection() {
56    return &section_;
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 .eh_frame .eh_frame_hdr .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    // | Elf_Phdr EH_FRAME R     | .eh_frame_hdr
593    // +-------------------------+
594    // | .dynsym                 |
595    // | Elf_Sym  STN_UNDEF      |
596    // | Elf_Sym  oatdata        |
597    // | Elf_Sym  oatexec        |
598    // | Elf_Sym  oatlastword    |
599    // | Elf_Sym  oatbss         | (Optional)
600    // | Elf_Sym  oatbsslastword | (Optional)
601    // +-------------------------+
602    // | .dynstr                 |
603    // | \0                      |
604    // | oatdata\0               |
605    // | oatexec\0               |
606    // | oatlastword\0           |
607    // | boot.oat\0              |
608    // +-------------------------+
609    // | .hash                   |
610    // | Elf_Word nbucket = b    |
611    // | Elf_Word nchain  = c    |
612    // | Elf_Word bucket[0]      |
613    // |         ...             |
614    // | Elf_Word bucket[b - 1]  |
615    // | Elf_Word chain[0]       |
616    // |         ...             |
617    // | Elf_Word chain[c - 1]   |
618    // +-------------------------+
619    // | .eh_frame               |  (Optional)
620    // +-------------------------+
621    // | .eh_frame_hdr           |  (Optional)
622    // +-------------------------+
623    // | .rodata                 |
624    // | oatdata..oatexec-4      |
625    // +-------------------------+
626    // | .text                   |
627    // | oatexec..oatlastword    |
628    // +-------------------------+
629    // | .dynamic                |
630    // | Elf_Dyn DT_SONAME       |
631    // | Elf_Dyn DT_HASH         |
632    // | Elf_Dyn DT_SYMTAB       |
633    // | Elf_Dyn DT_SYMENT       |
634    // | Elf_Dyn DT_STRTAB       |
635    // | Elf_Dyn DT_STRSZ        |
636    // | Elf_Dyn DT_NULL         |
637    // +-------------------------+  (Optional)
638    // | .strtab                 |  (Optional)
639    // | program symbol names    |  (Optional)
640    // +-------------------------+  (Optional)
641    // | .symtab                 |  (Optional)
642    // | program symbols         |  (Optional)
643    // +-------------------------+
644    // | .shstrtab               |
645    // | \0                      |
646    // | .dynamic\0              |
647    // | .dynsym\0               |
648    // | .dynstr\0               |
649    // | .hash\0                 |
650    // | .rodata\0               |
651    // | .text\0                 |
652    // | .bss\0                  |  (Optional)
653    // | .shstrtab\0             |
654    // | .symtab\0               |  (Optional)
655    // | .strtab\0               |  (Optional)
656    // | .eh_frame\0             |  (Optional)
657    // | .eh_frame_hdr\0         |  (Optional)
658    // | .debug_info\0           |  (Optional)
659    // | .debug_abbrev\0         |  (Optional)
660    // | .debug_str\0            |  (Optional)
661    // | .debug_line\0           |  (Optional)
662    // +-------------------------+  (Optional)
663    // | .debug_info             |  (Optional)
664    // +-------------------------+  (Optional)
665    // | .debug_abbrev           |  (Optional)
666    // +-------------------------+  (Optional)
667    // | .debug_str              |  (Optional)
668    // +-------------------------+  (Optional)
669    // | .debug_line             |  (Optional)
670    // +-------------------------+  (Optional)
671    // | Elf_Shdr NULL           |
672    // | Elf_Shdr .dynsym        |
673    // | Elf_Shdr .dynstr        |
674    // | Elf_Shdr .hash          |
675    // | Elf_Shdr .rodata        |
676    // | Elf_Shdr .text          |
677    // | Elf_Shdr .bss           |  (Optional)
678    // | Elf_Shdr .dynamic       |
679    // | Elf_Shdr .shstrtab      |
680    // | Elf_Shdr .eh_frame      |  (Optional)
681    // | Elf_Shdr .eh_frame_hdr  |  (Optional)
682    // | Elf_Shdr .debug_info    |  (Optional)
683    // | Elf_Shdr .debug_abbrev  |  (Optional)
684    // | Elf_Shdr .debug_str     |  (Optional)
685    // | Elf_Shdr .debug_line    |  (Optional)
686    // +-------------------------+
687
688    if (fatal_error_) {
689      return false;
690    }
691    // Step 1. Figure out all the offsets.
692
693    if (debug_logging_) {
694      LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
695      LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
696    }
697
698    memset(&program_headers_, 0, sizeof(program_headers_));
699    program_headers_[PH_PHDR].p_type    = PT_PHDR;
700    program_headers_[PH_PHDR].p_offset  = PHDR_OFFSET;
701    program_headers_[PH_PHDR].p_vaddr   = PHDR_OFFSET;
702    program_headers_[PH_PHDR].p_paddr   = PHDR_OFFSET;
703    program_headers_[PH_PHDR].p_filesz  = sizeof(program_headers_);
704    program_headers_[PH_PHDR].p_memsz   = sizeof(program_headers_);
705    program_headers_[PH_PHDR].p_flags   = PF_R;
706    program_headers_[PH_PHDR].p_align   = sizeof(Elf_Word);
707
708    program_headers_[PH_LOAD_R__].p_type    = PT_LOAD;
709    program_headers_[PH_LOAD_R__].p_offset  = 0;
710    program_headers_[PH_LOAD_R__].p_vaddr   = 0;
711    program_headers_[PH_LOAD_R__].p_paddr   = 0;
712    program_headers_[PH_LOAD_R__].p_flags   = PF_R;
713
714    program_headers_[PH_LOAD_R_X].p_type    = PT_LOAD;
715    program_headers_[PH_LOAD_R_X].p_flags   = PF_R | PF_X;
716
717    program_headers_[PH_LOAD_RW_BSS].p_type    = PT_LOAD;
718    program_headers_[PH_LOAD_RW_BSS].p_flags   = PF_R | PF_W;
719
720    program_headers_[PH_LOAD_RW_DYNAMIC].p_type    = PT_LOAD;
721    program_headers_[PH_LOAD_RW_DYNAMIC].p_flags   = PF_R | PF_W;
722
723    program_headers_[PH_DYNAMIC].p_type    = PT_DYNAMIC;
724    program_headers_[PH_DYNAMIC].p_flags   = PF_R | PF_W;
725
726    program_headers_[PH_EH_FRAME_HDR].p_type = PT_NULL;
727    program_headers_[PH_EH_FRAME_HDR].p_flags = PF_R;
728
729    // Get the dynstr string.
730    dynstr_ = dynsym_builder_.GenerateStrtab();
731
732    // Add the SONAME to the dynstr.
733    dynstr_soname_offset_ = dynstr_.size();
734    std::string file_name(elf_file_->GetPath());
735    size_t directory_separator_pos = file_name.rfind('/');
736    if (directory_separator_pos != std::string::npos) {
737      file_name = file_name.substr(directory_separator_pos + 1);
738    }
739    dynstr_ += file_name;
740    dynstr_ += '\0';
741    if (debug_logging_) {
742      LOG(INFO) << "dynstr size (bytes)   =" << dynstr_.size()
743                << std::hex << " " << dynstr_.size();
744      LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
745                << std::hex << " " << dynsym_builder_.GetSize();
746    }
747
748    // Get the section header string table.
749    shstrtab_ += '\0';
750
751    // Setup sym_undef
752    memset(&null_hdr_, 0, sizeof(null_hdr_));
753    null_hdr_.sh_type = SHT_NULL;
754    null_hdr_.sh_link = SHN_UNDEF;
755    section_ptrs_.push_back(&null_hdr_);
756
757    section_index_ = 1;
758
759    // setup .dynsym
760    section_ptrs_.push_back(dynsym_builder_.GetSection());
761    AssignSectionStr(&dynsym_builder_, &shstrtab_);
762    dynsym_builder_.SetSectionIndex(section_index_);
763    section_index_++;
764
765    // Setup .dynstr
766    section_ptrs_.push_back(dynsym_builder_.GetStrTab()->GetSection());
767    AssignSectionStr(dynsym_builder_.GetStrTab(), &shstrtab_);
768    dynsym_builder_.GetStrTab()->SetSectionIndex(section_index_);
769    section_index_++;
770
771    // Setup .hash
772    section_ptrs_.push_back(hash_builder_.GetSection());
773    AssignSectionStr(&hash_builder_, &shstrtab_);
774    hash_builder_.SetSectionIndex(section_index_);
775    section_index_++;
776
777    // Setup .rodata
778    section_ptrs_.push_back(rodata_builder_.GetSection());
779    AssignSectionStr(&rodata_builder_, &shstrtab_);
780    rodata_builder_.SetSectionIndex(section_index_);
781    section_index_++;
782
783    // Setup .text
784    section_ptrs_.push_back(text_builder_.GetSection());
785    AssignSectionStr(&text_builder_, &shstrtab_);
786    text_builder_.SetSectionIndex(section_index_);
787    section_index_++;
788
789    // Setup .bss
790    if (bss_builder_.GetSize() != 0u) {
791      section_ptrs_.push_back(bss_builder_.GetSection());
792      AssignSectionStr(&bss_builder_, &shstrtab_);
793      bss_builder_.SetSectionIndex(section_index_);
794      section_index_++;
795    }
796
797    // Setup .dynamic
798    section_ptrs_.push_back(dynamic_builder_.GetSection());
799    AssignSectionStr(&dynamic_builder_, &shstrtab_);
800    dynamic_builder_.SetSectionIndex(section_index_);
801    section_index_++;
802
803    // Fill in the hash section.
804    hash_ = dynsym_builder_.GenerateHashContents();
805
806    if (debug_logging_) {
807      LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
808                << std::hex << " " << hash_.size() * sizeof(Elf_Word);
809    }
810
811    Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
812
813    // Get the layout in the sections.
814    //
815    // Get the layout of the dynsym section.
816    dynsym_builder_.GetSection()->sh_offset =
817        RoundUp(base_offset, dynsym_builder_.GetSection()->sh_addralign);
818    dynsym_builder_.GetSection()->sh_addr = dynsym_builder_.GetSection()->sh_offset;
819    dynsym_builder_.GetSection()->sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
820    dynsym_builder_.GetSection()->sh_link = dynsym_builder_.GetLink();
821
822    // Get the layout of the dynstr section.
823    dynsym_builder_.GetStrTab()->GetSection()->sh_offset =
824        NextOffset<Elf_Word, Elf_Shdr>(*dynsym_builder_.GetStrTab()->GetSection(),
825                                       *dynsym_builder_.GetSection());
826    dynsym_builder_.GetStrTab()->GetSection()->sh_addr =
827        dynsym_builder_.GetStrTab()->GetSection()->sh_offset;
828    dynsym_builder_.GetStrTab()->GetSection()->sh_size = dynstr_.size();
829    dynsym_builder_.GetStrTab()->GetSection()->sh_link = dynsym_builder_.GetStrTab()->GetLink();
830
831    // Get the layout of the hash section
832    hash_builder_.GetSection()->sh_offset =
833        NextOffset<Elf_Word, Elf_Shdr>(*hash_builder_.GetSection(),
834                                       *dynsym_builder_.GetStrTab()->GetSection());
835    hash_builder_.GetSection()->sh_addr = hash_builder_.GetSection()->sh_offset;
836    hash_builder_.GetSection()->sh_size = hash_.size() * sizeof(Elf_Word);
837    hash_builder_.GetSection()->sh_link = hash_builder_.GetLink();
838
839    // Get the layout of the extra sections with SHF_ALLOC flag.
840    // This will deal with .eh_frame and .eh_frame_hdr.
841    // .eh_frame contains relative pointers to .text which we
842    // want to fixup between the calls to Init() and Write().
843    // Therefore we handle those sections here as opposed to Write().
844    // It also has the nice side effect of including .eh_frame
845    // with the rest of LOAD_R segment.  It must come before .rodata
846    // because .rodata and .text must be next to each other.
847    Elf_Shdr* prev = hash_builder_.GetSection();
848    for (auto* it : other_builders_) {
849      if ((it->GetSection()->sh_flags & SHF_ALLOC) != 0) {
850        it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
851        it->GetSection()->sh_addr = it->GetSection()->sh_offset;
852        it->GetSection()->sh_size = it->GetBuffer()->size();
853        it->GetSection()->sh_link = it->GetLink();
854        prev = it->GetSection();
855      }
856    }
857    // If the sections exist, check that they have been handled.
858    const auto* eh_frame = FindRawSection(".eh_frame");
859    if (eh_frame != nullptr) {
860      DCHECK_NE(eh_frame->GetSection()->sh_offset, 0u);
861    }
862    const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr");
863    if (eh_frame_hdr != nullptr) {
864      DCHECK_NE(eh_frame_hdr->GetSection()->sh_offset, 0u);
865    }
866
867    // Get the layout of the rodata section.
868    rodata_builder_.GetSection()->sh_offset =
869        NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(), *prev);
870    rodata_builder_.GetSection()->sh_addr = rodata_builder_.GetSection()->sh_offset;
871    rodata_builder_.GetSection()->sh_size = rodata_builder_.GetSize();
872    rodata_builder_.GetSection()->sh_link = rodata_builder_.GetLink();
873
874    // Get the layout of the text section.
875    text_builder_.GetSection()->sh_offset =
876        NextOffset<Elf_Word, Elf_Shdr>(*text_builder_.GetSection(),
877                                       *rodata_builder_.GetSection());
878    text_builder_.GetSection()->sh_addr = text_builder_.GetSection()->sh_offset;
879    text_builder_.GetSection()->sh_size = text_builder_.GetSize();
880    text_builder_.GetSection()->sh_link = text_builder_.GetLink();
881    CHECK_ALIGNED(rodata_builder_.GetSection()->sh_offset +
882                  rodata_builder_.GetSection()->sh_size, kPageSize);
883
884    // Get the layout of the .bss section.
885    bss_builder_.GetSection()->sh_offset =
886        NextOffset<Elf_Word, Elf_Shdr>(*bss_builder_.GetSection(),
887                                       *text_builder_.GetSection());
888    bss_builder_.GetSection()->sh_addr = bss_builder_.GetSection()->sh_offset;
889    bss_builder_.GetSection()->sh_size = bss_builder_.GetSize();
890    bss_builder_.GetSection()->sh_link = bss_builder_.GetLink();
891
892    // Get the layout of the dynamic section.
893    CHECK(IsAlignedParam(bss_builder_.GetSection()->sh_offset,
894                         dynamic_builder_.GetSection()->sh_addralign));
895    dynamic_builder_.GetSection()->sh_offset = bss_builder_.GetSection()->sh_offset;
896    dynamic_builder_.GetSection()->sh_addr =
897        NextOffset<Elf_Word, Elf_Shdr>(*dynamic_builder_.GetSection(), *bss_builder_.GetSection());
898    dynamic_builder_.GetSection()->sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
899    dynamic_builder_.GetSection()->sh_link = dynamic_builder_.GetLink();
900
901    if (debug_logging_) {
902      LOG(INFO) << "dynsym off=" << dynsym_builder_.GetSection()->sh_offset
903                << " dynsym size=" << dynsym_builder_.GetSection()->sh_size;
904      LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->GetSection()->sh_offset
905                << " dynstr size=" << dynsym_builder_.GetStrTab()->GetSection()->sh_size;
906      LOG(INFO) << "hash off=" << hash_builder_.GetSection()->sh_offset
907                << " hash size=" << hash_builder_.GetSection()->sh_size;
908      LOG(INFO) << "rodata off=" << rodata_builder_.GetSection()->sh_offset
909                << " rodata size=" << rodata_builder_.GetSection()->sh_size;
910      LOG(INFO) << "text off=" << text_builder_.GetSection()->sh_offset
911                << " text size=" << text_builder_.GetSection()->sh_size;
912      LOG(INFO) << "dynamic off=" << dynamic_builder_.GetSection()->sh_offset
913                << " dynamic size=" << dynamic_builder_.GetSection()->sh_size;
914    }
915
916    return true;
917  }
918
919  bool Write() {
920    std::vector<ElfFilePiece<Elf_Word>*> pieces;
921    Elf_Shdr* prev = dynamic_builder_.GetSection();
922    std::string strtab;
923
924    if (IncludingDebugSymbols()) {
925      // Setup .symtab
926      section_ptrs_.push_back(symtab_builder_.GetSection());
927      AssignSectionStr(&symtab_builder_, &shstrtab_);
928      symtab_builder_.SetSectionIndex(section_index_);
929      section_index_++;
930
931      // Setup .strtab
932      section_ptrs_.push_back(symtab_builder_.GetStrTab()->GetSection());
933      AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
934      symtab_builder_.GetStrTab()->SetSectionIndex(section_index_);
935      section_index_++;
936
937      strtab = symtab_builder_.GenerateStrtab();
938      if (debug_logging_) {
939        LOG(INFO) << "strtab size (bytes)    =" << strtab.size()
940                  << std::hex << " " << strtab.size();
941        LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
942                  << std::hex << " " << symtab_builder_.GetSize();
943      }
944    }
945
946    // Setup all the other sections.
947    for (auto* builder : other_builders_) {
948      section_ptrs_.push_back(builder->GetSection());
949      AssignSectionStr(builder, &shstrtab_);
950      builder->SetSectionIndex(section_index_);
951      section_index_++;
952    }
953
954    // Setup shstrtab
955    section_ptrs_.push_back(shstrtab_builder_.GetSection());
956    AssignSectionStr(&shstrtab_builder_, &shstrtab_);
957    shstrtab_builder_.SetSectionIndex(section_index_);
958    section_index_++;
959
960    if (debug_logging_) {
961      LOG(INFO) << ".shstrtab size    (bytes)   =" << shstrtab_.size()
962                << std::hex << " " << shstrtab_.size();
963      LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
964                << std::hex << " " << section_ptrs_.size();
965    }
966
967    if (IncludingDebugSymbols()) {
968      // Get the layout of the symtab section.
969      symtab_builder_.GetSection()->sh_offset =
970          NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetSection(),
971                                         *dynamic_builder_.GetSection());
972      symtab_builder_.GetSection()->sh_addr = 0;
973      // Add to leave space for the null symbol.
974      symtab_builder_.GetSection()->sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
975      symtab_builder_.GetSection()->sh_link = symtab_builder_.GetLink();
976
977      // Get the layout of the dynstr section.
978      symtab_builder_.GetStrTab()->GetSection()->sh_offset =
979          NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetStrTab()->GetSection(),
980                                         *symtab_builder_.GetSection());
981      symtab_builder_.GetStrTab()->GetSection()->sh_addr = 0;
982      symtab_builder_.GetStrTab()->GetSection()->sh_size = strtab.size();
983      symtab_builder_.GetStrTab()->GetSection()->sh_link = symtab_builder_.GetStrTab()->GetLink();
984
985      prev = symtab_builder_.GetStrTab()->GetSection();
986      if (debug_logging_) {
987        LOG(INFO) << "symtab off=" << symtab_builder_.GetSection()->sh_offset
988                  << " symtab size=" << symtab_builder_.GetSection()->sh_size;
989        LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->GetSection()->sh_offset
990                  << " strtab size=" << symtab_builder_.GetStrTab()->GetSection()->sh_size;
991      }
992    }
993
994    // Get the layout of the extra sections without SHF_ALLOC flag.
995    // (This will deal with the debug sections if they are there)
996    for (auto* it : other_builders_) {
997      if ((it->GetSection()->sh_flags & SHF_ALLOC) == 0) {
998        it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
999        it->GetSection()->sh_addr = 0;
1000        it->GetSection()->sh_size = it->GetBuffer()->size();
1001        it->GetSection()->sh_link = it->GetLink();
1002
1003        // We postpone adding an ElfFilePiece to keep the order in "pieces."
1004
1005        prev = it->GetSection();
1006        if (debug_logging_) {
1007          LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset
1008                    << " size=" << it->GetSection()->sh_size;
1009        }
1010      }
1011    }
1012
1013    // Get the layout of the shstrtab section
1014    shstrtab_builder_.GetSection()->sh_offset =
1015        NextOffset<Elf_Word, Elf_Shdr>(*shstrtab_builder_.GetSection(), *prev);
1016    shstrtab_builder_.GetSection()->sh_addr = 0;
1017    shstrtab_builder_.GetSection()->sh_size = shstrtab_.size();
1018    shstrtab_builder_.GetSection()->sh_link = shstrtab_builder_.GetLink();
1019    if (debug_logging_) {
1020        LOG(INFO) << "shstrtab off=" << shstrtab_builder_.GetSection()->sh_offset
1021                  << " shstrtab size=" << shstrtab_builder_.GetSection()->sh_size;
1022    }
1023
1024    // The section list comes after come after.
1025    Elf_Word sections_offset = RoundUp(
1026        shstrtab_builder_.GetSection()->sh_offset + shstrtab_builder_.GetSection()->sh_size,
1027        sizeof(Elf_Word));
1028
1029    // Setup the actual symbol arrays.
1030    std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
1031    CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.GetSection()->sh_size);
1032    std::vector<Elf_Sym> symtab;
1033    if (IncludingDebugSymbols()) {
1034      symtab = symtab_builder_.GenerateSymtab();
1035      CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.GetSection()->sh_size);
1036    }
1037
1038    // Setup the dynamic section.
1039    // This will add the 2 values we cannot know until now time, namely the size
1040    // and the soname_offset.
1041    std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
1042                                                                  dynstr_soname_offset_);
1043    CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.GetSection()->sh_size);
1044
1045    // Finish setup of the program headers now that we know the layout of the
1046    // whole file.
1047    Elf_Word load_r_size =
1048        rodata_builder_.GetSection()->sh_offset + rodata_builder_.GetSection()->sh_size;
1049    program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
1050    program_headers_[PH_LOAD_R__].p_memsz =  load_r_size;
1051    program_headers_[PH_LOAD_R__].p_align =  rodata_builder_.GetSection()->sh_addralign;
1052
1053    Elf_Word load_rx_size = text_builder_.GetSection()->sh_size;
1054    program_headers_[PH_LOAD_R_X].p_offset = text_builder_.GetSection()->sh_offset;
1055    program_headers_[PH_LOAD_R_X].p_vaddr  = text_builder_.GetSection()->sh_offset;
1056    program_headers_[PH_LOAD_R_X].p_paddr  = text_builder_.GetSection()->sh_offset;
1057    program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
1058    program_headers_[PH_LOAD_R_X].p_memsz  = load_rx_size;
1059    program_headers_[PH_LOAD_R_X].p_align  = text_builder_.GetSection()->sh_addralign;
1060
1061    program_headers_[PH_LOAD_RW_BSS].p_offset = bss_builder_.GetSection()->sh_offset;
1062    program_headers_[PH_LOAD_RW_BSS].p_vaddr  = bss_builder_.GetSection()->sh_offset;
1063    program_headers_[PH_LOAD_RW_BSS].p_paddr  = bss_builder_.GetSection()->sh_offset;
1064    program_headers_[PH_LOAD_RW_BSS].p_filesz = 0;
1065    program_headers_[PH_LOAD_RW_BSS].p_memsz  = bss_builder_.GetSection()->sh_size;
1066    program_headers_[PH_LOAD_RW_BSS].p_align  = bss_builder_.GetSection()->sh_addralign;
1067
1068    program_headers_[PH_LOAD_RW_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
1069    program_headers_[PH_LOAD_RW_DYNAMIC].p_vaddr  = dynamic_builder_.GetSection()->sh_addr;
1070    program_headers_[PH_LOAD_RW_DYNAMIC].p_paddr  = dynamic_builder_.GetSection()->sh_addr;
1071    program_headers_[PH_LOAD_RW_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1072    program_headers_[PH_LOAD_RW_DYNAMIC].p_memsz  = dynamic_builder_.GetSection()->sh_size;
1073    program_headers_[PH_LOAD_RW_DYNAMIC].p_align  = dynamic_builder_.GetSection()->sh_addralign;
1074
1075    program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
1076    program_headers_[PH_DYNAMIC].p_vaddr  = dynamic_builder_.GetSection()->sh_addr;
1077    program_headers_[PH_DYNAMIC].p_paddr  = dynamic_builder_.GetSection()->sh_addr;
1078    program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1079    program_headers_[PH_DYNAMIC].p_memsz  = dynamic_builder_.GetSection()->sh_size;
1080    program_headers_[PH_DYNAMIC].p_align  = dynamic_builder_.GetSection()->sh_addralign;
1081
1082    const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr");
1083    if (eh_frame_hdr != nullptr) {
1084      const auto* eh_frame = FindRawSection(".eh_frame");
1085      // Check layout:
1086      // 1) eh_frame is before eh_frame_hdr.
1087      // 2) There's no gap.
1088      CHECK(eh_frame != nullptr);
1089      CHECK_LE(eh_frame->GetSection()->sh_offset, eh_frame_hdr->GetSection()->sh_offset);
1090      CHECK_EQ(eh_frame->GetSection()->sh_offset + eh_frame->GetSection()->sh_size,
1091               eh_frame_hdr->GetSection()->sh_offset);
1092
1093      program_headers_[PH_EH_FRAME_HDR].p_type   = PT_GNU_EH_FRAME;
1094      program_headers_[PH_EH_FRAME_HDR].p_offset = eh_frame_hdr->GetSection()->sh_offset;
1095      program_headers_[PH_EH_FRAME_HDR].p_vaddr  = eh_frame_hdr->GetSection()->sh_addr;
1096      program_headers_[PH_EH_FRAME_HDR].p_paddr  = eh_frame_hdr->GetSection()->sh_addr;
1097      program_headers_[PH_EH_FRAME_HDR].p_filesz = eh_frame_hdr->GetSection()->sh_size;
1098      program_headers_[PH_EH_FRAME_HDR].p_memsz  = eh_frame_hdr->GetSection()->sh_size;
1099      program_headers_[PH_EH_FRAME_HDR].p_align  = eh_frame_hdr->GetSection()->sh_addralign;
1100    }
1101
1102    // Finish setup of the Ehdr values.
1103    elf_header_.e_phoff = PHDR_OFFSET;
1104    elf_header_.e_shoff = sections_offset;
1105    elf_header_.e_phnum = (bss_builder_.GetSection()->sh_size != 0u) ? PH_NUM : PH_NUM - 1;
1106    elf_header_.e_shnum = section_ptrs_.size();
1107    elf_header_.e_shstrndx = shstrtab_builder_.GetSectionIndex();
1108
1109    // Add the rest of the pieces to the list.
1110    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_,
1111                                                      sizeof(elf_header_)));
1112    if (bss_builder_.GetSection()->sh_size != 0u) {
1113      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1114                                                        &program_headers_[0],
1115                                                        elf_header_.e_phnum * sizeof(Elf_Phdr)));
1116    } else {
1117      // Skip PH_LOAD_RW_BSS.
1118      Elf_Word part1_size = PH_LOAD_RW_BSS * sizeof(Elf_Phdr);
1119      Elf_Word part2_size = (PH_NUM - PH_LOAD_RW_BSS - 1) * sizeof(Elf_Phdr);
1120      CHECK_EQ(part1_size + part2_size, elf_header_.e_phnum * sizeof(Elf_Phdr));
1121      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1122                                                        &program_headers_[0], part1_size));
1123      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers part 2",
1124                                                        PHDR_OFFSET + part1_size,
1125                                                        &program_headers_[PH_LOAD_RW_BSS + 1],
1126                                                        part2_size));
1127    }
1128    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic",
1129                                                      dynamic_builder_.GetSection()->sh_offset,
1130                                                      dynamic.data(),
1131                                                      dynamic_builder_.GetSection()->sh_size));
1132    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.GetSection()->sh_offset,
1133                                                      dynsym.data(),
1134                                                      dynsym.size() * sizeof(Elf_Sym)));
1135    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr",
1136                                                    dynsym_builder_.GetStrTab()->GetSection()->sh_offset,
1137                                                    dynstr_.c_str(), dynstr_.size()));
1138    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.GetSection()->sh_offset,
1139                                                      hash_.data(),
1140                                                      hash_.size() * sizeof(Elf_Word)));
1141    pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.GetSection()->sh_offset,
1142                                                      oat_writer_));
1143    pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.GetSection()->sh_offset,
1144                                                       oat_writer_));
1145    if (IncludingDebugSymbols()) {
1146      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab",
1147                                                        symtab_builder_.GetSection()->sh_offset,
1148                                                        symtab.data(),
1149                                                        symtab.size() * sizeof(Elf_Sym)));
1150      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab",
1151                                                    symtab_builder_.GetStrTab()->GetSection()->sh_offset,
1152                                                    strtab.c_str(), strtab.size()));
1153    }
1154    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab",
1155                                                      shstrtab_builder_.GetSection()->sh_offset,
1156                                                      &shstrtab_[0], shstrtab_.size()));
1157    for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
1158      // Just add all the sections in induvidually since they are all over the
1159      // place on the heap/stack.
1160      Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
1161      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off,
1162                                                        section_ptrs_[i], sizeof(Elf_Shdr)));
1163    }
1164
1165    // Postponed debug info.
1166    for (auto* it : other_builders_) {
1167      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->GetName(), it->GetSection()->sh_offset,
1168                                                        it->GetBuffer()->data(),
1169                                                        it->GetBuffer()->size()));
1170    }
1171
1172    if (!WriteOutFile(pieces)) {
1173      LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
1174
1175      STLDeleteElements(&pieces);  // Have to manually clean pieces.
1176      return false;
1177    }
1178
1179    STLDeleteElements(&pieces);  // Have to manually clean pieces.
1180    return true;
1181  }
1182
1183  // Adds the given raw section to the builder.  It does not take ownership.
1184  void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* bld) {
1185    other_builders_.push_back(bld);
1186  }
1187
1188  const ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>*
1189  FindRawSection(const char* name) {
1190    for (const auto* other_builder : other_builders_) {
1191      if (other_builder->GetName() == name) {
1192        return other_builder;
1193      }
1194    }
1195    return nullptr;
1196  }
1197
1198 private:
1199  void SetISA(InstructionSet isa) {
1200    switch (isa) {
1201      case kArm:
1202        // Fall through.
1203      case kThumb2: {
1204        elf_header_.e_machine = EM_ARM;
1205        elf_header_.e_flags = EF_ARM_EABI_VER5;
1206        break;
1207      }
1208      case kArm64: {
1209        elf_header_.e_machine = EM_AARCH64;
1210        elf_header_.e_flags = 0;
1211        break;
1212      }
1213      case kX86: {
1214        elf_header_.e_machine = EM_386;
1215        elf_header_.e_flags = 0;
1216        break;
1217      }
1218      case kX86_64: {
1219        elf_header_.e_machine = EM_X86_64;
1220        elf_header_.e_flags = 0;
1221        break;
1222      }
1223      case kMips: {
1224        elf_header_.e_machine = EM_MIPS;
1225        elf_header_.e_flags = (EF_MIPS_NOREORDER |
1226                               EF_MIPS_PIC       |
1227                               EF_MIPS_CPIC      |
1228                               EF_MIPS_ABI_O32   |
1229                               EF_MIPS_ARCH_32R2);
1230        break;
1231      }
1232      case kMips64: {
1233        elf_header_.e_machine = EM_MIPS;
1234        elf_header_.e_flags = (EF_MIPS_NOREORDER |
1235                               EF_MIPS_PIC       |
1236                               EF_MIPS_CPIC      |
1237                               EF_MIPS_ARCH_64R6);
1238        break;
1239      }
1240      default: {
1241        fatal_error_ = true;
1242        LOG(FATAL) << "Unknown instruction set: " << isa;
1243        break;
1244      }
1245    }
1246  }
1247
1248  void SetupEhdr() {
1249    memset(&elf_header_, 0, sizeof(elf_header_));
1250    elf_header_.e_ident[EI_MAG0]       = ELFMAG0;
1251    elf_header_.e_ident[EI_MAG1]       = ELFMAG1;
1252    elf_header_.e_ident[EI_MAG2]       = ELFMAG2;
1253    elf_header_.e_ident[EI_MAG3]       = ELFMAG3;
1254    elf_header_.e_ident[EI_CLASS]      = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
1255                                         ? ELFCLASS32 : ELFCLASS64;;
1256    elf_header_.e_ident[EI_DATA]       = ELFDATA2LSB;
1257    elf_header_.e_ident[EI_VERSION]    = EV_CURRENT;
1258    elf_header_.e_ident[EI_OSABI]      = ELFOSABI_LINUX;
1259    elf_header_.e_ident[EI_ABIVERSION] = 0;
1260    elf_header_.e_type = ET_DYN;
1261    elf_header_.e_version = 1;
1262    elf_header_.e_entry = 0;
1263    elf_header_.e_ehsize = sizeof(Elf_Ehdr);
1264    elf_header_.e_phentsize = sizeof(Elf_Phdr);
1265    elf_header_.e_shentsize = sizeof(Elf_Shdr);
1266    elf_header_.e_phoff = sizeof(Elf_Ehdr);
1267  }
1268
1269  // Sets up a bunch of the required Dynamic Section entries.
1270  // Namely it will initialize all the mandatory ones that it can.
1271  // Specifically:
1272  // DT_HASH
1273  // DT_STRTAB
1274  // DT_SYMTAB
1275  // DT_SYMENT
1276  //
1277  // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
1278  void SetupDynamic() {
1279    dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
1280    dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1281    dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1282    dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1283  }
1284
1285  // Sets up the basic dynamic symbols that are needed, namely all those we
1286  // can know already.
1287  //
1288  // Specifically adds:
1289  // oatdata
1290  // oatexec
1291  // oatlastword
1292  void SetupRequiredSymbols() {
1293    dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1294                              rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1295    dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1296                              text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1297    dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1298                              true, 4, STB_GLOBAL, STT_OBJECT);
1299    if (bss_builder_.GetSize() != 0u) {
1300      dynsym_builder_.AddSymbol("oatbss", &bss_builder_, 0, true,
1301                                bss_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1302      dynsym_builder_.AddSymbol("oatbsslastword", &bss_builder_, bss_builder_.GetSize() - 4,
1303                                true, 4, STB_GLOBAL, STT_OBJECT);
1304    }
1305  }
1306
1307  void AssignSectionStr(ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* builder,
1308                        std::string* strtab) {
1309    builder->GetSection()->sh_name = strtab->size();
1310    *strtab += builder->GetName();
1311    *strtab += '\0';
1312    if (debug_logging_) {
1313      LOG(INFO) << "adding section name \"" << builder->GetName() << "\" "
1314                << "to shstrtab at offset " << builder->GetSection()->sh_name;
1315    }
1316  }
1317
1318
1319  // Write each of the pieces out to the file.
1320  bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) {
1321    for (auto it = pieces.begin(); it != pieces.end(); ++it) {
1322      if (!(*it)->Write(elf_file_)) {
1323        return false;
1324      }
1325    }
1326    return true;
1327  }
1328
1329  bool IncludingDebugSymbols() const {
1330    return add_symbols_ && symtab_builder_.GetSize() > 1;
1331  }
1332
1333  CodeOutput* const oat_writer_;
1334  File* const elf_file_;
1335  const bool add_symbols_;
1336  const bool debug_logging_;
1337
1338  bool fatal_error_ = false;
1339
1340  // What phdr is.
1341  static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
1342  enum : uint8_t {
1343    PH_PHDR             = 0,
1344    PH_LOAD_R__         = 1,
1345    PH_LOAD_R_X         = 2,
1346    PH_LOAD_RW_BSS      = 3,
1347    PH_LOAD_RW_DYNAMIC  = 4,
1348    PH_DYNAMIC          = 5,
1349    PH_EH_FRAME_HDR     = 6,
1350    PH_NUM              = 7,
1351  };
1352  static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
1353  Elf_Phdr program_headers_[PH_NUM];
1354
1355  Elf_Ehdr elf_header_;
1356
1357  Elf_Shdr null_hdr_;
1358  std::string shstrtab_;
1359  // The index of the current section being built. The first being 1.
1360  uint32_t section_index_;
1361  std::string dynstr_;
1362  uint32_t dynstr_soname_offset_;
1363  std::vector<const Elf_Shdr*> section_ptrs_;
1364  std::vector<Elf_Word> hash_;
1365
1366  ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> text_builder_;
1367  ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> rodata_builder_;
1368  ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bss_builder_;
1369  ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> dynsym_builder_;
1370  ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> symtab_builder_;
1371  ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> hash_builder_;
1372  ElfDynamicBuilder<Elf_Word, Elf_Sword, Elf_Dyn, Elf_Shdr> dynamic_builder_;
1373  ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> shstrtab_builder_;
1374  std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>*> other_builders_;
1375
1376  DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
1377};
1378
1379}  // namespace art
1380
1381#endif  // ART_COMPILER_ELF_BUILDER_H_
1382