// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_ELF_H_
#define RUNTIME_VM_ELF_H_

#include "vm/allocation.h"
#include "vm/compiler/runtime_api.h"
#include "vm/datastream.h"
#include "vm/growable_array.h"
#include "vm/zone.h"

namespace dart {

#if defined(DART_PRECOMPILER)

class Dwarf;
class ElfWriteStream;
class Section;
class Segment;
class StringTable;
class SymbolTable;

class Elf : public ZoneAllocated {
 public:
  enum class Type {
    // A snapshot that should include segment contents.
    Snapshot,
    // Separately compiled debugging information that should not include
    // most segment contents.
    DebugInfo,
  };

  Elf(Zone* zone, BaseWriteStream* stream, Type type, Dwarf* dwarf = nullptr);

  static constexpr intptr_t kPageSize = 16 * KB;
  static constexpr uword kNoSectionStart = 0;

  bool IsStripped() const { return dwarf_ == nullptr; }

  Zone* zone() const { return zone_; }
  const Dwarf* dwarf() const { return dwarf_; }
  Dwarf* dwarf() { return dwarf_; }
  const SymbolTable* symtab() const { return symtab_; }

  // Stores the information needed to appropriately generate a
  // relocation from the target to the source at the given section offset.
  // If a given symbol is nullptr, then the offset is absolute (from 0).
  struct Relocation {
    size_t size_in_bytes;
    intptr_t section_offset;
    const char* source_symbol;
    intptr_t source_offset;
    const char* target_symbol;
    intptr_t target_offset;
  };

  // Stores the information needed to appropriately generate a symbol
  // during finalization.
  struct SymbolData {
    const char* name;
    intptr_t type;
    intptr_t offset;
    size_t size;
  };

  void AddText(const char* name,
               const uint8_t* bytes,
               intptr_t size,
               const ZoneGrowableArray<Relocation>* relocations,
               const ZoneGrowableArray<SymbolData>* symbol);
  void AddROData(const char* name,
                 const uint8_t* bytes,
                 intptr_t size,
                 const ZoneGrowableArray<Relocation>* relocations,
                 const ZoneGrowableArray<SymbolData>* symbols);

  void Finalize();

 private:
  static constexpr const char* kBuildIdNoteName = ".note.gnu.build-id";

  // Adds the section and also creates a PT_LOAD segment for the section if it
  // is an allocated section.
  //
  // For allocated sections, if a symbol_name is provided, a symbol for the
  // section will be added to the dynamic table (if allocated) and static
  // table (if not stripped) during finalization.
  void AddSection(Section* section,
                  const char* name,
                  const char* symbol_name = nullptr);

  const Section* FindSectionBySymbolName(const char* symbol_name) const;

  void CreateBSS();
  void GenerateBuildId();

  void OrderSectionsAndCreateSegments();

  void FinalizeSymbols();
  void FinalizeDwarfSections();
  void FinalizeProgramTable();
  void ComputeOffsets();

  void FinalizeEhFrame();

  void WriteHeader(ElfWriteStream* stream);
  void WriteSectionTable(ElfWriteStream* stream);
  void WriteProgramTable(ElfWriteStream* stream);
  void WriteSections(ElfWriteStream* stream);

  Zone* const zone_;
  BaseWriteStream* const unwrapped_stream_;
  const Type type_;

  // If nullptr, then the ELF file should be stripped of static information like
  // the static symbol table (and its corresponding string table).
  Dwarf* const dwarf_;

  // All our strings would fit in a single page. However, we use separate
  // .shstrtab and .dynstr to work around a bug in Android's strip utility.
  StringTable* const shstrtab_;
  StringTable* const dynstrtab_;
  SymbolTable* const dynsym_;

  // The static tables are always created for use in relocation calculations,
  // even though they may not end up in the final ELF file.
  StringTable* const strtab_;
  SymbolTable* const symtab_;

  // We always create a BSS section for all Elf files to keep memory offsets
  // consistent, though it is NOBITS for separate debugging information.
  Section* bss_ = nullptr;

  // We currently create a GNU build ID for all ELF snapshots and associated
  // debugging information.
  Section* build_id_ = nullptr;

  GrowableArray<Section*> sections_;
  GrowableArray<Segment*> segments_;

  intptr_t memory_offset_;
  intptr_t section_table_file_offset_ = -1;
  intptr_t section_table_file_size_ = -1;
  intptr_t program_table_file_offset_ = -1;
  intptr_t program_table_file_size_ = -1;
};

#endif  // DART_PRECOMPILER

}  // namespace dart

#endif  // RUNTIME_VM_ELF_H_
