//===-- ArmUnwindInfo.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 <vector>

#include "Utility/ARM_DWARF_Registers.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ArmUnwindInfo.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Utility/Endian.h"

/*
 * Unwind information reader and parser for the ARM exception handling ABI
 *
 * Implemented based on:
 *     Exception Handling ABI for the ARM Architecture
 *     Document number: ARM IHI 0038A (current through ABI r2.09)
 *     Date of Issue: 25th January 2007, reissued 30th November 2012
 *     http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
 */

using namespace lldb;
using namespace lldb_private;

// Converts a prel31 value to lldb::addr_t with sign extension
static addr_t Prel31ToAddr(uint32_t prel31) {
  addr_t res = prel31;
  if (prel31 & (1 << 30))
    res |= 0xffffffff80000000ULL;
  return res;
}

ArmUnwindInfo::ArmExidxEntry::ArmExidxEntry(uint32_t f, lldb::addr_t a,
                                            uint32_t d)
    : file_address(f), address(a), data(d) {}

bool ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry &other) const {
  return address < other.address;
}

ArmUnwindInfo::ArmUnwindInfo(ObjectFile &objfile, SectionSP &arm_exidx,
                             SectionSP &arm_extab)
    : m_byte_order(objfile.GetByteOrder()), m_arm_exidx_sp(arm_exidx),
      m_arm_extab_sp(arm_extab) {
  objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data);
  objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data);

  addr_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress();

  offset_t offset = 0;
  while (m_arm_exidx_data.ValidOffset(offset)) {
    lldb::addr_t file_addr = exidx_base_addr + offset;
    lldb::addr_t addr = exidx_base_addr + (addr_t)offset +
                        Prel31ToAddr(m_arm_exidx_data.GetU32(&offset));
    uint32_t data = m_arm_exidx_data.GetU32(&offset);
    m_exidx_entries.emplace_back(file_addr, addr, data);
  }

  // Sort the entries in the exidx section. The entries should be sorted inside
  // the section but some old compiler isn't sorted them.
  llvm::sort(m_exidx_entries.begin(), m_exidx_entries.end());
}

ArmUnwindInfo::~ArmUnwindInfo() {}

// Read a byte from the unwind instruction stream with the given offset. Custom
// function is required because have to red in order of significance within
// their containing word (most significant byte first) and in increasing word
// address order.
uint8_t ArmUnwindInfo::GetByteAtOffset(const uint32_t *data,
                                       uint16_t offset) const {
  uint32_t value = data[offset / 4];
  if (m_byte_order != endian::InlHostByteOrder())
    value = llvm::ByteSwap_32(value);
  return (value >> ((3 - (offset % 4)) * 8)) & 0xff;
}

uint64_t ArmUnwindInfo::GetULEB128(const uint32_t *data, uint16_t &offset,
                                   uint16_t max_offset) const {
  uint64_t result = 0;
  uint8_t shift = 0;
  while (offset < max_offset) {
    uint8_t byte = GetByteAtOffset(data, offset++);
    result |= (uint64_t)(byte & 0x7f) << shift;
    if ((byte & 0x80) == 0)
      break;
    shift += 7;
  }
  return result;
}

