blob: 9ab3602606133a14e046243223b9349932662691 [file] [log] [blame]
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_ELF_BUILDER_H_
18#define ART_COMPILER_ELF_BUILDER_H_
19
Ian Rogersd582fa42014-11-05 23:46:43 -080020#include "arch/instruction_set.h"
Andreas Gampecc676072014-09-23 22:58:07 -070021#include "base/stl_util.h"
Ian Rogers0279ebb2014-10-08 17:27:48 -070022#include "base/value_object.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070023#include "buffered_output_stream.h"
24#include "elf_utils.h"
25#include "file_output_stream.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070026
27namespace art {
28
29template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -070030class ElfSectionBuilder : public ValueObject {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070031 public:
32 ElfSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
33 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link, Elf_Word info,
Ian Rogers0279ebb2014-10-08 17:27:48 -070034 Elf_Word align, Elf_Word entsize)
35 : section_index_(0), name_(sec_name), link_(link) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070036 memset(&section_, 0, sizeof(section_));
37 section_.sh_type = type;
38 section_.sh_flags = flags;
39 section_.sh_info = info;
40 section_.sh_addralign = align;
41 section_.sh_entsize = entsize;
42 }
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:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700497 bool DoActualWrite(File* elf_file ATTRIBUTE_UNUSED) OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700498 // 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,
Vladimir Marko5c42c292015-02-25 12:02:49 +0000541 Elf_Word bss_relative_offset,
542 Elf_Word bss_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700543 const bool add_symbols,
544 bool debug = false)
545 : oat_writer_(oat_writer),
546 elf_file_(elf_file),
547 add_symbols_(add_symbols),
548 debug_logging_(debug),
549 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
550 SHF_ALLOC | SHF_EXECINSTR),
551 rodata_builder_(".rodata", rodata_size, rodata_relative_offset, SHT_PROGBITS, SHF_ALLOC),
Vladimir Marko5c42c292015-02-25 12:02:49 +0000552 bss_builder_(".bss", bss_size, bss_relative_offset, SHT_NOBITS, SHF_ALLOC),
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700553 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
554 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
555 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0, sizeof(Elf_Word),
556 sizeof(Elf_Word)),
557 dynamic_builder_(".dynamic", &dynsym_builder_),
558 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
559 SetupEhdr();
560 SetupDynamic();
561 SetupRequiredSymbols();
562 SetISA(isa);
563 }
564 ~ElfBuilder() {}
565
Ian Rogers0279ebb2014-10-08 17:27:48 -0700566 const ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>& GetTextBuilder() const {
567 return text_builder_;
568 }
569
570 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* GetSymtabBuilder() {
571 return &symtab_builder_;
572 }
573
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700574 bool Init() {
Vladimir Marko5c42c292015-02-25 12:02:49 +0000575 // Since the .text section of an oat file contains relative references to .rodata
576 // and (optionally) .bss, we keep these 2 or 3 sections together. This creates
577 // a non-traditional layout where the .bss section is mapped independently of the
578 // .dynamic section and needs its own program header with LOAD RW.
579 //
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700580 // The basic layout of the elf file. Order may be different in final output.
581 // +-------------------------+
582 // | Elf_Ehdr |
583 // +-------------------------+
584 // | Elf_Phdr PHDR |
585 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata
586 // | Elf_Phdr LOAD R X | .text
Vladimir Marko5c42c292015-02-25 12:02:49 +0000587 // | Elf_Phdr LOAD RW | .bss (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700588 // | Elf_Phdr LOAD RW | .dynamic
589 // | Elf_Phdr DYNAMIC | .dynamic
590 // +-------------------------+
591 // | .dynsym |
592 // | Elf_Sym STN_UNDEF |
593 // | Elf_Sym oatdata |
594 // | Elf_Sym oatexec |
595 // | Elf_Sym oatlastword |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000596 // | Elf_Sym oatbss | (Optional)
597 // | Elf_Sym oatbsslastword | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700598 // +-------------------------+
599 // | .dynstr |
600 // | \0 |
601 // | oatdata\0 |
602 // | oatexec\0 |
603 // | oatlastword\0 |
604 // | boot.oat\0 |
605 // +-------------------------+
606 // | .hash |
607 // | Elf_Word nbucket = b |
608 // | Elf_Word nchain = c |
609 // | Elf_Word bucket[0] |
610 // | ... |
611 // | Elf_Word bucket[b - 1] |
612 // | Elf_Word chain[0] |
613 // | ... |
614 // | Elf_Word chain[c - 1] |
615 // +-------------------------+
616 // | .rodata |
617 // | oatdata..oatexec-4 |
618 // +-------------------------+
619 // | .text |
620 // | oatexec..oatlastword |
621 // +-------------------------+
622 // | .dynamic |
623 // | Elf_Dyn DT_SONAME |
624 // | Elf_Dyn DT_HASH |
625 // | Elf_Dyn DT_SYMTAB |
626 // | Elf_Dyn DT_SYMENT |
627 // | Elf_Dyn DT_STRTAB |
628 // | Elf_Dyn DT_STRSZ |
629 // | Elf_Dyn DT_NULL |
630 // +-------------------------+ (Optional)
631 // | .strtab | (Optional)
632 // | program symbol names | (Optional)
633 // +-------------------------+ (Optional)
634 // | .symtab | (Optional)
635 // | program symbols | (Optional)
636 // +-------------------------+
637 // | .shstrtab |
638 // | \0 |
639 // | .dynamic\0 |
640 // | .dynsym\0 |
641 // | .dynstr\0 |
642 // | .hash\0 |
643 // | .rodata\0 |
644 // | .text\0 |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000645 // | .bss\0 | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700646 // | .shstrtab\0 |
647 // | .symtab\0 | (Optional)
648 // | .strtab\0 | (Optional)
649 // | .debug_str\0 | (Optional)
650 // | .debug_info\0 | (Optional)
651 // | .eh_frame\0 | (Optional)
652 // | .debug_line\0 | (Optional)
653 // | .debug_abbrev\0 | (Optional)
654 // +-------------------------+ (Optional)
655 // | .debug_info | (Optional)
656 // +-------------------------+ (Optional)
657 // | .debug_abbrev | (Optional)
658 // +-------------------------+ (Optional)
659 // | .eh_frame | (Optional)
660 // +-------------------------+ (Optional)
661 // | .debug_line | (Optional)
662 // +-------------------------+ (Optional)
663 // | .debug_str | (Optional)
664 // +-------------------------+ (Optional)
665 // | Elf_Shdr NULL |
666 // | Elf_Shdr .dynsym |
667 // | Elf_Shdr .dynstr |
668 // | Elf_Shdr .hash |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700669 // | Elf_Shdr .rodata |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000670 // | Elf_Shdr .text |
671 // | Elf_Shdr .bss | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700672 // | Elf_Shdr .dynamic |
673 // | Elf_Shdr .shstrtab |
674 // | Elf_Shdr .debug_info | (Optional)
675 // | Elf_Shdr .debug_abbrev | (Optional)
676 // | Elf_Shdr .eh_frame | (Optional)
677 // | Elf_Shdr .debug_line | (Optional)
678 // | Elf_Shdr .debug_str | (Optional)
679 // +-------------------------+
680
681 if (fatal_error_) {
682 return false;
683 }
684 // Step 1. Figure out all the offsets.
685
686 if (debug_logging_) {
687 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
688 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
689 }
690
691 memset(&program_headers_, 0, sizeof(program_headers_));
692 program_headers_[PH_PHDR].p_type = PT_PHDR;
693 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET;
694 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET;
695 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET;
696 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_);
697 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_);
698 program_headers_[PH_PHDR].p_flags = PF_R;
699 program_headers_[PH_PHDR].p_align = sizeof(Elf_Word);
700
701 program_headers_[PH_LOAD_R__].p_type = PT_LOAD;
702 program_headers_[PH_LOAD_R__].p_offset = 0;
703 program_headers_[PH_LOAD_R__].p_vaddr = 0;
704 program_headers_[PH_LOAD_R__].p_paddr = 0;
705 program_headers_[PH_LOAD_R__].p_flags = PF_R;
706
707 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD;
708 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X;
709
Vladimir Marko5c42c292015-02-25 12:02:49 +0000710 program_headers_[PH_LOAD_RW_BSS].p_type = PT_LOAD;
711 program_headers_[PH_LOAD_RW_BSS].p_flags = PF_R | PF_W;
712
713 program_headers_[PH_LOAD_RW_DYNAMIC].p_type = PT_LOAD;
714 program_headers_[PH_LOAD_RW_DYNAMIC].p_flags = PF_R | PF_W;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700715
716 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC;
717 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W;
718
719 // Get the dynstr string.
720 dynstr_ = dynsym_builder_.GenerateStrtab();
721
722 // Add the SONAME to the dynstr.
723 dynstr_soname_offset_ = dynstr_.size();
724 std::string file_name(elf_file_->GetPath());
725 size_t directory_separator_pos = file_name.rfind('/');
726 if (directory_separator_pos != std::string::npos) {
727 file_name = file_name.substr(directory_separator_pos + 1);
728 }
729 dynstr_ += file_name;
730 dynstr_ += '\0';
731 if (debug_logging_) {
732 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size()
733 << std::hex << " " << dynstr_.size();
734 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
735 << std::hex << " " << dynsym_builder_.GetSize();
736 }
737
738 // Get the section header string table.
739 shstrtab_ += '\0';
740
741 // Setup sym_undef
742 memset(&null_hdr_, 0, sizeof(null_hdr_));
743 null_hdr_.sh_type = SHT_NULL;
744 null_hdr_.sh_link = SHN_UNDEF;
745 section_ptrs_.push_back(&null_hdr_);
746
747 section_index_ = 1;
748
749 // setup .dynsym
Ian Rogers0279ebb2014-10-08 17:27:48 -0700750 section_ptrs_.push_back(dynsym_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700751 AssignSectionStr(&dynsym_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700752 dynsym_builder_.SetSectionIndex(section_index_);
753 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700754
755 // Setup .dynstr
Ian Rogers0279ebb2014-10-08 17:27:48 -0700756 section_ptrs_.push_back(dynsym_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700757 AssignSectionStr(dynsym_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700758 dynsym_builder_.GetStrTab()->SetSectionIndex(section_index_);
759 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700760
761 // Setup .hash
Ian Rogers0279ebb2014-10-08 17:27:48 -0700762 section_ptrs_.push_back(hash_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700763 AssignSectionStr(&hash_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700764 hash_builder_.SetSectionIndex(section_index_);
765 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700766
767 // Setup .rodata
Ian Rogers0279ebb2014-10-08 17:27:48 -0700768 section_ptrs_.push_back(rodata_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700769 AssignSectionStr(&rodata_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700770 rodata_builder_.SetSectionIndex(section_index_);
771 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700772
773 // Setup .text
Ian Rogers0279ebb2014-10-08 17:27:48 -0700774 section_ptrs_.push_back(text_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700775 AssignSectionStr(&text_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700776 text_builder_.SetSectionIndex(section_index_);
777 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700778
Vladimir Marko5c42c292015-02-25 12:02:49 +0000779 // Setup .bss
780 if (bss_builder_.GetSize() != 0u) {
781 section_ptrs_.push_back(bss_builder_.GetSection());
782 AssignSectionStr(&bss_builder_, &shstrtab_);
783 bss_builder_.SetSectionIndex(section_index_);
784 section_index_++;
785 }
786
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700787 // Setup .dynamic
Ian Rogers0279ebb2014-10-08 17:27:48 -0700788 section_ptrs_.push_back(dynamic_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700789 AssignSectionStr(&dynamic_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700790 dynamic_builder_.SetSectionIndex(section_index_);
791 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700792
793 // Fill in the hash section.
794 hash_ = dynsym_builder_.GenerateHashContents();
795
796 if (debug_logging_) {
797 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
798 << std::hex << " " << hash_.size() * sizeof(Elf_Word);
799 }
800
801 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
802
803 // Get the layout in the sections.
804 //
805 // Get the layout of the dynsym section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700806 dynsym_builder_.GetSection()->sh_offset =
807 RoundUp(base_offset, dynsym_builder_.GetSection()->sh_addralign);
808 dynsym_builder_.GetSection()->sh_addr = dynsym_builder_.GetSection()->sh_offset;
809 dynsym_builder_.GetSection()->sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
810 dynsym_builder_.GetSection()->sh_link = dynsym_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700811
812 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700813 dynsym_builder_.GetStrTab()->GetSection()->sh_offset =
814 NextOffset<Elf_Word, Elf_Shdr>(*dynsym_builder_.GetStrTab()->GetSection(),
815 *dynsym_builder_.GetSection());
816 dynsym_builder_.GetStrTab()->GetSection()->sh_addr =
817 dynsym_builder_.GetStrTab()->GetSection()->sh_offset;
818 dynsym_builder_.GetStrTab()->GetSection()->sh_size = dynstr_.size();
819 dynsym_builder_.GetStrTab()->GetSection()->sh_link = dynsym_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700820
821 // Get the layout of the hash section
Ian Rogers0279ebb2014-10-08 17:27:48 -0700822 hash_builder_.GetSection()->sh_offset =
823 NextOffset<Elf_Word, Elf_Shdr>(*hash_builder_.GetSection(),
824 *dynsym_builder_.GetStrTab()->GetSection());
825 hash_builder_.GetSection()->sh_addr = hash_builder_.GetSection()->sh_offset;
826 hash_builder_.GetSection()->sh_size = hash_.size() * sizeof(Elf_Word);
827 hash_builder_.GetSection()->sh_link = hash_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700828
829 // Get the layout of the rodata section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700830 rodata_builder_.GetSection()->sh_offset =
831 NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(),
832 *hash_builder_.GetSection());
833 rodata_builder_.GetSection()->sh_addr = rodata_builder_.GetSection()->sh_offset;
834 rodata_builder_.GetSection()->sh_size = rodata_builder_.GetSize();
835 rodata_builder_.GetSection()->sh_link = rodata_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700836
837 // Get the layout of the text section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700838 text_builder_.GetSection()->sh_offset =
839 NextOffset<Elf_Word, Elf_Shdr>(*text_builder_.GetSection(),
840 *rodata_builder_.GetSection());
841 text_builder_.GetSection()->sh_addr = text_builder_.GetSection()->sh_offset;
842 text_builder_.GetSection()->sh_size = text_builder_.GetSize();
843 text_builder_.GetSection()->sh_link = text_builder_.GetLink();
844 CHECK_ALIGNED(rodata_builder_.GetSection()->sh_offset +
845 rodata_builder_.GetSection()->sh_size, kPageSize);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700846
Vladimir Marko5c42c292015-02-25 12:02:49 +0000847 // Get the layout of the .bss section.
848 bss_builder_.GetSection()->sh_offset =
849 NextOffset<Elf_Word, Elf_Shdr>(*bss_builder_.GetSection(),
850 *text_builder_.GetSection());
851 bss_builder_.GetSection()->sh_addr = bss_builder_.GetSection()->sh_offset;
852 bss_builder_.GetSection()->sh_size = bss_builder_.GetSize();
853 bss_builder_.GetSection()->sh_link = bss_builder_.GetLink();
854
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700855 // Get the layout of the dynamic section.
Vladimir Marko5c42c292015-02-25 12:02:49 +0000856 CHECK(IsAlignedParam(bss_builder_.GetSection()->sh_offset,
857 dynamic_builder_.GetSection()->sh_addralign));
858 dynamic_builder_.GetSection()->sh_offset = bss_builder_.GetSection()->sh_offset;
859 dynamic_builder_.GetSection()->sh_addr =
860 NextOffset<Elf_Word, Elf_Shdr>(*dynamic_builder_.GetSection(), *bss_builder_.GetSection());
Ian Rogers0279ebb2014-10-08 17:27:48 -0700861 dynamic_builder_.GetSection()->sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
862 dynamic_builder_.GetSection()->sh_link = dynamic_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700863
864 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700865 LOG(INFO) << "dynsym off=" << dynsym_builder_.GetSection()->sh_offset
866 << " dynsym size=" << dynsym_builder_.GetSection()->sh_size;
867 LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->GetSection()->sh_offset
868 << " dynstr size=" << dynsym_builder_.GetStrTab()->GetSection()->sh_size;
869 LOG(INFO) << "hash off=" << hash_builder_.GetSection()->sh_offset
870 << " hash size=" << hash_builder_.GetSection()->sh_size;
871 LOG(INFO) << "rodata off=" << rodata_builder_.GetSection()->sh_offset
872 << " rodata size=" << rodata_builder_.GetSection()->sh_size;
873 LOG(INFO) << "text off=" << text_builder_.GetSection()->sh_offset
874 << " text size=" << text_builder_.GetSection()->sh_size;
875 LOG(INFO) << "dynamic off=" << dynamic_builder_.GetSection()->sh_offset
876 << " dynamic size=" << dynamic_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700877 }
878
879 return true;
880 }
881
882 bool Write() {
Andreas Gampecc676072014-09-23 22:58:07 -0700883 std::vector<ElfFilePiece<Elf_Word>*> pieces;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700884 Elf_Shdr* prev = dynamic_builder_.GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700885 std::string strtab;
886
887 if (IncludingDebugSymbols()) {
888 // Setup .symtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700889 section_ptrs_.push_back(symtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700890 AssignSectionStr(&symtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700891 symtab_builder_.SetSectionIndex(section_index_);
892 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700893
894 // Setup .strtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700895 section_ptrs_.push_back(symtab_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700896 AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700897 symtab_builder_.GetStrTab()->SetSectionIndex(section_index_);
898 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700899
900 strtab = symtab_builder_.GenerateStrtab();
901 if (debug_logging_) {
902 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
903 << std::hex << " " << strtab.size();
904 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
905 << std::hex << " " << symtab_builder_.GetSize();
906 }
907 }
908
909 // Setup all the other sections.
910 for (ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder = other_builders_.data(),
911 *end = builder + other_builders_.size();
912 builder != end; ++builder) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700913 section_ptrs_.push_back(builder->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700914 AssignSectionStr(builder, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700915 builder->SetSectionIndex(section_index_);
916 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700917 }
918
919 // Setup shstrtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700920 section_ptrs_.push_back(shstrtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700921 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700922 shstrtab_builder_.SetSectionIndex(section_index_);
923 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700924
925 if (debug_logging_) {
926 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
927 << std::hex << " " << shstrtab_.size();
928 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
929 << std::hex << " " << section_ptrs_.size();
930 }
931
932 if (IncludingDebugSymbols()) {
933 // Get the layout of the symtab section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700934 symtab_builder_.GetSection()->sh_offset =
935 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetSection(),
936 *dynamic_builder_.GetSection());
937 symtab_builder_.GetSection()->sh_addr = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700938 // Add to leave space for the null symbol.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700939 symtab_builder_.GetSection()->sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
940 symtab_builder_.GetSection()->sh_link = symtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700941
942 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700943 symtab_builder_.GetStrTab()->GetSection()->sh_offset =
944 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetStrTab()->GetSection(),
945 *symtab_builder_.GetSection());
946 symtab_builder_.GetStrTab()->GetSection()->sh_addr = 0;
947 symtab_builder_.GetStrTab()->GetSection()->sh_size = strtab.size();
948 symtab_builder_.GetStrTab()->GetSection()->sh_link = symtab_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700949
Ian Rogers0279ebb2014-10-08 17:27:48 -0700950 prev = symtab_builder_.GetStrTab()->GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700951 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700952 LOG(INFO) << "symtab off=" << symtab_builder_.GetSection()->sh_offset
953 << " symtab size=" << symtab_builder_.GetSection()->sh_size;
954 LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->GetSection()->sh_offset
955 << " strtab size=" << symtab_builder_.GetStrTab()->GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700956 }
957 }
958
959 // Get the layout of the extra sections. (This will deal with the debug
960 // sections if they are there)
961 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700962 it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
963 it->GetSection()->sh_addr = 0;
964 it->GetSection()->sh_size = it->GetBuffer()->size();
965 it->GetSection()->sh_link = it->GetLink();
Andreas Gampecc676072014-09-23 22:58:07 -0700966
967 // We postpone adding an ElfFilePiece to keep the order in "pieces."
968
Ian Rogers0279ebb2014-10-08 17:27:48 -0700969 prev = it->GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700970 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700971 LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset
972 << " size=" << it->GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700973 }
974 }
975
976 // Get the layout of the shstrtab section
Ian Rogers0279ebb2014-10-08 17:27:48 -0700977 shstrtab_builder_.GetSection()->sh_offset =
978 NextOffset<Elf_Word, Elf_Shdr>(*shstrtab_builder_.GetSection(), *prev);
979 shstrtab_builder_.GetSection()->sh_addr = 0;
980 shstrtab_builder_.GetSection()->sh_size = shstrtab_.size();
981 shstrtab_builder_.GetSection()->sh_link = shstrtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700982 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700983 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.GetSection()->sh_offset
984 << " shstrtab size=" << shstrtab_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700985 }
986
987 // The section list comes after come after.
988 Elf_Word sections_offset = RoundUp(
Ian Rogers0279ebb2014-10-08 17:27:48 -0700989 shstrtab_builder_.GetSection()->sh_offset + shstrtab_builder_.GetSection()->sh_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700990 sizeof(Elf_Word));
991
992 // Setup the actual symbol arrays.
993 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -0700994 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700995 std::vector<Elf_Sym> symtab;
996 if (IncludingDebugSymbols()) {
997 symtab = symtab_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -0700998 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700999 }
1000
1001 // Setup the dynamic section.
1002 // This will add the 2 values we cannot know until now time, namely the size
1003 // and the soname_offset.
1004 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
1005 dynstr_soname_offset_);
Ian Rogers0279ebb2014-10-08 17:27:48 -07001006 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001007
1008 // Finish setup of the program headers now that we know the layout of the
1009 // whole file.
Ian Rogers0279ebb2014-10-08 17:27:48 -07001010 Elf_Word load_r_size =
1011 rodata_builder_.GetSection()->sh_offset + rodata_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001012 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
1013 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001014 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001015
Ian Rogers0279ebb2014-10-08 17:27:48 -07001016 Elf_Word load_rx_size = text_builder_.GetSection()->sh_size;
1017 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.GetSection()->sh_offset;
1018 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.GetSection()->sh_offset;
1019 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.GetSection()->sh_offset;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001020 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
1021 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001022 program_headers_[PH_LOAD_R_X].p_align = text_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001023
Vladimir Marko5c42c292015-02-25 12:02:49 +00001024 program_headers_[PH_LOAD_RW_BSS].p_offset = bss_builder_.GetSection()->sh_offset;
1025 program_headers_[PH_LOAD_RW_BSS].p_vaddr = bss_builder_.GetSection()->sh_offset;
1026 program_headers_[PH_LOAD_RW_BSS].p_paddr = bss_builder_.GetSection()->sh_offset;
1027 program_headers_[PH_LOAD_RW_BSS].p_filesz = 0;
1028 program_headers_[PH_LOAD_RW_BSS].p_memsz = bss_builder_.GetSection()->sh_size;
1029 program_headers_[PH_LOAD_RW_BSS].p_align = bss_builder_.GetSection()->sh_addralign;
1030
1031 program_headers_[PH_LOAD_RW_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
1032 program_headers_[PH_LOAD_RW_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_addr;
1033 program_headers_[PH_LOAD_RW_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_addr;
1034 program_headers_[PH_LOAD_RW_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1035 program_headers_[PH_LOAD_RW_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1036 program_headers_[PH_LOAD_RW_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001037
Ian Rogers0279ebb2014-10-08 17:27:48 -07001038 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001039 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_addr;
1040 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_addr;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001041 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1042 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1043 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001044
1045 // Finish setup of the Ehdr values.
1046 elf_header_.e_phoff = PHDR_OFFSET;
1047 elf_header_.e_shoff = sections_offset;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001048 elf_header_.e_phnum = (bss_builder_.GetSection()->sh_size != 0u) ? PH_NUM : PH_NUM - 1;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001049 elf_header_.e_shnum = section_ptrs_.size();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001050 elf_header_.e_shstrndx = shstrtab_builder_.GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001051
1052 // Add the rest of the pieces to the list.
Andreas Gampecc676072014-09-23 22:58:07 -07001053 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_,
1054 sizeof(elf_header_)));
Vladimir Marko5c42c292015-02-25 12:02:49 +00001055 if (bss_builder_.GetSection()->sh_size != 0u) {
1056 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1057 &program_headers_[0],
1058 elf_header_.e_phnum * sizeof(Elf_Phdr)));
1059 } else {
1060 // Skip PH_LOAD_RW_BSS.
1061 Elf_Word part1_size = PH_LOAD_RW_BSS * sizeof(Elf_Phdr);
1062 Elf_Word part2_size = (PH_NUM - PH_LOAD_RW_BSS - 1) * sizeof(Elf_Phdr);
1063 CHECK_EQ(part1_size + part2_size, elf_header_.e_phnum * sizeof(Elf_Phdr));
1064 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1065 &program_headers_[0], part1_size));
1066 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers part 2",
1067 PHDR_OFFSET + part1_size,
1068 &program_headers_[PH_LOAD_RW_BSS + 1],
1069 part2_size));
1070 }
Andreas Gampecc676072014-09-23 22:58:07 -07001071 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001072 dynamic_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001073 dynamic.data(),
Ian Rogers0279ebb2014-10-08 17:27:48 -07001074 dynamic_builder_.GetSection()->sh_size));
1075 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001076 dynsym.data(),
1077 dynsym.size() * sizeof(Elf_Sym)));
1078 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001079 dynsym_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001080 dynstr_.c_str(), dynstr_.size()));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001081 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001082 hash_.data(),
1083 hash_.size() * sizeof(Elf_Word)));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001084 pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001085 oat_writer_));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001086 pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001087 oat_writer_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001088 if (IncludingDebugSymbols()) {
Andreas Gampecc676072014-09-23 22:58:07 -07001089 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001090 symtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001091 symtab.data(),
1092 symtab.size() * sizeof(Elf_Sym)));
1093 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001094 symtab_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001095 strtab.c_str(), strtab.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001096 }
Andreas Gampecc676072014-09-23 22:58:07 -07001097 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001098 shstrtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001099 &shstrtab_[0], shstrtab_.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001100 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
1101 // Just add all the sections in induvidually since they are all over the
1102 // place on the heap/stack.
1103 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
Andreas Gampecc676072014-09-23 22:58:07 -07001104 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off,
1105 section_ptrs_[i], sizeof(Elf_Shdr)));
1106 }
1107
1108 // Postponed debug info.
1109 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001110 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->GetName(), it->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001111 it->GetBuffer()->data(),
1112 it->GetBuffer()->size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001113 }
1114
1115 if (!WriteOutFile(pieces)) {
1116 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
Andreas Gampecc676072014-09-23 22:58:07 -07001117
1118 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001119 return false;
1120 }
1121
Andreas Gampecc676072014-09-23 22:58:07 -07001122 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001123 return true;
1124 }
1125
1126 // Adds the given raw section to the builder. This will copy it. The caller
1127 // is responsible for deallocating their copy.
1128 void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bld) {
1129 other_builders_.push_back(bld);
1130 }
1131
1132 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001133 void SetISA(InstructionSet isa) {
1134 switch (isa) {
1135 case kArm:
1136 // Fall through.
1137 case kThumb2: {
1138 elf_header_.e_machine = EM_ARM;
1139 elf_header_.e_flags = EF_ARM_EABI_VER5;
1140 break;
1141 }
1142 case kArm64: {
1143 elf_header_.e_machine = EM_AARCH64;
1144 elf_header_.e_flags = 0;
1145 break;
1146 }
1147 case kX86: {
1148 elf_header_.e_machine = EM_386;
1149 elf_header_.e_flags = 0;
1150 break;
1151 }
1152 case kX86_64: {
1153 elf_header_.e_machine = EM_X86_64;
1154 elf_header_.e_flags = 0;
1155 break;
1156 }
1157 case kMips: {
1158 elf_header_.e_machine = EM_MIPS;
1159 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1160 EF_MIPS_PIC |
1161 EF_MIPS_CPIC |
1162 EF_MIPS_ABI_O32 |
1163 EF_MIPS_ARCH_32R2);
1164 break;
1165 }
Andreas Gampe57b34292015-01-14 15:45:59 -08001166 case kMips64: {
1167 elf_header_.e_machine = EM_MIPS;
1168 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1169 EF_MIPS_PIC |
1170 EF_MIPS_CPIC |
1171 EF_MIPS_ARCH_64R6);
1172 break;
1173 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001174 default: {
1175 fatal_error_ = true;
1176 LOG(FATAL) << "Unknown instruction set: " << isa;
1177 break;
1178 }
1179 }
1180 }
1181
1182 void SetupEhdr() {
1183 memset(&elf_header_, 0, sizeof(elf_header_));
1184 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
1185 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
1186 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
1187 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
Tong Shen62d1ca32014-09-03 17:24:56 -07001188 elf_header_.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
1189 ? ELFCLASS32 : ELFCLASS64;;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001190 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
1191 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
1192 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
1193 elf_header_.e_ident[EI_ABIVERSION] = 0;
1194 elf_header_.e_type = ET_DYN;
1195 elf_header_.e_version = 1;
1196 elf_header_.e_entry = 0;
1197 elf_header_.e_ehsize = sizeof(Elf_Ehdr);
1198 elf_header_.e_phentsize = sizeof(Elf_Phdr);
1199 elf_header_.e_shentsize = sizeof(Elf_Shdr);
1200 elf_header_.e_phoff = sizeof(Elf_Ehdr);
1201 }
1202
1203 // Sets up a bunch of the required Dynamic Section entries.
1204 // Namely it will initialize all the mandatory ones that it can.
1205 // Specifically:
1206 // DT_HASH
1207 // DT_STRTAB
1208 // DT_SYMTAB
1209 // DT_SYMENT
1210 //
1211 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
1212 void SetupDynamic() {
1213 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
1214 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1215 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1216 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1217 }
1218
1219 // Sets up the basic dynamic symbols that are needed, namely all those we
1220 // can know already.
1221 //
1222 // Specifically adds:
1223 // oatdata
1224 // oatexec
1225 // oatlastword
1226 void SetupRequiredSymbols() {
1227 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1228 rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1229 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1230 text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1231 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1232 true, 4, STB_GLOBAL, STT_OBJECT);
Vladimir Marko5c42c292015-02-25 12:02:49 +00001233 if (bss_builder_.GetSize() != 0u) {
1234 dynsym_builder_.AddSymbol("oatbss", &bss_builder_, 0, true,
1235 bss_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1236 dynsym_builder_.AddSymbol("oatbsslastword", &bss_builder_, bss_builder_.GetSize() - 4,
1237 true, 4, STB_GLOBAL, STT_OBJECT);
1238 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001239 }
1240
Ian Rogers0279ebb2014-10-08 17:27:48 -07001241 void AssignSectionStr(ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* builder,
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001242 std::string* strtab) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001243 builder->GetSection()->sh_name = strtab->size();
1244 *strtab += builder->GetName();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001245 *strtab += '\0';
1246 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001247 LOG(INFO) << "adding section name \"" << builder->GetName() << "\" "
1248 << "to shstrtab at offset " << builder->GetSection()->sh_name;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001249 }
1250 }
1251
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001252
1253 // Write each of the pieces out to the file.
Andreas Gampecc676072014-09-23 22:58:07 -07001254 bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001255 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
Andreas Gampecc676072014-09-23 22:58:07 -07001256 if (!(*it)->Write(elf_file_)) {
1257 return false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001258 }
1259 }
1260 return true;
1261 }
1262
Ian Rogers0279ebb2014-10-08 17:27:48 -07001263 bool IncludingDebugSymbols() const {
1264 return add_symbols_ && symtab_builder_.GetSize() > 1;
1265 }
1266
1267 CodeOutput* const oat_writer_;
1268 File* const elf_file_;
1269 const bool add_symbols_;
1270 const bool debug_logging_;
1271
1272 bool fatal_error_ = false;
1273
1274 // What phdr is.
1275 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
1276 enum : uint8_t {
Vladimir Marko5c42c292015-02-25 12:02:49 +00001277 PH_PHDR = 0,
1278 PH_LOAD_R__ = 1,
1279 PH_LOAD_R_X = 2,
1280 PH_LOAD_RW_BSS = 3,
1281 PH_LOAD_RW_DYNAMIC = 4,
1282 PH_DYNAMIC = 5,
1283 PH_NUM = 6,
Ian Rogers0279ebb2014-10-08 17:27:48 -07001284 };
1285 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
1286 Elf_Phdr program_headers_[PH_NUM];
1287
1288 Elf_Ehdr elf_header_;
1289
1290 Elf_Shdr null_hdr_;
1291 std::string shstrtab_;
1292 // The index of the current section being built. The first being 1.
1293 uint32_t section_index_;
1294 std::string dynstr_;
1295 uint32_t dynstr_soname_offset_;
1296 std::vector<const Elf_Shdr*> section_ptrs_;
1297 std::vector<Elf_Word> hash_;
1298
1299 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> text_builder_;
1300 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> rodata_builder_;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001301 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bss_builder_;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001302 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> dynsym_builder_;
1303 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> symtab_builder_;
1304 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> hash_builder_;
1305 ElfDynamicBuilder<Elf_Word, Elf_Sword, Elf_Dyn, Elf_Shdr> dynamic_builder_;
1306 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> shstrtab_builder_;
1307 std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>> other_builders_;
1308
1309 DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001310};
1311
1312} // namespace art
1313
1314#endif // ART_COMPILER_ELF_BUILDER_H_