//===-- AddressRange.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Stream.h"
#include "lldb/lldb-defines.h"

#include "llvm/Support/Compiler.h"

#include <memory>

#include <cinttypes>

namespace lldb_private {
class SectionList;
}

using namespace lldb;
using namespace lldb_private;

AddressRange::AddressRange() : m_base_addr() {}

AddressRange::AddressRange(addr_t file_addr, addr_t byte_size,
                           const SectionList *section_list)
    : m_base_addr(file_addr, section_list), m_byte_size(byte_size) {}

AddressRange::AddressRange(const lldb::SectionSP &section, addr_t offset,
                           addr_t byte_size)
    : m_base_addr(section, offset), m_byte_size(byte_size) {}

AddressRange::AddressRange(const Address &so_addr, addr_t byte_size)
    : m_base_addr(so_addr), m_byte_size(byte_size) {}

AddressRange::~AddressRange() = default;

bool AddressRange::Contains(const Address &addr) const {
  SectionSP range_sect_sp = GetBaseAddress().GetSection();
  SectionSP addr_sect_sp = addr.GetSection();
  if (range_sect_sp) {
    if (!addr_sect_sp ||
        range_sect_sp->GetModule() != addr_sect_sp->GetModule())
      return false; // Modules do not match.
  } else if (addr_sect_sp) {
    return false; // Range has no module but "addr" does because addr has a
                  // section
  }
  // Either the modules match, or both have no module, so it is ok to compare
  // the file addresses in this case only.
  return ContainsFileAddress(addr);
}

bool AddressRange::ContainsFileAddress(const Address &addr) const {
  if (addr.GetSection() == m_base_addr.GetSection())
    return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize();
  addr_t file_base_addr = GetBaseAddress().GetFileAddress();
  if (file_base_addr == LLDB_INVALID_ADDRESS)
    return false;

  addr_t file_addr = addr.GetFileAddress();
  if (file_addr == LLDB_INVALID_ADDRESS)
    return false;

  if (file_base_addr <= file_addr)
    return (file_addr - file_base_addr) < GetByteSize();

  return false;
}

bool AddressRange::ContainsFileAddress(addr_t file_addr) const {
  if (file_addr == LLDB_INVALID_ADDRESS)
    return false;

  addr_t file_base_addr = GetBaseAddress().GetFileAddress();
  if (file_base_addr == LLDB_INVALID_ADDRESS)
    return false;

  if (file_base_addr <= file_addr)
    return (file_addr - file_base_addr) < GetByteSize();

  return false;
}

bool AddressRange::ContainsLoadAddress(const Address &addr,
                                       Target *target) const {
  if (addr.GetSection() == m_base_addr.GetSection())
    return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize();
  addr_t load_base_addr = GetBaseAddress().GetLoadAddress(target);
  if (load_base_addr == LLDB_INVALID_ADDRESS)
    return false;

  addr_t load_addr = addr.GetLoadAddress(target);
  if (load_addr == LLDB_INVALID_ADDRESS)
    return false;

  if (load_base_addr <= load_addr)
    return (load_addr - load_base_addr) < GetByteSize();

  return false;
}

bool AddressRange::ContainsLoadAddress(addr_t load_addr, Target *target) const {
  if (load_addr == LLDB_INVALID_ADDRESS)
    return false;

  addr_t load_base_addr = GetBaseAddress().GetLoadAddress(target);
  if (load_base_addr == LLDB_INVALID_ADDRESS)
    return false;

  if (load_base_addr <= load_addr)
    return (load_addr - load_base_addr) < GetByteSize();

  return false;
}

bool AddressRange::Extend(const AddressRange &rhs_range) {
  addr_t lhs_end_addr = GetBaseAddress().GetFileAddress() + GetByteSize();
  addr_t rhs_base_addr = rhs_range.GetBaseAddress().GetFileAddress();

  if (!ContainsFileAddress(rhs_range.GetBaseAddress()) &&
      lhs_end_addr != rhs_base_addr)
    // The ranges don't intersect at all on the right side of this range.
    return false;

  addr_t rhs_end_addr = rhs_base_addr + rhs_range.GetByteSize();
  if (lhs_end_addr >= rhs_end_addr)
    // The rhs range totally overlaps this one, nothing to add.
    return false;

  m_byte_size += rhs_end_addr - lhs_end_addr;
  return true;
}

void AddressRange::Clear() {
  m_base_addr.Clear();
  m_byte_size = 0;
}

bool AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style,
                        Address::DumpStyle fallback_style) const {
  addr_t vmaddr = LLDB_INVALID_ADDRESS;
  int addr_size = sizeof(addr_t);
  if (target)
    addr_size = target->GetArchitecture().GetAddressByteSize();

  bool show_module = false;
  switch (style) {
  default:
    break;
  case Address::DumpStyleSectionNameOffset:
  case Address::DumpStyleSectionPointerOffset:
    s->PutChar('[');
    m_base_addr.Dump(s, target, style, fallback_style);
    s->PutChar('-');
    DumpAddress(s->AsRawOstream(), m_base_addr.GetOffset() + GetByteSize(),
                addr_size);
    s->PutChar(')');
    return true;
    break;

  case Address::DumpStyleModuleWithFileAddress:
    show_module = true;
    LLVM_FALLTHROUGH;
  case Address::DumpStyleFileAddress:
    vmaddr = m_base_addr.GetFileAddress();
    break;

  case Address::DumpStyleLoadAddress:
    vmaddr = m_base_addr.GetLoadAddress(target);
    break;
  }

  if (vmaddr != LLDB_INVALID_ADDRESS) {
    if (show_module) {
      ModuleSP module_sp(GetBaseAddress().GetModule());
      if (module_sp)
        s->Printf("%s", module_sp->GetFileSpec().GetFilename().AsCString(
                            "<Unknown>"));
    }
    DumpAddressRange(s->AsRawOstream(), vmaddr, vmaddr + GetByteSize(),
                     addr_size);
    return true;
  } else if (fallback_style != Address::DumpStyleInvalid) {
    return Dump(s, target, fallback_style, Address::DumpStyleInvalid);
  }

  return false;
}

void AddressRange::DumpDebug(Stream *s) const {
  s->Printf("%p: AddressRange section = %p, offset = 0x%16.16" PRIx64
            ", byte_size = 0x%16.16" PRIx64 "\n",
            static_cast<const void *>(this),
            static_cast<void *>(m_base_addr.GetSection().get()),
            m_base_addr.GetOffset(), GetByteSize());
}
