// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SRC_LIB_ELFLDLTL_INCLUDE_LIB_ELFLDLTL_DYNAMIC_H_
#define SRC_LIB_ELFLDLTL_INCLUDE_LIB_ELFLDLTL_DYNAMIC_H_

#include <lib/stdcompat/span.h>
#include <zircon/compiler.h>

#include <optional>
#include <string_view>
#include <type_traits>
#include <utility>

#include "init-fini.h"
#include "internal/dynamic-tag-error.h"
#include "layout.h"
#include "relocation.h"
#include "symbol.h"

namespace elfldltl {

using namespace std::literals::string_view_literals;

// elfldltl::DecodeDynamic does a single-pass decoding of the PT_DYNAMIC data
// by statically combining multiple "observer" objects.  Various observers are
// defined to collect different subsets of the dynamic linking metadata needed
// for different purposes.

// This represents a PT_DYNAMIC entry that's been matched to a specific tag.
// These types are used in the arguments to Observe callbacks; see below.
template <ElfDynTag Tag>
struct DynamicTagMatch {};

// This is the base class for Dynamic*Observer classes.
// Each Observer subclass should define these two methods:
//  * template <class DiagnosticsType, class Memory>
//    bool Observe(DiagnosticsType& diagnostics, Memory& memory,
//                 DynamicTagMatch<Tag> tag, Addr val);
//  * template <class DiagnosticsType, class Memory>
//    bool Finish(DiagnosticsType& diagnostics, Memory& memory);
// Observe will be called with each entry matching any Tag of the Tags... list.
// Then Finish will be called at the end of all entries unless processing was
// terminated early for some reason, in which case the observer object is
// usually going to be destroyed without checking its results.  Both return
// false if processing the dynamic section should be terminated early.

template <class Observer, ElfDynTag... Tags>
struct DynamicTagObserver {};

// This decodes a dynamic section by matching each entry against a list of
// observers.  Each observer should be of a subclass of DynamicTagObserver that
// indicates the tags it matches.  If any matching observer returns false then
// this stops processing early and returns false.  Otherwise, each observer's
// Finish method is called, stopping early if one returns false.
template <class DiagnosticsType, class Memory, class Dyn, size_t N, class... Observers>
constexpr bool DecodeDynamic(DiagnosticsType&& diagnostics, Memory&& memory,
                             cpp20::span<const Dyn, N> dyn, Observers&&... observers) {
  // The span is an upper bound but the section is terminated by a null entry.
  for (const auto& entry : dyn) {
    // At the terminator entry, call each observer's Finish() method.
    if (entry.tag == ElfDynTag::kNull) {
      return (observers.Finish(diagnostics, memory) && ...);
    }

    // Present each entry to each matching observer (see below).
    if ((!DecodeDynamic(diagnostics, memory, entry, observers) || ...)) {
      return false;
    }
  }

  // This should never be reached.
  return diagnostics.FormatError("missing DT_NULL terminator in PT_DYNAMIC"sv);
}

// Match a single dynamic section entry against a single observer.  If the
// observer matches, its Observe overload for the matching tag is called.
// Returns the value of that call, or true if this observer didn't match.
template <class DiagnosticsType, class Memory, class Dyn, class Observer, ElfDynTag... Tags>
constexpr bool DecodeDynamic(DiagnosticsType&& diagnostics, Memory&& memory, const Dyn& entry,
                             DynamicTagObserver<Observer, Tags...>& observer) {
  bool ok = true;
  auto call_observer = [&](auto dt) {
    ok = static_cast<Observer&>(observer).Observe(diagnostics, memory, dt, entry.val);
    return true;
  };

  ((entry.tag == Tags && call_observer(DynamicTagMatch<Tags>{})) || ...);

  return ok;
}

// This is a very simple observer that rejects DT_TEXTREL and DF_TEXTREL.
class DynamicTextrelRejectObserver
    : public DynamicTagObserver<DynamicTextrelRejectObserver, ElfDynTag::kTextRel,
                                ElfDynTag::kFlags> {
 public:
  static constexpr std::string_view kMessage = "DT_TEXTREL and DF_TEXTREL not supported";

  template <class DiagnosticsType, class Memory, typename ValueType>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kTextRel> tag, ValueType val) {
    // If this is called at all, that's an error.
    return diagnostics.FormatError(kMessage);
  }

