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