diff options
author | Alex Light <allight@google.com> | 2014-06-04 15:43:03 -0700 |
---|---|---|
committer | Alex Light <allight@google.com> | 2014-06-09 15:18:18 -0700 |
commit | ad13cb2db8c4a64298ed85c82ae7366ee73f7640 (patch) | |
tree | dccfebf1adafbbc89492b087bec000d7767868e9 /compiler/elf_writer_quick.h | |
parent | 5d4a3fedcb18dadba5f50661e2a6d86890adfcbc (diff) | |
download | android_art-ad13cb2db8c4a64298ed85c82ae7366ee73f7640.tar.gz android_art-ad13cb2db8c4a64298ed85c82ae7366ee73f7640.tar.bz2 android_art-ad13cb2db8c4a64298ed85c82ae7366ee73f7640.zip |
Rewrite ElfWriterQuick to make it more modular.
Remade ElfWriterQuick so that it would use a more modular design and allow
the addition of additional features onto it in a more straightforward way.
Change-Id: I07971eb2080890645fab1b02c7305697e85d3a64
Diffstat (limited to 'compiler/elf_writer_quick.h')
-rw-r--r-- | compiler/elf_writer_quick.h | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h index dec75dc83f..fe7ce18736 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(§ion_, 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. |