blob: e535b6de5a7ededfb9e23733ce51972479b02906 [file] [log] [blame]
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001/*
2 * Copyright (C) 2014 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
17#ifndef ART_COMPILER_ELF_BUILDER_H_
18#define ART_COMPILER_ELF_BUILDER_H_
19
Andreas Gampecc676072014-09-23 22:58:07 -070020#include "base/stl_util.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070021#include "buffered_output_stream.h"
22#include "elf_utils.h"
23#include "file_output_stream.h"
24#include "instruction_set.h"
25
26namespace art {
27
28template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
29class ElfSectionBuilder {
30 public:
31 ElfSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
32 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link, Elf_Word info,
33 Elf_Word align, Elf_Word entsize) : name_(sec_name), link_(link) {
34 memset(&section_, 0, sizeof(section_));
35 section_.sh_type = type;
36 section_.sh_flags = flags;
37 section_.sh_info = info;
38 section_.sh_addralign = align;
39 section_.sh_entsize = entsize;
40 }
41
42 virtual ~ElfSectionBuilder() {}
43
44 Elf_Shdr section_;
45 Elf_Word section_index_ = 0;
46
47 Elf_Word GetLink() {
48 return (link_) ? link_->section_index_ : 0;
49 }
50
51 const std::string name_;
52
53 protected:
54 const ElfSectionBuilder* link_;
55};
56
57template <typename Elf_Word, typename Elf_Sword, typename Elf_Dyn, typename Elf_Shdr>
58class ElfDynamicBuilder : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
59 public:
60 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un) {
61 if (tag == DT_NULL) {
62 return;
63 }
64 dynamics_.push_back({nullptr, tag, d_un});
65 }
66
67 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un,
68 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section) {
69 if (tag == DT_NULL) {
70 return;
71 }
72 dynamics_.push_back({section, tag, d_un});
73 }
74
75 ElfDynamicBuilder(const std::string& sec_name,
76 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link)
77 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC,
78 link, 0, kPageSize, sizeof(Elf_Dyn)) {}
79 ~ElfDynamicBuilder() {}
80
81 Elf_Word GetSize() {
82 // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
83 // these must be added when we actually put the file together because
84 // their values are very dependent on state.
85 return dynamics_.size() + 3;
86 }
87
88 // Create the actual dynamic vector. strsz should be the size of the .dynstr
89 // table and soname_off should be the offset of the soname in .dynstr.
90 // Since niether can be found prior to final layout we will wait until here
91 // to add them.
92 std::vector<Elf_Dyn> GetDynamics(Elf_Word strsz, Elf_Word soname) {
93 std::vector<Elf_Dyn> ret;
94 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
95 if (it->section_) {
96 // We are adding an address relative to a section.
97 ret.push_back(
98 {it->tag_, {it->off_ + it->section_->section_.sh_addr}});
99 } else {
100 ret.push_back({it->tag_, {it->off_}});
101 }
102 }
103 ret.push_back({DT_STRSZ, {strsz}});
104 ret.push_back({DT_SONAME, {soname}});
105 ret.push_back({DT_NULL, {0}});
106 return ret;
107 }
108
109 protected:
110 struct ElfDynamicState {
111 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_;
112 Elf_Sword tag_;
113 Elf_Word off_;
114 };
115 std::vector<ElfDynamicState> dynamics_;
116};
117
118template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
119class ElfRawSectionBuilder : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
120 public:
121 ElfRawSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
122 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* link, Elf_Word info,
123 Elf_Word align, Elf_Word entsize)
124 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, link, info, align,
125 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
134template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
135class ElfOatSectionBuilder : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
136 public:
137 ElfOatSectionBuilder(const std::string& sec_name, Elf_Word size, Elf_Word offset,
138 Elf_Word type, Elf_Word flags)
139 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, nullptr, 0, kPageSize,
140 0), offset_(offset), size_(size) {}
141 ~ElfOatSectionBuilder() {}
142
143 Elf_Word GetOffset() {
144 return offset_;
145 }
146
147 Elf_Word GetSize() {
148 return size_;
149 }
150
151 protected:
152 // Offset of the content within the file.
153 Elf_Word offset_;
154 // Size of the content within the file.
155 Elf_Word size_;
156};
157
158static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
159 return ((binding) << 4) + ((type) & 0xf);
160}
161
162// from bionic
163static inline unsigned elfhash(const char *_name) {
164 const unsigned char *name = (const unsigned char *) _name;
165 unsigned h = 0, g;
166
167 while (*name) {
168 h = (h << 4) + *name++;
169 g = h & 0xf0000000;
170 h ^= g;
171 h ^= g >> 24;
172 }
173 return h;
174}
175
176template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Sym,
177 typename Elf_Shdr>
178class ElfSymtabBuilder : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
179 public:
180 // Add a symbol with given name to this symtab. The symbol refers to
181 // 'relative_addr' within the given section and has the given attributes.
182 void AddSymbol(const std::string& name,
183 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section,
184 Elf_Addr addr,
185 bool is_relative,
186 Elf_Word size,
187 uint8_t binding,
188 uint8_t type,
189 uint8_t other = 0) {
190 CHECK(section);
191 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
192 MakeStInfo(binding, type), other, 0};
193 symbols_.push_back(state);
194 }
195
196 ElfSymtabBuilder(const std::string& sec_name, Elf_Word type,
197 const std::string& str_name, Elf_Word str_type, bool alloc)
198 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, ((alloc) ? SHF_ALLOC : 0U),
199 &strtab_, 0, sizeof(Elf_Word),
200 sizeof(Elf_Sym)), str_name_(str_name),
201 str_type_(str_type),
202 strtab_(str_name,
203 str_type,
204 ((alloc) ? SHF_ALLOC : 0U),
205 nullptr, 0, 1, 1) {}
206 ~ElfSymtabBuilder() {}
207
208 std::vector<Elf_Word> GenerateHashContents() {
209 // Here is how The ELF hash table works.
210 // There are 3 arrays to worry about.
211 // * The symbol table where the symbol information is.
212 // * The bucket array which is an array of indexes into the symtab and chain.
213 // * The chain array which is also an array of indexes into the symtab and chain.
214 //
215 // Lets say the state is something like this.
216 // +--------+ +--------+ +-----------+
217 // | symtab | | bucket | | chain |
218 // | null | | 1 | | STN_UNDEF |
219 // | <sym1> | | 4 | | 2 |
220 // | <sym2> | | | | 5 |
221 // | <sym3> | | | | STN_UNDEF |
222 // | <sym4> | | | | 3 |
223 // | <sym5> | | | | STN_UNDEF |
224 // +--------+ +--------+ +-----------+
225 //
226 // The lookup process (in python psudocode) is
227 //
228 // def GetSym(name):
229 // # NB STN_UNDEF == 0
230 // indx = bucket[elfhash(name) % num_buckets]
231 // while indx != STN_UNDEF:
232 // if GetSymbolName(symtab[indx]) == name:
233 // return symtab[indx]
234 // indx = chain[indx]
235 // return SYMBOL_NOT_FOUND
236 //
237 // Between bucket and chain arrays every symtab index must be present exactly
238 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
239
240 // Select number of buckets.
241 // This is essentially arbitrary.
242 Elf_Word nbuckets;
243 Elf_Word chain_size = GetSize();
244 if (symbols_.size() < 8) {
245 nbuckets = 2;
246 } else if (symbols_.size() < 32) {
247 nbuckets = 4;
248 } else if (symbols_.size() < 256) {
249 nbuckets = 16;
250 } else {
251 // Have about 32 ids per bucket.
252 nbuckets = RoundUp(symbols_.size()/32, 2);
253 }
254 std::vector<Elf_Word> hash;
255 hash.push_back(nbuckets);
256 hash.push_back(chain_size);
257 uint32_t bucket_offset = hash.size();
258 uint32_t chain_offset = bucket_offset + nbuckets;
259 hash.resize(hash.size() + nbuckets + chain_size, 0);
260
261 Elf_Word* buckets = hash.data() + bucket_offset;
262 Elf_Word* chain = hash.data() + chain_offset;
263
264 // Set up the actual hash table.
265 for (Elf_Word i = 0; i < symbols_.size(); i++) {
266 // Add 1 since we need to have the null symbol that is not in the symbols
267 // list.
268 Elf_Word index = i + 1;
269 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
270 if (buckets[hash_val] == 0) {
271 buckets[hash_val] = index;
272 } else {
273 hash_val = buckets[hash_val];
274 CHECK_LT(hash_val, chain_size);
275 while (chain[hash_val] != 0) {
276 hash_val = chain[hash_val];
277 CHECK_LT(hash_val, chain_size);
278 }
279 chain[hash_val] = index;
280 // Check for loops. Works because if this is non-empty then there must be
281 // another cell which already contains the same symbol index as this one,
282 // which means some symbol has more then one name, which isn't allowed.
283 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
284 }
285 }
286
287 return hash;
288 }
289
290 std::string GenerateStrtab() {
291 std::string tab;
292 tab += '\0';
293 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
294 it->name_idx_ = tab.size();
295 tab += it->name_;
296 tab += '\0';
297 }
298 strtab_.section_.sh_size = tab.size();
299 return tab;
300 }
301
302 std::vector<Elf_Sym> GenerateSymtab() {
303 std::vector<Elf_Sym> ret;
304 Elf_Sym undef_sym;
305 memset(&undef_sym, 0, sizeof(undef_sym));
306 undef_sym.st_shndx = SHN_UNDEF;
307 ret.push_back(undef_sym);
308
309 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
310 Elf_Sym sym;
311 memset(&sym, 0, sizeof(sym));
312 sym.st_name = it->name_idx_;
313 if (it->is_relative_) {
314 sym.st_value = it->addr_ + it->section_->section_.sh_offset;
315 } else {
316 sym.st_value = it->addr_;
317 }
318 sym.st_size = it->size_;
319 sym.st_other = it->other_;
320 sym.st_shndx = it->section_->section_index_;
321 sym.st_info = it->info_;
322
323 ret.push_back(sym);
324 }
325 return ret;
326 }
327
328 Elf_Word GetSize() {
329 // 1 is for the implicit NULL symbol.
330 return symbols_.size() + 1;
331 }
332
333 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* GetStrTab() {
334 return &strtab_;
335 }
336
337 protected:
338 struct ElfSymbolState {
339 const std::string name_;
340 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_;
341 Elf_Addr addr_;
342 Elf_Word size_;
343 bool is_relative_;
344 uint8_t info_;
345 uint8_t other_;
346 // Used during Write() to temporarially hold name index in the strtab.
347 Elf_Word name_idx_;
348 };
349
350 // Information for the strsym for dynstr sections.
351 const std::string str_name_;
352 Elf_Word str_type_;
353 // The symbols in the same order they will be in the symbol table.
354 std::vector<ElfSymbolState> symbols_;
355 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> strtab_;
356};
357
Andreas Gampecc676072014-09-23 22:58:07 -0700358template <typename Elf_Word>
359class ElfFilePiece {
360 public:
361 virtual ~ElfFilePiece() {}
362
363 virtual bool Write(File* elf_file) {
364 if (static_cast<off_t>(offset_) != lseek(elf_file->Fd(), offset_, SEEK_SET)) {
365 PLOG(ERROR) << "Failed to seek to " << GetDescription() << " offset " << offset_ << " for "
366 << elf_file->GetPath();
367 return false;
368 }
369
370 return DoActualWrite(elf_file);
371 }
372
373 static bool Compare(ElfFilePiece* a, ElfFilePiece* b) {
374 return a->offset_ < b->offset_;
375 }
376
377 protected:
378 explicit ElfFilePiece(Elf_Word offset) : offset_(offset) {}
379
380 virtual std::string GetDescription() = 0;
381 virtual bool DoActualWrite(File* elf_file) = 0;
382
383 Elf_Word offset_;
384};
385
386template <typename Elf_Word>
387class ElfFileMemoryPiece : public ElfFilePiece<Elf_Word> {
388 public:
389 ElfFileMemoryPiece(const std::string& name, Elf_Word offset, const void* data, Elf_Word size)
390 : ElfFilePiece<Elf_Word>(offset), dbg_name_(name), data_(data), size_(size) {}
391
392 bool DoActualWrite(File* elf_file) OVERRIDE {
393 DCHECK(data_ != nullptr || size_ == 0U) << dbg_name_ << " " << size_;
394
395 if (!elf_file->WriteFully(data_, size_)) {
396 PLOG(ERROR) << "Failed to write " << dbg_name_ << " for " << elf_file->GetPath();
397 return false;
398 }
399
400 return true;
401 }
402
403 std::string GetDescription() OVERRIDE {
404 return dbg_name_;
405 }
406
407 private:
408 const std::string& dbg_name_;
409 const void *data_;
410 Elf_Word size_;
411};
412
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700413class CodeOutput {
414 public:
415 virtual bool Write(OutputStream* out) = 0;
416 virtual ~CodeOutput() {}
417};
418
Andreas Gampecc676072014-09-23 22:58:07 -0700419template <typename Elf_Word>
420class ElfFileRodataPiece : public ElfFilePiece<Elf_Word> {
421 public:
422 ElfFileRodataPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
423 output_(output) {}
424
425 bool DoActualWrite(File* elf_file) OVERRIDE {
426 std::unique_ptr<BufferedOutputStream> output_stream(
427 new BufferedOutputStream(new FileOutputStream(elf_file)));
428 if (!output_->Write(output_stream.get())) {
429 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file->GetPath();
430 return false;
431 }
432
433 return true;
434 }
435
436 std::string GetDescription() OVERRIDE {
437 return ".rodata";
438 }
439
440 private:
441 CodeOutput* output_;
442};
443
444template <typename Elf_Word>
445class ElfFileOatTextPiece : public ElfFilePiece<Elf_Word> {
446 public:
447 ElfFileOatTextPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
448 output_(output) {}
449
450 bool DoActualWrite(File* elf_file) OVERRIDE {
451 // All data is written by the ElfFileRodataPiece right now, as the oat writer writes in one
452 // piece. This is for future flexibility.
453 UNUSED(output_);
454 return true;
455 }
456
457 std::string GetDescription() OVERRIDE {
458 return ".text";
459 }
460
461 private:
462 CodeOutput* output_;
463};
464
465template <typename Elf_Word>
466static bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces, File* elf_file) {
467 // TODO It would be nice if this checked for overlap.
468 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
469 if (!(*it)->Write(elf_file)) {
470 return false;
471 }
472 }
473 return true;
474}
475
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700476template <typename Elf_Word, typename Elf_Shdr>
477static inline constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) {
478 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
479}
480
481template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Dyn,
482 typename Elf_Sym, typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr>
483class ElfBuilder FINAL {
484 public:
485 ElfBuilder(CodeOutput* oat_writer,
486 File* elf_file,
487 InstructionSet isa,
488 Elf_Word rodata_relative_offset,
489 Elf_Word rodata_size,
490 Elf_Word text_relative_offset,
491 Elf_Word text_size,
492 const bool add_symbols,
493 bool debug = false)
494 : oat_writer_(oat_writer),
495 elf_file_(elf_file),
496 add_symbols_(add_symbols),
497 debug_logging_(debug),
498 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
499 SHF_ALLOC | SHF_EXECINSTR),
500 rodata_builder_(".rodata", rodata_size, rodata_relative_offset, SHT_PROGBITS, SHF_ALLOC),
501 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
502 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
503 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0, sizeof(Elf_Word),
504 sizeof(Elf_Word)),
505 dynamic_builder_(".dynamic", &dynsym_builder_),
506 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
507 SetupEhdr();
508 SetupDynamic();
509 SetupRequiredSymbols();
510 SetISA(isa);
511 }
512 ~ElfBuilder() {}
513
514 bool Init() {
515 // The basic layout of the elf file. Order may be different in final output.
516 // +-------------------------+
517 // | Elf_Ehdr |
518 // +-------------------------+
519 // | Elf_Phdr PHDR |
520 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata
521 // | Elf_Phdr LOAD R X | .text
522 // | Elf_Phdr LOAD RW | .dynamic
523 // | Elf_Phdr DYNAMIC | .dynamic
524 // +-------------------------+
525 // | .dynsym |
526 // | Elf_Sym STN_UNDEF |
527 // | Elf_Sym oatdata |
528 // | Elf_Sym oatexec |
529 // | Elf_Sym oatlastword |
530 // +-------------------------+
531 // | .dynstr |
532 // | \0 |
533 // | oatdata\0 |
534 // | oatexec\0 |
535 // | oatlastword\0 |
536 // | boot.oat\0 |
537 // +-------------------------+
538 // | .hash |
539 // | Elf_Word nbucket = b |
540 // | Elf_Word nchain = c |
541 // | Elf_Word bucket[0] |
542 // | ... |
543 // | Elf_Word bucket[b - 1] |
544 // | Elf_Word chain[0] |
545 // | ... |
546 // | Elf_Word chain[c - 1] |
547 // +-------------------------+
548 // | .rodata |
549 // | oatdata..oatexec-4 |
550 // +-------------------------+
551 // | .text |
552 // | oatexec..oatlastword |
553 // +-------------------------+
554 // | .dynamic |
555 // | Elf_Dyn DT_SONAME |
556 // | Elf_Dyn DT_HASH |
557 // | Elf_Dyn DT_SYMTAB |
558 // | Elf_Dyn DT_SYMENT |
559 // | Elf_Dyn DT_STRTAB |
560 // | Elf_Dyn DT_STRSZ |
561 // | Elf_Dyn DT_NULL |
562 // +-------------------------+ (Optional)
563 // | .strtab | (Optional)
564 // | program symbol names | (Optional)
565 // +-------------------------+ (Optional)
566 // | .symtab | (Optional)
567 // | program symbols | (Optional)
568 // +-------------------------+
569 // | .shstrtab |
570 // | \0 |
571 // | .dynamic\0 |
572 // | .dynsym\0 |
573 // | .dynstr\0 |
574 // | .hash\0 |
575 // | .rodata\0 |
576 // | .text\0 |
577 // | .shstrtab\0 |
578 // | .symtab\0 | (Optional)
579 // | .strtab\0 | (Optional)
580 // | .debug_str\0 | (Optional)
581 // | .debug_info\0 | (Optional)
582 // | .eh_frame\0 | (Optional)
583 // | .debug_line\0 | (Optional)
584 // | .debug_abbrev\0 | (Optional)
585 // +-------------------------+ (Optional)
586 // | .debug_info | (Optional)
587 // +-------------------------+ (Optional)
588 // | .debug_abbrev | (Optional)
589 // +-------------------------+ (Optional)
590 // | .eh_frame | (Optional)
591 // +-------------------------+ (Optional)
592 // | .debug_line | (Optional)
593 // +-------------------------+ (Optional)
594 // | .debug_str | (Optional)
595 // +-------------------------+ (Optional)
596 // | Elf_Shdr NULL |
597 // | Elf_Shdr .dynsym |
598 // | Elf_Shdr .dynstr |
599 // | Elf_Shdr .hash |
600 // | Elf_Shdr .text |
601 // | Elf_Shdr .rodata |
602 // | Elf_Shdr .dynamic |
603 // | Elf_Shdr .shstrtab |
604 // | Elf_Shdr .debug_info | (Optional)
605 // | Elf_Shdr .debug_abbrev | (Optional)
606 // | Elf_Shdr .eh_frame | (Optional)
607 // | Elf_Shdr .debug_line | (Optional)
608 // | Elf_Shdr .debug_str | (Optional)
609 // +-------------------------+
610
611 if (fatal_error_) {
612 return false;
613 }
614 // Step 1. Figure out all the offsets.
615
616 if (debug_logging_) {
617 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
618 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
619 }
620
621 memset(&program_headers_, 0, sizeof(program_headers_));
622 program_headers_[PH_PHDR].p_type = PT_PHDR;
623 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET;
624 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET;
625 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET;
626 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_);
627 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_);
628 program_headers_[PH_PHDR].p_flags = PF_R;
629 program_headers_[PH_PHDR].p_align = sizeof(Elf_Word);
630
631 program_headers_[PH_LOAD_R__].p_type = PT_LOAD;
632 program_headers_[PH_LOAD_R__].p_offset = 0;
633 program_headers_[PH_LOAD_R__].p_vaddr = 0;
634 program_headers_[PH_LOAD_R__].p_paddr = 0;
635 program_headers_[PH_LOAD_R__].p_flags = PF_R;
636
637 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD;
638 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X;
639
640 program_headers_[PH_LOAD_RW_].p_type = PT_LOAD;
641 program_headers_[PH_LOAD_RW_].p_flags = PF_R | PF_W;
642
643 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC;
644 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W;
645
646 // Get the dynstr string.
647 dynstr_ = dynsym_builder_.GenerateStrtab();
648
649 // Add the SONAME to the dynstr.
650 dynstr_soname_offset_ = dynstr_.size();
651 std::string file_name(elf_file_->GetPath());
652 size_t directory_separator_pos = file_name.rfind('/');
653 if (directory_separator_pos != std::string::npos) {
654 file_name = file_name.substr(directory_separator_pos + 1);
655 }
656 dynstr_ += file_name;
657 dynstr_ += '\0';
658 if (debug_logging_) {
659 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size()
660 << std::hex << " " << dynstr_.size();
661 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
662 << std::hex << " " << dynsym_builder_.GetSize();
663 }
664
665 // Get the section header string table.
666 shstrtab_ += '\0';
667
668 // Setup sym_undef
669 memset(&null_hdr_, 0, sizeof(null_hdr_));
670 null_hdr_.sh_type = SHT_NULL;
671 null_hdr_.sh_link = SHN_UNDEF;
672 section_ptrs_.push_back(&null_hdr_);
673
674 section_index_ = 1;
675
676 // setup .dynsym
677 section_ptrs_.push_back(&dynsym_builder_.section_);
678 AssignSectionStr(&dynsym_builder_, &shstrtab_);
679 dynsym_builder_.section_index_ = section_index_++;
680
681 // Setup .dynstr
682 section_ptrs_.push_back(&dynsym_builder_.GetStrTab()->section_);
683 AssignSectionStr(dynsym_builder_.GetStrTab(), &shstrtab_);
684 dynsym_builder_.GetStrTab()->section_index_ = section_index_++;
685
686 // Setup .hash
687 section_ptrs_.push_back(&hash_builder_.section_);
688 AssignSectionStr(&hash_builder_, &shstrtab_);
689 hash_builder_.section_index_ = section_index_++;
690
691 // Setup .rodata
692 section_ptrs_.push_back(&rodata_builder_.section_);
693 AssignSectionStr(&rodata_builder_, &shstrtab_);
694 rodata_builder_.section_index_ = section_index_++;
695
696 // Setup .text
697 section_ptrs_.push_back(&text_builder_.section_);
698 AssignSectionStr(&text_builder_, &shstrtab_);
699 text_builder_.section_index_ = section_index_++;
700
701 // Setup .dynamic
702 section_ptrs_.push_back(&dynamic_builder_.section_);
703 AssignSectionStr(&dynamic_builder_, &shstrtab_);
704 dynamic_builder_.section_index_ = section_index_++;
705
706 // Fill in the hash section.
707 hash_ = dynsym_builder_.GenerateHashContents();
708
709 if (debug_logging_) {
710 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
711 << std::hex << " " << hash_.size() * sizeof(Elf_Word);
712 }
713
714 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
715
716 // Get the layout in the sections.
717 //
718 // Get the layout of the dynsym section.
719 dynsym_builder_.section_.sh_offset = RoundUp(base_offset, dynsym_builder_.section_.sh_addralign);
720 dynsym_builder_.section_.sh_addr = dynsym_builder_.section_.sh_offset;
721 dynsym_builder_.section_.sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
722 dynsym_builder_.section_.sh_link = dynsym_builder_.GetLink();
723
724 // Get the layout of the dynstr section.
725 dynsym_builder_.GetStrTab()->section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
726 (dynsym_builder_.GetStrTab()->section_,
727 dynsym_builder_.section_);
728 dynsym_builder_.GetStrTab()->section_.sh_addr = dynsym_builder_.GetStrTab()->section_.sh_offset;
729 dynsym_builder_.GetStrTab()->section_.sh_size = dynstr_.size();
730 dynsym_builder_.GetStrTab()->section_.sh_link = dynsym_builder_.GetStrTab()->GetLink();
731
732 // Get the layout of the hash section
733 hash_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
734 (hash_builder_.section_,
735 dynsym_builder_.GetStrTab()->section_);
736 hash_builder_.section_.sh_addr = hash_builder_.section_.sh_offset;
737 hash_builder_.section_.sh_size = hash_.size() * sizeof(Elf_Word);
738 hash_builder_.section_.sh_link = hash_builder_.GetLink();
739
740 // Get the layout of the rodata section.
741 rodata_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
742 (rodata_builder_.section_,
743 hash_builder_.section_);
744 rodata_builder_.section_.sh_addr = rodata_builder_.section_.sh_offset;
745 rodata_builder_.section_.sh_size = rodata_builder_.GetSize();
746 rodata_builder_.section_.sh_link = rodata_builder_.GetLink();
747
748 // Get the layout of the text section.
749 text_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
750 (text_builder_.section_, rodata_builder_.section_);
751 text_builder_.section_.sh_addr = text_builder_.section_.sh_offset;
752 text_builder_.section_.sh_size = text_builder_.GetSize();
753 text_builder_.section_.sh_link = text_builder_.GetLink();
754 CHECK_ALIGNED(rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size, kPageSize);
755
756 // Get the layout of the dynamic section.
757 dynamic_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
758 (dynamic_builder_.section_,
759 text_builder_.section_);
760 dynamic_builder_.section_.sh_addr = dynamic_builder_.section_.sh_offset;
761 dynamic_builder_.section_.sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
762 dynamic_builder_.section_.sh_link = dynamic_builder_.GetLink();
763
764 if (debug_logging_) {
765 LOG(INFO) << "dynsym off=" << dynsym_builder_.section_.sh_offset
766 << " dynsym size=" << dynsym_builder_.section_.sh_size;
767 LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->section_.sh_offset
768 << " dynstr size=" << dynsym_builder_.GetStrTab()->section_.sh_size;
769 LOG(INFO) << "hash off=" << hash_builder_.section_.sh_offset
770 << " hash size=" << hash_builder_.section_.sh_size;
771 LOG(INFO) << "rodata off=" << rodata_builder_.section_.sh_offset
772 << " rodata size=" << rodata_builder_.section_.sh_size;
773 LOG(INFO) << "text off=" << text_builder_.section_.sh_offset
774 << " text size=" << text_builder_.section_.sh_size;
775 LOG(INFO) << "dynamic off=" << dynamic_builder_.section_.sh_offset
776 << " dynamic size=" << dynamic_builder_.section_.sh_size;
777 }
778
779 return true;
780 }
781
782 bool Write() {
Andreas Gampecc676072014-09-23 22:58:07 -0700783 std::vector<ElfFilePiece<Elf_Word>*> pieces;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700784 Elf_Shdr prev = dynamic_builder_.section_;
785 std::string strtab;
786
787 if (IncludingDebugSymbols()) {
788 // Setup .symtab
789 section_ptrs_.push_back(&symtab_builder_.section_);
790 AssignSectionStr(&symtab_builder_, &shstrtab_);
791 symtab_builder_.section_index_ = section_index_++;
792
793 // Setup .strtab
794 section_ptrs_.push_back(&symtab_builder_.GetStrTab()->section_);
795 AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
796 symtab_builder_.GetStrTab()->section_index_ = section_index_++;
797
798 strtab = symtab_builder_.GenerateStrtab();
799 if (debug_logging_) {
800 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
801 << std::hex << " " << strtab.size();
802 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
803 << std::hex << " " << symtab_builder_.GetSize();
804 }
805 }
806
807 // Setup all the other sections.
808 for (ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder = other_builders_.data(),
809 *end = builder + other_builders_.size();
810 builder != end; ++builder) {
811 section_ptrs_.push_back(&builder->section_);
812 AssignSectionStr(builder, &shstrtab_);
813 builder->section_index_ = section_index_++;
814 }
815
816 // Setup shstrtab
817 section_ptrs_.push_back(&shstrtab_builder_.section_);
818 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
819 shstrtab_builder_.section_index_ = section_index_++;
820
821 if (debug_logging_) {
822 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
823 << std::hex << " " << shstrtab_.size();
824 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
825 << std::hex << " " << section_ptrs_.size();
826 }
827
828 if (IncludingDebugSymbols()) {
829 // Get the layout of the symtab section.
830 symtab_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
831 (symtab_builder_.section_,
832 dynamic_builder_.section_);
833 symtab_builder_.section_.sh_addr = 0;
834 // Add to leave space for the null symbol.
835 symtab_builder_.section_.sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
836 symtab_builder_.section_.sh_link = symtab_builder_.GetLink();
837
838 // Get the layout of the dynstr section.
839 symtab_builder_.GetStrTab()->section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
840 (symtab_builder_.GetStrTab()->section_,
841 symtab_builder_.section_);
842 symtab_builder_.GetStrTab()->section_.sh_addr = 0;
843 symtab_builder_.GetStrTab()->section_.sh_size = strtab.size();
844 symtab_builder_.GetStrTab()->section_.sh_link = symtab_builder_.GetStrTab()->GetLink();
845
846 prev = symtab_builder_.GetStrTab()->section_;
847 if (debug_logging_) {
848 LOG(INFO) << "symtab off=" << symtab_builder_.section_.sh_offset
849 << " symtab size=" << symtab_builder_.section_.sh_size;
850 LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->section_.sh_offset
851 << " strtab size=" << symtab_builder_.GetStrTab()->section_.sh_size;
852 }
853 }
854
855 // Get the layout of the extra sections. (This will deal with the debug
856 // sections if they are there)
857 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
858 it->section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>(it->section_, prev);
859 it->section_.sh_addr = 0;
860 it->section_.sh_size = it->GetBuffer()->size();
861 it->section_.sh_link = it->GetLink();
Andreas Gampecc676072014-09-23 22:58:07 -0700862
863 // We postpone adding an ElfFilePiece to keep the order in "pieces."
864
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700865 prev = it->section_;
866 if (debug_logging_) {
867 LOG(INFO) << it->name_ << " off=" << it->section_.sh_offset
868 << " size=" << it->section_.sh_size;
869 }
870 }
871
872 // Get the layout of the shstrtab section
873 shstrtab_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
874 (shstrtab_builder_.section_, prev);
875 shstrtab_builder_.section_.sh_addr = 0;
876 shstrtab_builder_.section_.sh_size = shstrtab_.size();
877 shstrtab_builder_.section_.sh_link = shstrtab_builder_.GetLink();
878 if (debug_logging_) {
879 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.section_.sh_offset
880 << " shstrtab size=" << shstrtab_builder_.section_.sh_size;
881 }
882
883 // The section list comes after come after.
884 Elf_Word sections_offset = RoundUp(
885 shstrtab_builder_.section_.sh_offset + shstrtab_builder_.section_.sh_size,
886 sizeof(Elf_Word));
887
888 // Setup the actual symbol arrays.
889 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
890 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.section_.sh_size);
891 std::vector<Elf_Sym> symtab;
892 if (IncludingDebugSymbols()) {
893 symtab = symtab_builder_.GenerateSymtab();
894 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.section_.sh_size);
895 }
896
897 // Setup the dynamic section.
898 // This will add the 2 values we cannot know until now time, namely the size
899 // and the soname_offset.
900 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
901 dynstr_soname_offset_);
902 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.section_.sh_size);
903
904 // Finish setup of the program headers now that we know the layout of the
905 // whole file.
906 Elf_Word load_r_size = rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size;
907 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
908 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
909 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.section_.sh_addralign;
910
911 Elf_Word load_rx_size = text_builder_.section_.sh_size;
912 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.section_.sh_offset;
913 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.section_.sh_offset;
914 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.section_.sh_offset;
915 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
916 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
917 program_headers_[PH_LOAD_R_X].p_align = text_builder_.section_.sh_addralign;
918
919 program_headers_[PH_LOAD_RW_].p_offset = dynamic_builder_.section_.sh_offset;
920 program_headers_[PH_LOAD_RW_].p_vaddr = dynamic_builder_.section_.sh_offset;
921 program_headers_[PH_LOAD_RW_].p_paddr = dynamic_builder_.section_.sh_offset;
922 program_headers_[PH_LOAD_RW_].p_filesz = dynamic_builder_.section_.sh_size;
923 program_headers_[PH_LOAD_RW_].p_memsz = dynamic_builder_.section_.sh_size;
924 program_headers_[PH_LOAD_RW_].p_align = dynamic_builder_.section_.sh_addralign;
925
926 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.section_.sh_offset;
927 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.section_.sh_offset;
928 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.section_.sh_offset;
929 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.section_.sh_size;
930 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.section_.sh_size;
931 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.section_.sh_addralign;
932
933 // Finish setup of the Ehdr values.
934 elf_header_.e_phoff = PHDR_OFFSET;
935 elf_header_.e_shoff = sections_offset;
936 elf_header_.e_phnum = PH_NUM;
937 elf_header_.e_shnum = section_ptrs_.size();
938 elf_header_.e_shstrndx = shstrtab_builder_.section_index_;
939
940 // Add the rest of the pieces to the list.
Andreas Gampecc676072014-09-23 22:58:07 -0700941 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_,
942 sizeof(elf_header_)));
943 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
944 &program_headers_, sizeof(program_headers_)));
945 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic",
946 dynamic_builder_.section_.sh_offset,
947 dynamic.data(),
948 dynamic_builder_.section_.sh_size));
949 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.section_.sh_offset,
950 dynsym.data(),
951 dynsym.size() * sizeof(Elf_Sym)));
952 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr",
953 dynsym_builder_.GetStrTab()->section_.sh_offset,
954 dynstr_.c_str(), dynstr_.size()));
955 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.section_.sh_offset,
956 hash_.data(),
957 hash_.size() * sizeof(Elf_Word)));
958 pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.section_.sh_offset,
959 oat_writer_));
960 pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.section_.sh_offset,
961 oat_writer_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700962 if (IncludingDebugSymbols()) {
Andreas Gampecc676072014-09-23 22:58:07 -0700963 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab",
964 symtab_builder_.section_.sh_offset,
965 symtab.data(),
966 symtab.size() * sizeof(Elf_Sym)));
967 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab",
968 symtab_builder_.GetStrTab()->section_.sh_offset,
969 strtab.c_str(), strtab.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700970 }
Andreas Gampecc676072014-09-23 22:58:07 -0700971 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab",
972 shstrtab_builder_.section_.sh_offset,
973 &shstrtab_[0], shstrtab_.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700974 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
975 // Just add all the sections in induvidually since they are all over the
976 // place on the heap/stack.
977 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
Andreas Gampecc676072014-09-23 22:58:07 -0700978 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off,
979 section_ptrs_[i], sizeof(Elf_Shdr)));
980 }
981
982 // Postponed debug info.
983 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
984 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->name_, it->section_.sh_offset,
985 it->GetBuffer()->data(),
986 it->GetBuffer()->size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700987 }
988
989 if (!WriteOutFile(pieces)) {
990 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
Andreas Gampecc676072014-09-23 22:58:07 -0700991
992 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700993 return false;
994 }
995
Andreas Gampecc676072014-09-23 22:58:07 -0700996 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700997 return true;
998 }
999
1000 // Adds the given raw section to the builder. This will copy it. The caller
1001 // is responsible for deallocating their copy.
1002 void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bld) {
1003 other_builders_.push_back(bld);
1004 }
1005
1006 private:
1007 CodeOutput* oat_writer_;
1008 File* elf_file_;
1009 const bool add_symbols_;
1010 const bool debug_logging_;
1011
1012 bool fatal_error_ = false;
1013
1014 // What phdr is.
1015 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
1016 enum : uint8_t {
1017 PH_PHDR = 0,
1018 PH_LOAD_R__ = 1,
1019 PH_LOAD_R_X = 2,
1020 PH_LOAD_RW_ = 3,
1021 PH_DYNAMIC = 4,
1022 PH_NUM = 5,
1023 };
1024 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
1025 Elf_Phdr program_headers_[PH_NUM];
1026
1027 Elf_Ehdr elf_header_;
1028
1029 Elf_Shdr null_hdr_;
1030 std::string shstrtab_;
1031 uint32_t section_index_;
1032 std::string dynstr_;
1033 uint32_t dynstr_soname_offset_;
1034 std::vector<Elf_Shdr*> section_ptrs_;
1035 std::vector<Elf_Word> hash_;
1036
1037 public:
1038 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> text_builder_;
1039 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> rodata_builder_;
1040 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> dynsym_builder_;
1041 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> symtab_builder_;
1042 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> hash_builder_;
1043 ElfDynamicBuilder<Elf_Word, Elf_Sword, Elf_Dyn, Elf_Shdr> dynamic_builder_;
1044 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> shstrtab_builder_;
1045 std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>> other_builders_;
1046
1047 private:
1048 void SetISA(InstructionSet isa) {
1049 switch (isa) {
1050 case kArm:
1051 // Fall through.
1052 case kThumb2: {
1053 elf_header_.e_machine = EM_ARM;
1054 elf_header_.e_flags = EF_ARM_EABI_VER5;
1055 break;
1056 }
1057 case kArm64: {
1058 elf_header_.e_machine = EM_AARCH64;
1059 elf_header_.e_flags = 0;
1060 break;
1061 }
1062 case kX86: {
1063 elf_header_.e_machine = EM_386;
1064 elf_header_.e_flags = 0;
1065 break;
1066 }
1067 case kX86_64: {
1068 elf_header_.e_machine = EM_X86_64;
1069 elf_header_.e_flags = 0;
1070 break;
1071 }
1072 case kMips: {
1073 elf_header_.e_machine = EM_MIPS;
1074 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1075 EF_MIPS_PIC |
1076 EF_MIPS_CPIC |
1077 EF_MIPS_ABI_O32 |
1078 EF_MIPS_ARCH_32R2);
1079 break;
1080 }
1081 default: {
1082 fatal_error_ = true;
1083 LOG(FATAL) << "Unknown instruction set: " << isa;
1084 break;
1085 }
1086 }
1087 }
1088
1089 void SetupEhdr() {
1090 memset(&elf_header_, 0, sizeof(elf_header_));
1091 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
1092 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
1093 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
1094 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
1095 elf_header_.e_ident[EI_CLASS] = ELFCLASS32;
1096 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
1097 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
1098 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
1099 elf_header_.e_ident[EI_ABIVERSION] = 0;
1100 elf_header_.e_type = ET_DYN;
1101 elf_header_.e_version = 1;
1102 elf_header_.e_entry = 0;
1103 elf_header_.e_ehsize = sizeof(Elf_Ehdr);
1104 elf_header_.e_phentsize = sizeof(Elf_Phdr);
1105 elf_header_.e_shentsize = sizeof(Elf_Shdr);
1106 elf_header_.e_phoff = sizeof(Elf_Ehdr);
1107 }
1108
1109 // Sets up a bunch of the required Dynamic Section entries.
1110 // Namely it will initialize all the mandatory ones that it can.
1111 // Specifically:
1112 // DT_HASH
1113 // DT_STRTAB
1114 // DT_SYMTAB
1115 // DT_SYMENT
1116 //
1117 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
1118 void SetupDynamic() {
1119 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
1120 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1121 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1122 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1123 }
1124
1125 // Sets up the basic dynamic symbols that are needed, namely all those we
1126 // can know already.
1127 //
1128 // Specifically adds:
1129 // oatdata
1130 // oatexec
1131 // oatlastword
1132 void SetupRequiredSymbols() {
1133 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1134 rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1135 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1136 text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1137 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1138 true, 4, STB_GLOBAL, STT_OBJECT);
1139 }
1140
1141 void AssignSectionStr(ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder,
1142 std::string* strtab) {
1143 builder->section_.sh_name = strtab->size();
1144 *strtab += builder->name_;
1145 *strtab += '\0';
1146 if (debug_logging_) {
1147 LOG(INFO) << "adding section name \"" << builder->name_ << "\" "
1148 << "to shstrtab at offset " << builder->section_.sh_name;
1149 }
1150 }
1151
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001152
1153 // Write each of the pieces out to the file.
Andreas Gampecc676072014-09-23 22:58:07 -07001154 bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001155 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
Andreas Gampecc676072014-09-23 22:58:07 -07001156 if (!(*it)->Write(elf_file_)) {
1157 return false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001158 }
1159 }
1160 return true;
1161 }
1162
1163 bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.GetSize() > 1; }
1164};
1165
1166} // namespace art
1167
1168#endif // ART_COMPILER_ELF_BUILDER_H_