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