blob: c7ef8721741e428bb5506ca58c098ec9fd8f60c0 [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;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +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:
Nicolas Geoffray7eebd952014-09-01 15:13:00 +000056 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)
Brian Carlstromb12f3472014-06-11 14:54:46 -070059 : 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
Nicolas Geoffray7eebd952014-09-01 15:13:00 +000070 Elf32_Shdr section_;
71 Elf32_Word section_index_ = 0;
Brian Carlstromb12f3472014-06-11 14:54:46 -070072
73 protected:
74 const std::string name_;
75 const ElfSectionBuilder* link_;
76
Nicolas Geoffray7eebd952014-09-01 15:13:00 +000077 Elf32_Word GetLink() {
Brian Carlstromb12f3472014-06-11 14:54:46 -070078 return (link_) ? link_->section_index_ : 0;
79 }
80
81 private:
82 friend class ElfBuilder;
83 };
84
85 class ElfDynamicBuilder : public ElfSectionBuilder {
86 public:
Nicolas Geoffray7eebd952014-09-01 15:13:00 +000087 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,
Nicolas Geoffray7eebd952014-09-01 15:13:00 +000092 0, kPageSize, sizeof(Elf32_Dyn)) {}
Brian Carlstromb12f3472014-06-11 14:54:46 -070093 ~ElfDynamicBuilder() {}
94
95 protected:
96 struct ElfDynamicState {
97 ElfSectionBuilder* section_;
Nicolas Geoffray7eebd952014-09-01 15:13:00 +000098 Elf32_Sword tag_;
99 Elf32_Word off_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700100 };
101 std::vector<ElfDynamicState> dynamics_;
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000102 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.
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000113 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:
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000121 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)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700124 : 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:
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000138 ElfOatSectionBuilder(const std::string& sec_name, Elf32_Word size, Elf32_Word offset,
139 Elf32_Word type, Elf32_Word flags)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700140 : 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.
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000146 Elf32_Word offset_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700147 // Size of the content within the file.
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000148 Elf32_Word size_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700149
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,
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000160 Elf32_Addr addr,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700161 bool is_relative,
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000162 Elf32_Word size,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700163 uint8_t binding,
164 uint8_t type,
165 uint8_t other = 0);
166
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000167 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,
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000170 sizeof(Elf32_Word), sizeof(Elf32_Sym)),
Brian Carlstromb12f3472014-06-11 14:54:46 -0700171 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:
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000176 std::vector<Elf32_Word> GenerateHashContents();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700177 std::string GenerateStrtab();
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000178 std::vector<Elf32_Sym> GenerateSymtab();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700179
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000180 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_;
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000188 Elf32_Addr addr_;
189 Elf32_Word size_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700190 bool is_relative_;
191 uint8_t info_;
192 uint8_t other_;
193 // Used during Write() to temporarially hold name index in the strtab.
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000194 Elf32_Word name_idx_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700195 };
196
197 // Information for the strsym for dynstr sections.
198 const std::string str_name_;
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000199 Elf32_Word str_type_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700200 // 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,
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000213 Elf32_Word rodata_relative_offset,
214 Elf32_Word rodata_size,
215 Elf32_Word text_relative_offset,
216 Elf32_Word text_size,
Brian Carlstromb12f3472014-06-11 14:54:46 -0700217 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,
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000230 sizeof(Elf32_Word), sizeof(Elf32_Word)),
Brian Carlstromb12f3472014-06-11 14:54:46 -0700231 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
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700240 bool Init();
Brian Carlstromb12f3472014-06-11 14:54:46 -0700241 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
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700257 // What phdr is.
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000258 static const uint32_t PHDR_OFFSET = sizeof(Elf32_Ehdr);
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700259 enum : uint8_t {
260 PH_PHDR = 0,
261 PH_LOAD_R__ = 1,
262 PH_LOAD_R_X = 2,
263 PH_LOAD_RW_ = 3,
264 PH_DYNAMIC = 4,
265 PH_NUM = 5,
266 };
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000267 static const uint32_t PHDR_SIZE = sizeof(Elf32_Phdr) * PH_NUM;
268 Elf32_Phdr program_headers_[PH_NUM];
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700269
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000270 Elf32_Ehdr elf_header_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700271
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000272 Elf32_Shdr null_hdr_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700273 std::string shstrtab_;
274 uint32_t section_index_;
275 std::string dynstr_;
276 uint32_t dynstr_soname_offset_;
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000277 std::vector<Elf32_Shdr*> section_ptrs_;
278 std::vector<Elf32_Word> hash_;
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700279
Brian Carlstromb12f3472014-06-11 14:54:46 -0700280 public:
281 ElfOatSectionBuilder text_builder_;
282 ElfOatSectionBuilder rodata_builder_;
283 ElfSymtabBuilder dynsym_builder_;
284 ElfSymtabBuilder symtab_builder_;
285 ElfSectionBuilder hash_builder_;
286 ElfDynamicBuilder dynamic_builder_;
287 ElfSectionBuilder shstrtab_builder_;
288 std::vector<ElfRawSectionBuilder> other_builders_;
289
290 private:
291 void SetISA(InstructionSet isa);
292 void SetupEhdr();
293
294 // Sets up a bunch of the required Dynamic Section entries.
295 // Namely it will initialize all the mandatory ones that it can.
296 // Specifically:
297 // DT_HASH
298 // DT_STRTAB
299 // DT_SYMTAB
300 // DT_SYMENT
301 //
302 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
303 void SetupDynamic();
304
305 // Sets up the basic dynamic symbols that are needed, namely all those we
306 // can know already.
307 //
308 // Specifically adds:
309 // oatdata
310 // oatexec
311 // oatlastword
312 void SetupRequiredSymbols();
313 void AssignSectionStr(ElfSectionBuilder *builder, std::string* strtab);
314 struct ElfFilePiece {
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000315 ElfFilePiece(const std::string& name, Elf32_Word offset, const void* data, Elf32_Word size)
Brian Carlstromb12f3472014-06-11 14:54:46 -0700316 : dbg_name_(name), offset_(offset), data_(data), size_(size) {}
317 ~ElfFilePiece() {}
318
319 const std::string& dbg_name_;
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000320 Elf32_Word offset_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700321 const void *data_;
Nicolas Geoffray7eebd952014-09-01 15:13:00 +0000322 Elf32_Word size_;
Brian Carlstromb12f3472014-06-11 14:54:46 -0700323 static bool Compare(ElfFilePiece a, ElfFilePiece b) {
324 return a.offset_ < b.offset_;
325 }
326 };
327
328 // Write each of the pieces out to the file.
329 bool WriteOutFile(const std::vector<ElfFilePiece>& pieces);
Brian Carlstrom8758c642014-06-11 14:22:02 -0700330 bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.GetSize() > 1; }
Brian Carlstromb12f3472014-06-11 14:54:46 -0700331 };
332
Mark Mendellae9fd932014-02-10 16:14:35 -0800333 /*
334 * @brief Generate the DWARF debug_info and debug_abbrev sections
335 * @param oat_writer The Oat file Writer.
336 * @param dbg_info Compilation unit information.
337 * @param dbg_abbrev Abbreviations used to generate dbg_info.
338 * @param dbg_str Debug strings.
339 */
340 void FillInCFIInformation(OatWriter* oat_writer, std::vector<uint8_t>* dbg_info,
Yevgeny Roubane3ea8382014-08-08 16:29:38 +0700341 std::vector<uint8_t>* dbg_abbrev, std::vector<uint8_t>* dbg_str,
342 std::vector<uint8_t>* dbg_line, uint32_t text_section_offset);
Mark Mendellae9fd932014-02-10 16:14:35 -0800343
Brian Carlstrom6a47b9d2013-05-17 10:58:25 -0700344 DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
345};
346
347} // namespace art
348
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700349#endif // ART_COMPILER_ELF_WRITER_QUICK_H_