brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.7 KiB · 75dcb6e Raw
346 lines · cpp
1//===-- EmulationStateARM.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "EmulationStateARM.h"10 11#include "lldb/Interpreter/OptionValueArray.h"12#include "lldb/Interpreter/OptionValueDictionary.h"13#include "lldb/Target/RegisterContext.h"14#include "lldb/Target/StackFrame.h"15#include "lldb/Utility/RegisterValue.h"16#include "lldb/Utility/Scalar.h"17 18#include "Utility/ARM_DWARF_Registers.h"19 20using namespace lldb;21using namespace lldb_private;22 23EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {24  ClearPseudoRegisters();25}26 27EmulationStateARM::~EmulationStateARM() = default;28 29bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num,30                                                 uint64_t value) {31  if (reg_num <= dwarf_cpsr)32    m_gpr[reg_num - dwarf_r0] = (uint32_t)value;33  else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {34    uint32_t idx = reg_num - dwarf_s0;35    m_vfp_regs.s_regs[idx] = (uint32_t)value;36  } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) {37    uint32_t idx = reg_num - dwarf_d0;38    if (idx < 16) {39      m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;40      m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);41    } else42      m_vfp_regs.d_regs[idx - 16] = value;43  } else44    return false;45 46  return true;47}48 49uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num,50                                                    bool &success) {51  uint64_t value = 0;52  success = true;53 54  if (reg_num <= dwarf_cpsr)55    value = m_gpr[reg_num - dwarf_r0];56  else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {57    uint32_t idx = reg_num - dwarf_s0;58    value = m_vfp_regs.s_regs[idx];59  } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) {60    uint32_t idx = reg_num - dwarf_d0;61    if (idx < 16)62      value = (uint64_t)m_vfp_regs.s_regs[idx * 2] |63              ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] << 32);64    else65      value = m_vfp_regs.d_regs[idx - 16];66  } else67    success = false;68 69  return value;70}71 72void EmulationStateARM::ClearPseudoRegisters() {73  for (int i = 0; i < 17; ++i)74    m_gpr[i] = 0;75 76  for (int i = 0; i < 32; ++i)77    m_vfp_regs.s_regs[i] = 0;78 79  for (int i = 0; i < 16; ++i)80    m_vfp_regs.d_regs[i] = 0;81}82 83void EmulationStateARM::ClearPseudoMemory() { m_memory.clear(); }84 85bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address,86                                             uint32_t value) {87  m_memory[p_address] = value;88  return true;89}90 91uint32_t EmulationStateARM::ReadFromPseudoAddress(lldb::addr_t p_address,92                                                  bool &success) {93  std::map<lldb::addr_t, uint32_t>::iterator pos;94  uint32_t ret_val = 0;95 96  success = true;97  pos = m_memory.find(p_address);98  if (pos != m_memory.end())99    ret_val = pos->second;100  else101    success = false;102 103  return ret_val;104}105 106size_t EmulationStateARM::ReadPseudoMemory(107    EmulateInstruction *instruction, void *baton,108    const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst,109    size_t length) {110  if (!baton)111    return 0;112 113  bool success = true;114  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;115  if (length <= 4) {116    uint32_t value = pseudo_state->ReadFromPseudoAddress(addr, success);117    if (!success)118      return 0;119 120    if (endian::InlHostByteOrder() == lldb::eByteOrderBig)121      value = llvm::byteswap<uint32_t>(value);122    *((uint32_t *)dst) = value;123  } else if (length == 8) {124    uint32_t value1 = pseudo_state->ReadFromPseudoAddress(addr, success);125    if (!success)126      return 0;127 128    uint32_t value2 = pseudo_state->ReadFromPseudoAddress(addr + 4, success);129    if (!success)130      return 0;131 132    if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {133      value1 = llvm::byteswap<uint32_t>(value1);134      value2 = llvm::byteswap<uint32_t>(value2);135    }136    ((uint32_t *)dst)[0] = value1;137    ((uint32_t *)dst)[1] = value2;138  } else139    success = false;140 141  if (success)142    return length;143 144  return 0;145}146 147size_t EmulationStateARM::WritePseudoMemory(148    EmulateInstruction *instruction, void *baton,149    const EmulateInstruction::Context &context, lldb::addr_t addr,150    const void *dst, size_t length) {151  if (!baton)152    return 0;153 154  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;155 156  if (length <= 4) {157    uint32_t value;158    memcpy (&value, dst, sizeof (uint32_t));159    if (endian::InlHostByteOrder() == lldb::eByteOrderBig)160      value = llvm::byteswap<uint32_t>(value);161 162    pseudo_state->StoreToPseudoAddress(addr, value);163    return length;164  } else if (length == 8) {165    uint32_t value1;166    uint32_t value2;167    memcpy (&value1, dst, sizeof (uint32_t));168    memcpy(&value2, static_cast<const uint8_t *>(dst) + sizeof(uint32_t),169           sizeof(uint32_t));170    if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {171      value1 = llvm::byteswap<uint32_t>(value1);172      value2 = llvm::byteswap<uint32_t>(value2);173    }174 175    pseudo_state->StoreToPseudoAddress(addr, value1);176    pseudo_state->StoreToPseudoAddress(addr + 4, value2);177    return length;178  }179 180  return 0;181}182 183bool EmulationStateARM::ReadPseudoRegister(184    EmulateInstruction *instruction, void *baton,185    const lldb_private::RegisterInfo *reg_info,186    lldb_private::RegisterValue &reg_value) {187  if (!baton || !reg_info)188    return false;189 190  bool success = true;191  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;192  const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];193  assert(dwarf_reg_num != LLDB_INVALID_REGNUM);194  uint64_t reg_uval =195      pseudo_state->ReadPseudoRegisterValue(dwarf_reg_num, success);196 197  if (success)198    success = reg_value.SetUInt(reg_uval, reg_info->byte_size);199  return success;200}201 202bool EmulationStateARM::WritePseudoRegister(203    EmulateInstruction *instruction, void *baton,204    const EmulateInstruction::Context &context,205    const lldb_private::RegisterInfo *reg_info,206    const lldb_private::RegisterValue &reg_value) {207  if (!baton || !reg_info)208    return false;209 210  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;211  const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];212  assert(dwarf_reg_num != LLDB_INVALID_REGNUM);213  return pseudo_state->StorePseudoRegisterValue(dwarf_reg_num,214                                                reg_value.GetAsUInt64());215}216 217bool EmulationStateARM::CompareState(EmulationStateARM &other_state,218                                     Stream &out_stream) {219  bool match = true;220 221  for (int i = 0; match && i < 17; ++i) {222    if (m_gpr[i] != other_state.m_gpr[i]) {223      match = false;224      out_stream.Printf("r%d: 0x%x != 0x%x\n", i, m_gpr[i],225                        other_state.m_gpr[i]);226    }227  }228 229  for (int i = 0; match && i < 32; ++i) {230    if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i]) {231      match = false;232      out_stream.Printf("s%d: 0x%x != 0x%x\n", i, m_vfp_regs.s_regs[i],233                        other_state.m_vfp_regs.s_regs[i]);234    }235  }236 237  for (int i = 0; match && i < 16; ++i) {238    if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i]) {239      match = false;240      out_stream.Printf("d%d: 0x%" PRIx64 " != 0x%" PRIx64 "\n", i + 16,241                        m_vfp_regs.d_regs[i], other_state.m_vfp_regs.d_regs[i]);242    }243  }244 245  // other_state is the expected state. If it has memory, check it.246  if (!other_state.m_memory.empty() && m_memory != other_state.m_memory) {247    match = false;248    out_stream.Printf("memory does not match\n");249    out_stream.Printf("got memory:\n");250    for (auto p : m_memory)251      out_stream.Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);252    out_stream.Printf("expected memory:\n");253    for (auto p : other_state.m_memory)254      out_stream.Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);255  }256 257  return match;258}259 260bool EmulationStateARM::LoadRegistersStateFromDictionary(261    OptionValueDictionary *reg_dict, char kind, int first_reg, int num) {262  StreamString sstr;263  for (int i = 0; i < num; ++i) {264    sstr.Clear();265    sstr.Printf("%c%d", kind, i);266    OptionValueSP value_sp = reg_dict->GetValueForKey(sstr.GetString());267    if (value_sp.get() == nullptr)268      return false;269    uint64_t reg_value = value_sp->GetValueAs<uint64_t>().value_or(0);270    StorePseudoRegisterValue(first_reg + i, reg_value);271  }272 273  return true;274}275 276bool EmulationStateARM::LoadStateFromDictionary(277    OptionValueDictionary *test_data) {278  static constexpr llvm::StringLiteral memory_key("memory");279  static constexpr llvm::StringLiteral registers_key("registers");280 281  if (!test_data)282    return false;283 284  OptionValueSP value_sp = test_data->GetValueForKey(memory_key);285 286  // Load memory, if present.287 288  if (value_sp.get() != nullptr) {289    static constexpr llvm::StringLiteral address_key("address");290    static constexpr llvm::StringLiteral data_key("data");291    uint64_t start_address = 0;292 293    OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();294    value_sp = mem_dict->GetValueForKey(address_key);295    if (value_sp.get() == nullptr)296      return false;297    else298      start_address = value_sp->GetValueAs<uint64_t>().value_or(0);299 300    value_sp = mem_dict->GetValueForKey(data_key);301    OptionValueArray *mem_array = value_sp->GetAsArray();302    if (!mem_array)303      return false;304 305    uint32_t num_elts = mem_array->GetSize();306    uint32_t address = (uint32_t)start_address;307 308    for (uint32_t i = 0; i < num_elts; ++i) {309      value_sp = mem_array->GetValueAtIndex(i);310      if (value_sp.get() == nullptr)311        return false;312      uint64_t value = value_sp->GetValueAs<uint64_t>().value_or(0);313      StoreToPseudoAddress(address, value);314      address = address + 4;315    }316  }317 318  value_sp = test_data->GetValueForKey(registers_key);319  if (value_sp.get() == nullptr)320    return false;321 322  // Load General Registers323 324  OptionValueDictionary *reg_dict = value_sp->GetAsDictionary();325  if (!LoadRegistersStateFromDictionary(reg_dict, 'r', dwarf_r0, 16))326    return false;327 328  static constexpr llvm::StringLiteral cpsr_name("cpsr");329  value_sp = reg_dict->GetValueForKey(cpsr_name);330  if (value_sp.get() == nullptr)331    return false;332  StorePseudoRegisterValue(dwarf_cpsr,333                           value_sp->GetValueAs<uint64_t>().value_or(0));334 335  // Load s/d Registers336  // To prevent you giving both types in a state and overwriting337  // one or the other, we'll expect to get either all S registers,338  // or all D registers. Not a mix of the two.339  bool found_s_registers =340      LoadRegistersStateFromDictionary(reg_dict, 's', dwarf_s0, 32);341  bool found_d_registers =342      LoadRegistersStateFromDictionary(reg_dict, 'd', dwarf_d0, 32);343 344  return found_s_registers != found_d_registers;345}346