blob: 9c173f888571d8637a0c1e0bb62bef0ac0348e75 [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
Ian Rogersd582fa42014-11-05 23:46:43 -080020#include "arch/instruction_set.h"
Andreas Gampecc676072014-09-23 22:58:07 -070021#include "base/stl_util.h"
Ian Rogers0279ebb2014-10-08 17:27:48 -070022#include "base/value_object.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070023#include "buffered_output_stream.h"
24#include "elf_utils.h"
25#include "file_output_stream.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070026
27namespace art {
28
Andreas Gampe54fc26c2014-09-04 21:47:42 -070029class CodeOutput {
30 public:
Vladimir Markof4da6752014-08-01 19:04:18 +010031 virtual void SetCodeOffset(size_t offset) = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070032 virtual bool Write(OutputStream* out) = 0;
33 virtual ~CodeOutput() {}
34};
35
David Srbecky533c2072015-04-22 12:20:22 +010036template <typename ElfTypes>
Andreas Gampe54fc26c2014-09-04 21:47:42 -070037class ElfBuilder FINAL {
38 public:
David Srbecky533c2072015-04-22 12:20:22 +010039 using Elf_Addr = typename ElfTypes::Addr;
40 using Elf_Word = typename ElfTypes::Word;
41 using Elf_Sword = typename ElfTypes::Sword;
42 using Elf_Ehdr = typename ElfTypes::Ehdr;
43 using Elf_Shdr = typename ElfTypes::Shdr;
44 using Elf_Sym = typename ElfTypes::Sym;
45 using Elf_Phdr = typename ElfTypes::Phdr;
46 using Elf_Dyn = typename ElfTypes::Dyn;
47
David Srbecky0c5bbc12015-04-28 17:54:52 +010048 class ElfSectionBuilder : public ValueObject {
49 public:
50 ElfSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
51 const ElfSectionBuilder *link, Elf_Word info,
52 Elf_Word align, Elf_Word entsize)
53 : section_index_(0), name_(sec_name), link_(link) {
54 memset(&section_, 0, sizeof(section_));
55 section_.sh_type = type;
56 section_.sh_flags = flags;
57 section_.sh_info = info;
58 section_.sh_addralign = align;
59 section_.sh_entsize = entsize;
60 }
61 ElfSectionBuilder(const ElfSectionBuilder&) = default;
62
63 ~ElfSectionBuilder() {}
64
65 Elf_Word GetLink() const {
66 return (link_ != nullptr) ? link_->section_index_ : 0;
67 }
68
69 const Elf_Shdr* GetSection() const {
70 return &section_;
71 }
72
73 Elf_Shdr* GetSection() {
74 return &section_;
75 }
76
77 Elf_Word GetSectionIndex() const {
78 return section_index_;
79 }
80
81 void SetSectionIndex(Elf_Word section_index) {
82 section_index_ = section_index;
83 }
84
85 const std::string& GetName() const {
86 return name_;
87 }
88
89 private:
90 Elf_Shdr section_;
91 Elf_Word section_index_;
92 const std::string name_;
93 const ElfSectionBuilder* const link_;
94 };
95
96 class ElfDynamicBuilder FINAL : public ElfSectionBuilder {
97 public:
98 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un) {
99 if (tag == DT_NULL) {
100 return;
101 }
102 dynamics_.push_back({nullptr, tag, d_un});
103 }
104
105 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un,
106 const ElfSectionBuilder* section) {
107 if (tag == DT_NULL) {
108 return;
109 }
110 dynamics_.push_back({section, tag, d_un});
111 }
112
113 ElfDynamicBuilder(const std::string& sec_name,
114 ElfSectionBuilder *link)
115 : ElfSectionBuilder(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC,
116 link, 0, kPageSize, sizeof(Elf_Dyn)) {}
117 ~ElfDynamicBuilder() {}
118
119 Elf_Word GetSize() const {
120 // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
121 // these must be added when we actually put the file together because
122 // their values are very dependent on state.
123 return dynamics_.size() + 3;
124 }
125
126 // Create the actual dynamic vector. strsz should be the size of the .dynstr
127 // table and soname_off should be the offset of the soname in .dynstr.
128 // Since niether can be found prior to final layout we will wait until here
129 // to add them.
130 std::vector<Elf_Dyn> GetDynamics(Elf_Word strsz, Elf_Word soname) const {
131 std::vector<Elf_Dyn> ret;
132 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
133 if (it->section_ != nullptr) {
134 // We are adding an address relative to a section.
135 ret.push_back(
136 {it->tag_, {it->off_ + it->section_->GetSection()->sh_addr}});
137 } else {
138 ret.push_back({it->tag_, {it->off_}});
139 }
140 }
141 ret.push_back({DT_STRSZ, {strsz}});
142 ret.push_back({DT_SONAME, {soname}});
143 ret.push_back({DT_NULL, {0}});
144 return ret;
145 }
146
147 private:
148 struct ElfDynamicState {
149 const ElfSectionBuilder* section_;
150 Elf_Sword tag_;
151 Elf_Word off_;
152 };
153 std::vector<ElfDynamicState> dynamics_;
154 };
155
156 class ElfRawSectionBuilder FINAL : public ElfSectionBuilder {
157 public:
158 ElfRawSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
159 const ElfSectionBuilder* link, Elf_Word info,
160 Elf_Word align, Elf_Word entsize)
161 : ElfSectionBuilder(sec_name, type, flags, link, info, align, entsize) {
162 }
163 ElfRawSectionBuilder(const ElfRawSectionBuilder&) = default;
164
165 ~ElfRawSectionBuilder() {}
166
167 std::vector<uint8_t>* GetBuffer() {
168 return &buf_;
169 }
170
171 void SetBuffer(const std::vector<uint8_t>& buf) {
172 buf_ = buf;
173 }
174
175 private:
176 std::vector<uint8_t> buf_;
177 };
178
179 class ElfOatSectionBuilder FINAL : public ElfSectionBuilder {
180 public:
181 ElfOatSectionBuilder(const std::string& sec_name, Elf_Word size, Elf_Word offset,
182 Elf_Word type, Elf_Word flags)
183 : ElfSectionBuilder(sec_name, type, flags, nullptr, 0, kPageSize, 0),
184 offset_(offset), size_(size) {
185 }
186
187 ~ElfOatSectionBuilder() {}
188
189 Elf_Word GetOffset() const {
190 return offset_;
191 }
192
193 Elf_Word GetSize() const {
194 return size_;
195 }
196
197 private:
198 // Offset of the content within the file.
199 Elf_Word offset_;
200 // Size of the content within the file.
201 Elf_Word size_;
202 };
203
204 static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
205 return ((binding) << 4) + ((type) & 0xf);
206 }
207
208 // from bionic
209 static inline unsigned elfhash(const char *_name) {
210 const unsigned char *name = (const unsigned char *) _name;
211 unsigned h = 0, g;
212
213 while (*name) {
214 h = (h << 4) + *name++;
215 g = h & 0xf0000000;
216 h ^= g;
217 h ^= g >> 24;
218 }
219 return h;
220 }
221
222 class ElfSymtabBuilder FINAL : public ElfSectionBuilder {
223 public:
224 // Add a symbol with given name to this symtab. The symbol refers to
225 // 'relative_addr' within the given section and has the given attributes.
226 void AddSymbol(const std::string& name,
227 const ElfSectionBuilder* section,
228 Elf_Addr addr,
229 bool is_relative,
230 Elf_Word size,
231 uint8_t binding,
232 uint8_t type,
233 uint8_t other = 0) {
234 CHECK(section);
235 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
236 MakeStInfo(binding, type), other, 0};
237 symbols_.push_back(state);
238 }
239
240 ElfSymtabBuilder(const std::string& sec_name, Elf_Word type,
241 const std::string& str_name, Elf_Word str_type, bool alloc)
242 : ElfSectionBuilder(sec_name, type, ((alloc) ? SHF_ALLOC : 0U),
243 &strtab_, 0, sizeof(Elf_Word),
244 sizeof(Elf_Sym)), str_name_(str_name),
245 str_type_(str_type),
246 strtab_(str_name,
247 str_type,
248 ((alloc) ? SHF_ALLOC : 0U),
249 nullptr, 0, 1, 1) {
250 }
251
252 ~ElfSymtabBuilder() {}
253
254 std::vector<Elf_Word> GenerateHashContents() const {
255 // Here is how The ELF hash table works.
256 // There are 3 arrays to worry about.
257 // * The symbol table where the symbol information is.
258 // * The bucket array which is an array of indexes into the symtab and chain.
259 // * The chain array which is also an array of indexes into the symtab and chain.
260 //
261 // Lets say the state is something like this.
262 // +--------+ +--------+ +-----------+
263 // | symtab | | bucket | | chain |
264 // | null | | 1 | | STN_UNDEF |
265 // | <sym1> | | 4 | | 2 |
266 // | <sym2> | | | | 5 |
267 // | <sym3> | | | | STN_UNDEF |
268 // | <sym4> | | | | 3 |
269 // | <sym5> | | | | STN_UNDEF |
270 // +--------+ +--------+ +-----------+
271 //
272 // The lookup process (in python psudocode) is
273 //
274 // def GetSym(name):
275 // # NB STN_UNDEF == 0
276 // indx = bucket[elfhash(name) % num_buckets]
277 // while indx != STN_UNDEF:
278 // if GetSymbolName(symtab[indx]) == name:
279 // return symtab[indx]
280 // indx = chain[indx]
281 // return SYMBOL_NOT_FOUND
282 //
283 // Between bucket and chain arrays every symtab index must be present exactly
284 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
285
286 // Select number of buckets.
287 // This is essentially arbitrary.
288 Elf_Word nbuckets;
289 Elf_Word chain_size = GetSize();
290 if (symbols_.size() < 8) {
291 nbuckets = 2;
292 } else if (symbols_.size() < 32) {
293 nbuckets = 4;
294 } else if (symbols_.size() < 256) {
295 nbuckets = 16;
296 } else {
297 // Have about 32 ids per bucket.
298 nbuckets = RoundUp(symbols_.size()/32, 2);
299 }
300 std::vector<Elf_Word> hash;
301 hash.push_back(nbuckets);
302 hash.push_back(chain_size);
303 uint32_t bucket_offset = hash.size();
304 uint32_t chain_offset = bucket_offset + nbuckets;
305 hash.resize(hash.size() + nbuckets + chain_size, 0);
306
307 Elf_Word* buckets = hash.data() + bucket_offset;
308 Elf_Word* chain = hash.data() + chain_offset;
309
310 // Set up the actual hash table.
311 for (Elf_Word i = 0; i < symbols_.size(); i++) {
312 // Add 1 since we need to have the null symbol that is not in the symbols
313 // list.
314 Elf_Word index = i + 1;
315 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
316 if (buckets[hash_val] == 0) {
317 buckets[hash_val] = index;
318 } else {
319 hash_val = buckets[hash_val];
320 CHECK_LT(hash_val, chain_size);
321 while (chain[hash_val] != 0) {
322 hash_val = chain[hash_val];
323 CHECK_LT(hash_val, chain_size);
324 }
325 chain[hash_val] = index;
326 // Check for loops. Works because if this is non-empty then there must be
327 // another cell which already contains the same symbol index as this one,
328 // which means some symbol has more then one name, which isn't allowed.
329 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
330 }
331 }
332
333 return hash;
334 }
335
336 std::string GenerateStrtab() {
337 std::string tab;
338 tab += '\0';
339 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
340 it->name_idx_ = tab.size();
341 tab += it->name_;
342 tab += '\0';
343 }
344 strtab_.GetSection()->sh_size = tab.size();
345 return tab;
346 }
347
348 std::vector<Elf_Sym> GenerateSymtab() {
349 std::vector<Elf_Sym> ret;
350 Elf_Sym undef_sym;
351 memset(&undef_sym, 0, sizeof(undef_sym));
352 undef_sym.st_shndx = SHN_UNDEF;
353 ret.push_back(undef_sym);
354
355 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
356 Elf_Sym sym;
357 memset(&sym, 0, sizeof(sym));
358 sym.st_name = it->name_idx_;
359 if (it->is_relative_) {
360 sym.st_value = it->addr_ + it->section_->GetSection()->sh_offset;
361 } else {
362 sym.st_value = it->addr_;
363 }
364 sym.st_size = it->size_;
365 sym.st_other = it->other_;
366 sym.st_shndx = it->section_->GetSectionIndex();
367 sym.st_info = it->info_;
368
369 ret.push_back(sym);
370 }
371 return ret;
372 }
373
374 Elf_Word GetSize() const {
375 // 1 is for the implicit null symbol.
376 return symbols_.size() + 1;
377 }
378
379 ElfSectionBuilder* GetStrTab() {
380 return &strtab_;
381 }
382
383 private:
384 struct ElfSymbolState {
385 const std::string name_;
386 const ElfSectionBuilder* section_;
387 Elf_Addr addr_;
388 Elf_Word size_;
389 bool is_relative_;
390 uint8_t info_;
391 uint8_t other_;
392 // Used during Write() to temporarially hold name index in the strtab.
393 Elf_Word name_idx_;
394 };
395
396 // Information for the strsym for dynstr sections.
397 const std::string str_name_;
398 Elf_Word str_type_;
399 // The symbols in the same order they will be in the symbol table.
400 std::vector<ElfSymbolState> symbols_;
401 ElfSectionBuilder strtab_;
402 };
403
404 template <typename Elf_Word>
405 class ElfFilePiece {
406 public:
407 virtual ~ElfFilePiece() {}
408
409 virtual bool Write(File* elf_file) {
410 if (static_cast<off_t>(offset_) != lseek(elf_file->Fd(), offset_, SEEK_SET)) {
411 PLOG(ERROR) << "Failed to seek to " << GetDescription() << " offset " << offset_ << " for "
412 << elf_file->GetPath();
413 return false;
414 }
415
416 return DoActualWrite(elf_file);
417 }
418
419 static bool Compare(ElfFilePiece* a, ElfFilePiece* b) {
420 return a->offset_ < b->offset_;
421 }
422
423 protected:
424 explicit ElfFilePiece(Elf_Word offset) : offset_(offset) {}
425
426 Elf_Word GetOffset() const {
427 return offset_;
428 }
429
430 virtual const char* GetDescription() const = 0;
431 virtual bool DoActualWrite(File* elf_file) = 0;
432
433 private:
434 const Elf_Word offset_;
435
436 DISALLOW_COPY_AND_ASSIGN(ElfFilePiece);
437 };
438
439 template <typename Elf_Word>
440 class ElfFileMemoryPiece FINAL : public ElfFilePiece<Elf_Word> {
441 public:
442 ElfFileMemoryPiece(const std::string& name, Elf_Word offset, const void* data, Elf_Word size)
443 : ElfFilePiece<Elf_Word>(offset), dbg_name_(name), data_(data), size_(size) {}
444
445 protected:
446 bool DoActualWrite(File* elf_file) OVERRIDE {
447 DCHECK(data_ != nullptr || size_ == 0U) << dbg_name_ << " " << size_;
448
449 if (!elf_file->WriteFully(data_, size_)) {
450 PLOG(ERROR) << "Failed to write " << dbg_name_ << " for " << elf_file->GetPath();
451 return false;
452 }
453
454 return true;
455 }
456
457 const char* GetDescription() const OVERRIDE {
458 return dbg_name_.c_str();
459 }
460
461 private:
462 const std::string& dbg_name_;
463 const void *data_;
464 Elf_Word size_;
465 };
466
467 template <typename Elf_Word>
468 class ElfFileRodataPiece FINAL : public ElfFilePiece<Elf_Word> {
469 public:
470 ElfFileRodataPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
471 output_(output) {}
472
473 protected:
474 bool DoActualWrite(File* elf_file) OVERRIDE {
475 output_->SetCodeOffset(this->GetOffset());
476 std::unique_ptr<BufferedOutputStream> output_stream(
477 new BufferedOutputStream(new FileOutputStream(elf_file)));
478 if (!output_->Write(output_stream.get())) {
479 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file->GetPath();
480 return false;
481 }
482
483 return true;
484 }
485
486 const char* GetDescription() const OVERRIDE {
487 return ".rodata";
488 }
489
490 private:
491 CodeOutput* const output_;
492
493 DISALLOW_COPY_AND_ASSIGN(ElfFileRodataPiece);
494 };
495
496 template <typename Elf_Word>
497 class ElfFileOatTextPiece FINAL : public ElfFilePiece<Elf_Word> {
498 public:
499 ElfFileOatTextPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
500 output_(output) {}
501
502 protected:
503 bool DoActualWrite(File* elf_file ATTRIBUTE_UNUSED) OVERRIDE {
504 // All data is written by the ElfFileRodataPiece right now, as the oat writer writes in one
505 // piece. This is for future flexibility.
506 UNUSED(output_);
507 return true;
508 }
509
510 const char* GetDescription() const OVERRIDE {
511 return ".text";
512 }
513
514 private:
515 CodeOutput* const output_;
516
517 DISALLOW_COPY_AND_ASSIGN(ElfFileOatTextPiece);
518 };
519
520 template <typename Elf_Word>
521 static bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces, File* elf_file) {
522 // TODO It would be nice if this checked for overlap.
523 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
524 if (!(*it)->Write(elf_file)) {
525 return false;
526 }
527 }
528 return true;
529 }
530
531 template <typename Elf_Word, typename Elf_Shdr>
532 static inline constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) {
533 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
534 }
535
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700536 ElfBuilder(CodeOutput* oat_writer,
537 File* elf_file,
538 InstructionSet isa,
539 Elf_Word rodata_relative_offset,
540 Elf_Word rodata_size,
541 Elf_Word text_relative_offset,
542 Elf_Word text_size,
Vladimir Marko5c42c292015-02-25 12:02:49 +0000543 Elf_Word bss_relative_offset,
544 Elf_Word bss_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700545 const bool add_symbols,
546 bool debug = false)
547 : oat_writer_(oat_writer),
548 elf_file_(elf_file),
549 add_symbols_(add_symbols),
550 debug_logging_(debug),
551 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
552 SHF_ALLOC | SHF_EXECINSTR),
553 rodata_builder_(".rodata", rodata_size, rodata_relative_offset, SHT_PROGBITS, SHF_ALLOC),
Vladimir Marko5c42c292015-02-25 12:02:49 +0000554 bss_builder_(".bss", bss_size, bss_relative_offset, SHT_NOBITS, SHF_ALLOC),
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700555 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
556 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
557 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0, sizeof(Elf_Word),
558 sizeof(Elf_Word)),
559 dynamic_builder_(".dynamic", &dynsym_builder_),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700560 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, nullptr, 0, 1, 1) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700561 SetupEhdr();
562 SetupDynamic();
563 SetupRequiredSymbols();
564 SetISA(isa);
565 }
566 ~ElfBuilder() {}
567
David Srbecky0c5bbc12015-04-28 17:54:52 +0100568 const ElfOatSectionBuilder& GetTextBuilder() const {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700569 return text_builder_;
570 }
571
David Srbecky0c5bbc12015-04-28 17:54:52 +0100572 ElfSymtabBuilder* GetSymtabBuilder() {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700573 return &symtab_builder_;
574 }
575
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700576 bool Init() {
Vladimir Marko5c42c292015-02-25 12:02:49 +0000577 // Since the .text section of an oat file contains relative references to .rodata
578 // and (optionally) .bss, we keep these 2 or 3 sections together. This creates
579 // a non-traditional layout where the .bss section is mapped independently of the
580 // .dynamic section and needs its own program header with LOAD RW.
581 //
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700582 // The basic layout of the elf file. Order may be different in final output.
583 // +-------------------------+
584 // | Elf_Ehdr |
585 // +-------------------------+
586 // | Elf_Phdr PHDR |
David Srbecky527c9c72015-04-17 21:14:10 +0100587 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .eh_frame .eh_frame_hdr .rodata
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700588 // | Elf_Phdr LOAD R X | .text
Vladimir Marko5c42c292015-02-25 12:02:49 +0000589 // | Elf_Phdr LOAD RW | .bss (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700590 // | Elf_Phdr LOAD RW | .dynamic
591 // | Elf_Phdr DYNAMIC | .dynamic
David Srbecky527c9c72015-04-17 21:14:10 +0100592 // | Elf_Phdr EH_FRAME R | .eh_frame_hdr
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700593 // +-------------------------+
594 // | .dynsym |
595 // | Elf_Sym STN_UNDEF |
596 // | Elf_Sym oatdata |
597 // | Elf_Sym oatexec |
598 // | Elf_Sym oatlastword |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000599 // | Elf_Sym oatbss | (Optional)
600 // | Elf_Sym oatbsslastword | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700601 // +-------------------------+
602 // | .dynstr |
603 // | \0 |
604 // | oatdata\0 |
605 // | oatexec\0 |
606 // | oatlastword\0 |
607 // | boot.oat\0 |
608 // +-------------------------+
609 // | .hash |
610 // | Elf_Word nbucket = b |
611 // | Elf_Word nchain = c |
612 // | Elf_Word bucket[0] |
613 // | ... |
614 // | Elf_Word bucket[b - 1] |
615 // | Elf_Word chain[0] |
616 // | ... |
617 // | Elf_Word chain[c - 1] |
618 // +-------------------------+
David Srbecky527c9c72015-04-17 21:14:10 +0100619 // | .eh_frame | (Optional)
620 // +-------------------------+
621 // | .eh_frame_hdr | (Optional)
622 // +-------------------------+
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700623 // | .rodata |
624 // | oatdata..oatexec-4 |
625 // +-------------------------+
626 // | .text |
627 // | oatexec..oatlastword |
628 // +-------------------------+
629 // | .dynamic |
630 // | Elf_Dyn DT_SONAME |
631 // | Elf_Dyn DT_HASH |
632 // | Elf_Dyn DT_SYMTAB |
633 // | Elf_Dyn DT_SYMENT |
634 // | Elf_Dyn DT_STRTAB |
635 // | Elf_Dyn DT_STRSZ |
636 // | Elf_Dyn DT_NULL |
637 // +-------------------------+ (Optional)
638 // | .strtab | (Optional)
639 // | program symbol names | (Optional)
640 // +-------------------------+ (Optional)
641 // | .symtab | (Optional)
642 // | program symbols | (Optional)
643 // +-------------------------+
644 // | .shstrtab |
645 // | \0 |
646 // | .dynamic\0 |
647 // | .dynsym\0 |
648 // | .dynstr\0 |
649 // | .hash\0 |
650 // | .rodata\0 |
651 // | .text\0 |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000652 // | .bss\0 | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700653 // | .shstrtab\0 |
654 // | .symtab\0 | (Optional)
655 // | .strtab\0 | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700656 // | .eh_frame\0 | (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100657 // | .eh_frame_hdr\0 | (Optional)
658 // | .debug_info\0 | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700659 // | .debug_abbrev\0 | (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100660 // | .debug_str\0 | (Optional)
661 // | .debug_line\0 | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700662 // +-------------------------+ (Optional)
663 // | .debug_info | (Optional)
664 // +-------------------------+ (Optional)
665 // | .debug_abbrev | (Optional)
666 // +-------------------------+ (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100667 // | .debug_str | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700668 // +-------------------------+ (Optional)
669 // | .debug_line | (Optional)
670 // +-------------------------+ (Optional)
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700671 // | Elf_Shdr null |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700672 // | Elf_Shdr .dynsym |
673 // | Elf_Shdr .dynstr |
674 // | Elf_Shdr .hash |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700675 // | Elf_Shdr .rodata |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000676 // | Elf_Shdr .text |
677 // | Elf_Shdr .bss | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700678 // | Elf_Shdr .dynamic |
679 // | Elf_Shdr .shstrtab |
David Srbecky527c9c72015-04-17 21:14:10 +0100680 // | Elf_Shdr .eh_frame | (Optional)
681 // | Elf_Shdr .eh_frame_hdr | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700682 // | Elf_Shdr .debug_info | (Optional)
683 // | Elf_Shdr .debug_abbrev | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700684 // | Elf_Shdr .debug_str | (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100685 // | Elf_Shdr .debug_line | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700686 // +-------------------------+
687
688 if (fatal_error_) {
689 return false;
690 }
691 // Step 1. Figure out all the offsets.
692
693 if (debug_logging_) {
694 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
695 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
696 }
697
698 memset(&program_headers_, 0, sizeof(program_headers_));
699 program_headers_[PH_PHDR].p_type = PT_PHDR;
700 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET;
701 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET;
702 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET;
703 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_);
704 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_);
705 program_headers_[PH_PHDR].p_flags = PF_R;
706 program_headers_[PH_PHDR].p_align = sizeof(Elf_Word);
707
708 program_headers_[PH_LOAD_R__].p_type = PT_LOAD;
709 program_headers_[PH_LOAD_R__].p_offset = 0;
710 program_headers_[PH_LOAD_R__].p_vaddr = 0;
711 program_headers_[PH_LOAD_R__].p_paddr = 0;
712 program_headers_[PH_LOAD_R__].p_flags = PF_R;
713
714 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD;
715 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X;
716
Vladimir Marko5c42c292015-02-25 12:02:49 +0000717 program_headers_[PH_LOAD_RW_BSS].p_type = PT_LOAD;
718 program_headers_[PH_LOAD_RW_BSS].p_flags = PF_R | PF_W;
719
720 program_headers_[PH_LOAD_RW_DYNAMIC].p_type = PT_LOAD;
721 program_headers_[PH_LOAD_RW_DYNAMIC].p_flags = PF_R | PF_W;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700722
723 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC;
724 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W;
725
David Srbecky527c9c72015-04-17 21:14:10 +0100726 program_headers_[PH_EH_FRAME_HDR].p_type = PT_NULL;
727 program_headers_[PH_EH_FRAME_HDR].p_flags = PF_R;
728
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700729 // Get the dynstr string.
730 dynstr_ = dynsym_builder_.GenerateStrtab();
731
732 // Add the SONAME to the dynstr.
733 dynstr_soname_offset_ = dynstr_.size();
734 std::string file_name(elf_file_->GetPath());
735 size_t directory_separator_pos = file_name.rfind('/');
736 if (directory_separator_pos != std::string::npos) {
737 file_name = file_name.substr(directory_separator_pos + 1);
738 }
739 dynstr_ += file_name;
740 dynstr_ += '\0';
741 if (debug_logging_) {
742 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size()
743 << std::hex << " " << dynstr_.size();
744 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
745 << std::hex << " " << dynsym_builder_.GetSize();
746 }
747
748 // Get the section header string table.
749 shstrtab_ += '\0';
750
751 // Setup sym_undef
752 memset(&null_hdr_, 0, sizeof(null_hdr_));
753 null_hdr_.sh_type = SHT_NULL;
754 null_hdr_.sh_link = SHN_UNDEF;
755 section_ptrs_.push_back(&null_hdr_);
756
757 section_index_ = 1;
758
759 // setup .dynsym
Ian Rogers0279ebb2014-10-08 17:27:48 -0700760 section_ptrs_.push_back(dynsym_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700761 AssignSectionStr(&dynsym_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700762 dynsym_builder_.SetSectionIndex(section_index_);
763 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700764
765 // Setup .dynstr
Ian Rogers0279ebb2014-10-08 17:27:48 -0700766 section_ptrs_.push_back(dynsym_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700767 AssignSectionStr(dynsym_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700768 dynsym_builder_.GetStrTab()->SetSectionIndex(section_index_);
769 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700770
771 // Setup .hash
Ian Rogers0279ebb2014-10-08 17:27:48 -0700772 section_ptrs_.push_back(hash_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700773 AssignSectionStr(&hash_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700774 hash_builder_.SetSectionIndex(section_index_);
775 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700776
David Srbecky0c5bbc12015-04-28 17:54:52 +0100777 // Setup .eh_frame and .eh_frame_hdr
778 for (auto* builder : other_builders_) {
779 if ((builder->GetSection()->sh_flags & SHF_ALLOC) != 0) {
780 section_ptrs_.push_back(builder->GetSection());
781 AssignSectionStr(builder, &shstrtab_);
782 builder->SetSectionIndex(section_index_);
783 section_index_++;
784 }
785 }
786
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700787 // Setup .rodata
Ian Rogers0279ebb2014-10-08 17:27:48 -0700788 section_ptrs_.push_back(rodata_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700789 AssignSectionStr(&rodata_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700790 rodata_builder_.SetSectionIndex(section_index_);
791 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700792
793 // Setup .text
Ian Rogers0279ebb2014-10-08 17:27:48 -0700794 section_ptrs_.push_back(text_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700795 AssignSectionStr(&text_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700796 text_builder_.SetSectionIndex(section_index_);
797 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700798
Vladimir Marko5c42c292015-02-25 12:02:49 +0000799 // Setup .bss
800 if (bss_builder_.GetSize() != 0u) {
801 section_ptrs_.push_back(bss_builder_.GetSection());
802 AssignSectionStr(&bss_builder_, &shstrtab_);
803 bss_builder_.SetSectionIndex(section_index_);
804 section_index_++;
805 }
806
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700807 // Setup .dynamic
Ian Rogers0279ebb2014-10-08 17:27:48 -0700808 section_ptrs_.push_back(dynamic_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700809 AssignSectionStr(&dynamic_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700810 dynamic_builder_.SetSectionIndex(section_index_);
811 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700812
813 // Fill in the hash section.
814 hash_ = dynsym_builder_.GenerateHashContents();
815
816 if (debug_logging_) {
817 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
818 << std::hex << " " << hash_.size() * sizeof(Elf_Word);
819 }
820
821 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
822
823 // Get the layout in the sections.
824 //
825 // Get the layout of the dynsym section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700826 dynsym_builder_.GetSection()->sh_offset =
827 RoundUp(base_offset, dynsym_builder_.GetSection()->sh_addralign);
828 dynsym_builder_.GetSection()->sh_addr = dynsym_builder_.GetSection()->sh_offset;
829 dynsym_builder_.GetSection()->sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
830 dynsym_builder_.GetSection()->sh_link = dynsym_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700831
832 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700833 dynsym_builder_.GetStrTab()->GetSection()->sh_offset =
834 NextOffset<Elf_Word, Elf_Shdr>(*dynsym_builder_.GetStrTab()->GetSection(),
835 *dynsym_builder_.GetSection());
836 dynsym_builder_.GetStrTab()->GetSection()->sh_addr =
837 dynsym_builder_.GetStrTab()->GetSection()->sh_offset;
838 dynsym_builder_.GetStrTab()->GetSection()->sh_size = dynstr_.size();
839 dynsym_builder_.GetStrTab()->GetSection()->sh_link = dynsym_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700840
841 // Get the layout of the hash section
Ian Rogers0279ebb2014-10-08 17:27:48 -0700842 hash_builder_.GetSection()->sh_offset =
843 NextOffset<Elf_Word, Elf_Shdr>(*hash_builder_.GetSection(),
844 *dynsym_builder_.GetStrTab()->GetSection());
845 hash_builder_.GetSection()->sh_addr = hash_builder_.GetSection()->sh_offset;
846 hash_builder_.GetSection()->sh_size = hash_.size() * sizeof(Elf_Word);
847 hash_builder_.GetSection()->sh_link = hash_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700848
David Srbecky527c9c72015-04-17 21:14:10 +0100849 // Get the layout of the extra sections with SHF_ALLOC flag.
850 // This will deal with .eh_frame and .eh_frame_hdr.
851 // .eh_frame contains relative pointers to .text which we
852 // want to fixup between the calls to Init() and Write().
853 // Therefore we handle those sections here as opposed to Write().
854 // It also has the nice side effect of including .eh_frame
855 // with the rest of LOAD_R segment. It must come before .rodata
856 // because .rodata and .text must be next to each other.
857 Elf_Shdr* prev = hash_builder_.GetSection();
858 for (auto* it : other_builders_) {
859 if ((it->GetSection()->sh_flags & SHF_ALLOC) != 0) {
860 it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
861 it->GetSection()->sh_addr = it->GetSection()->sh_offset;
862 it->GetSection()->sh_size = it->GetBuffer()->size();
863 it->GetSection()->sh_link = it->GetLink();
864 prev = it->GetSection();
865 }
866 }
867 // If the sections exist, check that they have been handled.
868 const auto* eh_frame = FindRawSection(".eh_frame");
869 if (eh_frame != nullptr) {
870 DCHECK_NE(eh_frame->GetSection()->sh_offset, 0u);
871 }
872 const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr");
873 if (eh_frame_hdr != nullptr) {
874 DCHECK_NE(eh_frame_hdr->GetSection()->sh_offset, 0u);
875 }
876
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700877 // Get the layout of the rodata section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700878 rodata_builder_.GetSection()->sh_offset =
David Srbecky527c9c72015-04-17 21:14:10 +0100879 NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(), *prev);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700880 rodata_builder_.GetSection()->sh_addr = rodata_builder_.GetSection()->sh_offset;
881 rodata_builder_.GetSection()->sh_size = rodata_builder_.GetSize();
882 rodata_builder_.GetSection()->sh_link = rodata_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700883
884 // Get the layout of the text section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700885 text_builder_.GetSection()->sh_offset =
886 NextOffset<Elf_Word, Elf_Shdr>(*text_builder_.GetSection(),
887 *rodata_builder_.GetSection());
888 text_builder_.GetSection()->sh_addr = text_builder_.GetSection()->sh_offset;
889 text_builder_.GetSection()->sh_size = text_builder_.GetSize();
890 text_builder_.GetSection()->sh_link = text_builder_.GetLink();
891 CHECK_ALIGNED(rodata_builder_.GetSection()->sh_offset +
892 rodata_builder_.GetSection()->sh_size, kPageSize);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700893
Vladimir Marko5c42c292015-02-25 12:02:49 +0000894 // Get the layout of the .bss section.
895 bss_builder_.GetSection()->sh_offset =
896 NextOffset<Elf_Word, Elf_Shdr>(*bss_builder_.GetSection(),
897 *text_builder_.GetSection());
898 bss_builder_.GetSection()->sh_addr = bss_builder_.GetSection()->sh_offset;
899 bss_builder_.GetSection()->sh_size = bss_builder_.GetSize();
900 bss_builder_.GetSection()->sh_link = bss_builder_.GetLink();
901
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700902 // Get the layout of the dynamic section.
Vladimir Marko5c42c292015-02-25 12:02:49 +0000903 CHECK(IsAlignedParam(bss_builder_.GetSection()->sh_offset,
904 dynamic_builder_.GetSection()->sh_addralign));
905 dynamic_builder_.GetSection()->sh_offset = bss_builder_.GetSection()->sh_offset;
906 dynamic_builder_.GetSection()->sh_addr =
907 NextOffset<Elf_Word, Elf_Shdr>(*dynamic_builder_.GetSection(), *bss_builder_.GetSection());
Ian Rogers0279ebb2014-10-08 17:27:48 -0700908 dynamic_builder_.GetSection()->sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
909 dynamic_builder_.GetSection()->sh_link = dynamic_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700910
911 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700912 LOG(INFO) << "dynsym off=" << dynsym_builder_.GetSection()->sh_offset
913 << " dynsym size=" << dynsym_builder_.GetSection()->sh_size;
914 LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->GetSection()->sh_offset
915 << " dynstr size=" << dynsym_builder_.GetStrTab()->GetSection()->sh_size;
916 LOG(INFO) << "hash off=" << hash_builder_.GetSection()->sh_offset
917 << " hash size=" << hash_builder_.GetSection()->sh_size;
918 LOG(INFO) << "rodata off=" << rodata_builder_.GetSection()->sh_offset
919 << " rodata size=" << rodata_builder_.GetSection()->sh_size;
920 LOG(INFO) << "text off=" << text_builder_.GetSection()->sh_offset
921 << " text size=" << text_builder_.GetSection()->sh_size;
922 LOG(INFO) << "dynamic off=" << dynamic_builder_.GetSection()->sh_offset
923 << " dynamic size=" << dynamic_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700924 }
925
926 return true;
927 }
928
929 bool Write() {
Andreas Gampecc676072014-09-23 22:58:07 -0700930 std::vector<ElfFilePiece<Elf_Word>*> pieces;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700931 Elf_Shdr* prev = dynamic_builder_.GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700932 std::string strtab;
933
934 if (IncludingDebugSymbols()) {
935 // Setup .symtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700936 section_ptrs_.push_back(symtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700937 AssignSectionStr(&symtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700938 symtab_builder_.SetSectionIndex(section_index_);
939 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700940
941 // Setup .strtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700942 section_ptrs_.push_back(symtab_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700943 AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700944 symtab_builder_.GetStrTab()->SetSectionIndex(section_index_);
945 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700946
947 strtab = symtab_builder_.GenerateStrtab();
948 if (debug_logging_) {
949 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
950 << std::hex << " " << strtab.size();
951 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
952 << std::hex << " " << symtab_builder_.GetSize();
953 }
954 }
955
956 // Setup all the other sections.
David Srbecky527c9c72015-04-17 21:14:10 +0100957 for (auto* builder : other_builders_) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100958 if ((builder->GetSection()->sh_flags & SHF_ALLOC) == 0) {
959 section_ptrs_.push_back(builder->GetSection());
960 AssignSectionStr(builder, &shstrtab_);
961 builder->SetSectionIndex(section_index_);
962 section_index_++;
963 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700964 }
965
966 // Setup shstrtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700967 section_ptrs_.push_back(shstrtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700968 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700969 shstrtab_builder_.SetSectionIndex(section_index_);
970 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700971
972 if (debug_logging_) {
973 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
974 << std::hex << " " << shstrtab_.size();
975 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
976 << std::hex << " " << section_ptrs_.size();
977 }
978
979 if (IncludingDebugSymbols()) {
980 // Get the layout of the symtab section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700981 symtab_builder_.GetSection()->sh_offset =
982 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetSection(),
983 *dynamic_builder_.GetSection());
984 symtab_builder_.GetSection()->sh_addr = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700985 // Add to leave space for the null symbol.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700986 symtab_builder_.GetSection()->sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
987 symtab_builder_.GetSection()->sh_link = symtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700988
989 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700990 symtab_builder_.GetStrTab()->GetSection()->sh_offset =
991 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetStrTab()->GetSection(),
992 *symtab_builder_.GetSection());
993 symtab_builder_.GetStrTab()->GetSection()->sh_addr = 0;
994 symtab_builder_.GetStrTab()->GetSection()->sh_size = strtab.size();
995 symtab_builder_.GetStrTab()->GetSection()->sh_link = symtab_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700996
Ian Rogers0279ebb2014-10-08 17:27:48 -0700997 prev = symtab_builder_.GetStrTab()->GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700998 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700999 LOG(INFO) << "symtab off=" << symtab_builder_.GetSection()->sh_offset
1000 << " symtab size=" << symtab_builder_.GetSection()->sh_size;
1001 LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->GetSection()->sh_offset
1002 << " strtab size=" << symtab_builder_.GetStrTab()->GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001003 }
1004 }
1005
David Srbecky527c9c72015-04-17 21:14:10 +01001006 // Get the layout of the extra sections without SHF_ALLOC flag.
1007 // (This will deal with the debug sections if they are there)
1008 for (auto* it : other_builders_) {
1009 if ((it->GetSection()->sh_flags & SHF_ALLOC) == 0) {
1010 it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
1011 it->GetSection()->sh_addr = 0;
1012 it->GetSection()->sh_size = it->GetBuffer()->size();
1013 it->GetSection()->sh_link = it->GetLink();
Andreas Gampecc676072014-09-23 22:58:07 -07001014
David Srbecky527c9c72015-04-17 21:14:10 +01001015 // We postpone adding an ElfFilePiece to keep the order in "pieces."
Andreas Gampecc676072014-09-23 22:58:07 -07001016
David Srbecky527c9c72015-04-17 21:14:10 +01001017 prev = it->GetSection();
1018 if (debug_logging_) {
1019 LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset
1020 << " size=" << it->GetSection()->sh_size;
1021 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001022 }
1023 }
1024
1025 // Get the layout of the shstrtab section
Ian Rogers0279ebb2014-10-08 17:27:48 -07001026 shstrtab_builder_.GetSection()->sh_offset =
1027 NextOffset<Elf_Word, Elf_Shdr>(*shstrtab_builder_.GetSection(), *prev);
1028 shstrtab_builder_.GetSection()->sh_addr = 0;
1029 shstrtab_builder_.GetSection()->sh_size = shstrtab_.size();
1030 shstrtab_builder_.GetSection()->sh_link = shstrtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001031 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001032 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.GetSection()->sh_offset
1033 << " shstrtab size=" << shstrtab_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001034 }
1035
1036 // The section list comes after come after.
1037 Elf_Word sections_offset = RoundUp(
Ian Rogers0279ebb2014-10-08 17:27:48 -07001038 shstrtab_builder_.GetSection()->sh_offset + shstrtab_builder_.GetSection()->sh_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001039 sizeof(Elf_Word));
1040
1041 // Setup the actual symbol arrays.
1042 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001043 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001044 std::vector<Elf_Sym> symtab;
1045 if (IncludingDebugSymbols()) {
1046 symtab = symtab_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001047 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001048 }
1049
1050 // Setup the dynamic section.
1051 // This will add the 2 values we cannot know until now time, namely the size
1052 // and the soname_offset.
1053 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
1054 dynstr_soname_offset_);
Ian Rogers0279ebb2014-10-08 17:27:48 -07001055 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001056
1057 // Finish setup of the program headers now that we know the layout of the
1058 // whole file.
Ian Rogers0279ebb2014-10-08 17:27:48 -07001059 Elf_Word load_r_size =
1060 rodata_builder_.GetSection()->sh_offset + rodata_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001061 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
1062 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001063 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001064
Ian Rogers0279ebb2014-10-08 17:27:48 -07001065 Elf_Word load_rx_size = text_builder_.GetSection()->sh_size;
1066 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.GetSection()->sh_offset;
1067 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.GetSection()->sh_offset;
1068 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.GetSection()->sh_offset;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001069 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
1070 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001071 program_headers_[PH_LOAD_R_X].p_align = text_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001072
Vladimir Marko5c42c292015-02-25 12:02:49 +00001073 program_headers_[PH_LOAD_RW_BSS].p_offset = bss_builder_.GetSection()->sh_offset;
1074 program_headers_[PH_LOAD_RW_BSS].p_vaddr = bss_builder_.GetSection()->sh_offset;
1075 program_headers_[PH_LOAD_RW_BSS].p_paddr = bss_builder_.GetSection()->sh_offset;
1076 program_headers_[PH_LOAD_RW_BSS].p_filesz = 0;
1077 program_headers_[PH_LOAD_RW_BSS].p_memsz = bss_builder_.GetSection()->sh_size;
1078 program_headers_[PH_LOAD_RW_BSS].p_align = bss_builder_.GetSection()->sh_addralign;
1079
1080 program_headers_[PH_LOAD_RW_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
1081 program_headers_[PH_LOAD_RW_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_addr;
1082 program_headers_[PH_LOAD_RW_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_addr;
1083 program_headers_[PH_LOAD_RW_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1084 program_headers_[PH_LOAD_RW_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1085 program_headers_[PH_LOAD_RW_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001086
Ian Rogers0279ebb2014-10-08 17:27:48 -07001087 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001088 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_addr;
1089 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_addr;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001090 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1091 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1092 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001093
David Srbecky527c9c72015-04-17 21:14:10 +01001094 const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr");
1095 if (eh_frame_hdr != nullptr) {
1096 const auto* eh_frame = FindRawSection(".eh_frame");
1097 // Check layout:
1098 // 1) eh_frame is before eh_frame_hdr.
1099 // 2) There's no gap.
1100 CHECK(eh_frame != nullptr);
1101 CHECK_LE(eh_frame->GetSection()->sh_offset, eh_frame_hdr->GetSection()->sh_offset);
1102 CHECK_EQ(eh_frame->GetSection()->sh_offset + eh_frame->GetSection()->sh_size,
1103 eh_frame_hdr->GetSection()->sh_offset);
1104
1105 program_headers_[PH_EH_FRAME_HDR].p_type = PT_GNU_EH_FRAME;
1106 program_headers_[PH_EH_FRAME_HDR].p_offset = eh_frame_hdr->GetSection()->sh_offset;
1107 program_headers_[PH_EH_FRAME_HDR].p_vaddr = eh_frame_hdr->GetSection()->sh_addr;
1108 program_headers_[PH_EH_FRAME_HDR].p_paddr = eh_frame_hdr->GetSection()->sh_addr;
1109 program_headers_[PH_EH_FRAME_HDR].p_filesz = eh_frame_hdr->GetSection()->sh_size;
1110 program_headers_[PH_EH_FRAME_HDR].p_memsz = eh_frame_hdr->GetSection()->sh_size;
1111 program_headers_[PH_EH_FRAME_HDR].p_align = eh_frame_hdr->GetSection()->sh_addralign;
1112 }
1113
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001114 // Finish setup of the Ehdr values.
1115 elf_header_.e_phoff = PHDR_OFFSET;
1116 elf_header_.e_shoff = sections_offset;
David Srbecky0c5bbc12015-04-28 17:54:52 +01001117 elf_header_.e_phnum = PH_NUM - (bss_builder_.GetSection()->sh_size == 0u ? 1 : 0)
1118 - (eh_frame_hdr == nullptr ? 1 : 0);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001119 elf_header_.e_shnum = section_ptrs_.size();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001120 elf_header_.e_shstrndx = shstrtab_builder_.GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001121
1122 // Add the rest of the pieces to the list.
Andreas Gampecc676072014-09-23 22:58:07 -07001123 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_,
1124 sizeof(elf_header_)));
Vladimir Marko5c42c292015-02-25 12:02:49 +00001125 if (bss_builder_.GetSection()->sh_size != 0u) {
1126 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1127 &program_headers_[0],
1128 elf_header_.e_phnum * sizeof(Elf_Phdr)));
1129 } else {
1130 // Skip PH_LOAD_RW_BSS.
1131 Elf_Word part1_size = PH_LOAD_RW_BSS * sizeof(Elf_Phdr);
David Srbecky0c5bbc12015-04-28 17:54:52 +01001132 Elf_Word part2_size = (elf_header_.e_phnum - PH_LOAD_RW_BSS) * sizeof(Elf_Phdr);
Vladimir Marko5c42c292015-02-25 12:02:49 +00001133 CHECK_EQ(part1_size + part2_size, elf_header_.e_phnum * sizeof(Elf_Phdr));
1134 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1135 &program_headers_[0], part1_size));
1136 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers part 2",
1137 PHDR_OFFSET + part1_size,
1138 &program_headers_[PH_LOAD_RW_BSS + 1],
1139 part2_size));
1140 }
Andreas Gampecc676072014-09-23 22:58:07 -07001141 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001142 dynamic_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001143 dynamic.data(),
Ian Rogers0279ebb2014-10-08 17:27:48 -07001144 dynamic_builder_.GetSection()->sh_size));
1145 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001146 dynsym.data(),
1147 dynsym.size() * sizeof(Elf_Sym)));
1148 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001149 dynsym_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001150 dynstr_.c_str(), dynstr_.size()));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001151 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001152 hash_.data(),
1153 hash_.size() * sizeof(Elf_Word)));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001154 pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001155 oat_writer_));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001156 pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001157 oat_writer_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001158 if (IncludingDebugSymbols()) {
Andreas Gampecc676072014-09-23 22:58:07 -07001159 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001160 symtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001161 symtab.data(),
1162 symtab.size() * sizeof(Elf_Sym)));
1163 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001164 symtab_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001165 strtab.c_str(), strtab.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001166 }
Andreas Gampecc676072014-09-23 22:58:07 -07001167 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001168 shstrtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001169 &shstrtab_[0], shstrtab_.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001170 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
1171 // Just add all the sections in induvidually since they are all over the
1172 // place on the heap/stack.
1173 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
Andreas Gampecc676072014-09-23 22:58:07 -07001174 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off,
1175 section_ptrs_[i], sizeof(Elf_Shdr)));
1176 }
1177
1178 // Postponed debug info.
David Srbecky527c9c72015-04-17 21:14:10 +01001179 for (auto* it : other_builders_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001180 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->GetName(), it->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001181 it->GetBuffer()->data(),
1182 it->GetBuffer()->size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001183 }
1184
1185 if (!WriteOutFile(pieces)) {
1186 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
Andreas Gampecc676072014-09-23 22:58:07 -07001187
1188 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001189 return false;
1190 }
1191
Andreas Gampecc676072014-09-23 22:58:07 -07001192 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001193 return true;
1194 }
1195
David Srbecky527c9c72015-04-17 21:14:10 +01001196 // Adds the given raw section to the builder. It does not take ownership.
David Srbecky0c5bbc12015-04-28 17:54:52 +01001197 void RegisterRawSection(ElfRawSectionBuilder* bld) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001198 other_builders_.push_back(bld);
1199 }
1200
David Srbecky0c5bbc12015-04-28 17:54:52 +01001201 const ElfRawSectionBuilder* FindRawSection(const char* name) {
David Srbecky527c9c72015-04-17 21:14:10 +01001202 for (const auto* other_builder : other_builders_) {
1203 if (other_builder->GetName() == name) {
1204 return other_builder;
1205 }
1206 }
1207 return nullptr;
1208 }
1209
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001210 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001211 void SetISA(InstructionSet isa) {
1212 switch (isa) {
1213 case kArm:
1214 // Fall through.
1215 case kThumb2: {
1216 elf_header_.e_machine = EM_ARM;
1217 elf_header_.e_flags = EF_ARM_EABI_VER5;
1218 break;
1219 }
1220 case kArm64: {
1221 elf_header_.e_machine = EM_AARCH64;
1222 elf_header_.e_flags = 0;
1223 break;
1224 }
1225 case kX86: {
1226 elf_header_.e_machine = EM_386;
1227 elf_header_.e_flags = 0;
1228 break;
1229 }
1230 case kX86_64: {
1231 elf_header_.e_machine = EM_X86_64;
1232 elf_header_.e_flags = 0;
1233 break;
1234 }
1235 case kMips: {
1236 elf_header_.e_machine = EM_MIPS;
1237 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1238 EF_MIPS_PIC |
1239 EF_MIPS_CPIC |
1240 EF_MIPS_ABI_O32 |
1241 EF_MIPS_ARCH_32R2);
1242 break;
1243 }
Andreas Gampe57b34292015-01-14 15:45:59 -08001244 case kMips64: {
1245 elf_header_.e_machine = EM_MIPS;
1246 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1247 EF_MIPS_PIC |
1248 EF_MIPS_CPIC |
1249 EF_MIPS_ARCH_64R6);
1250 break;
1251 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001252 default: {
1253 fatal_error_ = true;
1254 LOG(FATAL) << "Unknown instruction set: " << isa;
1255 break;
1256 }
1257 }
1258 }
1259
1260 void SetupEhdr() {
1261 memset(&elf_header_, 0, sizeof(elf_header_));
1262 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
1263 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
1264 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
1265 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
Tong Shen62d1ca32014-09-03 17:24:56 -07001266 elf_header_.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
1267 ? ELFCLASS32 : ELFCLASS64;;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001268 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
1269 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
1270 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
1271 elf_header_.e_ident[EI_ABIVERSION] = 0;
1272 elf_header_.e_type = ET_DYN;
1273 elf_header_.e_version = 1;
1274 elf_header_.e_entry = 0;
1275 elf_header_.e_ehsize = sizeof(Elf_Ehdr);
1276 elf_header_.e_phentsize = sizeof(Elf_Phdr);
1277 elf_header_.e_shentsize = sizeof(Elf_Shdr);
1278 elf_header_.e_phoff = sizeof(Elf_Ehdr);
1279 }
1280
1281 // Sets up a bunch of the required Dynamic Section entries.
1282 // Namely it will initialize all the mandatory ones that it can.
1283 // Specifically:
1284 // DT_HASH
1285 // DT_STRTAB
1286 // DT_SYMTAB
1287 // DT_SYMENT
1288 //
1289 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
1290 void SetupDynamic() {
1291 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
1292 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1293 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1294 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1295 }
1296
1297 // Sets up the basic dynamic symbols that are needed, namely all those we
1298 // can know already.
1299 //
1300 // Specifically adds:
1301 // oatdata
1302 // oatexec
1303 // oatlastword
1304 void SetupRequiredSymbols() {
1305 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1306 rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1307 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1308 text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1309 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1310 true, 4, STB_GLOBAL, STT_OBJECT);
Vladimir Marko5c42c292015-02-25 12:02:49 +00001311 if (bss_builder_.GetSize() != 0u) {
1312 dynsym_builder_.AddSymbol("oatbss", &bss_builder_, 0, true,
1313 bss_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1314 dynsym_builder_.AddSymbol("oatbsslastword", &bss_builder_, bss_builder_.GetSize() - 4,
1315 true, 4, STB_GLOBAL, STT_OBJECT);
1316 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001317 }
1318
David Srbecky0c5bbc12015-04-28 17:54:52 +01001319 void AssignSectionStr(ElfSectionBuilder* builder, std::string* strtab) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001320 builder->GetSection()->sh_name = strtab->size();
1321 *strtab += builder->GetName();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001322 *strtab += '\0';
1323 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001324 LOG(INFO) << "adding section name \"" << builder->GetName() << "\" "
1325 << "to shstrtab at offset " << builder->GetSection()->sh_name;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001326 }
1327 }
1328
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001329
1330 // Write each of the pieces out to the file.
Andreas Gampecc676072014-09-23 22:58:07 -07001331 bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001332 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
Andreas Gampecc676072014-09-23 22:58:07 -07001333 if (!(*it)->Write(elf_file_)) {
1334 return false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001335 }
1336 }
1337 return true;
1338 }
1339
Ian Rogers0279ebb2014-10-08 17:27:48 -07001340 bool IncludingDebugSymbols() const {
1341 return add_symbols_ && symtab_builder_.GetSize() > 1;
1342 }
1343
1344 CodeOutput* const oat_writer_;
1345 File* const elf_file_;
1346 const bool add_symbols_;
1347 const bool debug_logging_;
1348
1349 bool fatal_error_ = false;
1350
1351 // What phdr is.
1352 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
1353 enum : uint8_t {
Vladimir Marko5c42c292015-02-25 12:02:49 +00001354 PH_PHDR = 0,
1355 PH_LOAD_R__ = 1,
1356 PH_LOAD_R_X = 2,
1357 PH_LOAD_RW_BSS = 3,
1358 PH_LOAD_RW_DYNAMIC = 4,
1359 PH_DYNAMIC = 5,
David Srbecky527c9c72015-04-17 21:14:10 +01001360 PH_EH_FRAME_HDR = 6,
1361 PH_NUM = 7,
Ian Rogers0279ebb2014-10-08 17:27:48 -07001362 };
1363 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
1364 Elf_Phdr program_headers_[PH_NUM];
1365
1366 Elf_Ehdr elf_header_;
1367
1368 Elf_Shdr null_hdr_;
1369 std::string shstrtab_;
1370 // The index of the current section being built. The first being 1.
1371 uint32_t section_index_;
1372 std::string dynstr_;
1373 uint32_t dynstr_soname_offset_;
1374 std::vector<const Elf_Shdr*> section_ptrs_;
1375 std::vector<Elf_Word> hash_;
1376
David Srbecky0c5bbc12015-04-28 17:54:52 +01001377 ElfOatSectionBuilder text_builder_;
1378 ElfOatSectionBuilder rodata_builder_;
1379 ElfOatSectionBuilder bss_builder_;
1380 ElfSymtabBuilder dynsym_builder_;
1381 ElfSymtabBuilder symtab_builder_;
1382 ElfSectionBuilder hash_builder_;
1383 ElfDynamicBuilder dynamic_builder_;
1384 ElfSectionBuilder shstrtab_builder_;
1385 std::vector<ElfRawSectionBuilder*> other_builders_;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001386
1387 DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001388};
1389
1390} // namespace art
1391
1392#endif // ART_COMPILER_ELF_BUILDER_H_