blob: 35320f5bc81528b41ee16fb87d03a8fff82a22e5 [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
20#include "buffered_output_stream.h"
21#include "elf_utils.h"
22#include "file_output_stream.h"
23#include "instruction_set.h"
24
25namespace art {
26
27template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
28class ElfSectionBuilder {
29 public:
30 ElfSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
31 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link, Elf_Word info,
32 Elf_Word align, Elf_Word entsize) : name_(sec_name), link_(link) {
33 memset(&section_, 0, sizeof(section_));
34 section_.sh_type = type;
35 section_.sh_flags = flags;
36 section_.sh_info = info;
37 section_.sh_addralign = align;
38 section_.sh_entsize = entsize;
39 }
40
41 virtual ~ElfSectionBuilder() {}
42
43 Elf_Shdr section_;
44 Elf_Word section_index_ = 0;
45
46 Elf_Word GetLink() {
47 return (link_) ? link_->section_index_ : 0;
48 }
49
50 const std::string name_;
51
52 protected:
53 const ElfSectionBuilder* link_;
54};
55
56template <typename Elf_Word, typename Elf_Sword, typename Elf_Dyn, typename Elf_Shdr>
57class ElfDynamicBuilder : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
58 public:
59 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un) {
60 if (tag == DT_NULL) {
61 return;
62 }
63 dynamics_.push_back({nullptr, tag, d_un});
64 }
65
66 void AddDynamicTag(Elf_Sword tag, Elf_Word d_un,
67 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section) {
68 if (tag == DT_NULL) {
69 return;
70 }
71 dynamics_.push_back({section, tag, d_un});
72 }
73
74 ElfDynamicBuilder(const std::string& sec_name,
75 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *link)
76 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC,
77 link, 0, kPageSize, sizeof(Elf_Dyn)) {}
78 ~ElfDynamicBuilder() {}
79
80 Elf_Word GetSize() {
81 // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
82 // these must be added when we actually put the file together because
83 // their values are very dependent on state.
84 return dynamics_.size() + 3;
85 }
86
87 // Create the actual dynamic vector. strsz should be the size of the .dynstr
88 // table and soname_off should be the offset of the soname in .dynstr.
89 // Since niether can be found prior to final layout we will wait until here
90 // to add them.
91 std::vector<Elf_Dyn> GetDynamics(Elf_Word strsz, Elf_Word soname) {
92 std::vector<Elf_Dyn> ret;
93 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) {
94 if (it->section_) {
95 // We are adding an address relative to a section.
96 ret.push_back(
97 {it->tag_, {it->off_ + it->section_->section_.sh_addr}});
98 } else {
99 ret.push_back({it->tag_, {it->off_}});
100 }
101 }
102 ret.push_back({DT_STRSZ, {strsz}});
103 ret.push_back({DT_SONAME, {soname}});
104 ret.push_back({DT_NULL, {0}});
105 return ret;
106 }
107
108 protected:
109 struct ElfDynamicState {
110 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_;
111 Elf_Sword tag_;
112 Elf_Word off_;
113 };
114 std::vector<ElfDynamicState> dynamics_;
115};
116
117template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
118class ElfRawSectionBuilder : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
119 public:
120 ElfRawSectionBuilder(const std::string& sec_name, Elf_Word type, Elf_Word flags,
121 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* link, Elf_Word info,
122 Elf_Word align, Elf_Word entsize)
123 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, link, info, align,
124 entsize) {}
125 ~ElfRawSectionBuilder() {}
126 std::vector<uint8_t>* GetBuffer() { return &buf_; }
127 void SetBuffer(std::vector<uint8_t>&& buf) { buf_ = buf; }
128
129 protected:
130 std::vector<uint8_t> buf_;
131};
132
133template <typename Elf_Word, typename Elf_Sword, typename Elf_Shdr>
134class ElfOatSectionBuilder : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
135 public:
136 ElfOatSectionBuilder(const std::string& sec_name, Elf_Word size, Elf_Word offset,
137 Elf_Word type, Elf_Word flags)
138 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, flags, nullptr, 0, kPageSize,
139 0), offset_(offset), size_(size) {}
140 ~ElfOatSectionBuilder() {}
141
142 Elf_Word GetOffset() {
143 return offset_;
144 }
145
146 Elf_Word GetSize() {
147 return size_;
148 }
149
150 protected:
151 // Offset of the content within the file.
152 Elf_Word offset_;
153 // Size of the content within the file.
154 Elf_Word size_;
155};
156
157static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
158 return ((binding) << 4) + ((type) & 0xf);
159}
160
161// from bionic
162static inline unsigned elfhash(const char *_name) {
163 const unsigned char *name = (const unsigned char *) _name;
164 unsigned h = 0, g;
165
166 while (*name) {
167 h = (h << 4) + *name++;
168 g = h & 0xf0000000;
169 h ^= g;
170 h ^= g >> 24;
171 }
172 return h;
173}
174
175template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Sym,
176 typename Elf_Shdr>
177class ElfSymtabBuilder : public ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> {
178 public:
179 // Add a symbol with given name to this symtab. The symbol refers to
180 // 'relative_addr' within the given section and has the given attributes.
181 void AddSymbol(const std::string& name,
182 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section,
183 Elf_Addr addr,
184 bool is_relative,
185 Elf_Word size,
186 uint8_t binding,
187 uint8_t type,
188 uint8_t other = 0) {
189 CHECK(section);
190 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative,
191 MakeStInfo(binding, type), other, 0};
192 symbols_.push_back(state);
193 }
194
195 ElfSymtabBuilder(const std::string& sec_name, Elf_Word type,
196 const std::string& str_name, Elf_Word str_type, bool alloc)
197 : ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>(sec_name, type, ((alloc) ? SHF_ALLOC : 0U),
198 &strtab_, 0, sizeof(Elf_Word),
199 sizeof(Elf_Sym)), str_name_(str_name),
200 str_type_(str_type),
201 strtab_(str_name,
202 str_type,
203 ((alloc) ? SHF_ALLOC : 0U),
204 nullptr, 0, 1, 1) {}
205 ~ElfSymtabBuilder() {}
206
207 std::vector<Elf_Word> GenerateHashContents() {
208 // Here is how The ELF hash table works.
209 // There are 3 arrays to worry about.
210 // * The symbol table where the symbol information is.
211 // * The bucket array which is an array of indexes into the symtab and chain.
212 // * The chain array which is also an array of indexes into the symtab and chain.
213 //
214 // Lets say the state is something like this.
215 // +--------+ +--------+ +-----------+
216 // | symtab | | bucket | | chain |
217 // | null | | 1 | | STN_UNDEF |
218 // | <sym1> | | 4 | | 2 |
219 // | <sym2> | | | | 5 |
220 // | <sym3> | | | | STN_UNDEF |
221 // | <sym4> | | | | 3 |
222 // | <sym5> | | | | STN_UNDEF |
223 // +--------+ +--------+ +-----------+
224 //
225 // The lookup process (in python psudocode) is
226 //
227 // def GetSym(name):
228 // # NB STN_UNDEF == 0
229 // indx = bucket[elfhash(name) % num_buckets]
230 // while indx != STN_UNDEF:
231 // if GetSymbolName(symtab[indx]) == name:
232 // return symtab[indx]
233 // indx = chain[indx]
234 // return SYMBOL_NOT_FOUND
235 //
236 // Between bucket and chain arrays every symtab index must be present exactly
237 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
238
239 // Select number of buckets.
240 // This is essentially arbitrary.
241 Elf_Word nbuckets;
242 Elf_Word chain_size = GetSize();
243 if (symbols_.size() < 8) {
244 nbuckets = 2;
245 } else if (symbols_.size() < 32) {
246 nbuckets = 4;
247 } else if (symbols_.size() < 256) {
248 nbuckets = 16;
249 } else {
250 // Have about 32 ids per bucket.
251 nbuckets = RoundUp(symbols_.size()/32, 2);
252 }
253 std::vector<Elf_Word> hash;
254 hash.push_back(nbuckets);
255 hash.push_back(chain_size);
256 uint32_t bucket_offset = hash.size();
257 uint32_t chain_offset = bucket_offset + nbuckets;
258 hash.resize(hash.size() + nbuckets + chain_size, 0);
259
260 Elf_Word* buckets = hash.data() + bucket_offset;
261 Elf_Word* chain = hash.data() + chain_offset;
262
263 // Set up the actual hash table.
264 for (Elf_Word i = 0; i < symbols_.size(); i++) {
265 // Add 1 since we need to have the null symbol that is not in the symbols
266 // list.
267 Elf_Word index = i + 1;
268 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets;
269 if (buckets[hash_val] == 0) {
270 buckets[hash_val] = index;
271 } else {
272 hash_val = buckets[hash_val];
273 CHECK_LT(hash_val, chain_size);
274 while (chain[hash_val] != 0) {
275 hash_val = chain[hash_val];
276 CHECK_LT(hash_val, chain_size);
277 }
278 chain[hash_val] = index;
279 // Check for loops. Works because if this is non-empty then there must be
280 // another cell which already contains the same symbol index as this one,
281 // which means some symbol has more then one name, which isn't allowed.
282 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
283 }
284 }
285
286 return hash;
287 }
288
289 std::string GenerateStrtab() {
290 std::string tab;
291 tab += '\0';
292 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) {
293 it->name_idx_ = tab.size();
294 tab += it->name_;
295 tab += '\0';
296 }
297 strtab_.section_.sh_size = tab.size();
298 return tab;
299 }
300
301 std::vector<Elf_Sym> GenerateSymtab() {
302 std::vector<Elf_Sym> ret;
303 Elf_Sym undef_sym;
304 memset(&undef_sym, 0, sizeof(undef_sym));
305 undef_sym.st_shndx = SHN_UNDEF;
306 ret.push_back(undef_sym);
307
308 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) {
309 Elf_Sym sym;
310 memset(&sym, 0, sizeof(sym));
311 sym.st_name = it->name_idx_;
312 if (it->is_relative_) {
313 sym.st_value = it->addr_ + it->section_->section_.sh_offset;
314 } else {
315 sym.st_value = it->addr_;
316 }
317 sym.st_size = it->size_;
318 sym.st_other = it->other_;
319 sym.st_shndx = it->section_->section_index_;
320 sym.st_info = it->info_;
321
322 ret.push_back(sym);
323 }
324 return ret;
325 }
326
327 Elf_Word GetSize() {
328 // 1 is for the implicit NULL symbol.
329 return symbols_.size() + 1;
330 }
331
332 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* GetStrTab() {
333 return &strtab_;
334 }
335
336 protected:
337 struct ElfSymbolState {
338 const std::string name_;
339 const ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>* section_;
340 Elf_Addr addr_;
341 Elf_Word size_;
342 bool is_relative_;
343 uint8_t info_;
344 uint8_t other_;
345 // Used during Write() to temporarially hold name index in the strtab.
346 Elf_Word name_idx_;
347 };
348
349 // Information for the strsym for dynstr sections.
350 const std::string str_name_;
351 Elf_Word str_type_;
352 // The symbols in the same order they will be in the symbol table.
353 std::vector<ElfSymbolState> symbols_;
354 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> strtab_;
355};
356
357class CodeOutput {
358 public:
359 virtual bool Write(OutputStream* out) = 0;
360 virtual ~CodeOutput() {}
361};
362
363template <typename Elf_Word, typename Elf_Shdr>
364static inline constexpr Elf_Word NextOffset(const Elf_Shdr& cur, const Elf_Shdr& prev) {
365 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign);
366}
367
368template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Dyn,
369 typename Elf_Sym, typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr>
370class ElfBuilder FINAL {
371 public:
372 ElfBuilder(CodeOutput* oat_writer,
373 File* elf_file,
374 InstructionSet isa,
375 Elf_Word rodata_relative_offset,
376 Elf_Word rodata_size,
377 Elf_Word text_relative_offset,
378 Elf_Word text_size,
379 const bool add_symbols,
380 bool debug = false)
381 : oat_writer_(oat_writer),
382 elf_file_(elf_file),
383 add_symbols_(add_symbols),
384 debug_logging_(debug),
385 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
386 SHF_ALLOC | SHF_EXECINSTR),
387 rodata_builder_(".rodata", rodata_size, rodata_relative_offset, SHT_PROGBITS, SHF_ALLOC),
388 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
389 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
390 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0, sizeof(Elf_Word),
391 sizeof(Elf_Word)),
392 dynamic_builder_(".dynamic", &dynsym_builder_),
393 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
394 SetupEhdr();
395 SetupDynamic();
396 SetupRequiredSymbols();
397 SetISA(isa);
398 }
399 ~ElfBuilder() {}
400
401 bool Init() {
402 // The basic layout of the elf file. Order may be different in final output.
403 // +-------------------------+
404 // | Elf_Ehdr |
405 // +-------------------------+
406 // | Elf_Phdr PHDR |
407 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata
408 // | Elf_Phdr LOAD R X | .text
409 // | Elf_Phdr LOAD RW | .dynamic
410 // | Elf_Phdr DYNAMIC | .dynamic
411 // +-------------------------+
412 // | .dynsym |
413 // | Elf_Sym STN_UNDEF |
414 // | Elf_Sym oatdata |
415 // | Elf_Sym oatexec |
416 // | Elf_Sym oatlastword |
417 // +-------------------------+
418 // | .dynstr |
419 // | \0 |
420 // | oatdata\0 |
421 // | oatexec\0 |
422 // | oatlastword\0 |
423 // | boot.oat\0 |
424 // +-------------------------+
425 // | .hash |
426 // | Elf_Word nbucket = b |
427 // | Elf_Word nchain = c |
428 // | Elf_Word bucket[0] |
429 // | ... |
430 // | Elf_Word bucket[b - 1] |
431 // | Elf_Word chain[0] |
432 // | ... |
433 // | Elf_Word chain[c - 1] |
434 // +-------------------------+
435 // | .rodata |
436 // | oatdata..oatexec-4 |
437 // +-------------------------+
438 // | .text |
439 // | oatexec..oatlastword |
440 // +-------------------------+
441 // | .dynamic |
442 // | Elf_Dyn DT_SONAME |
443 // | Elf_Dyn DT_HASH |
444 // | Elf_Dyn DT_SYMTAB |
445 // | Elf_Dyn DT_SYMENT |
446 // | Elf_Dyn DT_STRTAB |
447 // | Elf_Dyn DT_STRSZ |
448 // | Elf_Dyn DT_NULL |
449 // +-------------------------+ (Optional)
450 // | .strtab | (Optional)
451 // | program symbol names | (Optional)
452 // +-------------------------+ (Optional)
453 // | .symtab | (Optional)
454 // | program symbols | (Optional)
455 // +-------------------------+
456 // | .shstrtab |
457 // | \0 |
458 // | .dynamic\0 |
459 // | .dynsym\0 |
460 // | .dynstr\0 |
461 // | .hash\0 |
462 // | .rodata\0 |
463 // | .text\0 |
464 // | .shstrtab\0 |
465 // | .symtab\0 | (Optional)
466 // | .strtab\0 | (Optional)
467 // | .debug_str\0 | (Optional)
468 // | .debug_info\0 | (Optional)
469 // | .eh_frame\0 | (Optional)
470 // | .debug_line\0 | (Optional)
471 // | .debug_abbrev\0 | (Optional)
472 // +-------------------------+ (Optional)
473 // | .debug_info | (Optional)
474 // +-------------------------+ (Optional)
475 // | .debug_abbrev | (Optional)
476 // +-------------------------+ (Optional)
477 // | .eh_frame | (Optional)
478 // +-------------------------+ (Optional)
479 // | .debug_line | (Optional)
480 // +-------------------------+ (Optional)
481 // | .debug_str | (Optional)
482 // +-------------------------+ (Optional)
483 // | Elf_Shdr NULL |
484 // | Elf_Shdr .dynsym |
485 // | Elf_Shdr .dynstr |
486 // | Elf_Shdr .hash |
487 // | Elf_Shdr .text |
488 // | Elf_Shdr .rodata |
489 // | Elf_Shdr .dynamic |
490 // | Elf_Shdr .shstrtab |
491 // | Elf_Shdr .debug_info | (Optional)
492 // | Elf_Shdr .debug_abbrev | (Optional)
493 // | Elf_Shdr .eh_frame | (Optional)
494 // | Elf_Shdr .debug_line | (Optional)
495 // | Elf_Shdr .debug_str | (Optional)
496 // +-------------------------+
497
498 if (fatal_error_) {
499 return false;
500 }
501 // Step 1. Figure out all the offsets.
502
503 if (debug_logging_) {
504 LOG(INFO) << "phdr_offset=" << PHDR_OFFSET << std::hex << " " << PHDR_OFFSET;
505 LOG(INFO) << "phdr_size=" << PHDR_SIZE << std::hex << " " << PHDR_SIZE;
506 }
507
508 memset(&program_headers_, 0, sizeof(program_headers_));
509 program_headers_[PH_PHDR].p_type = PT_PHDR;
510 program_headers_[PH_PHDR].p_offset = PHDR_OFFSET;
511 program_headers_[PH_PHDR].p_vaddr = PHDR_OFFSET;
512 program_headers_[PH_PHDR].p_paddr = PHDR_OFFSET;
513 program_headers_[PH_PHDR].p_filesz = sizeof(program_headers_);
514 program_headers_[PH_PHDR].p_memsz = sizeof(program_headers_);
515 program_headers_[PH_PHDR].p_flags = PF_R;
516 program_headers_[PH_PHDR].p_align = sizeof(Elf_Word);
517
518 program_headers_[PH_LOAD_R__].p_type = PT_LOAD;
519 program_headers_[PH_LOAD_R__].p_offset = 0;
520 program_headers_[PH_LOAD_R__].p_vaddr = 0;
521 program_headers_[PH_LOAD_R__].p_paddr = 0;
522 program_headers_[PH_LOAD_R__].p_flags = PF_R;
523
524 program_headers_[PH_LOAD_R_X].p_type = PT_LOAD;
525 program_headers_[PH_LOAD_R_X].p_flags = PF_R | PF_X;
526
527 program_headers_[PH_LOAD_RW_].p_type = PT_LOAD;
528 program_headers_[PH_LOAD_RW_].p_flags = PF_R | PF_W;
529
530 program_headers_[PH_DYNAMIC].p_type = PT_DYNAMIC;
531 program_headers_[PH_DYNAMIC].p_flags = PF_R | PF_W;
532
533 // Get the dynstr string.
534 dynstr_ = dynsym_builder_.GenerateStrtab();
535
536 // Add the SONAME to the dynstr.
537 dynstr_soname_offset_ = dynstr_.size();
538 std::string file_name(elf_file_->GetPath());
539 size_t directory_separator_pos = file_name.rfind('/');
540 if (directory_separator_pos != std::string::npos) {
541 file_name = file_name.substr(directory_separator_pos + 1);
542 }
543 dynstr_ += file_name;
544 dynstr_ += '\0';
545 if (debug_logging_) {
546 LOG(INFO) << "dynstr size (bytes) =" << dynstr_.size()
547 << std::hex << " " << dynstr_.size();
548 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize()
549 << std::hex << " " << dynsym_builder_.GetSize();
550 }
551
552 // Get the section header string table.
553 shstrtab_ += '\0';
554
555 // Setup sym_undef
556 memset(&null_hdr_, 0, sizeof(null_hdr_));
557 null_hdr_.sh_type = SHT_NULL;
558 null_hdr_.sh_link = SHN_UNDEF;
559 section_ptrs_.push_back(&null_hdr_);
560
561 section_index_ = 1;
562
563 // setup .dynsym
564 section_ptrs_.push_back(&dynsym_builder_.section_);
565 AssignSectionStr(&dynsym_builder_, &shstrtab_);
566 dynsym_builder_.section_index_ = section_index_++;
567
568 // Setup .dynstr
569 section_ptrs_.push_back(&dynsym_builder_.GetStrTab()->section_);
570 AssignSectionStr(dynsym_builder_.GetStrTab(), &shstrtab_);
571 dynsym_builder_.GetStrTab()->section_index_ = section_index_++;
572
573 // Setup .hash
574 section_ptrs_.push_back(&hash_builder_.section_);
575 AssignSectionStr(&hash_builder_, &shstrtab_);
576 hash_builder_.section_index_ = section_index_++;
577
578 // Setup .rodata
579 section_ptrs_.push_back(&rodata_builder_.section_);
580 AssignSectionStr(&rodata_builder_, &shstrtab_);
581 rodata_builder_.section_index_ = section_index_++;
582
583 // Setup .text
584 section_ptrs_.push_back(&text_builder_.section_);
585 AssignSectionStr(&text_builder_, &shstrtab_);
586 text_builder_.section_index_ = section_index_++;
587
588 // Setup .dynamic
589 section_ptrs_.push_back(&dynamic_builder_.section_);
590 AssignSectionStr(&dynamic_builder_, &shstrtab_);
591 dynamic_builder_.section_index_ = section_index_++;
592
593 // Fill in the hash section.
594 hash_ = dynsym_builder_.GenerateHashContents();
595
596 if (debug_logging_) {
597 LOG(INFO) << ".hash size (bytes)=" << hash_.size() * sizeof(Elf_Word)
598 << std::hex << " " << hash_.size() * sizeof(Elf_Word);
599 }
600
601 Elf_Word base_offset = sizeof(Elf_Ehdr) + sizeof(program_headers_);
602
603 // Get the layout in the sections.
604 //
605 // Get the layout of the dynsym section.
606 dynsym_builder_.section_.sh_offset = RoundUp(base_offset, dynsym_builder_.section_.sh_addralign);
607 dynsym_builder_.section_.sh_addr = dynsym_builder_.section_.sh_offset;
608 dynsym_builder_.section_.sh_size = dynsym_builder_.GetSize() * sizeof(Elf_Sym);
609 dynsym_builder_.section_.sh_link = dynsym_builder_.GetLink();
610
611 // Get the layout of the dynstr section.
612 dynsym_builder_.GetStrTab()->section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
613 (dynsym_builder_.GetStrTab()->section_,
614 dynsym_builder_.section_);
615 dynsym_builder_.GetStrTab()->section_.sh_addr = dynsym_builder_.GetStrTab()->section_.sh_offset;
616 dynsym_builder_.GetStrTab()->section_.sh_size = dynstr_.size();
617 dynsym_builder_.GetStrTab()->section_.sh_link = dynsym_builder_.GetStrTab()->GetLink();
618
619 // Get the layout of the hash section
620 hash_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
621 (hash_builder_.section_,
622 dynsym_builder_.GetStrTab()->section_);
623 hash_builder_.section_.sh_addr = hash_builder_.section_.sh_offset;
624 hash_builder_.section_.sh_size = hash_.size() * sizeof(Elf_Word);
625 hash_builder_.section_.sh_link = hash_builder_.GetLink();
626
627 // Get the layout of the rodata section.
628 rodata_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
629 (rodata_builder_.section_,
630 hash_builder_.section_);
631 rodata_builder_.section_.sh_addr = rodata_builder_.section_.sh_offset;
632 rodata_builder_.section_.sh_size = rodata_builder_.GetSize();
633 rodata_builder_.section_.sh_link = rodata_builder_.GetLink();
634
635 // Get the layout of the text section.
636 text_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
637 (text_builder_.section_, rodata_builder_.section_);
638 text_builder_.section_.sh_addr = text_builder_.section_.sh_offset;
639 text_builder_.section_.sh_size = text_builder_.GetSize();
640 text_builder_.section_.sh_link = text_builder_.GetLink();
641 CHECK_ALIGNED(rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size, kPageSize);
642
643 // Get the layout of the dynamic section.
644 dynamic_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
645 (dynamic_builder_.section_,
646 text_builder_.section_);
647 dynamic_builder_.section_.sh_addr = dynamic_builder_.section_.sh_offset;
648 dynamic_builder_.section_.sh_size = dynamic_builder_.GetSize() * sizeof(Elf_Dyn);
649 dynamic_builder_.section_.sh_link = dynamic_builder_.GetLink();
650
651 if (debug_logging_) {
652 LOG(INFO) << "dynsym off=" << dynsym_builder_.section_.sh_offset
653 << " dynsym size=" << dynsym_builder_.section_.sh_size;
654 LOG(INFO) << "dynstr off=" << dynsym_builder_.GetStrTab()->section_.sh_offset
655 << " dynstr size=" << dynsym_builder_.GetStrTab()->section_.sh_size;
656 LOG(INFO) << "hash off=" << hash_builder_.section_.sh_offset
657 << " hash size=" << hash_builder_.section_.sh_size;
658 LOG(INFO) << "rodata off=" << rodata_builder_.section_.sh_offset
659 << " rodata size=" << rodata_builder_.section_.sh_size;
660 LOG(INFO) << "text off=" << text_builder_.section_.sh_offset
661 << " text size=" << text_builder_.section_.sh_size;
662 LOG(INFO) << "dynamic off=" << dynamic_builder_.section_.sh_offset
663 << " dynamic size=" << dynamic_builder_.section_.sh_size;
664 }
665
666 return true;
667 }
668
669 bool Write() {
670 std::vector<ElfFilePiece> pieces;
671 Elf_Shdr prev = dynamic_builder_.section_;
672 std::string strtab;
673
674 if (IncludingDebugSymbols()) {
675 // Setup .symtab
676 section_ptrs_.push_back(&symtab_builder_.section_);
677 AssignSectionStr(&symtab_builder_, &shstrtab_);
678 symtab_builder_.section_index_ = section_index_++;
679
680 // Setup .strtab
681 section_ptrs_.push_back(&symtab_builder_.GetStrTab()->section_);
682 AssignSectionStr(symtab_builder_.GetStrTab(), &shstrtab_);
683 symtab_builder_.GetStrTab()->section_index_ = section_index_++;
684
685 strtab = symtab_builder_.GenerateStrtab();
686 if (debug_logging_) {
687 LOG(INFO) << "strtab size (bytes) =" << strtab.size()
688 << std::hex << " " << strtab.size();
689 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize()
690 << std::hex << " " << symtab_builder_.GetSize();
691 }
692 }
693
694 // Setup all the other sections.
695 for (ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder = other_builders_.data(),
696 *end = builder + other_builders_.size();
697 builder != end; ++builder) {
698 section_ptrs_.push_back(&builder->section_);
699 AssignSectionStr(builder, &shstrtab_);
700 builder->section_index_ = section_index_++;
701 }
702
703 // Setup shstrtab
704 section_ptrs_.push_back(&shstrtab_builder_.section_);
705 AssignSectionStr(&shstrtab_builder_, &shstrtab_);
706 shstrtab_builder_.section_index_ = section_index_++;
707
708 if (debug_logging_) {
709 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab_.size()
710 << std::hex << " " << shstrtab_.size();
711 LOG(INFO) << "section list size (elements)=" << section_ptrs_.size()
712 << std::hex << " " << section_ptrs_.size();
713 }
714
715 if (IncludingDebugSymbols()) {
716 // Get the layout of the symtab section.
717 symtab_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
718 (symtab_builder_.section_,
719 dynamic_builder_.section_);
720 symtab_builder_.section_.sh_addr = 0;
721 // Add to leave space for the null symbol.
722 symtab_builder_.section_.sh_size = symtab_builder_.GetSize() * sizeof(Elf_Sym);
723 symtab_builder_.section_.sh_link = symtab_builder_.GetLink();
724
725 // Get the layout of the dynstr section.
726 symtab_builder_.GetStrTab()->section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
727 (symtab_builder_.GetStrTab()->section_,
728 symtab_builder_.section_);
729 symtab_builder_.GetStrTab()->section_.sh_addr = 0;
730 symtab_builder_.GetStrTab()->section_.sh_size = strtab.size();
731 symtab_builder_.GetStrTab()->section_.sh_link = symtab_builder_.GetStrTab()->GetLink();
732
733 prev = symtab_builder_.GetStrTab()->section_;
734 if (debug_logging_) {
735 LOG(INFO) << "symtab off=" << symtab_builder_.section_.sh_offset
736 << " symtab size=" << symtab_builder_.section_.sh_size;
737 LOG(INFO) << "strtab off=" << symtab_builder_.GetStrTab()->section_.sh_offset
738 << " strtab size=" << symtab_builder_.GetStrTab()->section_.sh_size;
739 }
740 }
741
742 // Get the layout of the extra sections. (This will deal with the debug
743 // sections if they are there)
744 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) {
745 it->section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>(it->section_, prev);
746 it->section_.sh_addr = 0;
747 it->section_.sh_size = it->GetBuffer()->size();
748 it->section_.sh_link = it->GetLink();
749 pieces.push_back(ElfFilePiece(it->name_, it->section_.sh_offset,
750 it->GetBuffer()->data(), it->GetBuffer()->size()));
751 prev = it->section_;
752 if (debug_logging_) {
753 LOG(INFO) << it->name_ << " off=" << it->section_.sh_offset
754 << " size=" << it->section_.sh_size;
755 }
756 }
757
758 // Get the layout of the shstrtab section
759 shstrtab_builder_.section_.sh_offset = NextOffset<Elf_Word, Elf_Shdr>
760 (shstrtab_builder_.section_, prev);
761 shstrtab_builder_.section_.sh_addr = 0;
762 shstrtab_builder_.section_.sh_size = shstrtab_.size();
763 shstrtab_builder_.section_.sh_link = shstrtab_builder_.GetLink();
764 if (debug_logging_) {
765 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.section_.sh_offset
766 << " shstrtab size=" << shstrtab_builder_.section_.sh_size;
767 }
768
769 // The section list comes after come after.
770 Elf_Word sections_offset = RoundUp(
771 shstrtab_builder_.section_.sh_offset + shstrtab_builder_.section_.sh_size,
772 sizeof(Elf_Word));
773
774 // Setup the actual symbol arrays.
775 std::vector<Elf_Sym> dynsym = dynsym_builder_.GenerateSymtab();
776 CHECK_EQ(dynsym.size() * sizeof(Elf_Sym), dynsym_builder_.section_.sh_size);
777 std::vector<Elf_Sym> symtab;
778 if (IncludingDebugSymbols()) {
779 symtab = symtab_builder_.GenerateSymtab();
780 CHECK_EQ(symtab.size() * sizeof(Elf_Sym), symtab_builder_.section_.sh_size);
781 }
782
783 // Setup the dynamic section.
784 // This will add the 2 values we cannot know until now time, namely the size
785 // and the soname_offset.
786 std::vector<Elf_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr_.size(),
787 dynstr_soname_offset_);
788 CHECK_EQ(dynamic.size() * sizeof(Elf_Dyn), dynamic_builder_.section_.sh_size);
789
790 // Finish setup of the program headers now that we know the layout of the
791 // whole file.
792 Elf_Word load_r_size = rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size;
793 program_headers_[PH_LOAD_R__].p_filesz = load_r_size;
794 program_headers_[PH_LOAD_R__].p_memsz = load_r_size;
795 program_headers_[PH_LOAD_R__].p_align = rodata_builder_.section_.sh_addralign;
796
797 Elf_Word load_rx_size = text_builder_.section_.sh_size;
798 program_headers_[PH_LOAD_R_X].p_offset = text_builder_.section_.sh_offset;
799 program_headers_[PH_LOAD_R_X].p_vaddr = text_builder_.section_.sh_offset;
800 program_headers_[PH_LOAD_R_X].p_paddr = text_builder_.section_.sh_offset;
801 program_headers_[PH_LOAD_R_X].p_filesz = load_rx_size;
802 program_headers_[PH_LOAD_R_X].p_memsz = load_rx_size;
803 program_headers_[PH_LOAD_R_X].p_align = text_builder_.section_.sh_addralign;
804
805 program_headers_[PH_LOAD_RW_].p_offset = dynamic_builder_.section_.sh_offset;
806 program_headers_[PH_LOAD_RW_].p_vaddr = dynamic_builder_.section_.sh_offset;
807 program_headers_[PH_LOAD_RW_].p_paddr = dynamic_builder_.section_.sh_offset;
808 program_headers_[PH_LOAD_RW_].p_filesz = dynamic_builder_.section_.sh_size;
809 program_headers_[PH_LOAD_RW_].p_memsz = dynamic_builder_.section_.sh_size;
810 program_headers_[PH_LOAD_RW_].p_align = dynamic_builder_.section_.sh_addralign;
811
812 program_headers_[PH_DYNAMIC].p_offset = dynamic_builder_.section_.sh_offset;
813 program_headers_[PH_DYNAMIC].p_vaddr = dynamic_builder_.section_.sh_offset;
814 program_headers_[PH_DYNAMIC].p_paddr = dynamic_builder_.section_.sh_offset;
815 program_headers_[PH_DYNAMIC].p_filesz = dynamic_builder_.section_.sh_size;
816 program_headers_[PH_DYNAMIC].p_memsz = dynamic_builder_.section_.sh_size;
817 program_headers_[PH_DYNAMIC].p_align = dynamic_builder_.section_.sh_addralign;
818
819 // Finish setup of the Ehdr values.
820 elf_header_.e_phoff = PHDR_OFFSET;
821 elf_header_.e_shoff = sections_offset;
822 elf_header_.e_phnum = PH_NUM;
823 elf_header_.e_shnum = section_ptrs_.size();
824 elf_header_.e_shstrndx = shstrtab_builder_.section_index_;
825
826 // Add the rest of the pieces to the list.
827 pieces.push_back(ElfFilePiece("Elf Header", 0, &elf_header_, sizeof(elf_header_)));
828 pieces.push_back(ElfFilePiece("Program headers", PHDR_OFFSET,
829 &program_headers_, sizeof(program_headers_)));
830 pieces.push_back(ElfFilePiece(".dynamic", dynamic_builder_.section_.sh_offset,
831 dynamic.data(), dynamic_builder_.section_.sh_size));
832 pieces.push_back(ElfFilePiece(".dynsym", dynsym_builder_.section_.sh_offset,
833 dynsym.data(), dynsym.size() * sizeof(Elf_Sym)));
834 pieces.push_back(ElfFilePiece(".dynstr", dynsym_builder_.GetStrTab()->section_.sh_offset,
835 dynstr_.c_str(), dynstr_.size()));
836 pieces.push_back(ElfFilePiece(".hash", hash_builder_.section_.sh_offset,
837 hash_.data(), hash_.size() * sizeof(Elf_Word)));
838 pieces.push_back(ElfFilePiece(".rodata", rodata_builder_.section_.sh_offset,
839 nullptr, rodata_builder_.section_.sh_size));
840 pieces.push_back(ElfFilePiece(".text", text_builder_.section_.sh_offset,
841 nullptr, text_builder_.section_.sh_size));
842 if (IncludingDebugSymbols()) {
843 pieces.push_back(ElfFilePiece(".symtab", symtab_builder_.section_.sh_offset,
844 symtab.data(), symtab.size() * sizeof(Elf_Sym)));
845 pieces.push_back(ElfFilePiece(".strtab", symtab_builder_.GetStrTab()->section_.sh_offset,
846 strtab.c_str(), strtab.size()));
847 }
848 pieces.push_back(ElfFilePiece(".shstrtab", shstrtab_builder_.section_.sh_offset,
849 &shstrtab_[0], shstrtab_.size()));
850 for (uint32_t i = 0; i < section_ptrs_.size(); ++i) {
851 // Just add all the sections in induvidually since they are all over the
852 // place on the heap/stack.
853 Elf_Word cur_off = sections_offset + i * sizeof(Elf_Shdr);
854 pieces.push_back(ElfFilePiece("section table piece", cur_off,
855 section_ptrs_[i], sizeof(Elf_Shdr)));
856 }
857
858 if (!WriteOutFile(pieces)) {
859 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath();
860 return false;
861 }
862 // write out the actual oat file data.
863 Elf_Word oat_data_offset = rodata_builder_.section_.sh_offset;
864 if (static_cast<off_t>(oat_data_offset) != lseek(elf_file_->Fd(), oat_data_offset, SEEK_SET)) {
865 PLOG(ERROR) << "Failed to seek to .rodata offset " << oat_data_offset
866 << " for " << elf_file_->GetPath();
867 return false;
868 }
869 std::unique_ptr<BufferedOutputStream> output_stream(
870 new BufferedOutputStream(new FileOutputStream(elf_file_)));
871 if (!oat_writer_->Write(output_stream.get())) {
872 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file_->GetPath();
873 return false;
874 }
875
876 return true;
877 }
878
879 // Adds the given raw section to the builder. This will copy it. The caller
880 // is responsible for deallocating their copy.
881 void RegisterRawSection(ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> bld) {
882 other_builders_.push_back(bld);
883 }
884
885 private:
886 CodeOutput* oat_writer_;
887 File* elf_file_;
888 const bool add_symbols_;
889 const bool debug_logging_;
890
891 bool fatal_error_ = false;
892
893 // What phdr is.
894 static const uint32_t PHDR_OFFSET = sizeof(Elf_Ehdr);
895 enum : uint8_t {
896 PH_PHDR = 0,
897 PH_LOAD_R__ = 1,
898 PH_LOAD_R_X = 2,
899 PH_LOAD_RW_ = 3,
900 PH_DYNAMIC = 4,
901 PH_NUM = 5,
902 };
903 static const uint32_t PHDR_SIZE = sizeof(Elf_Phdr) * PH_NUM;
904 Elf_Phdr program_headers_[PH_NUM];
905
906 Elf_Ehdr elf_header_;
907
908 Elf_Shdr null_hdr_;
909 std::string shstrtab_;
910 uint32_t section_index_;
911 std::string dynstr_;
912 uint32_t dynstr_soname_offset_;
913 std::vector<Elf_Shdr*> section_ptrs_;
914 std::vector<Elf_Word> hash_;
915
916 public:
917 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> text_builder_;
918 ElfOatSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> rodata_builder_;
919 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> dynsym_builder_;
920 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr> symtab_builder_;
921 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> hash_builder_;
922 ElfDynamicBuilder<Elf_Word, Elf_Sword, Elf_Dyn, Elf_Shdr> dynamic_builder_;
923 ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> shstrtab_builder_;
924 std::vector<ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr>> other_builders_;
925
926 private:
927 void SetISA(InstructionSet isa) {
928 switch (isa) {
929 case kArm:
930 // Fall through.
931 case kThumb2: {
932 elf_header_.e_machine = EM_ARM;
933 elf_header_.e_flags = EF_ARM_EABI_VER5;
934 break;
935 }
936 case kArm64: {
937 elf_header_.e_machine = EM_AARCH64;
938 elf_header_.e_flags = 0;
939 break;
940 }
941 case kX86: {
942 elf_header_.e_machine = EM_386;
943 elf_header_.e_flags = 0;
944 break;
945 }
946 case kX86_64: {
947 elf_header_.e_machine = EM_X86_64;
948 elf_header_.e_flags = 0;
949 break;
950 }
951 case kMips: {
952 elf_header_.e_machine = EM_MIPS;
953 elf_header_.e_flags = (EF_MIPS_NOREORDER |
954 EF_MIPS_PIC |
955 EF_MIPS_CPIC |
956 EF_MIPS_ABI_O32 |
957 EF_MIPS_ARCH_32R2);
958 break;
959 }
960 default: {
961 fatal_error_ = true;
962 LOG(FATAL) << "Unknown instruction set: " << isa;
963 break;
964 }
965 }
966 }
967
968 void SetupEhdr() {
969 memset(&elf_header_, 0, sizeof(elf_header_));
970 elf_header_.e_ident[EI_MAG0] = ELFMAG0;
971 elf_header_.e_ident[EI_MAG1] = ELFMAG1;
972 elf_header_.e_ident[EI_MAG2] = ELFMAG2;
973 elf_header_.e_ident[EI_MAG3] = ELFMAG3;
974 elf_header_.e_ident[EI_CLASS] = ELFCLASS32;
975 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB;
976 elf_header_.e_ident[EI_VERSION] = EV_CURRENT;
977 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX;
978 elf_header_.e_ident[EI_ABIVERSION] = 0;
979 elf_header_.e_type = ET_DYN;
980 elf_header_.e_version = 1;
981 elf_header_.e_entry = 0;
982 elf_header_.e_ehsize = sizeof(Elf_Ehdr);
983 elf_header_.e_phentsize = sizeof(Elf_Phdr);
984 elf_header_.e_shentsize = sizeof(Elf_Shdr);
985 elf_header_.e_phoff = sizeof(Elf_Ehdr);
986 }
987
988 // Sets up a bunch of the required Dynamic Section entries.
989 // Namely it will initialize all the mandatory ones that it can.
990 // Specifically:
991 // DT_HASH
992 // DT_STRTAB
993 // DT_SYMTAB
994 // DT_SYMENT
995 //
996 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
997 void SetupDynamic() {
998 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_);
999 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, dynsym_builder_.GetStrTab());
1000 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_);
1001 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym));
1002 }
1003
1004 // Sets up the basic dynamic symbols that are needed, namely all those we
1005 // can know already.
1006 //
1007 // Specifically adds:
1008 // oatdata
1009 // oatexec
1010 // oatlastword
1011 void SetupRequiredSymbols() {
1012 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true,
1013 rodata_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1014 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true,
1015 text_builder_.GetSize(), STB_GLOBAL, STT_OBJECT);
1016 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.GetSize() - 4,
1017 true, 4, STB_GLOBAL, STT_OBJECT);
1018 }
1019
1020 void AssignSectionStr(ElfSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> *builder,
1021 std::string* strtab) {
1022 builder->section_.sh_name = strtab->size();
1023 *strtab += builder->name_;
1024 *strtab += '\0';
1025 if (debug_logging_) {
1026 LOG(INFO) << "adding section name \"" << builder->name_ << "\" "
1027 << "to shstrtab at offset " << builder->section_.sh_name;
1028 }
1029 }
1030
1031 struct ElfFilePiece {
1032 ElfFilePiece(const std::string& name, Elf_Word offset, const void* data, Elf_Word size)
1033 : dbg_name_(name), offset_(offset), data_(data), size_(size) {}
1034 ~ElfFilePiece() {}
1035
1036 const std::string& dbg_name_;
1037 Elf_Word offset_;
1038 const void *data_;
1039 Elf_Word size_;
1040 static bool Compare(ElfFilePiece a, ElfFilePiece b) {
1041 return a.offset_ < b.offset_;
1042 }
1043 };
1044
1045 // Write each of the pieces out to the file.
1046 bool WriteOutFile(const std::vector<ElfFilePiece>& pieces) {
1047 // TODO It would be nice if this checked for overlap.
1048 for (auto it = pieces.begin(); it != pieces.end(); ++it) {
1049 if (it->data_) {
1050 if (static_cast<off_t>(it->offset_) != lseek(elf_file_->Fd(), it->offset_, SEEK_SET)) {
1051 PLOG(ERROR) << "Failed to seek to " << it->dbg_name_ << " offset location "
1052 << it->offset_ << " for " << elf_file_->GetPath();
1053 return false;
1054 }
1055 if (!elf_file_->WriteFully(it->data_, it->size_)) {
1056 PLOG(ERROR) << "Failed to write " << it->dbg_name_ << " for " << elf_file_->GetPath();
1057 return false;
1058 }
1059 }
1060 }
1061 return true;
1062 }
1063
1064 bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.GetSize() > 1; }
1065};
1066
1067} // namespace art
1068
1069#endif // ART_COMPILER_ELF_BUILDER_H_