  template <class DiagnosticsType, class Memory, typename ValueType>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kFlags> tag, ValueType val) {
    if (val & ElfDynFlags::kTextRel) {
      return diagnostics.FormatError(kMessage);
    }
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Finish(DiagnosticsType& diagnostics, Memory& memory) {
    // There is no state kept aside from in the diagnostics object, so nothing
    // to do.
    return true;
  }
};

// This is a base class for Dynamic*Observer classes in the common pattern
// where an Info object will be filled in with data observed in dynamic
// entries.  A subclass can do `using Base::Base;` to get the constructor that
// takes an Info reference, and has the info() accessor for it.  Then it must
// define its own `Observe` and `Finish` methods.

template <class Observer, class Info, class Elf, ElfDynTag... Tags>
class DynamicInfoObserver : public DynamicTagObserver<Observer, Tags...> {
 public:
  DynamicInfoObserver() = delete;
  constexpr DynamicInfoObserver(const DynamicInfoObserver&) = default;

  constexpr explicit DynamicInfoObserver(Info& info) : info_(info) {}

  constexpr Info& info() { return info_; }
  constexpr const Info& info() const { return info_; }

 protected:
  // This is a utility class for the common pattern of a pair of dynamic tags
  // for a table address and its size in bytes.  The SizedArray object's
  // set_address and set_size_bytes methods should be called from Observe
  // methods for the respective dynamic tags.  Then a Finish method calls
  // SizedArray::Finish<T, Setter, Tag1, Tag2> using explicit template
  // arguments giving the type of table elements, &Info::set_foo for the setter
  // in info() that takes a span<T>, and the two tags, passing it the
  // diagnostics, memory and info objects by reference.  This calls the setter
  // only if both tags were present and the table was successfully fetched from
  // memory.  It diagnoses all the partial and invalid cases in detail with
  // calls to diagnostics.FormatError, and does nothing at all if neither tag
  // is present.
  //
  // The optional third tag is for a related count that also may be present.
  // If this tag is supplied, the setter takes a second argument.  If the
  // CountTag was not present at runtime, that second argument will be zero.
  //
  // The SizedArray object is contextually convertible to bool to test whether
  // either tag was present at all.
  class SizedArray {
   public:
    template <typename T, auto Setter, ElfDynTag AddressTag, ElfDynTag SizeBytesTag,
              ElfDynTag CountTag = ElfDynTag::kNull, class DiagnosticsType, class Memory>
    constexpr bool Finish(DiagnosticsType&& diagnostics, Memory&& memory, Info& info,
                          typename Elf::size_type count = 0) {
      if (!address_ && !size_bytes_) {
        // No corresponding entries were found.
        return true;
      }
      // Check invariants.
      using Error = internal::DynamicTagError<AddressTag, SizeBytesTag, CountTag>;
      if (!address_) [[unlikely]] {
        return diagnostics.FormatError(Error::kMissingAddress);
      }
      if (!size_bytes_) [[unlikely]] {
        return diagnostics.FormatError(Error::kMissingSize);
      }
      if (*address_ % alignof(T) != 0) [[unlikely]] {
        // Don't store the bad address so that no misaligned fetches will be
        // attempted later if we keep going to look for more errors.
        *address_ = 0;
        return diagnostics.FormatError(Error::kMisalignedAddress);
      }
      if (*size_bytes_ % sizeof(T) != 0) [[unlikely]] {
        return diagnostics.FormatError(Error::kMisalignedSize);
      }
      // Fetch the table.
      if (auto table = memory.template ReadArray<T>(*address_, *size_bytes_ / sizeof(T))) {
        if constexpr (CountTag != ElfDynTag::kNull) {
          if (count > table->size()) [[unlikely]] {
            return diagnostics.FormatError(Error::kInvalidCount);
          }
          (info.*Setter)(*table, count);
        } else {
          (info.*Setter)(*table);
        }
        return true;
      }
      return diagnostics.FormatError(Error::kRead);
    }

