//===-- SectionLoadHistory.cpp ----------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/SectionLoadHistory.h"

#include "lldb/Target/SectionLoadList.h"
#include "lldb/Utility/Stream.h"

using namespace lldb;
using namespace lldb_private;

bool SectionLoadHistory::IsEmpty() const {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  return m_stop_id_to_section_load_list.empty();
}

void SectionLoadHistory::Clear() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  m_stop_id_to_section_load_list.clear();
}

uint32_t SectionLoadHistory::GetLastStopID() const {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  if (m_stop_id_to_section_load_list.empty())
    return 0;
  else
    return m_stop_id_to_section_load_list.rbegin()->first;
}

SectionLoadList *
SectionLoadHistory::GetSectionLoadListForStopID(uint32_t stop_id,
                                                bool read_only) {
  if (!m_stop_id_to_section_load_list.empty()) {
    if (read_only) {
      // The section load list is for reading data only so we don't need to
      // create a new SectionLoadList for the current stop ID, just return the
      // section load list for the stop ID that is equal to or less than the
      // current stop ID
      if (stop_id == eStopIDNow) {
        // If we are asking for the latest and greatest value, it is always at
        // the end of our list because that will be the highest stop ID.
        StopIDToSectionLoadList::reverse_iterator rpos =
            m_stop_id_to_section_load_list.rbegin();
        return rpos->second.get();
      } else {
        StopIDToSectionLoadList::iterator pos =
            m_stop_id_to_section_load_list.lower_bound(stop_id);
        if (pos != m_stop_id_to_section_load_list.end() &&
            pos->first == stop_id)
          return pos->second.get();
        else if (pos != m_stop_id_to_section_load_list.begin()) {
          --pos;
          return pos->second.get();
        }
      }
    } else {
      // You can only use "eStopIDNow" when reading from the section load
      // history
      assert(stop_id != eStopIDNow);

      // We are updating the section load list (not read only), so if the stop
      // ID passed in isn't the same as the last stop ID in our collection,
      // then create a new node using the current stop ID
      StopIDToSectionLoadList::iterator pos =
          m_stop_id_to_section_load_list.lower_bound(stop_id);
      if (pos != m_stop_id_to_section_load_list.end() &&
          pos->first == stop_id) {
        // We already have an entry for this value
        return pos->second.get();
      }

      // We must make a new section load list that is based on the last valid
      // section load list, so here we copy the last section load list and add
      // a new node for the current stop ID.
      StopIDToSectionLoadList::reverse_iterator rpos =
          m_stop_id_to_section_load_list.rbegin();
      SectionLoadListSP section_load_list_sp(
          new SectionLoadList(*rpos->second.get()));
      m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
      return section_load_list_sp.get();
    }
  }
  SectionLoadListSP section_load_list_sp(new SectionLoadList());
  if (stop_id == eStopIDNow)
    stop_id = 0;
  m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
  return section_load_list_sp.get();
}

SectionLoadList &SectionLoadHistory::GetCurrentSectionLoadList() {
  const bool read_only = true;
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  SectionLoadList *section_load_list =
      GetSectionLoadListForStopID(eStopIDNow, read_only);
  assert(section_load_list != NULL);
  return *section_load_list;
}

addr_t
SectionLoadHistory::GetSectionLoadAddress(uint32_t stop_id,
                                          const lldb::SectionSP &section_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  const bool read_only = true;
  SectionLoadList *section_load_list =
      GetSectionLoadListForStopID(stop_id, read_only);
  return section_load_list->GetSectionLoadAddress(section_sp);
}

bool SectionLoadHistory::ResolveLoadAddress(uint32_t stop_id, addr_t load_addr,
                                            Address &so_addr) {
  // First find the top level section that this load address exists in
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  const bool read_only = true;
  SectionLoadList *section_load_list =
      GetSectionLoadListForStopID(stop_id, read_only);
  return section_load_list->ResolveLoadAddress(load_addr, so_addr);
}

bool SectionLoadHistory::SetSectionLoadAddress(
    uint32_t stop_id, const lldb::SectionSP &section_sp, addr_t load_addr,
    bool warn_multiple) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  const bool read_only = false;
  SectionLoadList *section_load_list =
      GetSectionLoadListForStopID(stop_id, read_only);
  return section_load_list->SetSectionLoadAddress(section_sp, load_addr,
                                                  warn_multiple);
}

size_t
SectionLoadHistory::SetSectionUnloaded(uint32_t stop_id,
                                       const lldb::SectionSP &section_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  const bool read_only = false;
  SectionLoadList *section_load_list =
      GetSectionLoadListForStopID(stop_id, read_only);
  return section_load_list->SetSectionUnloaded(section_sp);
}

bool SectionLoadHistory::SetSectionUnloaded(uint32_t stop_id,
                                            const lldb::SectionSP &section_sp,
                                            addr_t load_addr) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  const bool read_only = false;
  SectionLoadList *section_load_list =
      GetSectionLoadListForStopID(stop_id, read_only);
  return section_load_list->SetSectionUnloaded(section_sp, load_addr);
}

void SectionLoadHistory::Dump(Stream &s, Target *target) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  StopIDToSectionLoadList::iterator pos,
      end = m_stop_id_to_section_load_list.end();
  for (pos = m_stop_id_to_section_load_list.begin(); pos != end; ++pos) {
    s.Printf("StopID = %u:\n", pos->first);
    pos->second->Dump(s, target);
    s.EOL();
  }
}
