//===-- UnwindPlan.cpp ----------------------------------*- C++ -*-===//
//
// 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/Symbol/UnwindPlan.h"

#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"

using namespace lldb;
using namespace lldb_private;

bool UnwindPlan::Row::RegisterLocation::
operator==(const UnwindPlan::Row::RegisterLocation &rhs) const {
  if (m_type == rhs.m_type) {
    switch (m_type) {
    case unspecified:
    case undefined:
    case same:
      return true;

    case atCFAPlusOffset:
    case isCFAPlusOffset:
    case atAFAPlusOffset:
    case isAFAPlusOffset:
      return m_location.offset == rhs.m_location.offset;

    case inOtherRegister:
      return m_location.reg_num == rhs.m_location.reg_num;

    case atDWARFExpression:
    case isDWARFExpression:
      if (m_location.expr.length == rhs.m_location.expr.length)
        return !memcmp(m_location.expr.opcodes, rhs.m_location.expr.opcodes,
                       m_location.expr.length);
      break;
    }
  }
  return false;
}

// This function doesn't copy the dwarf expression bytes; they must remain in
// allocated memory for the lifespan of this UnwindPlan object.
void UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression(
    const uint8_t *opcodes, uint32_t len) {
  m_type = atDWARFExpression;
  m_location.expr.opcodes = opcodes;
  m_location.expr.length = len;
}

// This function doesn't copy the dwarf expression bytes; they must remain in
// allocated memory for the lifespan of this UnwindPlan object.
void UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression(
    const uint8_t *opcodes, uint32_t len) {
  m_type = isDWARFExpression;
  m_location.expr.opcodes = opcodes;
  m_location.expr.length = len;
}

static llvm::Optional<std::pair<lldb::ByteOrder, uint32_t>>
GetByteOrderAndAddrSize(Thread *thread) {
  if (!thread)
    return llvm::None;
  ProcessSP process_sp = thread->GetProcess();
  if (!process_sp)
    return llvm::None;
  ArchSpec arch = process_sp->GetTarget().GetArchitecture();
  return std::make_pair(arch.GetByteOrder(), arch.GetAddressByteSize());
}

static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *thread) {
  if (auto order_and_width = GetByteOrderAndAddrSize(thread)) {
    DataExtractor extractor(expr.data(), expr.size(), order_and_width->first,
                            order_and_width->second);
    if (!DWARFExpression::PrintDWARFExpression(s, extractor,
                                               order_and_width->second,
                                               /*dwarf_ref_size*/ 4,
                                               /*location_expression*/ false))
      s.PutCString("invalid-dwarf-expr");
  } else
    s.PutCString("dwarf-expr");
}

void UnwindPlan::Row::RegisterLocation::Dump(Stream &s,
                                             const UnwindPlan *unwind_plan,
                                             const UnwindPlan::Row *row,
                                             Thread *thread,
                                             bool verbose) const {
  switch (m_type) {
  case unspecified:
    if (verbose)
      s.PutCString("=<unspec>");
    else
      s.PutCString("=!");
    break;
  case undefined:
    if (verbose)
      s.PutCString("=<undef>");
    else
      s.PutCString("=?");
    break;
  case same:
    s.PutCString("= <same>");
    break;

  case atCFAPlusOffset:
  case isCFAPlusOffset: {
    s.PutChar('=');
    if (m_type == atCFAPlusOffset)
      s.PutChar('[');
    s.Printf("CFA%+d", m_location.offset);
    if (m_type == atCFAPlusOffset)
      s.PutChar(']');
  } break;

  case atAFAPlusOffset:
  case isAFAPlusOffset: {
    s.PutChar('=');
    if (m_type == atAFAPlusOffset)
      s.PutChar('[');
    s.Printf("AFA%+d", m_location.offset);
    if (m_type == atAFAPlusOffset)
      s.PutChar(']');
  } break;

  case inOtherRegister: {
    const RegisterInfo *other_reg_info = nullptr;
    if (unwind_plan)
      other_reg_info = unwind_plan->GetRegisterInfo(thread, m_location.reg_num);
    if (other_reg_info)
      s.Printf("=%s", other_reg_info->name);
    else
      s.Printf("=reg(%u)", m_location.reg_num);
  } break;

  case atDWARFExpression:
  case isDWARFExpression: {
    s.PutChar('=');
    if (m_type == atDWARFExpression)
      s.PutChar('[');
    DumpDWARFExpr(
        s, llvm::makeArrayRef(m_location.expr.opcodes, m_location.expr.length),
        thread);
    if (m_type == atDWARFExpression)
      s.PutChar(']');
  } break;
  }
}

