1/*
2 * Copyright (C) 2012 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_WRITER_QUICK_H_
18#define ART_COMPILER_ELF_WRITER_QUICK_H_
19
20#include "elf_utils.h"
21#include "elf_writer.h"
22#include "instruction_set.h"
23
24namespace art {
25
26class ElfWriterQuick FINAL : public ElfWriter {
27 public:
28  // Write an ELF file. Returns true on success, false on failure.
29  static bool Create(File* file,
30                     OatWriter* oat_writer,
31                     const std::vector<const DexFile*>& dex_files,
32                     const std::string& android_root,
33                     bool is_host,
34                     const CompilerDriver& driver)
35      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
36
37 protected:
38  bool Write(OatWriter* oat_writer,
39             const std::vector<const DexFile*>& dex_files,
40             const std::string& android_root,
41             bool is_host)
42      OVERRIDE
43      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
44
45 private:
46  ElfWriterQuick(const CompilerDriver& driver, File* elf_file)
47    : ElfWriter(driver, elf_file) {}
48  ~ElfWriterQuick() {}
49
50  class ElfBuilder;
51  void AddDebugSymbols(ElfBuilder& builder,
52                       OatWriter* oat_writer,
53                       bool debug);
54  void ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug);
55
56  class ElfSectionBuilder {
57   public:
58    ElfSectionBuilder(const std::string& sec_name, Elf32_Word type, Elf32_Word flags,
59                      const ElfSectionBuilder *link, Elf32_Word info, Elf32_Word align,
60                      Elf32_Word entsize)
61        : name_(sec_name), link_(link) {
62      memset(&section_, 0, sizeof(section_));
63      section_.sh_type = type;
64      section_.sh_flags = flags;
65      section_.sh_info = info;
66      section_.sh_addralign = align;
67      section_.sh_entsize = entsize;
68    }
69
70    virtual ~ElfSectionBuilder() {}
71
72    Elf32_Shdr section_;
73    Elf32_Word section_index_ = 0;
74
75   protected:
76    const std::string name_;
77    const ElfSectionBuilder* link_;
78
79    Elf32_Word GetLink() {
80      return (link_) ? link_->section_index_ : 0;
81    }
82
83   private:
84    friend class ElfBuilder;
85  };
86
87  class ElfDynamicBuilder : public ElfSectionBuilder {
88   public:
89    void AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un);
90    void AddDynamicTag(Elf32_Sword tag, Elf32_Word offset, ElfSectionBuilder* section);
91
92    ElfDynamicBuilder(const std::string& sec_name, ElfSectionBuilder *link)
93        : ElfSectionBuilder(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC, link,
94                            0, kPageSize, sizeof(Elf32_Dyn)) {}
95    ~ElfDynamicBuilder() {}
96
97   protected:
98    struct ElfDynamicState {
99      ElfSectionBuilder* section_;
100      Elf32_Sword tag_;
101      Elf32_Word off_;
102    };
103    std::vector<ElfDynamicState> dynamics_;
104    Elf32_Word GetSize() {
105      // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
106      // these must be added when we actually put the file together because
107      // their values are very dependent on state.
108      return dynamics_.size() + 3;
109    }
110
111    // Create the actual dynamic vector. strsz should be the size of the .dynstr
112    // table and soname_off should be the offset of the soname in .dynstr.
113    // Since niether can be found prior to final layout we will wait until here
114    // to add them.
115    std::vector<Elf32_Dyn> GetDynamics(Elf32_Word strsz, Elf32_Word soname_off);
116
117   private:
118    friend class ElfBuilder;
119  };
120
121  class ElfRawSectionBuilder : public ElfSectionBuilder {
122   public:
123    ElfRawSectionBuilder(const std::string& sec_name, Elf32_Word type, Elf32_Word flags,
124                         const ElfSectionBuilder* link, Elf32_Word info, Elf32_Word align,
125                         Elf32_Word entsize)
126        : ElfSectionBuilder(sec_name, type, flags, link, info, align, entsize) {}
127    ~ElfRawSectionBuilder() {}
128    std::vector<uint8_t>* GetBuffer() { return &buf_; }
129    void SetBuffer(std::vector<uint8_t> buf) { buf_ = buf; }
130
131   protected:
132    std::vector<uint8_t> buf_;
133
134   private:
135    friend class ElfBuilder;
136  };
137
138  class ElfOatSectionBuilder : public ElfSectionBuilder {
139   public:
140    ElfOatSectionBuilder(const std::string& sec_name, Elf32_Word size, Elf32_Word offset,
141                         Elf32_Word type, Elf32_Word flags)
142        : ElfSectionBuilder(sec_name, type, flags, NULL, 0, kPageSize, 0),
143          offset_(offset), size_(size) {}
144    ~ElfOatSectionBuilder() {}
145
146   protected:
147    // Offset of the content within the file.
148    Elf32_Word offset_;
149    // Size of the content within the file.
150    Elf32_Word size_;
151
152   private:
153    friend class ElfBuilder;
154  };
155
156  class ElfSymtabBuilder : public ElfSectionBuilder {
157   public:
158    // Add a symbol with given name to this symtab. The symbol refers to
159    // 'relative_addr' within the given section and has the given attributes.
160    void AddSymbol(const std::string& name,
161                   const ElfSectionBuilder* section,
162                   Elf32_Addr addr,
163                   bool is_relative,
164                   Elf32_Word size,
165                   uint8_t binding,
166                   uint8_t type,
167                   uint8_t other = 0);
168
169    ElfSymtabBuilder(const std::string& sec_name, Elf32_Word type,
170                     const std::string& str_name, Elf32_Word str_type, bool alloc)
171        : ElfSectionBuilder(sec_name, type, ((alloc) ? SHF_ALLOC : 0U), &strtab_, 0,
172                            sizeof(Elf32_Word), sizeof(Elf32_Sym)),
173          str_name_(str_name), str_type_(str_type),
174          strtab_(str_name, str_type, ((alloc) ? SHF_ALLOC : 0U), NULL, 0, 1, 1) {}
175    ~ElfSymtabBuilder() {}
176
177   protected:
178    std::vector<Elf32_Word> GenerateHashContents();
179    std::string GenerateStrtab();
180    std::vector<Elf32_Sym> GenerateSymtab();
181
182    Elf32_Word GetSize() {
183      // 1 is for the implicit NULL symbol.
184      return symbols_.size() + 1;
185    }
186
187    struct ElfSymbolState {
188      const std::string name_;
189      const ElfSectionBuilder* section_;
190      Elf32_Addr addr_;
191      Elf32_Word size_;
192      bool is_relative_;
193      uint8_t info_;
194      uint8_t other_;
195      // Used during Write() to temporarially hold name index in the strtab.
196      Elf32_Word name_idx_;
197    };
198
199    // Information for the strsym for dynstr sections.
200    const std::string str_name_;
201    Elf32_Word str_type_;
202    // The symbols in the same order they will be in the symbol table.
203    std::vector<ElfSymbolState> symbols_;
204    ElfSectionBuilder strtab_;
205
206   private:
207    friend class ElfBuilder;
208  };
209
210  class ElfBuilder FINAL {
211   public:
212    ElfBuilder(OatWriter* oat_writer,
213               File* elf_file,
214               InstructionSet isa,
215               Elf32_Word rodata_relative_offset,
216               Elf32_Word rodata_size,
217               Elf32_Word text_relative_offset,
218               Elf32_Word text_size,
219               const bool add_symbols,
220               bool debug = false)
221        : oat_writer_(oat_writer),
222          elf_file_(elf_file),
223          add_symbols_(add_symbols),
224          debug_logging_(debug),
225          text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
226                        SHF_ALLOC | SHF_EXECINSTR),
227          rodata_builder_(".rodata", rodata_size, rodata_relative_offset,
228                          SHT_PROGBITS, SHF_ALLOC),
229          dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
230          symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
231          hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0,
232                        sizeof(Elf32_Word), sizeof(Elf32_Word)),
233          dynamic_builder_(".dynamic", &dynsym_builder_),
234          shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
235      SetupEhdr();
236      SetupDynamic();
237      SetupRequiredSymbols();
238      SetISA(isa);
239    }
240    ~ElfBuilder() {}
241
242    bool Write();
243
244    // Adds the given raw section to the builder. This will copy it. The caller
245    // is responsible for deallocating their copy.
246    void RegisterRawSection(ElfRawSectionBuilder bld) {
247      other_builders_.push_back(bld);
248    }
249
250   private:
251    OatWriter* oat_writer_;
252    File* elf_file_;
253    const bool add_symbols_;
254    const bool debug_logging_;
255
256    bool fatal_error_ = false;
257
258    Elf32_Ehdr elf_header_;
259
260   public:
261    ElfOatSectionBuilder text_builder_;
262    ElfOatSectionBuilder rodata_builder_;
263    ElfSymtabBuilder dynsym_builder_;
264    ElfSymtabBuilder symtab_builder_;
265    ElfSectionBuilder hash_builder_;
266    ElfDynamicBuilder dynamic_builder_;
267    ElfSectionBuilder shstrtab_builder_;
268    std::vector<ElfRawSectionBuilder> other_builders_;
269
270   private:
271    void SetISA(InstructionSet isa);
272    void SetupEhdr();
273
274    // Sets up a bunch of the required Dynamic Section entries.
275    // Namely it will initialize all the mandatory ones that it can.
276    // Specifically:
277    // DT_HASH
278    // DT_STRTAB
279    // DT_SYMTAB
280    // DT_SYMENT
281    //
282    // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
283    void SetupDynamic();
284
285    // Sets up the basic dynamic symbols that are needed, namely all those we
286    // can know already.
287    //
288    // Specifically adds:
289    // oatdata
290    // oatexec
291    // oatlastword
292    void SetupRequiredSymbols();
293    void AssignSectionStr(ElfSectionBuilder *builder, std::string* strtab);
294
295    bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.GetSize() > 1; }
296  };
297
298  /*
299   * @brief Generate the DWARF debug_info and debug_abbrev sections
300   * @param oat_writer The Oat file Writer.
301   * @param dbg_info Compilation unit information.
302   * @param dbg_abbrev Abbreviations used to generate dbg_info.
303   * @param dbg_str Debug strings.
304   */
305  void FillInCFIInformation(OatWriter* oat_writer, std::vector<uint8_t>* dbg_info,
306                            std::vector<uint8_t>* dbg_abbrev, std::vector<uint8_t>* dbg_str);
307
308  DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
309};
310
311}  // namespace art
312
313#endif  // ART_COMPILER_ELF_WRITER_QUICK_H_
314