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

#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 avlue 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.
  std::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) == 0xc0) {
      // 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.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());
}
