/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#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 {

class ElfWriterQuick FINAL : public ElfWriter {
 public:
  // Write an ELF file. Returns true on success, false on failure.
  static bool Create(File* file,
                     OatWriter* oat_writer,
                     const std::vector<const DexFile*>& dex_files,
                     const std::string& android_root,
                     bool is_host,
                     const CompilerDriver& driver)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

 protected:
  bool Write(OatWriter* oat_writer,
             const std::vector<const DexFile*>& dex_files,
             const std::string& android_root,
             bool is_host)
      OVERRIDE
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

 private:
  ElfWriterQuick(const CompilerDriver& driver, File* elf_file)
    : 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_Word d_un);
    void AddDynamicTag(Elf32_Sword tag, Elf32_Word 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_Word off_;
    };
    std::vector<ElfDynamicState> dynamics_;
    Elf32_Word GetSize() {
      // 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_Word strsz, Elf32_Word 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 GetSize() {
      // 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_.GetSize() > 1; }
  };

  /*
   * @brief Generate the DWARF debug_info and debug_abbrev sections
   * @param oat_writer The Oat file Writer.
   * @param dbg_info Compilation unit information.
   * @param dbg_abbrev Abbreviations used to generate dbg_info.
   * @param dbg_str Debug strings.
   */
  void FillInCFIInformation(OatWriter* oat_writer, std::vector<uint8_t>* dbg_info,
                            std::vector<uint8_t>* dbg_abbrev, std::vector<uint8_t>* dbg_str);

  DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
};

}  // namespace art

#endif  // ART_COMPILER_ELF_WRITER_QUICK_H_