bool ArmUnwindInfo::GetUnwindPlan(Target &target, const Address &addr,
                                  UnwindPlan &unwind_plan) {
  const uint32_t *data = (const uint32_t *)GetExceptionHandlingTableEntry(addr);
  if (data == nullptr)
    return false; // No unwind information for the function

  if (data[0] == 0x1)
    return false; // EXIDX_CANTUNWIND

  uint16_t byte_count = 0;
  uint16_t byte_offset = 0;
  if (data[0] & 0x80000000) {
    switch ((data[0] >> 24) & 0x0f) {
    case 0:
      byte_count = 4;
      byte_offset = 1;
      break;
    case 1:
    case 2:
      byte_count = 4 * ((data[0] >> 16) & 0xff) + 4;
      byte_offset = 2;
      break;
    default:
      // Unhandled personality routine index
      return false;
    }
  } else {
    byte_count = 4 * ((data[1] >> 24) & 0xff) + 8;
    byte_offset = 5;
  }

  uint8_t vsp_reg = dwarf_sp;
  int32_t vsp = 0;
  std::vector<std::pair<uint32_t, int32_t>>
      register_offsets; // register -> (offset from vsp_reg)

  while (byte_offset < byte_count) {
    uint8_t byte1 = GetByteAtOffset(data, byte_offset++);
    if ((byte1 & 0xc0) == 0x00) {
      // 00xxxxxx
      // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive
      vsp += ((byte1 & 0x3f) << 2) + 4;
    } else if ((byte1 & 0xc0) == 0x40) {
      // 01xxxxxx
      // vsp = vsp – (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive
      vsp -= ((byte1 & 0x3f) << 2) + 4;
    } else if ((byte1 & 0xf0) == 0x80) {
      if (byte_offset >= byte_count)
        return false;

      uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
      if (byte1 == 0x80 && byte2 == 0) {
        // 10000000 00000000
        // Refuse to unwind (for example, out of a cleanup) (see remark a)
        return false;
      } else {
        // 1000iiii iiiiiiii (i not all 0)
        // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see
        // remark b)
        uint16_t regs = ((byte1 & 0x0f) << 8) | byte2;
        for (uint8_t i = 0; i < 12; ++i) {
          if (regs & (1 << i)) {
            register_offsets.emplace_back(dwarf_r4 + i, vsp);
            vsp += 4;
          }
        }
      }
    } else if ((byte1 & 0xff) == 0x9d) {
      // 10011101
      // Reserved as prefix for ARM register to register moves
      return false;
    } else if ((byte1 & 0xff) == 0x9f) {
      // 10011111
      // Reserved as prefix for Intel Wireless MMX register to register moves
      return false;
    } else if ((byte1 & 0xf0) == 0x90) {
      // 1001nnnn (nnnn != 13,15)
      // Set vsp = r[nnnn]
      vsp_reg = dwarf_r0 + (byte1 & 0x0f);
    } else if ((byte1 & 0xf8) == 0xa0) {
      // 10100nnn
      // Pop r4-r[4+nnn]
      uint8_t n = byte1 & 0x7;
      for (uint8_t i = 0; i <= n; ++i) {
        register_offsets.emplace_back(dwarf_r4 + i, vsp);
        vsp += 4;
      }
    } else if ((byte1 & 0xf8) == 0xa8) {
      // 10101nnn
      // Pop r4-r[4+nnn], r14
      uint8_t n = byte1 & 0x7;
      for (uint8_t i = 0; i <= n; ++i) {
        register_offsets.emplace_back(dwarf_r4 + i, vsp);
        vsp += 4;
      }

      register_offsets.emplace_back(dwarf_lr, vsp);
      vsp += 4;
    } else if ((byte1 & 0xff) == 0xb0) {
      // 10110000
      // Finish (see remark c)
      break;
    } else if ((byte1 & 0xff) == 0xb1) {
      if (byte_offset >= byte_count)
        return false;

      uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
      if ((byte2 & 0xff) == 0x00) {
        // 10110001 00000000
        // Spare (see remark f)
        return false;
      } else if ((byte2 & 0xf0) == 0x00) {
        // 10110001 0000iiii (i not all 0)
        // Pop integer registers under mask {r3, r2, r1, r0}
        for (uint8_t i = 0; i < 4; ++i) {
          if (byte2 & (1 << i)) {
            register_offsets.emplace_back(dwarf_r0 + i, vsp);
            vsp += 4;
          }
        }
      } else {
        // 10110001 xxxxyyyy
        // Spare (xxxx != 0000)
        return false;
      }
    } else if ((byte1 & 0xff) == 0xb2) {
      // 10110010 uleb128
      // vsp = vsp + 0x204+ (uleb128 << 2)
      uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count);
      vsp += 0x204 + (uleb128 << 2);
    } else if ((byte1 & 0xff) == 0xb3) {
      // 10110011 sssscccc
      // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if)
      // by FSTMFDX (see remark d)
      if (byte_offset >= byte_count)
        return false;

      uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
      uint8_t s = (byte2 & 0xf0) >> 4;
      uint8_t c = (byte2 & 0x0f) >> 0;
      for (uint8_t i = 0; i <= c; ++i) {
        register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
        vsp += 8;
      }
      vsp += 4;
    } else if ((byte1 & 0xfc) == 0xb4) {
      // 101101nn
      // Spare (was Pop FPA)
      return false;
    } else if ((byte1 & 0xf8) == 0xb8) {
      // 10111nnn
      // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by
      // FSTMFDX (see remark d)
      uint8_t n = byte1 & 0x07;
      for (uint8_t i = 0; i <= n; ++i) {
        register_offsets.emplace_back(dwarf_d8 + i, vsp);
        vsp += 8;
      }
      vsp += 4;
    } else if ((byte1 & 0xf8) == 0xc0) {
      // 11000nnn (nnn != 6,7)
      // Intel Wireless MMX pop wR[10]-wR[10+nnn]

      // 11000110 sssscccc
      // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e)

      // 11000111 00000000
      // Spare

      // 11000111 0000iiii
      // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0}

      // 11000111 xxxxyyyy
      // Spare (xxxx != 0000)

      return false;
    } else if ((byte1 & 0xff) == 0xc8) {
      // 11001000 sssscccc
      // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved
      // (as if) by FSTMFDD (see remarks d,e)
      if (byte_offset >= byte_count)
        return false;

      uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
      uint8_t s = (byte2 & 0xf0) >> 4;
      uint8_t c = (byte2 & 0x0f) >> 0;
      for (uint8_t i = 0; i <= c; ++i) {
        register_offsets.emplace_back(dwarf_d16 + s + i, vsp);
        vsp += 8;
      }
    } else if ((byte1 & 0xff) == 0xc9) {
      // 11001001 sssscccc
      // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if)
      // by FSTMFDD (see remark d)
      if (byte_offset >= byte_count)
        return false;

      uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
      uint8_t s = (byte2 & 0xf0) >> 4;
      uint8_t c = (byte2 & 0x0f) >> 0;
      for (uint8_t i = 0; i <= c; ++i) {
        register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
        vsp += 8;
      }
    } else if ((byte1 & 0xf8) == 0xc8) {
      // 11001yyy
      // Spare (yyy != 000, 001)
      return false;
    } else if ((byte1 & 0xf8) == 0xd0) {
      // 11010nnn
      // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by
      // FSTMFDD (see remark d)
      uint8_t n = byte1 & 0x07;
      for (uint8_t i = 0; i <= n; ++i) {
        register_offsets.emplace_back(dwarf_d8 + i, vsp);
        vsp += 8;
      }
    } else if ((byte1 & 0xc0) == 0xc0) {
      // 11xxxyyy Spare (xxx != 000, 001, 010)
      return false;
    } else {
      return false;
    }
  }

  UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>();
  row->SetOffset(0);
  row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp);

  bool have_location_for_pc = false;
  for (const auto &offset : register_offsets) {
    have_location_for_pc |= offset.first == dwarf_pc;
    row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp,
                                              true);
  }

  if (!have_location_for_pc) {
    UnwindPlan::Row::RegisterLocation lr_location;
    if (row->GetRegisterInfo(dwarf_lr, lr_location))
      row->SetRegisterInfo(dwarf_pc, lr_location);
    else
      row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false);
  }

  unwind_plan.AppendRow(row);
  unwind_plan.SetSourceName("ARM.exidx unwind info");
  unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
  unwind_plan.SetRegisterKind(eRegisterKindDWARF);

  return true;
}

const uint8_t *
ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address &addr) {
  auto it = std::upper_bound(m_exidx_entries.begin(), m_exidx_entries.end(),
                             ArmExidxEntry{0, addr.GetFileAddress(), 0});
  if (it == m_exidx_entries.begin())
    return nullptr;
  --it;

  if (it->data == 0x1)
    return nullptr; // EXIDX_CANTUNWIND

  if (it->data & 0x80000000)
    return (const uint8_t *)&it->data;

  addr_t data_file_addr = it->file_address + 4 + Prel31ToAddr(it->data);
  return m_arm_extab_data.GetDataStart() +
         (data_file_addr - m_arm_extab_sp->GetFileAddress());
}
