elf_builder.h revision 0c5bbc11a6af7b4f83b3929bc99de690635095c0
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
29class CodeOutput {
30 public:
31  virtual void SetCodeOffset(size_t offset) = 0;
32  virtual bool Write(OutputStream* out) = 0;
33  virtual ~CodeOutput() {}
34};
35
36template <typename ElfTypes>
37class ElfBuilder FINAL {
38 public:
39  using Elf_Addr = typename ElfTypes::Addr;
40  using Elf_Word = typename ElfTypes::Word;
41  using Elf_Sword = typename ElfTypes::Sword;
42  using Elf_Ehdr = typename ElfTypes::Ehdr;
43  using Elf_Shdr = typename ElfTypes::Shdr;
44  using Elf_Sym = typename ElfTypes::Sym;
45  using Elf_Phdr = typename ElfTypes::Phdr;
46  using Elf_Dyn = typename ElfTypes::Dyn;
47
48  class ElfSectionBuilder : public ValueObject {
49   public:
50    ElfSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
51                      const ElfSectionBuilder *link, Elf_Word info,
52                      Elf_Word align, Elf_Word entsize)
53        : section_index_(0), name_(sec_name), link_(link) {
54      memset(&section_, 0, sizeof(section_));
55      section_.sh_type = type;
56      section_.sh_flags = flags;
57      section_.sh_info = info;
58      section_.sh_addralign = align;
59      section_.sh_entsize = entsize;
60    }
61    ElfSectionBuilder(const ElfSectionBuilder&) = default;
62
63    ~ElfSectionBuilder() {}
64
65    Elf_Word GetLink() const {
66      return (link_ != nullptr) ? link_->section_index_ : 0;
67    }
68
69    const Elf_Shdr* GetSection() const {
70      return &section_;
71    }
72
73    Elf_Shdr* GetSection() {
74      return &section_;
75    }
76
77    Elf_Word GetSectionIndex() const {
78      return section_index_;
79    }
80
81    void SetSectionIndex(Elf_Word section_index) {
82      section_index_ = section_index;
83    }
84
85    const std::string& GetName() const {
86      return name_;
87    }
88
89   private:
90    Elf_Shdr section_;
91    Elf_Word section_index_;
92    const std::string name_;
93    const ElfSectionBuilder* const link_;
94  };
95
96  class ElfDynamicBuilder FINAL : public ElfSectionBuilder {
97   public:
98    void AddDynamicTag(Elf_Sword tag, Elf_Word d_un) {
99      if (tag == DT_NULL) {
100        return;
101      }
102      dynamics_.push_back({nullptr, tag, d_un});
103    }
104
105    void AddDynamicTag(Elf_Sword tag, Elf_Word d_un,
106                       const ElfSectionBuilder* section) {
107      if (tag == DT_NULL) {
108        return;
109      }
110      dynamics_.push_back({section, tag, d_un});
111    }
112
113    ElfDynamicBuilder(const std::string& sec_name,
114                      ElfSectionBuilder *link)
115    : ElfSectionBuilder(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC,
116                                  link, 0, kPageSize, sizeof(Elf_Dyn)) {}
117    ~ElfDynamicBuilder() {}
118
119    Elf_Word GetSize() const {
120      // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
121      // these must be added when we actually put the file together because
122      // their values are very dependent on state.
123      return dynamics_.size() + 3;
124    }
125
126    // Create the actual dynamic vector. strsz should be the size of the .dynstr
127    // table and soname_off should be the offset of the soname in .dynstr.
128    // Since niether can be found prior to final layout we will wait until here
129    // to add them.
130    std::vector<Elf_Dyn> GetDynamics(Elf_Word strsz, Elf_Word soname) const {
131      std::vector<Elf_Dyn> ret;
132      for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
133        if (it->section_ != nullptr) {
134          // We are adding an address relative to a section.
135          ret.push_back(
136              {it->tag_, {it->off_ + it->section_->GetSection()->sh_addr}});
137        } else {
138          ret.push_back({it->tag_, {it->off_}});
139        }
140      }
141      ret.push_back({DT_STRSZ, {strsz}});
142      ret.push_back({DT_SONAME, {soname}});
143      ret.push_back({DT_NULL, {0}});
144      return ret;
145    }
146
147   private:
148    struct ElfDynamicState {
149      const ElfSectionBuilder* section_;
150      Elf_Sword tag_;
151      Elf_Word off_;
152    };
153    std::vector<ElfDynamicState> dynamics_;
154  };
155
156  class ElfRawSectionBuilder FINAL : public ElfSectionBuilder {
157   public:
158    ElfRawSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
159                         const ElfSectionBuilder* link, Elf_Word info,
160                         Elf_Word align, Elf_Word entsize)
161      : ElfSectionBuilder(sec_name, type, flags, link, info, align, entsize) {
162    }
163    ElfRawSectionBuilder(const ElfRawSectionBuilder&) = default;
164
165    ~ElfRawSectionBuilder() {}
166
167    std::vector<uint8_t>* GetBuffer() {
168      return &buf_;
169    }
170
171    void SetBuffer(const std::vector<uint8_t>& buf) {
172      buf_ = buf;
173    }
174
175   private:
176    std::vector<uint8_t> buf_;
177  };
178
179  class ElfOatSectionBuilder FINAL : public ElfSectionBuilder {
180   public:
181    ElfOatSectionBuilder(const std::string& sec_name, Elf_Word size, Elf_Word offset,
182                         Elf_Word type, Elf_Word flags)
183      : ElfSectionBuilder(sec_name, type, flags, nullptr, 0, kPageSize, 0),
184        offset_(offset), size_(size) {
185    }
186
187    ~ElfOatSectionBuilder() {}
188
189    Elf_Word GetOffset() const {
190      return offset_;
191    }
192
193    Elf_Word GetSize() const {
194      return size_;
195    }
196
197   private:
198    // Offset of the content within the file.
199    Elf_Word offset_;
200    // Size of the content within the file.
201    Elf_Word size_;
202  };
203
204  static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
205    return ((binding) << 4) + ((type) & 0xf);
206  }
207
208  // from bionic
209  static inline unsigned elfhash(const char *_name) {
210    const unsigned char *name = (const unsigned char *) _name;
211    unsigned h = 0, g;
212
213    while (*name) {
214      h = (h << 4) + *name++;
215      g = h & 0xf0000000;
216      h ^= g;
217      h ^= g >> 24;
218    }
219    return h;
220  }
221
222  class ElfSymtabBuilder FINAL : public ElfSectionBuilder {
223   public:
224    // Add a symbol with given name to this symtab. The symbol refers to
225    // 'relative_addr' within the given section and has the given attributes.
226    void AddSymbol(const std::string& name,
227                   const ElfSectionBuilder* section,
228                   Elf_Addr addr,
229                   bool is_relative,
230                   Elf_Word size,
231                   uint8_t binding,
232                   uint8_t type,
233                   uint8_t other = 0) {
234      CHECK(section);
235      ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
236                                              MakeStInfo(binding, type), other, 0};
237      symbols_.push_back(state);
238    }
239
240    ElfSymtabBuilder(const std::string& sec_name, Elf_Word type,
241                     const std::string& str_name, Elf_Word str_type, bool alloc)
242    : ElfSectionBuilder(sec_name, type, ((alloc) ? SHF_ALLOC : 0U),
243                        &strtab_, 0, sizeof(Elf_Word),
244                        sizeof(Elf_Sym)), str_name_(str_name),
245                        str_type_(str_type),
246                        strtab_(str_name,
247                                str_type,
248                                ((alloc) ? SHF_ALLOC : 0U),
249                                nullptr, 0, 1, 1) {
250    }
251
252    ~ElfSymtabBuilder() {}
253
254    std::vector<Elf_Word> GenerateHashContents() const {
255      // Here is how The ELF hash table works.
256      // There are 3 arrays to worry about.
257      // * The symbol table where the symbol information is.
258      // * The bucket array which is an array of indexes into the symtab and chain.
259      // * The chain array which is also an array of indexes into the symtab and chain.
260      //
261      // Lets say the state is something like this.
262      // +--------+       +--------+      +-----------+
263      // | symtab |       | bucket |      |   chain   |
264      // |  null  |       | 1      |      | STN_UNDEF |
265      // | <sym1> |       | 4      |      | 2         |
266      // | <sym2> |       |        |      | 5         |
267      // | <sym3> |       |        |      | STN_UNDEF |
268      // | <sym4> |       |        |      | 3         |
269      // | <sym5> |       |        |      | STN_UNDEF |
270      // +--------+       +--------+      +-----------+
271      //
272      // The lookup process (in python psudocode) is
273      //
274      // def GetSym(name):
275      //     # NB STN_UNDEF == 0
276      //     indx = bucket[elfhash(name) % num_buckets]
277      //     while indx != STN_UNDEF:
278      //         if GetSymbolName(symtab[indx]) == name:
279      //             return symtab[indx]
280      //         indx = chain[indx]
281      //     return SYMBOL_NOT_FOUND
282      //
283      // Between bucket and chain arrays every symtab index must be present exactly
284      // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
285
286      // Select number of buckets.
287      // This is essentially arbitrary.
288      Elf_Word nbuckets;
289      Elf_Word chain_size = GetSize();
290      if (symbols_.size() < 8) {
291        nbuckets = 2;
292      } else if (symbols_.size() < 32) {
293        nbuckets = 4;
294      } else if (symbols_.size() < 256) {
295        nbuckets = 16;
296      } else {
297        // Have about 32 ids per bucket.
298        nbuckets = RoundUp(symbols_.size()/32, 2);
299      }
300      std::vector<Elf_Word> hash;
301      hash.push_back(nbuckets);
302      hash.push_back(chain_size);
303      uint32_t bucket_offset = hash.size();
304      uint32_t chain_offset = bucket_offset + nbuckets;
305      hash.resize(hash.size() + nbuckets + chain_size, 0);
306
307      Elf_Word* buckets = hash.data() + bucket_offset;
308      Elf_Word* chain   = hash.data() + chain_offset;
309
310      // Set up the actual hash table.
311      for (Elf_Word i = 0; i < symbols_.size(); i++) {
312        // Add 1 since we need to have the null symbol that is not in the symbols
313        // list.
314        Elf_Word index = i + 1;
315        Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
316        if (buckets[hash_val] == 0) {
317          buckets[hash_val] = index;
318        } else {
319          hash_val = buckets[hash_val];
320          CHECK_LT(hash_val, chain_size);
321          while (chain[hash_val] != 0) {
322            hash_val = chain[hash_val];
323            CHECK_LT(hash_val, chain_size);
324          }
325          chain[hash_val] = index;
326          // Check for loops. Works because if this is non-empty then there must be
327          // another cell which already contains the same symbol index as this one,
328          // which means some symbol has more then one name, which isn't allowed.
329          CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
330        }
331      }
332
333      return hash;
334    }
335
336    std::string GenerateStrtab() {
337      std::string tab;
338      tab += '\0';
339      for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
340        it->name_idx_ = tab.size();
341        tab += it->name_;
342        tab += '\0';
343      }
344      strtab_.GetSection()->sh_size = tab.size();
345      return tab;
346    }
347
348    std::vector<Elf_Sym> GenerateSymtab() {
349      std::vector<Elf_Sym> ret;
350      Elf_Sym undef_sym;
351      memset(&undef_sym, 0, sizeof(undef_sym));
352      undef_sym.st_shndx = SHN_UNDEF;
353      ret.push_back(undef_sym);
354
355      for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
356        Elf_Sym sym;
357        memset(&sym, 0, sizeof(sym));
358        sym.st_name = it->name_idx_;
359        if (it->is_relative_) {
360          sym.st_value = it->addr_ + it->section_->GetSection()->sh_offset;
361        } else {
362          sym.st_value = it->addr_;
363        }
364        sym.st_size = it->size_;
365        sym.st_other = it->other_;
366        sym.st_shndx = it->section_->GetSectionIndex();
367        sym.st_info = it->info_;
368
369        ret.push_back(sym);
370      }
371      return ret;
372    }
373
374    Elf_Word GetSize() const {
375      // 1 is for the implicit null symbol.
376      return symbols_.size() + 1;
377    }
378
379    ElfSectionBuilder* GetStrTab() {
380      return &strtab_;
381    }
382
383   private:
384    struct ElfSymbolState {
385      const std::string name_;
386      const ElfSectionBuilder* section_;
387      Elf_Addr addr_;
388      Elf_Word size_;
389      bool is_relative_;
390      uint8_t info_;
391      uint8_t other_;
392      // Used during Write() to temporarially hold name index in the strtab.
393      Elf_Word name_idx_;
394    };
395
396    // Information for the strsym for dynstr sections.
397    const std::string str_name_;
398    Elf_Word str_type_;
399    // The symbols in the same order they will be in the symbol table.
400    std::vector<ElfSymbolState> symbols_;
401    ElfSectionBuilder strtab_;
402  };
403
404  template <typename Elf_Word>
405  class ElfFilePiece {
406   public:
407    virtual ~ElfFilePiece() {}
408
409    virtual bool Write(File* elf_file) {
410      if (static_cast<off_t>(offset_) != lseek(elf_file->Fd(), offset_, SEEK_SET)) {
411        PLOG(ERROR) << "Failed to seek to " << GetDescription() << " offset " << offset_ << " for "
412            << elf_file->GetPath();
413        return false;
414      }
415
416      return DoActualWrite(elf_file);
417    }
418
419    static bool Compare(ElfFilePiece* a, ElfFilePiece* b) {
420      return a->offset_ < b->offset_;
421    }
422
423   protected:
424    explicit ElfFilePiece(Elf_Word offset) : offset_(offset) {}
425
426    Elf_Word GetOffset() const {
427      return offset_;
428    }
429
430    virtual const char* GetDescription() const = 0;
431    virtual bool DoActualWrite(File* elf_file) = 0;
432
433   private:
434    const Elf_Word offset_;
435
436    DISALLOW_COPY_AND_ASSIGN(ElfFilePiece);
437  };
438
439  template <typename Elf_Word>
440  class ElfFileMemoryPiece FINAL : public ElfFilePiece<Elf_Word> {
441   public:
442    ElfFileMemoryPiece(const std::string& name, Elf_Word offset, const void* data, Elf_Word size)
443        : ElfFilePiece<Elf_Word>(offset), dbg_name_(name), data_(data), size_(size) {}
444
445   protected:
446    bool DoActualWrite(File* elf_file) OVERRIDE {
447      DCHECK(data_ != nullptr || size_ == 0U) << dbg_name_ << " " << size_;
448
449      if (!elf_file->WriteFully(data_, size_)) {
450        PLOG(ERROR) << "Failed to write " << dbg_name_ << " for " << elf_file->GetPath();
451        return false;
452      }
453
454      return true;
455    }
456
457    const char* GetDescription() const OVERRIDE {
458      return dbg_name_.c_str();
459    }
460
461   private:
462    const std::string& dbg_name_;
463    const void *data_;
464    Elf_Word size_;
465  };
466
467  template <typename Elf_Word>
468  class ElfFileRodataPiece FINAL : public ElfFilePiece<Elf_Word> {
469   public:
470    ElfFileRodataPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
471        output_(output) {}
472
473   protected:
474    bool DoActualWrite(File* elf_file) OVERRIDE {
475      output_->SetCodeOffset(this->GetOffset());
476      std::unique_ptr<BufferedOutputStream> output_stream(
477          new BufferedOutputStream(new FileOutputStream(elf_file)));
478      if (!output_->Write(output_stream.get())) {
479        PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file->GetPath();
480        return false;
481      }
482
483      return true;
484    }
485
486    const char* GetDescription() const OVERRIDE {
487      return ".rodata";
488    }
489
490   private:
491    CodeOutput* const output_;
492
493    DISALLOW_COPY_AND_ASSIGN(ElfFileRodataPiece);
494  };
495
496  template <typename Elf_Word>
497  class ElfFileOatTextPiece FINAL : public ElfFilePiece<Elf_Word> {
498   public:
499    ElfFileOatTextPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
500        output_(output) {}
501
502   protected:
503    bool DoActualWrite(File* elf_file ATTRIBUTE_UNUSED) OVERRIDE {
504      // All data is written by the ElfFileRodataPiece right now, as the oat writer writes in one
505      // piece. This is for future flexibility.
506      UNUSED(output_);
507      return true;
508    }
509
510    const char* GetDescription() const OVERRIDE {
511      return ".text";
512    }
513
514   private:
515    CodeOutput* const output_;
516
517    DISALLOW_COPY_AND_ASSIGN(ElfFileOatTextPiece);
518  };
519
520  template <typename Elf_Word>
521  static bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces, File* elf_file) {
522    // TODO It would be nice if this checked for overlap.
523    for (auto it = pieces.begin(); it != pieces.end(); ++it) {
524      if (!(*it)->Write(elf_file)) {
525        return false;
526      }
527    }
528    return true;
529  }
530
531  template <typename Elf_Word, typename Elf_Shdr>
532  static inline constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) {
533    return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
534  }
535
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, nullptr, 0, 1, 1) {
561    SetupEhdr();
562    SetupDynamic();
563    SetupRequiredSymbols();
564    SetISA(isa);
565  }
566  ~ElfBuilder() {}
567
568  const ElfOatSectionBuilder& GetTextBuilder() const {
569    return text_builder_;
570  }
571
572  ElfSymtabBuilder* 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 .eh_frame and .eh_frame_hdr
778    for (auto* builder : other_builders_) {
779      if ((builder->GetSection()->sh_flags & SHF_ALLOC) != 0) {
780        section_ptrs_.push_back(builder->GetSection());
781        AssignSectionStr(builder, &shstrtab_);
782        builder->SetSectionIndex(section_index_);
783        section_index_++;
784      }
785    }
786
787    // Setup .rodata
788    section_ptrs_.push_back(rodata_builder_.GetSection());
789    AssignSectionStr(&rodata_builder_, &shstrtab_);
790    rodata_builder_.SetSectionIndex(section_index_);
791    section_index_++;
792
793    // Setup .text
794    section_ptrs_.push_back(text_builder_.GetSection());
795    AssignSectionStr(&text_builder_, &shstrtab_);
796    text_builder_.SetSectionIndex(section_index_);
797    section_index_++;
798
799    // Setup .bss
800    if (bss_builder_.GetSize() != 0u) {
801      section_ptrs_.push_back(bss_builder_.GetSection());
802      AssignSectionStr(&bss_builder_, &shstrtab_);
803      bss_builder_.SetSectionIndex(section_index_);
804      section_index_++;
805    }
806
807    // Setup .dynamic
808    section_ptrs_.push_back(dynamic_builder_.GetSection());
809    AssignSectionStr(&dynamic_builder_, &shstrtab_);
810    dynamic_builder_.SetSectionIndex(section_index_);
811    section_index_++;
812
813    // Fill in the hash section.
814    hash_ = dynsym_builder_.GenerateHashContents();
815
816    if (debug_logging_) {
817      LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
818                << std::hex << " " << hash_.size() * sizeof(Elf_Word);
819    }
820
821    Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
822
823    // Get the layout in the sections.
824    //
825    // Get the layout of the dynsym section.
826    dynsym_builder_.GetSection()->sh_offset =
827        RoundUp(base_offset, dynsym_builder_.GetSection()->sh_addralign);
828    dynsym_builder_.GetSection()->sh_addr = dynsym_builder_.GetSection()->sh_offset;
829    dynsym_builder_.GetSection()->sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
830    dynsym_builder_.GetSection()->sh_link = dynsym_builder_.GetLink();
831
832    // Get the layout of the dynstr section.
833    dynsym_builder_.GetStrTab()->GetSection()->sh_offset =
834        NextOffset<Elf_Word, Elf_Shdr>(*dynsym_builder_.GetStrTab()->GetSection(),
835                                       *dynsym_builder_.GetSection());
836    dynsym_builder_.GetStrTab()->GetSection()->sh_addr =
837        dynsym_builder_.GetStrTab()->GetSection()->sh_offset;
838    dynsym_builder_.GetStrTab()->GetSection()->sh_size = dynstr_.size();
839    dynsym_builder_.GetStrTab()->GetSection()->sh_link = dynsym_builder_.GetStrTab()->GetLink();
840
841    // Get the layout of the hash section
842    hash_builder_.GetSection()->sh_offset =
843        NextOffset<Elf_Word, Elf_Shdr>(*hash_builder_.GetSection(),
844                                       *dynsym_builder_.GetStrTab()->GetSection());
845    hash_builder_.GetSection()->sh_addr = hash_builder_.GetSection()->sh_offset;
846    hash_builder_.GetSection()->sh_size = hash_.size() * sizeof(Elf_Word);
847    hash_builder_.GetSection()->sh_link = hash_builder_.GetLink();
848
849    // Get the layout of the extra sections with SHF_ALLOC flag.
850    // This will deal with .eh_frame and .eh_frame_hdr.
851    // .eh_frame contains relative pointers to .text which we
852    // want to fixup between the calls to Init() and Write().
853    // Therefore we handle those sections here as opposed to Write().
854    // It also has the nice side effect of including .eh_frame
855    // with the rest of LOAD_R segment.  It must come before .rodata
856    // because .rodata and .text must be next to each other.
857    Elf_Shdr* prev = hash_builder_.GetSection();
858    for (auto* it : other_builders_) {
859      if ((it->GetSection()->sh_flags & SHF_ALLOC) != 0) {
860        it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
861        it->GetSection()->sh_addr = it->GetSection()->sh_offset;
862        it->GetSection()->sh_size = it->GetBuffer()->size();
863        it->GetSection()->sh_link = it->GetLink();
864        prev = it->GetSection();
865      }
866    }
867    // If the sections exist, check that they have been handled.
868    const auto* eh_frame = FindRawSection(".eh_frame");
869    if (eh_frame != nullptr) {
870      DCHECK_NE(eh_frame->GetSection()->sh_offset, 0u);
871    }
872    const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr");
873    if (eh_frame_hdr != nullptr) {
874      DCHECK_NE(eh_frame_hdr->GetSection()->sh_offset, 0u);
875    }
876
877    // Get the layout of the rodata section.
878    rodata_builder_.GetSection()->sh_offset =
879        NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(), *prev);
880    rodata_builder_.GetSection()->sh_addr = rodata_builder_.GetSection()->sh_offset;
881    rodata_builder_.GetSection()->sh_size = rodata_builder_.GetSize();
882    rodata_builder_.GetSection()->sh_link = rodata_builder_.GetLink();
883
884    // Get the layout of the text section.
885    text_builder_.GetSection()->sh_offset =
886        NextOffset<Elf_Word, Elf_Shdr>(*text_builder_.GetSection(),
887                                       *rodata_builder_.GetSection());
888    text_builder_.GetSection()->sh_addr = text_builder_.GetSection()->sh_offset;
889    text_builder_.GetSection()->sh_size = text_builder_.GetSize();
890    text_builder_.GetSection()->sh_link = text_builder_.GetLink();
891    CHECK_ALIGNED(rodata_builder_.GetSection()->sh_offset +
892                  rodata_builder_.GetSection()->sh_size, kPageSize);
893
894    // Get the layout of the .bss section.
895    bss_builder_.GetSection()->sh_offset =
896        NextOffset<Elf_Word, Elf_Shdr>(*bss_builder_.GetSection(),
897                                       *text_builder_.GetSection());
898    bss_builder_.GetSection()->sh_addr = bss_builder_.GetSection()->sh_offset;
899    bss_builder_.GetSection()->sh_size = bss_builder_.GetSize();
900    bss_builder_.GetSection()->sh_link = bss_builder_.GetLink();
901
902    // Get the layout of the dynamic section.
903    CHECK(IsAlignedParam(bss_builder_.GetSection()->sh_offset,
904                         dynamic_builder_.GetSection()->sh_addralign));
905    dynamic_builder_.GetSection()->sh_offset = bss_builder_.GetSection()->sh_offset;
906    dynamic_builder_.GetSection()->sh_addr =
907        NextOffset<Elf_Word, Elf_Shdr>(*dynamic_builder_.GetSection(), *bss_builder_.GetSection());
908    dynamic_builder_.GetSection()->sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
909    dynamic_builder_.GetSection()->sh_link = dynamic_builder_.GetLink();
910
911    if (debug_logging_) {
912      LOG(INFO) << "dynsym off=" << dynsym_builder_.GetSection()->sh_offset
913                << " dynsym size=" << dynsym_builder_.GetSection()->sh_size;
914      LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->GetSection()->sh_offset
915                << " dynstr size=" << dynsym_builder_.GetStrTab()->GetSection()->sh_size;
916      LOG(INFO) << "hash off=" << hash_builder_.GetSection()->sh_offset
917                << " hash size=" << hash_builder_.GetSection()->sh_size;
918      LOG(INFO) << "rodata off=" << rodata_builder_.GetSection()->sh_offset
919                << " rodata size=" << rodata_builder_.GetSection()->sh_size;
920      LOG(INFO) << "text off=" << text_builder_.GetSection()->sh_offset
921                << " text size=" << text_builder_.GetSection()->sh_size;
922      LOG(INFO) << "dynamic off=" << dynamic_builder_.GetSection()->sh_offset
923                << " dynamic size=" << dynamic_builder_.GetSection()->sh_size;
924    }
925
926    return true;
927  }
928
929  bool Write() {
930    std::vector<ElfFilePiece<Elf_Word>*> pieces;
931    Elf_Shdr* prev = dynamic_builder_.GetSection();
932    std::string strtab;
933
934    if (IncludingDebugSymbols()) {
935      // Setup .symtab
936      section_ptrs_.push_back(symtab_builder_.GetSection());
937      AssignSectionStr(&symtab_builder_, &shstrtab_);
938      symtab_builder_.SetSectionIndex(section_index_);
939      section_index_++;
940
941      // Setup .strtab
942      section_ptrs_.push_back(symtab_builder_.GetStrTab()->GetSection());
943      AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
944      symtab_builder_.GetStrTab()->SetSectionIndex(section_index_);
945      section_index_++;
946
947      strtab = symtab_builder_.GenerateStrtab();
948      if (debug_logging_) {
949        LOG(INFO) << "strtab size (bytes)    =" << strtab.size()
950                  << std::hex << " " << strtab.size();
951        LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
952                  << std::hex << " " << symtab_builder_.GetSize();
953      }
954    }
955
956    // Setup all the other sections.
957    for (auto* builder : other_builders_) {
958      if ((builder->GetSection()->sh_flags & SHF_ALLOC) == 0) {
959        section_ptrs_.push_back(builder->GetSection());
960        AssignSectionStr(builder, &shstrtab_);
961        builder->SetSectionIndex(section_index_);
962        section_index_++;
963      }
964    }
965
966    // Setup shstrtab
967    section_ptrs_.push_back(shstrtab_builder_.GetSection());
968    AssignSectionStr(&shstrtab_builder_, &shstrtab_);
969    shstrtab_builder_.SetSectionIndex(section_index_);
970    section_index_++;
971
972    if (debug_logging_) {
973      LOG(INFO) << ".shstrtab size    (bytes)   =" << shstrtab_.size()
974                << std::hex << " " << shstrtab_.size();
975      LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
976                << std::hex << " " << section_ptrs_.size();
977    }
978
979    if (IncludingDebugSymbols()) {
980      // Get the layout of the symtab section.
981      symtab_builder_.GetSection()->sh_offset =
982          NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetSection(),
983                                         *dynamic_builder_.GetSection());
984      symtab_builder_.GetSection()->sh_addr = 0;
985      // Add to leave space for the null symbol.
986      symtab_builder_.GetSection()->sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
987      symtab_builder_.GetSection()->sh_link = symtab_builder_.GetLink();
988
989      // Get the layout of the dynstr section.
990      symtab_builder_.GetStrTab()->GetSection()->sh_offset =
991          NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetStrTab()->GetSection(),
992                                         *symtab_builder_.GetSection());
993      symtab_builder_.GetStrTab()->GetSection()->sh_addr = 0;
994      symtab_builder_.GetStrTab()->GetSection()->sh_size = strtab.size();
995      symtab_builder_.GetStrTab()->GetSection()->sh_link = symtab_builder_.GetStrTab()->GetLink();
996
997      prev = symtab_builder_.GetStrTab()->GetSection();
998      if (debug_logging_) {
999        LOG(INFO) << "symtab off=" << symtab_builder_.GetSection()->sh_offset
1000                  << " symtab size=" << symtab_builder_.GetSection()->sh_size;
1001        LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->GetSection()->sh_offset
1002                  << " strtab size=" << symtab_builder_.GetStrTab()->GetSection()->sh_size;
1003      }
1004    }
1005
1006    // Get the layout of the extra sections without SHF_ALLOC flag.
1007    // (This will deal with the debug sections if they are there)
1008    for (auto* it : other_builders_) {
1009      if ((it->GetSection()->sh_flags & SHF_ALLOC) == 0) {
1010        it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
1011        it->GetSection()->sh_addr = 0;
1012        it->GetSection()->sh_size = it->GetBuffer()->size();
1013        it->GetSection()->sh_link = it->GetLink();
1014
1015        // We postpone adding an ElfFilePiece to keep the order in "pieces."
1016
1017        prev = it->GetSection();
1018        if (debug_logging_) {
1019          LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset
1020                    << " size=" << it->GetSection()->sh_size;
1021        }
1022      }
1023    }
1024
1025    // Get the layout of the shstrtab section
1026    shstrtab_builder_.GetSection()->sh_offset =
1027        NextOffset<Elf_Word, Elf_Shdr>(*shstrtab_builder_.GetSection(), *prev);
1028    shstrtab_builder_.GetSection()->sh_addr = 0;
1029    shstrtab_builder_.GetSection()->sh_size = shstrtab_.size();
1030    shstrtab_builder_.GetSection()->sh_link = shstrtab_builder_.GetLink();
1031    if (debug_logging_) {
1032        LOG(INFO) << "shstrtab off=" << shstrtab_builder_.GetSection()->sh_offset
1033                  << " shstrtab size=" << shstrtab_builder_.GetSection()->sh_size;
1034    }
1035
1036    // The section list comes after come after.
1037    Elf_Word sections_offset = RoundUp(
1038        shstrtab_builder_.GetSection()->sh_offset + shstrtab_builder_.GetSection()->sh_size,
1039        sizeof(Elf_Word));
1040
1041    // Setup the actual symbol arrays.
1042    std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
1043    CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.GetSection()->sh_size);
1044    std::vector<Elf_Sym> symtab;
1045    if (IncludingDebugSymbols()) {
1046      symtab = symtab_builder_.GenerateSymtab();
1047      CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.GetSection()->sh_size);
1048    }
1049
1050    // Setup the dynamic section.
1051    // This will add the 2 values we cannot know until now time, namely the size
1052    // and the soname_offset.
1053    std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
1054                                                                  dynstr_soname_offset_);
1055    CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.GetSection()->sh_size);
1056
1057    // Finish setup of the program headers now that we know the layout of the
1058    // whole file.
1059    Elf_Word load_r_size =
1060        rodata_builder_.GetSection()->sh_offset + rodata_builder_.GetSection()->sh_size;
1061    program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
1062    program_headers_[PH_LOAD_R__].p_memsz =  load_r_size;
1063    program_headers_[PH_LOAD_R__].p_align =  rodata_builder_.GetSection()->sh_addralign;
1064
1065    Elf_Word load_rx_size = text_builder_.GetSection()->sh_size;
1066    program_headers_[PH_LOAD_R_X].p_offset = text_builder_.GetSection()->sh_offset;
1067    program_headers_[PH_LOAD_R_X].p_vaddr  = text_builder_.GetSection()->sh_offset;
1068    program_headers_[PH_LOAD_R_X].p_paddr  = text_builder_.GetSection()->sh_offset;
1069    program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
1070    program_headers_[PH_LOAD_R_X].p_memsz  = load_rx_size;
1071    program_headers_[PH_LOAD_R_X].p_align  = text_builder_.GetSection()->sh_addralign;
1072
1073    program_headers_[PH_LOAD_RW_BSS].p_offset = bss_builder_.GetSection()->sh_offset;
1074    program_headers_[PH_LOAD_RW_BSS].p_vaddr  = bss_builder_.GetSection()->sh_offset;
1075    program_headers_[PH_LOAD_RW_BSS].p_paddr  = bss_builder_.GetSection()->sh_offset;
1076    program_headers_[PH_LOAD_RW_BSS].p_filesz = 0;
1077    program_headers_[PH_LOAD_RW_BSS].p_memsz  = bss_builder_.GetSection()->sh_size;
1078    program_headers_[PH_LOAD_RW_BSS].p_align  = bss_builder_.GetSection()->sh_addralign;
1079
1080    program_headers_[PH_LOAD_RW_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
1081    program_headers_[PH_LOAD_RW_DYNAMIC].p_vaddr  = dynamic_builder_.GetSection()->sh_addr;
1082    program_headers_[PH_LOAD_RW_DYNAMIC].p_paddr  = dynamic_builder_.GetSection()->sh_addr;
1083    program_headers_[PH_LOAD_RW_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1084    program_headers_[PH_LOAD_RW_DYNAMIC].p_memsz  = dynamic_builder_.GetSection()->sh_size;
1085    program_headers_[PH_LOAD_RW_DYNAMIC].p_align  = dynamic_builder_.GetSection()->sh_addralign;
1086
1087    program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
1088    program_headers_[PH_DYNAMIC].p_vaddr  = dynamic_builder_.GetSection()->sh_addr;
1089    program_headers_[PH_DYNAMIC].p_paddr  = dynamic_builder_.GetSection()->sh_addr;
1090    program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1091    program_headers_[PH_DYNAMIC].p_memsz  = dynamic_builder_.GetSection()->sh_size;
1092    program_headers_[PH_DYNAMIC].p_align  = dynamic_builder_.GetSection()->sh_addralign;
1093
1094    const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr");
1095    if (eh_frame_hdr != nullptr) {
1096      const auto* eh_frame = FindRawSection(".eh_frame");
1097      // Check layout:
1098      // 1) eh_frame is before eh_frame_hdr.
1099      // 2) There's no gap.
1100      CHECK(eh_frame != nullptr);
1101      CHECK_LE(eh_frame->GetSection()->sh_offset, eh_frame_hdr->GetSection()->sh_offset);
1102      CHECK_EQ(eh_frame->GetSection()->sh_offset + eh_frame->GetSection()->sh_size,
1103               eh_frame_hdr->GetSection()->sh_offset);
1104
1105      program_headers_[PH_EH_FRAME_HDR].p_type   = PT_GNU_EH_FRAME;
1106      program_headers_[PH_EH_FRAME_HDR].p_offset = eh_frame_hdr->GetSection()->sh_offset;
1107      program_headers_[PH_EH_FRAME_HDR].p_vaddr  = eh_frame_hdr->GetSection()->sh_addr;
1108      program_headers_[PH_EH_FRAME_HDR].p_paddr  = eh_frame_hdr->GetSection()->sh_addr;
1109      program_headers_[PH_EH_FRAME_HDR].p_filesz = eh_frame_hdr->GetSection()->sh_size;
1110      program_headers_[PH_EH_FRAME_HDR].p_memsz  = eh_frame_hdr->GetSection()->sh_size;
1111      program_headers_[PH_EH_FRAME_HDR].p_align  = eh_frame_hdr->GetSection()->sh_addralign;
1112    }
1113
1114    // Finish setup of the Ehdr values.
1115    elf_header_.e_phoff = PHDR_OFFSET;
1116    elf_header_.e_shoff = sections_offset;
1117    elf_header_.e_phnum = PH_NUM - (bss_builder_.GetSection()->sh_size == 0u ? 1 : 0)
1118                                 - (eh_frame_hdr == nullptr ? 1 : 0);
1119    elf_header_.e_shnum = section_ptrs_.size();
1120    elf_header_.e_shstrndx = shstrtab_builder_.GetSectionIndex();
1121
1122    // Add the rest of the pieces to the list.
1123    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_,
1124                                                      sizeof(elf_header_)));
1125    if (bss_builder_.GetSection()->sh_size != 0u) {
1126      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1127                                                        &program_headers_[0],
1128                                                        elf_header_.e_phnum * sizeof(Elf_Phdr)));
1129    } else {
1130      // Skip PH_LOAD_RW_BSS.
1131      Elf_Word part1_size = PH_LOAD_RW_BSS * sizeof(Elf_Phdr);
1132      Elf_Word part2_size = (elf_header_.e_phnum - PH_LOAD_RW_BSS) * sizeof(Elf_Phdr);
1133      CHECK_EQ(part1_size + part2_size, elf_header_.e_phnum * sizeof(Elf_Phdr));
1134      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1135                                                        &program_headers_[0], part1_size));
1136      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers part 2",
1137                                                        PHDR_OFFSET + part1_size,
1138                                                        &program_headers_[PH_LOAD_RW_BSS + 1],
1139                                                        part2_size));
1140    }
1141    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic",
1142                                                      dynamic_builder_.GetSection()->sh_offset,
1143                                                      dynamic.data(),
1144                                                      dynamic_builder_.GetSection()->sh_size));
1145    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.GetSection()->sh_offset,
1146                                                      dynsym.data(),
1147                                                      dynsym.size() * sizeof(Elf_Sym)));
1148    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr",
1149                                                    dynsym_builder_.GetStrTab()->GetSection()->sh_offset,
1150                                                    dynstr_.c_str(), dynstr_.size()));
1151    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.GetSection()->sh_offset,
1152                                                      hash_.data(),
1153                                                      hash_.size() * sizeof(Elf_Word)));
1154    pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.GetSection()->sh_offset,
1155                                                      oat_writer_));
1156    pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.GetSection()->sh_offset,
1157                                                       oat_writer_));
1158    if (IncludingDebugSymbols()) {
1159      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab",
1160                                                        symtab_builder_.GetSection()->sh_offset,
1161                                                        symtab.data(),
1162                                                        symtab.size() * sizeof(Elf_Sym)));
1163      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab",
1164                                                    symtab_builder_.GetStrTab()->GetSection()->sh_offset,
1165                                                    strtab.c_str(), strtab.size()));
1166    }
1167    pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab",
1168                                                      shstrtab_builder_.GetSection()->sh_offset,
1169                                                      &shstrtab_[0], shstrtab_.size()));
1170    for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
1171      // Just add all the sections in induvidually since they are all over the
1172      // place on the heap/stack.
1173      Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
1174      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off,
1175                                                        section_ptrs_[i], sizeof(Elf_Shdr)));
1176    }
1177
1178    // Postponed debug info.
1179    for (auto* it : other_builders_) {
1180      pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->GetName(), it->GetSection()->sh_offset,
1181                                                        it->GetBuffer()->data(),
1182                                                        it->GetBuffer()->size()));
1183    }
1184
1185    if (!WriteOutFile(pieces)) {
1186      LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
1187
1188      STLDeleteElements(&pieces);  // Have to manually clean pieces.
1189      return false;
1190    }
1191
1192    STLDeleteElements(&pieces);  // Have to manually clean pieces.
1193    return true;
1194  }
1195
1196  // Adds the given raw section to the builder.  It does not take ownership.
1197  void RegisterRawSection(ElfRawSectionBuilder* bld) {
1198    other_builders_.push_back(bld);
1199  }
1200
1201  const ElfRawSectionBuilder* FindRawSection(const char* name) {
1202    for (const auto* other_builder : other_builders_) {
1203      if (other_builder->GetName() == name) {
1204        return other_builder;
1205      }
1206    }
1207    return nullptr;
1208  }
1209
1210 private:
1211  void SetISA(InstructionSet isa) {
1212    switch (isa) {
1213      case kArm:
1214        // Fall through.
1215      case kThumb2: {
1216        elf_header_.e_machine = EM_ARM;
1217        elf_header_.e_flags = EF_ARM_EABI_VER5;
1218        break;
1219      }
1220      case kArm64: {
1221        elf_header_.e_machine = EM_AARCH64;
1222        elf_header_.e_flags = 0;
1223        break;
1224      }
1225      case kX86: {
1226        elf_header_.e_machine = EM_386;
1227        elf_header_.e_flags = 0;
1228        break;
1229      }
1230      case kX86_64: {
1231        elf_header_.e_machine = EM_X86_64;
1232        elf_header_.e_flags = 0;
1233        break;
1234      }
1235      case kMips: {
1236        elf_header_.e_machine = EM_MIPS;
1237        elf_header_.e_flags = (EF_MIPS_NOREORDER |
1238                               EF_MIPS_PIC       |
1239                               EF_MIPS_CPIC      |
1240                               EF_MIPS_ABI_O32   |
1241                               EF_MIPS_ARCH_32R2);
1242        break;
1243      }
1244      case kMips64: {
1245        elf_header_.e_machine = EM_MIPS;
1246        elf_header_.e_flags = (EF_MIPS_NOREORDER |
1247                               EF_MIPS_PIC       |
1248                               EF_MIPS_CPIC      |
1249                               EF_MIPS_ARCH_64R6);
1250        break;
1251      }
1252      default: {
1253        fatal_error_ = true;
1254        LOG(FATAL) << "Unknown instruction set: " << isa;
1255        break;
1256      }
1257    }
1258  }
1259
1260  void SetupEhdr() {
1261    memset(&elf_header_, 0, sizeof(elf_header_));
1262    elf_header_.e_ident[EI_MAG0]       = ELFMAG0;
1263    elf_header_.e_ident[EI_MAG1]       = ELFMAG1;
1264    elf_header_.e_ident[EI_MAG2]       = ELFMAG2;
1265    elf_header_.e_ident[EI_MAG3]       = ELFMAG3;
1266    elf_header_.e_ident[EI_CLASS]      = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
1267                                         ? ELFCLASS32 : ELFCLASS64;;
1268    elf_header_.e_ident[EI_DATA]       = ELFDATA2LSB;
1269    elf_header_.e_ident[EI_VERSION]    = EV_CURRENT;
1270    elf_header_.e_ident[EI_OSABI]      = ELFOSABI_LINUX;
1271    elf_header_.e_ident[EI_ABIVERSION] = 0;
1272    elf_header_.e_type = ET_DYN;
1273    elf_header_.e_version = 1;
1274    elf_header_.e_entry = 0;
1275    elf_header_.e_ehsize = sizeof(Elf_Ehdr);
1276    elf_header_.e_phentsize = sizeof(Elf_Phdr);
1277    elf_header_.e_shentsize = sizeof(Elf_Shdr);
1278    elf_header_.e_phoff = sizeof(Elf_Ehdr);
1279  }
1280
1281  // Sets up a bunch of the required Dynamic Section entries.
1282  // Namely it will initialize all the mandatory ones that it can.
1283  // Specifically:
1284  // DT_HASH
1285  // DT_STRTAB
1286  // DT_SYMTAB
1287  // DT_SYMENT
1288  //
1289  // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
1290  void SetupDynamic() {
1291    dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
1292    dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1293    dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1294    dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1295  }
1296
1297  // Sets up the basic dynamic symbols that are needed, namely all those we
1298  // can know already.
1299  //
1300  // Specifically adds:
1301  // oatdata
1302  // oatexec
1303  // oatlastword
1304  void SetupRequiredSymbols() {
1305    dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1306                              rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1307    dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1308                              text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1309    dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1310                              true, 4, STB_GLOBAL, STT_OBJECT);
1311    if (bss_builder_.GetSize() != 0u) {
1312      dynsym_builder_.AddSymbol("oatbss", &bss_builder_, 0, true,
1313                                bss_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1314      dynsym_builder_.AddSymbol("oatbsslastword", &bss_builder_, bss_builder_.GetSize() - 4,
1315                                true, 4, STB_GLOBAL, STT_OBJECT);
1316    }
1317  }
1318
1319  void AssignSectionStr(ElfSectionBuilder* builder, std::string* strtab) {
1320    builder->GetSection()->sh_name = strtab->size();
1321    *strtab += builder->GetName();
1322    *strtab += '\0';
1323    if (debug_logging_) {
1324      LOG(INFO) << "adding section name \"" << builder->GetName() << "\" "
1325                << "to shstrtab at offset " << builder->GetSection()->sh_name;
1326    }
1327  }
1328
1329
1330  // Write each of the pieces out to the file.
1331  bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) {
1332    for (auto it = pieces.begin(); it != pieces.end(); ++it) {
1333      if (!(*it)->Write(elf_file_)) {
1334        return false;
1335      }
1336    }
1337    return true;
1338  }
1339
1340  bool IncludingDebugSymbols() const {
1341    return add_symbols_ && symtab_builder_.GetSize() > 1;
1342  }
1343
1344  CodeOutput* const oat_writer_;
1345  File* const elf_file_;
1346  const bool add_symbols_;
1347  const bool debug_logging_;
1348
1349  bool fatal_error_ = false;
1350
1351  // What phdr is.
1352  static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
1353  enum : uint8_t {
1354    PH_PHDR             = 0,
1355    PH_LOAD_R__         = 1,
1356    PH_LOAD_R_X         = 2,
1357    PH_LOAD_RW_BSS      = 3,
1358    PH_LOAD_RW_DYNAMIC  = 4,
1359    PH_DYNAMIC          = 5,
1360    PH_EH_FRAME_HDR     = 6,
1361    PH_NUM              = 7,
1362  };
1363  static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
1364  Elf_Phdr program_headers_[PH_NUM];
1365
1366  Elf_Ehdr elf_header_;
1367
1368  Elf_Shdr null_hdr_;
1369  std::string shstrtab_;
1370  // The index of the current section being built. The first being 1.
1371  uint32_t section_index_;
1372  std::string dynstr_;
1373  uint32_t dynstr_soname_offset_;
1374  std::vector<const Elf_Shdr*> section_ptrs_;
1375  std::vector<Elf_Word> hash_;
1376
1377  ElfOatSectionBuilder text_builder_;
1378  ElfOatSectionBuilder rodata_builder_;
1379  ElfOatSectionBuilder bss_builder_;
1380  ElfSymtabBuilder dynsym_builder_;
1381  ElfSymtabBuilder symtab_builder_;
1382  ElfSectionBuilder hash_builder_;
1383  ElfDynamicBuilder dynamic_builder_;
1384  ElfSectionBuilder shstrtab_builder_;
1385  std::vector<ElfRawSectionBuilder*> other_builders_;
1386
1387  DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
1388};
1389
1390}  // namespace art
1391
1392#endif  // ART_COMPILER_ELF_BUILDER_H_
1393