blob: 63d3a0dabbee7870aef44c2e0b37eb7b32ebb2ee [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 Srbecky033d7452015-04-30 19:57:35 +0100152 using PatchFn = void (*)(const std::vector<uintptr_t>& patch_locations,
153 Elf_Addr buffer_address,
154 Elf_Addr base_address,
155 std::vector<uint8_t>* buffer);
156
David Srbeckybc90fd02015-04-22 19:40:27 +0100157 // Section with content based on simple memory buffer.
158 // The buffer can be optionally patched before writing.
David Srbeckybc90fd02015-04-22 19:40:27 +0100159 class RawSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100160 public:
David Srbeckybc90fd02015-04-22 19:40:27 +0100161 RawSection(const std::string& name, Elf_Word type, Elf_Word flags,
162 const Section* link, Elf_Word info, Elf_Word align, Elf_Word entsize,
David Srbecky033d7452015-04-30 19:57:35 +0100163 PatchFn patch = nullptr, const Section* patch_base_section = nullptr)
David Srbeckybc90fd02015-04-22 19:40:27 +0100164 : Section(name, type, flags, link, info, align, entsize),
David Srbecky033d7452015-04-30 19:57:35 +0100165 patched_(false), patch_(patch), patch_base_section_(patch_base_section) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100166 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100167
David Srbeckybc90fd02015-04-22 19:40:27 +0100168 Elf_Word GetSize() const OVERRIDE {
169 return buffer_.size();
170 }
171
172 bool Write(File* elf_file) OVERRIDE {
173 if (!patch_locations_.empty()) {
David Srbecky033d7452015-04-30 19:57:35 +0100174 DCHECK(!patched_); // Do not patch twice.
175 DCHECK(patch_ != nullptr);
176 DCHECK(patch_base_section_ != nullptr);
177 patch_(patch_locations_,
178 this->GetHeader()->sh_addr,
179 patch_base_section_->GetHeader()->sh_addr,
180 &buffer_);
181 patched_ = true;
David Srbeckybc90fd02015-04-22 19:40:27 +0100182 }
183 return WriteArray(elf_file, buffer_.data(), buffer_.size());
184 }
185
186 bool IsEmpty() const {
187 return buffer_.size() == 0;
188 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100189
190 std::vector<uint8_t>* GetBuffer() {
David Srbeckybc90fd02015-04-22 19:40:27 +0100191 return &buffer_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100192 }
193
David Srbeckybc90fd02015-04-22 19:40:27 +0100194 void SetBuffer(const std::vector<uint8_t>& buffer) {
195 buffer_ = buffer;
196 }
197
198 std::vector<uintptr_t>* GetPatchLocations() {
199 return &patch_locations_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100200 }
201
202 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100203 std::vector<uint8_t> buffer_;
204 std::vector<uintptr_t> patch_locations_;
David Srbecky033d7452015-04-30 19:57:35 +0100205 bool patched_;
206 // User-provided function to do the actual patching.
207 PatchFn patch_;
208 // The section that we patch against (usually .text).
209 const Section* patch_base_section_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100210 };
211
David Srbeckybc90fd02015-04-22 19:40:27 +0100212 // Writer of .rodata section or .text section.
213 // The write is done lazily using the provided CodeOutput.
214 class OatSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100215 public:
David Srbeckybc90fd02015-04-22 19:40:27 +0100216 OatSection(const std::string& name, Elf_Word type, Elf_Word flags,
217 const Section* link, Elf_Word info, Elf_Word align,
218 Elf_Word entsize, Elf_Word size, CodeOutput* code_output)
219 : Section(name, type, flags, link, info, align, entsize),
220 size_(size), code_output_(code_output) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100221 }
222
David Srbeckybc90fd02015-04-22 19:40:27 +0100223 Elf_Word GetSize() const OVERRIDE {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100224 return size_;
225 }
226
David Srbeckybc90fd02015-04-22 19:40:27 +0100227 bool Write(File* elf_file) OVERRIDE {
228 // The BufferedOutputStream class contains the buffer as field,
229 // therefore it is too big to allocate on the stack.
230 std::unique_ptr<BufferedOutputStream> output_stream(
231 new BufferedOutputStream(new FileOutputStream(elf_file)));
232 return code_output_->Write(output_stream.get());
233 }
234
David Srbecky0c5bbc12015-04-28 17:54:52 +0100235 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100236 Elf_Word size_;
237 CodeOutput* code_output_;
238 };
239
240 // Writer of .bss section.
241 class NoBitsSection FINAL : public Section {
242 public:
243 NoBitsSection(const std::string& name, Elf_Word size)
244 : Section(name, SHT_NOBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
245 size_(size) {
246 }
247
248 Elf_Word GetSize() const OVERRIDE {
249 return size_;
250 }
251
252 bool Write(File* elf_file ATTRIBUTE_UNUSED) OVERRIDE {
253 LOG(ERROR) << "This section should not be written to the ELF file";
254 return false;
255 }
256
257 private:
David Srbecky0c5bbc12015-04-28 17:54:52 +0100258 Elf_Word size_;
259 };
260
David Srbeckybc90fd02015-04-22 19:40:27 +0100261 // Writer of .dynstr .strtab and .shstrtab sections.
262 class StrtabSection FINAL : public Section {
263 public:
264 StrtabSection(const std::string& name, Elf_Word flags)
265 : Section(name, SHT_STRTAB, flags, nullptr, 0, 1, 1) {
266 buffer_.reserve(4 * KB);
267 // The first entry of strtab must be empty string.
268 buffer_ += '\0';
David Srbecky0c5bbc12015-04-28 17:54:52 +0100269 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100270
David Srbeckybc90fd02015-04-22 19:40:27 +0100271 Elf_Word AddName(const std::string& name) {
272 Elf_Word offset = buffer_.size();
273 buffer_ += name;
274 buffer_ += '\0';
275 return offset;
276 }
277
278 Elf_Word GetSize() const OVERRIDE {
279 return buffer_.size();
280 }
281
282 bool Write(File* elf_file) OVERRIDE {
283 return WriteArray(elf_file, buffer_.data(), buffer_.size());
284 }
285
286 private:
287 std::string buffer_;
288 };
289
290 class HashSection;
291
292 // Writer of .dynsym and .symtab sections.
293 class SymtabSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100294 public:
295 // Add a symbol with given name to this symtab. The symbol refers to
296 // 'relative_addr' within the given section and has the given attributes.
David Srbeckybc90fd02015-04-22 19:40:27 +0100297 void AddSymbol(const std::string& name, const Section* section,
298 Elf_Addr addr, bool is_relative, Elf_Word size,
299 uint8_t binding, uint8_t type, uint8_t other = 0) {
300 CHECK(section != nullptr);
301 Elf_Word name_idx = strtab_->AddName(name);
302 symbols_.push_back({ name, section, addr, size, is_relative,
303 MakeStInfo(binding, type), other, name_idx });
David Srbecky0c5bbc12015-04-28 17:54:52 +0100304 }
305
David Srbeckybc90fd02015-04-22 19:40:27 +0100306 SymtabSection(const std::string& name, Elf_Word type, Elf_Word flags,
307 StrtabSection* strtab)
308 : Section(name, type, flags, strtab, 0, sizeof(Elf_Word), sizeof(Elf_Sym)),
309 strtab_(strtab) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100310 }
311
David Srbeckybc90fd02015-04-22 19:40:27 +0100312 bool IsEmpty() const {
313 return symbols_.empty();
314 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100315
David Srbeckybc90fd02015-04-22 19:40:27 +0100316 Elf_Word GetSize() const OVERRIDE {
317 return (1 /* NULL */ + symbols_.size()) * sizeof(Elf_Sym);
318 }
319
320 bool Write(File* elf_file) OVERRIDE {
321 std::vector<Elf_Sym> buffer;
322 buffer.reserve(1u + symbols_.size());
323 buffer.push_back(Elf_Sym()); // NULL.
324 for (const ElfSymbolState& it : symbols_) {
325 Elf_Sym sym = Elf_Sym();
326 sym.st_name = it.name_idx_;
327 if (it.is_relative_) {
328 sym.st_value = it.addr_ + it.section_->GetHeader()->sh_addr;
329 } else {
330 sym.st_value = it.addr_;
331 }
332 sym.st_size = it.size_;
333 sym.st_other = it.other_;
334 sym.st_shndx = it.section_->GetSectionIndex();
335 sym.st_info = it.info_;
336 buffer.push_back(sym);
337 }
338 return WriteArray(elf_file, buffer.data(), buffer.size());
339 }
340
341 private:
342 struct ElfSymbolState {
343 const std::string name_;
344 const Section* section_;
345 Elf_Addr addr_;
346 Elf_Word size_;
347 bool is_relative_;
348 uint8_t info_;
349 uint8_t other_;
350 Elf_Word name_idx_; // index in the strtab.
351 };
352
353 static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
354 return ((binding) << 4) + ((type) & 0xf);
355 }
356
357 // The symbols in the same order they will be in the symbol table.
358 std::vector<ElfSymbolState> symbols_;
359 StrtabSection* strtab_;
360
361 friend class HashSection;
362 };
363
364 // TODO: Consider removing.
365 // We use it only for the dynsym section which has only 5 symbols.
366 // We do not use it for symtab, and we probably do not have to
367 // since we use those symbols only to print backtraces.
368 class HashSection FINAL : public Section {
369 public:
370 HashSection(const std::string& name, Elf_Word flags, SymtabSection* symtab)
371 : Section(name, SHT_HASH, flags, symtab,
372 0, sizeof(Elf_Word), sizeof(Elf_Word)),
373 symtab_(symtab) {
374 }
375
376 Elf_Word GetSize() const OVERRIDE {
377 Elf_Word nbuckets = GetNumBuckets();
378 Elf_Word chain_size = symtab_->symbols_.size() + 1 /* NULL */;
379 return (2 /* header */ + nbuckets + chain_size) * sizeof(Elf_Word);
380 }
381
382 bool Write(File* const elf_file) OVERRIDE {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100383 // Here is how The ELF hash table works.
384 // There are 3 arrays to worry about.
385 // * The symbol table where the symbol information is.
386 // * The bucket array which is an array of indexes into the symtab and chain.
387 // * The chain array which is also an array of indexes into the symtab and chain.
388 //
389 // Lets say the state is something like this.
390 // +--------+ +--------+ +-----------+
391 // | symtab | | bucket | | chain |
392 // | null | | 1 | | STN_UNDEF |
393 // | <sym1> | | 4 | | 2 |
394 // | <sym2> | | | | 5 |
395 // | <sym3> | | | | STN_UNDEF |
396 // | <sym4> | | | | 3 |
397 // | <sym5> | | | | STN_UNDEF |
398 // +--------+ +--------+ +-----------+
399 //
400 // The lookup process (in python psudocode) is
401 //
402 // def GetSym(name):
403 // # NB STN_UNDEF == 0
404 // indx = bucket[elfhash(name) % num_buckets]
405 // while indx != STN_UNDEF:
406 // if GetSymbolName(symtab[indx]) == name:
407 // return symtab[indx]
408 // indx = chain[indx]
409 // return SYMBOL_NOT_FOUND
410 //
411 // Between bucket and chain arrays every symtab index must be present exactly
412 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
David Srbeckybc90fd02015-04-22 19:40:27 +0100413 const auto& symbols = symtab_->symbols_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100414 // Select number of buckets.
415 // This is essentially arbitrary.
David Srbeckybc90fd02015-04-22 19:40:27 +0100416 Elf_Word nbuckets = GetNumBuckets();
417 // 1 is for the implicit NULL symbol.
418 Elf_Word chain_size = (symbols.size() + 1);
David Srbecky0c5bbc12015-04-28 17:54:52 +0100419 std::vector<Elf_Word> hash;
420 hash.push_back(nbuckets);
421 hash.push_back(chain_size);
422 uint32_t bucket_offset = hash.size();
423 uint32_t chain_offset = bucket_offset + nbuckets;
424 hash.resize(hash.size() + nbuckets + chain_size, 0);
425
426 Elf_Word* buckets = hash.data() + bucket_offset;
427 Elf_Word* chain = hash.data() + chain_offset;
428
429 // Set up the actual hash table.
David Srbeckybc90fd02015-04-22 19:40:27 +0100430 for (Elf_Word i = 0; i < symbols.size(); i++) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100431 // Add 1 since we need to have the null symbol that is not in the symbols
432 // list.
433 Elf_Word index = i + 1;
David Srbeckybc90fd02015-04-22 19:40:27 +0100434 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols[i].name_.c_str())) % nbuckets;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100435 if (buckets[hash_val] == 0) {
436 buckets[hash_val] = index;
437 } else {
438 hash_val = buckets[hash_val];
439 CHECK_LT(hash_val, chain_size);
440 while (chain[hash_val] != 0) {
441 hash_val = chain[hash_val];
442 CHECK_LT(hash_val, chain_size);
443 }
444 chain[hash_val] = index;
445 // Check for loops. Works because if this is non-empty then there must be
446 // another cell which already contains the same symbol index as this one,
447 // which means some symbol has more then one name, which isn't allowed.
448 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
449 }
450 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100451 return WriteArray(elf_file, hash.data(), hash.size());
David Srbecky0c5bbc12015-04-28 17:54:52 +0100452 }
453
454 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100455 Elf_Word GetNumBuckets() const {
456 const auto& symbols = symtab_->symbols_;
457 if (symbols.size() < 8) {
458 return 2;
459 } else if (symbols.size() < 32) {
460 return 4;
461 } else if (symbols.size() < 256) {
462 return 16;
463 } else {
464 // Have about 32 ids per bucket.
465 return RoundUp(symbols.size()/32, 2);
David Srbecky0c5bbc12015-04-28 17:54:52 +0100466 }
467 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100468
David Srbeckybc90fd02015-04-22 19:40:27 +0100469 // from bionic
470 static inline unsigned elfhash(const char *_name) {
471 const unsigned char *name = (const unsigned char *) _name;
472 unsigned h = 0, g;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100473
David Srbeckybc90fd02015-04-22 19:40:27 +0100474 while (*name) {
475 h = (h << 4) + *name++;
476 g = h & 0xf0000000;
477 h ^= g;
478 h ^= g >> 24;
479 }
480 return h;
481 }
482
483 SymtabSection* symtab_;
484
485 DISALLOW_COPY_AND_ASSIGN(HashSection);
486 };
487
488 ElfBuilder(InstructionSet isa,
489 Elf_Word rodata_size, CodeOutput* rodata_writer,
490 Elf_Word text_size, CodeOutput* text_writer,
491 Elf_Word bss_size)
492 : isa_(isa),
493 dynstr_(".dynstr", SHF_ALLOC),
494 dynsym_(".dynsym", SHT_DYNSYM, SHF_ALLOC, &dynstr_),
495 hash_(".hash", SHF_ALLOC, &dynsym_),
496 rodata_(".rodata", SHT_PROGBITS, SHF_ALLOC,
497 nullptr, 0, kPageSize, 0, rodata_size, rodata_writer),
498 text_(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR,
499 nullptr, 0, kPageSize, 0, text_size, text_writer),
500 bss_(".bss", bss_size),
501 dynamic_(".dynamic", &dynsym_),
502 strtab_(".strtab", 0),
503 symtab_(".symtab", SHT_SYMTAB, 0, &strtab_),
504 shstrtab_(".shstrtab", 0) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700505 }
506 ~ElfBuilder() {}
507
David Srbeckybc90fd02015-04-22 19:40:27 +0100508 OatSection* GetText() { return &text_; }
509 SymtabSection* GetSymtab() { return &symtab_; }
Ian Rogers0279ebb2014-10-08 17:27:48 -0700510
David Srbeckybc90fd02015-04-22 19:40:27 +0100511 bool Write(File* elf_file) {
Vladimir Marko5c42c292015-02-25 12:02:49 +0000512 // Since the .text section of an oat file contains relative references to .rodata
513 // and (optionally) .bss, we keep these 2 or 3 sections together. This creates
514 // a non-traditional layout where the .bss section is mapped independently of the
515 // .dynamic section and needs its own program header with LOAD RW.
516 //
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700517 // The basic layout of the elf file. Order may be different in final output.
518 // +-------------------------+
519 // | Elf_Ehdr |
520 // +-------------------------+
521 // | Elf_Phdr PHDR |
David Srbeckyb0a962c2015-04-28 19:43:56 +0100522 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700523 // | Elf_Phdr LOAD R X | .text
Vladimir Marko5c42c292015-02-25 12:02:49 +0000524 // | Elf_Phdr LOAD RW | .bss (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700525 // | Elf_Phdr LOAD RW | .dynamic
526 // | Elf_Phdr DYNAMIC | .dynamic
David Srbeckyb0a962c2015-04-28 19:43:56 +0100527 // | Elf_Phdr LOAD R | .eh_frame .eh_frame_hdr
David Srbecky527c9c72015-04-17 21:14:10 +0100528 // | Elf_Phdr EH_FRAME R | .eh_frame_hdr
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700529 // +-------------------------+
530 // | .dynsym |
531 // | Elf_Sym STN_UNDEF |
532 // | Elf_Sym oatdata |
533 // | Elf_Sym oatexec |
534 // | Elf_Sym oatlastword |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000535 // | Elf_Sym oatbss | (Optional)
536 // | Elf_Sym oatbsslastword | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700537 // +-------------------------+
538 // | .dynstr |
David Srbeckybc90fd02015-04-22 19:40:27 +0100539 // | names for .dynsym |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700540 // +-------------------------+
541 // | .hash |
David Srbeckybc90fd02015-04-22 19:40:27 +0100542 // | hashtable for dynsym |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700543 // +-------------------------+
544 // | .rodata |
545 // | oatdata..oatexec-4 |
546 // +-------------------------+
547 // | .text |
548 // | oatexec..oatlastword |
549 // +-------------------------+
550 // | .dynamic |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700551 // | Elf_Dyn DT_HASH |
David Srbeckybc90fd02015-04-22 19:40:27 +0100552 // | Elf_Dyn DT_STRTAB |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700553 // | Elf_Dyn DT_SYMTAB |
554 // | Elf_Dyn DT_SYMENT |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700555 // | Elf_Dyn DT_STRSZ |
David Srbeckybc90fd02015-04-22 19:40:27 +0100556 // | Elf_Dyn DT_SONAME |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700557 // | Elf_Dyn DT_NULL |
558 // +-------------------------+ (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700559 // | .symtab | (Optional)
560 // | program symbols | (Optional)
David Srbeckybc90fd02015-04-22 19:40:27 +0100561 // +-------------------------+ (Optional)
562 // | .strtab | (Optional)
563 // | names for .symtab | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700564 // +-------------------------+ (Optional)
David Srbeckyb0a962c2015-04-28 19:43:56 +0100565 // | .eh_frame | (Optional)
566 // +-------------------------+ (Optional)
567 // | .eh_frame_hdr | (Optional)
568 // +-------------------------+ (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700569 // | .debug_info | (Optional)
570 // +-------------------------+ (Optional)
571 // | .debug_abbrev | (Optional)
572 // +-------------------------+ (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100573 // | .debug_str | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700574 // +-------------------------+ (Optional)
575 // | .debug_line | (Optional)
David Srbeckybc90fd02015-04-22 19:40:27 +0100576 // +-------------------------+
577 // | .shstrtab |
578 // | names of sections |
579 // +-------------------------+
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700580 // | Elf_Shdr null |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700581 // | Elf_Shdr .dynsym |
582 // | Elf_Shdr .dynstr |
583 // | Elf_Shdr .hash |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700584 // | Elf_Shdr .rodata |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000585 // | Elf_Shdr .text |
586 // | Elf_Shdr .bss | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700587 // | Elf_Shdr .dynamic |
David Srbeckybc90fd02015-04-22 19:40:27 +0100588 // | Elf_Shdr .symtab | (Optional)
589 // | Elf_Shdr .strtab | (Optional)
David Srbeckyb0a962c2015-04-28 19:43:56 +0100590 // | Elf_Shdr .eh_frame | (Optional)
591 // | Elf_Shdr .eh_frame_hdr | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700592 // | Elf_Shdr .debug_info | (Optional)
593 // | Elf_Shdr .debug_abbrev | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700594 // | Elf_Shdr .debug_str | (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100595 // | Elf_Shdr .debug_line | (Optional)
David Srbeckybc90fd02015-04-22 19:40:27 +0100596 // | Elf_Shdr .oat_patches | (Optional)
597 // | Elf_Shdr .shstrtab |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700598 // +-------------------------+
David Srbeckybc90fd02015-04-22 19:40:27 +0100599 constexpr bool debug_logging_ = false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700600
David Srbeckybc90fd02015-04-22 19:40:27 +0100601 // Create a list of all section which we want to write.
602 // This is the order in which they will be written.
603 std::vector<Section*> sections;
604 sections.push_back(&dynsym_);
605 sections.push_back(&dynstr_);
606 sections.push_back(&hash_);
David Srbeckybc90fd02015-04-22 19:40:27 +0100607 sections.push_back(&rodata_);
608 sections.push_back(&text_);
609 if (bss_.GetSize() != 0u) {
610 sections.push_back(&bss_);
Vladimir Marko5c42c292015-02-25 12:02:49 +0000611 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100612 sections.push_back(&dynamic_);
613 if (!symtab_.IsEmpty()) {
614 sections.push_back(&symtab_);
615 sections.push_back(&strtab_);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700616 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100617 for (Section* section : other_sections_) {
David Srbeckyb0a962c2015-04-28 19:43:56 +0100618 sections.push_back(section);
David Srbecky527c9c72015-04-17 21:14:10 +0100619 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100620 sections.push_back(&shstrtab_);
621 for (size_t i = 0; i < sections.size(); i++) {
622 // The first section index is 1. Index 0 is reserved for NULL.
623 // Section index is used for relative symbols and for section links.
624 sections[i]->SetSectionIndex(i + 1);
625 // Add section name to .shstrtab.
626 Elf_Word name_offset = shstrtab_.AddName(sections[i]->GetName());
627 sections[i]->GetHeader()->sh_name = name_offset;
David Srbecky527c9c72015-04-17 21:14:10 +0100628 }
629
David Srbeckybc90fd02015-04-22 19:40:27 +0100630 // The running program does not have access to section headers
631 // and the loader is not supposed to use them either.
632 // The dynamic sections therefore replicates some of the layout
633 // information like the address and size of .rodata and .text.
634 // It also contains other metadata like the SONAME.
635 // The .dynamic section is found using the PT_DYNAMIC program header.
636 BuildDynsymSection();
637 BuildDynamicSection(elf_file->GetPath());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700638
David Srbeckybc90fd02015-04-22 19:40:27 +0100639 // We do not know the number of headers until the final stages of write.
640 // It is easiest to just reserve a fixed amount of space for them.
David Srbeckyb0a962c2015-04-28 19:43:56 +0100641 constexpr size_t kMaxProgramHeaders = 8;
David Srbeckybc90fd02015-04-22 19:40:27 +0100642 constexpr size_t kProgramHeadersOffset = sizeof(Elf_Ehdr);
643 constexpr size_t kProgramHeadersSize = sizeof(Elf_Phdr) * kMaxProgramHeaders;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700644
David Srbeckybc90fd02015-04-22 19:40:27 +0100645 // Layout of all sections - determine the final file offsets and addresses.
646 // This must be done after we have built all sections and know their size.
647 Elf_Off file_offset = kProgramHeadersOffset + kProgramHeadersSize;
648 Elf_Addr load_address = file_offset;
649 std::vector<Elf_Shdr> section_headers;
650 section_headers.reserve(1u + sections.size());
651 section_headers.push_back(Elf_Shdr()); // NULL at index 0.
652 for (auto* section : sections) {
653 Elf_Shdr* header = section->GetHeader();
654 Elf_Off alignment = header->sh_addralign > 0 ? header->sh_addralign : 1;
655 header->sh_size = section->GetSize();
656 header->sh_link = section->GetLink();
657 // Allocate memory for the section in the file.
658 if (header->sh_type != SHT_NOBITS) {
659 header->sh_offset = RoundUp(file_offset, alignment);
660 file_offset = header->sh_offset + header->sh_size;
661 }
662 // Allocate memory for the section during program execution.
663 if ((header->sh_flags & SHF_ALLOC) != 0) {
664 header->sh_addr = RoundUp(load_address, alignment);
665 load_address = header->sh_addr + header->sh_size;
666 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700667 if (debug_logging_) {
David Srbeckybc90fd02015-04-22 19:40:27 +0100668 LOG(INFO) << "Section " << section->GetName() << ":" << std::hex
669 << " offset=0x" << header->sh_offset
670 << " addr=0x" << header->sh_addr
671 << " size=0x" << header->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700672 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100673 // Collect section headers into continuous array for convenience.
674 section_headers.push_back(*header);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700675 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100676 Elf_Off section_headers_offset = RoundUp(file_offset, sizeof(Elf_Word));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700677
David Srbeckybc90fd02015-04-22 19:40:27 +0100678 // Create program headers now that we know the layout of the whole file.
679 // Each segment contains one or more sections which are mapped together.
680 // Not all sections are mapped during the execution of the program.
681 // PT_LOAD does the mapping. Other PT_* types allow the program to locate
682 // interesting parts of memory and their addresses overlap with PT_LOAD.
683 std::vector<Elf_Phdr> program_headers;
684 program_headers.push_back(MakeProgramHeader(PT_PHDR, PF_R,
685 kProgramHeadersOffset, kProgramHeadersSize, sizeof(Elf_Word)));
686 // Create the main LOAD R segment which spans all sections up to .rodata.
687 const Elf_Shdr* rodata = rodata_.GetHeader();
688 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R,
689 0, rodata->sh_offset + rodata->sh_size, rodata->sh_addralign));
690 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_X, text_));
691 if (bss_.GetHeader()->sh_size != 0u) {
692 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_W, bss_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700693 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100694 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_W, dynamic_));
695 program_headers.push_back(MakeProgramHeader(PT_DYNAMIC, PF_R | PF_W, dynamic_));
David Srbeckyb0a962c2015-04-28 19:43:56 +0100696 const Section* eh_frame = FindSection(".eh_frame");
697 if (eh_frame != nullptr) {
698 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R, *eh_frame));
699 const Section* eh_frame_hdr = FindSection(".eh_frame_hdr");
700 if (eh_frame_hdr != nullptr) {
701 // Check layout: eh_frame is before eh_frame_hdr and there is no gap.
702 CHECK_LE(eh_frame->GetHeader()->sh_offset, eh_frame_hdr->GetHeader()->sh_offset);
703 CHECK_EQ(eh_frame->GetHeader()->sh_offset + eh_frame->GetHeader()->sh_size,
704 eh_frame_hdr->GetHeader()->sh_offset);
705 // Extend the PT_LOAD of .eh_frame to include the .eh_frame_hdr as well.
706 program_headers.back().p_filesz += eh_frame_hdr->GetHeader()->sh_size;
707 program_headers.back().p_memsz += eh_frame_hdr->GetHeader()->sh_size;
708 program_headers.push_back(MakeProgramHeader(PT_GNU_EH_FRAME, PF_R, *eh_frame_hdr));
709 }
David Srbecky527c9c72015-04-17 21:14:10 +0100710 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100711 CHECK_LE(program_headers.size(), kMaxProgramHeaders);
David Srbecky527c9c72015-04-17 21:14:10 +0100712
David Srbeckybc90fd02015-04-22 19:40:27 +0100713 // Create the main ELF header.
714 Elf_Ehdr elf_header = MakeElfHeader(isa_);
715 elf_header.e_phoff = kProgramHeadersOffset;
716 elf_header.e_shoff = section_headers_offset;
717 elf_header.e_phnum = program_headers.size();
718 elf_header.e_shnum = section_headers.size();
719 elf_header.e_shstrndx = shstrtab_.GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700720
David Srbeckybc90fd02015-04-22 19:40:27 +0100721 // Write all headers and section content to the file.
722 // Depending on the implementations of Section::Write, this
723 // might be just memory copies or some more elaborate operations.
724 if (!WriteArray(elf_file, &elf_header, 1)) {
725 LOG(INFO) << "Failed to write the ELF header";
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700726 return false;
727 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100728 if (!WriteArray(elf_file, program_headers.data(), program_headers.size())) {
729 LOG(INFO) << "Failed to write the program headers";
730 return false;
731 }
732 for (Section* section : sections) {
733 const Elf_Shdr* header = section->GetHeader();
734 if (header->sh_type != SHT_NOBITS) {
735 if (!SeekTo(elf_file, header->sh_offset) || !section->Write(elf_file)) {
736 LOG(INFO) << "Failed to write section " << section->GetName();
737 return false;
738 }
739 Elf_Word current_offset = lseek(elf_file->Fd(), 0, SEEK_CUR);
740 CHECK_EQ(current_offset, header->sh_offset + header->sh_size)
741 << "The number of bytes written does not match GetSize()";
742 }
743 }
744 if (!SeekTo(elf_file, section_headers_offset) ||
745 !WriteArray(elf_file, section_headers.data(), section_headers.size())) {
746 LOG(INFO) << "Failed to write the section headers";
747 return false;
748 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700749 return true;
750 }
751
David Srbeckybc90fd02015-04-22 19:40:27 +0100752 // Adds the given section to the builder. It does not take ownership.
753 void RegisterSection(Section* section) {
754 other_sections_.push_back(section);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700755 }
756
David Srbeckybc90fd02015-04-22 19:40:27 +0100757 const Section* FindSection(const char* name) {
758 for (const auto* section : other_sections_) {
759 if (section->GetName() == name) {
760 return section;
David Srbecky527c9c72015-04-17 21:14:10 +0100761 }
762 }
763 return nullptr;
764 }
765
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700766 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100767 static bool SeekTo(File* elf_file, Elf_Word offset) {
768 DCHECK_LE(lseek(elf_file->Fd(), 0, SEEK_CUR), static_cast<off_t>(offset))
769 << "Seeking backwards";
770 if (static_cast<off_t>(offset) != lseek(elf_file->Fd(), offset, SEEK_SET)) {
771 PLOG(ERROR) << "Failed to seek in file " << elf_file->GetPath();
772 return false;
773 }
774 return true;
775 }
776
777 template<typename T>
778 static bool WriteArray(File* elf_file, const T* data, size_t count) {
779 DCHECK(data != nullptr);
780 if (!elf_file->WriteFully(data, count * sizeof(T))) {
781 PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
782 return false;
783 }
784 return true;
785 }
786
787 // Helper - create segment header based on memory range.
788 static Elf_Phdr MakeProgramHeader(Elf_Word type, Elf_Word flags,
789 Elf_Off offset, Elf_Word size, Elf_Word align) {
790 Elf_Phdr phdr = Elf_Phdr();
791 phdr.p_type = type;
792 phdr.p_flags = flags;
793 phdr.p_offset = offset;
794 phdr.p_vaddr = offset;
795 phdr.p_paddr = offset;
796 phdr.p_filesz = size;
797 phdr.p_memsz = size;
798 phdr.p_align = align;
799 return phdr;
800 }
801
802 // Helper - create segment header based on section header.
803 static Elf_Phdr MakeProgramHeader(Elf_Word type, Elf_Word flags,
804 const Section& section) {
805 const Elf_Shdr* shdr = section.GetHeader();
806 // Only run-time allocated sections should be in segment headers.
807 CHECK_NE(shdr->sh_flags & SHF_ALLOC, 0u);
808 Elf_Phdr phdr = Elf_Phdr();
809 phdr.p_type = type;
810 phdr.p_flags = flags;
811 phdr.p_offset = shdr->sh_offset;
812 phdr.p_vaddr = shdr->sh_addr;
813 phdr.p_paddr = shdr->sh_addr;
814 phdr.p_filesz = shdr->sh_type != SHT_NOBITS ? shdr->sh_size : 0u;
815 phdr.p_memsz = shdr->sh_size;
816 phdr.p_align = shdr->sh_addralign;
817 return phdr;
818 }
819
820 static Elf_Ehdr MakeElfHeader(InstructionSet isa) {
821 Elf_Ehdr elf_header = Elf_Ehdr();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700822 switch (isa) {
823 case kArm:
824 // Fall through.
825 case kThumb2: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100826 elf_header.e_machine = EM_ARM;
827 elf_header.e_flags = EF_ARM_EABI_VER5;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700828 break;
829 }
830 case kArm64: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100831 elf_header.e_machine = EM_AARCH64;
832 elf_header.e_flags = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700833 break;
834 }
835 case kX86: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100836 elf_header.e_machine = EM_386;
837 elf_header.e_flags = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700838 break;
839 }
840 case kX86_64: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100841 elf_header.e_machine = EM_X86_64;
842 elf_header.e_flags = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700843 break;
844 }
845 case kMips: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100846 elf_header.e_machine = EM_MIPS;
847 elf_header.e_flags = (EF_MIPS_NOREORDER |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700848 EF_MIPS_PIC |
849 EF_MIPS_CPIC |
850 EF_MIPS_ABI_O32 |
851 EF_MIPS_ARCH_32R2);
852 break;
853 }
Andreas Gampe57b34292015-01-14 15:45:59 -0800854 case kMips64: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100855 elf_header.e_machine = EM_MIPS;
856 elf_header.e_flags = (EF_MIPS_NOREORDER |
Andreas Gampe57b34292015-01-14 15:45:59 -0800857 EF_MIPS_PIC |
858 EF_MIPS_CPIC |
859 EF_MIPS_ARCH_64R6);
860 break;
861 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100862 case kNone: {
863 LOG(FATAL) << "No instruction set";
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700864 }
865 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700866
David Srbeckybc90fd02015-04-22 19:40:27 +0100867 elf_header.e_ident[EI_MAG0] = ELFMAG0;
868 elf_header.e_ident[EI_MAG1] = ELFMAG1;
869 elf_header.e_ident[EI_MAG2] = ELFMAG2;
870 elf_header.e_ident[EI_MAG3] = ELFMAG3;
871 elf_header.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
Tong Shen62d1ca32014-09-03 17:24:56 -0700872 ? ELFCLASS32 : ELFCLASS64;;
David Srbeckybc90fd02015-04-22 19:40:27 +0100873 elf_header.e_ident[EI_DATA] = ELFDATA2LSB;
874 elf_header.e_ident[EI_VERSION] = EV_CURRENT;
875 elf_header.e_ident[EI_OSABI] = ELFOSABI_LINUX;
876 elf_header.e_ident[EI_ABIVERSION] = 0;
877 elf_header.e_type = ET_DYN;
878 elf_header.e_version = 1;
879 elf_header.e_entry = 0;
880 elf_header.e_ehsize = sizeof(Elf_Ehdr);
881 elf_header.e_phentsize = sizeof(Elf_Phdr);
882 elf_header.e_shentsize = sizeof(Elf_Shdr);
883 elf_header.e_phoff = sizeof(Elf_Ehdr);
884 return elf_header;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700885 }
886
David Srbeckybc90fd02015-04-22 19:40:27 +0100887 void BuildDynamicSection(const std::string& elf_file_path) {
888 std::string soname(elf_file_path);
889 size_t directory_separator_pos = soname.rfind('/');
890 if (directory_separator_pos != std::string::npos) {
891 soname = soname.substr(directory_separator_pos + 1);
892 }
893 // NB: We must add the name before adding DT_STRSZ.
894 Elf_Word soname_offset = dynstr_.AddName(soname);
895
896 dynamic_.AddDynamicTag(DT_HASH, 0, &hash_);
897 dynamic_.AddDynamicTag(DT_STRTAB, 0, &dynstr_);
898 dynamic_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_);
899 dynamic_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym), nullptr);
900 dynamic_.AddDynamicTag(DT_STRSZ, dynstr_.GetSize(), nullptr);
901 dynamic_.AddDynamicTag(DT_SONAME, soname_offset, nullptr);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700902 }
903
David Srbeckybc90fd02015-04-22 19:40:27 +0100904 void BuildDynsymSection() {
905 dynsym_.AddSymbol("oatdata", &rodata_, 0, true,
906 rodata_.GetSize(), STB_GLOBAL, STT_OBJECT);
907 dynsym_.AddSymbol("oatexec", &text_, 0, true,
908 text_.GetSize(), STB_GLOBAL, STT_OBJECT);
909 dynsym_.AddSymbol("oatlastword", &text_, text_.GetSize() - 4,
910 true, 4, STB_GLOBAL, STT_OBJECT);
911 if (bss_.GetSize() != 0u) {
912 dynsym_.AddSymbol("oatbss", &bss_, 0, true,
913 bss_.GetSize(), STB_GLOBAL, STT_OBJECT);
914 dynsym_.AddSymbol("oatbsslastword", &bss_, bss_.GetSize() - 4,
915 true, 4, STB_GLOBAL, STT_OBJECT);
Vladimir Marko5c42c292015-02-25 12:02:49 +0000916 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700917 }
918
David Srbeckybc90fd02015-04-22 19:40:27 +0100919 InstructionSet isa_;
920 StrtabSection dynstr_;
921 SymtabSection dynsym_;
922 HashSection hash_;
923 OatSection rodata_;
924 OatSection text_;
925 NoBitsSection bss_;
926 DynamicSection dynamic_;
927 StrtabSection strtab_;
928 SymtabSection symtab_;
929 std::vector<Section*> other_sections_;
930 StrtabSection shstrtab_;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700931
932 DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700933};
934
935} // namespace art
936
937#endif // ART_COMPILER_ELF_BUILDER_H_