blob: c32bdb45dcd9811c9a427c697d1548360ef2cf59 [file] [log] [blame]
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_ELF_BUILDER_H_
18#define ART_COMPILER_ELF_BUILDER_H_
19
Andreas Gampecc676072014-09-23 22:58:07 -070020#include "base/stl_util.h"
Ian Rogers0279ebb2014-10-08 17:27:48 -070021#include "base/value_object.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070022#include "buffered_output_stream.h"
23#include "elf_utils.h"
24#include "file_output_stream.h"
25#include "instruction_set.h"
26
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 }
43
Ian Rogers0279ebb2014-10-08 17:27:48 -070044 ~ElfSectionBuilder() {}
Andreas Gampe54fc26c2014-09-04 21:47:42 -070045
Ian Rogers0279ebb2014-10-08 17:27:48 -070046 Elf_Word GetLink() const {
47 return (link_ != nullptr) ? link_->section_index_ : 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070048 }
49
Ian Rogers0279ebb2014-10-08 17:27:48 -070050 const Elf_Shdr* GetSection() const {
51 return &section_;
52 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -070053
Ian Rogers0279ebb2014-10-08 17:27:48 -070054 Elf_Shdr* GetSection() {
55 return &section_;
56 }
57
58 Elf_Word GetSectionIndex() const {
59 return section_index_;
60 }
61
62 void SetSectionIndex(Elf_Word section_index) {
63 section_index_ = section_index;
64 }
65
66 const std::string& GetName() const {
67 return name_;
68 }
69
70 private:
71 Elf_Shdr section_;
72 Elf_Word section_index_;
73 const std::string name_;
74 const ElfSectionBuilder* const link_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070075};
76
77template <typename Elf_Word, typename Elf_Sword, typename Elf_Dyn, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -070078class ElfDynamicBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070079 public:
80 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un) {
81 if (tag == DT_NULL) {
82 return;
83 }
84 dynamics_.push_back({nullptr, tag, d_un});
85 }
86
87 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un,
Ian Rogers0279ebb2014-10-08 17:27:48 -070088 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070089 if (tag == DT_NULL) {
90 return;
91 }
92 dynamics_.push_back({section, tag, d_un});
93 }
94
95 ElfDynamicBuilder(const std::string& sec_name,
96 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link)
97 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC,
98 link, 0, kPageSize, sizeof(Elf_Dyn)) {}
99 ~ElfDynamicBuilder() {}
100
Ian Rogers0279ebb2014-10-08 17:27:48 -0700101 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700102 // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
103 // these must be added when we actually put the file together because
104 // their values are very dependent on state.
105 return dynamics_.size() + 3;
106 }
107
108 // Create the actual dynamic vector. strsz should be the size of the .dynstr
109 // table and soname_off should be the offset of the soname in .dynstr.
110 // Since niether can be found prior to final layout we will wait until here
111 // to add them.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700112 std::vector<Elf_Dyn> GetDynamics(Elf_Word strsz, Elf_Word soname) const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700113 std::vector<Elf_Dyn> ret;
114 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700115 if (it->section_ != nullptr) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700116 // We are adding an address relative to a section.
117 ret.push_back(
Ian Rogers0279ebb2014-10-08 17:27:48 -0700118 {it->tag_, {it->off_ + it->section_->GetSection()->sh_addr}});
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700119 } else {
120 ret.push_back({it->tag_, {it->off_}});
121 }
122 }
123 ret.push_back({DT_STRSZ, {strsz}});
124 ret.push_back({DT_SONAME, {soname}});
125 ret.push_back({DT_NULL, {0}});
126 return ret;
127 }
128
Ian Rogers0279ebb2014-10-08 17:27:48 -0700129 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700130 struct ElfDynamicState {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700131 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700132 Elf_Sword tag_;
133 Elf_Word off_;
134 };
135 std::vector<ElfDynamicState> dynamics_;
136};
137
138template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700139class ElfRawSectionBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700140 public:
141 ElfRawSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
142 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* link, Elf_Word info,
143 Elf_Word align, Elf_Word entsize)
144 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, link, info, align,
Ian Rogers0279ebb2014-10-08 17:27:48 -0700145 entsize) {
146 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700147
Ian Rogers0279ebb2014-10-08 17:27:48 -0700148 ~ElfRawSectionBuilder() {}
149
150 std::vector<uint8_t>* GetBuffer() {
151 return &buf_;
152 }
153
154 void SetBuffer(const std::vector<uint8_t>& buf) {
155 buf_ = buf;
156 }
157
158 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700159 std::vector<uint8_t> buf_;
160};
161
162template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700163class ElfOatSectionBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700164 public:
165 ElfOatSectionBuilder(const std::string& sec_name, Elf_Word size, Elf_Word offset,
166 Elf_Word type, Elf_Word flags)
167 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, nullptr, 0, kPageSize,
Ian Rogers0279ebb2014-10-08 17:27:48 -0700168 0),
169 offset_(offset), size_(size) {
170 }
171
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700172 ~ElfOatSectionBuilder() {}
173
Ian Rogers0279ebb2014-10-08 17:27:48 -0700174 Elf_Word GetOffset() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700175 return offset_;
176 }
177
Ian Rogers0279ebb2014-10-08 17:27:48 -0700178 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700179 return size_;
180 }
181
Ian Rogers0279ebb2014-10-08 17:27:48 -0700182 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700183 // Offset of the content within the file.
184 Elf_Word offset_;
185 // Size of the content within the file.
186 Elf_Word size_;
187};
188
189static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
190 return ((binding) << 4) + ((type) & 0xf);
191}
192
193// from bionic
194static inline unsigned elfhash(const char *_name) {
195 const unsigned char *name = (const unsigned char *) _name;
196 unsigned h = 0, g;
197
198 while (*name) {
199 h = (h << 4) + *name++;
200 g = h & 0xf0000000;
201 h ^= g;
202 h ^= g >> 24;
203 }
204 return h;
205}
206
207template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Sym,
208 typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700209class ElfSymtabBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700210 public:
211 // Add a symbol with given name to this symtab. The symbol refers to
212 // 'relative_addr' within the given section and has the given attributes.
213 void AddSymbol(const std::string& name,
214 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section,
215 Elf_Addr addr,
216 bool is_relative,
217 Elf_Word size,
218 uint8_t binding,
219 uint8_t type,
220 uint8_t other = 0) {
221 CHECK(section);
222 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
223 MakeStInfo(binding, type), other, 0};
224 symbols_.push_back(state);
225 }
226
227 ElfSymtabBuilder(const std::string& sec_name, Elf_Word type,
228 const std::string& str_name, Elf_Word str_type, bool alloc)
229 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, ((alloc) ? SHF_ALLOC : 0U),
230 &strtab_, 0, sizeof(Elf_Word),
231 sizeof(Elf_Sym)), str_name_(str_name),
232 str_type_(str_type),
233 strtab_(str_name,
234 str_type,
235 ((alloc) ? SHF_ALLOC : 0U),
Ian Rogers0279ebb2014-10-08 17:27:48 -0700236 nullptr, 0, 1, 1) {
237 }
238
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700239 ~ElfSymtabBuilder() {}
240
Ian Rogers0279ebb2014-10-08 17:27:48 -0700241 std::vector<Elf_Word> GenerateHashContents() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700242 // Here is how The ELF hash table works.
243 // There are 3 arrays to worry about.
244 // * The symbol table where the symbol information is.
245 // * The bucket array which is an array of indexes into the symtab and chain.
246 // * The chain array which is also an array of indexes into the symtab and chain.
247 //
248 // Lets say the state is something like this.
249 // +--------+ +--------+ +-----------+
250 // | symtab | | bucket | | chain |
251 // | null | | 1 | | STN_UNDEF |
252 // | <sym1> | | 4 | | 2 |
253 // | <sym2> | | | | 5 |
254 // | <sym3> | | | | STN_UNDEF |
255 // | <sym4> | | | | 3 |
256 // | <sym5> | | | | STN_UNDEF |
257 // +--------+ +--------+ +-----------+
258 //
259 // The lookup process (in python psudocode) is
260 //
261 // def GetSym(name):
262 // # NB STN_UNDEF == 0
263 // indx = bucket[elfhash(name) % num_buckets]
264 // while indx != STN_UNDEF:
265 // if GetSymbolName(symtab[indx]) == name:
266 // return symtab[indx]
267 // indx = chain[indx]
268 // return SYMBOL_NOT_FOUND
269 //
270 // Between bucket and chain arrays every symtab index must be present exactly
271 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
272
273 // Select number of buckets.
274 // This is essentially arbitrary.
275 Elf_Word nbuckets;
276 Elf_Word chain_size = GetSize();
277 if (symbols_.size() < 8) {
278 nbuckets = 2;
279 } else if (symbols_.size() < 32) {
280 nbuckets = 4;
281 } else if (symbols_.size() < 256) {
282 nbuckets = 16;
283 } else {
284 // Have about 32 ids per bucket.
285 nbuckets = RoundUp(symbols_.size()/32, 2);
286 }
287 std::vector<Elf_Word> hash;
288 hash.push_back(nbuckets);
289 hash.push_back(chain_size);
290 uint32_t bucket_offset = hash.size();
291 uint32_t chain_offset = bucket_offset + nbuckets;
292 hash.resize(hash.size() + nbuckets + chain_size, 0);
293
294 Elf_Word* buckets = hash.data() + bucket_offset;
295 Elf_Word* chain = hash.data() + chain_offset;
296
297 // Set up the actual hash table.
298 for (Elf_Word i = 0; i < symbols_.size(); i++) {
299 // Add 1 since we need to have the null symbol that is not in the symbols
300 // list.
301 Elf_Word index = i + 1;
302 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
303 if (buckets[hash_val] == 0) {
304 buckets[hash_val] = index;
305 } else {
306 hash_val = buckets[hash_val];
307 CHECK_LT(hash_val, chain_size);
308 while (chain[hash_val] != 0) {
309 hash_val = chain[hash_val];
310 CHECK_LT(hash_val, chain_size);
311 }
312 chain[hash_val] = index;
313 // Check for loops. Works because if this is non-empty then there must be
314 // another cell which already contains the same symbol index as this one,
315 // which means some symbol has more then one name, which isn't allowed.
316 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
317 }
318 }
319
320 return hash;
321 }
322
323 std::string GenerateStrtab() {
324 std::string tab;
325 tab += '\0';
326 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
327 it->name_idx_ = tab.size();
328 tab += it->name_;
329 tab += '\0';
330 }
Ian Rogers0279ebb2014-10-08 17:27:48 -0700331 strtab_.GetSection()->sh_size = tab.size();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700332 return tab;
333 }
334
335 std::vector<Elf_Sym> GenerateSymtab() {
336 std::vector<Elf_Sym> ret;
337 Elf_Sym undef_sym;
338 memset(&undef_sym, 0, sizeof(undef_sym));
339 undef_sym.st_shndx = SHN_UNDEF;
340 ret.push_back(undef_sym);
341
342 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
343 Elf_Sym sym;
344 memset(&sym, 0, sizeof(sym));
345 sym.st_name = it->name_idx_;
346 if (it->is_relative_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700347 sym.st_value = it->addr_ + it->section_->GetSection()->sh_offset;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700348 } else {
349 sym.st_value = it->addr_;
350 }
351 sym.st_size = it->size_;
352 sym.st_other = it->other_;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700353 sym.st_shndx = it->section_->GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700354 sym.st_info = it->info_;
355
356 ret.push_back(sym);
357 }
358 return ret;
359 }
360
Ian Rogers0279ebb2014-10-08 17:27:48 -0700361 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700362 // 1 is for the implicit NULL symbol.
363 return symbols_.size() + 1;
364 }
365
366 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* GetStrTab() {
367 return &strtab_;
368 }
369
Ian Rogers0279ebb2014-10-08 17:27:48 -0700370 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700371 struct ElfSymbolState {
372 const std::string name_;
373 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_;
374 Elf_Addr addr_;
375 Elf_Word size_;
376 bool is_relative_;
377 uint8_t info_;
378 uint8_t other_;
379 // Used during Write() to temporarially hold name index in the strtab.
380 Elf_Word name_idx_;
381 };
382
383 // Information for the strsym for dynstr sections.
384 const std::string str_name_;
385 Elf_Word str_type_;
386 // The symbols in the same order they will be in the symbol table.
387 std::vector<ElfSymbolState> symbols_;
388 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> strtab_;
389};
390
Andreas Gampecc676072014-09-23 22:58:07 -0700391template <typename Elf_Word>
392class ElfFilePiece {
393 public:
394 virtual ~ElfFilePiece() {}
395
396 virtual bool Write(File* elf_file) {
397 if (static_cast<off_t>(offset_) != lseek(elf_file->Fd(), offset_, SEEK_SET)) {
398 PLOG(ERROR) << "Failed to seek to " << GetDescription() << " offset " << offset_ << " for "
399 << elf_file->GetPath();
400 return false;
401 }
402
403 return DoActualWrite(elf_file);
404 }
405
406 static bool Compare(ElfFilePiece* a, ElfFilePiece* b) {
407 return a->offset_ < b->offset_;
408 }
409
410 protected:
411 explicit ElfFilePiece(Elf_Word offset) : offset_(offset) {}
412
Ian Rogers0279ebb2014-10-08 17:27:48 -0700413 Elf_Word GetOffset() const {
414 return offset_;
415 }
416
417 virtual const char* GetDescription() const = 0;
Andreas Gampecc676072014-09-23 22:58:07 -0700418 virtual bool DoActualWrite(File* elf_file) = 0;
419
Ian Rogers0279ebb2014-10-08 17:27:48 -0700420 private:
421 const Elf_Word offset_;
422
423 DISALLOW_COPY_AND_ASSIGN(ElfFilePiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700424};
425
426template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700427class ElfFileMemoryPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700428 public:
429 ElfFileMemoryPiece(const std::string& name, Elf_Word offset, const void* data, Elf_Word size)
430 : ElfFilePiece<Elf_Word>(offset), dbg_name_(name), data_(data), size_(size) {}
431
Ian Rogers0279ebb2014-10-08 17:27:48 -0700432 protected:
Andreas Gampecc676072014-09-23 22:58:07 -0700433 bool DoActualWrite(File* elf_file) OVERRIDE {
434 DCHECK(data_ != nullptr || size_ == 0U) << dbg_name_ << " " << size_;
435
436 if (!elf_file->WriteFully(data_, size_)) {
437 PLOG(ERROR) << "Failed to write " << dbg_name_ << " for " << elf_file->GetPath();
438 return false;
439 }
440
441 return true;
442 }
443
Ian Rogers0279ebb2014-10-08 17:27:48 -0700444 const char* GetDescription() const OVERRIDE {
445 return dbg_name_.c_str();
Andreas Gampecc676072014-09-23 22:58:07 -0700446 }
447
448 private:
449 const std::string& dbg_name_;
450 const void *data_;
451 Elf_Word size_;
452};
453
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700454class CodeOutput {
455 public:
Vladimir Markof4da6752014-08-01 19:04:18 +0100456 virtual void SetCodeOffset(size_t offset) = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700457 virtual bool Write(OutputStream* out) = 0;
458 virtual ~CodeOutput() {}
459};
460
Andreas Gampecc676072014-09-23 22:58:07 -0700461template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700462class ElfFileRodataPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700463 public:
464 ElfFileRodataPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
465 output_(output) {}
466
Ian Rogers0279ebb2014-10-08 17:27:48 -0700467 protected:
Andreas Gampecc676072014-09-23 22:58:07 -0700468 bool DoActualWrite(File* elf_file) OVERRIDE {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700469 output_->SetCodeOffset(this->GetOffset());
Andreas Gampecc676072014-09-23 22:58:07 -0700470 std::unique_ptr<BufferedOutputStream> output_stream(
471 new BufferedOutputStream(new FileOutputStream(elf_file)));
472 if (!output_->Write(output_stream.get())) {
473 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file->GetPath();
474 return false;
475 }
476
477 return true;
478 }
479
Ian Rogers0279ebb2014-10-08 17:27:48 -0700480 const char* GetDescription() const OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700481 return ".rodata";
482 }
483
484 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700485 CodeOutput* const output_;
486
487 DISALLOW_COPY_AND_ASSIGN(ElfFileRodataPiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700488};
489
490template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700491class ElfFileOatTextPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700492 public:
493 ElfFileOatTextPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
494 output_(output) {}
495
Ian Rogers0279ebb2014-10-08 17:27:48 -0700496 protected:
Andreas Gampecc676072014-09-23 22:58:07 -0700497 bool DoActualWrite(File* elf_file) OVERRIDE {
498 // All data is written by the ElfFileRodataPiece right now, as the oat writer writes in one
499 // piece. This is for future flexibility.
500 UNUSED(output_);
501 return true;
502 }
503
Ian Rogers0279ebb2014-10-08 17:27:48 -0700504 const char* GetDescription() const OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700505 return ".text";
506 }
507
508 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700509 CodeOutput* const output_;
510
511 DISALLOW_COPY_AND_ASSIGN(ElfFileOatTextPiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700512};
513
514template <typename Elf_Word>
515static bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces, File* elf_file) {
516 // TODO It would be nice if this checked for overlap.
517 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
518 if (!(*it)->Write(elf_file)) {
519 return false;
520 }
521 }
522 return true;
523}
524
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700525template <typename Elf_Word, typename Elf_Shdr>
526static inline constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) {
527 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
528}
529
530template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Dyn,
531 typename Elf_Sym, typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr>
532class ElfBuilder FINAL {
533 public:
534 ElfBuilder(CodeOutput* oat_writer,
535 File* elf_file,
536 InstructionSet isa,
537 Elf_Word rodata_relative_offset,
538 Elf_Word rodata_size,
539 Elf_Word text_relative_offset,
540 Elf_Word text_size,
541 const bool add_symbols,
542 bool debug = false)
543 : oat_writer_(oat_writer),
544 elf_file_(elf_file),
545 add_symbols_(add_symbols),
546 debug_logging_(debug),
547 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
548 SHF_ALLOC | SHF_EXECINSTR),
549 rodata_builder_(".rodata", rodata_size, rodata_relative_offset, SHT_PROGBITS, SHF_ALLOC),
550 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
551 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
552 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0, sizeof(Elf_Word),
553 sizeof(Elf_Word)),
554 dynamic_builder_(".dynamic", &dynsym_builder_),
555 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
556 SetupEhdr();
557 SetupDynamic();
558 SetupRequiredSymbols();
559 SetISA(isa);
560 }
561 ~ElfBuilder() {}
562
Ian Rogers0279ebb2014-10-08 17:27:48 -0700563 const ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>& GetTextBuilder() const {
564 return text_builder_;
565 }
566
567 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* GetSymtabBuilder() {
568 return &symtab_builder_;
569 }
570
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700571 bool Init() {
572 // The basic layout of the elf file. Order may be different in final output.
573 // +-------------------------+
574 // | Elf_Ehdr |
575 // +-------------------------+
576 // | Elf_Phdr PHDR |
577 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata
578 // | Elf_Phdr LOAD R X | .text
579 // | Elf_Phdr LOAD RW | .dynamic
580 // | Elf_Phdr DYNAMIC | .dynamic
581 // +-------------------------+
582 // | .dynsym |
583 // | Elf_Sym STN_UNDEF |
584 // | Elf_Sym oatdata |
585 // | Elf_Sym oatexec |
586 // | Elf_Sym oatlastword |
587 // +-------------------------+
588 // | .dynstr |
589 // | \0 |
590 // | oatdata\0 |
591 // | oatexec\0 |
592 // | oatlastword\0 |
593 // | boot.oat\0 |
594 // +-------------------------+
595 // | .hash |
596 // | Elf_Word nbucket = b |
597 // | Elf_Word nchain = c |
598 // | Elf_Word bucket[0] |
599 // | ... |
600 // | Elf_Word bucket[b - 1] |
601 // | Elf_Word chain[0] |
602 // | ... |
603 // | Elf_Word chain[c - 1] |
604 // +-------------------------+
605 // | .rodata |
606 // | oatdata..oatexec-4 |
607 // +-------------------------+
608 // | .text |
609 // | oatexec..oatlastword |
610 // +-------------------------+
611 // | .dynamic |
612 // | Elf_Dyn DT_SONAME |
613 // | Elf_Dyn DT_HASH |
614 // | Elf_Dyn DT_SYMTAB |
615 // | Elf_Dyn DT_SYMENT |
616 // | Elf_Dyn DT_STRTAB |
617 // | Elf_Dyn DT_STRSZ |
618 // | Elf_Dyn DT_NULL |
619 // +-------------------------+ (Optional)
620 // | .strtab | (Optional)
621 // | program symbol names | (Optional)
622 // +-------------------------+ (Optional)
623 // | .symtab | (Optional)
624 // | program symbols | (Optional)
625 // +-------------------------+
626 // | .shstrtab |
627 // | \0 |
628 // | .dynamic\0 |
629 // | .dynsym\0 |
630 // | .dynstr\0 |
631 // | .hash\0 |
632 // | .rodata\0 |
633 // | .text\0 |
634 // | .shstrtab\0 |
635 // | .symtab\0 | (Optional)
636 // | .strtab\0 | (Optional)
637 // | .debug_str\0 | (Optional)
638 // | .debug_info\0 | (Optional)
639 // | .eh_frame\0 | (Optional)
640 // | .debug_line\0 | (Optional)
641 // | .debug_abbrev\0 | (Optional)
642 // +-------------------------+ (Optional)
643 // | .debug_info | (Optional)
644 // +-------------------------+ (Optional)
645 // | .debug_abbrev | (Optional)
646 // +-------------------------+ (Optional)
647 // | .eh_frame | (Optional)
648 // +-------------------------+ (Optional)
649 // | .debug_line | (Optional)
650 // +-------------------------+ (Optional)
651 // | .debug_str | (Optional)
652 // +-------------------------+ (Optional)
653 // | Elf_Shdr NULL |
654 // | Elf_Shdr .dynsym |
655 // | Elf_Shdr .dynstr |
656 // | Elf_Shdr .hash |
657 // | Elf_Shdr .text |
658 // | Elf_Shdr .rodata |
659 // | Elf_Shdr .dynamic |
660 // | Elf_Shdr .shstrtab |
661 // | Elf_Shdr .debug_info | (Optional)
662 // | Elf_Shdr .debug_abbrev | (Optional)
663 // | Elf_Shdr .eh_frame | (Optional)
664 // | Elf_Shdr .debug_line | (Optional)
665 // | Elf_Shdr .debug_str | (Optional)
666 // +-------------------------+
667
668 if (fatal_error_) {
669 return false;
670 }
671 // Step 1. Figure out all the offsets.
672
673 if (debug_logging_) {
674 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
675 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
676 }
677
678 memset(&program_headers_, 0, sizeof(program_headers_));
679 program_headers_[PH_PHDR].p_type = PT_PHDR;
680 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET;
681 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET;
682 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET;
683 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_);
684 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_);
685 program_headers_[PH_PHDR].p_flags = PF_R;
686 program_headers_[PH_PHDR].p_align = sizeof(Elf_Word);
687
688 program_headers_[PH_LOAD_R__].p_type = PT_LOAD;
689 program_headers_[PH_LOAD_R__].p_offset = 0;
690 program_headers_[PH_LOAD_R__].p_vaddr = 0;
691 program_headers_[PH_LOAD_R__].p_paddr = 0;
692 program_headers_[PH_LOAD_R__].p_flags = PF_R;
693
694 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD;
695 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X;
696
697 program_headers_[PH_LOAD_RW_].p_type = PT_LOAD;
698 program_headers_[PH_LOAD_RW_].p_flags = PF_R | PF_W;
699
700 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC;
701 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W;
702
703 // Get the dynstr string.
704 dynstr_ = dynsym_builder_.GenerateStrtab();
705
706 // Add the SONAME to the dynstr.
707 dynstr_soname_offset_ = dynstr_.size();
708 std::string file_name(elf_file_->GetPath());
709 size_t directory_separator_pos = file_name.rfind('/');
710 if (directory_separator_pos != std::string::npos) {
711 file_name = file_name.substr(directory_separator_pos + 1);
712 }
713 dynstr_ += file_name;
714 dynstr_ += '\0';
715 if (debug_logging_) {
716 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size()
717 << std::hex << " " << dynstr_.size();
718 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
719 << std::hex << " " << dynsym_builder_.GetSize();
720 }
721
722 // Get the section header string table.
723 shstrtab_ += '\0';
724
725 // Setup sym_undef
726 memset(&null_hdr_, 0, sizeof(null_hdr_));
727 null_hdr_.sh_type = SHT_NULL;
728 null_hdr_.sh_link = SHN_UNDEF;
729 section_ptrs_.push_back(&null_hdr_);
730
731 section_index_ = 1;
732
733 // setup .dynsym
Ian Rogers0279ebb2014-10-08 17:27:48 -0700734 section_ptrs_.push_back(dynsym_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700735 AssignSectionStr(&dynsym_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700736 dynsym_builder_.SetSectionIndex(section_index_);
737 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700738
739 // Setup .dynstr
Ian Rogers0279ebb2014-10-08 17:27:48 -0700740 section_ptrs_.push_back(dynsym_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700741 AssignSectionStr(dynsym_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700742 dynsym_builder_.GetStrTab()->SetSectionIndex(section_index_);
743 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700744
745 // Setup .hash
Ian Rogers0279ebb2014-10-08 17:27:48 -0700746 section_ptrs_.push_back(hash_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700747 AssignSectionStr(&hash_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700748 hash_builder_.SetSectionIndex(section_index_);
749 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700750
751 // Setup .rodata
Ian Rogers0279ebb2014-10-08 17:27:48 -0700752 section_ptrs_.push_back(rodata_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700753 AssignSectionStr(&rodata_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700754 rodata_builder_.SetSectionIndex(section_index_);
755 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700756
757 // Setup .text
Ian Rogers0279ebb2014-10-08 17:27:48 -0700758 section_ptrs_.push_back(text_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700759 AssignSectionStr(&text_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700760 text_builder_.SetSectionIndex(section_index_);
761 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700762
763 // Setup .dynamic
Ian Rogers0279ebb2014-10-08 17:27:48 -0700764 section_ptrs_.push_back(dynamic_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700765 AssignSectionStr(&dynamic_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700766 dynamic_builder_.SetSectionIndex(section_index_);
767 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700768
769 // Fill in the hash section.
770 hash_ = dynsym_builder_.GenerateHashContents();
771
772 if (debug_logging_) {
773 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
774 << std::hex << " " << hash_.size() * sizeof(Elf_Word);
775 }
776
777 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
778
779 // Get the layout in the sections.
780 //
781 // Get the layout of the dynsym section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700782 dynsym_builder_.GetSection()->sh_offset =
783 RoundUp(base_offset, dynsym_builder_.GetSection()->sh_addralign);
784 dynsym_builder_.GetSection()->sh_addr = dynsym_builder_.GetSection()->sh_offset;
785 dynsym_builder_.GetSection()->sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
786 dynsym_builder_.GetSection()->sh_link = dynsym_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700787
788 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700789 dynsym_builder_.GetStrTab()->GetSection()->sh_offset =
790 NextOffset<Elf_Word, Elf_Shdr>(*dynsym_builder_.GetStrTab()->GetSection(),
791 *dynsym_builder_.GetSection());
792 dynsym_builder_.GetStrTab()->GetSection()->sh_addr =
793 dynsym_builder_.GetStrTab()->GetSection()->sh_offset;
794 dynsym_builder_.GetStrTab()->GetSection()->sh_size = dynstr_.size();
795 dynsym_builder_.GetStrTab()->GetSection()->sh_link = dynsym_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700796
797 // Get the layout of the hash section
Ian Rogers0279ebb2014-10-08 17:27:48 -0700798 hash_builder_.GetSection()->sh_offset =
799 NextOffset<Elf_Word, Elf_Shdr>(*hash_builder_.GetSection(),
800 *dynsym_builder_.GetStrTab()->GetSection());
801 hash_builder_.GetSection()->sh_addr = hash_builder_.GetSection()->sh_offset;
802 hash_builder_.GetSection()->sh_size = hash_.size() * sizeof(Elf_Word);
803 hash_builder_.GetSection()->sh_link = hash_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700804
805 // Get the layout of the rodata section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700806 rodata_builder_.GetSection()->sh_offset =
807 NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(),
808 *hash_builder_.GetSection());
809 rodata_builder_.GetSection()->sh_addr = rodata_builder_.GetSection()->sh_offset;
810 rodata_builder_.GetSection()->sh_size = rodata_builder_.GetSize();
811 rodata_builder_.GetSection()->sh_link = rodata_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700812
813 // Get the layout of the text section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700814 text_builder_.GetSection()->sh_offset =
815 NextOffset<Elf_Word, Elf_Shdr>(*text_builder_.GetSection(),
816 *rodata_builder_.GetSection());
817 text_builder_.GetSection()->sh_addr = text_builder_.GetSection()->sh_offset;
818 text_builder_.GetSection()->sh_size = text_builder_.GetSize();
819 text_builder_.GetSection()->sh_link = text_builder_.GetLink();
820 CHECK_ALIGNED(rodata_builder_.GetSection()->sh_offset +
821 rodata_builder_.GetSection()->sh_size, kPageSize);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700822
823 // Get the layout of the dynamic section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700824 dynamic_builder_.GetSection()->sh_offset =
825 NextOffset<Elf_Word, Elf_Shdr>(*dynamic_builder_.GetSection(), *text_builder_.GetSection());
826 dynamic_builder_.GetSection()->sh_addr = dynamic_builder_.GetSection()->sh_offset;
827 dynamic_builder_.GetSection()->sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
828 dynamic_builder_.GetSection()->sh_link = dynamic_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700829
830 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700831 LOG(INFO) << "dynsym off=" << dynsym_builder_.GetSection()->sh_offset
832 << " dynsym size=" << dynsym_builder_.GetSection()->sh_size;
833 LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->GetSection()->sh_offset
834 << " dynstr size=" << dynsym_builder_.GetStrTab()->GetSection()->sh_size;
835 LOG(INFO) << "hash off=" << hash_builder_.GetSection()->sh_offset
836 << " hash size=" << hash_builder_.GetSection()->sh_size;
837 LOG(INFO) << "rodata off=" << rodata_builder_.GetSection()->sh_offset
838 << " rodata size=" << rodata_builder_.GetSection()->sh_size;
839 LOG(INFO) << "text off=" << text_builder_.GetSection()->sh_offset
840 << " text size=" << text_builder_.GetSection()->sh_size;
841 LOG(INFO) << "dynamic off=" << dynamic_builder_.GetSection()->sh_offset
842 << " dynamic size=" << dynamic_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700843 }
844
845 return true;
846 }
847
848 bool Write() {
Andreas Gampecc676072014-09-23 22:58:07 -0700849 std::vector<ElfFilePiece<Elf_Word>*> pieces;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700850 Elf_Shdr* prev = dynamic_builder_.GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700851 std::string strtab;
852
853 if (IncludingDebugSymbols()) {
854 // Setup .symtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700855 section_ptrs_.push_back(symtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700856 AssignSectionStr(&symtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700857 symtab_builder_.SetSectionIndex(section_index_);
858 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700859
860 // Setup .strtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700861 section_ptrs_.push_back(symtab_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700862 AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700863 symtab_builder_.GetStrTab()->SetSectionIndex(section_index_);
864 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700865
866 strtab = symtab_builder_.GenerateStrtab();
867 if (debug_logging_) {
868 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
869 << std::hex << " " << strtab.size();
870 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
871 << std::hex << " " << symtab_builder_.GetSize();
872 }
873 }
874
875 // Setup all the other sections.
876 for (ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder = other_builders_.data(),
877 *end = builder + other_builders_.size();
878 builder != end; ++builder) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700879 section_ptrs_.push_back(builder->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700880 AssignSectionStr(builder, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700881 builder->SetSectionIndex(section_index_);
882 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700883 }
884
885 // Setup shstrtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700886 section_ptrs_.push_back(shstrtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700887 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700888 shstrtab_builder_.SetSectionIndex(section_index_);
889 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700890
891 if (debug_logging_) {
892 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
893 << std::hex << " " << shstrtab_.size();
894 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
895 << std::hex << " " << section_ptrs_.size();
896 }
897
898 if (IncludingDebugSymbols()) {
899 // Get the layout of the symtab section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700900 symtab_builder_.GetSection()->sh_offset =
901 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetSection(),
902 *dynamic_builder_.GetSection());
903 symtab_builder_.GetSection()->sh_addr = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700904 // Add to leave space for the null symbol.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700905 symtab_builder_.GetSection()->sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
906 symtab_builder_.GetSection()->sh_link = symtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700907
908 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700909 symtab_builder_.GetStrTab()->GetSection()->sh_offset =
910 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetStrTab()->GetSection(),
911 *symtab_builder_.GetSection());
912 symtab_builder_.GetStrTab()->GetSection()->sh_addr = 0;
913 symtab_builder_.GetStrTab()->GetSection()->sh_size = strtab.size();
914 symtab_builder_.GetStrTab()->GetSection()->sh_link = symtab_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700915
Ian Rogers0279ebb2014-10-08 17:27:48 -0700916 prev = symtab_builder_.GetStrTab()->GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700917 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700918 LOG(INFO) << "symtab off=" << symtab_builder_.GetSection()->sh_offset
919 << " symtab size=" << symtab_builder_.GetSection()->sh_size;
920 LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->GetSection()->sh_offset
921 << " strtab size=" << symtab_builder_.GetStrTab()->GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700922 }
923 }
924
925 // Get the layout of the extra sections. (This will deal with the debug
926 // sections if they are there)
927 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700928 it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
929 it->GetSection()->sh_addr = 0;
930 it->GetSection()->sh_size = it->GetBuffer()->size();
931 it->GetSection()->sh_link = it->GetLink();
Andreas Gampecc676072014-09-23 22:58:07 -0700932
933 // We postpone adding an ElfFilePiece to keep the order in "pieces."
934
Ian Rogers0279ebb2014-10-08 17:27:48 -0700935 prev = it->GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700936 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700937 LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset
938 << " size=" << it->GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700939 }
940 }
941
942 // Get the layout of the shstrtab section
Ian Rogers0279ebb2014-10-08 17:27:48 -0700943 shstrtab_builder_.GetSection()->sh_offset =
944 NextOffset<Elf_Word, Elf_Shdr>(*shstrtab_builder_.GetSection(), *prev);
945 shstrtab_builder_.GetSection()->sh_addr = 0;
946 shstrtab_builder_.GetSection()->sh_size = shstrtab_.size();
947 shstrtab_builder_.GetSection()->sh_link = shstrtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700948 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700949 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.GetSection()->sh_offset
950 << " shstrtab size=" << shstrtab_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700951 }
952
953 // The section list comes after come after.
954 Elf_Word sections_offset = RoundUp(
Ian Rogers0279ebb2014-10-08 17:27:48 -0700955 shstrtab_builder_.GetSection()->sh_offset + shstrtab_builder_.GetSection()->sh_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700956 sizeof(Elf_Word));
957
958 // Setup the actual symbol arrays.
959 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -0700960 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700961 std::vector<Elf_Sym> symtab;
962 if (IncludingDebugSymbols()) {
963 symtab = symtab_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -0700964 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700965 }
966
967 // Setup the dynamic section.
968 // This will add the 2 values we cannot know until now time, namely the size
969 // and the soname_offset.
970 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
971 dynstr_soname_offset_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700972 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700973
974 // Finish setup of the program headers now that we know the layout of the
975 // whole file.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700976 Elf_Word load_r_size =
977 rodata_builder_.GetSection()->sh_offset + rodata_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700978 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
979 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700980 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700981
Ian Rogers0279ebb2014-10-08 17:27:48 -0700982 Elf_Word load_rx_size = text_builder_.GetSection()->sh_size;
983 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.GetSection()->sh_offset;
984 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.GetSection()->sh_offset;
985 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.GetSection()->sh_offset;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700986 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
987 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700988 program_headers_[PH_LOAD_R_X].p_align = text_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700989
Ian Rogers0279ebb2014-10-08 17:27:48 -0700990 program_headers_[PH_LOAD_RW_].p_offset = dynamic_builder_.GetSection()->sh_offset;
991 program_headers_[PH_LOAD_RW_].p_vaddr = dynamic_builder_.GetSection()->sh_offset;
992 program_headers_[PH_LOAD_RW_].p_paddr = dynamic_builder_.GetSection()->sh_offset;
993 program_headers_[PH_LOAD_RW_].p_filesz = dynamic_builder_.GetSection()->sh_size;
994 program_headers_[PH_LOAD_RW_].p_memsz = dynamic_builder_.GetSection()->sh_size;
995 program_headers_[PH_LOAD_RW_].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700996
Ian Rogers0279ebb2014-10-08 17:27:48 -0700997 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
998 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_offset;
999 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_offset;
1000 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1001 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1002 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001003
1004 // Finish setup of the Ehdr values.
1005 elf_header_.e_phoff = PHDR_OFFSET;
1006 elf_header_.e_shoff = sections_offset;
1007 elf_header_.e_phnum = PH_NUM;
1008 elf_header_.e_shnum = section_ptrs_.size();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001009 elf_header_.e_shstrndx = shstrtab_builder_.GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001010
1011 // Add the rest of the pieces to the list.
Andreas Gampecc676072014-09-23 22:58:07 -07001012 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_,
1013 sizeof(elf_header_)));
1014 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1015 &program_headers_, sizeof(program_headers_)));
1016 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001017 dynamic_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001018 dynamic.data(),
Ian Rogers0279ebb2014-10-08 17:27:48 -07001019 dynamic_builder_.GetSection()->sh_size));
1020 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001021 dynsym.data(),
1022 dynsym.size() * sizeof(Elf_Sym)));
1023 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001024 dynsym_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001025 dynstr_.c_str(), dynstr_.size()));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001026 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001027 hash_.data(),
1028 hash_.size() * sizeof(Elf_Word)));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001029 pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001030 oat_writer_));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001031 pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001032 oat_writer_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001033 if (IncludingDebugSymbols()) {
Andreas Gampecc676072014-09-23 22:58:07 -07001034 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001035 symtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001036 symtab.data(),
1037 symtab.size() * sizeof(Elf_Sym)));
1038 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001039 symtab_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001040 strtab.c_str(), strtab.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001041 }
Andreas Gampecc676072014-09-23 22:58:07 -07001042 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001043 shstrtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001044 &shstrtab_[0], shstrtab_.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001045 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
1046 // Just add all the sections in induvidually since they are all over the
1047 // place on the heap/stack.
1048 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
Andreas Gampecc676072014-09-23 22:58:07 -07001049 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off,
1050 section_ptrs_[i], sizeof(Elf_Shdr)));
1051 }
1052
1053 // Postponed debug info.
1054 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001055 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->GetName(), it->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001056 it->GetBuffer()->data(),
1057 it->GetBuffer()->size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001058 }
1059
1060 if (!WriteOutFile(pieces)) {
1061 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
Andreas Gampecc676072014-09-23 22:58:07 -07001062
1063 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001064 return false;
1065 }
1066
Andreas Gampecc676072014-09-23 22:58:07 -07001067 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001068 return true;
1069 }
1070
1071 // Adds the given raw section to the builder. This will copy it. The caller
1072 // is responsible for deallocating their copy.
1073 void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bld) {
1074 other_builders_.push_back(bld);
1075 }
1076
1077 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001078 void SetISA(InstructionSet isa) {
1079 switch (isa) {
1080 case kArm:
1081 // Fall through.
1082 case kThumb2: {
1083 elf_header_.e_machine = EM_ARM;
1084 elf_header_.e_flags = EF_ARM_EABI_VER5;
1085 break;
1086 }
1087 case kArm64: {
1088 elf_header_.e_machine = EM_AARCH64;
1089 elf_header_.e_flags = 0;
1090 break;
1091 }
1092 case kX86: {
1093 elf_header_.e_machine = EM_386;
1094 elf_header_.e_flags = 0;
1095 break;
1096 }
1097 case kX86_64: {
1098 elf_header_.e_machine = EM_X86_64;
1099 elf_header_.e_flags = 0;
1100 break;
1101 }
1102 case kMips: {
1103 elf_header_.e_machine = EM_MIPS;
1104 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1105 EF_MIPS_PIC |
1106 EF_MIPS_CPIC |
1107 EF_MIPS_ABI_O32 |
1108 EF_MIPS_ARCH_32R2);
1109 break;
1110 }
1111 default: {
1112 fatal_error_ = true;
1113 LOG(FATAL) << "Unknown instruction set: " << isa;
1114 break;
1115 }
1116 }
1117 }
1118
1119 void SetupEhdr() {
1120 memset(&elf_header_, 0, sizeof(elf_header_));
1121 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
1122 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
1123 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
1124 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
Tong Shen62d1ca32014-09-03 17:24:56 -07001125 elf_header_.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
1126 ? ELFCLASS32 : ELFCLASS64;;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001127 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
1128 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
1129 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
1130 elf_header_.e_ident[EI_ABIVERSION] = 0;
1131 elf_header_.e_type = ET_DYN;
1132 elf_header_.e_version = 1;
1133 elf_header_.e_entry = 0;
1134 elf_header_.e_ehsize = sizeof(Elf_Ehdr);
1135 elf_header_.e_phentsize = sizeof(Elf_Phdr);
1136 elf_header_.e_shentsize = sizeof(Elf_Shdr);
1137 elf_header_.e_phoff = sizeof(Elf_Ehdr);
1138 }
1139
1140 // Sets up a bunch of the required Dynamic Section entries.
1141 // Namely it will initialize all the mandatory ones that it can.
1142 // Specifically:
1143 // DT_HASH
1144 // DT_STRTAB
1145 // DT_SYMTAB
1146 // DT_SYMENT
1147 //
1148 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
1149 void SetupDynamic() {
1150 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
1151 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1152 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1153 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1154 }
1155
1156 // Sets up the basic dynamic symbols that are needed, namely all those we
1157 // can know already.
1158 //
1159 // Specifically adds:
1160 // oatdata
1161 // oatexec
1162 // oatlastword
1163 void SetupRequiredSymbols() {
1164 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1165 rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1166 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1167 text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1168 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1169 true, 4, STB_GLOBAL, STT_OBJECT);
1170 }
1171
Ian Rogers0279ebb2014-10-08 17:27:48 -07001172 void AssignSectionStr(ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* builder,
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001173 std::string* strtab) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001174 builder->GetSection()->sh_name = strtab->size();
1175 *strtab += builder->GetName();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001176 *strtab += '\0';
1177 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001178 LOG(INFO) << "adding section name \"" << builder->GetName() << "\" "
1179 << "to shstrtab at offset " << builder->GetSection()->sh_name;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001180 }
1181 }
1182
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001183
1184 // Write each of the pieces out to the file.
Andreas Gampecc676072014-09-23 22:58:07 -07001185 bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001186 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
Andreas Gampecc676072014-09-23 22:58:07 -07001187 if (!(*it)->Write(elf_file_)) {
1188 return false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001189 }
1190 }
1191 return true;
1192 }
1193
Ian Rogers0279ebb2014-10-08 17:27:48 -07001194 bool IncludingDebugSymbols() const {
1195 return add_symbols_ && symtab_builder_.GetSize() > 1;
1196 }
1197
1198 CodeOutput* const oat_writer_;
1199 File* const elf_file_;
1200 const bool add_symbols_;
1201 const bool debug_logging_;
1202
1203 bool fatal_error_ = false;
1204
1205 // What phdr is.
1206 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
1207 enum : uint8_t {
1208 PH_PHDR = 0,
1209 PH_LOAD_R__ = 1,
1210 PH_LOAD_R_X = 2,
1211 PH_LOAD_RW_ = 3,
1212 PH_DYNAMIC = 4,
1213 PH_NUM = 5,
1214 };
1215 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
1216 Elf_Phdr program_headers_[PH_NUM];
1217
1218 Elf_Ehdr elf_header_;
1219
1220 Elf_Shdr null_hdr_;
1221 std::string shstrtab_;
1222 // The index of the current section being built. The first being 1.
1223 uint32_t section_index_;
1224 std::string dynstr_;
1225 uint32_t dynstr_soname_offset_;
1226 std::vector<const Elf_Shdr*> section_ptrs_;
1227 std::vector<Elf_Word> hash_;
1228
1229 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> text_builder_;
1230 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> rodata_builder_;
1231 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> dynsym_builder_;
1232 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> symtab_builder_;
1233 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> hash_builder_;
1234 ElfDynamicBuilder<Elf_Word, Elf_Sword, Elf_Dyn, Elf_Shdr> dynamic_builder_;
1235 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> shstrtab_builder_;
1236 std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>> other_builders_;
1237
1238 DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001239};
1240
1241} // namespace art
1242
1243#endif // ART_COMPILER_ELF_BUILDER_H_