blob: 07976e8880efcccd6a0c91c18792dcc32a848312 [file] [log] [blame]
Andreas Gampe54fc26c2014-09-04 21:47:42 -07001/*
David Srbeckybc90fd02015-04-22 19:40:27 +01002 * Copyright (C) 2015 The Android Open Source Project
Andreas Gampe54fc26c2014-09-04 21:47:42 -07003 *
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
David Srbeckybc90fd02015-04-22 19:40:27 +010020#include <vector>
21
Ian Rogersd582fa42014-11-05 23:46:43 -080022#include "arch/instruction_set.h"
David Srbeckybc90fd02015-04-22 19:40:27 +010023#include "base/unix_file/fd_file.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070024#include "buffered_output_stream.h"
25#include "elf_utils.h"
26#include "file_output_stream.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070027
28namespace art {
29
Andreas Gampe54fc26c2014-09-04 21:47:42 -070030class CodeOutput {
31 public:
32 virtual bool Write(OutputStream* out) = 0;
33 virtual ~CodeOutput() {}
34};
35
David Srbeckybc90fd02015-04-22 19:40:27 +010036// Writes ELF file.
37// The main complication is that the sections often want to reference
38// each other. We solve this by writing the ELF file in two stages:
39// * Sections are asked about their size, and overall layout is calculated.
40// * Sections do the actual writes which may use offsets of other sections.
David Srbecky533c2072015-04-22 12:20:22 +010041template <typename ElfTypes>
Andreas Gampe54fc26c2014-09-04 21:47:42 -070042class ElfBuilder FINAL {
43 public:
David Srbecky533c2072015-04-22 12:20:22 +010044 using Elf_Addr = typename ElfTypes::Addr;
David Srbeckybc90fd02015-04-22 19:40:27 +010045 using Elf_Off = typename ElfTypes::Off;
David Srbecky533c2072015-04-22 12:20:22 +010046 using Elf_Word = typename ElfTypes::Word;
47 using Elf_Sword = typename ElfTypes::Sword;
48 using Elf_Ehdr = typename ElfTypes::Ehdr;
49 using Elf_Shdr = typename ElfTypes::Shdr;
50 using Elf_Sym = typename ElfTypes::Sym;
51 using Elf_Phdr = typename ElfTypes::Phdr;
52 using Elf_Dyn = typename ElfTypes::Dyn;
53
David Srbeckybc90fd02015-04-22 19:40:27 +010054 // Base class of all sections.
55 class Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +010056 public:
David Srbeckybc90fd02015-04-22 19:40:27 +010057 Section(const std::string& name, Elf_Word type, Elf_Word flags,
58 const Section* link, Elf_Word info, Elf_Word align, Elf_Word entsize)
59 : header_(), section_index_(0), name_(name), link_(link) {
60 header_.sh_type = type;
61 header_.sh_flags = flags;
62 header_.sh_info = info;
63 header_.sh_addralign = align;
64 header_.sh_entsize = entsize;
David Srbecky0c5bbc12015-04-28 17:54:52 +010065 }
David Srbeckybc90fd02015-04-22 19:40:27 +010066 virtual ~Section() {}
David Srbecky0c5bbc12015-04-28 17:54:52 +010067
David Srbeckybc90fd02015-04-22 19:40:27 +010068 // Returns the size of the content of this section. It is used to
69 // calculate file offsets of all sections before doing any writes.
70 virtual Elf_Word GetSize() const = 0;
71
72 // Write the content of this section to the given file.
73 // This must write exactly the number of bytes returned by GetSize().
74 // Offsets of all sections are known when this method is called.
75 virtual bool Write(File* elf_file) = 0;
David Srbecky0c5bbc12015-04-28 17:54:52 +010076
77 Elf_Word GetLink() const {
David Srbeckybc90fd02015-04-22 19:40:27 +010078 return (link_ != nullptr) ? link_->GetSectionIndex() : 0;
David Srbecky0c5bbc12015-04-28 17:54:52 +010079 }
80
David Srbeckybc90fd02015-04-22 19:40:27 +010081 const Elf_Shdr* GetHeader() const {
82 return &header_;
David Srbecky0c5bbc12015-04-28 17:54:52 +010083 }
84
David Srbeckybc90fd02015-04-22 19:40:27 +010085 Elf_Shdr* GetHeader() {
86 return &header_;
David Srbecky0c5bbc12015-04-28 17:54:52 +010087 }
88
89 Elf_Word GetSectionIndex() const {
David Srbeckybc90fd02015-04-22 19:40:27 +010090 DCHECK_NE(section_index_, 0u);
David Srbecky0c5bbc12015-04-28 17:54:52 +010091 return section_index_;
92 }
93
94 void SetSectionIndex(Elf_Word section_index) {
95 section_index_ = section_index;
96 }
97
98 const std::string& GetName() const {
99 return name_;
100 }
101
102 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100103 Elf_Shdr header_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100104 Elf_Word section_index_;
105 const std::string name_;
David Srbeckybc90fd02015-04-22 19:40:27 +0100106 const Section* const link_;
107
108 DISALLOW_COPY_AND_ASSIGN(Section);
David Srbecky0c5bbc12015-04-28 17:54:52 +0100109 };
110
David Srbeckybc90fd02015-04-22 19:40:27 +0100111 // Writer of .dynamic section.
112 class DynamicSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100113 public:
David Srbeckybc90fd02015-04-22 19:40:27 +0100114 void AddDynamicTag(Elf_Sword tag, Elf_Word value, const Section* section) {
115 DCHECK_NE(tag, static_cast<Elf_Sword>(DT_NULL));
116 dynamics_.push_back({tag, value, section});
David Srbecky0c5bbc12015-04-28 17:54:52 +0100117 }
118
David Srbeckybc90fd02015-04-22 19:40:27 +0100119 DynamicSection(const std::string& name, Section* link)
120 : Section(name, SHT_DYNAMIC, SHF_ALLOC,
121 link, 0, kPageSize, sizeof(Elf_Dyn)) {}
122
123 Elf_Word GetSize() const OVERRIDE {
124 return (dynamics_.size() + 1 /* DT_NULL */) * sizeof(Elf_Dyn);
David Srbecky0c5bbc12015-04-28 17:54:52 +0100125 }
126
David Srbeckybc90fd02015-04-22 19:40:27 +0100127 bool Write(File* elf_file) OVERRIDE {
128 std::vector<Elf_Dyn> buffer;
129 buffer.reserve(dynamics_.size() + 1u);
130 for (const ElfDynamicState& it : dynamics_) {
131 if (it.section_ != nullptr) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100132 // We are adding an address relative to a section.
David Srbeckybc90fd02015-04-22 19:40:27 +0100133 buffer.push_back(
134 {it.tag_, {it.value_ + it.section_->GetHeader()->sh_addr}});
David Srbecky0c5bbc12015-04-28 17:54:52 +0100135 } else {
David Srbeckybc90fd02015-04-22 19:40:27 +0100136 buffer.push_back({it.tag_, {it.value_}});
David Srbecky0c5bbc12015-04-28 17:54:52 +0100137 }
138 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100139 buffer.push_back({DT_NULL, {0}});
140 return WriteArray(elf_file, buffer.data(), buffer.size());
David Srbecky0c5bbc12015-04-28 17:54:52 +0100141 }
142
143 private:
144 struct ElfDynamicState {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100145 Elf_Sword tag_;
David Srbeckybc90fd02015-04-22 19:40:27 +0100146 Elf_Word value_;
147 const Section* section_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100148 };
149 std::vector<ElfDynamicState> dynamics_;
150 };
151
David Srbeckybc90fd02015-04-22 19:40:27 +0100152 // Section with content based on simple memory buffer.
153 // The buffer can be optionally patched before writing.
154 // The resulting address can be either absolute memory
155 // address or offset relative to the pointer location.
156 class RawSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100157 public:
David Srbeckybc90fd02015-04-22 19:40:27 +0100158 RawSection(const std::string& name, Elf_Word type, Elf_Word flags,
159 const Section* link, Elf_Word info, Elf_Word align, Elf_Word entsize,
160 const Section* patch_base = nullptr, bool patch_relative = false,
161 bool patch_64bit = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)))
162 : Section(name, type, flags, link, info, align, entsize),
163 patched(false), patch_base_(patch_base),
164 patch_relative_(patch_relative), patch_64bit_(patch_64bit) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100165 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100166
David Srbeckybc90fd02015-04-22 19:40:27 +0100167 Elf_Word GetSize() const OVERRIDE {
168 return buffer_.size();
169 }
170
171 bool Write(File* elf_file) OVERRIDE {
172 if (!patch_locations_.empty()) {
173 DCHECK(patch_base_ != nullptr);
174 DCHECK(!patched); // Do not patch twice.
175 if (patch_relative_) {
176 if (patch_64bit_) {
177 Patch<true, uint64_t>();
178 } else {
179 Patch<true, uint32_t>();
180 }
181 } else {
182 if (patch_64bit_) {
183 Patch<false, uint64_t>();
184 } else {
185 Patch<false, uint32_t>();
186 }
187 }
188 patched = true;
189 }
190 return WriteArray(elf_file, buffer_.data(), buffer_.size());
191 }
192
193 bool IsEmpty() const {
194 return buffer_.size() == 0;
195 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100196
197 std::vector<uint8_t>* GetBuffer() {
David Srbeckybc90fd02015-04-22 19:40:27 +0100198 return &buffer_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100199 }
200
David Srbeckybc90fd02015-04-22 19:40:27 +0100201 void SetBuffer(const std::vector<uint8_t>& buffer) {
202 buffer_ = buffer;
203 }
204
205 std::vector<uintptr_t>* GetPatchLocations() {
206 return &patch_locations_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100207 }
208
209 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100210 template <bool RelativeAddress = false, typename PatchedAddress = Elf_Addr>
211 void Patch() {
212 Elf_Addr base_addr = patch_base_->GetHeader()->sh_addr;
213 Elf_Addr addr = this->GetHeader()->sh_addr;
214 for (uintptr_t patch_location : patch_locations_) {
215 typedef __attribute__((__aligned__(1))) PatchedAddress UnalignedAddress;
216 auto* to_patch = reinterpret_cast<UnalignedAddress*>(buffer_.data() + patch_location);
217 *to_patch = (base_addr + *to_patch) - (RelativeAddress ? (addr + patch_location) : 0);
218 }
219 }
220
221 std::vector<uint8_t> buffer_;
222 std::vector<uintptr_t> patch_locations_;
223 bool patched;
224 const Section* patch_base_;
225 bool patch_relative_;
226 bool patch_64bit_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100227 };
228
David Srbeckybc90fd02015-04-22 19:40:27 +0100229 // Writer of .rodata section or .text section.
230 // The write is done lazily using the provided CodeOutput.
231 class OatSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100232 public:
David Srbeckybc90fd02015-04-22 19:40:27 +0100233 OatSection(const std::string& name, Elf_Word type, Elf_Word flags,
234 const Section* link, Elf_Word info, Elf_Word align,
235 Elf_Word entsize, Elf_Word size, CodeOutput* code_output)
236 : Section(name, type, flags, link, info, align, entsize),
237 size_(size), code_output_(code_output) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100238 }
239
David Srbeckybc90fd02015-04-22 19:40:27 +0100240 Elf_Word GetSize() const OVERRIDE {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100241 return size_;
242 }
243
David Srbeckybc90fd02015-04-22 19:40:27 +0100244 bool Write(File* elf_file) OVERRIDE {
245 // The BufferedOutputStream class contains the buffer as field,
246 // therefore it is too big to allocate on the stack.
247 std::unique_ptr<BufferedOutputStream> output_stream(
248 new BufferedOutputStream(new FileOutputStream(elf_file)));
249 return code_output_->Write(output_stream.get());
250 }
251
David Srbecky0c5bbc12015-04-28 17:54:52 +0100252 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100253 Elf_Word size_;
254 CodeOutput* code_output_;
255 };
256
257 // Writer of .bss section.
258 class NoBitsSection FINAL : public Section {
259 public:
260 NoBitsSection(const std::string& name, Elf_Word size)
261 : Section(name, SHT_NOBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
262 size_(size) {
263 }
264
265 Elf_Word GetSize() const OVERRIDE {
266 return size_;
267 }
268
269 bool Write(File* elf_file ATTRIBUTE_UNUSED) OVERRIDE {
270 LOG(ERROR) << "This section should not be written to the ELF file";
271 return false;
272 }
273
274 private:
David Srbecky0c5bbc12015-04-28 17:54:52 +0100275 Elf_Word size_;
276 };
277
David Srbeckybc90fd02015-04-22 19:40:27 +0100278 // Writer of .dynstr .strtab and .shstrtab sections.
279 class StrtabSection FINAL : public Section {
280 public:
281 StrtabSection(const std::string& name, Elf_Word flags)
282 : Section(name, SHT_STRTAB, flags, nullptr, 0, 1, 1) {
283 buffer_.reserve(4 * KB);
284 // The first entry of strtab must be empty string.
285 buffer_ += '\0';
David Srbecky0c5bbc12015-04-28 17:54:52 +0100286 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100287
David Srbeckybc90fd02015-04-22 19:40:27 +0100288 Elf_Word AddName(const std::string& name) {
289 Elf_Word offset = buffer_.size();
290 buffer_ += name;
291 buffer_ += '\0';
292 return offset;
293 }
294
295 Elf_Word GetSize() const OVERRIDE {
296 return buffer_.size();
297 }
298
299 bool Write(File* elf_file) OVERRIDE {
300 return WriteArray(elf_file, buffer_.data(), buffer_.size());
301 }
302
303 private:
304 std::string buffer_;
305 };
306
307 class HashSection;
308
309 // Writer of .dynsym and .symtab sections.
310 class SymtabSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100311 public:
312 // Add a symbol with given name to this symtab. The symbol refers to
313 // 'relative_addr' within the given section and has the given attributes.
David Srbeckybc90fd02015-04-22 19:40:27 +0100314 void AddSymbol(const std::string& name, const Section* section,
315 Elf_Addr addr, bool is_relative, Elf_Word size,
316 uint8_t binding, uint8_t type, uint8_t other = 0) {
317 CHECK(section != nullptr);
318 Elf_Word name_idx = strtab_->AddName(name);
319 symbols_.push_back({ name, section, addr, size, is_relative,
320 MakeStInfo(binding, type), other, name_idx });
David Srbecky0c5bbc12015-04-28 17:54:52 +0100321 }
322
David Srbeckybc90fd02015-04-22 19:40:27 +0100323 SymtabSection(const std::string& name, Elf_Word type, Elf_Word flags,
324 StrtabSection* strtab)
325 : Section(name, type, flags, strtab, 0, sizeof(Elf_Word), sizeof(Elf_Sym)),
326 strtab_(strtab) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100327 }
328
David Srbeckybc90fd02015-04-22 19:40:27 +0100329 bool IsEmpty() const {
330 return symbols_.empty();
331 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100332
David Srbeckybc90fd02015-04-22 19:40:27 +0100333 Elf_Word GetSize() const OVERRIDE {
334 return (1 /* NULL */ + symbols_.size()) * sizeof(Elf_Sym);
335 }
336
337 bool Write(File* elf_file) OVERRIDE {
338 std::vector<Elf_Sym> buffer;
339 buffer.reserve(1u + symbols_.size());
340 buffer.push_back(Elf_Sym()); // NULL.
341 for (const ElfSymbolState& it : symbols_) {
342 Elf_Sym sym = Elf_Sym();
343 sym.st_name = it.name_idx_;
344 if (it.is_relative_) {
345 sym.st_value = it.addr_ + it.section_->GetHeader()->sh_addr;
346 } else {
347 sym.st_value = it.addr_;
348 }
349 sym.st_size = it.size_;
350 sym.st_other = it.other_;
351 sym.st_shndx = it.section_->GetSectionIndex();
352 sym.st_info = it.info_;
353 buffer.push_back(sym);
354 }
355 return WriteArray(elf_file, buffer.data(), buffer.size());
356 }
357
358 private:
359 struct ElfSymbolState {
360 const std::string name_;
361 const Section* section_;
362 Elf_Addr addr_;
363 Elf_Word size_;
364 bool is_relative_;
365 uint8_t info_;
366 uint8_t other_;
367 Elf_Word name_idx_; // index in the strtab.
368 };
369
370 static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
371 return ((binding) << 4) + ((type) & 0xf);
372 }
373
374 // The symbols in the same order they will be in the symbol table.
375 std::vector<ElfSymbolState> symbols_;
376 StrtabSection* strtab_;
377
378 friend class HashSection;
379 };
380
381 // TODO: Consider removing.
382 // We use it only for the dynsym section which has only 5 symbols.
383 // We do not use it for symtab, and we probably do not have to
384 // since we use those symbols only to print backtraces.
385 class HashSection FINAL : public Section {
386 public:
387 HashSection(const std::string& name, Elf_Word flags, SymtabSection* symtab)
388 : Section(name, SHT_HASH, flags, symtab,
389 0, sizeof(Elf_Word), sizeof(Elf_Word)),
390 symtab_(symtab) {
391 }
392
393 Elf_Word GetSize() const OVERRIDE {
394 Elf_Word nbuckets = GetNumBuckets();
395 Elf_Word chain_size = symtab_->symbols_.size() + 1 /* NULL */;
396 return (2 /* header */ + nbuckets + chain_size) * sizeof(Elf_Word);
397 }
398
399 bool Write(File* const elf_file) OVERRIDE {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100400 // Here is how The ELF hash table works.
401 // There are 3 arrays to worry about.
402 // * The symbol table where the symbol information is.
403 // * The bucket array which is an array of indexes into the symtab and chain.
404 // * The chain array which is also an array of indexes into the symtab and chain.
405 //
406 // Lets say the state is something like this.
407 // +--------+ +--------+ +-----------+
408 // | symtab | | bucket | | chain |
409 // | null | | 1 | | STN_UNDEF |
410 // | <sym1> | | 4 | | 2 |
411 // | <sym2> | | | | 5 |
412 // | <sym3> | | | | STN_UNDEF |
413 // | <sym4> | | | | 3 |
414 // | <sym5> | | | | STN_UNDEF |
415 // +--------+ +--------+ +-----------+
416 //
417 // The lookup process (in python psudocode) is
418 //
419 // def GetSym(name):
420 // # NB STN_UNDEF == 0
421 // indx = bucket[elfhash(name) % num_buckets]
422 // while indx != STN_UNDEF:
423 // if GetSymbolName(symtab[indx]) == name:
424 // return symtab[indx]
425 // indx = chain[indx]
426 // return SYMBOL_NOT_FOUND
427 //
428 // Between bucket and chain arrays every symtab index must be present exactly
429 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
David Srbeckybc90fd02015-04-22 19:40:27 +0100430 const auto& symbols = symtab_->symbols_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100431 // Select number of buckets.
432 // This is essentially arbitrary.
David Srbeckybc90fd02015-04-22 19:40:27 +0100433 Elf_Word nbuckets = GetNumBuckets();
434 // 1 is for the implicit NULL symbol.
435 Elf_Word chain_size = (symbols.size() + 1);
David Srbecky0c5bbc12015-04-28 17:54:52 +0100436 std::vector<Elf_Word> hash;
437 hash.push_back(nbuckets);
438 hash.push_back(chain_size);
439 uint32_t bucket_offset = hash.size();
440 uint32_t chain_offset = bucket_offset + nbuckets;
441 hash.resize(hash.size() + nbuckets + chain_size, 0);
442
443 Elf_Word* buckets = hash.data() + bucket_offset;
444 Elf_Word* chain = hash.data() + chain_offset;
445
446 // Set up the actual hash table.
David Srbeckybc90fd02015-04-22 19:40:27 +0100447 for (Elf_Word i = 0; i < symbols.size(); i++) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100448 // Add 1 since we need to have the null symbol that is not in the symbols
449 // list.
450 Elf_Word index = i + 1;
David Srbeckybc90fd02015-04-22 19:40:27 +0100451 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols[i].name_.c_str())) % nbuckets;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100452 if (buckets[hash_val] == 0) {
453 buckets[hash_val] = index;
454 } else {
455 hash_val = buckets[hash_val];
456 CHECK_LT(hash_val, chain_size);
457 while (chain[hash_val] != 0) {
458 hash_val = chain[hash_val];
459 CHECK_LT(hash_val, chain_size);
460 }
461 chain[hash_val] = index;
462 // Check for loops. Works because if this is non-empty then there must be
463 // another cell which already contains the same symbol index as this one,
464 // which means some symbol has more then one name, which isn't allowed.
465 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
466 }
467 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100468 return WriteArray(elf_file, hash.data(), hash.size());
David Srbecky0c5bbc12015-04-28 17:54:52 +0100469 }
470
471 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100472 Elf_Word GetNumBuckets() const {
473 const auto& symbols = symtab_->symbols_;
474 if (symbols.size() < 8) {
475 return 2;
476 } else if (symbols.size() < 32) {
477 return 4;
478 } else if (symbols.size() < 256) {
479 return 16;
480 } else {
481 // Have about 32 ids per bucket.
482 return RoundUp(symbols.size()/32, 2);
David Srbecky0c5bbc12015-04-28 17:54:52 +0100483 }
484 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100485
David Srbeckybc90fd02015-04-22 19:40:27 +0100486 // from bionic
487 static inline unsigned elfhash(const char *_name) {
488 const unsigned char *name = (const unsigned char *) _name;
489 unsigned h = 0, g;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100490
David Srbeckybc90fd02015-04-22 19:40:27 +0100491 while (*name) {
492 h = (h << 4) + *name++;
493 g = h & 0xf0000000;
494 h ^= g;
495 h ^= g >> 24;
496 }
497 return h;
498 }
499
500 SymtabSection* symtab_;
501
502 DISALLOW_COPY_AND_ASSIGN(HashSection);
503 };
504
505 ElfBuilder(InstructionSet isa,
506 Elf_Word rodata_size, CodeOutput* rodata_writer,
507 Elf_Word text_size, CodeOutput* text_writer,
508 Elf_Word bss_size)
509 : isa_(isa),
510 dynstr_(".dynstr", SHF_ALLOC),
511 dynsym_(".dynsym", SHT_DYNSYM, SHF_ALLOC, &dynstr_),
512 hash_(".hash", SHF_ALLOC, &dynsym_),
513 rodata_(".rodata", SHT_PROGBITS, SHF_ALLOC,
514 nullptr, 0, kPageSize, 0, rodata_size, rodata_writer),
515 text_(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR,
516 nullptr, 0, kPageSize, 0, text_size, text_writer),
517 bss_(".bss", bss_size),
518 dynamic_(".dynamic", &dynsym_),
519 strtab_(".strtab", 0),
520 symtab_(".symtab", SHT_SYMTAB, 0, &strtab_),
521 shstrtab_(".shstrtab", 0) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700522 }
523 ~ElfBuilder() {}
524
David Srbeckybc90fd02015-04-22 19:40:27 +0100525 OatSection* GetText() { return &text_; }
526 SymtabSection* GetSymtab() { return &symtab_; }
Ian Rogers0279ebb2014-10-08 17:27:48 -0700527
David Srbeckybc90fd02015-04-22 19:40:27 +0100528 bool Write(File* elf_file) {
Vladimir Marko5c42c292015-02-25 12:02:49 +0000529 // Since the .text section of an oat file contains relative references to .rodata
530 // and (optionally) .bss, we keep these 2 or 3 sections together. This creates
531 // a non-traditional layout where the .bss section is mapped independently of the
532 // .dynamic section and needs its own program header with LOAD RW.
533 //
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700534 // The basic layout of the elf file. Order may be different in final output.
535 // +-------------------------+
536 // | Elf_Ehdr |
537 // +-------------------------+
538 // | Elf_Phdr PHDR |
David Srbeckyb0a962c2015-04-28 19:43:56 +0100539 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700540 // | Elf_Phdr LOAD R X | .text
Vladimir Marko5c42c292015-02-25 12:02:49 +0000541 // | Elf_Phdr LOAD RW | .bss (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700542 // | Elf_Phdr LOAD RW | .dynamic
543 // | Elf_Phdr DYNAMIC | .dynamic
David Srbeckyb0a962c2015-04-28 19:43:56 +0100544 // | Elf_Phdr LOAD R | .eh_frame .eh_frame_hdr
David Srbecky527c9c72015-04-17 21:14:10 +0100545 // | Elf_Phdr EH_FRAME R | .eh_frame_hdr
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700546 // +-------------------------+
547 // | .dynsym |
548 // | Elf_Sym STN_UNDEF |
549 // | Elf_Sym oatdata |
550 // | Elf_Sym oatexec |
551 // | Elf_Sym oatlastword |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000552 // | Elf_Sym oatbss | (Optional)
553 // | Elf_Sym oatbsslastword | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700554 // +-------------------------+
555 // | .dynstr |
David Srbeckybc90fd02015-04-22 19:40:27 +0100556 // | names for .dynsym |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700557 // +-------------------------+
558 // | .hash |
David Srbeckybc90fd02015-04-22 19:40:27 +0100559 // | hashtable for dynsym |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700560 // +-------------------------+
561 // | .rodata |
562 // | oatdata..oatexec-4 |
563 // +-------------------------+
564 // | .text |
565 // | oatexec..oatlastword |
566 // +-------------------------+
567 // | .dynamic |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700568 // | Elf_Dyn DT_HASH |
David Srbeckybc90fd02015-04-22 19:40:27 +0100569 // | Elf_Dyn DT_STRTAB |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700570 // | Elf_Dyn DT_SYMTAB |
571 // | Elf_Dyn DT_SYMENT |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700572 // | Elf_Dyn DT_STRSZ |
David Srbeckybc90fd02015-04-22 19:40:27 +0100573 // | Elf_Dyn DT_SONAME |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700574 // | Elf_Dyn DT_NULL |
575 // +-------------------------+ (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700576 // | .symtab | (Optional)
577 // | program symbols | (Optional)
David Srbeckybc90fd02015-04-22 19:40:27 +0100578 // +-------------------------+ (Optional)
579 // | .strtab | (Optional)
580 // | names for .symtab | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700581 // +-------------------------+ (Optional)
David Srbeckyb0a962c2015-04-28 19:43:56 +0100582 // | .eh_frame | (Optional)
583 // +-------------------------+ (Optional)
584 // | .eh_frame_hdr | (Optional)
585 // +-------------------------+ (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700586 // | .debug_info | (Optional)
587 // +-------------------------+ (Optional)
588 // | .debug_abbrev | (Optional)
589 // +-------------------------+ (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100590 // | .debug_str | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700591 // +-------------------------+ (Optional)
592 // | .debug_line | (Optional)
David Srbeckybc90fd02015-04-22 19:40:27 +0100593 // +-------------------------+
594 // | .shstrtab |
595 // | names of sections |
596 // +-------------------------+
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700597 // | Elf_Shdr null |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700598 // | Elf_Shdr .dynsym |
599 // | Elf_Shdr .dynstr |
600 // | Elf_Shdr .hash |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700601 // | Elf_Shdr .rodata |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000602 // | Elf_Shdr .text |
603 // | Elf_Shdr .bss | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700604 // | Elf_Shdr .dynamic |
David Srbeckybc90fd02015-04-22 19:40:27 +0100605 // | Elf_Shdr .symtab | (Optional)
606 // | Elf_Shdr .strtab | (Optional)
David Srbeckyb0a962c2015-04-28 19:43:56 +0100607 // | Elf_Shdr .eh_frame | (Optional)
608 // | Elf_Shdr .eh_frame_hdr | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700609 // | Elf_Shdr .debug_info | (Optional)
610 // | Elf_Shdr .debug_abbrev | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700611 // | Elf_Shdr .debug_str | (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100612 // | Elf_Shdr .debug_line | (Optional)
David Srbeckybc90fd02015-04-22 19:40:27 +0100613 // | Elf_Shdr .oat_patches | (Optional)
614 // | Elf_Shdr .shstrtab |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700615 // +-------------------------+
David Srbeckybc90fd02015-04-22 19:40:27 +0100616 constexpr bool debug_logging_ = false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700617
David Srbeckybc90fd02015-04-22 19:40:27 +0100618 // Create a list of all section which we want to write.
619 // This is the order in which they will be written.
620 std::vector<Section*> sections;
621 sections.push_back(&dynsym_);
622 sections.push_back(&dynstr_);
623 sections.push_back(&hash_);
David Srbeckybc90fd02015-04-22 19:40:27 +0100624 sections.push_back(&rodata_);
625 sections.push_back(&text_);
626 if (bss_.GetSize() != 0u) {
627 sections.push_back(&bss_);
Vladimir Marko5c42c292015-02-25 12:02:49 +0000628 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100629 sections.push_back(&dynamic_);
630 if (!symtab_.IsEmpty()) {
631 sections.push_back(&symtab_);
632 sections.push_back(&strtab_);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700633 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100634 for (Section* section : other_sections_) {
David Srbeckyb0a962c2015-04-28 19:43:56 +0100635 sections.push_back(section);
David Srbecky527c9c72015-04-17 21:14:10 +0100636 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100637 sections.push_back(&shstrtab_);
638 for (size_t i = 0; i < sections.size(); i++) {
639 // The first section index is 1. Index 0 is reserved for NULL.
640 // Section index is used for relative symbols and for section links.
641 sections[i]->SetSectionIndex(i + 1);
642 // Add section name to .shstrtab.
643 Elf_Word name_offset = shstrtab_.AddName(sections[i]->GetName());
644 sections[i]->GetHeader()->sh_name = name_offset;
David Srbecky527c9c72015-04-17 21:14:10 +0100645 }
646
David Srbeckybc90fd02015-04-22 19:40:27 +0100647 // The running program does not have access to section headers
648 // and the loader is not supposed to use them either.
649 // The dynamic sections therefore replicates some of the layout
650 // information like the address and size of .rodata and .text.
651 // It also contains other metadata like the SONAME.
652 // The .dynamic section is found using the PT_DYNAMIC program header.
653 BuildDynsymSection();
654 BuildDynamicSection(elf_file->GetPath());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700655
David Srbeckybc90fd02015-04-22 19:40:27 +0100656 // We do not know the number of headers until the final stages of write.
657 // It is easiest to just reserve a fixed amount of space for them.
David Srbeckyb0a962c2015-04-28 19:43:56 +0100658 constexpr size_t kMaxProgramHeaders = 8;
David Srbeckybc90fd02015-04-22 19:40:27 +0100659 constexpr size_t kProgramHeadersOffset = sizeof(Elf_Ehdr);
660 constexpr size_t kProgramHeadersSize = sizeof(Elf_Phdr) * kMaxProgramHeaders;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700661
David Srbeckybc90fd02015-04-22 19:40:27 +0100662 // Layout of all sections - determine the final file offsets and addresses.
663 // This must be done after we have built all sections and know their size.
664 Elf_Off file_offset = kProgramHeadersOffset + kProgramHeadersSize;
665 Elf_Addr load_address = file_offset;
666 std::vector<Elf_Shdr> section_headers;
667 section_headers.reserve(1u + sections.size());
668 section_headers.push_back(Elf_Shdr()); // NULL at index 0.
669 for (auto* section : sections) {
670 Elf_Shdr* header = section->GetHeader();
671 Elf_Off alignment = header->sh_addralign > 0 ? header->sh_addralign : 1;
672 header->sh_size = section->GetSize();
673 header->sh_link = section->GetLink();
674 // Allocate memory for the section in the file.
675 if (header->sh_type != SHT_NOBITS) {
676 header->sh_offset = RoundUp(file_offset, alignment);
677 file_offset = header->sh_offset + header->sh_size;
678 }
679 // Allocate memory for the section during program execution.
680 if ((header->sh_flags & SHF_ALLOC) != 0) {
681 header->sh_addr = RoundUp(load_address, alignment);
682 load_address = header->sh_addr + header->sh_size;
683 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700684 if (debug_logging_) {
David Srbeckybc90fd02015-04-22 19:40:27 +0100685 LOG(INFO) << "Section " << section->GetName() << ":" << std::hex
686 << " offset=0x" << header->sh_offset
687 << " addr=0x" << header->sh_addr
688 << " size=0x" << header->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700689 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100690 // Collect section headers into continuous array for convenience.
691 section_headers.push_back(*header);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700692 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100693 Elf_Off section_headers_offset = RoundUp(file_offset, sizeof(Elf_Word));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700694
David Srbeckybc90fd02015-04-22 19:40:27 +0100695 // Create program headers now that we know the layout of the whole file.
696 // Each segment contains one or more sections which are mapped together.
697 // Not all sections are mapped during the execution of the program.
698 // PT_LOAD does the mapping. Other PT_* types allow the program to locate
699 // interesting parts of memory and their addresses overlap with PT_LOAD.
700 std::vector<Elf_Phdr> program_headers;
701 program_headers.push_back(MakeProgramHeader(PT_PHDR, PF_R,
702 kProgramHeadersOffset, kProgramHeadersSize, sizeof(Elf_Word)));
703 // Create the main LOAD R segment which spans all sections up to .rodata.
704 const Elf_Shdr* rodata = rodata_.GetHeader();
705 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R,
706 0, rodata->sh_offset + rodata->sh_size, rodata->sh_addralign));
707 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_X, text_));
708 if (bss_.GetHeader()->sh_size != 0u) {
709 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_W, bss_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700710 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100711 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_W, dynamic_));
712 program_headers.push_back(MakeProgramHeader(PT_DYNAMIC, PF_R | PF_W, dynamic_));
David Srbeckyb0a962c2015-04-28 19:43:56 +0100713 const Section* eh_frame = FindSection(".eh_frame");
714 if (eh_frame != nullptr) {
715 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R, *eh_frame));
716 const Section* eh_frame_hdr = FindSection(".eh_frame_hdr");
717 if (eh_frame_hdr != nullptr) {
718 // Check layout: eh_frame is before eh_frame_hdr and there is no gap.
719 CHECK_LE(eh_frame->GetHeader()->sh_offset, eh_frame_hdr->GetHeader()->sh_offset);
720 CHECK_EQ(eh_frame->GetHeader()->sh_offset + eh_frame->GetHeader()->sh_size,
721 eh_frame_hdr->GetHeader()->sh_offset);
722 // Extend the PT_LOAD of .eh_frame to include the .eh_frame_hdr as well.
723 program_headers.back().p_filesz += eh_frame_hdr->GetHeader()->sh_size;
724 program_headers.back().p_memsz += eh_frame_hdr->GetHeader()->sh_size;
725 program_headers.push_back(MakeProgramHeader(PT_GNU_EH_FRAME, PF_R, *eh_frame_hdr));
726 }
David Srbecky527c9c72015-04-17 21:14:10 +0100727 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100728 CHECK_LE(program_headers.size(), kMaxProgramHeaders);
David Srbecky527c9c72015-04-17 21:14:10 +0100729
David Srbeckybc90fd02015-04-22 19:40:27 +0100730 // Create the main ELF header.
731 Elf_Ehdr elf_header = MakeElfHeader(isa_);
732 elf_header.e_phoff = kProgramHeadersOffset;
733 elf_header.e_shoff = section_headers_offset;
734 elf_header.e_phnum = program_headers.size();
735 elf_header.e_shnum = section_headers.size();
736 elf_header.e_shstrndx = shstrtab_.GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700737
David Srbeckybc90fd02015-04-22 19:40:27 +0100738 // Write all headers and section content to the file.
739 // Depending on the implementations of Section::Write, this
740 // might be just memory copies or some more elaborate operations.
741 if (!WriteArray(elf_file, &elf_header, 1)) {
742 LOG(INFO) << "Failed to write the ELF header";
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700743 return false;
744 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100745 if (!WriteArray(elf_file, program_headers.data(), program_headers.size())) {
746 LOG(INFO) << "Failed to write the program headers";
747 return false;
748 }
749 for (Section* section : sections) {
750 const Elf_Shdr* header = section->GetHeader();
751 if (header->sh_type != SHT_NOBITS) {
752 if (!SeekTo(elf_file, header->sh_offset) || !section->Write(elf_file)) {
753 LOG(INFO) << "Failed to write section " << section->GetName();
754 return false;
755 }
756 Elf_Word current_offset = lseek(elf_file->Fd(), 0, SEEK_CUR);
757 CHECK_EQ(current_offset, header->sh_offset + header->sh_size)
758 << "The number of bytes written does not match GetSize()";
759 }
760 }
761 if (!SeekTo(elf_file, section_headers_offset) ||
762 !WriteArray(elf_file, section_headers.data(), section_headers.size())) {
763 LOG(INFO) << "Failed to write the section headers";
764 return false;
765 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700766 return true;
767 }
768
David Srbeckybc90fd02015-04-22 19:40:27 +0100769 // Adds the given section to the builder. It does not take ownership.
770 void RegisterSection(Section* section) {
771 other_sections_.push_back(section);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700772 }
773
David Srbeckybc90fd02015-04-22 19:40:27 +0100774 const Section* FindSection(const char* name) {
775 for (const auto* section : other_sections_) {
776 if (section->GetName() == name) {
777 return section;
David Srbecky527c9c72015-04-17 21:14:10 +0100778 }
779 }
780 return nullptr;
781 }
782
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700783 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100784 static bool SeekTo(File* elf_file, Elf_Word offset) {
785 DCHECK_LE(lseek(elf_file->Fd(), 0, SEEK_CUR), static_cast<off_t>(offset))
786 << "Seeking backwards";
787 if (static_cast<off_t>(offset) != lseek(elf_file->Fd(), offset, SEEK_SET)) {
788 PLOG(ERROR) << "Failed to seek in file " << elf_file->GetPath();
789 return false;
790 }
791 return true;
792 }
793
794 template<typename T>
795 static bool WriteArray(File* elf_file, const T* data, size_t count) {
796 DCHECK(data != nullptr);
797 if (!elf_file->WriteFully(data, count * sizeof(T))) {
798 PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
799 return false;
800 }
801 return true;
802 }
803
804 // Helper - create segment header based on memory range.
805 static Elf_Phdr MakeProgramHeader(Elf_Word type, Elf_Word flags,
806 Elf_Off offset, Elf_Word size, Elf_Word align) {
807 Elf_Phdr phdr = Elf_Phdr();
808 phdr.p_type = type;
809 phdr.p_flags = flags;
810 phdr.p_offset = offset;
811 phdr.p_vaddr = offset;
812 phdr.p_paddr = offset;
813 phdr.p_filesz = size;
814 phdr.p_memsz = size;
815 phdr.p_align = align;
816 return phdr;
817 }
818
819 // Helper - create segment header based on section header.
820 static Elf_Phdr MakeProgramHeader(Elf_Word type, Elf_Word flags,
821 const Section& section) {
822 const Elf_Shdr* shdr = section.GetHeader();
823 // Only run-time allocated sections should be in segment headers.
824 CHECK_NE(shdr->sh_flags & SHF_ALLOC, 0u);
825 Elf_Phdr phdr = Elf_Phdr();
826 phdr.p_type = type;
827 phdr.p_flags = flags;
828 phdr.p_offset = shdr->sh_offset;
829 phdr.p_vaddr = shdr->sh_addr;
830 phdr.p_paddr = shdr->sh_addr;
831 phdr.p_filesz = shdr->sh_type != SHT_NOBITS ? shdr->sh_size : 0u;
832 phdr.p_memsz = shdr->sh_size;
833 phdr.p_align = shdr->sh_addralign;
834 return phdr;
835 }
836
837 static Elf_Ehdr MakeElfHeader(InstructionSet isa) {
838 Elf_Ehdr elf_header = Elf_Ehdr();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700839 switch (isa) {
840 case kArm:
841 // Fall through.
842 case kThumb2: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100843 elf_header.e_machine = EM_ARM;
844 elf_header.e_flags = EF_ARM_EABI_VER5;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700845 break;
846 }
847 case kArm64: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100848 elf_header.e_machine = EM_AARCH64;
849 elf_header.e_flags = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700850 break;
851 }
852 case kX86: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100853 elf_header.e_machine = EM_386;
854 elf_header.e_flags = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700855 break;
856 }
857 case kX86_64: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100858 elf_header.e_machine = EM_X86_64;
859 elf_header.e_flags = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700860 break;
861 }
862 case kMips: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100863 elf_header.e_machine = EM_MIPS;
864 elf_header.e_flags = (EF_MIPS_NOREORDER |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700865 EF_MIPS_PIC |
866 EF_MIPS_CPIC |
867 EF_MIPS_ABI_O32 |
868 EF_MIPS_ARCH_32R2);
869 break;
870 }
Andreas Gampe57b34292015-01-14 15:45:59 -0800871 case kMips64: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100872 elf_header.e_machine = EM_MIPS;
873 elf_header.e_flags = (EF_MIPS_NOREORDER |
Andreas Gampe57b34292015-01-14 15:45:59 -0800874 EF_MIPS_PIC |
875 EF_MIPS_CPIC |
876 EF_MIPS_ARCH_64R6);
877 break;
878 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100879 case kNone: {
880 LOG(FATAL) << "No instruction set";
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700881 }
882 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700883
David Srbeckybc90fd02015-04-22 19:40:27 +0100884 elf_header.e_ident[EI_MAG0] = ELFMAG0;
885 elf_header.e_ident[EI_MAG1] = ELFMAG1;
886 elf_header.e_ident[EI_MAG2] = ELFMAG2;
887 elf_header.e_ident[EI_MAG3] = ELFMAG3;
888 elf_header.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
Tong Shen62d1ca32014-09-03 17:24:56 -0700889 ? ELFCLASS32 : ELFCLASS64;;
David Srbeckybc90fd02015-04-22 19:40:27 +0100890 elf_header.e_ident[EI_DATA] = ELFDATA2LSB;
891 elf_header.e_ident[EI_VERSION] = EV_CURRENT;
892 elf_header.e_ident[EI_OSABI] = ELFOSABI_LINUX;
893 elf_header.e_ident[EI_ABIVERSION] = 0;
894 elf_header.e_type = ET_DYN;
895 elf_header.e_version = 1;
896 elf_header.e_entry = 0;
897 elf_header.e_ehsize = sizeof(Elf_Ehdr);
898 elf_header.e_phentsize = sizeof(Elf_Phdr);
899 elf_header.e_shentsize = sizeof(Elf_Shdr);
900 elf_header.e_phoff = sizeof(Elf_Ehdr);
901 return elf_header;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700902 }
903
David Srbeckybc90fd02015-04-22 19:40:27 +0100904 void BuildDynamicSection(const std::string& elf_file_path) {
905 std::string soname(elf_file_path);
906 size_t directory_separator_pos = soname.rfind('/');
907 if (directory_separator_pos != std::string::npos) {
908 soname = soname.substr(directory_separator_pos + 1);
909 }
910 // NB: We must add the name before adding DT_STRSZ.
911 Elf_Word soname_offset = dynstr_.AddName(soname);
912
913 dynamic_.AddDynamicTag(DT_HASH, 0, &hash_);
914 dynamic_.AddDynamicTag(DT_STRTAB, 0, &dynstr_);
915 dynamic_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_);
916 dynamic_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym), nullptr);
917 dynamic_.AddDynamicTag(DT_STRSZ, dynstr_.GetSize(), nullptr);
918 dynamic_.AddDynamicTag(DT_SONAME, soname_offset, nullptr);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700919 }
920
David Srbeckybc90fd02015-04-22 19:40:27 +0100921 void BuildDynsymSection() {
922 dynsym_.AddSymbol("oatdata", &rodata_, 0, true,
923 rodata_.GetSize(), STB_GLOBAL, STT_OBJECT);
924 dynsym_.AddSymbol("oatexec", &text_, 0, true,
925 text_.GetSize(), STB_GLOBAL, STT_OBJECT);
926 dynsym_.AddSymbol("oatlastword", &text_, text_.GetSize() - 4,
927 true, 4, STB_GLOBAL, STT_OBJECT);
928 if (bss_.GetSize() != 0u) {
929 dynsym_.AddSymbol("oatbss", &bss_, 0, true,
930 bss_.GetSize(), STB_GLOBAL, STT_OBJECT);
931 dynsym_.AddSymbol("oatbsslastword", &bss_, bss_.GetSize() - 4,
932 true, 4, STB_GLOBAL, STT_OBJECT);
Vladimir Marko5c42c292015-02-25 12:02:49 +0000933 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700934 }
935
David Srbeckybc90fd02015-04-22 19:40:27 +0100936 InstructionSet isa_;
937 StrtabSection dynstr_;
938 SymtabSection dynsym_;
939 HashSection hash_;
940 OatSection rodata_;
941 OatSection text_;
942 NoBitsSection bss_;
943 DynamicSection dynamic_;
944 StrtabSection strtab_;
945 SymtabSection symtab_;
946 std::vector<Section*> other_sections_;
947 StrtabSection shstrtab_;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700948
949 DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700950};
951
952} // namespace art
953
954#endif // ART_COMPILER_ELF_BUILDER_H_