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