static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan,
                             Thread *thread, uint32_t reg_num) {
  const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo(thread, reg_num);
  if (reg_info)
    s.PutCString(reg_info->name);
  else
    s.Printf("reg(%u)", reg_num);
}

bool UnwindPlan::Row::FAValue::
operator==(const UnwindPlan::Row::FAValue &rhs) const {
  if (m_type == rhs.m_type) {
    switch (m_type) {
    case unspecified:
      return true;

    case isRegisterPlusOffset:
      return m_value.reg.offset == rhs.m_value.reg.offset;

    case isRegisterDereferenced:
      return m_value.reg.reg_num == rhs.m_value.reg.reg_num;

    case isDWARFExpression:
      if (m_value.expr.length == rhs.m_value.expr.length)
        return !memcmp(m_value.expr.opcodes, rhs.m_value.expr.opcodes,
                       m_value.expr.length);
      break;
    }
  }
  return false;
}

void UnwindPlan::Row::FAValue::Dump(Stream &s, const UnwindPlan *unwind_plan,
                                     Thread *thread) const {
  switch (m_type) {
  case isRegisterPlusOffset:
    DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
    s.Printf("%+3d", m_value.reg.offset);
    break;
  case isRegisterDereferenced:
    s.PutChar('[');
    DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
    s.PutChar(']');
    break;
  case isDWARFExpression:
    DumpDWARFExpr(s,
                  llvm::makeArrayRef(m_value.expr.opcodes, m_value.expr.length),
                  thread);
    break;
  default:
    s.PutCString("unspecified");
    break;
  }
}

void UnwindPlan::Row::Clear() {
  m_cfa_value.SetUnspecified();
  m_afa_value.SetUnspecified();
  m_offset = 0;
  m_register_locations.clear();
}

void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan,
                           Thread *thread, addr_t base_addr) const {
  if (base_addr != LLDB_INVALID_ADDRESS)
    s.Printf("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
  else
    s.Printf("%4" PRId64 ": CFA=", GetOffset());

  m_cfa_value.Dump(s, unwind_plan, thread);

  if (!m_afa_value.IsUnspecified()) {
    s.Printf(" AFA=");
    m_afa_value.Dump(s, unwind_plan, thread);
  }

  s.Printf(" => ");
  for (collection::const_iterator idx = m_register_locations.begin();
       idx != m_register_locations.end(); ++idx) {
    DumpRegisterName(s, unwind_plan, thread, idx->first);
    const bool verbose = false;
    idx->second.Dump(s, unwind_plan, this, thread, verbose);
    s.PutChar(' ');
  }
  s.EOL();
}

UnwindPlan::Row::Row()
    : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations() {}

bool UnwindPlan::Row::GetRegisterInfo(
    uint32_t reg_num,
    UnwindPlan::Row::RegisterLocation &register_location) const {
  collection::const_iterator pos = m_register_locations.find(reg_num);
  if (pos != m_register_locations.end()) {
    register_location = pos->second;
    return true;
  }
  return false;
}

void UnwindPlan::Row::RemoveRegisterInfo(uint32_t reg_num) {
  collection::const_iterator pos = m_register_locations.find(reg_num);
  if (pos != m_register_locations.end()) {
    m_register_locations.erase(pos);
  }
}

void UnwindPlan::Row::SetRegisterInfo(
    uint32_t reg_num,
    const UnwindPlan::Row::RegisterLocation register_location) {
  m_register_locations[reg_num] = register_location;
}

bool UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num,
                                                           int32_t offset,
                                                           bool can_replace) {
  if (!can_replace &&
      m_register_locations.find(reg_num) != m_register_locations.end())
    return false;
  RegisterLocation reg_loc;
  reg_loc.SetAtCFAPlusOffset(offset);
  m_register_locations[reg_num] = reg_loc;
  return true;
}

