blob: 3be2478e49e8d5332e60d72bd3a95faa0c86a896 [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:
Vladimir Markof4da6752014-08-01 19:04:18 +0100415 virtual void SetCodeOffset(size_t offset) = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700416 virtual bool Write(OutputStream* out) = 0;
417 virtual ~CodeOutput() {}
418};
419
Andreas Gampecc676072014-09-23 22:58:07 -0700420template <typename Elf_Word>
421class ElfFileRodataPiece : public ElfFilePiece<Elf_Word> {
422 public:
423 ElfFileRodataPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
424 output_(output) {}
425
426 bool DoActualWrite(File* elf_file) OVERRIDE {
Vladimir Markof4da6752014-08-01 19:04:18 +0100427 output_->SetCodeOffset(this->offset_);
Andreas Gampecc676072014-09-23 22:58:07 -0700428 std::unique_ptr<BufferedOutputStream> output_stream(
429 new BufferedOutputStream(new FileOutputStream(elf_file)));
430 if (!output_->Write(output_stream.get())) {
431 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file->GetPath();
432 return false;
433 }
434
435 return true;
436 }
437
438 std::string GetDescription() OVERRIDE {
439 return ".rodata";
440 }
441
442 private:
443 CodeOutput* output_;
444};
445
446template <typename Elf_Word>
447class ElfFileOatTextPiece : public ElfFilePiece<Elf_Word> {
448 public:
449 ElfFileOatTextPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
450 output_(output) {}
451
452 bool DoActualWrite(File* elf_file) OVERRIDE {
453 // All data is written by the ElfFileRodataPiece right now, as the oat writer writes in one
454 // piece. This is for future flexibility.
455 UNUSED(output_);
456 return true;
457 }
458
459 std::string GetDescription() OVERRIDE {
460 return ".text";
461 }
462
463 private:
464 CodeOutput* output_;
465};
466
467template <typename Elf_Word>
468static bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces, File* elf_file) {
469 // TODO It would be nice if this checked for overlap.
470 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
471 if (!(*it)->Write(elf_file)) {
472 return false;
473 }
474 }
475 return true;
476}
477
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700478template <typename Elf_Word, typename Elf_Shdr>
479static inline constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) {
480 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
481}
482
483template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Dyn,
484 typename Elf_Sym, typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr>
485class ElfBuilder FINAL {
486 public:
487 ElfBuilder(CodeOutput* oat_writer,
488 File* elf_file,
489 InstructionSet isa,
490 Elf_Word rodata_relative_offset,
491 Elf_Word rodata_size,
492 Elf_Word text_relative_offset,
493 Elf_Word text_size,
494 const bool add_symbols,
495 bool debug = false)
496 : oat_writer_(oat_writer),
497 elf_file_(elf_file),
498 add_symbols_(add_symbols),
499 debug_logging_(debug),
500 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
501 SHF_ALLOC | SHF_EXECINSTR),
502 rodata_builder_(".rodata", rodata_size, rodata_relative_offset, SHT_PROGBITS, SHF_ALLOC),
503 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
504 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
505 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0, sizeof(Elf_Word),
506 sizeof(Elf_Word)),
507 dynamic_builder_(".dynamic", &dynsym_builder_),
508 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
509 SetupEhdr();
510 SetupDynamic();
511 SetupRequiredSymbols();
512 SetISA(isa);
513 }
514 ~ElfBuilder() {}
515
516 bool Init() {
517 // The basic layout of the elf file. Order may be different in final output.
518 // +-------------------------+
519 // | Elf_Ehdr |
520 // +-------------------------+
521 // | Elf_Phdr PHDR |
522 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata
523 // | Elf_Phdr LOAD R X | .text
524 // | Elf_Phdr LOAD RW | .dynamic
525 // | Elf_Phdr DYNAMIC | .dynamic
526 // +-------------------------+
527 // | .dynsym |
528 // | Elf_Sym STN_UNDEF |
529 // | Elf_Sym oatdata |
530 // | Elf_Sym oatexec |
531 // | Elf_Sym oatlastword |
532 // +-------------------------+
533 // | .dynstr |
534 // | \0 |
535 // | oatdata\0 |
536 // | oatexec\0 |
537 // | oatlastword\0 |
538 // | boot.oat\0 |
539 // +-------------------------+
540 // | .hash |
541 // | Elf_Word nbucket = b |
542 // | Elf_Word nchain = c |
543 // | Elf_Word bucket[0] |
544 // | ... |
545 // | Elf_Word bucket[b - 1] |
546 // | Elf_Word chain[0] |
547 // | ... |
548 // | Elf_Word chain[c - 1] |
549 // +-------------------------+
550 // | .rodata |
551 // | oatdata..oatexec-4 |
552 // +-------------------------+
553 // | .text |
554 // | oatexec..oatlastword |
555 // +-------------------------+
556 // | .dynamic |
557 // | Elf_Dyn DT_SONAME |
558 // | Elf_Dyn DT_HASH |
559 // | Elf_Dyn DT_SYMTAB |
560 // | Elf_Dyn DT_SYMENT |
561 // | Elf_Dyn DT_STRTAB |
562 // | Elf_Dyn DT_STRSZ |
563 // | Elf_Dyn DT_NULL |
564 // +-------------------------+ (Optional)
565 // | .strtab | (Optional)
566 // | program symbol names | (Optional)
567 // +-------------------------+ (Optional)
568 // | .symtab | (Optional)
569 // | program symbols | (Optional)
570 // +-------------------------+
571 // | .shstrtab |
572 // | \0 |
573 // | .dynamic\0 |
574 // | .dynsym\0 |
575 // | .dynstr\0 |
576 // | .hash\0 |
577 // | .rodata\0 |
578 // | .text\0 |
579 // | .shstrtab\0 |
580 // | .symtab\0 | (Optional)
581 // | .strtab\0 | (Optional)
582 // | .debug_str\0 | (Optional)
583 // | .debug_info\0 | (Optional)
584 // | .eh_frame\0 | (Optional)
585 // | .debug_line\0 | (Optional)
586 // | .debug_abbrev\0 | (Optional)
587 // +-------------------------+ (Optional)
588 // | .debug_info | (Optional)
589 // +-------------------------+ (Optional)
590 // | .debug_abbrev | (Optional)
591 // +-------------------------+ (Optional)
592 // | .eh_frame | (Optional)
593 // +-------------------------+ (Optional)
594 // | .debug_line | (Optional)
595 // +-------------------------+ (Optional)
596 // | .debug_str | (Optional)
597 // +-------------------------+ (Optional)
598 // | Elf_Shdr NULL |
599 // | Elf_Shdr .dynsym |
600 // | Elf_Shdr .dynstr |
601 // | Elf_Shdr .hash |
602 // | Elf_Shdr .text |
603 // | Elf_Shdr .rodata |
604 // | Elf_Shdr .dynamic |
605 // | Elf_Shdr .shstrtab |
606 // | Elf_Shdr .debug_info | (Optional)
607 // | Elf_Shdr .debug_abbrev | (Optional)
608 // | Elf_Shdr .eh_frame | (Optional)
609 // | Elf_Shdr .debug_line | (Optional)
610 // | Elf_Shdr .debug_str | (Optional)
611 // +-------------------------+
612
613 if (fatal_error_) {
614 return false;
615 }
616 // Step 1. Figure out all the offsets.
617
618 if (debug_logging_) {
619 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
620 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
621 }
622
623 memset(&program_headers_, 0, sizeof(program_headers_));
624 program_headers_[PH_PHDR].p_type = PT_PHDR;
625 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET;
626 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET;
627 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET;
628 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_);
629 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_);
630 program_headers_[PH_PHDR].p_flags = PF_R;
631 program_headers_[PH_PHDR].p_align = sizeof(Elf_Word);
632
633 program_headers_[PH_LOAD_R__].p_type = PT_LOAD;
634 program_headers_[PH_LOAD_R__].p_offset = 0;
635 program_headers_[PH_LOAD_R__].p_vaddr = 0;
636 program_headers_[PH_LOAD_R__].p_paddr = 0;
637 program_headers_[PH_LOAD_R__].p_flags = PF_R;
638
639 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD;
640 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X;
641
642 program_headers_[PH_LOAD_RW_].p_type = PT_LOAD;
643 program_headers_[PH_LOAD_RW_].p_flags = PF_R | PF_W;
644
645 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC;
646 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W;
647
648 // Get the dynstr string.
649 dynstr_ = dynsym_builder_.GenerateStrtab();
650
651 // Add the SONAME to the dynstr.
652 dynstr_soname_offset_ = dynstr_.size();
653 std::string file_name(elf_file_->GetPath());
654 size_t directory_separator_pos = file_name.rfind('/');
655 if (directory_separator_pos != std::string::npos) {
656 file_name = file_name.substr(directory_separator_pos + 1);
657 }
658 dynstr_ += file_name;
659 dynstr_ += '\0';
660 if (debug_logging_) {
661 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size()
662 << std::hex << " " << dynstr_.size();
663 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
664 << std::hex << " " << dynsym_builder_.GetSize();
665 }
666
667 // Get the section header string table.
668 shstrtab_ += '\0';
669
670 // Setup sym_undef
671 memset(&null_hdr_, 0, sizeof(null_hdr_));
672 null_hdr_.sh_type = SHT_NULL;
673 null_hdr_.sh_link = SHN_UNDEF;
674 section_ptrs_.push_back(&null_hdr_);
675
676 section_index_ = 1;
677
678 // setup .dynsym
679 section_ptrs_.push_back(&dynsym_builder_.section_);
680 AssignSectionStr(&dynsym_builder_, &shstrtab_);
681 dynsym_builder_.section_index_ = section_index_++;
682
683 // Setup .dynstr
684 section_ptrs_.push_back(&dynsym_builder_.GetStrTab()->section_);
685 AssignSectionStr(dynsym_builder_.GetStrTab(), &shstrtab_);
686 dynsym_builder_.GetStrTab()->section_index_ = section_index_++;
687
688 // Setup .hash
689 section_ptrs_.push_back(&hash_builder_.section_);
690 AssignSectionStr(&hash_builder_, &shstrtab_);
691 hash_builder_.section_index_ = section_index_++;
692
693 // Setup .rodata
694 section_ptrs_.push_back(&rodata_builder_.section_);
695 AssignSectionStr(&rodata_builder_, &shstrtab_);
696 rodata_builder_.section_index_ = section_index_++;
697
698 // Setup .text
699 section_ptrs_.push_back(&text_builder_.section_);
700 AssignSectionStr(&text_builder_, &shstrtab_);
701 text_builder_.section_index_ = section_index_++;
702
703 // Setup .dynamic
704 section_ptrs_.push_back(&dynamic_builder_.section_);
705 AssignSectionStr(&dynamic_builder_, &shstrtab_);
706 dynamic_builder_.section_index_ = section_index_++;
707
708 // Fill in the hash section.
709 hash_ = dynsym_builder_.GenerateHashContents();
710
711 if (debug_logging_) {
712 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
713 << std::hex << " " << hash_.size() * sizeof(Elf_Word);
714 }
715
716 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
717
718 // Get the layout in the sections.
719 //
720 // Get the layout of the dynsym section.
721 dynsym_builder_.section_.sh_offset = RoundUp(base_offset, dynsym_builder_.section_.sh_addralign);
722 dynsym_builder_.section_.sh_addr = dynsym_builder_.section_.sh_offset;
723 dynsym_builder_.section_.sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
724 dynsym_builder_.section_.sh_link = dynsym_builder_.GetLink();
725
726 // Get the layout of the dynstr section.
727 dynsym_builder_.GetStrTab()->section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
728 (dynsym_builder_.GetStrTab()->section_,
729 dynsym_builder_.section_);
730 dynsym_builder_.GetStrTab()->section_.sh_addr = dynsym_builder_.GetStrTab()->section_.sh_offset;
731 dynsym_builder_.GetStrTab()->section_.sh_size = dynstr_.size();
732 dynsym_builder_.GetStrTab()->section_.sh_link = dynsym_builder_.GetStrTab()->GetLink();
733
734 // Get the layout of the hash section
735 hash_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
736 (hash_builder_.section_,
737 dynsym_builder_.GetStrTab()->section_);
738 hash_builder_.section_.sh_addr = hash_builder_.section_.sh_offset;
739 hash_builder_.section_.sh_size = hash_.size() * sizeof(Elf_Word);
740 hash_builder_.section_.sh_link = hash_builder_.GetLink();
741
742 // Get the layout of the rodata section.
743 rodata_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
744 (rodata_builder_.section_,
745 hash_builder_.section_);
746 rodata_builder_.section_.sh_addr = rodata_builder_.section_.sh_offset;
747 rodata_builder_.section_.sh_size = rodata_builder_.GetSize();
748 rodata_builder_.section_.sh_link = rodata_builder_.GetLink();
749
750 // Get the layout of the text section.
751 text_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
752 (text_builder_.section_, rodata_builder_.section_);
753 text_builder_.section_.sh_addr = text_builder_.section_.sh_offset;
754 text_builder_.section_.sh_size = text_builder_.GetSize();
755 text_builder_.section_.sh_link = text_builder_.GetLink();
756 CHECK_ALIGNED(rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size, kPageSize);
757
758 // Get the layout of the dynamic section.
759 dynamic_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
760 (dynamic_builder_.section_,
761 text_builder_.section_);
762 dynamic_builder_.section_.sh_addr = dynamic_builder_.section_.sh_offset;
763 dynamic_builder_.section_.sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
764 dynamic_builder_.section_.sh_link = dynamic_builder_.GetLink();
765
766 if (debug_logging_) {
767 LOG(INFO) << "dynsym off=" << dynsym_builder_.section_.sh_offset
768 << " dynsym size=" << dynsym_builder_.section_.sh_size;
769 LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->section_.sh_offset
770 << " dynstr size=" << dynsym_builder_.GetStrTab()->section_.sh_size;
771 LOG(INFO) << "hash off=" << hash_builder_.section_.sh_offset
772 << " hash size=" << hash_builder_.section_.sh_size;
773 LOG(INFO) << "rodata off=" << rodata_builder_.section_.sh_offset
774 << " rodata size=" << rodata_builder_.section_.sh_size;
775 LOG(INFO) << "text off=" << text_builder_.section_.sh_offset
776 << " text size=" << text_builder_.section_.sh_size;
777 LOG(INFO) << "dynamic off=" << dynamic_builder_.section_.sh_offset
778 << " dynamic size=" << dynamic_builder_.section_.sh_size;
779 }
780
781 return true;
782 }
783
784 bool Write() {
Andreas Gampecc676072014-09-23 22:58:07 -0700785 std::vector<ElfFilePiece<Elf_Word>*> pieces;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700786 Elf_Shdr prev = dynamic_builder_.section_;
787 std::string strtab;
788
789 if (IncludingDebugSymbols()) {
790 // Setup .symtab
791 section_ptrs_.push_back(&symtab_builder_.section_);
792 AssignSectionStr(&symtab_builder_, &shstrtab_);
793 symtab_builder_.section_index_ = section_index_++;
794
795 // Setup .strtab
796 section_ptrs_.push_back(&symtab_builder_.GetStrTab()->section_);
797 AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
798 symtab_builder_.GetStrTab()->section_index_ = section_index_++;
799
800 strtab = symtab_builder_.GenerateStrtab();
801 if (debug_logging_) {
802 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
803 << std::hex << " " << strtab.size();
804 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
805 << std::hex << " " << symtab_builder_.GetSize();
806 }
807 }
808
809 // Setup all the other sections.
810 for (ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder = other_builders_.data(),
811 *end = builder + other_builders_.size();
812 builder != end; ++builder) {
813 section_ptrs_.push_back(&builder->section_);
814 AssignSectionStr(builder, &shstrtab_);
815 builder->section_index_ = section_index_++;
816 }
817
818 // Setup shstrtab
819 section_ptrs_.push_back(&shstrtab_builder_.section_);
820 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
821 shstrtab_builder_.section_index_ = section_index_++;
822
823 if (debug_logging_) {
824 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
825 << std::hex << " " << shstrtab_.size();
826 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
827 << std::hex << " " << section_ptrs_.size();
828 }
829
830 if (IncludingDebugSymbols()) {
831 // Get the layout of the symtab section.
832 symtab_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
833 (symtab_builder_.section_,
834 dynamic_builder_.section_);
835 symtab_builder_.section_.sh_addr = 0;
836 // Add to leave space for the null symbol.
837 symtab_builder_.section_.sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
838 symtab_builder_.section_.sh_link = symtab_builder_.GetLink();
839
840 // Get the layout of the dynstr section.
841 symtab_builder_.GetStrTab()->section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
842 (symtab_builder_.GetStrTab()->section_,
843 symtab_builder_.section_);
844 symtab_builder_.GetStrTab()->section_.sh_addr = 0;
845 symtab_builder_.GetStrTab()->section_.sh_size = strtab.size();
846 symtab_builder_.GetStrTab()->section_.sh_link = symtab_builder_.GetStrTab()->GetLink();
847
848 prev = symtab_builder_.GetStrTab()->section_;
849 if (debug_logging_) {
850 LOG(INFO) << "symtab off=" << symtab_builder_.section_.sh_offset
851 << " symtab size=" << symtab_builder_.section_.sh_size;
852 LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->section_.sh_offset
853 << " strtab size=" << symtab_builder_.GetStrTab()->section_.sh_size;
854 }
855 }
856
857 // Get the layout of the extra sections. (This will deal with the debug
858 // sections if they are there)
859 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
860 it->section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>(it->section_, prev);
861 it->section_.sh_addr = 0;
862 it->section_.sh_size = it->GetBuffer()->size();
863 it->section_.sh_link = it->GetLink();
Andreas Gampecc676072014-09-23 22:58:07 -0700864
865 // We postpone adding an ElfFilePiece to keep the order in "pieces."
866
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700867 prev = it->section_;
868 if (debug_logging_) {
869 LOG(INFO) << it->name_ << " off=" << it->section_.sh_offset
870 << " size=" << it->section_.sh_size;
871 }
872 }
873
874 // Get the layout of the shstrtab section
875 shstrtab_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
876 (shstrtab_builder_.section_, prev);
877 shstrtab_builder_.section_.sh_addr = 0;
878 shstrtab_builder_.section_.sh_size = shstrtab_.size();
879 shstrtab_builder_.section_.sh_link = shstrtab_builder_.GetLink();
880 if (debug_logging_) {
881 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.section_.sh_offset
882 << " shstrtab size=" << shstrtab_builder_.section_.sh_size;
883 }
884
885 // The section list comes after come after.
886 Elf_Word sections_offset = RoundUp(
887 shstrtab_builder_.section_.sh_offset + shstrtab_builder_.section_.sh_size,
888 sizeof(Elf_Word));
889
890 // Setup the actual symbol arrays.
891 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
892 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.section_.sh_size);
893 std::vector<Elf_Sym> symtab;
894 if (IncludingDebugSymbols()) {
895 symtab = symtab_builder_.GenerateSymtab();
896 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.section_.sh_size);
897 }
898
899 // Setup the dynamic section.
900 // This will add the 2 values we cannot know until now time, namely the size
901 // and the soname_offset.
902 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
903 dynstr_soname_offset_);
904 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.section_.sh_size);
905
906 // Finish setup of the program headers now that we know the layout of the
907 // whole file.
908 Elf_Word load_r_size = rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size;
909 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
910 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
911 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.section_.sh_addralign;
912
913 Elf_Word load_rx_size = text_builder_.section_.sh_size;
914 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.section_.sh_offset;
915 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.section_.sh_offset;
916 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.section_.sh_offset;
917 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
918 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
919 program_headers_[PH_LOAD_R_X].p_align = text_builder_.section_.sh_addralign;
920
921 program_headers_[PH_LOAD_RW_].p_offset = dynamic_builder_.section_.sh_offset;
922 program_headers_[PH_LOAD_RW_].p_vaddr = dynamic_builder_.section_.sh_offset;
923 program_headers_[PH_LOAD_RW_].p_paddr = dynamic_builder_.section_.sh_offset;
924 program_headers_[PH_LOAD_RW_].p_filesz = dynamic_builder_.section_.sh_size;
925 program_headers_[PH_LOAD_RW_].p_memsz = dynamic_builder_.section_.sh_size;
926 program_headers_[PH_LOAD_RW_].p_align = dynamic_builder_.section_.sh_addralign;
927
928 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.section_.sh_offset;
929 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.section_.sh_offset;
930 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.section_.sh_offset;
931 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.section_.sh_size;
932 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.section_.sh_size;
933 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.section_.sh_addralign;
934
935 // Finish setup of the Ehdr values.
936 elf_header_.e_phoff = PHDR_OFFSET;
937 elf_header_.e_shoff = sections_offset;
938 elf_header_.e_phnum = PH_NUM;
939 elf_header_.e_shnum = section_ptrs_.size();
940 elf_header_.e_shstrndx = shstrtab_builder_.section_index_;
941
942 // Add the rest of the pieces to the list.
Andreas Gampecc676072014-09-23 22:58:07 -0700943 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_,
944 sizeof(elf_header_)));
945 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
946 &program_headers_, sizeof(program_headers_)));
947 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic",
948 dynamic_builder_.section_.sh_offset,
949 dynamic.data(),
950 dynamic_builder_.section_.sh_size));
951 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.section_.sh_offset,
952 dynsym.data(),
953 dynsym.size() * sizeof(Elf_Sym)));
954 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr",
955 dynsym_builder_.GetStrTab()->section_.sh_offset,
956 dynstr_.c_str(), dynstr_.size()));
957 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.section_.sh_offset,
958 hash_.data(),
959 hash_.size() * sizeof(Elf_Word)));
960 pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.section_.sh_offset,
961 oat_writer_));
962 pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.section_.sh_offset,
963 oat_writer_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700964 if (IncludingDebugSymbols()) {
Andreas Gampecc676072014-09-23 22:58:07 -0700965 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab",
966 symtab_builder_.section_.sh_offset,
967 symtab.data(),
968 symtab.size() * sizeof(Elf_Sym)));
969 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab",
970 symtab_builder_.GetStrTab()->section_.sh_offset,
971 strtab.c_str(), strtab.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700972 }
Andreas Gampecc676072014-09-23 22:58:07 -0700973 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab",
974 shstrtab_builder_.section_.sh_offset,
975 &shstrtab_[0], shstrtab_.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700976 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
977 // Just add all the sections in induvidually since they are all over the
978 // place on the heap/stack.
979 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
Andreas Gampecc676072014-09-23 22:58:07 -0700980 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off,
981 section_ptrs_[i], sizeof(Elf_Shdr)));
982 }
983
984 // Postponed debug info.
985 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
986 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->name_, it->section_.sh_offset,
987 it->GetBuffer()->data(),
988 it->GetBuffer()->size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700989 }
990
991 if (!WriteOutFile(pieces)) {
992 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
Andreas Gampecc676072014-09-23 22:58:07 -0700993
994 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700995 return false;
996 }
997
Andreas Gampecc676072014-09-23 22:58:07 -0700998 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700999 return true;
1000 }
1001
1002 // Adds the given raw section to the builder. This will copy it. The caller
1003 // is responsible for deallocating their copy.
1004 void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bld) {
1005 other_builders_.push_back(bld);
1006 }
1007
1008 private:
1009 CodeOutput* oat_writer_;
1010 File* elf_file_;
1011 const bool add_symbols_;
1012 const bool debug_logging_;
1013
1014 bool fatal_error_ = false;
1015
1016 // What phdr is.
1017 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
1018 enum : uint8_t {
1019 PH_PHDR = 0,
1020 PH_LOAD_R__ = 1,
1021 PH_LOAD_R_X = 2,
1022 PH_LOAD_RW_ = 3,
1023 PH_DYNAMIC = 4,
1024 PH_NUM = 5,
1025 };
1026 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
1027 Elf_Phdr program_headers_[PH_NUM];
1028
1029 Elf_Ehdr elf_header_;
1030
1031 Elf_Shdr null_hdr_;
1032 std::string shstrtab_;
1033 uint32_t section_index_;
1034 std::string dynstr_;
1035 uint32_t dynstr_soname_offset_;
1036 std::vector<Elf_Shdr*> section_ptrs_;
1037 std::vector<Elf_Word> hash_;
1038
1039 public:
1040 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> text_builder_;
1041 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> rodata_builder_;
1042 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> dynsym_builder_;
1043 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> symtab_builder_;
1044 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> hash_builder_;
1045 ElfDynamicBuilder<Elf_Word, Elf_Sword, Elf_Dyn, Elf_Shdr> dynamic_builder_;
1046 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> shstrtab_builder_;
1047 std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>> other_builders_;
1048
1049 private:
1050 void SetISA(InstructionSet isa) {
1051 switch (isa) {
1052 case kArm:
1053 // Fall through.
1054 case kThumb2: {
1055 elf_header_.e_machine = EM_ARM;
1056 elf_header_.e_flags = EF_ARM_EABI_VER5;
1057 break;
1058 }
1059 case kArm64: {
1060 elf_header_.e_machine = EM_AARCH64;
1061 elf_header_.e_flags = 0;
1062 break;
1063 }
1064 case kX86: {
1065 elf_header_.e_machine = EM_386;
1066 elf_header_.e_flags = 0;
1067 break;
1068 }
1069 case kX86_64: {
1070 elf_header_.e_machine = EM_X86_64;
1071 elf_header_.e_flags = 0;
1072 break;
1073 }
1074 case kMips: {
1075 elf_header_.e_machine = EM_MIPS;
1076 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1077 EF_MIPS_PIC |
1078 EF_MIPS_CPIC |
1079 EF_MIPS_ABI_O32 |
1080 EF_MIPS_ARCH_32R2);
1081 break;
1082 }
1083 default: {
1084 fatal_error_ = true;
1085 LOG(FATAL) << "Unknown instruction set: " << isa;
1086 break;
1087 }
1088 }
1089 }
1090
1091 void SetupEhdr() {
1092 memset(&elf_header_, 0, sizeof(elf_header_));
1093 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
1094 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
1095 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
1096 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
1097 elf_header_.e_ident[EI_CLASS] = ELFCLASS32;
1098 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
1099 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
1100 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
1101 elf_header_.e_ident[EI_ABIVERSION] = 0;
1102 elf_header_.e_type = ET_DYN;
1103 elf_header_.e_version = 1;
1104 elf_header_.e_entry = 0;
1105 elf_header_.e_ehsize = sizeof(Elf_Ehdr);
1106 elf_header_.e_phentsize = sizeof(Elf_Phdr);
1107 elf_header_.e_shentsize = sizeof(Elf_Shdr);
1108 elf_header_.e_phoff = sizeof(Elf_Ehdr);
1109 }
1110
1111 // Sets up a bunch of the required Dynamic Section entries.
1112 // Namely it will initialize all the mandatory ones that it can.
1113 // Specifically:
1114 // DT_HASH
1115 // DT_STRTAB
1116 // DT_SYMTAB
1117 // DT_SYMENT
1118 //
1119 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
1120 void SetupDynamic() {
1121 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
1122 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1123 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1124 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1125 }
1126
1127 // Sets up the basic dynamic symbols that are needed, namely all those we
1128 // can know already.
1129 //
1130 // Specifically adds:
1131 // oatdata
1132 // oatexec
1133 // oatlastword
1134 void SetupRequiredSymbols() {
1135 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1136 rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1137 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1138 text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1139 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1140 true, 4, STB_GLOBAL, STT_OBJECT);
1141 }
1142
1143 void AssignSectionStr(ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder,
1144 std::string* strtab) {
1145 builder->section_.sh_name = strtab->size();
1146 *strtab += builder->name_;
1147 *strtab += '\0';
1148 if (debug_logging_) {
1149 LOG(INFO) << "adding section name \"" << builder->name_ << "\" "
1150 << "to shstrtab at offset " << builder->section_.sh_name;
1151 }
1152 }
1153
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001154
1155 // Write each of the pieces out to the file.
Andreas Gampecc676072014-09-23 22:58:07 -07001156 bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001157 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
Andreas Gampecc676072014-09-23 22:58:07 -07001158 if (!(*it)->Write(elf_file_)) {
1159 return false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001160 }
1161 }
1162 return true;
1163 }
1164
1165 bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.GetSize() > 1; }
1166};
1167
1168} // namespace art
1169
1170#endif // ART_COMPILER_ELF_BUILDER_H_