    constexpr explicit operator bool() const { return address_ || size_bytes_; }

    constexpr void set_address(typename Elf::size_type val) { address_ = val; }

    constexpr void set_size_bytes(typename Elf::size_type val) { size_bytes_ = val; }

   private:
    std::optional<typename Elf::size_type> address_, size_bytes_;
  };

 private:
  Info& info_;
};

// This is an observer to fill in an elfldltl::RelocationInfo<Elf> object.
// Its constructor takes (elfldltl::RelocationInfo<Elf>&, Memory&).
template <class Elf>
class DynamicRelocationInfoObserver;

// This is just a shorthand to avoid repeating the long list of parameters.
template <class Elf>
using DynamicRelocationInfoObserverBase =
    DynamicInfoObserver<DynamicRelocationInfoObserver<Elf>, RelocationInfo<Elf>, Elf,
                        ElfDynTag::kJmpRel, ElfDynTag::kPltRel, ElfDynTag::kPltRelSz,
                        ElfDynTag::kRelr, ElfDynTag::kRelrSz, ElfDynTag::kRelrEnt, ElfDynTag::kRel,
                        ElfDynTag::kRelCount, ElfDynTag::kRelEnt, ElfDynTag::kRelSz,
                        ElfDynTag::kRela, ElfDynTag::kRelaCount, ElfDynTag::kRelaEnt,
                        ElfDynTag::kRelaSz>;

template <class Elf>
class DynamicRelocationInfoObserver : public DynamicRelocationInfoObserverBase<Elf> {
 public:
  using Base = DynamicRelocationInfoObserverBase<Elf>;
  using Info = RelocationInfo<Elf>;
  using size_type = typename Elf::size_type;