bool UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num,
                                                           int32_t offset,
                                                           bool can_replace) {
  if (!can_replace &&
      m_register_locations.find(reg_num) != m_register_locations.end())
    return false;
  RegisterLocation reg_loc;
  reg_loc.SetIsCFAPlusOffset(offset);
  m_register_locations[reg_num] = reg_loc;
  return true;
}

bool UnwindPlan::Row::SetRegisterLocationToUndefined(
    uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) {
  collection::iterator pos = m_register_locations.find(reg_num);
  collection::iterator end = m_register_locations.end();

  if (pos != end) {
    if (!can_replace)
      return false;
    if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
      return false;
  }
  RegisterLocation reg_loc;
  reg_loc.SetUndefined();
  m_register_locations[reg_num] = reg_loc;
  return true;
}

bool UnwindPlan::Row::SetRegisterLocationToUnspecified(uint32_t reg_num,
                                                       bool can_replace) {
  if (!can_replace &&
      m_register_locations.find(reg_num) != m_register_locations.end())
    return false;
  RegisterLocation reg_loc;
  reg_loc.SetUnspecified();
  m_register_locations[reg_num] = reg_loc;
  return true;
}

bool UnwindPlan::Row::SetRegisterLocationToRegister(uint32_t reg_num,
                                                    uint32_t other_reg_num,
                                                    bool can_replace) {
  if (!can_replace &&
      m_register_locations.find(reg_num) != m_register_locations.end())
    return false;
  RegisterLocation reg_loc;
  reg_loc.SetInRegister(other_reg_num);
  m_register_locations[reg_num] = reg_loc;
  return true;
}

bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num,
                                                bool must_replace) {
  if (must_replace &&
      m_register_locations.find(reg_num) == m_register_locations.end())
    return false;
  RegisterLocation reg_loc;
  reg_loc.SetSame();
  m_register_locations[reg_num] = reg_loc;
  return true;
}

bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const {
  return m_offset == rhs.m_offset &&
      m_cfa_value == rhs.m_cfa_value &&
      m_afa_value == rhs.m_afa_value &&
      m_register_locations == rhs.m_register_locations;
}

void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) {
  if (m_row_list.empty() ||
      m_row_list.back()->GetOffset() != row_sp->GetOffset())
    m_row_list.push_back(row_sp);
  else
    m_row_list.back() = row_sp;
}

void UnwindPlan::InsertRow(const UnwindPlan::RowSP &row_sp,
                           bool replace_existing) {
  collection::iterator it = m_row_list.begin();
  while (it != m_row_list.end()) {
    RowSP row = *it;
    if (row->GetOffset() >= row_sp->GetOffset())
      break;
    it++;
  }
  if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset())
    m_row_list.insert(it, row_sp);
  else if (replace_existing)
    *it = row_sp;
}

UnwindPlan::RowSP UnwindPlan::GetRowForFunctionOffset(int offset) const {
  RowSP row;
  if (!m_row_list.empty()) {
    if (offset == -1)
      row = m_row_list.back();
    else {
      collection::const_iterator pos, end = m_row_list.end();
      for (pos = m_row_list.begin(); pos != end; ++pos) {
        if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
          row = *pos;
        else
          break;
      }
    }
  }
  return row;
}

bool UnwindPlan::IsValidRowIndex(uint32_t idx) const {
  return idx < m_row_list.size();
}

const UnwindPlan::RowSP UnwindPlan::GetRowAtIndex(uint32_t idx) const {
  if (idx < m_row_list.size())
    return m_row_list[idx];
  else {
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
    if (log)
      log->Printf("error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index "
                  "(number rows is %u)",
                  idx, (uint32_t)m_row_list.size());
    return UnwindPlan::RowSP();
  }
}

const UnwindPlan::RowSP UnwindPlan::GetLastRow() const {
  if (m_row_list.empty()) {
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
    if (log)
      log->Printf("UnwindPlan::GetLastRow() when rows are empty");
    return UnwindPlan::RowSP();
  }
  return m_row_list.back();
}

int UnwindPlan::GetRowCount() const { return m_row_list.size(); }

void UnwindPlan::SetPlanValidAddressRange(const AddressRange &range) {
  if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
    m_plan_valid_address_range = range;
}

