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