blob: 124ed03c21d8dc725721a56e0d1f153a0a5a54d3 [file] [log] [blame]
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_ELF_BUILDER_H_
18#define ART_COMPILER_ELF_BUILDER_H_
19
Ian Rogersd582fa42014-11-05 23:46:43 -080020#include "arch/instruction_set.h"
Andreas Gampecc676072014-09-23 22:58:07 -070021#include "base/stl_util.h"
Ian Rogers0279ebb2014-10-08 17:27:48 -070022#include "base/value_object.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070023#include "buffered_output_stream.h"
24#include "elf_utils.h"
25#include "file_output_stream.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070026
27namespace art {
28
29template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -070030class ElfSectionBuilder : public ValueObject {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070031 public:
32 ElfSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
33 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link, Elf_Word info,
Ian Rogers0279ebb2014-10-08 17:27:48 -070034 Elf_Word align, Elf_Word entsize)
35 : section_index_(0), name_(sec_name), link_(link) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070036 memset(&section_, 0, sizeof(section_));
37 section_.sh_type = type;
38 section_.sh_flags = flags;
39 section_.sh_info = info;
40 section_.sh_addralign = align;
41 section_.sh_entsize = entsize;
42 }
Andreas Gampe758a8012015-04-03 21:28:42 -070043 ElfSectionBuilder(const ElfSectionBuilder&) = default;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070044
Ian Rogers0279ebb2014-10-08 17:27:48 -070045 ~ElfSectionBuilder() {}
Andreas Gampe54fc26c2014-09-04 21:47:42 -070046
Ian Rogers0279ebb2014-10-08 17:27:48 -070047 Elf_Word GetLink() const {
48 return (link_ != nullptr) ? link_->section_index_ : 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070049 }
50
Ian Rogers0279ebb2014-10-08 17:27:48 -070051 const Elf_Shdr* GetSection() const {
52 return &section_;
53 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -070054
Ian Rogers0279ebb2014-10-08 17:27:48 -070055 Elf_Shdr* GetSection() {
56 return &section_;
57 }
58
59 Elf_Word GetSectionIndex() const {
60 return section_index_;
61 }
62
63 void SetSectionIndex(Elf_Word section_index) {
64 section_index_ = section_index;
65 }
66
67 const std::string& GetName() const {
68 return name_;
69 }
70
71 private:
72 Elf_Shdr section_;
73 Elf_Word section_index_;
74 const std::string name_;
75 const ElfSectionBuilder* const link_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -070076};
77
78template <typename Elf_Word, typename Elf_Sword, typename Elf_Dyn, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -070079class ElfDynamicBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070080 public:
81 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un) {
82 if (tag == DT_NULL) {
83 return;
84 }
85 dynamics_.push_back({nullptr, tag, d_un});
86 }
87
88 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un,
Ian Rogers0279ebb2014-10-08 17:27:48 -070089 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -070090 if (tag == DT_NULL) {
91 return;
92 }
93 dynamics_.push_back({section, tag, d_un});
94 }
95
96 ElfDynamicBuilder(const std::string& sec_name,
97 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link)
98 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC,
99 link, 0, kPageSize, sizeof(Elf_Dyn)) {}
100 ~ElfDynamicBuilder() {}
101
Ian Rogers0279ebb2014-10-08 17:27:48 -0700102 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700103 // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
104 // these must be added when we actually put the file together because
105 // their values are very dependent on state.
106 return dynamics_.size() + 3;
107 }
108
109 // Create the actual dynamic vector. strsz should be the size of the .dynstr
110 // table and soname_off should be the offset of the soname in .dynstr.
111 // Since niether can be found prior to final layout we will wait until here
112 // to add them.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700113 std::vector<Elf_Dyn> GetDynamics(Elf_Word strsz, Elf_Word soname) const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700114 std::vector<Elf_Dyn> ret;
115 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700116 if (it->section_ != nullptr) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700117 // We are adding an address relative to a section.
118 ret.push_back(
Ian Rogers0279ebb2014-10-08 17:27:48 -0700119 {it->tag_, {it->off_ + it->section_->GetSection()->sh_addr}});
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700120 } else {
121 ret.push_back({it->tag_, {it->off_}});
122 }
123 }
124 ret.push_back({DT_STRSZ, {strsz}});
125 ret.push_back({DT_SONAME, {soname}});
126 ret.push_back({DT_NULL, {0}});
127 return ret;
128 }
129
Ian Rogers0279ebb2014-10-08 17:27:48 -0700130 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700131 struct ElfDynamicState {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700132 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700133 Elf_Sword tag_;
134 Elf_Word off_;
135 };
136 std::vector<ElfDynamicState> dynamics_;
137};
138
139template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700140class ElfRawSectionBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700141 public:
142 ElfRawSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
143 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* link, Elf_Word info,
144 Elf_Word align, Elf_Word entsize)
145 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, link, info, align,
Ian Rogers0279ebb2014-10-08 17:27:48 -0700146 entsize) {
147 }
Andreas Gampe758a8012015-04-03 21:28:42 -0700148 ElfRawSectionBuilder(const ElfRawSectionBuilder&) = default;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700149
Ian Rogers0279ebb2014-10-08 17:27:48 -0700150 ~ElfRawSectionBuilder() {}
151
152 std::vector<uint8_t>* GetBuffer() {
153 return &buf_;
154 }
155
156 void SetBuffer(const std::vector<uint8_t>& buf) {
157 buf_ = buf;
158 }
159
160 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700161 std::vector<uint8_t> buf_;
162};
163
164template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700165class ElfOatSectionBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700166 public:
167 ElfOatSectionBuilder(const std::string& sec_name, Elf_Word size, Elf_Word offset,
168 Elf_Word type, Elf_Word flags)
169 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, nullptr, 0, kPageSize,
Ian Rogers0279ebb2014-10-08 17:27:48 -0700170 0),
171 offset_(offset), size_(size) {
172 }
173
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700174 ~ElfOatSectionBuilder() {}
175
Ian Rogers0279ebb2014-10-08 17:27:48 -0700176 Elf_Word GetOffset() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700177 return offset_;
178 }
179
Ian Rogers0279ebb2014-10-08 17:27:48 -0700180 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700181 return size_;
182 }
183
Ian Rogers0279ebb2014-10-08 17:27:48 -0700184 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700185 // Offset of the content within the file.
186 Elf_Word offset_;
187 // Size of the content within the file.
188 Elf_Word size_;
189};
190
191static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
192 return ((binding) << 4) + ((type) & 0xf);
193}
194
195// from bionic
196static inline unsigned elfhash(const char *_name) {
197 const unsigned char *name = (const unsigned char *) _name;
198 unsigned h = 0, g;
199
200 while (*name) {
201 h = (h << 4) + *name++;
202 g = h & 0xf0000000;
203 h ^= g;
204 h ^= g >> 24;
205 }
206 return h;
207}
208
209template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Sym,
210 typename Elf_Shdr>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700211class ElfSymtabBuilder FINAL : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700212 public:
213 // Add a symbol with given name to this symtab. The symbol refers to
214 // 'relative_addr' within the given section and has the given attributes.
215 void AddSymbol(const std::string& name,
216 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section,
217 Elf_Addr addr,
218 bool is_relative,
219 Elf_Word size,
220 uint8_t binding,
221 uint8_t type,
222 uint8_t other = 0) {
223 CHECK(section);
224 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
225 MakeStInfo(binding, type), other, 0};
226 symbols_.push_back(state);
227 }
228
229 ElfSymtabBuilder(const std::string& sec_name, Elf_Word type,
230 const std::string& str_name, Elf_Word str_type, bool alloc)
231 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, ((alloc) ? SHF_ALLOC : 0U),
232 &strtab_, 0, sizeof(Elf_Word),
233 sizeof(Elf_Sym)), str_name_(str_name),
234 str_type_(str_type),
235 strtab_(str_name,
236 str_type,
237 ((alloc) ? SHF_ALLOC : 0U),
Ian Rogers0279ebb2014-10-08 17:27:48 -0700238 nullptr, 0, 1, 1) {
239 }
240
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700241 ~ElfSymtabBuilder() {}
242
Ian Rogers0279ebb2014-10-08 17:27:48 -0700243 std::vector<Elf_Word> GenerateHashContents() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700244 // Here is how The ELF hash table works.
245 // There are 3 arrays to worry about.
246 // * The symbol table where the symbol information is.
247 // * The bucket array which is an array of indexes into the symtab and chain.
248 // * The chain array which is also an array of indexes into the symtab and chain.
249 //
250 // Lets say the state is something like this.
251 // +--------+ +--------+ +-----------+
252 // | symtab | | bucket | | chain |
253 // | null | | 1 | | STN_UNDEF |
254 // | <sym1> | | 4 | | 2 |
255 // | <sym2> | | | | 5 |
256 // | <sym3> | | | | STN_UNDEF |
257 // | <sym4> | | | | 3 |
258 // | <sym5> | | | | STN_UNDEF |
259 // +--------+ +--------+ +-----------+
260 //
261 // The lookup process (in python psudocode) is
262 //
263 // def GetSym(name):
264 // # NB STN_UNDEF == 0
265 // indx = bucket[elfhash(name) % num_buckets]
266 // while indx != STN_UNDEF:
267 // if GetSymbolName(symtab[indx]) == name:
268 // return symtab[indx]
269 // indx = chain[indx]
270 // return SYMBOL_NOT_FOUND
271 //
272 // Between bucket and chain arrays every symtab index must be present exactly
273 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
274
275 // Select number of buckets.
276 // This is essentially arbitrary.
277 Elf_Word nbuckets;
278 Elf_Word chain_size = GetSize();
279 if (symbols_.size() < 8) {
280 nbuckets = 2;
281 } else if (symbols_.size() < 32) {
282 nbuckets = 4;
283 } else if (symbols_.size() < 256) {
284 nbuckets = 16;
285 } else {
286 // Have about 32 ids per bucket.
287 nbuckets = RoundUp(symbols_.size()/32, 2);
288 }
289 std::vector<Elf_Word> hash;
290 hash.push_back(nbuckets);
291 hash.push_back(chain_size);
292 uint32_t bucket_offset = hash.size();
293 uint32_t chain_offset = bucket_offset + nbuckets;
294 hash.resize(hash.size() + nbuckets + chain_size, 0);
295
296 Elf_Word* buckets = hash.data() + bucket_offset;
297 Elf_Word* chain = hash.data() + chain_offset;
298
299 // Set up the actual hash table.
300 for (Elf_Word i = 0; i < symbols_.size(); i++) {
301 // Add 1 since we need to have the null symbol that is not in the symbols
302 // list.
303 Elf_Word index = i + 1;
304 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
305 if (buckets[hash_val] == 0) {
306 buckets[hash_val] = index;
307 } else {
308 hash_val = buckets[hash_val];
309 CHECK_LT(hash_val, chain_size);
310 while (chain[hash_val] != 0) {
311 hash_val = chain[hash_val];
312 CHECK_LT(hash_val, chain_size);
313 }
314 chain[hash_val] = index;
315 // Check for loops. Works because if this is non-empty then there must be
316 // another cell which already contains the same symbol index as this one,
317 // which means some symbol has more then one name, which isn't allowed.
318 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
319 }
320 }
321
322 return hash;
323 }
324
325 std::string GenerateStrtab() {
326 std::string tab;
327 tab += '\0';
328 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
329 it->name_idx_ = tab.size();
330 tab += it->name_;
331 tab += '\0';
332 }
Ian Rogers0279ebb2014-10-08 17:27:48 -0700333 strtab_.GetSection()->sh_size = tab.size();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700334 return tab;
335 }
336
337 std::vector<Elf_Sym> GenerateSymtab() {
338 std::vector<Elf_Sym> ret;
339 Elf_Sym undef_sym;
340 memset(&undef_sym, 0, sizeof(undef_sym));
341 undef_sym.st_shndx = SHN_UNDEF;
342 ret.push_back(undef_sym);
343
344 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
345 Elf_Sym sym;
346 memset(&sym, 0, sizeof(sym));
347 sym.st_name = it->name_idx_;
348 if (it->is_relative_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700349 sym.st_value = it->addr_ + it->section_->GetSection()->sh_offset;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700350 } else {
351 sym.st_value = it->addr_;
352 }
353 sym.st_size = it->size_;
354 sym.st_other = it->other_;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700355 sym.st_shndx = it->section_->GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700356 sym.st_info = it->info_;
357
358 ret.push_back(sym);
359 }
360 return ret;
361 }
362
Ian Rogers0279ebb2014-10-08 17:27:48 -0700363 Elf_Word GetSize() const {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700364 // 1 is for the implicit NULL symbol.
365 return symbols_.size() + 1;
366 }
367
368 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* GetStrTab() {
369 return &strtab_;
370 }
371
Ian Rogers0279ebb2014-10-08 17:27:48 -0700372 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700373 struct ElfSymbolState {
374 const std::string name_;
375 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_;
376 Elf_Addr addr_;
377 Elf_Word size_;
378 bool is_relative_;
379 uint8_t info_;
380 uint8_t other_;
381 // Used during Write() to temporarially hold name index in the strtab.
382 Elf_Word name_idx_;
383 };
384
385 // Information for the strsym for dynstr sections.
386 const std::string str_name_;
387 Elf_Word str_type_;
388 // The symbols in the same order they will be in the symbol table.
389 std::vector<ElfSymbolState> symbols_;
390 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> strtab_;
391};
392
Andreas Gampecc676072014-09-23 22:58:07 -0700393template <typename Elf_Word>
394class ElfFilePiece {
395 public:
396 virtual ~ElfFilePiece() {}
397
398 virtual bool Write(File* elf_file) {
399 if (static_cast<off_t>(offset_) != lseek(elf_file->Fd(), offset_, SEEK_SET)) {
400 PLOG(ERROR) << "Failed to seek to " << GetDescription() << " offset " << offset_ << " for "
401 << elf_file->GetPath();
402 return false;
403 }
404
405 return DoActualWrite(elf_file);
406 }
407
408 static bool Compare(ElfFilePiece* a, ElfFilePiece* b) {
409 return a->offset_ < b->offset_;
410 }
411
412 protected:
413 explicit ElfFilePiece(Elf_Word offset) : offset_(offset) {}
414
Ian Rogers0279ebb2014-10-08 17:27:48 -0700415 Elf_Word GetOffset() const {
416 return offset_;
417 }
418
419 virtual const char* GetDescription() const = 0;
Andreas Gampecc676072014-09-23 22:58:07 -0700420 virtual bool DoActualWrite(File* elf_file) = 0;
421
Ian Rogers0279ebb2014-10-08 17:27:48 -0700422 private:
423 const Elf_Word offset_;
424
425 DISALLOW_COPY_AND_ASSIGN(ElfFilePiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700426};
427
428template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700429class ElfFileMemoryPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700430 public:
431 ElfFileMemoryPiece(const std::string& name, Elf_Word offset, const void* data, Elf_Word size)
432 : ElfFilePiece<Elf_Word>(offset), dbg_name_(name), data_(data), size_(size) {}
433
Ian Rogers0279ebb2014-10-08 17:27:48 -0700434 protected:
Andreas Gampecc676072014-09-23 22:58:07 -0700435 bool DoActualWrite(File* elf_file) OVERRIDE {
436 DCHECK(data_ != nullptr || size_ == 0U) << dbg_name_ << " " << size_;
437
438 if (!elf_file->WriteFully(data_, size_)) {
439 PLOG(ERROR) << "Failed to write " << dbg_name_ << " for " << elf_file->GetPath();
440 return false;
441 }
442
443 return true;
444 }
445
Ian Rogers0279ebb2014-10-08 17:27:48 -0700446 const char* GetDescription() const OVERRIDE {
447 return dbg_name_.c_str();
Andreas Gampecc676072014-09-23 22:58:07 -0700448 }
449
450 private:
451 const std::string& dbg_name_;
452 const void *data_;
453 Elf_Word size_;
454};
455
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700456class CodeOutput {
457 public:
Vladimir Markof4da6752014-08-01 19:04:18 +0100458 virtual void SetCodeOffset(size_t offset) = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700459 virtual bool Write(OutputStream* out) = 0;
460 virtual ~CodeOutput() {}
461};
462
Andreas Gampecc676072014-09-23 22:58:07 -0700463template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700464class ElfFileRodataPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700465 public:
466 ElfFileRodataPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
467 output_(output) {}
468
Ian Rogers0279ebb2014-10-08 17:27:48 -0700469 protected:
Andreas Gampecc676072014-09-23 22:58:07 -0700470 bool DoActualWrite(File* elf_file) OVERRIDE {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700471 output_->SetCodeOffset(this->GetOffset());
Andreas Gampecc676072014-09-23 22:58:07 -0700472 std::unique_ptr<BufferedOutputStream> output_stream(
473 new BufferedOutputStream(new FileOutputStream(elf_file)));
474 if (!output_->Write(output_stream.get())) {
475 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file->GetPath();
476 return false;
477 }
478
479 return true;
480 }
481
Ian Rogers0279ebb2014-10-08 17:27:48 -0700482 const char* GetDescription() const OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700483 return ".rodata";
484 }
485
486 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700487 CodeOutput* const output_;
488
489 DISALLOW_COPY_AND_ASSIGN(ElfFileRodataPiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700490};
491
492template <typename Elf_Word>
Ian Rogers0279ebb2014-10-08 17:27:48 -0700493class ElfFileOatTextPiece FINAL : public ElfFilePiece<Elf_Word> {
Andreas Gampecc676072014-09-23 22:58:07 -0700494 public:
495 ElfFileOatTextPiece(Elf_Word offset, CodeOutput* output) : ElfFilePiece<Elf_Word>(offset),
496 output_(output) {}
497
Ian Rogers0279ebb2014-10-08 17:27:48 -0700498 protected:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700499 bool DoActualWrite(File* elf_file ATTRIBUTE_UNUSED) OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700500 // All data is written by the ElfFileRodataPiece right now, as the oat writer writes in one
501 // piece. This is for future flexibility.
502 UNUSED(output_);
503 return true;
504 }
505
Ian Rogers0279ebb2014-10-08 17:27:48 -0700506 const char* GetDescription() const OVERRIDE {
Andreas Gampecc676072014-09-23 22:58:07 -0700507 return ".text";
508 }
509
510 private:
Ian Rogers0279ebb2014-10-08 17:27:48 -0700511 CodeOutput* const output_;
512
513 DISALLOW_COPY_AND_ASSIGN(ElfFileOatTextPiece);
Andreas Gampecc676072014-09-23 22:58:07 -0700514};
515
516template <typename Elf_Word>
517static bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces, File* elf_file) {
518 // TODO It would be nice if this checked for overlap.
519 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
520 if (!(*it)->Write(elf_file)) {
521 return false;
522 }
523 }
524 return true;
525}
526
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700527template <typename Elf_Word, typename Elf_Shdr>
528static inline constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) {
529 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
530}
531
532template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Dyn,
533 typename Elf_Sym, typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr>
534class ElfBuilder FINAL {
535 public:
536 ElfBuilder(CodeOutput* oat_writer,
537 File* elf_file,
538 InstructionSet isa,
539 Elf_Word rodata_relative_offset,
540 Elf_Word rodata_size,
541 Elf_Word text_relative_offset,
542 Elf_Word text_size,
Vladimir Marko5c42c292015-02-25 12:02:49 +0000543 Elf_Word bss_relative_offset,
544 Elf_Word bss_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700545 const bool add_symbols,
546 bool debug = false)
547 : oat_writer_(oat_writer),
548 elf_file_(elf_file),
549 add_symbols_(add_symbols),
550 debug_logging_(debug),
551 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
552 SHF_ALLOC | SHF_EXECINSTR),
553 rodata_builder_(".rodata", rodata_size, rodata_relative_offset, SHT_PROGBITS, SHF_ALLOC),
Vladimir Marko5c42c292015-02-25 12:02:49 +0000554 bss_builder_(".bss", bss_size, bss_relative_offset, SHT_NOBITS, SHF_ALLOC),
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700555 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
556 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
557 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0, sizeof(Elf_Word),
558 sizeof(Elf_Word)),
559 dynamic_builder_(".dynamic", &dynsym_builder_),
560 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
561 SetupEhdr();
562 SetupDynamic();
563 SetupRequiredSymbols();
564 SetISA(isa);
565 }
566 ~ElfBuilder() {}
567
Ian Rogers0279ebb2014-10-08 17:27:48 -0700568 const ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>& GetTextBuilder() const {
569 return text_builder_;
570 }
571
572 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* GetSymtabBuilder() {
573 return &symtab_builder_;
574 }
575
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700576 bool Init() {
Vladimir Marko5c42c292015-02-25 12:02:49 +0000577 // Since the .text section of an oat file contains relative references to .rodata
578 // and (optionally) .bss, we keep these 2 or 3 sections together. This creates
579 // a non-traditional layout where the .bss section is mapped independently of the
580 // .dynamic section and needs its own program header with LOAD RW.
581 //
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700582 // The basic layout of the elf file. Order may be different in final output.
583 // +-------------------------+
584 // | Elf_Ehdr |
585 // +-------------------------+
586 // | Elf_Phdr PHDR |
587 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata
588 // | Elf_Phdr LOAD R X | .text
Vladimir Marko5c42c292015-02-25 12:02:49 +0000589 // | Elf_Phdr LOAD RW | .bss (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700590 // | Elf_Phdr LOAD RW | .dynamic
591 // | Elf_Phdr DYNAMIC | .dynamic
592 // +-------------------------+
593 // | .dynsym |
594 // | Elf_Sym STN_UNDEF |
595 // | Elf_Sym oatdata |
596 // | Elf_Sym oatexec |
597 // | Elf_Sym oatlastword |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000598 // | Elf_Sym oatbss | (Optional)
599 // | Elf_Sym oatbsslastword | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700600 // +-------------------------+
601 // | .dynstr |
602 // | \0 |
603 // | oatdata\0 |
604 // | oatexec\0 |
605 // | oatlastword\0 |
606 // | boot.oat\0 |
607 // +-------------------------+
608 // | .hash |
609 // | Elf_Word nbucket = b |
610 // | Elf_Word nchain = c |
611 // | Elf_Word bucket[0] |
612 // | ... |
613 // | Elf_Word bucket[b - 1] |
614 // | Elf_Word chain[0] |
615 // | ... |
616 // | Elf_Word chain[c - 1] |
617 // +-------------------------+
618 // | .rodata |
619 // | oatdata..oatexec-4 |
620 // +-------------------------+
621 // | .text |
622 // | oatexec..oatlastword |
623 // +-------------------------+
624 // | .dynamic |
625 // | Elf_Dyn DT_SONAME |
626 // | Elf_Dyn DT_HASH |
627 // | Elf_Dyn DT_SYMTAB |
628 // | Elf_Dyn DT_SYMENT |
629 // | Elf_Dyn DT_STRTAB |
630 // | Elf_Dyn DT_STRSZ |
631 // | Elf_Dyn DT_NULL |
632 // +-------------------------+ (Optional)
633 // | .strtab | (Optional)
634 // | program symbol names | (Optional)
635 // +-------------------------+ (Optional)
636 // | .symtab | (Optional)
637 // | program symbols | (Optional)
638 // +-------------------------+
639 // | .shstrtab |
640 // | \0 |
641 // | .dynamic\0 |
642 // | .dynsym\0 |
643 // | .dynstr\0 |
644 // | .hash\0 |
645 // | .rodata\0 |
646 // | .text\0 |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000647 // | .bss\0 | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700648 // | .shstrtab\0 |
649 // | .symtab\0 | (Optional)
650 // | .strtab\0 | (Optional)
651 // | .debug_str\0 | (Optional)
652 // | .debug_info\0 | (Optional)
653 // | .eh_frame\0 | (Optional)
654 // | .debug_line\0 | (Optional)
655 // | .debug_abbrev\0 | (Optional)
656 // +-------------------------+ (Optional)
657 // | .debug_info | (Optional)
658 // +-------------------------+ (Optional)
659 // | .debug_abbrev | (Optional)
660 // +-------------------------+ (Optional)
661 // | .eh_frame | (Optional)
662 // +-------------------------+ (Optional)
663 // | .debug_line | (Optional)
664 // +-------------------------+ (Optional)
665 // | .debug_str | (Optional)
666 // +-------------------------+ (Optional)
667 // | Elf_Shdr NULL |
668 // | Elf_Shdr .dynsym |
669 // | Elf_Shdr .dynstr |
670 // | Elf_Shdr .hash |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700671 // | Elf_Shdr .rodata |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000672 // | Elf_Shdr .text |
673 // | Elf_Shdr .bss | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700674 // | Elf_Shdr .dynamic |
675 // | Elf_Shdr .shstrtab |
676 // | Elf_Shdr .debug_info | (Optional)
677 // | Elf_Shdr .debug_abbrev | (Optional)
678 // | Elf_Shdr .eh_frame | (Optional)
679 // | Elf_Shdr .debug_line | (Optional)
680 // | Elf_Shdr .debug_str | (Optional)
681 // +-------------------------+
682
683 if (fatal_error_) {
684 return false;
685 }
686 // Step 1. Figure out all the offsets.
687
688 if (debug_logging_) {
689 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
690 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
691 }
692
693 memset(&program_headers_, 0, sizeof(program_headers_));
694 program_headers_[PH_PHDR].p_type = PT_PHDR;
695 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET;
696 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET;
697 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET;
698 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_);
699 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_);
700 program_headers_[PH_PHDR].p_flags = PF_R;
701 program_headers_[PH_PHDR].p_align = sizeof(Elf_Word);
702
703 program_headers_[PH_LOAD_R__].p_type = PT_LOAD;
704 program_headers_[PH_LOAD_R__].p_offset = 0;
705 program_headers_[PH_LOAD_R__].p_vaddr = 0;
706 program_headers_[PH_LOAD_R__].p_paddr = 0;
707 program_headers_[PH_LOAD_R__].p_flags = PF_R;
708
709 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD;
710 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X;
711
Vladimir Marko5c42c292015-02-25 12:02:49 +0000712 program_headers_[PH_LOAD_RW_BSS].p_type = PT_LOAD;
713 program_headers_[PH_LOAD_RW_BSS].p_flags = PF_R | PF_W;
714
715 program_headers_[PH_LOAD_RW_DYNAMIC].p_type = PT_LOAD;
716 program_headers_[PH_LOAD_RW_DYNAMIC].p_flags = PF_R | PF_W;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700717
718 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC;
719 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W;
720
721 // Get the dynstr string.
722 dynstr_ = dynsym_builder_.GenerateStrtab();
723
724 // Add the SONAME to the dynstr.
725 dynstr_soname_offset_ = dynstr_.size();
726 std::string file_name(elf_file_->GetPath());
727 size_t directory_separator_pos = file_name.rfind('/');
728 if (directory_separator_pos != std::string::npos) {
729 file_name = file_name.substr(directory_separator_pos + 1);
730 }
731 dynstr_ += file_name;
732 dynstr_ += '\0';
733 if (debug_logging_) {
734 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size()
735 << std::hex << " " << dynstr_.size();
736 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
737 << std::hex << " " << dynsym_builder_.GetSize();
738 }
739
740 // Get the section header string table.
741 shstrtab_ += '\0';
742
743 // Setup sym_undef
744 memset(&null_hdr_, 0, sizeof(null_hdr_));
745 null_hdr_.sh_type = SHT_NULL;
746 null_hdr_.sh_link = SHN_UNDEF;
747 section_ptrs_.push_back(&null_hdr_);
748
749 section_index_ = 1;
750
751 // setup .dynsym
Ian Rogers0279ebb2014-10-08 17:27:48 -0700752 section_ptrs_.push_back(dynsym_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700753 AssignSectionStr(&dynsym_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700754 dynsym_builder_.SetSectionIndex(section_index_);
755 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700756
757 // Setup .dynstr
Ian Rogers0279ebb2014-10-08 17:27:48 -0700758 section_ptrs_.push_back(dynsym_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700759 AssignSectionStr(dynsym_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700760 dynsym_builder_.GetStrTab()->SetSectionIndex(section_index_);
761 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700762
763 // Setup .hash
Ian Rogers0279ebb2014-10-08 17:27:48 -0700764 section_ptrs_.push_back(hash_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700765 AssignSectionStr(&hash_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700766 hash_builder_.SetSectionIndex(section_index_);
767 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700768
769 // Setup .rodata
Ian Rogers0279ebb2014-10-08 17:27:48 -0700770 section_ptrs_.push_back(rodata_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700771 AssignSectionStr(&rodata_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700772 rodata_builder_.SetSectionIndex(section_index_);
773 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700774
775 // Setup .text
Ian Rogers0279ebb2014-10-08 17:27:48 -0700776 section_ptrs_.push_back(text_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700777 AssignSectionStr(&text_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700778 text_builder_.SetSectionIndex(section_index_);
779 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700780
Vladimir Marko5c42c292015-02-25 12:02:49 +0000781 // Setup .bss
782 if (bss_builder_.GetSize() != 0u) {
783 section_ptrs_.push_back(bss_builder_.GetSection());
784 AssignSectionStr(&bss_builder_, &shstrtab_);
785 bss_builder_.SetSectionIndex(section_index_);
786 section_index_++;
787 }
788
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700789 // Setup .dynamic
Ian Rogers0279ebb2014-10-08 17:27:48 -0700790 section_ptrs_.push_back(dynamic_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700791 AssignSectionStr(&dynamic_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700792 dynamic_builder_.SetSectionIndex(section_index_);
793 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700794
795 // Fill in the hash section.
796 hash_ = dynsym_builder_.GenerateHashContents();
797
798 if (debug_logging_) {
799 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
800 << std::hex << " " << hash_.size() * sizeof(Elf_Word);
801 }
802
803 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
804
805 // Get the layout in the sections.
806 //
807 // Get the layout of the dynsym section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700808 dynsym_builder_.GetSection()->sh_offset =
809 RoundUp(base_offset, dynsym_builder_.GetSection()->sh_addralign);
810 dynsym_builder_.GetSection()->sh_addr = dynsym_builder_.GetSection()->sh_offset;
811 dynsym_builder_.GetSection()->sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
812 dynsym_builder_.GetSection()->sh_link = dynsym_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700813
814 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700815 dynsym_builder_.GetStrTab()->GetSection()->sh_offset =
816 NextOffset<Elf_Word, Elf_Shdr>(*dynsym_builder_.GetStrTab()->GetSection(),
817 *dynsym_builder_.GetSection());
818 dynsym_builder_.GetStrTab()->GetSection()->sh_addr =
819 dynsym_builder_.GetStrTab()->GetSection()->sh_offset;
820 dynsym_builder_.GetStrTab()->GetSection()->sh_size = dynstr_.size();
821 dynsym_builder_.GetStrTab()->GetSection()->sh_link = dynsym_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700822
823 // Get the layout of the hash section
Ian Rogers0279ebb2014-10-08 17:27:48 -0700824 hash_builder_.GetSection()->sh_offset =
825 NextOffset<Elf_Word, Elf_Shdr>(*hash_builder_.GetSection(),
826 *dynsym_builder_.GetStrTab()->GetSection());
827 hash_builder_.GetSection()->sh_addr = hash_builder_.GetSection()->sh_offset;
828 hash_builder_.GetSection()->sh_size = hash_.size() * sizeof(Elf_Word);
829 hash_builder_.GetSection()->sh_link = hash_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700830
831 // Get the layout of the rodata section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700832 rodata_builder_.GetSection()->sh_offset =
833 NextOffset<Elf_Word, Elf_Shdr>(*rodata_builder_.GetSection(),
834 *hash_builder_.GetSection());
835 rodata_builder_.GetSection()->sh_addr = rodata_builder_.GetSection()->sh_offset;
836 rodata_builder_.GetSection()->sh_size = rodata_builder_.GetSize();
837 rodata_builder_.GetSection()->sh_link = rodata_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700838
839 // Get the layout of the text section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700840 text_builder_.GetSection()->sh_offset =
841 NextOffset<Elf_Word, Elf_Shdr>(*text_builder_.GetSection(),
842 *rodata_builder_.GetSection());
843 text_builder_.GetSection()->sh_addr = text_builder_.GetSection()->sh_offset;
844 text_builder_.GetSection()->sh_size = text_builder_.GetSize();
845 text_builder_.GetSection()->sh_link = text_builder_.GetLink();
846 CHECK_ALIGNED(rodata_builder_.GetSection()->sh_offset +
847 rodata_builder_.GetSection()->sh_size, kPageSize);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700848
Vladimir Marko5c42c292015-02-25 12:02:49 +0000849 // Get the layout of the .bss section.
850 bss_builder_.GetSection()->sh_offset =
851 NextOffset<Elf_Word, Elf_Shdr>(*bss_builder_.GetSection(),
852 *text_builder_.GetSection());
853 bss_builder_.GetSection()->sh_addr = bss_builder_.GetSection()->sh_offset;
854 bss_builder_.GetSection()->sh_size = bss_builder_.GetSize();
855 bss_builder_.GetSection()->sh_link = bss_builder_.GetLink();
856
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700857 // Get the layout of the dynamic section.
Vladimir Marko5c42c292015-02-25 12:02:49 +0000858 CHECK(IsAlignedParam(bss_builder_.GetSection()->sh_offset,
859 dynamic_builder_.GetSection()->sh_addralign));
860 dynamic_builder_.GetSection()->sh_offset = bss_builder_.GetSection()->sh_offset;
861 dynamic_builder_.GetSection()->sh_addr =
862 NextOffset<Elf_Word, Elf_Shdr>(*dynamic_builder_.GetSection(), *bss_builder_.GetSection());
Ian Rogers0279ebb2014-10-08 17:27:48 -0700863 dynamic_builder_.GetSection()->sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
864 dynamic_builder_.GetSection()->sh_link = dynamic_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700865
866 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700867 LOG(INFO) << "dynsym off=" << dynsym_builder_.GetSection()->sh_offset
868 << " dynsym size=" << dynsym_builder_.GetSection()->sh_size;
869 LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->GetSection()->sh_offset
870 << " dynstr size=" << dynsym_builder_.GetStrTab()->GetSection()->sh_size;
871 LOG(INFO) << "hash off=" << hash_builder_.GetSection()->sh_offset
872 << " hash size=" << hash_builder_.GetSection()->sh_size;
873 LOG(INFO) << "rodata off=" << rodata_builder_.GetSection()->sh_offset
874 << " rodata size=" << rodata_builder_.GetSection()->sh_size;
875 LOG(INFO) << "text off=" << text_builder_.GetSection()->sh_offset
876 << " text size=" << text_builder_.GetSection()->sh_size;
877 LOG(INFO) << "dynamic off=" << dynamic_builder_.GetSection()->sh_offset
878 << " dynamic size=" << dynamic_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700879 }
880
881 return true;
882 }
883
884 bool Write() {
Andreas Gampecc676072014-09-23 22:58:07 -0700885 std::vector<ElfFilePiece<Elf_Word>*> pieces;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700886 Elf_Shdr* prev = dynamic_builder_.GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700887 std::string strtab;
888
889 if (IncludingDebugSymbols()) {
890 // Setup .symtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700891 section_ptrs_.push_back(symtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700892 AssignSectionStr(&symtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700893 symtab_builder_.SetSectionIndex(section_index_);
894 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700895
896 // Setup .strtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700897 section_ptrs_.push_back(symtab_builder_.GetStrTab()->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700898 AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700899 symtab_builder_.GetStrTab()->SetSectionIndex(section_index_);
900 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700901
902 strtab = symtab_builder_.GenerateStrtab();
903 if (debug_logging_) {
904 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
905 << std::hex << " " << strtab.size();
906 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
907 << std::hex << " " << symtab_builder_.GetSize();
908 }
909 }
910
911 // Setup all the other sections.
912 for (ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder = other_builders_.data(),
913 *end = builder + other_builders_.size();
914 builder != end; ++builder) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700915 section_ptrs_.push_back(builder->GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700916 AssignSectionStr(builder, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700917 builder->SetSectionIndex(section_index_);
918 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700919 }
920
921 // Setup shstrtab
Ian Rogers0279ebb2014-10-08 17:27:48 -0700922 section_ptrs_.push_back(shstrtab_builder_.GetSection());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700923 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
Ian Rogers0279ebb2014-10-08 17:27:48 -0700924 shstrtab_builder_.SetSectionIndex(section_index_);
925 section_index_++;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700926
927 if (debug_logging_) {
928 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
929 << std::hex << " " << shstrtab_.size();
930 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
931 << std::hex << " " << section_ptrs_.size();
932 }
933
934 if (IncludingDebugSymbols()) {
935 // Get the layout of the symtab section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700936 symtab_builder_.GetSection()->sh_offset =
937 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetSection(),
938 *dynamic_builder_.GetSection());
939 symtab_builder_.GetSection()->sh_addr = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700940 // Add to leave space for the null symbol.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700941 symtab_builder_.GetSection()->sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
942 symtab_builder_.GetSection()->sh_link = symtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700943
944 // Get the layout of the dynstr section.
Ian Rogers0279ebb2014-10-08 17:27:48 -0700945 symtab_builder_.GetStrTab()->GetSection()->sh_offset =
946 NextOffset<Elf_Word, Elf_Shdr>(*symtab_builder_.GetStrTab()->GetSection(),
947 *symtab_builder_.GetSection());
948 symtab_builder_.GetStrTab()->GetSection()->sh_addr = 0;
949 symtab_builder_.GetStrTab()->GetSection()->sh_size = strtab.size();
950 symtab_builder_.GetStrTab()->GetSection()->sh_link = symtab_builder_.GetStrTab()->GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700951
Ian Rogers0279ebb2014-10-08 17:27:48 -0700952 prev = symtab_builder_.GetStrTab()->GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700953 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700954 LOG(INFO) << "symtab off=" << symtab_builder_.GetSection()->sh_offset
955 << " symtab size=" << symtab_builder_.GetSection()->sh_size;
956 LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->GetSection()->sh_offset
957 << " strtab size=" << symtab_builder_.GetStrTab()->GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700958 }
959 }
960
961 // Get the layout of the extra sections. (This will deal with the debug
962 // sections if they are there)
963 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700964 it->GetSection()->sh_offset = NextOffset<Elf_Word, Elf_Shdr>(*it->GetSection(), *prev);
965 it->GetSection()->sh_addr = 0;
966 it->GetSection()->sh_size = it->GetBuffer()->size();
967 it->GetSection()->sh_link = it->GetLink();
Andreas Gampecc676072014-09-23 22:58:07 -0700968
969 // We postpone adding an ElfFilePiece to keep the order in "pieces."
970
Ian Rogers0279ebb2014-10-08 17:27:48 -0700971 prev = it->GetSection();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700972 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700973 LOG(INFO) << it->GetName() << " off=" << it->GetSection()->sh_offset
974 << " size=" << it->GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700975 }
976 }
977
978 // Get the layout of the shstrtab section
Ian Rogers0279ebb2014-10-08 17:27:48 -0700979 shstrtab_builder_.GetSection()->sh_offset =
980 NextOffset<Elf_Word, Elf_Shdr>(*shstrtab_builder_.GetSection(), *prev);
981 shstrtab_builder_.GetSection()->sh_addr = 0;
982 shstrtab_builder_.GetSection()->sh_size = shstrtab_.size();
983 shstrtab_builder_.GetSection()->sh_link = shstrtab_builder_.GetLink();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700984 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -0700985 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.GetSection()->sh_offset
986 << " shstrtab size=" << shstrtab_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700987 }
988
989 // The section list comes after come after.
990 Elf_Word sections_offset = RoundUp(
Ian Rogers0279ebb2014-10-08 17:27:48 -0700991 shstrtab_builder_.GetSection()->sh_offset + shstrtab_builder_.GetSection()->sh_size,
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700992 sizeof(Elf_Word));
993
994 // Setup the actual symbol arrays.
995 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -0700996 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700997 std::vector<Elf_Sym> symtab;
998 if (IncludingDebugSymbols()) {
999 symtab = symtab_builder_.GenerateSymtab();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001000 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001001 }
1002
1003 // Setup the dynamic section.
1004 // This will add the 2 values we cannot know until now time, namely the size
1005 // and the soname_offset.
1006 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
1007 dynstr_soname_offset_);
Ian Rogers0279ebb2014-10-08 17:27:48 -07001008 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.GetSection()->sh_size);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001009
1010 // Finish setup of the program headers now that we know the layout of the
1011 // whole file.
Ian Rogers0279ebb2014-10-08 17:27:48 -07001012 Elf_Word load_r_size =
1013 rodata_builder_.GetSection()->sh_offset + rodata_builder_.GetSection()->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001014 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
1015 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001016 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001017
Ian Rogers0279ebb2014-10-08 17:27:48 -07001018 Elf_Word load_rx_size = text_builder_.GetSection()->sh_size;
1019 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.GetSection()->sh_offset;
1020 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.GetSection()->sh_offset;
1021 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.GetSection()->sh_offset;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001022 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
1023 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001024 program_headers_[PH_LOAD_R_X].p_align = text_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001025
Vladimir Marko5c42c292015-02-25 12:02:49 +00001026 program_headers_[PH_LOAD_RW_BSS].p_offset = bss_builder_.GetSection()->sh_offset;
1027 program_headers_[PH_LOAD_RW_BSS].p_vaddr = bss_builder_.GetSection()->sh_offset;
1028 program_headers_[PH_LOAD_RW_BSS].p_paddr = bss_builder_.GetSection()->sh_offset;
1029 program_headers_[PH_LOAD_RW_BSS].p_filesz = 0;
1030 program_headers_[PH_LOAD_RW_BSS].p_memsz = bss_builder_.GetSection()->sh_size;
1031 program_headers_[PH_LOAD_RW_BSS].p_align = bss_builder_.GetSection()->sh_addralign;
1032
1033 program_headers_[PH_LOAD_RW_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
1034 program_headers_[PH_LOAD_RW_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_addr;
1035 program_headers_[PH_LOAD_RW_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_addr;
1036 program_headers_[PH_LOAD_RW_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1037 program_headers_[PH_LOAD_RW_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1038 program_headers_[PH_LOAD_RW_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001039
Ian Rogers0279ebb2014-10-08 17:27:48 -07001040 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.GetSection()->sh_offset;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001041 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.GetSection()->sh_addr;
1042 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.GetSection()->sh_addr;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001043 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.GetSection()->sh_size;
1044 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.GetSection()->sh_size;
1045 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.GetSection()->sh_addralign;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001046
1047 // Finish setup of the Ehdr values.
1048 elf_header_.e_phoff = PHDR_OFFSET;
1049 elf_header_.e_shoff = sections_offset;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001050 elf_header_.e_phnum = (bss_builder_.GetSection()->sh_size != 0u) ? PH_NUM : PH_NUM - 1;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001051 elf_header_.e_shnum = section_ptrs_.size();
Ian Rogers0279ebb2014-10-08 17:27:48 -07001052 elf_header_.e_shstrndx = shstrtab_builder_.GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001053
1054 // Add the rest of the pieces to the list.
Andreas Gampecc676072014-09-23 22:58:07 -07001055 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Elf Header", 0, &elf_header_,
1056 sizeof(elf_header_)));
Vladimir Marko5c42c292015-02-25 12:02:49 +00001057 if (bss_builder_.GetSection()->sh_size != 0u) {
1058 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1059 &program_headers_[0],
1060 elf_header_.e_phnum * sizeof(Elf_Phdr)));
1061 } else {
1062 // Skip PH_LOAD_RW_BSS.
1063 Elf_Word part1_size = PH_LOAD_RW_BSS * sizeof(Elf_Phdr);
1064 Elf_Word part2_size = (PH_NUM - PH_LOAD_RW_BSS - 1) * sizeof(Elf_Phdr);
1065 CHECK_EQ(part1_size + part2_size, elf_header_.e_phnum * sizeof(Elf_Phdr));
1066 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers", PHDR_OFFSET,
1067 &program_headers_[0], part1_size));
1068 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("Program headers part 2",
1069 PHDR_OFFSET + part1_size,
1070 &program_headers_[PH_LOAD_RW_BSS + 1],
1071 part2_size));
1072 }
Andreas Gampecc676072014-09-23 22:58:07 -07001073 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynamic",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001074 dynamic_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001075 dynamic.data(),
Ian Rogers0279ebb2014-10-08 17:27:48 -07001076 dynamic_builder_.GetSection()->sh_size));
1077 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynsym", dynsym_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001078 dynsym.data(),
1079 dynsym.size() * sizeof(Elf_Sym)));
1080 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".dynstr",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001081 dynsym_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001082 dynstr_.c_str(), dynstr_.size()));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001083 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".hash", hash_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001084 hash_.data(),
1085 hash_.size() * sizeof(Elf_Word)));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001086 pieces.push_back(new ElfFileRodataPiece<Elf_Word>(rodata_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001087 oat_writer_));
Ian Rogers0279ebb2014-10-08 17:27:48 -07001088 pieces.push_back(new ElfFileOatTextPiece<Elf_Word>(text_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001089 oat_writer_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001090 if (IncludingDebugSymbols()) {
Andreas Gampecc676072014-09-23 22:58:07 -07001091 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".symtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001092 symtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001093 symtab.data(),
1094 symtab.size() * sizeof(Elf_Sym)));
1095 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".strtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001096 symtab_builder_.GetStrTab()->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001097 strtab.c_str(), strtab.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001098 }
Andreas Gampecc676072014-09-23 22:58:07 -07001099 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(".shstrtab",
Ian Rogers0279ebb2014-10-08 17:27:48 -07001100 shstrtab_builder_.GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001101 &shstrtab_[0], shstrtab_.size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001102 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
1103 // Just add all the sections in induvidually since they are all over the
1104 // place on the heap/stack.
1105 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
Andreas Gampecc676072014-09-23 22:58:07 -07001106 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>("section table piece", cur_off,
1107 section_ptrs_[i], sizeof(Elf_Shdr)));
1108 }
1109
1110 // Postponed debug info.
1111 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001112 pieces.push_back(new ElfFileMemoryPiece<Elf_Word>(it->GetName(), it->GetSection()->sh_offset,
Andreas Gampecc676072014-09-23 22:58:07 -07001113 it->GetBuffer()->data(),
1114 it->GetBuffer()->size()));
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001115 }
1116
1117 if (!WriteOutFile(pieces)) {
1118 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
Andreas Gampecc676072014-09-23 22:58:07 -07001119
1120 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001121 return false;
1122 }
1123
Andreas Gampecc676072014-09-23 22:58:07 -07001124 STLDeleteElements(&pieces); // Have to manually clean pieces.
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001125 return true;
1126 }
1127
1128 // Adds the given raw section to the builder. This will copy it. The caller
1129 // is responsible for deallocating their copy.
1130 void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bld) {
1131 other_builders_.push_back(bld);
1132 }
1133
1134 private:
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001135 void SetISA(InstructionSet isa) {
1136 switch (isa) {
1137 case kArm:
1138 // Fall through.
1139 case kThumb2: {
1140 elf_header_.e_machine = EM_ARM;
1141 elf_header_.e_flags = EF_ARM_EABI_VER5;
1142 break;
1143 }
1144 case kArm64: {
1145 elf_header_.e_machine = EM_AARCH64;
1146 elf_header_.e_flags = 0;
1147 break;
1148 }
1149 case kX86: {
1150 elf_header_.e_machine = EM_386;
1151 elf_header_.e_flags = 0;
1152 break;
1153 }
1154 case kX86_64: {
1155 elf_header_.e_machine = EM_X86_64;
1156 elf_header_.e_flags = 0;
1157 break;
1158 }
1159 case kMips: {
1160 elf_header_.e_machine = EM_MIPS;
1161 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1162 EF_MIPS_PIC |
1163 EF_MIPS_CPIC |
1164 EF_MIPS_ABI_O32 |
1165 EF_MIPS_ARCH_32R2);
1166 break;
1167 }
Andreas Gampe57b34292015-01-14 15:45:59 -08001168 case kMips64: {
1169 elf_header_.e_machine = EM_MIPS;
1170 elf_header_.e_flags = (EF_MIPS_NOREORDER |
1171 EF_MIPS_PIC |
1172 EF_MIPS_CPIC |
1173 EF_MIPS_ARCH_64R6);
1174 break;
1175 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001176 default: {
1177 fatal_error_ = true;
1178 LOG(FATAL) << "Unknown instruction set: " << isa;
1179 break;
1180 }
1181 }
1182 }
1183
1184 void SetupEhdr() {
1185 memset(&elf_header_, 0, sizeof(elf_header_));
1186 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
1187 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
1188 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
1189 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
Tong Shen62d1ca32014-09-03 17:24:56 -07001190 elf_header_.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
1191 ? ELFCLASS32 : ELFCLASS64;;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001192 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
1193 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
1194 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
1195 elf_header_.e_ident[EI_ABIVERSION] = 0;
1196 elf_header_.e_type = ET_DYN;
1197 elf_header_.e_version = 1;
1198 elf_header_.e_entry = 0;
1199 elf_header_.e_ehsize = sizeof(Elf_Ehdr);
1200 elf_header_.e_phentsize = sizeof(Elf_Phdr);
1201 elf_header_.e_shentsize = sizeof(Elf_Shdr);
1202 elf_header_.e_phoff = sizeof(Elf_Ehdr);
1203 }
1204
1205 // Sets up a bunch of the required Dynamic Section entries.
1206 // Namely it will initialize all the mandatory ones that it can.
1207 // Specifically:
1208 // DT_HASH
1209 // DT_STRTAB
1210 // DT_SYMTAB
1211 // DT_SYMENT
1212 //
1213 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
1214 void SetupDynamic() {
1215 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
1216 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1217 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1218 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1219 }
1220
1221 // Sets up the basic dynamic symbols that are needed, namely all those we
1222 // can know already.
1223 //
1224 // Specifically adds:
1225 // oatdata
1226 // oatexec
1227 // oatlastword
1228 void SetupRequiredSymbols() {
1229 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1230 rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1231 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1232 text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1233 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1234 true, 4, STB_GLOBAL, STT_OBJECT);
Vladimir Marko5c42c292015-02-25 12:02:49 +00001235 if (bss_builder_.GetSize() != 0u) {
1236 dynsym_builder_.AddSymbol("oatbss", &bss_builder_, 0, true,
1237 bss_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1238 dynsym_builder_.AddSymbol("oatbsslastword", &bss_builder_, bss_builder_.GetSize() - 4,
1239 true, 4, STB_GLOBAL, STT_OBJECT);
1240 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001241 }
1242
Ian Rogers0279ebb2014-10-08 17:27:48 -07001243 void AssignSectionStr(ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* builder,
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001244 std::string* strtab) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001245 builder->GetSection()->sh_name = strtab->size();
1246 *strtab += builder->GetName();
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001247 *strtab += '\0';
1248 if (debug_logging_) {
Ian Rogers0279ebb2014-10-08 17:27:48 -07001249 LOG(INFO) << "adding section name \"" << builder->GetName() << "\" "
1250 << "to shstrtab at offset " << builder->GetSection()->sh_name;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001251 }
1252 }
1253
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001254
1255 // Write each of the pieces out to the file.
Andreas Gampecc676072014-09-23 22:58:07 -07001256 bool WriteOutFile(const std::vector<ElfFilePiece<Elf_Word>*>& pieces) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001257 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
Andreas Gampecc676072014-09-23 22:58:07 -07001258 if (!(*it)->Write(elf_file_)) {
1259 return false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001260 }
1261 }
1262 return true;
1263 }
1264
Ian Rogers0279ebb2014-10-08 17:27:48 -07001265 bool IncludingDebugSymbols() const {
1266 return add_symbols_ && symtab_builder_.GetSize() > 1;
1267 }
1268
1269 CodeOutput* const oat_writer_;
1270 File* const elf_file_;
1271 const bool add_symbols_;
1272 const bool debug_logging_;
1273
1274 bool fatal_error_ = false;
1275
1276 // What phdr is.
1277 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
1278 enum : uint8_t {
Vladimir Marko5c42c292015-02-25 12:02:49 +00001279 PH_PHDR = 0,
1280 PH_LOAD_R__ = 1,
1281 PH_LOAD_R_X = 2,
1282 PH_LOAD_RW_BSS = 3,
1283 PH_LOAD_RW_DYNAMIC = 4,
1284 PH_DYNAMIC = 5,
1285 PH_NUM = 6,
Ian Rogers0279ebb2014-10-08 17:27:48 -07001286 };
1287 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
1288 Elf_Phdr program_headers_[PH_NUM];
1289
1290 Elf_Ehdr elf_header_;
1291
1292 Elf_Shdr null_hdr_;
1293 std::string shstrtab_;
1294 // The index of the current section being built. The first being 1.
1295 uint32_t section_index_;
1296 std::string dynstr_;
1297 uint32_t dynstr_soname_offset_;
1298 std::vector<const Elf_Shdr*> section_ptrs_;
1299 std::vector<Elf_Word> hash_;
1300
1301 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> text_builder_;
1302 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> rodata_builder_;
Vladimir Marko5c42c292015-02-25 12:02:49 +00001303 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bss_builder_;
Ian Rogers0279ebb2014-10-08 17:27:48 -07001304 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> dynsym_builder_;
1305 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> symtab_builder_;
1306 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> hash_builder_;
1307 ElfDynamicBuilder<Elf_Word, Elf_Sword, Elf_Dyn, Elf_Shdr> dynamic_builder_;
1308 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> shstrtab_builder_;
1309 std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>> other_builders_;
1310
1311 DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001312};
1313
1314} // namespace art
1315
1316#endif // ART_COMPILER_ELF_BUILDER_H_