  using Base::Base;

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kJmpRel> tag, size_type val) {
    jmprel_.set_address(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kPltRelSz> tag, size_type val) {
    jmprel_.set_size_bytes(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kPltRel> tag, size_type val) {
    pltrel_ = val;
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRelr> tag, size_type val) {
    relr_.set_address(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRelrSz> tag, size_type val) {
    relr_.set_size_bytes(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRel> tag, size_type val) {
    rel_.set_address(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRelSz> tag, size_type val) {
    rel_.set_size_bytes(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRelCount> tag, size_type val) {
    relcount_ = val;
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRela> tag, size_type val) {
    rela_.set_address(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRelaSz> tag, size_type val) {
    rela_.set_size_bytes(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRelaCount> tag, size_type val) {
    relacount_ = val;
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRelEnt> tag, size_type val) {
    return val == sizeof(typename Elf::Rel) ||
           diagnostics.FormatError("incorrect DT_RELENT value"sv);
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRelaEnt> tag, size_type val) {
    return val == sizeof(typename Elf::Rela) ||
           diagnostics.FormatError("incorrect DT_RELAENT value"sv);
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kRelrEnt> tag, size_type val) {
    return val == sizeof(typename Elf::Addr) ||
           diagnostics.FormatError("incorrect DT_RELRENT value"sv);
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Finish(DiagnosticsType& diagnostics, Memory& memory) {
    // DT_PLTREL says which format DT_JMPREL uses: DT_REL or DT_RELA.
    if (pltrel_ == static_cast<uint32_t>(ElfDynTag::kRel)) {
      if (!jmprel_.template Finish<typename Elf::Rel, &Info::set_jmprel, ElfDynTag::kJmpRel,
                                   ElfDynTag::kPltRelSz>(diagnostics, memory, this->info())) {
        return false;
      }
    } else if (pltrel_ == static_cast<uint32_t>(ElfDynTag::kRela)) {
      if (!jmprel_.template Finish<typename Elf::Rela, &Info::set_jmprel, ElfDynTag::kJmpRel,
                                   ElfDynTag::kPltRelSz>(diagnostics, memory, this->info())) {
        return false;
      }
    } else if (jmprel_ && !diagnostics.FormatError(pltrel_ ? "missing DT_PLTREL entry"sv
                                                           : "invalid DT_PLTREL entry"sv)) {
      return false;
    }
    return relr_.template Finish<typename Elf::Addr, &Info::set_relr, ElfDynTag::kRelr,
                                 ElfDynTag::kRelrSz>(diagnostics, memory, this->info()) &&
           rel_.template Finish<typename Elf::Rel, &Info::set_rel, ElfDynTag::kRel,
                                ElfDynTag::kRelSz, ElfDynTag::kRelCount>(diagnostics, memory,
                                                                         this->info(), relcount_) &&
           rela_.template Finish<typename Elf::Rela, &Info::set_rela, ElfDynTag::kRela,
                                 ElfDynTag::kRelaSz, ElfDynTag::kRelaCount>(
               diagnostics, memory, this->info(), relacount_);
  }

 private:
  typename Base::SizedArray relr_, rel_, rela_, jmprel_;
  typename Elf::size_type relcount_ = 0, relacount_ = 0;
  std::optional<typename Elf::size_type> pltrel_;
};

// Deduction guide.
template <class Elf>
DynamicRelocationInfoObserver(RelocationInfo<Elf>& info) -> DynamicRelocationInfoObserver<Elf>;

// This is an observer to fill in an elfldltl::SymbolInfo<Elf> object.
// Its constructor takes (elfldltl::SymbolInfo<Elf>&, Memory&).
template <class Elf>
class DynamicSymbolInfoObserver;

// This is just a shorthand to avoid repeating the long list of parameters.
template <class Elf>
using DynamicSymbolInfoObserverBase =
    DynamicInfoObserver<DynamicSymbolInfoObserver<Elf>, SymbolInfo<Elf>, Elf, ElfDynTag::kSymTab,
                        ElfDynTag::kSymEnt, ElfDynTag::kHash, ElfDynTag::kGnuHash,
                        ElfDynTag::kStrTab, ElfDynTag::kStrSz, ElfDynTag::kSoname,
                        ElfDynTag::kFlags, ElfDynTag::kFlags1>;

template <class Elf>
class DynamicSymbolInfoObserver : public DynamicSymbolInfoObserverBase<Elf> {
 public:
  using Base = DynamicSymbolInfoObserverBase<Elf>;
  using Info = SymbolInfo<Elf>;
  using size_type = typename Elf::size_type;

  using Base::Base;

  // There's one Observe overload for each dynamic tag the observer handles.

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kStrTab> tag, size_type val) {
    strtab_.set_address(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kStrSz> tag, size_type val) {
    strtab_.set_size_bytes(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kSymTab> tag, size_type val) {
    if (val % sizeof(size_type)) [[unlikely]] {
      // Mark that it was present so we don't diagnose a second error.
      // But don't use a bogus value so no misaligned fetches will be tried.
      symtab_ = 0;
      return diagnostics.FormatError("DT_SYMTAB has misaligned address"sv);
    }
    symtab_ = val;
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kHash> tag, size_type val) {
    if (val % sizeof(uint32_t)) [[unlikely]] {
      return diagnostics.FormatError("DT_HASH has misaligned address"sv);
    }
    hash_ = val;
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kGnuHash> tag, size_type val) {
    if (val % sizeof(size_type)) [[unlikely]] {
      return diagnostics.FormatError("DT_GNU_HASH has misaligned address"sv);
    }
    gnu_hash_ = val;
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kSoname> tag, size_type val) {
    soname_ = val;
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kSymEnt> tag, size_type val) {
    return val == sizeof(typename Elf::Sym) ||
           diagnostics.FormatError("incorrect DT_SYMENT value "sv, val);
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kFlags> tag, size_type val) {
    this->info().set_flags(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory,
                         DynamicTagMatch<ElfDynTag::kFlags1> tag, size_type val) {
    this->info().set_flags1(val);
    return true;
  }

  // Check and finalize what's been observed.
  template <class DiagnosticsType, class Memory>
  constexpr bool Finish(DiagnosticsType& diagnostics, Memory& memory) {
    if (hash_) {
      if (auto table = memory.template ReadArray<typename Elf::Word>(*hash_)) {
        this->info().set_compat_hash(*table);
      } else {
        return false;
      }
    }
    if (gnu_hash_) {
      if (auto table = memory.template ReadArray<typename Elf::Addr>(*gnu_hash_)) {
        this->info().set_gnu_hash(*table);
      } else {
        return false;
      }
    }
    if (!symtab_) {
      return !strtab_ || diagnostics.FormatError("DT_STRTAB with no DT_SYMTAB"sv);
    }
    if (auto symtab = memory.template ReadArray<typename Elf::Sym>(*symtab_)) {
      this->info().set_symtab(*symtab);
    } else {
      return false;
    }
    if (!strtab_.template Finish<char, &Info::set_strtab_as_span, ElfDynTag::kStrTab,
                                 ElfDynTag::kStrSz>(diagnostics, memory, this->info())) {
      return false;
    }
    if (soname_) {
      this->info().set_soname(*soname_);
      if (this->info().soname().empty()) [[unlikely]] {
        return diagnostics.FormatError("DT_SONAME does not fit in DT_STRTAB"sv);
      }
    }
    return true;
  }

 private:
  typename Base::SizedArray strtab_;
  std::optional<typename Elf::size_type> symtab_, hash_, gnu_hash_, soname_;
};

// Deduction guide.
template <class Elf>
DynamicSymbolInfoObserver(SymbolInfo<Elf>& info) -> DynamicSymbolInfoObserver<Elf>;

// These observers fill the same simple result structure.
// Their constructors take (elfldltl::InitFiniInfo<Elf>&, Memory&).
template <class Elf>
class DynamicInitObserver;

template <class Elf>
class DynamicFiniObserver;

template <class Elf, ElfDynTag Array, ElfDynTag ArraySz, ElfDynTag Legacy>
class DynamicInitFiniObserver;

// This is just a shorthand to avoid repeating the long list of parameters.
template <class Elf, ElfDynTag Array, ElfDynTag ArraySz, ElfDynTag Legacy>
using DynamicInitFiniObserverBase =
    DynamicInfoObserver<DynamicInitFiniObserver<Elf, Array, ArraySz, Legacy>, InitFiniInfo<Elf>,
                        Elf, Array, ArraySz, Legacy>;

template <class Elf, ElfDynTag Array, ElfDynTag ArraySz, ElfDynTag Legacy>
class DynamicInitFiniObserver : public DynamicInitFiniObserverBase<Elf, Array, ArraySz, Legacy> {
 public:
  using Base = DynamicInitFiniObserverBase<Elf, Array, ArraySz, Legacy>;
  using Info = InitFiniInfo<Elf>;
  using size_type = typename Elf::size_type;

  using Base::Base;

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory, DynamicTagMatch<Array> tag,
                         size_type val) {
    array_.set_address(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory, DynamicTagMatch<ArraySz> tag,
                         size_type val) {
    array_.set_size_bytes(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType& diagnostics, Memory& memory, DynamicTagMatch<Legacy> tag,
                         typename Elf::Addr val) {
    this->info().set_legacy(val);
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Finish(DiagnosticsType& diagnostics, Memory& memory) {
    return array_.template Finish<typename Elf::Addr, &Info::set_array,  //
                                  Array, ArraySz>(diagnostics, memory, this->info());
  }

 private:
  typename Base::SizedArray array_;
};

template <class Elf>
using DynamicInitObserverBase =
    DynamicInitFiniObserver<Elf, ElfDynTag::kInitArray, ElfDynTag::kInitArraySz, ElfDynTag::kInit>;

template <class Elf>
using DynamicFiniObserverBase =
    DynamicInitFiniObserver<Elf, ElfDynTag::kFiniArray, ElfDynTag::kFiniArraySz, ElfDynTag::kFini>;

template <class Elf>
class DynamicInitObserver : public DynamicInitObserverBase<Elf> {
 public:
  using DynamicInitObserverBase<Elf>::DynamicInitObserverBase;
};

template <class Elf>
class DynamicFiniObserver : public DynamicFiniObserverBase<Elf> {
 public:
  using DynamicFiniObserverBase<Elf>::DynamicFiniObserverBase;
};

// Deduction guides.

template <class Elf>
DynamicInitObserver(InitFiniInfo<Elf>& info) -> DynamicInitObserver<Elf>;

template <class Elf>
DynamicFiniObserver(InitFiniInfo<Elf>& info) -> DynamicFiniObserver<Elf>;

// This can be used for invoking a callback over every DT_NEEDED tag, passed
// as a string. Getting the string value requires that the SymbolInfo object
// be already set up. In practice this means that DynamicNeededObserver
// cannot safely be passed to DecodeDynamic with DynamicSymbolInfoObserver
// because there is no expectation that DT_STRTAB will appear before DT_NEEDED.
// It's the expectation that this would be used only once, just when loading
// dependencies, which is likely only going to happen after getting
// the symbol and relocation info of the current dso, so the cost of this
// restricition isn't high.
template <class Elf, class SymbolInfo, class Callback>
class DynamicNeededObserver
    : public DynamicTagObserver<DynamicNeededObserver<Elf, SymbolInfo, Callback>,
                                ElfDynTag::kNeeded> {
  using size_type = typename Elf::size_type;

 public:
  DynamicNeededObserver(const SymbolInfo& si, Callback callback) : si(si), callback(callback) {}

  template <class DiagnosticsType, class Memory>
  constexpr bool Observe(DiagnosticsType&, Memory&, DynamicTagMatch<ElfDynTag::kNeeded>,
                         size_type val) {
    return callback(si.string(val));
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Finish(DiagnosticsType&, Memory&) {
    return true;
  }

 private:
  const SymbolInfo& si;
  __NO_UNIQUE_ADDRESS Callback callback;
};

// Deduction guides.

template <class Elf, class AbiTraits, template <class, class> class SymbolInfo, class Callback>
DynamicNeededObserver(const SymbolInfo<Elf, AbiTraits>& info,
                      Callback) -> DynamicNeededObserver<Elf, SymbolInfo<Elf, AbiTraits>, Callback>;

// This provides a trivial observer that simply counts how many occurrences of
// any of the given tags appear.
template <class Elf, ElfDynTag... Tag>
class DynamicTagCountObserver
    : public DynamicTagObserver<DynamicTagCountObserver<Elf, Tag...>, Tag...> {
 public:
  explicit DynamicTagCountObserver(size_t& count) : count_(count) {}

  template <class DiagnosticsType, class Memory, ElfDynTag Match>
  constexpr bool Observe(DiagnosticsType&, Memory&, DynamicTagMatch<Match>,
                         typename Elf::size_type val) {
    static_assert(((Match == Tag) || ...));
    ++count_;
    return true;
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Finish(DiagnosticsType&, Memory&) {
    return true;
  }

 private:
  size_t& count_;
};

// An observer that will match the given tag and add its value to the provided
// container. This observer will call the `push_back` method from the
// container.h API with `Elf::size_type` values onto the container.
template <class Elf, ElfDynTag Tag, class Container, const std::string_view& ErrorString>
class DynamicValueCollectionObserver
    : public DynamicTagObserver<DynamicValueCollectionObserver<Elf, Tag, Container, ErrorString>,
                                Tag> {
 public:
  explicit DynamicValueCollectionObserver(Container& values) : values_(values) {}

  template <class DiagnosticsType, class Memory, ElfDynTag Match>
  constexpr bool Observe(DiagnosticsType& diag, Memory&, DynamicTagMatch<Match>,
                         typename Elf::size_type val) {
    static_assert(Match == Tag);
    return values_.push_back(diag, ErrorString, val);
  }

  template <class DiagnosticsType, class Memory>
  constexpr bool Finish(DiagnosticsType&, Memory&) {
    return true;
  }

 private:
  Container& values_;
};

}  // namespace elfldltl

#endif  // SRC_LIB_ELFLDLTL_INCLUDE_LIB_ELFLDLTL_DYNAMIC_H_
