blob: 890528eed38865ac45f0f876806759a597eb684d [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
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000026template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
27 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
28 typename Elf_Phdr, typename Elf_Shdr>
Ian Rogers3d504072014-03-01 09:16:49 -080029class ElfWriterQuick FINAL : public ElfWriter {
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -070030 public:
31 // Write an ELF file. Returns true on success, false on failure.
32 static bool Create(File* file,
Ian Rogers3d504072014-03-01 09:16:49 -080033 OatWriter* oat_writer,
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -070034 const std::vector<const DexFile*>& dex_files,
35 const std::string& android_root,
36 bool is_host,
37 const CompilerDriver& driver)
38 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
39
40 protected:
Ian Rogers3d504072014-03-01 09:16:49 -080041 bool Write(OatWriter* oat_writer,
42 const std::vector<const DexFile*>& dex_files,
43 const std::string& android_root,
44 bool is_host)
45 OVERRIDE
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -070046 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
47
48 private:
Ian Rogers3d504072014-03-01 09:16:49 -080049 ElfWriterQuick(const CompilerDriver& driver, File* elf_file)
50 : ElfWriter(driver, elf_file) {}
51 ~ElfWriterQuick() {}
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -070052
Brian Carlstromb12f3472014-06-11 14:54:46 -070053 class ElfBuilder;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +070054 void WriteDebugSymbols(ElfBuilder* builder, OatWriter* oat_writer);
Alex Light53cb16b2014-06-12 11:26:29 -070055 void ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug);
Alex Light78382fa2014-06-06 15:45:32 -070056
Brian Carlstromb12f3472014-06-11 14:54:46 -070057 class ElfSectionBuilder {
58 public:
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000059 ElfSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
60 const ElfSectionBuilder *link, Elf_Word info, Elf_Word align,
61 Elf_Word entsize)
Brian Carlstromb12f3472014-06-11 14:54:46 -070062 : name_(sec_name), link_(link) {
63 memset(&section_, 0, sizeof(section_));
64 section_.sh_type = type;
65 section_.sh_flags = flags;
66 section_.sh_info = info;
67 section_.sh_addralign = align;
68 section_.sh_entsize = entsize;
69 }
70
71 virtual ~ElfSectionBuilder() {}
72
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000073 Elf_Shdr section_;
74 Elf_Word section_index_ = 0;
Brian Carlstromb12f3472014-06-11 14:54:46 -070075
76 protected:
77 const std::string name_;
78 const ElfSectionBuilder* link_;
79
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000080 Elf_Word GetLink() {
Brian Carlstromb12f3472014-06-11 14:54:46 -070081 return (link_) ? link_->section_index_ : 0;
82 }
83
84 private:
85 friend class ElfBuilder;
86 };
87
88 class ElfDynamicBuilder : public ElfSectionBuilder {
89 public:
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000090 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un);
91 void AddDynamicTag(Elf_Sword tag, Elf_Word offset, ElfSectionBuilder* section);
Brian Carlstromb12f3472014-06-11 14:54:46 -070092
93 ElfDynamicBuilder(const std::string& sec_name, ElfSectionBuilder *link)
94 : ElfSectionBuilder(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC, link,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +000095 0, kPageSize, sizeof(Elf_Dyn)) {}
Brian Carlstromb12f3472014-06-11 14:54:46 -070096 ~ElfDynamicBuilder() {}
97
98 protected:
99 struct ElfDynamicState {
100 ElfSectionBuilder* section_;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000101 Elf_Sword tag_;
102 Elf_Word off_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700103 };
104 std::vector<ElfDynamicState> dynamics_;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000105 Elf_Word GetSize() {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700106 // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
107 // these must be added when we actually put the file together because
108 // their values are very dependent on state.
109 return dynamics_.size() + 3;
110 }
111
112 // Create the actual dynamic vector. strsz should be the size of the .dynstr
113 // table and soname_off should be the offset of the soname in .dynstr.
114 // Since niether can be found prior to final layout we will wait until here
115 // to add them.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000116 std::vector<Elf_Dyn> GetDynamics(Elf_Word strsz, Elf_Word soname_off);
Brian Carlstromb12f3472014-06-11 14:54:46 -0700117
118 private:
119 friend class ElfBuilder;
120 };
121
122 class ElfRawSectionBuilder : public ElfSectionBuilder {
123 public:
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000124 ElfRawSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
125 const ElfSectionBuilder* link, Elf_Word info, Elf_Word align,
126 Elf_Word entsize)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700127 : ElfSectionBuilder(sec_name, type, flags, link, info, align, entsize) {}
128 ~ElfRawSectionBuilder() {}
129 std::vector<uint8_t>* GetBuffer() { return &buf_; }
Andreas Gampe79273802014-08-05 20:21:05 -0700130 void SetBuffer(std::vector<uint8_t>&& buf) { buf_ = buf; }
Brian Carlstromb12f3472014-06-11 14:54:46 -0700131
132 protected:
133 std::vector<uint8_t> buf_;
134
135 private:
136 friend class ElfBuilder;
137 };
138
139 class ElfOatSectionBuilder : public ElfSectionBuilder {
140 public:
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000141 ElfOatSectionBuilder(const std::string& sec_name, Elf_Word size, Elf_Word offset,
142 Elf_Word type, Elf_Word flags)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700143 : ElfSectionBuilder(sec_name, type, flags, NULL, 0, kPageSize, 0),
144 offset_(offset), size_(size) {}
145 ~ElfOatSectionBuilder() {}
146
147 protected:
148 // Offset of the content within the file.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000149 Elf_Word offset_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700150 // Size of the content within the file.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000151 Elf_Word size_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700152
153 private:
154 friend class ElfBuilder;
155 };
156
157 class ElfSymtabBuilder : public ElfSectionBuilder {
158 public:
159 // Add a symbol with given name to this symtab. The symbol refers to
160 // 'relative_addr' within the given section and has the given attributes.
161 void AddSymbol(const std::string& name,
162 const ElfSectionBuilder* section,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000163 Elf_Addr addr,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700164 bool is_relative,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000165 Elf_Word size,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700166 uint8_t binding,
167 uint8_t type,
168 uint8_t other = 0);
169
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000170 ElfSymtabBuilder(const std::string& sec_name, Elf_Word type,
171 const std::string& str_name, Elf_Word str_type, bool alloc)
Brian Carlstrome130ee62014-07-01 23:54:20 -0700172 : ElfSectionBuilder(sec_name, type, ((alloc) ? SHF_ALLOC : 0U), &strtab_, 0,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000173 sizeof(Elf_Word), sizeof(Elf_Sym)),
Brian Carlstromb12f3472014-06-11 14:54:46 -0700174 str_name_(str_name), str_type_(str_type),
Brian Carlstrome130ee62014-07-01 23:54:20 -0700175 strtab_(str_name, str_type, ((alloc) ? SHF_ALLOC : 0U), NULL, 0, 1, 1) {}
Brian Carlstromb12f3472014-06-11 14:54:46 -0700176 ~ElfSymtabBuilder() {}
177
178 protected:
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000179 std::vector<Elf_Word> GenerateHashContents();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700180 std::string GenerateStrtab();
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000181 std::vector<Elf_Sym> GenerateSymtab();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700182
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000183 Elf_Word GetSize() {
Brian Carlstromb12f3472014-06-11 14:54:46 -0700184 // 1 is for the implicit NULL symbol.
185 return symbols_.size() + 1;
186 }
187
188 struct ElfSymbolState {
189 const std::string name_;
190 const ElfSectionBuilder* section_;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000191 Elf_Addr addr_;
192 Elf_Word size_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700193 bool is_relative_;
194 uint8_t info_;
195 uint8_t other_;
196 // Used during Write() to temporarially hold name index in the strtab.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000197 Elf_Word name_idx_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700198 };
199
200 // Information for the strsym for dynstr sections.
201 const std::string str_name_;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000202 Elf_Word str_type_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700203 // The symbols in the same order they will be in the symbol table.
204 std::vector<ElfSymbolState> symbols_;
205 ElfSectionBuilder strtab_;
206
207 private:
208 friend class ElfBuilder;
209 };
210
211 class ElfBuilder FINAL {
212 public:
213 ElfBuilder(OatWriter* oat_writer,
214 File* elf_file,
215 InstructionSet isa,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000216 Elf_Word rodata_relative_offset,
217 Elf_Word rodata_size,
218 Elf_Word text_relative_offset,
219 Elf_Word text_size,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700220 const bool add_symbols,
221 bool debug = false)
222 : oat_writer_(oat_writer),
223 elf_file_(elf_file),
224 add_symbols_(add_symbols),
225 debug_logging_(debug),
226 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
227 SHF_ALLOC | SHF_EXECINSTR),
228 rodata_builder_(".rodata", rodata_size, rodata_relative_offset,
229 SHT_PROGBITS, SHF_ALLOC),
230 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
231 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
232 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0,
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000233 sizeof(Elf_Word), sizeof(Elf_Word)),
Brian Carlstromb12f3472014-06-11 14:54:46 -0700234 dynamic_builder_(".dynamic", &dynsym_builder_),
235 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
236 SetupEhdr();
237 SetupDynamic();
238 SetupRequiredSymbols();
239 SetISA(isa);
240 }
241 ~ElfBuilder() {}
242
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700243 bool Init();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700244 bool Write();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700245
246 // Adds the given raw section to the builder. This will copy it. The caller
247 // is responsible for deallocating their copy.
248 void RegisterRawSection(ElfRawSectionBuilder bld) {
249 other_builders_.push_back(bld);
250 }
251
252 private:
253 OatWriter* oat_writer_;
254 File* elf_file_;
255 const bool add_symbols_;
256 const bool debug_logging_;
257
258 bool fatal_error_ = false;
259
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700260 // What phdr is.
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000261 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700262 enum : uint8_t {
263 PH_PHDR = 0,
264 PH_LOAD_R__ = 1,
265 PH_LOAD_R_X = 2,
266 PH_LOAD_RW_ = 3,
267 PH_DYNAMIC = 4,
268 PH_NUM = 5,
269 };
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000270 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
271 Elf_Phdr program_headers_[PH_NUM];
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700272
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000273 Elf_Ehdr elf_header_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700274
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000275 Elf_Shdr null_hdr_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700276 std::string shstrtab_;
277 uint32_t section_index_;
278 std::string dynstr_;
279 uint32_t dynstr_soname_offset_;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000280 std::vector<Elf_Shdr*> section_ptrs_;
281 std::vector<Elf_Word> hash_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700282
Brian Carlstromb12f3472014-06-11 14:54:46 -0700283 public:
284 ElfOatSectionBuilder text_builder_;
285 ElfOatSectionBuilder rodata_builder_;
286 ElfSymtabBuilder dynsym_builder_;
287 ElfSymtabBuilder symtab_builder_;
288 ElfSectionBuilder hash_builder_;
289 ElfDynamicBuilder dynamic_builder_;
290 ElfSectionBuilder shstrtab_builder_;
291 std::vector<ElfRawSectionBuilder> other_builders_;
292
293 private:
294 void SetISA(InstructionSet isa);
295 void SetupEhdr();
296
297 // Sets up a bunch of the required Dynamic Section entries.
298 // Namely it will initialize all the mandatory ones that it can.
299 // Specifically:
300 // DT_HASH
301 // DT_STRTAB
302 // DT_SYMTAB
303 // DT_SYMENT
304 //
305 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
306 void SetupDynamic();
307
308 // Sets up the basic dynamic symbols that are needed, namely all those we
309 // can know already.
310 //
311 // Specifically adds:
312 // oatdata
313 // oatexec
314 // oatlastword
315 void SetupRequiredSymbols();
316 void AssignSectionStr(ElfSectionBuilder *builder, std::string* strtab);
317 struct ElfFilePiece {
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000318 ElfFilePiece(const std::string& name, Elf_Word offset, const void* data, Elf_Word size)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700319 : dbg_name_(name), offset_(offset), data_(data), size_(size) {}
320 ~ElfFilePiece() {}
321
322 const std::string& dbg_name_;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000323 Elf_Word offset_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700324 const void *data_;
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000325 Elf_Word size_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700326 static bool Compare(ElfFilePiece a, ElfFilePiece b) {
327 return a.offset_ < b.offset_;
328 }
329 };
330
331 // Write each of the pieces out to the file.
332 bool WriteOutFile(const std::vector<ElfFilePiece>& pieces);
Brian Carlstrom8758c642014-06-11 14:22:02 -0700333 bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.GetSize() > 1; }
Brian Carlstromb12f3472014-06-11 14:54:46 -0700334 };
335
Mark Mendellae9fd932014-02-10 16:14:35 -0800336 /*
337 * @brief Generate the DWARF debug_info and debug_abbrev sections
338 * @param oat_writer The Oat file Writer.
339 * @param dbg_info Compilation unit information.
340 * @param dbg_abbrev Abbreviations used to generate dbg_info.
341 * @param dbg_str Debug strings.
342 */
343 void FillInCFIInformation(OatWriter* oat_writer, std::vector<uint8_t>* dbg_info,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700344 std::vector<uint8_t>* dbg_abbrev, std::vector<uint8_t>* dbg_str,
345 std::vector<uint8_t>* dbg_line, uint32_t text_section_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -0800346
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -0700347 DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
348};
349
Nicolas Geoffrayf9b87b12014-09-02 08:12:09 +0000350// Explicitly instantiated in elf_writer_quick.cc
351typedef ElfWriterQuick<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
352 Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr> ElfWriterQuick32;
353typedef ElfWriterQuick<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn,
354 Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr> ElfWriterQuick64;
355
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -0700356} // namespace art
357
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700358#endif // ART_COMPILER_ELF_WRITER_QUICK_H_