summaryrefslogtreecommitdiffstats
path: root/compiler/elf_writer_quick.h
diff options
context:
space:
mode:
authorBrian Carlstrom <bdc@google.com>2014-06-11 14:54:46 -0700
committerBrian Carlstrom <bdc@google.com>2014-06-11 15:02:00 -0700
commitb12f34742be4adaa804cc0d388ba51603bb95955 (patch)
treee2b61293c0b6be0f83f8ea46ae2f4d764b3a8f4a /compiler/elf_writer_quick.h
parent16e1eda5b1fcaf617371072692503714c7a6afe8 (diff)
downloadart-b12f34742be4adaa804cc0d388ba51603bb95955.zip
art-b12f34742be4adaa804cc0d388ba51603bb95955.tar.gz
art-b12f34742be4adaa804cc0d388ba51603bb95955.tar.bz2
Revert "Revert "Rewrite ElfWriterQuick to make it more modular.""
This reverts commit 35f72251e722cad03a08e8ceacbd5c244eab5c29.
Diffstat (limited to 'compiler/elf_writer_quick.h')
-rw-r--r--compiler/elf_writer_quick.h261
1 files changed, 261 insertions, 0 deletions
diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h
index dec75dc..fe7ce18 100644
--- a/compiler/elf_writer_quick.h
+++ b/compiler/elf_writer_quick.h
@@ -17,7 +17,9 @@
#ifndef ART_COMPILER_ELF_WRITER_QUICK_H_
#define ART_COMPILER_ELF_WRITER_QUICK_H_
+#include "elf_utils.h"
#include "elf_writer.h"
+#include "instruction_set.h"
namespace art {
@@ -45,6 +47,265 @@ class ElfWriterQuick FINAL : public ElfWriter {
: ElfWriter(driver, elf_file) {}
~ElfWriterQuick() {}
+ class ElfBuilder;
+ class ElfSectionBuilder {
+ public:
+ ElfSectionBuilder(const std::string& sec_name, Elf32_Word type, Elf32_Word flags,
+ const ElfSectionBuilder *link, Elf32_Word info, Elf32_Word align,
+ Elf32_Word entsize)
+ : name_(sec_name), link_(link) {
+ memset(&section_, 0, sizeof(section_));
+ section_.sh_type = type;
+ section_.sh_flags = flags;
+ section_.sh_info = info;
+ section_.sh_addralign = align;
+ section_.sh_entsize = entsize;
+ }
+
+ virtual ~ElfSectionBuilder() {}
+
+ Elf32_Shdr section_;
+ Elf32_Word section_index_ = 0;
+
+ protected:
+ const std::string name_;
+ const ElfSectionBuilder* link_;
+
+ Elf32_Word GetLink() {
+ return (link_) ? link_->section_index_ : 0;
+ }
+
+ private:
+ friend class ElfBuilder;
+ };
+
+ class ElfDynamicBuilder : public ElfSectionBuilder {
+ public:
+ void AddDynamicTag(Elf32_Sword tag, Elf32_Sword d_un);
+ void AddDynamicTag(Elf32_Sword tag, Elf32_Sword offset, ElfSectionBuilder* section);
+
+ ElfDynamicBuilder(const std::string& sec_name, ElfSectionBuilder *link)
+ : ElfSectionBuilder(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC, link,
+ 0, kPageSize, sizeof(Elf32_Dyn)) {}
+ ~ElfDynamicBuilder() {}
+
+ protected:
+ struct ElfDynamicState {
+ ElfSectionBuilder* section_;
+ Elf32_Sword tag_;
+ Elf32_Sword off_;
+ };
+ std::vector<ElfDynamicState> dynamics_;
+ Elf32_Word size() {
+ // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
+ // these must be added when we actually put the file together because
+ // their values are very dependent on state.
+ return dynamics_.size() + 3;
+ }
+
+ // Create the actual dynamic vector. strsz should be the size of the .dynstr
+ // table and soname_off should be the offset of the soname in .dynstr.
+ // Since niether can be found prior to final layout we will wait until here
+ // to add them.
+ std::vector<Elf32_Dyn> GetDynamics(Elf32_Sword strsz, Elf32_Sword soname_off);
+
+ private:
+ friend class ElfBuilder;
+ };
+
+ class ElfRawSectionBuilder : public ElfSectionBuilder {
+ public:
+ ElfRawSectionBuilder(const std::string& sec_name, Elf32_Word type, Elf32_Word flags,
+ const ElfSectionBuilder* link, Elf32_Word info, Elf32_Word align,
+ Elf32_Word entsize)
+ : ElfSectionBuilder(sec_name, type, flags, link, info, align, entsize) {}
+ ~ElfRawSectionBuilder() {}
+ std::vector<uint8_t>* GetBuffer() { return &buf_; }
+ void SetBuffer(std::vector<uint8_t> buf) { buf_ = buf; }
+
+ protected:
+ std::vector<uint8_t> buf_;
+
+ private:
+ friend class ElfBuilder;
+ };
+
+ class ElfOatSectionBuilder : public ElfSectionBuilder {
+ public:
+ ElfOatSectionBuilder(const std::string& sec_name, Elf32_Word size, Elf32_Word offset,
+ Elf32_Word type, Elf32_Word flags)
+ : ElfSectionBuilder(sec_name, type, flags, NULL, 0, kPageSize, 0),
+ offset_(offset), size_(size) {}
+ ~ElfOatSectionBuilder() {}
+
+ protected:
+ // Offset of the content within the file.
+ Elf32_Word offset_;
+ // Size of the content within the file.
+ Elf32_Word size_;
+
+ private:
+ friend class ElfBuilder;
+ };
+
+ class ElfSymtabBuilder : public ElfSectionBuilder {
+ public:
+ // Add a symbol with given name to this symtab. The symbol refers to
+ // 'relative_addr' within the given section and has the given attributes.
+ void AddSymbol(const std::string& name,
+ const ElfSectionBuilder* section,
+ Elf32_Addr addr,
+ bool is_relative,
+ Elf32_Word size,
+ uint8_t binding,
+ uint8_t type,
+ uint8_t other = 0);
+
+ ElfSymtabBuilder(const std::string& sec_name, Elf32_Word type,
+ const std::string& str_name, Elf32_Word str_type, bool alloc)
+ : ElfSectionBuilder(sec_name, type, ((alloc)?SHF_ALLOC:0), &strtab_, 0,
+ sizeof(Elf32_Word), sizeof(Elf32_Sym)),
+ str_name_(str_name), str_type_(str_type),
+ strtab_(str_name, str_type, ((alloc) ? SHF_ALLOC : 0), NULL, 0, 1, 1) {}
+ ~ElfSymtabBuilder() {}
+
+ protected:
+ std::vector<Elf32_Word> GenerateHashContents();
+ std::string GenerateStrtab();
+ std::vector<Elf32_Sym> GenerateSymtab();
+
+ Elf32_Word size() {
+ // 1 is for the implicit NULL symbol.
+ return symbols_.size() + 1;
+ }
+
+ struct ElfSymbolState {
+ const std::string name_;
+ const ElfSectionBuilder* section_;
+ Elf32_Addr addr_;
+ Elf32_Word size_;
+ bool is_relative_;
+ uint8_t info_;
+ uint8_t other_;
+ // Used during Write() to temporarially hold name index in the strtab.
+ Elf32_Word name_idx_;
+ };
+
+ // Information for the strsym for dynstr sections.
+ const std::string str_name_;
+ Elf32_Word str_type_;
+ // The symbols in the same order they will be in the symbol table.
+ std::vector<ElfSymbolState> symbols_;
+ ElfSectionBuilder strtab_;
+
+ private:
+ friend class ElfBuilder;
+ };
+
+ class ElfBuilder FINAL {
+ public:
+ ElfBuilder(OatWriter* oat_writer,
+ File* elf_file,
+ InstructionSet isa,
+ Elf32_Word rodata_relative_offset,
+ Elf32_Word rodata_size,
+ Elf32_Word text_relative_offset,
+ Elf32_Word text_size,
+ const bool add_symbols,
+ bool debug = false)
+ : oat_writer_(oat_writer),
+ elf_file_(elf_file),
+ add_symbols_(add_symbols),
+ debug_logging_(debug),
+ text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
+ SHF_ALLOC | SHF_EXECINSTR),
+ rodata_builder_(".rodata", rodata_size, rodata_relative_offset,
+ SHT_PROGBITS, SHF_ALLOC),
+ dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
+ symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
+ hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0,
+ sizeof(Elf32_Word), sizeof(Elf32_Word)),
+ dynamic_builder_(".dynamic", &dynsym_builder_),
+ shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
+ SetupEhdr();
+ SetupDynamic();
+ SetupRequiredSymbols();
+ SetISA(isa);
+ }
+ ~ElfBuilder() {}
+
+ bool Write();
+ ElfSymtabBuilder* GetDefaultDynsymBuilder() { return &dynsym_builder_; }
+
+ // Adds the given raw section to the builder. This will copy it. The caller
+ // is responsible for deallocating their copy.
+ void RegisterRawSection(ElfRawSectionBuilder bld) {
+ other_builders_.push_back(bld);
+ }
+
+ private:
+ OatWriter* oat_writer_;
+ File* elf_file_;
+ const bool add_symbols_;
+ const bool debug_logging_;
+
+ bool fatal_error_ = false;
+
+ Elf32_Ehdr elf_header_;
+
+ public:
+ ElfOatSectionBuilder text_builder_;
+ ElfOatSectionBuilder rodata_builder_;
+ ElfSymtabBuilder dynsym_builder_;
+ ElfSymtabBuilder symtab_builder_;
+ ElfSectionBuilder hash_builder_;
+ ElfDynamicBuilder dynamic_builder_;
+ ElfSectionBuilder shstrtab_builder_;
+ std::vector<ElfRawSectionBuilder> other_builders_;
+
+ private:
+ void SetISA(InstructionSet isa);
+ void SetupEhdr();
+
+ // Sets up a bunch of the required Dynamic Section entries.
+ // Namely it will initialize all the mandatory ones that it can.
+ // Specifically:
+ // DT_HASH
+ // DT_STRTAB
+ // DT_SYMTAB
+ // DT_SYMENT
+ //
+ // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
+ void SetupDynamic();
+
+ // Sets up the basic dynamic symbols that are needed, namely all those we
+ // can know already.
+ //
+ // Specifically adds:
+ // oatdata
+ // oatexec
+ // oatlastword
+ void SetupRequiredSymbols();
+ void AssignSectionStr(ElfSectionBuilder *builder, std::string* strtab);
+ struct ElfFilePiece {
+ ElfFilePiece(const std::string& name, Elf32_Word offset, const void* data, Elf32_Word size)
+ : dbg_name_(name), offset_(offset), data_(data), size_(size) {}
+ ~ElfFilePiece() {}
+
+ const std::string& dbg_name_;
+ Elf32_Word offset_;
+ const void *data_;
+ Elf32_Word size_;
+ static bool Compare(ElfFilePiece a, ElfFilePiece b) {
+ return a.offset_ < b.offset_;
+ }
+ };
+
+ // Write each of the pieces out to the file.
+ bool WriteOutFile(const std::vector<ElfFilePiece>& pieces);
+ bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.size() > 1; }
+ };
+
/*
* @brief Generate the DWARF debug_info and debug_abbrev sections
* @param oat_writer The Oat file Writer.