Home | History | Annotate | Download | only in compiler
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      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_WRITER_QUICK_H_
     18 #define ART_COMPILER_ELF_WRITER_QUICK_H_
     19 
     20 #include "elf_utils.h"
     21 #include "elf_writer.h"
     22 #include "instruction_set.h"
     23 
     24 namespace art {
     25 
     26 class ElfWriterQuick FINAL : public ElfWriter {
     27  public:
     28   // Write an ELF file. Returns true on success, false on failure.
     29   static bool Create(File* file,
     30                      OatWriter* oat_writer,
     31                      const std::vector<const DexFile*>& dex_files,
     32                      const std::string& android_root,
     33                      bool is_host,
     34                      const CompilerDriver& driver)
     35       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     36 
     37  protected:
     38   bool Write(OatWriter* oat_writer,
     39              const std::vector<const DexFile*>& dex_files,
     40              const std::string& android_root,
     41              bool is_host)
     42       OVERRIDE
     43       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
     44 
     45  private:
     46   ElfWriterQuick(const CompilerDriver& driver, File* elf_file)
     47     : ElfWriter(driver, elf_file) {}
     48   ~ElfWriterQuick() {}
     49 
     50   class ElfBuilder;
     51   void AddDebugSymbols(ElfBuilder& builder,
     52                        OatWriter* oat_writer,
     53                        bool debug);
     54   void ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug);
     55 
     56   class ElfSectionBuilder {
     57    public:
     58     ElfSectionBuilder(const std::string& sec_name, Elf32_Word type, Elf32_Word flags,
     59                       const ElfSectionBuilder *link, Elf32_Word info, Elf32_Word align,
     60                       Elf32_Word entsize)
     61         : name_(sec_name), link_(link) {
     62       memset(&section_, 0, sizeof(section_));
     63       section_.sh_type = type;
     64       section_.sh_flags = flags;
     65       section_.sh_info = info;
     66       section_.sh_addralign = align;
     67       section_.sh_entsize = entsize;
     68     }
     69 
     70     virtual ~ElfSectionBuilder() {}
     71 
     72     Elf32_Shdr section_;
     73     Elf32_Word section_index_ = 0;
     74 
     75    protected:
     76     const std::string name_;
     77     const ElfSectionBuilder* link_;
     78 
     79     Elf32_Word GetLink() {
     80       return (link_) ? link_->section_index_ : 0;
     81     }
     82 
     83    private:
     84     friend class ElfBuilder;
     85   };
     86 
     87   class ElfDynamicBuilder : public ElfSectionBuilder {
     88    public:
     89     void AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un);
     90     void AddDynamicTag(Elf32_Sword tag, Elf32_Word offset, ElfSectionBuilder* section);
     91 
     92     ElfDynamicBuilder(const std::string& sec_name, ElfSectionBuilder *link)
     93         : ElfSectionBuilder(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC, link,
     94                             0, kPageSize, sizeof(Elf32_Dyn)) {}
     95     ~ElfDynamicBuilder() {}
     96 
     97    protected:
     98     struct ElfDynamicState {
     99       ElfSectionBuilder* section_;
    100       Elf32_Sword tag_;
    101       Elf32_Word off_;
    102     };
    103     std::vector<ElfDynamicState> dynamics_;
    104     Elf32_Word GetSize() {
    105       // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of
    106       // these must be added when we actually put the file together because
    107       // their values are very dependent on state.
    108       return dynamics_.size() + 3;
    109     }
    110 
    111     // Create the actual dynamic vector. strsz should be the size of the .dynstr
    112     // table and soname_off should be the offset of the soname in .dynstr.
    113     // Since niether can be found prior to final layout we will wait until here
    114     // to add them.
    115     std::vector<Elf32_Dyn> GetDynamics(Elf32_Word strsz, Elf32_Word soname_off);
    116 
    117    private:
    118     friend class ElfBuilder;
    119   };
    120 
    121   class ElfRawSectionBuilder : public ElfSectionBuilder {
    122    public:
    123     ElfRawSectionBuilder(const std::string& sec_name, Elf32_Word type, Elf32_Word flags,
    124                          const ElfSectionBuilder* link, Elf32_Word info, Elf32_Word align,
    125                          Elf32_Word entsize)
    126         : ElfSectionBuilder(sec_name, type, flags, link, info, align, entsize) {}
    127     ~ElfRawSectionBuilder() {}
    128     std::vector<uint8_t>* GetBuffer() { return &buf_; }
    129     void SetBuffer(std::vector<uint8_t> buf) { buf_ = buf; }
    130 
    131    protected:
    132     std::vector<uint8_t> buf_;
    133 
    134    private:
    135     friend class ElfBuilder;
    136   };
    137 
    138   class ElfOatSectionBuilder : public ElfSectionBuilder {
    139    public:
    140     ElfOatSectionBuilder(const std::string& sec_name, Elf32_Word size, Elf32_Word offset,
    141                          Elf32_Word type, Elf32_Word flags)
    142         : ElfSectionBuilder(sec_name, type, flags, NULL, 0, kPageSize, 0),
    143           offset_(offset), size_(size) {}
    144     ~ElfOatSectionBuilder() {}
    145 
    146    protected:
    147     // Offset of the content within the file.
    148     Elf32_Word offset_;
    149     // Size of the content within the file.
    150     Elf32_Word size_;
    151 
    152    private:
    153     friend class ElfBuilder;
    154   };
    155 
    156   class ElfSymtabBuilder : public ElfSectionBuilder {
    157    public:
    158     // Add a symbol with given name to this symtab. The symbol refers to
    159     // 'relative_addr' within the given section and has the given attributes.
    160     void AddSymbol(const std::string& name,
    161                    const ElfSectionBuilder* section,
    162                    Elf32_Addr addr,
    163                    bool is_relative,
    164                    Elf32_Word size,
    165                    uint8_t binding,
    166                    uint8_t type,
    167                    uint8_t other = 0);
    168 
    169     ElfSymtabBuilder(const std::string& sec_name, Elf32_Word type,
    170                      const std::string& str_name, Elf32_Word str_type, bool alloc)
    171         : ElfSectionBuilder(sec_name, type, ((alloc) ? SHF_ALLOC : 0U), &strtab_, 0,
    172                             sizeof(Elf32_Word), sizeof(Elf32_Sym)),
    173           str_name_(str_name), str_type_(str_type),
    174           strtab_(str_name, str_type, ((alloc) ? SHF_ALLOC : 0U), NULL, 0, 1, 1) {}
    175     ~ElfSymtabBuilder() {}
    176 
    177    protected:
    178     std::vector<Elf32_Word> GenerateHashContents();
    179     std::string GenerateStrtab();
    180     std::vector<Elf32_Sym> GenerateSymtab();
    181 
    182     Elf32_Word GetSize() {
    183       // 1 is for the implicit NULL symbol.
    184       return symbols_.size() + 1;
    185     }
    186 
    187     struct ElfSymbolState {
    188       const std::string name_;
    189       const ElfSectionBuilder* section_;
    190       Elf32_Addr addr_;
    191       Elf32_Word size_;
    192       bool is_relative_;
    193       uint8_t info_;
    194       uint8_t other_;
    195       // Used during Write() to temporarially hold name index in the strtab.
    196       Elf32_Word name_idx_;
    197     };
    198 
    199     // Information for the strsym for dynstr sections.
    200     const std::string str_name_;
    201     Elf32_Word str_type_;
    202     // The symbols in the same order they will be in the symbol table.
    203     std::vector<ElfSymbolState> symbols_;
    204     ElfSectionBuilder strtab_;
    205 
    206    private:
    207     friend class ElfBuilder;
    208   };
    209 
    210   class ElfBuilder FINAL {
    211    public:
    212     ElfBuilder(OatWriter* oat_writer,
    213                File* elf_file,
    214                InstructionSet isa,
    215                Elf32_Word rodata_relative_offset,
    216                Elf32_Word rodata_size,
    217                Elf32_Word text_relative_offset,
    218                Elf32_Word text_size,
    219                const bool add_symbols,
    220                bool debug = false)
    221         : oat_writer_(oat_writer),
    222           elf_file_(elf_file),
    223           add_symbols_(add_symbols),
    224           debug_logging_(debug),
    225           text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS,
    226                         SHF_ALLOC | SHF_EXECINSTR),
    227           rodata_builder_(".rodata", rodata_size, rodata_relative_offset,
    228                           SHT_PROGBITS, SHF_ALLOC),
    229           dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true),
    230           symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false),
    231           hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0,
    232                         sizeof(Elf32_Word), sizeof(Elf32_Word)),
    233           dynamic_builder_(".dynamic", &dynsym_builder_),
    234           shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) {
    235       SetupEhdr();
    236       SetupDynamic();
    237       SetupRequiredSymbols();
    238       SetISA(isa);
    239     }
    240     ~ElfBuilder() {}
    241 
    242     bool Write();
    243 
    244     // Adds the given raw section to the builder. This will copy it. The caller
    245     // is responsible for deallocating their copy.
    246     void RegisterRawSection(ElfRawSectionBuilder bld) {
    247       other_builders_.push_back(bld);
    248     }
    249 
    250    private:
    251     OatWriter* oat_writer_;
    252     File* elf_file_;
    253     const bool add_symbols_;
    254     const bool debug_logging_;
    255 
    256     bool fatal_error_ = false;
    257 
    258     Elf32_Ehdr elf_header_;
    259 
    260    public:
    261     ElfOatSectionBuilder text_builder_;
    262     ElfOatSectionBuilder rodata_builder_;
    263     ElfSymtabBuilder dynsym_builder_;
    264     ElfSymtabBuilder symtab_builder_;
    265     ElfSectionBuilder hash_builder_;
    266     ElfDynamicBuilder dynamic_builder_;
    267     ElfSectionBuilder shstrtab_builder_;
    268     std::vector<ElfRawSectionBuilder> other_builders_;
    269 
    270    private:
    271     void SetISA(InstructionSet isa);
    272     void SetupEhdr();
    273 
    274     // Sets up a bunch of the required Dynamic Section entries.
    275     // Namely it will initialize all the mandatory ones that it can.
    276     // Specifically:
    277     // DT_HASH
    278     // DT_STRTAB
    279     // DT_SYMTAB
    280     // DT_SYMENT
    281     //
    282     // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later.
    283     void SetupDynamic();
    284 
    285     // Sets up the basic dynamic symbols that are needed, namely all those we
    286     // can know already.
    287     //
    288     // Specifically adds:
    289     // oatdata
    290     // oatexec
    291     // oatlastword
    292     void SetupRequiredSymbols();
    293     void AssignSectionStr(ElfSectionBuilder *builder, std::string* strtab);
    294 
    295     bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.GetSize() > 1; }
    296   };
    297 
    298   /*
    299    * @brief Generate the DWARF debug_info and debug_abbrev sections
    300    * @param oat_writer The Oat file Writer.
    301    * @param dbg_info Compilation unit information.
    302    * @param dbg_abbrev Abbreviations used to generate dbg_info.
    303    * @param dbg_str Debug strings.
    304    */
    305   void FillInCFIInformation(OatWriter* oat_writer, std::vector<uint8_t>* dbg_info,
    306                             std::vector<uint8_t>* dbg_abbrev, std::vector<uint8_t>* dbg_str);
    307 
    308   DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
    309 };
    310 
    311 }  // namespace art
    312 
    313 #endif  // ART_COMPILER_ELF_WRITER_QUICK_H_
    314