blob: 32c8cce031f5749538e863341d2ea7026980d5ab [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
David Srbecky533c2072015-04-22 12:20:22 +010029template <typename ElfTypes>
Ian Rogers0279ebb2014-10-08 17:27:48 -070030class ElfSectionBuilder : public ValueObject {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070031 public:
David Srbecky533c2072015-04-22 12:20:22 +010032 using Elf_Word = typename ElfTypes::Word;
33 using Elf_Shdr = typename ElfTypes::Shdr;
34
Andreas Gampe54fc26c2014-09-04 21:47:42 -070035 ElfSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
David Srbecky533c2072015-04-22 12:20:22 +010036 const ElfSectionBuilder<ElfTypes> *link, Elf_Word info,
Ian Rogers0279ebb2014-10-08 17:27:48 -070037 Elf_Word align, Elf_Word entsize)
38 : section_index_(0), name_(sec_name), link_(link) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070039 memset(&section_, 0, sizeof(section_));
40 section_.sh_type = type;
41 section_.sh_flags = flags;
42 section_.sh_info = info;
43 section_.sh_addralign = align;
44 section_.sh_entsize = entsize;
45 }
Andreas Gampe758a8012015-04-03 21:28:42 -070046 ElfSectionBuilder(const ElfSectionBuilder&) = default;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070047
Ian Rogers0279ebb2014-10-08 17:27:48 -070048 ~ElfSectionBuilder() {}
Andreas Gampe54fc26c2014-09-04 21:47:42 -070049
Ian Rogers0279ebb2014-10-08 17:27:48 -070050 Elf_Word GetLink() const {
51 return (link_ != nullptr) ? link_->section_index_ : 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070052 }
53
Ian Rogers0279ebb2014-10-08 17:27:48 -070054 const Elf_Shdr* GetSection() const {
55 return &section_;
56 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -070057
Ian Rogers0279ebb2014-10-08 17:27:48 -070058 Elf_Shdr* GetSection() {
59 return &section_;
60 }
61
62 Elf_Word GetSectionIndex() const {
63 return section_index_;
64 }
65
66 void SetSectionIndex(Elf_Word section_index) {
67 section_index_ = section_index;
68 }
69
70 const std::string& GetName() const {
71 return name_;
72 }
73
74 private:
75 Elf_Shdr section_;
76 Elf_Word section_index_;
77 const std::string name_;
78 const ElfSectionBuilder* const link_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070079};
80
David Srbecky533c2072015-04-22 12:20:22 +010081template <typename ElfTypes>
82class ElfDynamicBuilder FINAL : public ElfSectionBuilder<ElfTypes> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070083 public:
David Srbecky533c2072015-04-22 12:20:22 +010084 using Elf_Word = typename ElfTypes::Word;
85 using Elf_Sword = typename ElfTypes::Sword;
86 using Elf_Shdr = typename ElfTypes::Shdr;
87 using Elf_Dyn = typename ElfTypes::Dyn;
88
Andreas Gampe54fc26c2014-09-04 21:47:42 -070089 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un) {
90 if (tag == DT_NULL) {
91 return;
92 }
93 dynamics_.push_back({nullptr, tag, d_un});
94 }
95
96 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un,
David Srbecky533c2072015-04-22 12:20:22 +010097 const ElfSectionBuilder<ElfTypes>* section) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070098 if (tag == DT_NULL) {
99 return;
100 }
101 dynamics_.push_back({section, tag, d_un});
102 }
103
104 ElfDynamicBuilder(const std::string& sec_name,
David Srbecky533c2072015-04-22 12:20:22 +0100105 ElfSectionBuilder<ElfTypes> *link)
106 : ElfSectionBuilder<ElfTypes>(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC,
107 link, 0, kPageSize, sizeof(Elf_Dyn)) {}
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700108 ~ElfDynamicBuilder() {}
109
Ian Rogers0279ebb2014-10-08 17:27:48 -0700110 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700111 // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
112 // these must be added when we actually put the file together because
113 // their values are very dependent on state.
114 return dynamics_.size() + 3;
115 }
116
117 // Create the actual dynamic vector. strsz should be the size of the .dynstr
118 // table and soname_off should be the offset of the soname in .dynstr.
119 // Since niether can be found prior to final layout we will wait until here
120 // to add them.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700121 std::vector<Elf_Dyn> GetDynamics(Elf_Word strsz, Elf_Word soname) const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700122 std::vector<Elf_Dyn> ret;
123 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700124 if (it->section_ != nullptr) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700125 // We are adding an address relative to a section.
126 ret.push_back(
Ian Rogers0279ebb2014-10-08 17:27:48 -0700127 {it->tag_, {it->off_ + it->section_->GetSection()->sh_addr}});
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700128 } else {
129 ret.push_back({it->tag_, {it->off_}});
130 }
131 }
132 ret.push_back({DT_STRSZ, {strsz}});
133 ret.push_back({DT_SONAME, {soname}});
134 ret.push_back({DT_NULL, {0}});
135 return ret;
136 }
137
Ian Rogers0279ebb2014-10-08 17:27:48 -0700138 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700139 struct ElfDynamicState {
David Srbecky533c2072015-04-22 12:20:22 +0100140 const ElfSectionBuilder<ElfTypes>* section_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700141 Elf_Sword tag_;
142 Elf_Word off_;
143 };
144 std::vector<ElfDynamicState> dynamics_;
145};
146
David Srbecky533c2072015-04-22 12:20:22 +0100147template <typename ElfTypes>
148class ElfRawSectionBuilder FINAL : public ElfSectionBuilder<ElfTypes> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700149 public:
David Srbecky533c2072015-04-22 12:20:22 +0100150 using Elf_Word = typename ElfTypes::Word;
151
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700152 ElfRawSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
David Srbecky533c2072015-04-22 12:20:22 +0100153 const ElfSectionBuilder<ElfTypes>* link, Elf_Word info,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700154 Elf_Word align, Elf_Word entsize)
David Srbecky533c2072015-04-22 12:20:22 +0100155 : ElfSectionBuilder<ElfTypes>(sec_name, type, flags, link, info, align, entsize) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700156 }
Andreas Gampe758a8012015-04-03 21:28:42 -0700157 ElfRawSectionBuilder(const ElfRawSectionBuilder&) = default;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700158
Ian Rogers0279ebb2014-10-08 17:27:48 -0700159 ~ElfRawSectionBuilder() {}
160
161 std::vector<uint8_t>* GetBuffer() {
162 return &buf_;
163 }
164
165 void SetBuffer(const std::vector<uint8_t>& buf) {
166 buf_ = buf;
167 }
168
169 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700170 std::vector<uint8_t> buf_;
171};
172
David Srbecky533c2072015-04-22 12:20:22 +0100173template <typename ElfTypes>
174class ElfOatSectionBuilder FINAL : public ElfSectionBuilder<ElfTypes> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700175 public:
David Srbecky533c2072015-04-22 12:20:22 +0100176 using Elf_Word = typename ElfTypes::Word;
177
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700178 ElfOatSectionBuilder(const std::string& sec_name, Elf_Word size, Elf_Word offset,
179 Elf_Word type, Elf_Word flags)
David Srbecky533c2072015-04-22 12:20:22 +0100180 : ElfSectionBuilder<ElfTypes>(sec_name, type, flags, nullptr, 0, kPageSize, 0),
Ian Rogers0279ebb2014-10-08 17:27:48 -0700181 offset_(offset), size_(size) {
182 }
183
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700184 ~ElfOatSectionBuilder() {}
185
Ian Rogers0279ebb2014-10-08 17:27:48 -0700186 Elf_Word GetOffset() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700187 return offset_;
188 }
189
Ian Rogers0279ebb2014-10-08 17:27:48 -0700190 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700191 return size_;
192 }
193
Ian Rogers0279ebb2014-10-08 17:27:48 -0700194 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700195 // Offset of the content within the file.
196 Elf_Word offset_;
197 // Size of the content within the file.
198 Elf_Word size_;
199};
200
201static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
202 return ((binding) << 4) + ((type) & 0xf);
203}
204
205// from bionic
206static inline unsigned elfhash(const char *_name) {
207 const unsigned char *name = (const unsigned char *) _name;
208 unsigned h = 0, g;
209
210 while (*name) {
211 h = (h << 4) + *name++;
212 g = h & 0xf0000000;
213 h ^= g;
214 h ^= g >> 24;
215 }
216 return h;
217}
218
David Srbecky533c2072015-04-22 12:20:22 +0100219template <typename ElfTypes>
220class ElfSymtabBuilder FINAL : public ElfSectionBuilder<ElfTypes> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700221 public:
David Srbecky533c2072015-04-22 12:20:22 +0100222 using Elf_Addr = typename ElfTypes::Addr;
223 using Elf_Word = typename ElfTypes::Word;
224 using Elf_Sym = typename ElfTypes::Sym;
225
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700226 // Add a symbol with given name to this symtab. The symbol refers to
227 // 'relative_addr' within the given section and has the given attributes.
228 void AddSymbol(const std::string& name,
David Srbecky533c2072015-04-22 12:20:22 +0100229 const ElfSectionBuilder<ElfTypes>* section,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700230 Elf_Addr addr,
231 bool is_relative,
232 Elf_Word size,
233 uint8_t binding,
234 uint8_t type,
235 uint8_t other = 0) {
236 CHECK(section);
237 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
238 MakeStInfo(binding, type), other, 0};
239 symbols_.push_back(state);
240 }
241
242 ElfSymtabBuilder(const std::string& sec_name, Elf_Word type,
243 const std::string& str_name, Elf_Word str_type, bool alloc)
David Srbecky533c2072015-04-22 12:20:22 +0100244 : ElfSectionBuilder<ElfTypes>(sec_name, type, ((alloc) ? SHF_ALLOC : 0U),
245 &strtab_, 0, sizeof(Elf_Word),
246 sizeof(Elf_Sym)), str_name_(str_name),
247 str_type_(str_type),
248 strtab_(str_name,
249 str_type,
250 ((alloc) ? SHF_ALLOC : 0U),
251 nullptr, 0, 1, 1) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700252 }
253
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700254 ~ElfSymtabBuilder() {}
255
Ian Rogers0279ebb2014-10-08 17:27:48 -0700256 std::vector<Elf_Word> GenerateHashContents() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700257 // Here is how The ELF hash table works.
258 // There are 3 arrays to worry about.
259 // * The symbol table where the symbol information is.
260 // * The bucket array which is an array of indexes into the symtab and chain.
261 // * The chain array which is also an array of indexes into the symtab and chain.
262 //
263 // Lets say the state is something like this.
264 // +--------+ +--------+ +-----------+
265 // | symtab | | bucket | | chain |
266 // | null | | 1 | | STN_UNDEF |
267 // | <sym1> | | 4 | | 2 |
268 // | <sym2> | | | | 5 |
269 // | <sym3> | | | | STN_UNDEF |
270 // | <sym4> | | | | 3 |
271 // | <sym5> | | | | STN_UNDEF |
272 // +--------+ +--------+ +-----------+
273 //
274 // The lookup process (in python psudocode) is
275 //
276 // def GetSym(name):
277 // # NB STN_UNDEF == 0
278 // indx = bucket[elfhash(name) % num_buckets]
279 // while indx != STN_UNDEF:
280 // if GetSymbolName(symtab[indx]) == name:
281 // return symtab[indx]
282 // indx = chain[indx]
283 // return SYMBOL_NOT_FOUND
284 //
285 // Between bucket and chain arrays every symtab index must be present exactly
286 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
287
288 // Select number of buckets.
289 // This is essentially arbitrary.
290 Elf_Word nbuckets;
291 Elf_Word chain_size = GetSize();
292 if (symbols_.size() < 8) {
293 nbuckets = 2;
294 } else if (symbols_.size() < 32) {
295 nbuckets = 4;
296 } else if (symbols_.size() < 256) {
297 nbuckets = 16;
298 } else {
299 // Have about 32 ids per bucket.
300 nbuckets = RoundUp(symbols_.size()/32, 2);
301 }
302 std::vector<Elf_Word> hash;
303 hash.push_back(nbuckets);
304 hash.push_back(chain_size);
305 uint32_t bucket_offset = hash.size();
306 uint32_t chain_offset = bucket_offset + nbuckets;
307 hash.resize(hash.size() + nbuckets + chain_size, 0);
308
309 Elf_Word* buckets = hash.data() + bucket_offset;
310 Elf_Word* chain = hash.data() + chain_offset;
311
312 // Set up the actual hash table.
313 for (Elf_Word i = 0; i < symbols_.size(); i++) {
314 // Add 1 since we need to have the null symbol that is not in the symbols
315 // list.
316 Elf_Word index = i + 1;
317 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
318 if (buckets[hash_val] == 0) {
319 buckets[hash_val] = index;
320 } else {
321 hash_val = buckets[hash_val];
322 CHECK_LT(hash_val, chain_size);
323 while (chain[hash_val] != 0) {
324 hash_val = chain[hash_val];
325 CHECK_LT(hash_val, chain_size);
326 }
327 chain[hash_val] = index;
328 // Check for loops. Works because if this is non-empty then there must be
329 // another cell which already contains the same symbol index as this one,
330 // which means some symbol has more then one name, which isn't allowed.
331 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
332 }
333 }
334
335 return hash;
336 }
337
338 std::string GenerateStrtab() {
339 std::string tab;
340 tab += '\0';
341 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
342 it->name_idx_ = tab.size();
343 tab += it->name_;
344 tab += '\0';
345 }
Ian Rogers0279ebb2014-10-08 17:27:48 -0700346 strtab_.GetSection()->sh_size = tab.size();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700347 return tab;
348 }
349
350 std::vector<Elf_Sym> GenerateSymtab() {
351 std::vector<Elf_Sym> ret;
352 Elf_Sym undef_sym;
353 memset(&undef_sym, 0, sizeof(undef_sym));
354 undef_sym.st_shndx = SHN_UNDEF;
355 ret.push_back(undef_sym);
356
357 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
358 Elf_Sym sym;
359 memset(&sym, 0, sizeof(sym));
360 sym.st_name = it->name_idx_;
361 if (it->is_relative_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700362 sym.st_value = it->addr_ + it->section_->GetSection()->sh_offset;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700363 } else {
364 sym.st_value = it->addr_;
365 }
366 sym.st_size = it->size_;
367 sym.st_other = it->other_;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700368 sym.st_shndx = it->section_->GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700369 sym.st_info = it->info_;
370
371 ret.push_back(sym);
372 }
373 return ret;
374 }
375
Ian Rogers0279ebb2014-10-08 17:27:48 -0700376 Elf_Word GetSize() const {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700377 // 1 is for the implicit null symbol.
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700378 return symbols_.size() + 1;
379 }
380
David Srbecky533c2072015-04-22 12:20:22 +0100381 ElfSectionBuilder<ElfTypes>* GetStrTab() {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700382 return &strtab_;
383 }
384
Ian Rogers0279ebb2014-10-08 17:27:48 -0700385 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700386 struct ElfSymbolState {
387 const std::string name_;
David Srbecky533c2072015-04-22 12:20:22 +0100388 const ElfSectionBuilder<ElfTypes>* section_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700389 Elf_Addr addr_;
390 Elf_Word size_;
391 bool is_relative_;
392 uint8_t info_;
393 uint8_t other_;
394 // Used during Write() to temporarially hold name index in the strtab.
395 Elf_Word name_idx_;
396 };
397
398 // Information for the strsym for dynstr sections.
399 const std::string str_name_;
400 Elf_Word str_type_;
401 // The symbols in the same order they will be in the symbol table.
402 std::vector<ElfSymbolState> symbols_;
David Srbecky533c2072015-04-22 12:20:22 +0100403 ElfSectionBuilder<ElfTypes> strtab_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700404};
405
Andreas Gampecc676072014-09-23 22:58:07 -0700406template <typename Elf_Word>
407class ElfFilePiece {
408 public:
409 virtual ~ElfFilePiece() {}
410
411 virtual bool Write(File* elf_file) {
412 if (static_cast<off_t>(offset_) != lseek(elf_file->Fd(), offset_, SEEK_SET)) {
413 PLOG(ERROR) << "Failed to seek to " << GetDescription() << " offset " << offset_ << " for "
414 << elf_file->GetPath();
415 return false;
416 }
417
418 return DoActualWrite(elf_file);
419 }
420
421 static bool Compare(ElfFilePiece* a, ElfFilePiece* b) {
422 return a->offset_ < b->offset_;
423 }
424
425 protected:
426 explicit ElfFilePiece(Elf_Word offset) : offset_(offset) {}
427
Ian Rogers0279ebb2014-10-08 17:27:48 -0700428 Elf_Word GetOffset() const {
429 return offset_;
430 }
431
432 virtual const char* GetDescription() const = 0;
Andreas Gampecc676072014-09-23 22:58:07 -0700433 virtual bool DoActualWrite(File* elf_file) = 0;
434
Ian Rogers0279ebb2014-10-08 17:27:48 -0700435 private:
436 const Elf_Word offset_;
437
438 DISALLOW_COPY_AND_ASSIGN(ElfFilePiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700439};
440
441template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700442class ElfFileMemoryPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700443 public:
444 ElfFileMemoryPiece(const std::string& name, Elf_Word offset, const void* data, Elf_Word size)
445 : ElfFilePiece<Elf_Word>(offset), dbg_name_(name), data_(data), size_(size) {}
446
Ian Rogers0279ebb2014-10-08 17:27:48 -0700447 protected:
Andreas Gampecc676072014-09-23 22:58:07 -0700448 bool DoActualWrite(File* elf_file) OVERRIDE {
449 DCHECK(data_ != nullptr || size_ == 0U) << dbg_name_ << " " << size_;
450
451 if (!elf_file->WriteFully(data_, size_)) {
452 PLOG(ERROR) << "Failed to write " << dbg_name_ << " for " << elf_file->GetPath();
453 return false;
454 }
455
456 return true;
457 }
458
Ian Rogers0279ebb2014-10-08 17:27:48 -0700459 const char* GetDescription() const OVERRIDE {
460 return dbg_name_.c_str();
Andreas Gampecc676072014-09-23 22:58:07 -0700461 }
462
463 private:
464 const std::string& dbg_name_;
465 const void *data_;
466 Elf_Word size_;
467};
468
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700469class CodeOutput {
470 public:
Vladimir Markof4da6752014-08-01 19:04:18 +0100471 virtual void SetCodeOffset(size_t offset) = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700472 virtual bool Write(OutputStream* out) = 0;
473 virtual ~CodeOutput() {}
474};
475
Andreas Gampecc676072014-09-23 22:58:07 -0700476template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700477class ElfFileRodataPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700478 public:
479 ElfFileRodataPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
480 output_(output) {}
481
Ian Rogers0279ebb2014-10-08 17:27:48 -0700482 protected:
Andreas Gampecc676072014-09-23 22:58:07 -0700483 bool DoActualWrite(File* elf_file) OVERRIDE {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700484 output_->SetCodeOffset(this->GetOffset());
Andreas Gampecc676072014-09-23 22:58:07 -0700485 std::unique_ptr<BufferedOutputStream> output_stream(
486 new BufferedOutputStream(new FileOutputStream(elf_file)));
487 if (!output_->Write(output_stream.get())) {
488 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file->GetPath();
489 return false;
490 }
491
492 return true;
493 }
494
Ian Rogers0279ebb2014-10-08 17:27:48 -0700495 const char* GetDescription() const OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700496 return ".rodata";
497 }
498
499 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700500 CodeOutput* const output_;
501
502 DISALLOW_COPY_AND_ASSIGN(ElfFileRodataPiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700503};
504
505template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700506class ElfFileOatTextPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700507 public:
508 ElfFileOatTextPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
509 output_(output) {}
510
Ian Rogers0279ebb2014-10-08 17:27:48 -0700511 protected:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700512 bool DoActualWrite(File* elf_file ATTRIBUTE_UNUSED) OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700513 // All data is written by the ElfFileRodataPiece right now, as the oat writer writes in one
514 // piece. This is for future flexibility.
515 UNUSED(output_);
516 return true;
517 }
518
Ian Rogers0279ebb2014-10-08 17:27:48 -0700519 const char* GetDescription() const OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700520 return ".text";
521 }
522
523 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700524 CodeOutput* const output_;
525
526 DISALLOW_COPY_AND_ASSIGN(ElfFileOatTextPiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700527};
528
529template <typename Elf_Word>
530static bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces, File* elf_file) {
531 // TODO It would be nice if this checked for overlap.
532 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
533 if (!(*it)->Write(elf_file)) {
534 return false;
535 }
536 }
537 return true;
538}
539
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700540template <typename Elf_Word, typename Elf_Shdr>
541static inline constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) {
542 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
543}
544
David Srbecky533c2072015-04-22 12:20:22 +0100545template <typename ElfTypes>
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700546class ElfBuilder FINAL {
547 public:
David Srbecky533c2072015-04-22 12:20:22 +0100548 using Elf_Addr = typename ElfTypes::Addr;
549 using Elf_Word = typename ElfTypes::Word;
550 using Elf_Sword = typename ElfTypes::Sword;
551 using Elf_Ehdr = typename ElfTypes::Ehdr;
552 using Elf_Shdr = typename ElfTypes::Shdr;
553 using Elf_Sym = typename ElfTypes::Sym;
554 using Elf_Phdr = typename ElfTypes::Phdr;
555 using Elf_Dyn = typename ElfTypes::Dyn;
556
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700557 ElfBuilder(CodeOutput* oat_writer,
558 File* elf_file,
559 InstructionSet isa,
560 Elf_Word rodata_relative_offset,
561 Elf_Word rodata_size,
562 Elf_Word text_relative_offset,
563 Elf_Word text_size,
Vladimir Marko5c42c292015-02-25 12:02:49 +0000564 Elf_Word bss_relative_offset,
565 Elf_Word bss_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700566 const bool add_symbols,
567 bool debug = false)
568 : oat_writer_(oat_writer),
569 elf_file_(elf_file),
570 add_symbols_(add_symbols),
571 debug_logging_(debug),
572 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
573 SHF_ALLOC | SHF_EXECINSTR),
574 rodata_builder_(".rodata", rodata_size, rodata_relative_offset, SHT_PROGBITS, SHF_ALLOC),
Vladimir Marko5c42c292015-02-25 12:02:49 +0000575 bss_builder_(".bss", bss_size, bss_relative_offset, SHT_NOBITS, SHF_ALLOC),
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700576 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
577 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
578 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0, sizeof(Elf_Word),
579 sizeof(Elf_Word)),
580 dynamic_builder_(".dynamic", &dynsym_builder_),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700581 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, nullptr, 0, 1, 1) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700582 SetupEhdr();
583 SetupDynamic();
584 SetupRequiredSymbols();
585 SetISA(isa);
586 }
587 ~ElfBuilder() {}
588
David Srbecky533c2072015-04-22 12:20:22 +0100589 const ElfOatSectionBuilder<ElfTypes>& GetTextBuilder() const {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700590 return text_builder_;
591 }
592
David Srbecky533c2072015-04-22 12:20:22 +0100593 ElfSymtabBuilder<ElfTypes>* GetSymtabBuilder() {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700594 return &symtab_builder_;
595 }
596
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700597 bool Init() {
Vladimir Marko5c42c292015-02-25 12:02:49 +0000598 // Since the .text section of an oat file contains relative references to .rodata
599 // and (optionally) .bss, we keep these 2 or 3 sections together. This creates
600 // a non-traditional layout where the .bss section is mapped independently of the
601 // .dynamic section and needs its own program header with LOAD RW.
602 //
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700603 // The basic layout of the elf file. Order may be different in final output.
604 // +-------------------------+
605 // | Elf_Ehdr |
606 // +-------------------------+
607 // | Elf_Phdr PHDR |
David Srbecky527c9c72015-04-17 21:14:10 +0100608 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .eh_frame .eh_frame_hdr .rodata
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700609 // | Elf_Phdr LOAD R X | .text
Vladimir Marko5c42c292015-02-25 12:02:49 +0000610 // | Elf_Phdr LOAD RW | .bss (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700611 // | Elf_Phdr LOAD RW | .dynamic
612 // | Elf_Phdr DYNAMIC | .dynamic
David Srbecky527c9c72015-04-17 21:14:10 +0100613 // | Elf_Phdr EH_FRAME R | .eh_frame_hdr
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700614 // +-------------------------+
615 // | .dynsym |
616 // | Elf_Sym STN_UNDEF |
617 // | Elf_Sym oatdata |
618 // | Elf_Sym oatexec |
619 // | Elf_Sym oatlastword |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000620 // | Elf_Sym oatbss | (Optional)
621 // | Elf_Sym oatbsslastword | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700622 // +-------------------------+
623 // | .dynstr |
624 // | \0 |
625 // | oatdata\0 |
626 // | oatexec\0 |
627 // | oatlastword\0 |
628 // | boot.oat\0 |
629 // +-------------------------+
630 // | .hash |
631 // | Elf_Word nbucket = b |
632 // | Elf_Word nchain = c |
633 // | Elf_Word bucket[0] |
634 // | ... |
635 // | Elf_Word bucket[b - 1] |
636 // | Elf_Word chain[0] |
637 // | ... |
638 // | Elf_Word chain[c - 1] |
639 // +-------------------------+
David Srbecky527c9c72015-04-17 21:14:10 +0100640 // | .eh_frame | (Optional)
641 // +-------------------------+
642 // | .eh_frame_hdr | (Optional)
643 // +-------------------------+
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700644 // | .rodata |
645 // | oatdata..oatexec-4 |
646 // +-------------------------+
647 // | .text |
648 // | oatexec..oatlastword |
649 // +-------------------------+
650 // | .dynamic |
651 // | Elf_Dyn DT_SONAME |
652 // | Elf_Dyn DT_HASH |
653 // | Elf_Dyn DT_SYMTAB |
654 // | Elf_Dyn DT_SYMENT |
655 // | Elf_Dyn DT_STRTAB |
656 // | Elf_Dyn DT_STRSZ |
657 // | Elf_Dyn DT_NULL |
658 // +-------------------------+ (Optional)
659 // | .strtab | (Optional)
660 // | program symbol names | (Optional)
661 // +-------------------------+ (Optional)
662 // | .symtab | (Optional)
663 // | program symbols | (Optional)
664 // +-------------------------+
665 // | .shstrtab |
666 // | \0 |
667 // | .dynamic\0 |
668 // | .dynsym\0 |
669 // | .dynstr\0 |
670 // | .hash\0 |
671 // | .rodata\0 |
672 // | .text\0 |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000673 // | .bss\0 | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700674 // | .shstrtab\0 |
675 // | .symtab\0 | (Optional)
676 // | .strtab\0 | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700677 // | .eh_frame\0 | (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100678 // | .eh_frame_hdr\0 | (Optional)
679 // | .debug_info\0 | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700680 // | .debug_abbrev\0 | (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100681 // | .debug_str\0 | (Optional)
682 // | .debug_line\0 | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700683 // +-------------------------+ (Optional)
684 // | .debug_info | (Optional)
685 // +-------------------------+ (Optional)
686 // | .debug_abbrev | (Optional)
687 // +-------------------------+ (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100688 // | .debug_str | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700689 // +-------------------------+ (Optional)
690 // | .debug_line | (Optional)
691 // +-------------------------+ (Optional)
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700692 // | Elf_Shdr null |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700693 // | Elf_Shdr .dynsym |
694 // | Elf_Shdr .dynstr |
695 // | Elf_Shdr .hash |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700696 // | Elf_Shdr .rodata |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000697 // | Elf_Shdr .text |
698 // | Elf_Shdr .bss | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700699 // | Elf_Shdr .dynamic |
700 // | Elf_Shdr .shstrtab |
David Srbecky527c9c72015-04-17 21:14:10 +0100701 // | Elf_Shdr .eh_frame | (Optional)
702 // | Elf_Shdr .eh_frame_hdr | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700703 // | Elf_Shdr .debug_info | (Optional)
704 // | Elf_Shdr .debug_abbrev | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700705 // | Elf_Shdr .debug_str | (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100706 // | Elf_Shdr .debug_line | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700707 // +-------------------------+
708
709 if (fatal_error_) {
710 return false;
711 }
712 // Step 1. Figure out all the offsets.
713
714 if (debug_logging_) {
715 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
716 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
717 }
718
719 memset(&program_headers_, 0, sizeof(program_headers_));
720 program_headers_[PH_PHDR].p_type = PT_PHDR;
721 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET;
722 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET;
723 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET;
724 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_);
725 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_);
726 program_headers_[PH_PHDR].p_flags = PF_R;
727 program_headers_[PH_PHDR].p_align = sizeof(Elf_Word);
728
729 program_headers_[PH_LOAD_R__].p_type = PT_LOAD;
730 program_headers_[PH_LOAD_R__].p_offset = 0;
731 program_headers_[PH_LOAD_R__].p_vaddr = 0;
732 program_headers_[PH_LOAD_R__].p_paddr = 0;
733 program_headers_[PH_LOAD_R__].p_flags = PF_R;
734
735 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD;
736 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X;
737
Vladimir Marko5c42c292015-02-25 12:02:49 +0000738 program_headers_[PH_LOAD_RW_BSS].p_type = PT_LOAD;
739 program_headers_[PH_LOAD_RW_BSS].p_flags = PF_R | PF_W;
740
741 program_headers_[PH_LOAD_RW_DYNAMIC].p_type = PT_LOAD;
742 program_headers_[PH_LOAD_RW_DYNAMIC].p_flags = PF_R | PF_W;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700743
744 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC;
745 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W;
746
David Srbecky527c9c72015-04-17 21:14:10 +0100747 program_headers_[PH_EH_FRAME_HDR].p_type = PT_NULL;
748 program_headers_[PH_EH_FRAME_HDR].p_flags = PF_R;
749
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700750 // Get the dynstr string.
751 dynstr_ = dynsym_builder_.GenerateStrtab();
752
753 // Add the SONAME to the dynstr.
754 dynstr_soname_offset_ = dynstr_.size();
755 std::string file_name(elf_file_->GetPath());
756 size_t directory_separator_pos = file_name.rfind('/');
757 if (directory_separator_pos != std::string::npos) {
758 file_name = file_name.substr(directory_separator_pos + 1);
759 }
760 dynstr_ += file_name;
761 dynstr_ += '\0';
762 if (debug_logging_) {
763 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size()
764 << std::hex << " " << dynstr_.size();
765 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
766 << std::hex << " " << dynsym_builder_.GetSize();
767 }
768
769 // Get the section header string table.
770 shstrtab_ += '\0';
771
772 // Setup sym_undef
773 memset(&null_hdr_, 0, sizeof(null_hdr_));
774 null_hdr_.sh_type = SHT_NULL;
775 null_hdr_.sh_link = SHN_UNDEF;
776 section_ptrs_.push_back(&null_hdr_);
777
778 section_index_ = 1;
779
780 // setup .dynsym
Ian Rogers0279ebb2014-10-08 17:27:48 -0700781 section_ptrs_.push_back(dynsym_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700782 AssignSectionStr(&dynsym_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700783 dynsym_builder_.SetSectionIndex(section_index_);
784 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700785
786 // Setup .dynstr
Ian Rogers0279ebb2014-10-08 17:27:48 -0700787 section_ptrs_.push_back(dynsym_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700788 AssignSectionStr(dynsym_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700789 dynsym_builder_.GetStrTab()->SetSectionIndex(section_index_);
790 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700791
792 // Setup .hash
Ian Rogers0279ebb2014-10-08 17:27:48 -0700793 section_ptrs_.push_back(hash_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700794 AssignSectionStr(&hash_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700795 hash_builder_.SetSectionIndex(section_index_);
796 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700797
798 // Setup .rodata
Ian Rogers0279ebb2014-10-08 17:27:48 -0700799 section_ptrs_.push_back(rodata_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700800 AssignSectionStr(&rodata_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700801 rodata_builder_.SetSectionIndex(section_index_);
802 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700803
804 // Setup .text
Ian Rogers0279ebb2014-10-08 17:27:48 -0700805 section_ptrs_.push_back(text_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700806 AssignSectionStr(&text_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700807 text_builder_.SetSectionIndex(section_index_);
808 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700809
Vladimir Marko5c42c292015-02-25 12:02:49 +0000810 // Setup .bss
811 if (bss_builder_.GetSize() != 0u) {
812 section_ptrs_.push_back(bss_builder_.GetSection());
813 AssignSectionStr(&bss_builder_, &shstrtab_);
814 bss_builder_.SetSectionIndex(section_index_);
815 section_index_++;
816 }
817
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700818 // Setup .dynamic
Ian Rogers0279ebb2014-10-08 17:27:48 -0700819 section_ptrs_.push_back(dynamic_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700820 AssignSectionStr(&dynamic_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700821 dynamic_builder_.SetSectionIndex(section_index_);
822 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700823
824 // Fill in the hash section.
825 hash_ = dynsym_builder_.GenerateHashContents();
826
827 if (debug_logging_) {
828 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
829 << std::hex << " " << hash_.size() * sizeof(Elf_Word);
830 }
831
832 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
833
834 // Get the layout in the sections.
835 //
836 // Get the layout of the dynsym section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700837 dynsym_builder_.GetSection()->sh_offset =
838 RoundUp(base_offset, dynsym_builder_.GetSection()->sh_addralign);
839 dynsym_builder_.GetSection()->sh_addr = dynsym_builder_.GetSection()->sh_offset;
840 dynsym_builder_.GetSection()->sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
841 dynsym_builder_.GetSection()->sh_link = dynsym_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700842
843 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700844 dynsym_builder_.GetStrTab()->GetSection()->sh_offset =
845 NextOffset<Elf_Word, Elf_Shdr>(*dynsym_builder_.GetStrTab()->GetSection(),
846 *dynsym_builder_.GetSection());
847 dynsym_builder_.GetStrTab()->GetSection()->sh_addr =
848 dynsym_builder_.GetStrTab()->GetSection()->sh_offset;
849 dynsym_builder_.GetStrTab()->GetSection()->sh_size = dynstr_.size();
850 dynsym_builder_.GetStrTab()->GetSection()->sh_link = dynsym_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700851
852 // Get the layout of the hash section
Ian Rogers0279ebb2014-10-08 17:27:48 -0700853 hash_builder_.GetSection()->sh_offset =
854 NextOffset<Elf_Word, Elf_Shdr>(*hash_builder_.GetSection(),
855 *dynsym_builder_.GetStrTab()->GetSection());
856 hash_builder_.GetSection()->sh_addr = hash_builder_.GetSection()->sh_offset;
857 hash_builder_.GetSection()->sh_size = hash_.size() * sizeof(Elf_Word);
858 hash_builder_.GetSection()->sh_link = hash_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700859
David Srbecky527c9c72015-04-17 21:14:10 +0100860 // Get the layout of the extra sections with SHF_ALLOC flag.
861 // This will deal with .eh_frame and .eh_frame_hdr.
862 // .eh_frame contains relative pointers to .text which we
863 // want to fixup between the calls to Init() and Write().
864 // Therefore we handle those sections here as opposed to Write().
865 // It also has the nice side effect of including .eh_frame
866 // with the rest of LOAD_R segment. It must come before .rodata
867 // because .rodata and .text must be next to each other.
868 Elf_Shdr* prev = hash_builder_.GetSection();
869 for (auto* it : other_builders_) {
870 if ((it->GetSection()->sh_flags & SHF_ALLOC) != 0) {
871 it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
872 it->GetSection()->sh_addr = it->GetSection()->sh_offset;
873 it->GetSection()->sh_size = it->GetBuffer()->size();
874 it->GetSection()->sh_link = it->GetLink();
875 prev = it->GetSection();
876 }
877 }
878 // If the sections exist, check that they have been handled.
879 const auto* eh_frame = FindRawSection(".eh_frame");
880 if (eh_frame != nullptr) {
881 DCHECK_NE(eh_frame->GetSection()->sh_offset, 0u);
882 }
883 const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr");
884 if (eh_frame_hdr != nullptr) {
885 DCHECK_NE(eh_frame_hdr->GetSection()->sh_offset, 0u);
886 }
887
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700888 // Get the layout of the rodata section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700889 rodata_builder_.GetSection()->sh_offset =
David Srbecky527c9c72015-04-17 21:14:10 +0100890 NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(), *prev);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700891 rodata_builder_.GetSection()->sh_addr = rodata_builder_.GetSection()->sh_offset;
892 rodata_builder_.GetSection()->sh_size = rodata_builder_.GetSize();
893 rodata_builder_.GetSection()->sh_link = rodata_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700894
895 // Get the layout of the text section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700896 text_builder_.GetSection()->sh_offset =
897 NextOffset<Elf_Word, Elf_Shdr>(*text_builder_.GetSection(),
898 *rodata_builder_.GetSection());
899 text_builder_.GetSection()->sh_addr = text_builder_.GetSection()->sh_offset;
900 text_builder_.GetSection()->sh_size = text_builder_.GetSize();
901 text_builder_.GetSection()->sh_link = text_builder_.GetLink();
902 CHECK_ALIGNED(rodata_builder_.GetSection()->sh_offset +
903 rodata_builder_.GetSection()->sh_size, kPageSize);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700904
Vladimir Marko5c42c292015-02-25 12:02:49 +0000905 // Get the layout of the .bss section.
906 bss_builder_.GetSection()->sh_offset =
907 NextOffset<Elf_Word, Elf_Shdr>(*bss_builder_.GetSection(),
908 *text_builder_.GetSection());
909 bss_builder_.GetSection()->sh_addr = bss_builder_.GetSection()->sh_offset;
910 bss_builder_.GetSection()->sh_size = bss_builder_.GetSize();
911 bss_builder_.GetSection()->sh_link = bss_builder_.GetLink();
912
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700913 // Get the layout of the dynamic section.
Vladimir Marko5c42c292015-02-25 12:02:49 +0000914 CHECK(IsAlignedParam(bss_builder_.GetSection()->sh_offset,
915 dynamic_builder_.GetSection()->sh_addralign));
916 dynamic_builder_.GetSection()->sh_offset = bss_builder_.GetSection()->sh_offset;
917 dynamic_builder_.GetSection()->sh_addr =
918 NextOffset<Elf_Word, Elf_Shdr>(*dynamic_builder_.GetSection(), *bss_builder_.GetSection());
Ian Rogers0279ebb2014-10-08 17:27:48 -0700919 dynamic_builder_.GetSection()->sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
920 dynamic_builder_.GetSection()->sh_link = dynamic_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700921
922 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700923 LOG(INFO) << "dynsym off=" << dynsym_builder_.GetSection()->sh_offset
924 << " dynsym size=" << dynsym_builder_.GetSection()->sh_size;
925 LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->GetSection()->sh_offset
926 << " dynstr size=" << dynsym_builder_.GetStrTab()->GetSection()->sh_size;
927 LOG(INFO) << "hash off=" << hash_builder_.GetSection()->sh_offset
928 << " hash size=" << hash_builder_.GetSection()->sh_size;
929 LOG(INFO) << "rodata off=" << rodata_builder_.GetSection()->sh_offset
930 << " rodata size=" << rodata_builder_.GetSection()->sh_size;
931 LOG(INFO) << "text off=" << text_builder_.GetSection()->sh_offset
932 << " text size=" << text_builder_.GetSection()->sh_size;
933 LOG(INFO) << "dynamic off=" << dynamic_builder_.GetSection()->sh_offset
934 << " dynamic size=" << dynamic_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700935 }
936
937 return true;
938 }
939
940 bool Write() {
Andreas Gampecc676072014-09-23 22:58:07 -0700941 std::vector<ElfFilePiece<Elf_Word>*> pieces;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700942 Elf_Shdr* prev = dynamic_builder_.GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700943 std::string strtab;
944
945 if (IncludingDebugSymbols()) {
946 // Setup .symtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700947 section_ptrs_.push_back(symtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700948 AssignSectionStr(&symtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700949 symtab_builder_.SetSectionIndex(section_index_);
950 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700951
952 // Setup .strtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700953 section_ptrs_.push_back(symtab_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700954 AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700955 symtab_builder_.GetStrTab()->SetSectionIndex(section_index_);
956 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700957
958 strtab = symtab_builder_.GenerateStrtab();
959 if (debug_logging_) {
960 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
961 << std::hex << " " << strtab.size();
962 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
963 << std::hex << " " << symtab_builder_.GetSize();
964 }
965 }
966
967 // Setup all the other sections.
David Srbecky527c9c72015-04-17 21:14:10 +0100968 for (auto* builder : other_builders_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700969 section_ptrs_.push_back(builder->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700970 AssignSectionStr(builder, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700971 builder->SetSectionIndex(section_index_);
972 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700973 }
974
975 // Setup shstrtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700976 section_ptrs_.push_back(shstrtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700977 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700978 shstrtab_builder_.SetSectionIndex(section_index_);
979 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700980
981 if (debug_logging_) {
982 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
983 << std::hex << " " << shstrtab_.size();
984 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
985 << std::hex << " " << section_ptrs_.size();
986 }
987
988 if (IncludingDebugSymbols()) {
989 // Get the layout of the symtab section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700990 symtab_builder_.GetSection()->sh_offset =
991 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetSection(),
992 *dynamic_builder_.GetSection());
993 symtab_builder_.GetSection()->sh_addr = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700994 // Add to leave space for the null symbol.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700995 symtab_builder_.GetSection()->sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
996 symtab_builder_.GetSection()->sh_link = symtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700997
998 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700999 symtab_builder_.GetStrTab()->GetSection()->sh_offset =
1000 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetStrTab()->GetSection(),
1001 *symtab_builder_.GetSection());
1002 symtab_builder_.GetStrTab()->GetSection()->sh_addr = 0;
1003 symtab_builder_.GetStrTab()->GetSection()->sh_size = strtab.size();
1004 symtab_builder_.GetStrTab()->GetSection()->sh_link = symtab_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001005
Ian Rogers0279ebb2014-10-08 17:27:48 -07001006 prev = symtab_builder_.GetStrTab()->GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001007 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001008 LOG(INFO) << "symtab off=" << symtab_builder_.GetSection()->sh_offset
1009 << " symtab size=" << symtab_builder_.GetSection()->sh_size;
1010 LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->GetSection()->sh_offset
1011 << " strtab size=" << symtab_builder_.GetStrTab()->GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001012 }
1013 }
1014
David Srbecky527c9c72015-04-17 21:14:10 +01001015 // Get the layout of the extra sections without SHF_ALLOC flag.
1016 // (This will deal with the debug sections if they are there)
1017 for (auto* it : other_builders_) {
1018 if ((it->GetSection()->sh_flags & SHF_ALLOC) == 0) {
1019 it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
1020 it->GetSection()->sh_addr = 0;
1021 it->GetSection()->sh_size = it->GetBuffer()->size();
1022 it->GetSection()->sh_link = it->GetLink();
Andreas Gampecc676072014-09-23 22:58:07 -07001023
David Srbecky527c9c72015-04-17 21:14:10 +01001024 // We postpone adding an ElfFilePiece to keep the order in "pieces."
Andreas Gampecc676072014-09-23 22:58:07 -07001025
David Srbecky527c9c72015-04-17 21:14:10 +01001026 prev = it->GetSection();
1027 if (debug_logging_) {
1028 LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset
1029 << " size=" << it->GetSection()->sh_size;
1030 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001031 }
1032 }
1033
1034 // Get the layout of the shstrtab section
Ian Rogers0279ebb2014-10-08 17:27:48 -07001035 shstrtab_builder_.GetSection()->sh_offset =
1036 NextOffset<Elf_Word, Elf_Shdr>(*shstrtab_builder_.GetSection(), *prev);
1037 shstrtab_builder_.GetSection()->sh_addr = 0;
1038 shstrtab_builder_.GetSection()->sh_size = shstrtab_.size();
1039 shstrtab_builder_.GetSection()->sh_link = shstrtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001040 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001041 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.GetSection()->sh_offset
1042 << " shstrtab size=" << shstrtab_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001043 }
1044
1045 // The section list comes after come after.
1046 Elf_Word sections_offset = RoundUp(
Ian Rogers0279ebb2014-10-08 17:27:48 -07001047 shstrtab_builder_.GetSection()->sh_offset + shstrtab_builder_.GetSection()->sh_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001048 sizeof(Elf_Word));
1049
1050 // Setup the actual symbol arrays.
1051 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001052 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001053 std::vector<Elf_Sym> symtab;
1054 if (IncludingDebugSymbols()) {
1055 symtab = symtab_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001056 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001057 }
1058
1059 // Setup the dynamic section.
1060 // This will add the 2 values we cannot know until now time, namely the size
1061 // and the soname_offset.
1062 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
1063 dynstr_soname_offset_);
Ian Rogers0279ebb2014-10-08 17:27:48 -07001064 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001065
1066 // Finish setup of the program headers now that we know the layout of the
1067 // whole file.
Ian Rogers0279ebb2014-10-08 17:27:48 -07001068 Elf_Word load_r_size =
1069 rodata_builder_.GetSection()->sh_offset + rodata_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001070 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
1071 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001072 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001073
Ian Rogers0279ebb2014-10-08 17:27:48 -07001074 Elf_Word load_rx_size = text_builder_.GetSection()->sh_size;
1075 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.GetSection()->sh_offset;
1076 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.GetSection()->sh_offset;
1077 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.GetSection()->sh_offset;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001078 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
1079 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001080 program_headers_[PH_LOAD_R_X].p_align = text_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001081
Vladimir Marko5c42c292015-02-25 12:02:49 +00001082 program_headers_[PH_LOAD_RW_BSS].p_offset = bss_builder_.GetSection()->sh_offset;
1083 program_headers_[PH_LOAD_RW_BSS].p_vaddr = bss_builder_.GetSection()->sh_offset;
1084 program_headers_[PH_LOAD_RW_BSS].p_paddr = bss_builder_.GetSection()->sh_offset;
1085 program_headers_[PH_LOAD_RW_BSS].p_filesz = 0;
1086 program_headers_[PH_LOAD_RW_BSS].p_memsz = bss_builder_.GetSection()->sh_size;
1087 program_headers_[PH_LOAD_RW_BSS].p_align = bss_builder_.GetSection()->sh_addralign;
1088
1089 program_headers_[PH_LOAD_RW_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
1090 program_headers_[PH_LOAD_RW_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_addr;
1091 program_headers_[PH_LOAD_RW_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_addr;
1092 program_headers_[PH_LOAD_RW_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1093 program_headers_[PH_LOAD_RW_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1094 program_headers_[PH_LOAD_RW_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001095
Ian Rogers0279ebb2014-10-08 17:27:48 -07001096 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001097 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_addr;
1098 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_addr;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001099 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1100 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1101 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001102
David Srbecky527c9c72015-04-17 21:14:10 +01001103 const auto* eh_frame_hdr = FindRawSection(".eh_frame_hdr");
1104 if (eh_frame_hdr != nullptr) {
1105 const auto* eh_frame = FindRawSection(".eh_frame");
1106 // Check layout:
1107 // 1) eh_frame is before eh_frame_hdr.
1108 // 2) There's no gap.
1109 CHECK(eh_frame != nullptr);
1110 CHECK_LE(eh_frame->GetSection()->sh_offset, eh_frame_hdr->GetSection()->sh_offset);
1111 CHECK_EQ(eh_frame->GetSection()->sh_offset + eh_frame->GetSection()->sh_size,
1112 eh_frame_hdr->GetSection()->sh_offset);
1113
1114 program_headers_[PH_EH_FRAME_HDR].p_type = PT_GNU_EH_FRAME;
1115 program_headers_[PH_EH_FRAME_HDR].p_offset = eh_frame_hdr->GetSection()->sh_offset;
1116 program_headers_[PH_EH_FRAME_HDR].p_vaddr = eh_frame_hdr->GetSection()->sh_addr;
1117 program_headers_[PH_EH_FRAME_HDR].p_paddr = eh_frame_hdr->GetSection()->sh_addr;
1118 program_headers_[PH_EH_FRAME_HDR].p_filesz = eh_frame_hdr->GetSection()->sh_size;
1119 program_headers_[PH_EH_FRAME_HDR].p_memsz = eh_frame_hdr->GetSection()->sh_size;
1120 program_headers_[PH_EH_FRAME_HDR].p_align = eh_frame_hdr->GetSection()->sh_addralign;
1121 }
1122
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001123 // Finish setup of the Ehdr values.
1124 elf_header_.e_phoff = PHDR_OFFSET;
1125 elf_header_.e_shoff = sections_offset;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001126 elf_header_.e_phnum = (bss_builder_.GetSection()->sh_size != 0u) ? PH_NUM : PH_NUM - 1;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001127 elf_header_.e_shnum = section_ptrs_.size();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001128 elf_header_.e_shstrndx = shstrtab_builder_.GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001129
1130 // Add the rest of the pieces to the list.
Andreas Gampecc676072014-09-23 22:58:07 -07001131 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_,
1132 sizeof(elf_header_)));
Vladimir Marko5c42c292015-02-25 12:02:49 +00001133 if (bss_builder_.GetSection()->sh_size != 0u) {
1134 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1135 &program_headers_[0],
1136 elf_header_.e_phnum * sizeof(Elf_Phdr)));
1137 } else {
1138 // Skip PH_LOAD_RW_BSS.
1139 Elf_Word part1_size = PH_LOAD_RW_BSS * sizeof(Elf_Phdr);
1140 Elf_Word part2_size = (PH_NUM - PH_LOAD_RW_BSS - 1) * sizeof(Elf_Phdr);
1141 CHECK_EQ(part1_size + part2_size, elf_header_.e_phnum * sizeof(Elf_Phdr));
1142 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1143 &program_headers_[0], part1_size));
1144 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers part 2",
1145 PHDR_OFFSET + part1_size,
1146 &program_headers_[PH_LOAD_RW_BSS + 1],
1147 part2_size));
1148 }
Andreas Gampecc676072014-09-23 22:58:07 -07001149 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001150 dynamic_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001151 dynamic.data(),
Ian Rogers0279ebb2014-10-08 17:27:48 -07001152 dynamic_builder_.GetSection()->sh_size));
1153 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001154 dynsym.data(),
1155 dynsym.size() * sizeof(Elf_Sym)));
1156 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001157 dynsym_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001158 dynstr_.c_str(), dynstr_.size()));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001159 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001160 hash_.data(),
1161 hash_.size() * sizeof(Elf_Word)));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001162 pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001163 oat_writer_));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001164 pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001165 oat_writer_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001166 if (IncludingDebugSymbols()) {
Andreas Gampecc676072014-09-23 22:58:07 -07001167 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001168 symtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001169 symtab.data(),
1170 symtab.size() * sizeof(Elf_Sym)));
1171 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001172 symtab_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001173 strtab.c_str(), strtab.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001174 }
Andreas Gampecc676072014-09-23 22:58:07 -07001175 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001176 shstrtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001177 &shstrtab_[0], shstrtab_.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001178 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
1179 // Just add all the sections in induvidually since they are all over the
1180 // place on the heap/stack.
1181 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
Andreas Gampecc676072014-09-23 22:58:07 -07001182 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off,
1183 section_ptrs_[i], sizeof(Elf_Shdr)));
1184 }
1185
1186 // Postponed debug info.
David Srbecky527c9c72015-04-17 21:14:10 +01001187 for (auto* it : other_builders_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001188 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->GetName(), it->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001189 it->GetBuffer()->data(),
1190 it->GetBuffer()->size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001191 }
1192
1193 if (!WriteOutFile(pieces)) {
1194 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
Andreas Gampecc676072014-09-23 22:58:07 -07001195
1196 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001197 return false;
1198 }
1199
Andreas Gampecc676072014-09-23 22:58:07 -07001200 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001201 return true;
1202 }
1203
David Srbecky527c9c72015-04-17 21:14:10 +01001204 // Adds the given raw section to the builder. It does not take ownership.
David Srbecky533c2072015-04-22 12:20:22 +01001205 void RegisterRawSection(ElfRawSectionBuilder<ElfTypes>* bld) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001206 other_builders_.push_back(bld);
1207 }
1208
David Srbecky533c2072015-04-22 12:20:22 +01001209 const ElfRawSectionBuilder<ElfTypes>* FindRawSection(const char* name) {
David Srbecky527c9c72015-04-17 21:14:10 +01001210 for (const auto* other_builder : other_builders_) {
1211 if (other_builder->GetName() == name) {
1212 return other_builder;
1213 }
1214 }
1215 return nullptr;
1216 }
1217
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001218 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001219 void SetISA(InstructionSet isa) {
1220 switch (isa) {
1221 case kArm:
1222 // Fall through.
1223 case kThumb2: {
1224 elf_header_.e_machine = EM_ARM;
1225 elf_header_.e_flags = EF_ARM_EABI_VER5;
1226 break;
1227 }
1228 case kArm64: {
1229 elf_header_.e_machine = EM_AARCH64;
1230 elf_header_.e_flags = 0;
1231 break;
1232 }
1233 case kX86: {
1234 elf_header_.e_machine = EM_386;
1235 elf_header_.e_flags = 0;
1236 break;
1237 }
1238 case kX86_64: {
1239 elf_header_.e_machine = EM_X86_64;
1240 elf_header_.e_flags = 0;
1241 break;
1242 }
1243 case kMips: {
1244 elf_header_.e_machine = EM_MIPS;
1245 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1246 EF_MIPS_PIC |
1247 EF_MIPS_CPIC |
1248 EF_MIPS_ABI_O32 |
1249 EF_MIPS_ARCH_32R2);
1250 break;
1251 }
Andreas Gampe57b34292015-01-14 15:45:59 -08001252 case kMips64: {
1253 elf_header_.e_machine = EM_MIPS;
1254 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1255 EF_MIPS_PIC |
1256 EF_MIPS_CPIC |
1257 EF_MIPS_ARCH_64R6);
1258 break;
1259 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001260 default: {
1261 fatal_error_ = true;
1262 LOG(FATAL) << "Unknown instruction set: " << isa;
1263 break;
1264 }
1265 }
1266 }
1267
1268 void SetupEhdr() {
1269 memset(&elf_header_, 0, sizeof(elf_header_));
1270 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
1271 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
1272 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
1273 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
Tong Shen62d1ca32014-09-03 17:24:56 -07001274 elf_header_.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
1275 ? ELFCLASS32 : ELFCLASS64;;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001276 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
1277 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
1278 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
1279 elf_header_.e_ident[EI_ABIVERSION] = 0;
1280 elf_header_.e_type = ET_DYN;
1281 elf_header_.e_version = 1;
1282 elf_header_.e_entry = 0;
1283 elf_header_.e_ehsize = sizeof(Elf_Ehdr);
1284 elf_header_.e_phentsize = sizeof(Elf_Phdr);
1285 elf_header_.e_shentsize = sizeof(Elf_Shdr);
1286 elf_header_.e_phoff = sizeof(Elf_Ehdr);
1287 }
1288
1289 // Sets up a bunch of the required Dynamic Section entries.
1290 // Namely it will initialize all the mandatory ones that it can.
1291 // Specifically:
1292 // DT_HASH
1293 // DT_STRTAB
1294 // DT_SYMTAB
1295 // DT_SYMENT
1296 //
1297 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
1298 void SetupDynamic() {
1299 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
1300 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1301 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1302 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1303 }
1304
1305 // Sets up the basic dynamic symbols that are needed, namely all those we
1306 // can know already.
1307 //
1308 // Specifically adds:
1309 // oatdata
1310 // oatexec
1311 // oatlastword
1312 void SetupRequiredSymbols() {
1313 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1314 rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1315 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1316 text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1317 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1318 true, 4, STB_GLOBAL, STT_OBJECT);
Vladimir Marko5c42c292015-02-25 12:02:49 +00001319 if (bss_builder_.GetSize() != 0u) {
1320 dynsym_builder_.AddSymbol("oatbss", &bss_builder_, 0, true,
1321 bss_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1322 dynsym_builder_.AddSymbol("oatbsslastword", &bss_builder_, bss_builder_.GetSize() - 4,
1323 true, 4, STB_GLOBAL, STT_OBJECT);
1324 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001325 }
1326
David Srbecky533c2072015-04-22 12:20:22 +01001327 void AssignSectionStr(ElfSectionBuilder<ElfTypes>* builder, std::string* strtab) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001328 builder->GetSection()->sh_name = strtab->size();
1329 *strtab += builder->GetName();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001330 *strtab += '\0';
1331 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001332 LOG(INFO) << "adding section name \"" << builder->GetName() << "\" "
1333 << "to shstrtab at offset " << builder->GetSection()->sh_name;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001334 }
1335 }
1336
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001337
1338 // Write each of the pieces out to the file.
Andreas Gampecc676072014-09-23 22:58:07 -07001339 bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001340 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
Andreas Gampecc676072014-09-23 22:58:07 -07001341 if (!(*it)->Write(elf_file_)) {
1342 return false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001343 }
1344 }
1345 return true;
1346 }
1347
Ian Rogers0279ebb2014-10-08 17:27:48 -07001348 bool IncludingDebugSymbols() const {
1349 return add_symbols_ && symtab_builder_.GetSize() > 1;
1350 }
1351
1352 CodeOutput* const oat_writer_;
1353 File* const elf_file_;
1354 const bool add_symbols_;
1355 const bool debug_logging_;
1356
1357 bool fatal_error_ = false;
1358
1359 // What phdr is.
1360 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
1361 enum : uint8_t {
Vladimir Marko5c42c292015-02-25 12:02:49 +00001362 PH_PHDR = 0,
1363 PH_LOAD_R__ = 1,
1364 PH_LOAD_R_X = 2,
1365 PH_LOAD_RW_BSS = 3,
1366 PH_LOAD_RW_DYNAMIC = 4,
1367 PH_DYNAMIC = 5,
David Srbecky527c9c72015-04-17 21:14:10 +01001368 PH_EH_FRAME_HDR = 6,
1369 PH_NUM = 7,
Ian Rogers0279ebb2014-10-08 17:27:48 -07001370 };
1371 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
1372 Elf_Phdr program_headers_[PH_NUM];
1373
1374 Elf_Ehdr elf_header_;
1375
1376 Elf_Shdr null_hdr_;
1377 std::string shstrtab_;
1378 // The index of the current section being built. The first being 1.
1379 uint32_t section_index_;
1380 std::string dynstr_;
1381 uint32_t dynstr_soname_offset_;
1382 std::vector<const Elf_Shdr*> section_ptrs_;
1383 std::vector<Elf_Word> hash_;
1384
David Srbecky533c2072015-04-22 12:20:22 +01001385 ElfOatSectionBuilder<ElfTypes> text_builder_;
1386 ElfOatSectionBuilder<ElfTypes> rodata_builder_;
1387 ElfOatSectionBuilder<ElfTypes> bss_builder_;
1388 ElfSymtabBuilder<ElfTypes> dynsym_builder_;
1389 ElfSymtabBuilder<ElfTypes> symtab_builder_;
1390 ElfSectionBuilder<ElfTypes> hash_builder_;
1391 ElfDynamicBuilder<ElfTypes> dynamic_builder_;
1392 ElfSectionBuilder<ElfTypes> shstrtab_builder_;
1393 std::vector<ElfRawSectionBuilder<ElfTypes>*> other_builders_;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001394
1395 DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001396};
1397
1398} // namespace art
1399
1400#endif // ART_COMPILER_ELF_BUILDER_H_