blob: a0d36df4718a8d8c63fec3732d33b0f4c42cf88c [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);
Alex Light53cb16b2014-06-12 11:26:29 -070054 void ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug);
Alex Light78382fa2014-06-06 15:45:32 -070055
Brian Carlstromb12f3472014-06-11 14:54:46 -070056 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:
Brian Carlstrom8758c642014-06-11 14:22:02 -070089 void AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un);
90 void AddDynamicTag(Elf32_Sword tag, Elf32_Word offset, ElfSectionBuilder* section);
Brian Carlstromb12f3472014-06-11 14:54:46 -070091
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_;
Brian Carlstrom8758c642014-06-11 14:22:02 -0700101 Elf32_Word off_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700102 };
103 std::vector<ElfDynamicState> dynamics_;
Brian Carlstrom8758c642014-06-11 14:22:02 -0700104 Elf32_Word GetSize() {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700105 // 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.
Brian Carlstrom8758c642014-06-11 14:22:02 -0700115 std::vector<Elf32_Dyn> GetDynamics(Elf32_Word strsz, Elf32_Word soname_off);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700116
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)
Brian Carlstrome130ee62014-07-01 23:54:20 -0700171 : ElfSectionBuilder(sec_name, type, ((alloc) ? SHF_ALLOC : 0U), &strtab_, 0,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700172 sizeof(Elf32_Word), sizeof(Elf32_Sym)),
173 str_name_(str_name), str_type_(str_type),
Brian Carlstrome130ee62014-07-01 23:54:20 -0700174 strtab_(str_name, str_type, ((alloc) ? SHF_ALLOC : 0U), NULL, 0, 1, 1) {}
Brian Carlstromb12f3472014-06-11 14:54:46 -0700175 ~ElfSymtabBuilder() {}
176
177 protected:
178 std::vector<Elf32_Word> GenerateHashContents();
179 std::string GenerateStrtab();
180 std::vector<Elf32_Sym> GenerateSymtab();
181
Brian Carlstrom8758c642014-06-11 14:22:02 -0700182 Elf32_Word GetSize() {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700183 // 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();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700243
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 struct ElfFilePiece {
295 ElfFilePiece(const std::string& name, Elf32_Word offset, const void* data, Elf32_Word size)
296 : dbg_name_(name), offset_(offset), data_(data), size_(size) {}
297 ~ElfFilePiece() {}
298
299 const std::string& dbg_name_;
300 Elf32_Word offset_;
301 const void *data_;
302 Elf32_Word size_;
303 static bool Compare(ElfFilePiece a, ElfFilePiece b) {
304 return a.offset_ < b.offset_;
305 }
306 };
307
308 // Write each of the pieces out to the file.
309 bool WriteOutFile(const std::vector<ElfFilePiece>& pieces);
Brian Carlstrom8758c642014-06-11 14:22:02 -0700310 bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.GetSize() > 1; }
Brian Carlstromb12f3472014-06-11 14:54:46 -0700311 };
312
Mark Mendellae9fd932014-02-10 16:14:35 -0800313 /*
314 * @brief Generate the DWARF debug_info and debug_abbrev sections
315 * @param oat_writer The Oat file Writer.
316 * @param dbg_info Compilation unit information.
317 * @param dbg_abbrev Abbreviations used to generate dbg_info.
318 * @param dbg_str Debug strings.
319 */
320 void FillInCFIInformation(OatWriter* oat_writer, std::vector<uint8_t>* dbg_info,
321 std::vector<uint8_t>* dbg_abbrev, std::vector<uint8_t>* dbg_str);
322
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -0700323 DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
324};
325
326} // namespace art
327
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700328#endif // ART_COMPILER_ELF_WRITER_QUICK_H_