// Copyright 2023 Google LLC
//
// 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
//
//     https://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 MPACT_SIM_UTIL_PROGRAM_LOADER_ELF_PROGRAM_LOADER_H_
#define MPACT_SIM_UTIL_PROGRAM_LOADER_ELF_PROGRAM_LOADER_H_

#include <cstdint>
#include <map>
#include <string>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/functional/any_invocable.h"
#include "absl/status/statusor.h"
#include "elfio/elfio.hpp"
#include "elfio/elfio_segment.hpp"
#include "elfio/elfio_symbols.hpp"
#include "mpact/sim/generic/core_debug_interface.h"
#include "mpact/sim/util/memory/memory_interface.h"
#include "mpact/sim/util/program_loader/program_loader_interface.h"

namespace mpact {
namespace sim {
namespace util {

struct AddressRange {
  explicit AddressRange(uint64_t start) : start(start), end(start + 1) {}
  AddressRange(uint64_t start, uint64_t size)
      : start(start), end(start + size) {}

  uint64_t start;
  uint64_t end;
};

struct AddressRangeComp {
  bool operator()(const AddressRange& lhs, const AddressRange& rhs) const {
    if (lhs.end <= rhs.start) {
      return true;
    }
    return false;
  }
};

// This struct is used to describe a memory to be used by the elf program loader
// when there is more than one or two memories that have to be loaded.
struct MemoryDescriptor {
  // Pointer to the memory interface.
  util::MemoryInterface* memory;
  // Predicate function that takes a segment and return true if it should be
  // loaded into this memory.
  absl::AnyInvocable<bool(const ELFIO::segment&) const> predicate_fcn;
  // Function that takes a segment load address and returns the address it
  // should be loaded at in the memory. If not specified, the load address is
  // used unmodified.
  absl::AnyInvocable<uint64_t(uint64_t) const> address_fcn;
};

// This class wraps the elfio class to provide an easy interface to load the
// segments of an elf executable file into memory. If both code and data
// memories are given, then executable segments are loaded into code memory and
// all other segments into data memory.
//
// TODO(): Allow for a multiple memories to be passed in to allow
// segments to be loaded into different memories, not just one big contiguous
// memory.
class ElfProgramLoader : public ProgramLoaderInterface {
 public:
  ElfProgramLoader(util::MemoryInterface* code_memory,
                   util::MemoryInterface* data_memory);
  ElfProgramLoader(std::vector<MemoryDescriptor> memories);
  explicit ElfProgramLoader(util::MemoryInterface* memory);
  explicit ElfProgramLoader(generic::CoreDebugInterface* dbg_if);
  ElfProgramLoader() = delete;
  ~ElfProgramLoader() override;

  absl::StatusOr<uint64_t> LoadSymbols(const std::string& file_name) override;
  absl::StatusOr<uint64_t> LoadProgram(const std::string& file_name) override;
  // Return the value and size of the symbol 'name' if it exists in the symbol
  // table.
  absl::StatusOr<std::pair<uint64_t, uint64_t>> GetSymbol(
      const std::string& name) const;
  // If there is a function with symbol table value 'address' return its name.
  absl::StatusOr<std::string> GetFcnSymbolName(uint64_t address) const;
  // Looks up to see if the address is in the range of a function symbol, and
  // if so, returns the functions name.
  absl::StatusOr<std::string> GetFunctionName(uint64_t address) const;
  // If the GNU stack size program header exists, return the memory size.
  absl::StatusOr<uint64_t> GetStackSize() const;
  const ELFIO::elfio* elf_reader() const { return &elf_reader_; }

 private:
  int GetSegmentIndex(int section_index) const;
  const std::vector<MemoryDescriptor> memories_;
  bool loaded_ = false;
  ELFIO::elfio elf_reader_;
  util::MemoryInterface* code_memory_ = nullptr;
  util::MemoryInterface* data_memory_ = nullptr;
  generic::CoreDebugInterface* dbg_if_ = nullptr;
  std::vector<const ELFIO::symbol_section_accessor*> symbol_accessors_;
  absl::flat_hash_map<uint64_t, std::string> fcn_symbol_map_;
  std::map<AddressRange, std::string, AddressRangeComp> function_range_map_;
  uint64_t has_stack_size_ = false;
  uint64_t stack_size_ = 0;
};

}  // namespace util
}  // namespace sim
}  // namespace mpact

#endif  // MPACT_SIM_UTIL_PROGRAM_LOADER_ELF_PROGRAM_LOADER_H_