bool UnwindPlan::PlanValidAtAddress(Address addr) {
  // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
  if (GetRowCount() == 0) {
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
    if (log) {
      StreamString s;
      if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
        log->Printf("UnwindPlan is invalid -- no unwind rows for UnwindPlan "
                    "'%s' at address %s",
                    m_source_name.GetCString(), s.GetData());
      } else {
        log->Printf(
            "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
            m_source_name.GetCString());
      }
    }
    return false;
  }

  // If the 0th Row of unwind instructions is missing, or if it doesn't provide
  // a register to use to find the Canonical Frame Address, this is not a valid
  // UnwindPlan.
  if (GetRowAtIndex(0).get() == nullptr ||
      GetRowAtIndex(0)->GetCFAValue().GetValueType() ==
          Row::FAValue::unspecified) {
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
    if (log) {
      StreamString s;
      if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
        log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 "
                    "for UnwindPlan '%s' at address %s",
                    m_source_name.GetCString(), s.GetData());
      } else {
        log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 "
                    "for UnwindPlan '%s'",
                    m_source_name.GetCString());
      }
    }
    return false;
  }

  if (!m_plan_valid_address_range.GetBaseAddress().IsValid() ||
      m_plan_valid_address_range.GetByteSize() == 0)
    return true;

  if (!addr.IsValid())
    return true;

  if (m_plan_valid_address_range.ContainsFileAddress(addr))
    return true;

  return false;
}

void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const {
  if (!m_source_name.IsEmpty()) {
    s.Printf("This UnwindPlan originally sourced from %s\n",
             m_source_name.GetCString());
  }
  if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) {
    TargetSP target_sp(thread->CalculateTarget());
    addr_t lsda_load_addr = m_lsda_address.GetLoadAddress(target_sp.get());
    addr_t personality_func_load_addr =
        m_personality_func_addr.GetLoadAddress(target_sp.get());

    if (lsda_load_addr != LLDB_INVALID_ADDRESS &&
        personality_func_load_addr != LLDB_INVALID_ADDRESS) {
      s.Printf("LSDA address 0x%" PRIx64
               ", personality routine is at address 0x%" PRIx64 "\n",
               lsda_load_addr, personality_func_load_addr);
    }
  }
  s.Printf("This UnwindPlan is sourced from the compiler: ");
  switch (m_plan_is_sourced_from_compiler) {
  case eLazyBoolYes:
    s.Printf("yes.\n");
    break;
  case eLazyBoolNo:
    s.Printf("no.\n");
    break;
  case eLazyBoolCalculate:
    s.Printf("not specified.\n");
    break;
  }
  s.Printf("This UnwindPlan is valid at all instruction locations: ");
  switch (m_plan_is_valid_at_all_instruction_locations) {
  case eLazyBoolYes:
    s.Printf("yes.\n");
    break;
  case eLazyBoolNo:
    s.Printf("no.\n");
    break;
  case eLazyBoolCalculate:
    s.Printf("not specified.\n");
    break;
  }
  if (m_plan_valid_address_range.GetBaseAddress().IsValid() &&
      m_plan_valid_address_range.GetByteSize() > 0) {
    s.PutCString("Address range of this UnwindPlan: ");
    TargetSP target_sp(thread->CalculateTarget());
    m_plan_valid_address_range.Dump(&s, target_sp.get(),
                                    Address::DumpStyleSectionNameOffset);
    s.EOL();
  }
  collection::const_iterator pos, begin = m_row_list.begin(),
                                  end = m_row_list.end();
  for (pos = begin; pos != end; ++pos) {
    s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos));
    (*pos)->Dump(s, this, thread, base_addr);
  }
}

void UnwindPlan::SetSourceName(const char *source) {
  m_source_name = ConstString(source);
}

ConstString UnwindPlan::GetSourceName() const { return m_source_name; }

const RegisterInfo *UnwindPlan::GetRegisterInfo(Thread *thread,
                                                uint32_t unwind_reg) const {
  if (thread) {
    RegisterContext *reg_ctx = thread->GetRegisterContext().get();
    if (reg_ctx) {
      uint32_t reg;
      if (m_register_kind == eRegisterKindLLDB)
        reg = unwind_reg;
      else
        reg = reg_ctx->ConvertRegisterKindToRegisterNumber(m_register_kind,
                                                           unwind_reg);
      if (reg != LLDB_INVALID_REGNUM)
        return reg_ctx->GetRegisterInfoAtIndex(reg);
    }
  }
  return nullptr;
}
