blob: 323c933ab1e790f9f2fd8dd718a70c4b231a8f46 [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
29template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -070030class ElfSectionBuilder : public ValueObject {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070031 public:
32 ElfSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
33 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link, Elf_Word info,
Ian Rogers0279ebb2014-10-08 17:27:48 -070034 Elf_Word align, Elf_Word entsize)
35 : section_index_(0), name_(sec_name), link_(link) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070036 memset(&section_, 0, sizeof(section_));
37 section_.sh_type = type;
38 section_.sh_flags = flags;
39 section_.sh_info = info;
40 section_.sh_addralign = align;
41 section_.sh_entsize = entsize;
42 }
Andreas Gampe758a8012015-04-03 21:28:42 -070043 ElfSectionBuilder(const ElfSectionBuilder&) = default;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070044
Ian Rogers0279ebb2014-10-08 17:27:48 -070045 ~ElfSectionBuilder() {}
Andreas Gampe54fc26c2014-09-04 21:47:42 -070046
Ian Rogers0279ebb2014-10-08 17:27:48 -070047 Elf_Word GetLink() const {
48 return (link_ != nullptr) ? link_->section_index_ : 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070049 }
50
Ian Rogers0279ebb2014-10-08 17:27:48 -070051 const Elf_Shdr* GetSection() const {
52 return &section_;
53 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -070054
Ian Rogers0279ebb2014-10-08 17:27:48 -070055 Elf_Shdr* GetSection() {
56 return &section_;
57 }
58
59 Elf_Word GetSectionIndex() const {
60 return section_index_;
61 }
62
63 void SetSectionIndex(Elf_Word section_index) {
64 section_index_ = section_index;
65 }
66
67 const std::string& GetName() const {
68 return name_;
69 }
70
71 private:
72 Elf_Shdr section_;
73 Elf_Word section_index_;
74 const std::string name_;
75 const ElfSectionBuilder* const link_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070076};
77
78template <typename Elf_Word, typename Elf_Sword, typename Elf_Dyn, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -070079class ElfDynamicBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070080 public:
81 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un) {
82 if (tag == DT_NULL) {
83 return;
84 }
85 dynamics_.push_back({nullptr, tag, d_un});
86 }
87
88 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un,
Ian Rogers0279ebb2014-10-08 17:27:48 -070089 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070090 if (tag == DT_NULL) {
91 return;
92 }
93 dynamics_.push_back({section, tag, d_un});
94 }
95
96 ElfDynamicBuilder(const std::string& sec_name,
97 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link)
98 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC,
99 link, 0, kPageSize, sizeof(Elf_Dyn)) {}
100 ~ElfDynamicBuilder() {}
101
Ian Rogers0279ebb2014-10-08 17:27:48 -0700102 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700103 // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
104 // these must be added when we actually put the file together because
105 // their values are very dependent on state.
106 return dynamics_.size() + 3;
107 }
108
109 // Create the actual dynamic vector. strsz should be the size of the .dynstr
110 // table and soname_off should be the offset of the soname in .dynstr.
111 // Since niether can be found prior to final layout we will wait until here
112 // to add them.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700113 std::vector<Elf_Dyn> GetDynamics(Elf_Word strsz, Elf_Word soname) const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700114 std::vector<Elf_Dyn> ret;
115 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700116 if (it->section_ != nullptr) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700117 // We are adding an address relative to a section.
118 ret.push_back(
Ian Rogers0279ebb2014-10-08 17:27:48 -0700119 {it->tag_, {it->off_ + it->section_->GetSection()->sh_addr}});
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700120 } else {
121 ret.push_back({it->tag_, {it->off_}});
122 }
123 }
124 ret.push_back({DT_STRSZ, {strsz}});
125 ret.push_back({DT_SONAME, {soname}});
126 ret.push_back({DT_NULL, {0}});
127 return ret;
128 }
129
Ian Rogers0279ebb2014-10-08 17:27:48 -0700130 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700131 struct ElfDynamicState {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700132 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700133 Elf_Sword tag_;
134 Elf_Word off_;
135 };
136 std::vector<ElfDynamicState> dynamics_;
137};
138
139template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700140class ElfRawSectionBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700141 public:
142 ElfRawSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
143 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* link, Elf_Word info,
144 Elf_Word align, Elf_Word entsize)
145 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, link, info, align,
Ian Rogers0279ebb2014-10-08 17:27:48 -0700146 entsize) {
147 }
Andreas Gampe758a8012015-04-03 21:28:42 -0700148 ElfRawSectionBuilder(const ElfRawSectionBuilder&) = default;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700149
Ian Rogers0279ebb2014-10-08 17:27:48 -0700150 ~ElfRawSectionBuilder() {}
151
152 std::vector<uint8_t>* GetBuffer() {
153 return &buf_;
154 }
155
156 void SetBuffer(const std::vector<uint8_t>& buf) {
157 buf_ = buf;
158 }
159
160 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700161 std::vector<uint8_t> buf_;
162};
163
164template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700165class ElfOatSectionBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700166 public:
167 ElfOatSectionBuilder(const std::string& sec_name, Elf_Word size, Elf_Word offset,
168 Elf_Word type, Elf_Word flags)
169 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, nullptr, 0, kPageSize,
Ian Rogers0279ebb2014-10-08 17:27:48 -0700170 0),
171 offset_(offset), size_(size) {
172 }
173
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700174 ~ElfOatSectionBuilder() {}
175
Ian Rogers0279ebb2014-10-08 17:27:48 -0700176 Elf_Word GetOffset() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700177 return offset_;
178 }
179
Ian Rogers0279ebb2014-10-08 17:27:48 -0700180 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700181 return size_;
182 }
183
Ian Rogers0279ebb2014-10-08 17:27:48 -0700184 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700185 // Offset of the content within the file.
186 Elf_Word offset_;
187 // Size of the content within the file.
188 Elf_Word size_;
189};
190
191static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
192 return ((binding) << 4) + ((type) & 0xf);
193}
194
195// from bionic
196static inline unsigned elfhash(const char *_name) {
197 const unsigned char *name = (const unsigned char *) _name;
198 unsigned h = 0, g;
199
200 while (*name) {
201 h = (h << 4) + *name++;
202 g = h & 0xf0000000;
203 h ^= g;
204 h ^= g >> 24;
205 }
206 return h;
207}
208
209template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Sym,
210 typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700211class ElfSymtabBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700212 public:
213 // Add a symbol with given name to this symtab. The symbol refers to
214 // 'relative_addr' within the given section and has the given attributes.
215 void AddSymbol(const std::string& name,
216 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section,
217 Elf_Addr addr,
218 bool is_relative,
219 Elf_Word size,
220 uint8_t binding,
221 uint8_t type,
222 uint8_t other = 0) {
223 CHECK(section);
224 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
225 MakeStInfo(binding, type), other, 0};
226 symbols_.push_back(state);
227 }
228
229 ElfSymtabBuilder(const std::string& sec_name, Elf_Word type,
230 const std::string& str_name, Elf_Word str_type, bool alloc)
231 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, ((alloc) ? SHF_ALLOC : 0U),
232 &strtab_, 0, sizeof(Elf_Word),
233 sizeof(Elf_Sym)), str_name_(str_name),
234 str_type_(str_type),
235 strtab_(str_name,
236 str_type,
237 ((alloc) ? SHF_ALLOC : 0U),
Ian Rogers0279ebb2014-10-08 17:27:48 -0700238 nullptr, 0, 1, 1) {
239 }
240
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700241 ~ElfSymtabBuilder() {}
242
Ian Rogers0279ebb2014-10-08 17:27:48 -0700243 std::vector<Elf_Word> GenerateHashContents() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700244 // Here is how The ELF hash table works.
245 // There are 3 arrays to worry about.
246 // * The symbol table where the symbol information is.
247 // * The bucket array which is an array of indexes into the symtab and chain.
248 // * The chain array which is also an array of indexes into the symtab and chain.
249 //
250 // Lets say the state is something like this.
251 // +--------+ +--------+ +-----------+
252 // | symtab | | bucket | | chain |
253 // | null | | 1 | | STN_UNDEF |
254 // | <sym1> | | 4 | | 2 |
255 // | <sym2> | | | | 5 |
256 // | <sym3> | | | | STN_UNDEF |
257 // | <sym4> | | | | 3 |
258 // | <sym5> | | | | STN_UNDEF |
259 // +--------+ +--------+ +-----------+
260 //
261 // The lookup process (in python psudocode) is
262 //
263 // def GetSym(name):
264 // # NB STN_UNDEF == 0
265 // indx = bucket[elfhash(name) % num_buckets]
266 // while indx != STN_UNDEF:
267 // if GetSymbolName(symtab[indx]) == name:
268 // return symtab[indx]
269 // indx = chain[indx]
270 // return SYMBOL_NOT_FOUND
271 //
272 // Between bucket and chain arrays every symtab index must be present exactly
273 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
274
275 // Select number of buckets.
276 // This is essentially arbitrary.
277 Elf_Word nbuckets;
278 Elf_Word chain_size = GetSize();
279 if (symbols_.size() < 8) {
280 nbuckets = 2;
281 } else if (symbols_.size() < 32) {
282 nbuckets = 4;
283 } else if (symbols_.size() < 256) {
284 nbuckets = 16;
285 } else {
286 // Have about 32 ids per bucket.
287 nbuckets = RoundUp(symbols_.size()/32, 2);
288 }
289 std::vector<Elf_Word> hash;
290 hash.push_back(nbuckets);
291 hash.push_back(chain_size);
292 uint32_t bucket_offset = hash.size();
293 uint32_t chain_offset = bucket_offset + nbuckets;
294 hash.resize(hash.size() + nbuckets + chain_size, 0);
295
296 Elf_Word* buckets = hash.data() + bucket_offset;
297 Elf_Word* chain = hash.data() + chain_offset;
298
299 // Set up the actual hash table.
300 for (Elf_Word i = 0; i < symbols_.size(); i++) {
301 // Add 1 since we need to have the null symbol that is not in the symbols
302 // list.
303 Elf_Word index = i + 1;
304 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
305 if (buckets[hash_val] == 0) {
306 buckets[hash_val] = index;
307 } else {
308 hash_val = buckets[hash_val];
309 CHECK_LT(hash_val, chain_size);
310 while (chain[hash_val] != 0) {
311 hash_val = chain[hash_val];
312 CHECK_LT(hash_val, chain_size);
313 }
314 chain[hash_val] = index;
315 // Check for loops. Works because if this is non-empty then there must be
316 // another cell which already contains the same symbol index as this one,
317 // which means some symbol has more then one name, which isn't allowed.
318 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
319 }
320 }
321
322 return hash;
323 }
324
325 std::string GenerateStrtab() {
326 std::string tab;
327 tab += '\0';
328 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
329 it->name_idx_ = tab.size();
330 tab += it->name_;
331 tab += '\0';
332 }
Ian Rogers0279ebb2014-10-08 17:27:48 -0700333 strtab_.GetSection()->sh_size = tab.size();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700334 return tab;
335 }
336
337 std::vector<Elf_Sym> GenerateSymtab() {
338 std::vector<Elf_Sym> ret;
339 Elf_Sym undef_sym;
340 memset(&undef_sym, 0, sizeof(undef_sym));
341 undef_sym.st_shndx = SHN_UNDEF;
342 ret.push_back(undef_sym);
343
344 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
345 Elf_Sym sym;
346 memset(&sym, 0, sizeof(sym));
347 sym.st_name = it->name_idx_;
348 if (it->is_relative_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700349 sym.st_value = it->addr_ + it->section_->GetSection()->sh_offset;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700350 } else {
351 sym.st_value = it->addr_;
352 }
353 sym.st_size = it->size_;
354 sym.st_other = it->other_;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700355 sym.st_shndx = it->section_->GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700356 sym.st_info = it->info_;
357
358 ret.push_back(sym);
359 }
360 return ret;
361 }
362
Ian Rogers0279ebb2014-10-08 17:27:48 -0700363 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700364 // 1 is for the implicit NULL symbol.
365 return symbols_.size() + 1;
366 }
367
368 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* GetStrTab() {
369 return &strtab_;
370 }
371
Ian Rogers0279ebb2014-10-08 17:27:48 -0700372 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700373 struct ElfSymbolState {
374 const std::string name_;
375 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_;
376 Elf_Addr addr_;
377 Elf_Word size_;
378 bool is_relative_;
379 uint8_t info_;
380 uint8_t other_;
381 // Used during Write() to temporarially hold name index in the strtab.
382 Elf_Word name_idx_;
383 };
384
385 // Information for the strsym for dynstr sections.
386 const std::string str_name_;
387 Elf_Word str_type_;
388 // The symbols in the same order they will be in the symbol table.
389 std::vector<ElfSymbolState> symbols_;
390 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> strtab_;
391};
392
Andreas Gampecc676072014-09-23 22:58:07 -0700393template <typename Elf_Word>
394class ElfFilePiece {
395 public:
396 virtual ~ElfFilePiece() {}
397
398 virtual bool Write(File* elf_file) {
399 if (static_cast<off_t>(offset_) != lseek(elf_file->Fd(), offset_, SEEK_SET)) {
400 PLOG(ERROR) << "Failed to seek to " << GetDescription() << " offset " << offset_ << " for "
401 << elf_file->GetPath();
402 return false;
403 }
404
405 return DoActualWrite(elf_file);
406 }
407
408 static bool Compare(ElfFilePiece* a, ElfFilePiece* b) {
409 return a->offset_ < b->offset_;
410 }
411
412 protected:
413 explicit ElfFilePiece(Elf_Word offset) : offset_(offset) {}
414
Ian Rogers0279ebb2014-10-08 17:27:48 -0700415 Elf_Word GetOffset() const {
416 return offset_;
417 }
418
419 virtual const char* GetDescription() const = 0;
Andreas Gampecc676072014-09-23 22:58:07 -0700420 virtual bool DoActualWrite(File* elf_file) = 0;
421
Ian Rogers0279ebb2014-10-08 17:27:48 -0700422 private:
423 const Elf_Word offset_;
424
425 DISALLOW_COPY_AND_ASSIGN(ElfFilePiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700426};
427
428template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700429class ElfFileMemoryPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700430 public:
431 ElfFileMemoryPiece(const std::string& name, Elf_Word offset, const void* data, Elf_Word size)
432 : ElfFilePiece<Elf_Word>(offset), dbg_name_(name), data_(data), size_(size) {}
433
Ian Rogers0279ebb2014-10-08 17:27:48 -0700434 protected:
Andreas Gampecc676072014-09-23 22:58:07 -0700435 bool DoActualWrite(File* elf_file) OVERRIDE {
436 DCHECK(data_ != nullptr || size_ == 0U) << dbg_name_ << " " << size_;
437
438 if (!elf_file->WriteFully(data_, size_)) {
439 PLOG(ERROR) << "Failed to write " << dbg_name_ << " for " << elf_file->GetPath();
440 return false;
441 }
442
443 return true;
444 }
445
Ian Rogers0279ebb2014-10-08 17:27:48 -0700446 const char* GetDescription() const OVERRIDE {
447 return dbg_name_.c_str();
Andreas Gampecc676072014-09-23 22:58:07 -0700448 }
449
450 private:
451 const std::string& dbg_name_;
452 const void *data_;
453 Elf_Word size_;
454};
455
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700456class CodeOutput {
457 public:
Vladimir Markof4da6752014-08-01 19:04:18 +0100458 virtual void SetCodeOffset(size_t offset) = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700459 virtual bool Write(OutputStream* out) = 0;
460 virtual ~CodeOutput() {}
461};
462
Andreas Gampecc676072014-09-23 22:58:07 -0700463template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700464class ElfFileRodataPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700465 public:
466 ElfFileRodataPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
467 output_(output) {}
468
Ian Rogers0279ebb2014-10-08 17:27:48 -0700469 protected:
Andreas Gampecc676072014-09-23 22:58:07 -0700470 bool DoActualWrite(File* elf_file) OVERRIDE {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700471 output_->SetCodeOffset(this->GetOffset());
Andreas Gampecc676072014-09-23 22:58:07 -0700472 std::unique_ptr<BufferedOutputStream> output_stream(
473 new BufferedOutputStream(new FileOutputStream(elf_file)));
474 if (!output_->Write(output_stream.get())) {
475 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file->GetPath();
476 return false;
477 }
478
479 return true;
480 }
481
Ian Rogers0279ebb2014-10-08 17:27:48 -0700482 const char* GetDescription() const OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700483 return ".rodata";
484 }
485
486 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700487 CodeOutput* const output_;
488
489 DISALLOW_COPY_AND_ASSIGN(ElfFileRodataPiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700490};
491
492template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700493class ElfFileOatTextPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700494 public:
495 ElfFileOatTextPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
496 output_(output) {}
497
Ian Rogers0279ebb2014-10-08 17:27:48 -0700498 protected:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700499 bool DoActualWrite(File* elf_file ATTRIBUTE_UNUSED) OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700500 // All data is written by the ElfFileRodataPiece right now, as the oat writer writes in one
501 // piece. This is for future flexibility.
502 UNUSED(output_);
503 return true;
504 }
505
Ian Rogers0279ebb2014-10-08 17:27:48 -0700506 const char* GetDescription() const OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700507 return ".text";
508 }
509
510 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700511 CodeOutput* const output_;
512
513 DISALLOW_COPY_AND_ASSIGN(ElfFileOatTextPiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700514};
515
516template <typename Elf_Word>
517static bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces, File* elf_file) {
518 // TODO It would be nice if this checked for overlap.
519 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
520 if (!(*it)->Write(elf_file)) {
521 return false;
522 }
523 }
524 return true;
525}
526
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700527template <typename Elf_Word, typename Elf_Shdr>
528static inline constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) {
529 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
530}
531
532template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Dyn,
533 typename Elf_Sym, typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr>
534class ElfBuilder FINAL {
535 public:
536 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_),
560 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
561 SetupEhdr();
562 SetupDynamic();
563 SetupRequiredSymbols();
564 SetISA(isa);
565 }
566 ~ElfBuilder() {}
567
Ian Rogers0279ebb2014-10-08 17:27:48 -0700568 const ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>& GetTextBuilder() const {
569 return text_builder_;
570 }
571
572 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* GetSymtabBuilder() {
573 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)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700671 // | Elf_Shdr NULL |
672 // | 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
777 // Setup .rodata
Ian Rogers0279ebb2014-10-08 17:27:48 -0700778 section_ptrs_.push_back(rodata_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700779 AssignSectionStr(&rodata_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700780 rodata_builder_.SetSectionIndex(section_index_);
781 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700782
783 // Setup .text
Ian Rogers0279ebb2014-10-08 17:27:48 -0700784 section_ptrs_.push_back(text_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700785 AssignSectionStr(&text_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700786 text_builder_.SetSectionIndex(section_index_);
787 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700788
Vladimir Marko5c42c292015-02-25 12:02:49 +0000789 // Setup .bss
790 if (bss_builder_.GetSize() != 0u) {
791 section_ptrs_.push_back(bss_builder_.GetSection());
792 AssignSectionStr(&bss_builder_, &shstrtab_);
793 bss_builder_.SetSectionIndex(section_index_);
794 section_index_++;
795 }
796
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700797 // Setup .dynamic
Ian Rogers0279ebb2014-10-08 17:27:48 -0700798 section_ptrs_.push_back(dynamic_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700799 AssignSectionStr(&dynamic_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700800 dynamic_builder_.SetSectionIndex(section_index_);
801 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700802
803 // Fill in the hash section.
804 hash_ = dynsym_builder_.GenerateHashContents();
805
806 if (debug_logging_) {
807 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
808 << std::hex << " " << hash_.size() * sizeof(Elf_Word);
809 }
810
811 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
812
813 // Get the layout in the sections.
814 //
815 // Get the layout of the dynsym section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700816 dynsym_builder_.GetSection()->sh_offset =
817 RoundUp(base_offset, dynsym_builder_.GetSection()->sh_addralign);
818 dynsym_builder_.GetSection()->sh_addr = dynsym_builder_.GetSection()->sh_offset;
819 dynsym_builder_.GetSection()->sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
820 dynsym_builder_.GetSection()->sh_link = dynsym_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700821
822 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700823 dynsym_builder_.GetStrTab()->GetSection()->sh_offset =
824 NextOffset<Elf_Word, Elf_Shdr>(*dynsym_builder_.GetStrTab()->GetSection(),
825 *dynsym_builder_.GetSection());
826 dynsym_builder_.GetStrTab()->GetSection()->sh_addr =
827 dynsym_builder_.GetStrTab()->GetSection()->sh_offset;
828 dynsym_builder_.GetStrTab()->GetSection()->sh_size = dynstr_.size();
829 dynsym_builder_.GetStrTab()->GetSection()->sh_link = dynsym_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700830
831 // Get the layout of the hash section
Ian Rogers0279ebb2014-10-08 17:27:48 -0700832 hash_builder_.GetSection()->sh_offset =
833 NextOffset<Elf_Word, Elf_Shdr>(*hash_builder_.GetSection(),
834 *dynsym_builder_.GetStrTab()->GetSection());
835 hash_builder_.GetSection()->sh_addr = hash_builder_.GetSection()->sh_offset;
836 hash_builder_.GetSection()->sh_size = hash_.size() * sizeof(Elf_Word);
837 hash_builder_.GetSection()->sh_link = hash_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700838
David Srbecky527c9c72015-04-17 21:14:10 +0100839 // Get the layout of the extra sections with SHF_ALLOC flag.
840 // This will deal with .eh_frame and .eh_frame_hdr.
841 // .eh_frame contains relative pointers to .text which we
842 // want to fixup between the calls to Init() and Write().
843 // Therefore we handle those sections here as opposed to Write().
844 // It also has the nice side effect of including .eh_frame
845 // with the rest of LOAD_R segment. It must come before .rodata
846 // because .rodata and .text must be next to each other.
847 Elf_Shdr* prev = hash_builder_.GetSection();
848 for (auto* it : other_builders_) {
849 if ((it->GetSection()->sh_flags & SHF_ALLOC) != 0) {
850 it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
851 it->GetSection()->sh_addr = it->GetSection()->sh_offset;
852 it->GetSection()->sh_size = it->GetBuffer()->size();
853 it->GetSection()->sh_link = it->GetLink();
854 prev = it->GetSection();
855 }
856 }
857 // If the sections exist, check that they have been handled.
858 const auto* eh_frame = FindRawSection(".eh_frame");
859 if (eh_frame != nullptr) {
860 DCHECK_NE(eh_frame->GetSection()->sh_offset, 0u);
861 }
862 const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr");
863 if (eh_frame_hdr != nullptr) {
864 DCHECK_NE(eh_frame_hdr->GetSection()->sh_offset, 0u);
865 }
866
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700867 // Get the layout of the rodata section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700868 rodata_builder_.GetSection()->sh_offset =
David Srbecky527c9c72015-04-17 21:14:10 +0100869 NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(), *prev);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700870 rodata_builder_.GetSection()->sh_addr = rodata_builder_.GetSection()->sh_offset;
871 rodata_builder_.GetSection()->sh_size = rodata_builder_.GetSize();
872 rodata_builder_.GetSection()->sh_link = rodata_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700873
874 // Get the layout of the text section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700875 text_builder_.GetSection()->sh_offset =
876 NextOffset<Elf_Word, Elf_Shdr>(*text_builder_.GetSection(),
877 *rodata_builder_.GetSection());
878 text_builder_.GetSection()->sh_addr = text_builder_.GetSection()->sh_offset;
879 text_builder_.GetSection()->sh_size = text_builder_.GetSize();
880 text_builder_.GetSection()->sh_link = text_builder_.GetLink();
881 CHECK_ALIGNED(rodata_builder_.GetSection()->sh_offset +
882 rodata_builder_.GetSection()->sh_size, kPageSize);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700883
Vladimir Marko5c42c292015-02-25 12:02:49 +0000884 // Get the layout of the .bss section.
885 bss_builder_.GetSection()->sh_offset =
886 NextOffset<Elf_Word, Elf_Shdr>(*bss_builder_.GetSection(),
887 *text_builder_.GetSection());
888 bss_builder_.GetSection()->sh_addr = bss_builder_.GetSection()->sh_offset;
889 bss_builder_.GetSection()->sh_size = bss_builder_.GetSize();
890 bss_builder_.GetSection()->sh_link = bss_builder_.GetLink();
891
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700892 // Get the layout of the dynamic section.
Vladimir Marko5c42c292015-02-25 12:02:49 +0000893 CHECK(IsAlignedParam(bss_builder_.GetSection()->sh_offset,
894 dynamic_builder_.GetSection()->sh_addralign));
895 dynamic_builder_.GetSection()->sh_offset = bss_builder_.GetSection()->sh_offset;
896 dynamic_builder_.GetSection()->sh_addr =
897 NextOffset<Elf_Word, Elf_Shdr>(*dynamic_builder_.GetSection(), *bss_builder_.GetSection());
Ian Rogers0279ebb2014-10-08 17:27:48 -0700898 dynamic_builder_.GetSection()->sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
899 dynamic_builder_.GetSection()->sh_link = dynamic_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700900
901 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700902 LOG(INFO) << "dynsym off=" << dynsym_builder_.GetSection()->sh_offset
903 << " dynsym size=" << dynsym_builder_.GetSection()->sh_size;
904 LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->GetSection()->sh_offset
905 << " dynstr size=" << dynsym_builder_.GetStrTab()->GetSection()->sh_size;
906 LOG(INFO) << "hash off=" << hash_builder_.GetSection()->sh_offset
907 << " hash size=" << hash_builder_.GetSection()->sh_size;
908 LOG(INFO) << "rodata off=" << rodata_builder_.GetSection()->sh_offset
909 << " rodata size=" << rodata_builder_.GetSection()->sh_size;
910 LOG(INFO) << "text off=" << text_builder_.GetSection()->sh_offset
911 << " text size=" << text_builder_.GetSection()->sh_size;
912 LOG(INFO) << "dynamic off=" << dynamic_builder_.GetSection()->sh_offset
913 << " dynamic size=" << dynamic_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700914 }
915
916 return true;
917 }
918
919 bool Write() {
Andreas Gampecc676072014-09-23 22:58:07 -0700920 std::vector<ElfFilePiece<Elf_Word>*> pieces;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700921 Elf_Shdr* prev = dynamic_builder_.GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700922 std::string strtab;
923
924 if (IncludingDebugSymbols()) {
925 // Setup .symtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700926 section_ptrs_.push_back(symtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700927 AssignSectionStr(&symtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700928 symtab_builder_.SetSectionIndex(section_index_);
929 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700930
931 // Setup .strtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700932 section_ptrs_.push_back(symtab_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700933 AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700934 symtab_builder_.GetStrTab()->SetSectionIndex(section_index_);
935 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700936
937 strtab = symtab_builder_.GenerateStrtab();
938 if (debug_logging_) {
939 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
940 << std::hex << " " << strtab.size();
941 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
942 << std::hex << " " << symtab_builder_.GetSize();
943 }
944 }
945
946 // Setup all the other sections.
David Srbecky527c9c72015-04-17 21:14:10 +0100947 for (auto* builder : other_builders_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700948 section_ptrs_.push_back(builder->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700949 AssignSectionStr(builder, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700950 builder->SetSectionIndex(section_index_);
951 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700952 }
953
954 // Setup shstrtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700955 section_ptrs_.push_back(shstrtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700956 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700957 shstrtab_builder_.SetSectionIndex(section_index_);
958 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700959
960 if (debug_logging_) {
961 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
962 << std::hex << " " << shstrtab_.size();
963 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
964 << std::hex << " " << section_ptrs_.size();
965 }
966
967 if (IncludingDebugSymbols()) {
968 // Get the layout of the symtab section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700969 symtab_builder_.GetSection()->sh_offset =
970 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetSection(),
971 *dynamic_builder_.GetSection());
972 symtab_builder_.GetSection()->sh_addr = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700973 // Add to leave space for the null symbol.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700974 symtab_builder_.GetSection()->sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
975 symtab_builder_.GetSection()->sh_link = symtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700976
977 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700978 symtab_builder_.GetStrTab()->GetSection()->sh_offset =
979 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetStrTab()->GetSection(),
980 *symtab_builder_.GetSection());
981 symtab_builder_.GetStrTab()->GetSection()->sh_addr = 0;
982 symtab_builder_.GetStrTab()->GetSection()->sh_size = strtab.size();
983 symtab_builder_.GetStrTab()->GetSection()->sh_link = symtab_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700984
Ian Rogers0279ebb2014-10-08 17:27:48 -0700985 prev = symtab_builder_.GetStrTab()->GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700986 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700987 LOG(INFO) << "symtab off=" << symtab_builder_.GetSection()->sh_offset
988 << " symtab size=" << symtab_builder_.GetSection()->sh_size;
989 LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->GetSection()->sh_offset
990 << " strtab size=" << symtab_builder_.GetStrTab()->GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700991 }
992 }
993
David Srbecky527c9c72015-04-17 21:14:10 +0100994 // Get the layout of the extra sections without SHF_ALLOC flag.
995 // (This will deal with the debug sections if they are there)
996 for (auto* it : other_builders_) {
997 if ((it->GetSection()->sh_flags & SHF_ALLOC) == 0) {
998 it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
999 it->GetSection()->sh_addr = 0;
1000 it->GetSection()->sh_size = it->GetBuffer()->size();
1001 it->GetSection()->sh_link = it->GetLink();
Andreas Gampecc676072014-09-23 22:58:07 -07001002
David Srbecky527c9c72015-04-17 21:14:10 +01001003 // We postpone adding an ElfFilePiece to keep the order in "pieces."
Andreas Gampecc676072014-09-23 22:58:07 -07001004
David Srbecky527c9c72015-04-17 21:14:10 +01001005 prev = it->GetSection();
1006 if (debug_logging_) {
1007 LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset
1008 << " size=" << it->GetSection()->sh_size;
1009 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001010 }
1011 }
1012
1013 // Get the layout of the shstrtab section
Ian Rogers0279ebb2014-10-08 17:27:48 -07001014 shstrtab_builder_.GetSection()->sh_offset =
1015 NextOffset<Elf_Word, Elf_Shdr>(*shstrtab_builder_.GetSection(), *prev);
1016 shstrtab_builder_.GetSection()->sh_addr = 0;
1017 shstrtab_builder_.GetSection()->sh_size = shstrtab_.size();
1018 shstrtab_builder_.GetSection()->sh_link = shstrtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001019 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001020 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.GetSection()->sh_offset
1021 << " shstrtab size=" << shstrtab_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001022 }
1023
1024 // The section list comes after come after.
1025 Elf_Word sections_offset = RoundUp(
Ian Rogers0279ebb2014-10-08 17:27:48 -07001026 shstrtab_builder_.GetSection()->sh_offset + shstrtab_builder_.GetSection()->sh_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001027 sizeof(Elf_Word));
1028
1029 // Setup the actual symbol arrays.
1030 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001031 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001032 std::vector<Elf_Sym> symtab;
1033 if (IncludingDebugSymbols()) {
1034 symtab = symtab_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001035 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001036 }
1037
1038 // Setup the dynamic section.
1039 // This will add the 2 values we cannot know until now time, namely the size
1040 // and the soname_offset.
1041 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
1042 dynstr_soname_offset_);
Ian Rogers0279ebb2014-10-08 17:27:48 -07001043 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001044
1045 // Finish setup of the program headers now that we know the layout of the
1046 // whole file.
Ian Rogers0279ebb2014-10-08 17:27:48 -07001047 Elf_Word load_r_size =
1048 rodata_builder_.GetSection()->sh_offset + rodata_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001049 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
1050 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001051 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001052
Ian Rogers0279ebb2014-10-08 17:27:48 -07001053 Elf_Word load_rx_size = text_builder_.GetSection()->sh_size;
1054 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.GetSection()->sh_offset;
1055 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.GetSection()->sh_offset;
1056 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.GetSection()->sh_offset;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001057 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
1058 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001059 program_headers_[PH_LOAD_R_X].p_align = text_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001060
Vladimir Marko5c42c292015-02-25 12:02:49 +00001061 program_headers_[PH_LOAD_RW_BSS].p_offset = bss_builder_.GetSection()->sh_offset;
1062 program_headers_[PH_LOAD_RW_BSS].p_vaddr = bss_builder_.GetSection()->sh_offset;
1063 program_headers_[PH_LOAD_RW_BSS].p_paddr = bss_builder_.GetSection()->sh_offset;
1064 program_headers_[PH_LOAD_RW_BSS].p_filesz = 0;
1065 program_headers_[PH_LOAD_RW_BSS].p_memsz = bss_builder_.GetSection()->sh_size;
1066 program_headers_[PH_LOAD_RW_BSS].p_align = bss_builder_.GetSection()->sh_addralign;
1067
1068 program_headers_[PH_LOAD_RW_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
1069 program_headers_[PH_LOAD_RW_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_addr;
1070 program_headers_[PH_LOAD_RW_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_addr;
1071 program_headers_[PH_LOAD_RW_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1072 program_headers_[PH_LOAD_RW_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1073 program_headers_[PH_LOAD_RW_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001074
Ian Rogers0279ebb2014-10-08 17:27:48 -07001075 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001076 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_addr;
1077 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_addr;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001078 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1079 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1080 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001081
David Srbecky527c9c72015-04-17 21:14:10 +01001082 const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr");
1083 if (eh_frame_hdr != nullptr) {
1084 const auto* eh_frame = FindRawSection(".eh_frame");
1085 // Check layout:
1086 // 1) eh_frame is before eh_frame_hdr.
1087 // 2) There's no gap.
1088 CHECK(eh_frame != nullptr);
1089 CHECK_LE(eh_frame->GetSection()->sh_offset, eh_frame_hdr->GetSection()->sh_offset);
1090 CHECK_EQ(eh_frame->GetSection()->sh_offset + eh_frame->GetSection()->sh_size,
1091 eh_frame_hdr->GetSection()->sh_offset);
1092
1093 program_headers_[PH_EH_FRAME_HDR].p_type = PT_GNU_EH_FRAME;
1094 program_headers_[PH_EH_FRAME_HDR].p_offset = eh_frame_hdr->GetSection()->sh_offset;
1095 program_headers_[PH_EH_FRAME_HDR].p_vaddr = eh_frame_hdr->GetSection()->sh_addr;
1096 program_headers_[PH_EH_FRAME_HDR].p_paddr = eh_frame_hdr->GetSection()->sh_addr;
1097 program_headers_[PH_EH_FRAME_HDR].p_filesz = eh_frame_hdr->GetSection()->sh_size;
1098 program_headers_[PH_EH_FRAME_HDR].p_memsz = eh_frame_hdr->GetSection()->sh_size;
1099 program_headers_[PH_EH_FRAME_HDR].p_align = eh_frame_hdr->GetSection()->sh_addralign;
1100 }
1101
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001102 // Finish setup of the Ehdr values.
1103 elf_header_.e_phoff = PHDR_OFFSET;
1104 elf_header_.e_shoff = sections_offset;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001105 elf_header_.e_phnum = (bss_builder_.GetSection()->sh_size != 0u) ? PH_NUM : PH_NUM - 1;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001106 elf_header_.e_shnum = section_ptrs_.size();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001107 elf_header_.e_shstrndx = shstrtab_builder_.GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001108
1109 // Add the rest of the pieces to the list.
Andreas Gampecc676072014-09-23 22:58:07 -07001110 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_,
1111 sizeof(elf_header_)));
Vladimir Marko5c42c292015-02-25 12:02:49 +00001112 if (bss_builder_.GetSection()->sh_size != 0u) {
1113 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1114 &program_headers_[0],
1115 elf_header_.e_phnum * sizeof(Elf_Phdr)));
1116 } else {
1117 // Skip PH_LOAD_RW_BSS.
1118 Elf_Word part1_size = PH_LOAD_RW_BSS * sizeof(Elf_Phdr);
1119 Elf_Word part2_size = (PH_NUM - PH_LOAD_RW_BSS - 1) * sizeof(Elf_Phdr);
1120 CHECK_EQ(part1_size + part2_size, elf_header_.e_phnum * sizeof(Elf_Phdr));
1121 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1122 &program_headers_[0], part1_size));
1123 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers part 2",
1124 PHDR_OFFSET + part1_size,
1125 &program_headers_[PH_LOAD_RW_BSS + 1],
1126 part2_size));
1127 }
Andreas Gampecc676072014-09-23 22:58:07 -07001128 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001129 dynamic_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001130 dynamic.data(),
Ian Rogers0279ebb2014-10-08 17:27:48 -07001131 dynamic_builder_.GetSection()->sh_size));
1132 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001133 dynsym.data(),
1134 dynsym.size() * sizeof(Elf_Sym)));
1135 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001136 dynsym_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001137 dynstr_.c_str(), dynstr_.size()));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001138 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001139 hash_.data(),
1140 hash_.size() * sizeof(Elf_Word)));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001141 pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001142 oat_writer_));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001143 pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001144 oat_writer_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001145 if (IncludingDebugSymbols()) {
Andreas Gampecc676072014-09-23 22:58:07 -07001146 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001147 symtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001148 symtab.data(),
1149 symtab.size() * sizeof(Elf_Sym)));
1150 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001151 symtab_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001152 strtab.c_str(), strtab.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001153 }
Andreas Gampecc676072014-09-23 22:58:07 -07001154 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001155 shstrtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001156 &shstrtab_[0], shstrtab_.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001157 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
1158 // Just add all the sections in induvidually since they are all over the
1159 // place on the heap/stack.
1160 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
Andreas Gampecc676072014-09-23 22:58:07 -07001161 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off,
1162 section_ptrs_[i], sizeof(Elf_Shdr)));
1163 }
1164
1165 // Postponed debug info.
David Srbecky527c9c72015-04-17 21:14:10 +01001166 for (auto* it : other_builders_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001167 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->GetName(), it->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001168 it->GetBuffer()->data(),
1169 it->GetBuffer()->size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001170 }
1171
1172 if (!WriteOutFile(pieces)) {
1173 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
Andreas Gampecc676072014-09-23 22:58:07 -07001174
1175 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001176 return false;
1177 }
1178
Andreas Gampecc676072014-09-23 22:58:07 -07001179 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001180 return true;
1181 }
1182
David Srbecky527c9c72015-04-17 21:14:10 +01001183 // Adds the given raw section to the builder. It does not take ownership.
1184 void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* bld) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001185 other_builders_.push_back(bld);
1186 }
1187
David Srbecky527c9c72015-04-17 21:14:10 +01001188 const ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>*
1189 FindRawSection(const char* name) {
1190 for (const auto* other_builder : other_builders_) {
1191 if (other_builder->GetName() == name) {
1192 return other_builder;
1193 }
1194 }
1195 return nullptr;
1196 }
1197
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001198 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001199 void SetISA(InstructionSet isa) {
1200 switch (isa) {
1201 case kArm:
1202 // Fall through.
1203 case kThumb2: {
1204 elf_header_.e_machine = EM_ARM;
1205 elf_header_.e_flags = EF_ARM_EABI_VER5;
1206 break;
1207 }
1208 case kArm64: {
1209 elf_header_.e_machine = EM_AARCH64;
1210 elf_header_.e_flags = 0;
1211 break;
1212 }
1213 case kX86: {
1214 elf_header_.e_machine = EM_386;
1215 elf_header_.e_flags = 0;
1216 break;
1217 }
1218 case kX86_64: {
1219 elf_header_.e_machine = EM_X86_64;
1220 elf_header_.e_flags = 0;
1221 break;
1222 }
1223 case kMips: {
1224 elf_header_.e_machine = EM_MIPS;
1225 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1226 EF_MIPS_PIC |
1227 EF_MIPS_CPIC |
1228 EF_MIPS_ABI_O32 |
1229 EF_MIPS_ARCH_32R2);
1230 break;
1231 }
Andreas Gampe57b34292015-01-14 15:45:59 -08001232 case kMips64: {
1233 elf_header_.e_machine = EM_MIPS;
1234 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1235 EF_MIPS_PIC |
1236 EF_MIPS_CPIC |
1237 EF_MIPS_ARCH_64R6);
1238 break;
1239 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001240 default: {
1241 fatal_error_ = true;
1242 LOG(FATAL) << "Unknown instruction set: " << isa;
1243 break;
1244 }
1245 }
1246 }
1247
1248 void SetupEhdr() {
1249 memset(&elf_header_, 0, sizeof(elf_header_));
1250 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
1251 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
1252 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
1253 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
Tong Shen62d1ca32014-09-03 17:24:56 -07001254 elf_header_.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
1255 ? ELFCLASS32 : ELFCLASS64;;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001256 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
1257 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
1258 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
1259 elf_header_.e_ident[EI_ABIVERSION] = 0;
1260 elf_header_.e_type = ET_DYN;
1261 elf_header_.e_version = 1;
1262 elf_header_.e_entry = 0;
1263 elf_header_.e_ehsize = sizeof(Elf_Ehdr);
1264 elf_header_.e_phentsize = sizeof(Elf_Phdr);
1265 elf_header_.e_shentsize = sizeof(Elf_Shdr);
1266 elf_header_.e_phoff = sizeof(Elf_Ehdr);
1267 }
1268
1269 // Sets up a bunch of the required Dynamic Section entries.
1270 // Namely it will initialize all the mandatory ones that it can.
1271 // Specifically:
1272 // DT_HASH
1273 // DT_STRTAB
1274 // DT_SYMTAB
1275 // DT_SYMENT
1276 //
1277 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
1278 void SetupDynamic() {
1279 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
1280 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1281 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1282 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1283 }
1284
1285 // Sets up the basic dynamic symbols that are needed, namely all those we
1286 // can know already.
1287 //
1288 // Specifically adds:
1289 // oatdata
1290 // oatexec
1291 // oatlastword
1292 void SetupRequiredSymbols() {
1293 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1294 rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1295 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1296 text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1297 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1298 true, 4, STB_GLOBAL, STT_OBJECT);
Vladimir Marko5c42c292015-02-25 12:02:49 +00001299 if (bss_builder_.GetSize() != 0u) {
1300 dynsym_builder_.AddSymbol("oatbss", &bss_builder_, 0, true,
1301 bss_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1302 dynsym_builder_.AddSymbol("oatbsslastword", &bss_builder_, bss_builder_.GetSize() - 4,
1303 true, 4, STB_GLOBAL, STT_OBJECT);
1304 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001305 }
1306
Ian Rogers0279ebb2014-10-08 17:27:48 -07001307 void AssignSectionStr(ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* builder,
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001308 std::string* strtab) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001309 builder->GetSection()->sh_name = strtab->size();
1310 *strtab += builder->GetName();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001311 *strtab += '\0';
1312 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001313 LOG(INFO) << "adding section name \"" << builder->GetName() << "\" "
1314 << "to shstrtab at offset " << builder->GetSection()->sh_name;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001315 }
1316 }
1317
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001318
1319 // Write each of the pieces out to the file.
Andreas Gampecc676072014-09-23 22:58:07 -07001320 bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001321 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
Andreas Gampecc676072014-09-23 22:58:07 -07001322 if (!(*it)->Write(elf_file_)) {
1323 return false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001324 }
1325 }
1326 return true;
1327 }
1328
Ian Rogers0279ebb2014-10-08 17:27:48 -07001329 bool IncludingDebugSymbols() const {
1330 return add_symbols_ && symtab_builder_.GetSize() > 1;
1331 }
1332
1333 CodeOutput* const oat_writer_;
1334 File* const elf_file_;
1335 const bool add_symbols_;
1336 const bool debug_logging_;
1337
1338 bool fatal_error_ = false;
1339
1340 // What phdr is.
1341 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
1342 enum : uint8_t {
Vladimir Marko5c42c292015-02-25 12:02:49 +00001343 PH_PHDR = 0,
1344 PH_LOAD_R__ = 1,
1345 PH_LOAD_R_X = 2,
1346 PH_LOAD_RW_BSS = 3,
1347 PH_LOAD_RW_DYNAMIC = 4,
1348 PH_DYNAMIC = 5,
David Srbecky527c9c72015-04-17 21:14:10 +01001349 PH_EH_FRAME_HDR = 6,
1350 PH_NUM = 7,
Ian Rogers0279ebb2014-10-08 17:27:48 -07001351 };
1352 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
1353 Elf_Phdr program_headers_[PH_NUM];
1354
1355 Elf_Ehdr elf_header_;
1356
1357 Elf_Shdr null_hdr_;
1358 std::string shstrtab_;
1359 // The index of the current section being built. The first being 1.
1360 uint32_t section_index_;
1361 std::string dynstr_;
1362 uint32_t dynstr_soname_offset_;
1363 std::vector<const Elf_Shdr*> section_ptrs_;
1364 std::vector<Elf_Word> hash_;
1365
1366 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> text_builder_;
1367 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> rodata_builder_;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001368 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bss_builder_;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001369 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> dynsym_builder_;
1370 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> symtab_builder_;
1371 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> hash_builder_;
1372 ElfDynamicBuilder<Elf_Word, Elf_Sword, Elf_Dyn, Elf_Shdr> dynamic_builder_;
1373 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> shstrtab_builder_;
David Srbecky527c9c72015-04-17 21:14:10 +01001374 std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>*> other_builders_;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001375
1376 DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001377};
1378
1379} // namespace art
1380
1381#endif // ART_COMPILER_ELF_BUILDER_H_