blob: bbd962fae2b1039e21c041dddfa7a5e539aa6279 [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"
Vladimir Marko80afd022015-05-19 18:08:00 +010023#include "base/bit_utils.h"
David Srbeckybc90fd02015-04-22 19:40:27 +010024#include "base/unix_file/fd_file.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070025#include "buffered_output_stream.h"
26#include "elf_utils.h"
27#include "file_output_stream.h"
Andreas Gampe54fc26c2014-09-04 21:47:42 -070028
29namespace art {
30
Andreas Gampe54fc26c2014-09-04 21:47:42 -070031class CodeOutput {
32 public:
33 virtual bool Write(OutputStream* out) = 0;
34 virtual ~CodeOutput() {}
35};
36
David Srbeckybc90fd02015-04-22 19:40:27 +010037// Writes ELF file.
38// The main complication is that the sections often want to reference
39// each other. We solve this by writing the ELF file in two stages:
40// * Sections are asked about their size, and overall layout is calculated.
41// * Sections do the actual writes which may use offsets of other sections.
David Srbecky533c2072015-04-22 12:20:22 +010042template <typename ElfTypes>
Andreas Gampe54fc26c2014-09-04 21:47:42 -070043class ElfBuilder FINAL {
44 public:
David Srbecky533c2072015-04-22 12:20:22 +010045 using Elf_Addr = typename ElfTypes::Addr;
David Srbeckybc90fd02015-04-22 19:40:27 +010046 using Elf_Off = typename ElfTypes::Off;
David Srbecky533c2072015-04-22 12:20:22 +010047 using Elf_Word = typename ElfTypes::Word;
48 using Elf_Sword = typename ElfTypes::Sword;
49 using Elf_Ehdr = typename ElfTypes::Ehdr;
50 using Elf_Shdr = typename ElfTypes::Shdr;
51 using Elf_Sym = typename ElfTypes::Sym;
52 using Elf_Phdr = typename ElfTypes::Phdr;
53 using Elf_Dyn = typename ElfTypes::Dyn;
54
David Srbeckybc90fd02015-04-22 19:40:27 +010055 // Base class of all sections.
56 class Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +010057 public:
David Srbeckybc90fd02015-04-22 19:40:27 +010058 Section(const std::string& name, Elf_Word type, Elf_Word flags,
59 const Section* link, Elf_Word info, Elf_Word align, Elf_Word entsize)
David Srbecky491a7fe2015-05-28 00:59:08 +010060 : header_(), section_index_(0), name_(name), link_(link) {
61 header_.sh_type = type;
62 header_.sh_flags = flags;
63 header_.sh_info = info;
64 header_.sh_addralign = align;
65 header_.sh_entsize = entsize;
David Srbecky0c5bbc12015-04-28 17:54:52 +010066 }
David Srbeckybc90fd02015-04-22 19:40:27 +010067 virtual ~Section() {}
David Srbecky0c5bbc12015-04-28 17:54:52 +010068
David Srbeckybc90fd02015-04-22 19:40:27 +010069 // Returns the size of the content of this section. It is used to
70 // calculate file offsets of all sections before doing any writes.
71 virtual Elf_Word GetSize() const = 0;
72
73 // Write the content of this section to the given file.
74 // This must write exactly the number of bytes returned by GetSize().
75 // Offsets of all sections are known when this method is called.
76 virtual bool Write(File* elf_file) = 0;
David Srbecky0c5bbc12015-04-28 17:54:52 +010077
78 Elf_Word GetLink() const {
David Srbeckybc90fd02015-04-22 19:40:27 +010079 return (link_ != nullptr) ? link_->GetSectionIndex() : 0;
David Srbecky0c5bbc12015-04-28 17:54:52 +010080 }
81
David Srbeckybc90fd02015-04-22 19:40:27 +010082 const Elf_Shdr* GetHeader() const {
David Srbecky491a7fe2015-05-28 00:59:08 +010083 return &header_;
David Srbecky0c5bbc12015-04-28 17:54:52 +010084 }
85
David Srbeckybc90fd02015-04-22 19:40:27 +010086 Elf_Shdr* GetHeader() {
David Srbecky491a7fe2015-05-28 00:59:08 +010087 return &header_;
David Srbecky0c5bbc12015-04-28 17:54:52 +010088 }
89
90 Elf_Word GetSectionIndex() const {
David Srbeckybc90fd02015-04-22 19:40:27 +010091 DCHECK_NE(section_index_, 0u);
David Srbecky0c5bbc12015-04-28 17:54:52 +010092 return section_index_;
93 }
94
95 void SetSectionIndex(Elf_Word section_index) {
96 section_index_ = section_index;
97 }
98
99 const std::string& GetName() const {
100 return name_;
101 }
102
103 private:
David Srbecky491a7fe2015-05-28 00:59:08 +0100104 Elf_Shdr header_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100105 Elf_Word section_index_;
106 const std::string name_;
David Srbeckybc90fd02015-04-22 19:40:27 +0100107 const Section* const link_;
108
109 DISALLOW_COPY_AND_ASSIGN(Section);
David Srbecky0c5bbc12015-04-28 17:54:52 +0100110 };
111
David Srbeckybc90fd02015-04-22 19:40:27 +0100112 // Writer of .dynamic section.
113 class DynamicSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100114 public:
David Srbeckybc90fd02015-04-22 19:40:27 +0100115 void AddDynamicTag(Elf_Sword tag, Elf_Word value, const Section* section) {
116 DCHECK_NE(tag, static_cast<Elf_Sword>(DT_NULL));
117 dynamics_.push_back({tag, value, section});
David Srbecky0c5bbc12015-04-28 17:54:52 +0100118 }
119
David Srbeckybc90fd02015-04-22 19:40:27 +0100120 DynamicSection(const std::string& name, Section* link)
121 : Section(name, SHT_DYNAMIC, SHF_ALLOC,
122 link, 0, kPageSize, sizeof(Elf_Dyn)) {}
123
124 Elf_Word GetSize() const OVERRIDE {
125 return (dynamics_.size() + 1 /* DT_NULL */) * sizeof(Elf_Dyn);
David Srbecky0c5bbc12015-04-28 17:54:52 +0100126 }
127
David Srbeckybc90fd02015-04-22 19:40:27 +0100128 bool Write(File* elf_file) OVERRIDE {
129 std::vector<Elf_Dyn> buffer;
130 buffer.reserve(dynamics_.size() + 1u);
131 for (const ElfDynamicState& it : dynamics_) {
132 if (it.section_ != nullptr) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100133 // We are adding an address relative to a section.
David Srbeckybc90fd02015-04-22 19:40:27 +0100134 buffer.push_back(
135 {it.tag_, {it.value_ + it.section_->GetHeader()->sh_addr}});
David Srbecky0c5bbc12015-04-28 17:54:52 +0100136 } else {
David Srbeckybc90fd02015-04-22 19:40:27 +0100137 buffer.push_back({it.tag_, {it.value_}});
David Srbecky0c5bbc12015-04-28 17:54:52 +0100138 }
139 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100140 buffer.push_back({DT_NULL, {0}});
141 return WriteArray(elf_file, buffer.data(), buffer.size());
David Srbecky0c5bbc12015-04-28 17:54:52 +0100142 }
143
144 private:
145 struct ElfDynamicState {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100146 Elf_Sword tag_;
David Srbeckybc90fd02015-04-22 19:40:27 +0100147 Elf_Word value_;
148 const Section* section_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100149 };
150 std::vector<ElfDynamicState> dynamics_;
151 };
152
David Srbecky033d7452015-04-30 19:57:35 +0100153 using PatchFn = void (*)(const std::vector<uintptr_t>& patch_locations,
154 Elf_Addr buffer_address,
155 Elf_Addr base_address,
156 std::vector<uint8_t>* buffer);
157
David Srbeckybc90fd02015-04-22 19:40:27 +0100158 // Section with content based on simple memory buffer.
159 // The buffer can be optionally patched before writing.
David Srbeckybc90fd02015-04-22 19:40:27 +0100160 class RawSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100161 public:
David Srbeckybc90fd02015-04-22 19:40:27 +0100162 RawSection(const std::string& name, Elf_Word type, Elf_Word flags,
163 const Section* link, Elf_Word info, Elf_Word align, Elf_Word entsize,
David Srbecky033d7452015-04-30 19:57:35 +0100164 PatchFn patch = nullptr, const Section* patch_base_section = nullptr)
David Srbeckybc90fd02015-04-22 19:40:27 +0100165 : Section(name, type, flags, link, info, align, entsize),
David Srbecky033d7452015-04-30 19:57:35 +0100166 patched_(false), patch_(patch), patch_base_section_(patch_base_section) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100167 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100168
David Srbeckyf8980872015-05-22 17:04:47 +0100169 RawSection(const std::string& name, Elf_Word type)
170 : RawSection(name, type, 0, nullptr, 0, 1, 0, nullptr, nullptr) {
171 }
172
David Srbeckybc90fd02015-04-22 19:40:27 +0100173 Elf_Word GetSize() const OVERRIDE {
174 return buffer_.size();
175 }
176
177 bool Write(File* elf_file) OVERRIDE {
178 if (!patch_locations_.empty()) {
David Srbecky033d7452015-04-30 19:57:35 +0100179 DCHECK(!patched_); // Do not patch twice.
180 DCHECK(patch_ != nullptr);
181 DCHECK(patch_base_section_ != nullptr);
182 patch_(patch_locations_,
183 this->GetHeader()->sh_addr,
184 patch_base_section_->GetHeader()->sh_addr,
185 &buffer_);
186 patched_ = true;
David Srbeckybc90fd02015-04-22 19:40:27 +0100187 }
188 return WriteArray(elf_file, buffer_.data(), buffer_.size());
189 }
190
191 bool IsEmpty() const {
192 return buffer_.size() == 0;
193 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100194
195 std::vector<uint8_t>* GetBuffer() {
David Srbeckybc90fd02015-04-22 19:40:27 +0100196 return &buffer_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100197 }
198
David Srbeckybc90fd02015-04-22 19:40:27 +0100199 void SetBuffer(const std::vector<uint8_t>& buffer) {
200 buffer_ = buffer;
201 }
202
203 std::vector<uintptr_t>* GetPatchLocations() {
204 return &patch_locations_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100205 }
206
207 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100208 std::vector<uint8_t> buffer_;
209 std::vector<uintptr_t> patch_locations_;
David Srbecky033d7452015-04-30 19:57:35 +0100210 bool patched_;
211 // User-provided function to do the actual patching.
212 PatchFn patch_;
213 // The section that we patch against (usually .text).
214 const Section* patch_base_section_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100215 };
216
David Srbeckybc90fd02015-04-22 19:40:27 +0100217 // Writer of .rodata section or .text section.
218 // The write is done lazily using the provided CodeOutput.
219 class OatSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100220 public:
David Srbeckybc90fd02015-04-22 19:40:27 +0100221 OatSection(const std::string& name, Elf_Word type, Elf_Word flags,
222 const Section* link, Elf_Word info, Elf_Word align,
223 Elf_Word entsize, Elf_Word size, CodeOutput* code_output)
224 : Section(name, type, flags, link, info, align, entsize),
225 size_(size), code_output_(code_output) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100226 }
227
David Srbeckybc90fd02015-04-22 19:40:27 +0100228 Elf_Word GetSize() const OVERRIDE {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100229 return size_;
230 }
231
David Srbeckybc90fd02015-04-22 19:40:27 +0100232 bool Write(File* elf_file) OVERRIDE {
233 // The BufferedOutputStream class contains the buffer as field,
234 // therefore it is too big to allocate on the stack.
235 std::unique_ptr<BufferedOutputStream> output_stream(
236 new BufferedOutputStream(new FileOutputStream(elf_file)));
237 return code_output_->Write(output_stream.get());
238 }
239
David Srbecky0c5bbc12015-04-28 17:54:52 +0100240 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100241 Elf_Word size_;
242 CodeOutput* code_output_;
243 };
244
245 // Writer of .bss section.
246 class NoBitsSection FINAL : public Section {
247 public:
248 NoBitsSection(const std::string& name, Elf_Word size)
249 : Section(name, SHT_NOBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
250 size_(size) {
251 }
252
253 Elf_Word GetSize() const OVERRIDE {
254 return size_;
255 }
256
257 bool Write(File* elf_file ATTRIBUTE_UNUSED) OVERRIDE {
258 LOG(ERROR) << "This section should not be written to the ELF file";
259 return false;
260 }
261
262 private:
David Srbecky0c5bbc12015-04-28 17:54:52 +0100263 Elf_Word size_;
264 };
265
David Srbeckybc90fd02015-04-22 19:40:27 +0100266 // Writer of .dynstr .strtab and .shstrtab sections.
267 class StrtabSection FINAL : public Section {
268 public:
269 StrtabSection(const std::string& name, Elf_Word flags)
David Srbecky1a146bf2015-05-29 16:33:11 +0100270 : Section(name, SHT_STRTAB, flags, nullptr, 0, 1, 0) {
David Srbeckybc90fd02015-04-22 19:40:27 +0100271 buffer_.reserve(4 * KB);
272 // The first entry of strtab must be empty string.
273 buffer_ += '\0';
David Srbecky0c5bbc12015-04-28 17:54:52 +0100274 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100275
David Srbeckybc90fd02015-04-22 19:40:27 +0100276 Elf_Word AddName(const std::string& name) {
277 Elf_Word offset = buffer_.size();
278 buffer_ += name;
279 buffer_ += '\0';
280 return offset;
281 }
282
283 Elf_Word GetSize() const OVERRIDE {
284 return buffer_.size();
285 }
286
287 bool Write(File* elf_file) OVERRIDE {
288 return WriteArray(elf_file, buffer_.data(), buffer_.size());
289 }
290
291 private:
292 std::string buffer_;
293 };
294
295 class HashSection;
296
297 // Writer of .dynsym and .symtab sections.
298 class SymtabSection FINAL : public Section {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100299 public:
300 // Add a symbol with given name to this symtab. The symbol refers to
301 // 'relative_addr' within the given section and has the given attributes.
David Srbeckybc90fd02015-04-22 19:40:27 +0100302 void AddSymbol(const std::string& name, const Section* section,
303 Elf_Addr addr, bool is_relative, Elf_Word size,
304 uint8_t binding, uint8_t type, uint8_t other = 0) {
305 CHECK(section != nullptr);
306 Elf_Word name_idx = strtab_->AddName(name);
307 symbols_.push_back({ name, section, addr, size, is_relative,
308 MakeStInfo(binding, type), other, name_idx });
David Srbecky0c5bbc12015-04-28 17:54:52 +0100309 }
310
David Srbeckybc90fd02015-04-22 19:40:27 +0100311 SymtabSection(const std::string& name, Elf_Word type, Elf_Word flags,
312 StrtabSection* strtab)
David Srbecky67a06532015-05-29 18:09:05 +0100313 : Section(name, type, flags, strtab, 0, sizeof(Elf_Off), sizeof(Elf_Sym)),
David Srbeckybc90fd02015-04-22 19:40:27 +0100314 strtab_(strtab) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100315 }
316
David Srbeckybc90fd02015-04-22 19:40:27 +0100317 bool IsEmpty() const {
318 return symbols_.empty();
319 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100320
David Srbeckybc90fd02015-04-22 19:40:27 +0100321 Elf_Word GetSize() const OVERRIDE {
322 return (1 /* NULL */ + symbols_.size()) * sizeof(Elf_Sym);
323 }
324
325 bool Write(File* elf_file) OVERRIDE {
326 std::vector<Elf_Sym> buffer;
327 buffer.reserve(1u + symbols_.size());
328 buffer.push_back(Elf_Sym()); // NULL.
329 for (const ElfSymbolState& it : symbols_) {
330 Elf_Sym sym = Elf_Sym();
331 sym.st_name = it.name_idx_;
332 if (it.is_relative_) {
333 sym.st_value = it.addr_ + it.section_->GetHeader()->sh_addr;
334 } else {
335 sym.st_value = it.addr_;
336 }
337 sym.st_size = it.size_;
338 sym.st_other = it.other_;
339 sym.st_shndx = it.section_->GetSectionIndex();
340 sym.st_info = it.info_;
341 buffer.push_back(sym);
342 }
343 return WriteArray(elf_file, buffer.data(), buffer.size());
344 }
345
346 private:
347 struct ElfSymbolState {
348 const std::string name_;
349 const Section* section_;
350 Elf_Addr addr_;
351 Elf_Word size_;
352 bool is_relative_;
353 uint8_t info_;
354 uint8_t other_;
355 Elf_Word name_idx_; // index in the strtab.
356 };
357
358 static inline constexpr uint8_t MakeStInfo(uint8_t binding, uint8_t type) {
359 return ((binding) << 4) + ((type) & 0xf);
360 }
361
362 // The symbols in the same order they will be in the symbol table.
363 std::vector<ElfSymbolState> symbols_;
364 StrtabSection* strtab_;
365
366 friend class HashSection;
367 };
368
369 // TODO: Consider removing.
370 // We use it only for the dynsym section which has only 5 symbols.
371 // We do not use it for symtab, and we probably do not have to
372 // since we use those symbols only to print backtraces.
373 class HashSection FINAL : public Section {
374 public:
375 HashSection(const std::string& name, Elf_Word flags, SymtabSection* symtab)
376 : Section(name, SHT_HASH, flags, symtab,
377 0, sizeof(Elf_Word), sizeof(Elf_Word)),
378 symtab_(symtab) {
379 }
380
381 Elf_Word GetSize() const OVERRIDE {
382 Elf_Word nbuckets = GetNumBuckets();
383 Elf_Word chain_size = symtab_->symbols_.size() + 1 /* NULL */;
384 return (2 /* header */ + nbuckets + chain_size) * sizeof(Elf_Word);
385 }
386
387 bool Write(File* const elf_file) OVERRIDE {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100388 // Here is how The ELF hash table works.
389 // There are 3 arrays to worry about.
390 // * The symbol table where the symbol information is.
391 // * The bucket array which is an array of indexes into the symtab and chain.
392 // * The chain array which is also an array of indexes into the symtab and chain.
393 //
394 // Lets say the state is something like this.
395 // +--------+ +--------+ +-----------+
396 // | symtab | | bucket | | chain |
397 // | null | | 1 | | STN_UNDEF |
398 // | <sym1> | | 4 | | 2 |
399 // | <sym2> | | | | 5 |
400 // | <sym3> | | | | STN_UNDEF |
401 // | <sym4> | | | | 3 |
402 // | <sym5> | | | | STN_UNDEF |
403 // +--------+ +--------+ +-----------+
404 //
405 // The lookup process (in python psudocode) is
406 //
407 // def GetSym(name):
408 // # NB STN_UNDEF == 0
409 // indx = bucket[elfhash(name) % num_buckets]
410 // while indx != STN_UNDEF:
411 // if GetSymbolName(symtab[indx]) == name:
412 // return symtab[indx]
413 // indx = chain[indx]
414 // return SYMBOL_NOT_FOUND
415 //
416 // Between bucket and chain arrays every symtab index must be present exactly
417 // once (except for STN_UNDEF, which must be present 1 + num_bucket times).
David Srbeckybc90fd02015-04-22 19:40:27 +0100418 const auto& symbols = symtab_->symbols_;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100419 // Select number of buckets.
420 // This is essentially arbitrary.
David Srbeckybc90fd02015-04-22 19:40:27 +0100421 Elf_Word nbuckets = GetNumBuckets();
422 // 1 is for the implicit NULL symbol.
423 Elf_Word chain_size = (symbols.size() + 1);
David Srbecky0c5bbc12015-04-28 17:54:52 +0100424 std::vector<Elf_Word> hash;
425 hash.push_back(nbuckets);
426 hash.push_back(chain_size);
427 uint32_t bucket_offset = hash.size();
428 uint32_t chain_offset = bucket_offset + nbuckets;
429 hash.resize(hash.size() + nbuckets + chain_size, 0);
430
431 Elf_Word* buckets = hash.data() + bucket_offset;
432 Elf_Word* chain = hash.data() + chain_offset;
433
434 // Set up the actual hash table.
David Srbeckybc90fd02015-04-22 19:40:27 +0100435 for (Elf_Word i = 0; i < symbols.size(); i++) {
David Srbecky0c5bbc12015-04-28 17:54:52 +0100436 // Add 1 since we need to have the null symbol that is not in the symbols
437 // list.
438 Elf_Word index = i + 1;
David Srbeckybc90fd02015-04-22 19:40:27 +0100439 Elf_Word hash_val = static_cast<Elf_Word>(elfhash(symbols[i].name_.c_str())) % nbuckets;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100440 if (buckets[hash_val] == 0) {
441 buckets[hash_val] = index;
442 } else {
443 hash_val = buckets[hash_val];
444 CHECK_LT(hash_val, chain_size);
445 while (chain[hash_val] != 0) {
446 hash_val = chain[hash_val];
447 CHECK_LT(hash_val, chain_size);
448 }
449 chain[hash_val] = index;
450 // Check for loops. Works because if this is non-empty then there must be
451 // another cell which already contains the same symbol index as this one,
452 // which means some symbol has more then one name, which isn't allowed.
453 CHECK_EQ(chain[index], static_cast<Elf_Word>(0));
454 }
455 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100456 return WriteArray(elf_file, hash.data(), hash.size());
David Srbecky0c5bbc12015-04-28 17:54:52 +0100457 }
458
459 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100460 Elf_Word GetNumBuckets() const {
461 const auto& symbols = symtab_->symbols_;
462 if (symbols.size() < 8) {
463 return 2;
464 } else if (symbols.size() < 32) {
465 return 4;
466 } else if (symbols.size() < 256) {
467 return 16;
468 } else {
469 // Have about 32 ids per bucket.
470 return RoundUp(symbols.size()/32, 2);
David Srbecky0c5bbc12015-04-28 17:54:52 +0100471 }
472 }
David Srbecky0c5bbc12015-04-28 17:54:52 +0100473
David Srbeckybc90fd02015-04-22 19:40:27 +0100474 // from bionic
475 static inline unsigned elfhash(const char *_name) {
476 const unsigned char *name = (const unsigned char *) _name;
477 unsigned h = 0, g;
David Srbecky0c5bbc12015-04-28 17:54:52 +0100478
David Srbeckybc90fd02015-04-22 19:40:27 +0100479 while (*name) {
480 h = (h << 4) + *name++;
481 g = h & 0xf0000000;
482 h ^= g;
483 h ^= g >> 24;
484 }
485 return h;
486 }
487
488 SymtabSection* symtab_;
489
490 DISALLOW_COPY_AND_ASSIGN(HashSection);
491 };
492
493 ElfBuilder(InstructionSet isa,
494 Elf_Word rodata_size, CodeOutput* rodata_writer,
495 Elf_Word text_size, CodeOutput* text_writer,
496 Elf_Word bss_size)
497 : isa_(isa),
498 dynstr_(".dynstr", SHF_ALLOC),
499 dynsym_(".dynsym", SHT_DYNSYM, SHF_ALLOC, &dynstr_),
500 hash_(".hash", SHF_ALLOC, &dynsym_),
501 rodata_(".rodata", SHT_PROGBITS, SHF_ALLOC,
502 nullptr, 0, kPageSize, 0, rodata_size, rodata_writer),
503 text_(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR,
504 nullptr, 0, kPageSize, 0, text_size, text_writer),
505 bss_(".bss", bss_size),
David Srbecky1a146bf2015-05-29 16:33:11 +0100506 dynamic_(".dynamic", &dynstr_),
David Srbeckybc90fd02015-04-22 19:40:27 +0100507 strtab_(".strtab", 0),
508 symtab_(".symtab", SHT_SYMTAB, 0, &strtab_),
509 shstrtab_(".shstrtab", 0) {
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700510 }
511 ~ElfBuilder() {}
512
David Srbeckybc90fd02015-04-22 19:40:27 +0100513 OatSection* GetText() { return &text_; }
514 SymtabSection* GetSymtab() { return &symtab_; }
Ian Rogers0279ebb2014-10-08 17:27:48 -0700515
David Srbeckybc90fd02015-04-22 19:40:27 +0100516 bool Write(File* elf_file) {
Vladimir Marko5c42c292015-02-25 12:02:49 +0000517 // Since the .text section of an oat file contains relative references to .rodata
518 // and (optionally) .bss, we keep these 2 or 3 sections together. This creates
519 // a non-traditional layout where the .bss section is mapped independently of the
520 // .dynamic section and needs its own program header with LOAD RW.
521 //
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700522 // The basic layout of the elf file. Order may be different in final output.
523 // +-------------------------+
524 // | Elf_Ehdr |
525 // +-------------------------+
526 // | Elf_Phdr PHDR |
David Srbeckyb0a962c2015-04-28 19:43:56 +0100527 // | Elf_Phdr LOAD R | .dynsym .dynstr .hash .rodata
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700528 // | Elf_Phdr LOAD R X | .text
Vladimir Marko5c42c292015-02-25 12:02:49 +0000529 // | Elf_Phdr LOAD RW | .bss (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700530 // | Elf_Phdr LOAD RW | .dynamic
531 // | Elf_Phdr DYNAMIC | .dynamic
David Srbeckyb0a962c2015-04-28 19:43:56 +0100532 // | Elf_Phdr LOAD R | .eh_frame .eh_frame_hdr
David Srbecky527c9c72015-04-17 21:14:10 +0100533 // | Elf_Phdr EH_FRAME R | .eh_frame_hdr
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700534 // +-------------------------+
535 // | .dynsym |
536 // | Elf_Sym STN_UNDEF |
537 // | Elf_Sym oatdata |
538 // | Elf_Sym oatexec |
539 // | Elf_Sym oatlastword |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000540 // | Elf_Sym oatbss | (Optional)
541 // | Elf_Sym oatbsslastword | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700542 // +-------------------------+
543 // | .dynstr |
David Srbeckybc90fd02015-04-22 19:40:27 +0100544 // | names for .dynsym |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700545 // +-------------------------+
546 // | .hash |
David Srbeckybc90fd02015-04-22 19:40:27 +0100547 // | hashtable for dynsym |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700548 // +-------------------------+
549 // | .rodata |
550 // | oatdata..oatexec-4 |
551 // +-------------------------+
552 // | .text |
553 // | oatexec..oatlastword |
554 // +-------------------------+
555 // | .dynamic |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700556 // | Elf_Dyn DT_HASH |
David Srbeckybc90fd02015-04-22 19:40:27 +0100557 // | Elf_Dyn DT_STRTAB |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700558 // | Elf_Dyn DT_SYMTAB |
559 // | Elf_Dyn DT_SYMENT |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700560 // | Elf_Dyn DT_STRSZ |
David Srbeckybc90fd02015-04-22 19:40:27 +0100561 // | Elf_Dyn DT_SONAME |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700562 // | Elf_Dyn DT_NULL |
563 // +-------------------------+ (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700564 // | .symtab | (Optional)
565 // | program symbols | (Optional)
David Srbeckybc90fd02015-04-22 19:40:27 +0100566 // +-------------------------+ (Optional)
567 // | .strtab | (Optional)
568 // | names for .symtab | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700569 // +-------------------------+ (Optional)
David Srbeckyb0a962c2015-04-28 19:43:56 +0100570 // | .eh_frame | (Optional)
571 // +-------------------------+ (Optional)
572 // | .eh_frame_hdr | (Optional)
573 // +-------------------------+ (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700574 // | .debug_info | (Optional)
575 // +-------------------------+ (Optional)
576 // | .debug_abbrev | (Optional)
577 // +-------------------------+ (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100578 // | .debug_str | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700579 // +-------------------------+ (Optional)
580 // | .debug_line | (Optional)
David Srbeckybc90fd02015-04-22 19:40:27 +0100581 // +-------------------------+
582 // | .shstrtab |
583 // | names of sections |
584 // +-------------------------+
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700585 // | Elf_Shdr null |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700586 // | Elf_Shdr .dynsym |
587 // | Elf_Shdr .dynstr |
588 // | Elf_Shdr .hash |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700589 // | Elf_Shdr .rodata |
Vladimir Marko5c42c292015-02-25 12:02:49 +0000590 // | Elf_Shdr .text |
591 // | Elf_Shdr .bss | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700592 // | Elf_Shdr .dynamic |
David Srbeckybc90fd02015-04-22 19:40:27 +0100593 // | Elf_Shdr .symtab | (Optional)
594 // | Elf_Shdr .strtab | (Optional)
David Srbeckyb0a962c2015-04-28 19:43:56 +0100595 // | Elf_Shdr .eh_frame | (Optional)
596 // | Elf_Shdr .eh_frame_hdr | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700597 // | Elf_Shdr .debug_info | (Optional)
598 // | Elf_Shdr .debug_abbrev | (Optional)
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700599 // | Elf_Shdr .debug_str | (Optional)
David Srbecky527c9c72015-04-17 21:14:10 +0100600 // | Elf_Shdr .debug_line | (Optional)
David Srbeckybc90fd02015-04-22 19:40:27 +0100601 // | Elf_Shdr .oat_patches | (Optional)
602 // | Elf_Shdr .shstrtab |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700603 // +-------------------------+
David Srbeckybc90fd02015-04-22 19:40:27 +0100604 constexpr bool debug_logging_ = false;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700605
David Srbeckybc90fd02015-04-22 19:40:27 +0100606 // Create a list of all section which we want to write.
607 // This is the order in which they will be written.
608 std::vector<Section*> sections;
609 sections.push_back(&dynsym_);
610 sections.push_back(&dynstr_);
611 sections.push_back(&hash_);
David Srbeckybc90fd02015-04-22 19:40:27 +0100612 sections.push_back(&rodata_);
613 sections.push_back(&text_);
614 if (bss_.GetSize() != 0u) {
615 sections.push_back(&bss_);
Vladimir Marko5c42c292015-02-25 12:02:49 +0000616 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100617 sections.push_back(&dynamic_);
618 if (!symtab_.IsEmpty()) {
619 sections.push_back(&symtab_);
620 sections.push_back(&strtab_);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700621 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100622 for (Section* section : other_sections_) {
David Srbeckyb0a962c2015-04-28 19:43:56 +0100623 sections.push_back(section);
David Srbecky527c9c72015-04-17 21:14:10 +0100624 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100625 sections.push_back(&shstrtab_);
626 for (size_t i = 0; i < sections.size(); i++) {
627 // The first section index is 1. Index 0 is reserved for NULL.
628 // Section index is used for relative symbols and for section links.
629 sections[i]->SetSectionIndex(i + 1);
630 // Add section name to .shstrtab.
631 Elf_Word name_offset = shstrtab_.AddName(sections[i]->GetName());
632 sections[i]->GetHeader()->sh_name = name_offset;
David Srbecky527c9c72015-04-17 21:14:10 +0100633 }
634
David Srbeckybc90fd02015-04-22 19:40:27 +0100635 // The running program does not have access to section headers
636 // and the loader is not supposed to use them either.
637 // The dynamic sections therefore replicates some of the layout
638 // information like the address and size of .rodata and .text.
639 // It also contains other metadata like the SONAME.
640 // The .dynamic section is found using the PT_DYNAMIC program header.
641 BuildDynsymSection();
642 BuildDynamicSection(elf_file->GetPath());
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700643
David Srbeckybc90fd02015-04-22 19:40:27 +0100644 // We do not know the number of headers until the final stages of write.
645 // It is easiest to just reserve a fixed amount of space for them.
David Srbeckyb0a962c2015-04-28 19:43:56 +0100646 constexpr size_t kMaxProgramHeaders = 8;
David Srbeckybc90fd02015-04-22 19:40:27 +0100647 constexpr size_t kProgramHeadersOffset = sizeof(Elf_Ehdr);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700648
David Srbeckybc90fd02015-04-22 19:40:27 +0100649 // Layout of all sections - determine the final file offsets and addresses.
650 // This must be done after we have built all sections and know their size.
David Srbecky24981a12015-05-29 15:21:20 +0100651 Elf_Off file_offset = kProgramHeadersOffset + sizeof(Elf_Phdr) * kMaxProgramHeaders;
David Srbeckybc90fd02015-04-22 19:40:27 +0100652 Elf_Addr load_address = file_offset;
653 std::vector<Elf_Shdr> section_headers;
654 section_headers.reserve(1u + sections.size());
655 section_headers.push_back(Elf_Shdr()); // NULL at index 0.
656 for (auto* section : sections) {
657 Elf_Shdr* header = section->GetHeader();
658 Elf_Off alignment = header->sh_addralign > 0 ? header->sh_addralign : 1;
659 header->sh_size = section->GetSize();
660 header->sh_link = section->GetLink();
661 // Allocate memory for the section in the file.
662 if (header->sh_type != SHT_NOBITS) {
663 header->sh_offset = RoundUp(file_offset, alignment);
664 file_offset = header->sh_offset + header->sh_size;
665 }
666 // Allocate memory for the section during program execution.
667 if ((header->sh_flags & SHF_ALLOC) != 0) {
668 header->sh_addr = RoundUp(load_address, alignment);
669 load_address = header->sh_addr + header->sh_size;
670 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700671 if (debug_logging_) {
David Srbeckybc90fd02015-04-22 19:40:27 +0100672 LOG(INFO) << "Section " << section->GetName() << ":" << std::hex
673 << " offset=0x" << header->sh_offset
674 << " addr=0x" << header->sh_addr
675 << " size=0x" << header->sh_size;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700676 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100677 // Collect section headers into continuous array for convenience.
678 section_headers.push_back(*header);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700679 }
David Srbecky67a06532015-05-29 18:09:05 +0100680 Elf_Off section_headers_offset = RoundUp(file_offset, sizeof(Elf_Off));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700681
David Srbeckybc90fd02015-04-22 19:40:27 +0100682 // Create program headers now that we know the layout of the whole file.
683 // Each segment contains one or more sections which are mapped together.
684 // Not all sections are mapped during the execution of the program.
685 // PT_LOAD does the mapping. Other PT_* types allow the program to locate
686 // interesting parts of memory and their addresses overlap with PT_LOAD.
687 std::vector<Elf_Phdr> program_headers;
David Srbecky24981a12015-05-29 15:21:20 +0100688 program_headers.push_back(Elf_Phdr()); // Placeholder for PT_PHDR.
David Srbeckybc90fd02015-04-22 19:40:27 +0100689 // Create the main LOAD R segment which spans all sections up to .rodata.
690 const Elf_Shdr* rodata = rodata_.GetHeader();
691 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R,
692 0, rodata->sh_offset + rodata->sh_size, rodata->sh_addralign));
693 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_X, text_));
694 if (bss_.GetHeader()->sh_size != 0u) {
695 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_W, bss_));
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700696 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100697 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R | PF_W, dynamic_));
698 program_headers.push_back(MakeProgramHeader(PT_DYNAMIC, PF_R | PF_W, dynamic_));
David Srbeckyb0a962c2015-04-28 19:43:56 +0100699 const Section* eh_frame = FindSection(".eh_frame");
700 if (eh_frame != nullptr) {
701 program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R, *eh_frame));
702 const Section* eh_frame_hdr = FindSection(".eh_frame_hdr");
703 if (eh_frame_hdr != nullptr) {
704 // Check layout: eh_frame is before eh_frame_hdr and there is no gap.
705 CHECK_LE(eh_frame->GetHeader()->sh_offset, eh_frame_hdr->GetHeader()->sh_offset);
706 CHECK_EQ(eh_frame->GetHeader()->sh_offset + eh_frame->GetHeader()->sh_size,
707 eh_frame_hdr->GetHeader()->sh_offset);
708 // Extend the PT_LOAD of .eh_frame to include the .eh_frame_hdr as well.
709 program_headers.back().p_filesz += eh_frame_hdr->GetHeader()->sh_size;
710 program_headers.back().p_memsz += eh_frame_hdr->GetHeader()->sh_size;
711 program_headers.push_back(MakeProgramHeader(PT_GNU_EH_FRAME, PF_R, *eh_frame_hdr));
712 }
David Srbecky527c9c72015-04-17 21:14:10 +0100713 }
David Srbecky24981a12015-05-29 15:21:20 +0100714 DCHECK_EQ(program_headers[0].p_type, 0u); // Check placeholder.
715 program_headers[0] = MakeProgramHeader(PT_PHDR, PF_R,
David Srbecky67a06532015-05-29 18:09:05 +0100716 kProgramHeadersOffset, program_headers.size() * sizeof(Elf_Phdr), sizeof(Elf_Off));
David Srbeckybc90fd02015-04-22 19:40:27 +0100717 CHECK_LE(program_headers.size(), kMaxProgramHeaders);
David Srbecky527c9c72015-04-17 21:14:10 +0100718
David Srbeckybc90fd02015-04-22 19:40:27 +0100719 // Create the main ELF header.
720 Elf_Ehdr elf_header = MakeElfHeader(isa_);
721 elf_header.e_phoff = kProgramHeadersOffset;
722 elf_header.e_shoff = section_headers_offset;
723 elf_header.e_phnum = program_headers.size();
724 elf_header.e_shnum = section_headers.size();
725 elf_header.e_shstrndx = shstrtab_.GetSectionIndex();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700726
David Srbeckybc90fd02015-04-22 19:40:27 +0100727 // Write all headers and section content to the file.
728 // Depending on the implementations of Section::Write, this
729 // might be just memory copies or some more elaborate operations.
730 if (!WriteArray(elf_file, &elf_header, 1)) {
731 LOG(INFO) << "Failed to write the ELF header";
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700732 return false;
733 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100734 if (!WriteArray(elf_file, program_headers.data(), program_headers.size())) {
735 LOG(INFO) << "Failed to write the program headers";
736 return false;
737 }
738 for (Section* section : sections) {
739 const Elf_Shdr* header = section->GetHeader();
740 if (header->sh_type != SHT_NOBITS) {
741 if (!SeekTo(elf_file, header->sh_offset) || !section->Write(elf_file)) {
742 LOG(INFO) << "Failed to write section " << section->GetName();
743 return false;
744 }
745 Elf_Word current_offset = lseek(elf_file->Fd(), 0, SEEK_CUR);
746 CHECK_EQ(current_offset, header->sh_offset + header->sh_size)
747 << "The number of bytes written does not match GetSize()";
748 }
749 }
750 if (!SeekTo(elf_file, section_headers_offset) ||
751 !WriteArray(elf_file, section_headers.data(), section_headers.size())) {
752 LOG(INFO) << "Failed to write the section headers";
753 return false;
754 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700755 return true;
756 }
757
David Srbeckybc90fd02015-04-22 19:40:27 +0100758 // Adds the given section to the builder. It does not take ownership.
759 void RegisterSection(Section* section) {
760 other_sections_.push_back(section);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700761 }
762
David Srbeckybc90fd02015-04-22 19:40:27 +0100763 const Section* FindSection(const char* name) {
764 for (const auto* section : other_sections_) {
765 if (section->GetName() == name) {
766 return section;
David Srbecky527c9c72015-04-17 21:14:10 +0100767 }
768 }
769 return nullptr;
770 }
771
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700772 private:
David Srbeckybc90fd02015-04-22 19:40:27 +0100773 static bool SeekTo(File* elf_file, Elf_Word offset) {
774 DCHECK_LE(lseek(elf_file->Fd(), 0, SEEK_CUR), static_cast<off_t>(offset))
775 << "Seeking backwards";
776 if (static_cast<off_t>(offset) != lseek(elf_file->Fd(), offset, SEEK_SET)) {
777 PLOG(ERROR) << "Failed to seek in file " << elf_file->GetPath();
778 return false;
779 }
780 return true;
781 }
782
783 template<typename T>
784 static bool WriteArray(File* elf_file, const T* data, size_t count) {
David Srbeckyf8980872015-05-22 17:04:47 +0100785 if (count != 0) {
786 DCHECK(data != nullptr);
787 if (!elf_file->WriteFully(data, count * sizeof(T))) {
788 PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
789 return false;
790 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100791 }
792 return true;
793 }
794
795 // Helper - create segment header based on memory range.
796 static Elf_Phdr MakeProgramHeader(Elf_Word type, Elf_Word flags,
797 Elf_Off offset, Elf_Word size, Elf_Word align) {
798 Elf_Phdr phdr = Elf_Phdr();
799 phdr.p_type = type;
800 phdr.p_flags = flags;
801 phdr.p_offset = offset;
802 phdr.p_vaddr = offset;
803 phdr.p_paddr = offset;
804 phdr.p_filesz = size;
805 phdr.p_memsz = size;
806 phdr.p_align = align;
807 return phdr;
808 }
809
810 // Helper - create segment header based on section header.
811 static Elf_Phdr MakeProgramHeader(Elf_Word type, Elf_Word flags,
812 const Section& section) {
813 const Elf_Shdr* shdr = section.GetHeader();
814 // Only run-time allocated sections should be in segment headers.
815 CHECK_NE(shdr->sh_flags & SHF_ALLOC, 0u);
816 Elf_Phdr phdr = Elf_Phdr();
817 phdr.p_type = type;
818 phdr.p_flags = flags;
819 phdr.p_offset = shdr->sh_offset;
820 phdr.p_vaddr = shdr->sh_addr;
821 phdr.p_paddr = shdr->sh_addr;
822 phdr.p_filesz = shdr->sh_type != SHT_NOBITS ? shdr->sh_size : 0u;
823 phdr.p_memsz = shdr->sh_size;
824 phdr.p_align = shdr->sh_addralign;
825 return phdr;
826 }
827
828 static Elf_Ehdr MakeElfHeader(InstructionSet isa) {
829 Elf_Ehdr elf_header = Elf_Ehdr();
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700830 switch (isa) {
831 case kArm:
832 // Fall through.
833 case kThumb2: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100834 elf_header.e_machine = EM_ARM;
835 elf_header.e_flags = EF_ARM_EABI_VER5;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700836 break;
837 }
838 case kArm64: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100839 elf_header.e_machine = EM_AARCH64;
840 elf_header.e_flags = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700841 break;
842 }
843 case kX86: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100844 elf_header.e_machine = EM_386;
845 elf_header.e_flags = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700846 break;
847 }
848 case kX86_64: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100849 elf_header.e_machine = EM_X86_64;
850 elf_header.e_flags = 0;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700851 break;
852 }
853 case kMips: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100854 elf_header.e_machine = EM_MIPS;
855 elf_header.e_flags = (EF_MIPS_NOREORDER |
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700856 EF_MIPS_PIC |
857 EF_MIPS_CPIC |
858 EF_MIPS_ABI_O32 |
859 EF_MIPS_ARCH_32R2);
860 break;
861 }
Andreas Gampe57b34292015-01-14 15:45:59 -0800862 case kMips64: {
David Srbeckybc90fd02015-04-22 19:40:27 +0100863 elf_header.e_machine = EM_MIPS;
864 elf_header.e_flags = (EF_MIPS_NOREORDER |
Andreas Gampe57b34292015-01-14 15:45:59 -0800865 EF_MIPS_PIC |
866 EF_MIPS_CPIC |
867 EF_MIPS_ARCH_64R6);
868 break;
869 }
David Srbeckybc90fd02015-04-22 19:40:27 +0100870 case kNone: {
871 LOG(FATAL) << "No instruction set";
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700872 }
873 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700874
David Srbeckybc90fd02015-04-22 19:40:27 +0100875 elf_header.e_ident[EI_MAG0] = ELFMAG0;
876 elf_header.e_ident[EI_MAG1] = ELFMAG1;
877 elf_header.e_ident[EI_MAG2] = ELFMAG2;
878 elf_header.e_ident[EI_MAG3] = ELFMAG3;
879 elf_header.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
Tong Shen62d1ca32014-09-03 17:24:56 -0700880 ? ELFCLASS32 : ELFCLASS64;;
David Srbeckybc90fd02015-04-22 19:40:27 +0100881 elf_header.e_ident[EI_DATA] = ELFDATA2LSB;
882 elf_header.e_ident[EI_VERSION] = EV_CURRENT;
883 elf_header.e_ident[EI_OSABI] = ELFOSABI_LINUX;
884 elf_header.e_ident[EI_ABIVERSION] = 0;
885 elf_header.e_type = ET_DYN;
886 elf_header.e_version = 1;
887 elf_header.e_entry = 0;
888 elf_header.e_ehsize = sizeof(Elf_Ehdr);
889 elf_header.e_phentsize = sizeof(Elf_Phdr);
890 elf_header.e_shentsize = sizeof(Elf_Shdr);
891 elf_header.e_phoff = sizeof(Elf_Ehdr);
892 return elf_header;
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700893 }
894
David Srbeckybc90fd02015-04-22 19:40:27 +0100895 void BuildDynamicSection(const std::string& elf_file_path) {
896 std::string soname(elf_file_path);
897 size_t directory_separator_pos = soname.rfind('/');
898 if (directory_separator_pos != std::string::npos) {
899 soname = soname.substr(directory_separator_pos + 1);
900 }
901 // NB: We must add the name before adding DT_STRSZ.
902 Elf_Word soname_offset = dynstr_.AddName(soname);
903
904 dynamic_.AddDynamicTag(DT_HASH, 0, &hash_);
905 dynamic_.AddDynamicTag(DT_STRTAB, 0, &dynstr_);
906 dynamic_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_);
907 dynamic_.AddDynamicTag(DT_SYMENT, sizeof(Elf_Sym), nullptr);
908 dynamic_.AddDynamicTag(DT_STRSZ, dynstr_.GetSize(), nullptr);
909 dynamic_.AddDynamicTag(DT_SONAME, soname_offset, nullptr);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700910 }
911
David Srbeckybc90fd02015-04-22 19:40:27 +0100912 void BuildDynsymSection() {
913 dynsym_.AddSymbol("oatdata", &rodata_, 0, true,
914 rodata_.GetSize(), STB_GLOBAL, STT_OBJECT);
915 dynsym_.AddSymbol("oatexec", &text_, 0, true,
916 text_.GetSize(), STB_GLOBAL, STT_OBJECT);
917 dynsym_.AddSymbol("oatlastword", &text_, text_.GetSize() - 4,
918 true, 4, STB_GLOBAL, STT_OBJECT);
919 if (bss_.GetSize() != 0u) {
920 dynsym_.AddSymbol("oatbss", &bss_, 0, true,
921 bss_.GetSize(), STB_GLOBAL, STT_OBJECT);
922 dynsym_.AddSymbol("oatbsslastword", &bss_, bss_.GetSize() - 4,
923 true, 4, STB_GLOBAL, STT_OBJECT);
Vladimir Marko5c42c292015-02-25 12:02:49 +0000924 }
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700925 }
926
David Srbeckybc90fd02015-04-22 19:40:27 +0100927 InstructionSet isa_;
928 StrtabSection dynstr_;
929 SymtabSection dynsym_;
930 HashSection hash_;
931 OatSection rodata_;
932 OatSection text_;
933 NoBitsSection bss_;
934 DynamicSection dynamic_;
935 StrtabSection strtab_;
936 SymtabSection symtab_;
937 std::vector<Section*> other_sections_;
938 StrtabSection shstrtab_;
Ian Rogers0279ebb2014-10-08 17:27:48 -0700939
940 DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
Andreas Gampe54fc26c2014-09-04 21:47:42 -0700941};
942
943} // namespace art
944
945#endif // ART_COMPILER_ELF_BUILDER_H_