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 
24 namespace art {
25 
26 class 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:
ElfWriterQuick(const CompilerDriver & driver,File * elf_file)46   ElfWriterQuick(const CompilerDriver& driver, File* elf_file)
47     : ElfWriter(driver, elf_file) {}
~ElfWriterQuick()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:
ElfSectionBuilder(const std::string & sec_name,Elf32_Word type,Elf32_Word flags,const ElfSectionBuilder * link,Elf32_Word info,Elf32_Word align,Elf32_Word entsize)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 
~ElfSectionBuilder()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 
GetLink()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 
ElfDynamicBuilder(const std::string & sec_name,ElfSectionBuilder * link)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)) {}
~ElfDynamicBuilder()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_;
GetSize()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:
ElfRawSectionBuilder(const std::string & sec_name,Elf32_Word type,Elf32_Word flags,const ElfSectionBuilder * link,Elf32_Word info,Elf32_Word align,Elf32_Word entsize)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) {}
~ElfRawSectionBuilder()127     ~ElfRawSectionBuilder() {}
GetBuffer()128     std::vector<uint8_t>* GetBuffer() { return &buf_; }
SetBuffer(std::vector<uint8_t> 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:
ElfOatSectionBuilder(const std::string & sec_name,Elf32_Word size,Elf32_Word offset,Elf32_Word type,Elf32_Word flags)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) {}
~ElfOatSectionBuilder()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 
ElfSymtabBuilder(const std::string & sec_name,Elf32_Word type,const std::string & str_name,Elf32_Word str_type,bool alloc)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) {}
~ElfSymtabBuilder()175     ~ElfSymtabBuilder() {}
176 
177    protected:
178     std::vector<Elf32_Word> GenerateHashContents();
179     std::string GenerateStrtab();
180     std::vector<Elf32_Sym> GenerateSymtab();
181 
GetSize()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)
oat_writer_(oat_writer)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     }
~ElfBuilder()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.
RegisterRawSection(ElfRawSectionBuilder bld)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 
IncludingDebugSymbols()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