brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.1 KiB · fd8a0c0 Raw
647 lines · cpp
1//===-- NativeRegisterContextWindows_arm.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#if defined(__arm__) || defined(_M_ARM)10 11#include "NativeRegisterContextWindows_arm.h"12#include "NativeThreadWindows.h"13#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"14#include "ProcessWindowsLog.h"15#include "lldb/Host/HostInfo.h"16#include "lldb/Host/HostThread.h"17#include "lldb/Host/windows/HostThreadWindows.h"18#include "lldb/Host/windows/windows.h"19 20#include "lldb/Utility/Log.h"21#include "lldb/Utility/RegisterValue.h"22#include "llvm/ADT/STLExtras.h"23 24using namespace lldb;25using namespace lldb_private;26 27#define REG_CONTEXT_SIZE sizeof(::CONTEXT)28 29namespace {30static const uint32_t g_gpr_regnums_arm[] = {31    gpr_r0_arm,         gpr_r1_arm,   gpr_r2_arm,  gpr_r3_arm, gpr_r4_arm,32    gpr_r5_arm,         gpr_r6_arm,   gpr_r7_arm,  gpr_r8_arm, gpr_r9_arm,33    gpr_r10_arm,        gpr_r11_arm,  gpr_r12_arm, gpr_sp_arm, gpr_lr_arm,34    gpr_pc_arm,         gpr_cpsr_arm,35    LLDB_INVALID_REGNUM // Register set must be terminated with this flag36};37static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) ==38                  k_num_gpr_registers_arm,39              "g_gpr_regnums_arm has wrong number of register infos");40 41static const uint32_t g_fpr_regnums_arm[] = {42    fpu_s0_arm,         fpu_s1_arm,  fpu_s2_arm,  fpu_s3_arm,  fpu_s4_arm,43    fpu_s5_arm,         fpu_s6_arm,  fpu_s7_arm,  fpu_s8_arm,  fpu_s9_arm,44    fpu_s10_arm,        fpu_s11_arm, fpu_s12_arm, fpu_s13_arm, fpu_s14_arm,45    fpu_s15_arm,        fpu_s16_arm, fpu_s17_arm, fpu_s18_arm, fpu_s19_arm,46    fpu_s20_arm,        fpu_s21_arm, fpu_s22_arm, fpu_s23_arm, fpu_s24_arm,47    fpu_s25_arm,        fpu_s26_arm, fpu_s27_arm, fpu_s28_arm, fpu_s29_arm,48    fpu_s30_arm,        fpu_s31_arm,49 50    fpu_d0_arm,         fpu_d1_arm,  fpu_d2_arm,  fpu_d3_arm,  fpu_d4_arm,51    fpu_d5_arm,         fpu_d6_arm,  fpu_d7_arm,  fpu_d8_arm,  fpu_d9_arm,52    fpu_d10_arm,        fpu_d11_arm, fpu_d12_arm, fpu_d13_arm, fpu_d14_arm,53    fpu_d15_arm,        fpu_d16_arm, fpu_d17_arm, fpu_d18_arm, fpu_d19_arm,54    fpu_d20_arm,        fpu_d21_arm, fpu_d22_arm, fpu_d23_arm, fpu_d24_arm,55    fpu_d25_arm,        fpu_d26_arm, fpu_d27_arm, fpu_d28_arm, fpu_d29_arm,56    fpu_d30_arm,        fpu_d31_arm,57 58    fpu_q0_arm,         fpu_q1_arm,  fpu_q2_arm,  fpu_q3_arm,  fpu_q4_arm,59    fpu_q5_arm,         fpu_q6_arm,  fpu_q7_arm,  fpu_q8_arm,  fpu_q9_arm,60    fpu_q10_arm,        fpu_q11_arm, fpu_q12_arm, fpu_q13_arm, fpu_q14_arm,61    fpu_q15_arm,62 63    fpu_fpscr_arm,64    LLDB_INVALID_REGNUM // Register set must be terminated with this flag65};66static_assert(((sizeof g_fpr_regnums_arm / sizeof g_fpr_regnums_arm[0]) - 1) ==67                  k_num_fpr_registers_arm,68              "g_fpu_regnums_arm has wrong number of register infos");69 70static const RegisterSet g_reg_sets_arm[] = {71    {"General Purpose Registers", "gpr", std::size(g_gpr_regnums_arm) - 1,72     g_gpr_regnums_arm},73    {"Floating Point Registers", "fpr", std::size(g_fpr_regnums_arm) - 1,74     g_fpr_regnums_arm},75};76 77enum { k_num_register_sets = 2 };78 79} // namespace80 81static RegisterInfoInterface *82CreateRegisterInfoInterface(const ArchSpec &target_arch) {83  assert((HostInfo::GetArchitecture().GetAddressByteSize() == 4) &&84         "Register setting path assumes this is a 32-bit host");85  return new RegisterInfoPOSIX_arm(target_arch);86}87 88static Status GetThreadContextHelper(lldb::thread_t thread_handle,89                                     PCONTEXT context_ptr,90                                     const DWORD control_flag) {91  Log *log = GetLog(WindowsLog::Registers);92  Status error;93 94  memset(context_ptr, 0, sizeof(::CONTEXT));95  context_ptr->ContextFlags = control_flag;96  if (!::GetThreadContext(thread_handle, context_ptr)) {97    error = Status(GetLastError(), eErrorTypeWin32);98    LLDB_LOG(log, "{0} GetThreadContext failed with error {1}", __FUNCTION__,99             error);100    return error;101  }102  return Status();103}104 105static Status SetThreadContextHelper(lldb::thread_t thread_handle,106                                     PCONTEXT context_ptr) {107  Log *log = GetLog(WindowsLog::Registers);108  Status error;109  // It's assumed that the thread has stopped.110  if (!::SetThreadContext(thread_handle, context_ptr)) {111    error = Status(GetLastError(), eErrorTypeWin32);112    LLDB_LOG(log, "{0} SetThreadContext failed with error {1}", __FUNCTION__,113             error);114    return error;115  }116  return Status();117}118 119std::unique_ptr<NativeRegisterContextWindows>120NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(121    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {122  // TODO: Register context for a WoW64 application?123 124  // Register context for a native 64-bit application.125  return std::make_unique<NativeRegisterContextWindows_arm>(target_arch,126                                                            native_thread);127}128 129NativeRegisterContextWindows_arm::NativeRegisterContextWindows_arm(130    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)131    : NativeRegisterContextRegisterInfo(132          native_thread, CreateRegisterInfoInterface(target_arch)) {}133 134bool NativeRegisterContextWindows_arm::IsGPR(uint32_t reg_index) const {135  return (reg_index >= k_first_gpr_arm && reg_index <= k_last_gpr_arm);136}137 138bool NativeRegisterContextWindows_arm::IsFPR(uint32_t reg_index) const {139  return (reg_index >= k_first_fpr_arm && reg_index <= k_last_fpr_arm);140}141 142uint32_t NativeRegisterContextWindows_arm::GetRegisterSetCount() const {143  return k_num_register_sets;144}145 146const RegisterSet *147NativeRegisterContextWindows_arm::GetRegisterSet(uint32_t set_index) const {148  if (set_index >= k_num_register_sets)149    return nullptr;150  return &g_reg_sets_arm[set_index];151}152 153Status NativeRegisterContextWindows_arm::GPRRead(const uint32_t reg,154                                                 RegisterValue &reg_value) {155  ::CONTEXT tls_context;156  DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER;157  Status error =158      GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);159  if (error.Fail())160    return error;161 162  switch (reg) {163  case gpr_r0_arm:164    reg_value.SetUInt32(tls_context.R0);165    break;166  case gpr_r1_arm:167    reg_value.SetUInt32(tls_context.R1);168    break;169  case gpr_r2_arm:170    reg_value.SetUInt32(tls_context.R2);171    break;172  case gpr_r3_arm:173    reg_value.SetUInt32(tls_context.R3);174    break;175  case gpr_r4_arm:176    reg_value.SetUInt32(tls_context.R4);177    break;178  case gpr_r5_arm:179    reg_value.SetUInt32(tls_context.R5);180    break;181  case gpr_r6_arm:182    reg_value.SetUInt32(tls_context.R6);183    break;184  case gpr_r7_arm:185    reg_value.SetUInt32(tls_context.R7);186    break;187  case gpr_r8_arm:188    reg_value.SetUInt32(tls_context.R8);189    break;190  case gpr_r9_arm:191    reg_value.SetUInt32(tls_context.R9);192    break;193  case gpr_r10_arm:194    reg_value.SetUInt32(tls_context.R10);195    break;196  case gpr_r11_arm:197    reg_value.SetUInt32(tls_context.R11);198    break;199  case gpr_r12_arm:200    reg_value.SetUInt32(tls_context.R12);201    break;202  case gpr_sp_arm:203    reg_value.SetUInt32(tls_context.Sp);204    break;205  case gpr_lr_arm:206    reg_value.SetUInt32(tls_context.Lr);207    break;208  case gpr_pc_arm:209    reg_value.SetUInt32(tls_context.Pc);210    break;211  case gpr_cpsr_arm:212    reg_value.SetUInt32(tls_context.Cpsr);213    break;214  }215 216  return error;217}218 219Status220NativeRegisterContextWindows_arm::GPRWrite(const uint32_t reg,221                                           const RegisterValue &reg_value) {222  ::CONTEXT tls_context;223  DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER;224  auto thread_handle = GetThreadHandle();225  Status error =226      GetThreadContextHelper(thread_handle, &tls_context, context_flag);227  if (error.Fail())228    return error;229 230  switch (reg) {231  case gpr_r0_arm:232    tls_context.R0 = reg_value.GetAsUInt32();233    break;234  case gpr_r1_arm:235    tls_context.R1 = reg_value.GetAsUInt32();236    break;237  case gpr_r2_arm:238    tls_context.R2 = reg_value.GetAsUInt32();239    break;240  case gpr_r3_arm:241    tls_context.R3 = reg_value.GetAsUInt32();242    break;243  case gpr_r4_arm:244    tls_context.R4 = reg_value.GetAsUInt32();245    break;246  case gpr_r5_arm:247    tls_context.R5 = reg_value.GetAsUInt32();248    break;249  case gpr_r6_arm:250    tls_context.R6 = reg_value.GetAsUInt32();251    break;252  case gpr_r7_arm:253    tls_context.R7 = reg_value.GetAsUInt32();254    break;255  case gpr_r8_arm:256    tls_context.R8 = reg_value.GetAsUInt32();257    break;258  case gpr_r9_arm:259    tls_context.R9 = reg_value.GetAsUInt32();260    break;261  case gpr_r10_arm:262    tls_context.R10 = reg_value.GetAsUInt32();263    break;264  case gpr_r11_arm:265    tls_context.R11 = reg_value.GetAsUInt32();266    break;267  case gpr_r12_arm:268    tls_context.R12 = reg_value.GetAsUInt32();269    break;270  case gpr_sp_arm:271    tls_context.Sp = reg_value.GetAsUInt32();272    break;273  case gpr_lr_arm:274    tls_context.Lr = reg_value.GetAsUInt32();275    break;276  case gpr_pc_arm:277    tls_context.Pc = reg_value.GetAsUInt32();278    break;279  case gpr_cpsr_arm:280    tls_context.Cpsr = reg_value.GetAsUInt32();281    break;282  }283 284  return SetThreadContextHelper(thread_handle, &tls_context);285}286 287Status NativeRegisterContextWindows_arm::FPRRead(const uint32_t reg,288                                                 RegisterValue &reg_value) {289  ::CONTEXT tls_context;290  DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;291  Status error =292      GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);293  if (error.Fail())294    return error;295 296  switch (reg) {297  case fpu_s0_arm:298  case fpu_s1_arm:299  case fpu_s2_arm:300  case fpu_s3_arm:301  case fpu_s4_arm:302  case fpu_s5_arm:303  case fpu_s6_arm:304  case fpu_s7_arm:305  case fpu_s8_arm:306  case fpu_s9_arm:307  case fpu_s10_arm:308  case fpu_s11_arm:309  case fpu_s12_arm:310  case fpu_s13_arm:311  case fpu_s14_arm:312  case fpu_s15_arm:313  case fpu_s16_arm:314  case fpu_s17_arm:315  case fpu_s18_arm:316  case fpu_s19_arm:317  case fpu_s20_arm:318  case fpu_s21_arm:319  case fpu_s22_arm:320  case fpu_s23_arm:321  case fpu_s24_arm:322  case fpu_s25_arm:323  case fpu_s26_arm:324  case fpu_s27_arm:325  case fpu_s28_arm:326  case fpu_s29_arm:327  case fpu_s30_arm:328  case fpu_s31_arm:329    reg_value.SetUInt32(tls_context.S[reg - fpu_s0_arm],330                        RegisterValue::eTypeFloat);331    break;332 333  case fpu_d0_arm:334  case fpu_d1_arm:335  case fpu_d2_arm:336  case fpu_d3_arm:337  case fpu_d4_arm:338  case fpu_d5_arm:339  case fpu_d6_arm:340  case fpu_d7_arm:341  case fpu_d8_arm:342  case fpu_d9_arm:343  case fpu_d10_arm:344  case fpu_d11_arm:345  case fpu_d12_arm:346  case fpu_d13_arm:347  case fpu_d14_arm:348  case fpu_d15_arm:349  case fpu_d16_arm:350  case fpu_d17_arm:351  case fpu_d18_arm:352  case fpu_d19_arm:353  case fpu_d20_arm:354  case fpu_d21_arm:355  case fpu_d22_arm:356  case fpu_d23_arm:357  case fpu_d24_arm:358  case fpu_d25_arm:359  case fpu_d26_arm:360  case fpu_d27_arm:361  case fpu_d28_arm:362  case fpu_d29_arm:363  case fpu_d30_arm:364  case fpu_d31_arm:365    reg_value.SetUInt64(tls_context.D[reg - fpu_d0_arm],366                        RegisterValue::eTypeDouble);367    break;368 369  case fpu_q0_arm:370  case fpu_q1_arm:371  case fpu_q2_arm:372  case fpu_q3_arm:373  case fpu_q4_arm:374  case fpu_q5_arm:375  case fpu_q6_arm:376  case fpu_q7_arm:377  case fpu_q8_arm:378  case fpu_q9_arm:379  case fpu_q10_arm:380  case fpu_q11_arm:381  case fpu_q12_arm:382  case fpu_q13_arm:383  case fpu_q14_arm:384  case fpu_q15_arm:385    reg_value.SetBytes(&tls_context.Q[reg - fpu_q0_arm], 16,386                       endian::InlHostByteOrder());387    break;388 389  case fpu_fpscr_arm:390    reg_value.SetUInt32(tls_context.Fpscr);391    break;392  }393 394  return error;395}396 397Status398NativeRegisterContextWindows_arm::FPRWrite(const uint32_t reg,399                                           const RegisterValue &reg_value) {400  ::CONTEXT tls_context;401  DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;402  auto thread_handle = GetThreadHandle();403  Status error =404      GetThreadContextHelper(thread_handle, &tls_context, context_flag);405  if (error.Fail())406    return error;407 408  switch (reg) {409  case fpu_s0_arm:410  case fpu_s1_arm:411  case fpu_s2_arm:412  case fpu_s3_arm:413  case fpu_s4_arm:414  case fpu_s5_arm:415  case fpu_s6_arm:416  case fpu_s7_arm:417  case fpu_s8_arm:418  case fpu_s9_arm:419  case fpu_s10_arm:420  case fpu_s11_arm:421  case fpu_s12_arm:422  case fpu_s13_arm:423  case fpu_s14_arm:424  case fpu_s15_arm:425  case fpu_s16_arm:426  case fpu_s17_arm:427  case fpu_s18_arm:428  case fpu_s19_arm:429  case fpu_s20_arm:430  case fpu_s21_arm:431  case fpu_s22_arm:432  case fpu_s23_arm:433  case fpu_s24_arm:434  case fpu_s25_arm:435  case fpu_s26_arm:436  case fpu_s27_arm:437  case fpu_s28_arm:438  case fpu_s29_arm:439  case fpu_s30_arm:440  case fpu_s31_arm:441    tls_context.S[reg - fpu_s0_arm] = reg_value.GetAsUInt32();442    break;443 444  case fpu_d0_arm:445  case fpu_d1_arm:446  case fpu_d2_arm:447  case fpu_d3_arm:448  case fpu_d4_arm:449  case fpu_d5_arm:450  case fpu_d6_arm:451  case fpu_d7_arm:452  case fpu_d8_arm:453  case fpu_d9_arm:454  case fpu_d10_arm:455  case fpu_d11_arm:456  case fpu_d12_arm:457  case fpu_d13_arm:458  case fpu_d14_arm:459  case fpu_d15_arm:460  case fpu_d16_arm:461  case fpu_d17_arm:462  case fpu_d18_arm:463  case fpu_d19_arm:464  case fpu_d20_arm:465  case fpu_d21_arm:466  case fpu_d22_arm:467  case fpu_d23_arm:468  case fpu_d24_arm:469  case fpu_d25_arm:470  case fpu_d26_arm:471  case fpu_d27_arm:472  case fpu_d28_arm:473  case fpu_d29_arm:474  case fpu_d30_arm:475  case fpu_d31_arm:476    tls_context.D[reg - fpu_d0_arm] = reg_value.GetAsUInt64();477    break;478 479  case fpu_q0_arm:480  case fpu_q1_arm:481  case fpu_q2_arm:482  case fpu_q3_arm:483  case fpu_q4_arm:484  case fpu_q5_arm:485  case fpu_q6_arm:486  case fpu_q7_arm:487  case fpu_q8_arm:488  case fpu_q9_arm:489  case fpu_q10_arm:490  case fpu_q11_arm:491  case fpu_q12_arm:492  case fpu_q13_arm:493  case fpu_q14_arm:494  case fpu_q15_arm:495    memcpy(&tls_context.Q[reg - fpu_q0_arm], reg_value.GetBytes(), 16);496    break;497 498  case fpu_fpscr_arm:499    tls_context.Fpscr = reg_value.GetAsUInt32();500    break;501  }502 503  return SetThreadContextHelper(thread_handle, &tls_context);504}505 506Status507NativeRegisterContextWindows_arm::ReadRegister(const RegisterInfo *reg_info,508                                               RegisterValue &reg_value) {509  Status error;510  if (!reg_info) {511    error = Status::FromErrorString("reg_info NULL");512    return error;513  }514 515  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];516  if (reg == LLDB_INVALID_REGNUM) {517    // This is likely an internal register for lldb use only and should not be518    // directly queried.519    error = Status::FromErrorStringWithFormat(520        "register \"%s\" is an internal-only lldb "521        "register, cannot read directly",522        reg_info->name);523    return error;524  }525 526  if (IsGPR(reg))527    return GPRRead(reg, reg_value);528 529  if (IsFPR(reg))530    return FPRRead(reg, reg_value);531 532  return Status::FromErrorString("unimplemented");533}534 535Status NativeRegisterContextWindows_arm::WriteRegister(536    const RegisterInfo *reg_info, const RegisterValue &reg_value) {537  Status error;538 539  if (!reg_info) {540    error = Status::FromErrorString("reg_info NULL");541    return error;542  }543 544  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];545  if (reg == LLDB_INVALID_REGNUM) {546    // This is likely an internal register for lldb use only and should not be547    // directly written.548    error = Status::FromErrorStringWithFormat(549        "register \"%s\" is an internal-only lldb "550        "register, cannot write directly",551        reg_info->name);552    return error;553  }554 555  if (IsGPR(reg))556    return GPRWrite(reg, reg_value);557 558  if (IsFPR(reg))559    return FPRWrite(reg, reg_value);560 561  return Status::FromErrorString("unimplemented");562}563 564Status NativeRegisterContextWindows_arm::ReadAllRegisterValues(565    lldb::WritableDataBufferSP &data_sp) {566  const size_t data_size = REG_CONTEXT_SIZE;567  data_sp = std::make_shared<DataBufferHeap>(data_size, 0);568  ::CONTEXT tls_context;569  Status error =570      GetThreadContextHelper(GetThreadHandle(), &tls_context, CONTEXT_ALL);571  if (error.Fail())572    return error;573 574  uint8_t *dst = data_sp->GetBytes();575  ::memcpy(dst, &tls_context, data_size);576  return error;577}578 579Status NativeRegisterContextWindows_arm::WriteAllRegisterValues(580    const lldb::DataBufferSP &data_sp) {581  Status error;582  const size_t data_size = REG_CONTEXT_SIZE;583  if (!data_sp) {584    error = Status::FromErrorStringWithFormat(585        "NativeRegisterContextWindows_arm::%s invalid data_sp provided",586        __FUNCTION__);587    return error;588  }589 590  if (data_sp->GetByteSize() != data_size) {591    error = Status::FromErrorStringWithFormatv(592        "data_sp contained mismatched data size, expected {0}, actual {1}",593        data_size, data_sp->GetByteSize());594    return error;595  }596 597  ::CONTEXT tls_context;598  memcpy(&tls_context, data_sp->GetBytes(), data_size);599  return SetThreadContextHelper(GetThreadHandle(), &tls_context);600}601 602Status NativeRegisterContextWindows_arm::IsWatchpointHit(uint32_t wp_index,603                                                         bool &is_hit) {604  return Status::FromErrorString("unimplemented");605}606 607Status NativeRegisterContextWindows_arm::GetWatchpointHitIndex(608    uint32_t &wp_index, lldb::addr_t trap_addr) {609  return Status::FromErrorString("unimplemented");610}611 612Status NativeRegisterContextWindows_arm::IsWatchpointVacant(uint32_t wp_index,613                                                            bool &is_vacant) {614  return Status::FromErrorString("unimplemented");615}616 617Status NativeRegisterContextWindows_arm::SetHardwareWatchpointWithIndex(618    lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {619  return Status::FromErrorString("unimplemented");620}621 622bool NativeRegisterContextWindows_arm::ClearHardwareWatchpoint(623    uint32_t wp_index) {624  return false;625}626 627Status NativeRegisterContextWindows_arm::ClearAllHardwareWatchpoints() {628  return Status::FromErrorString("unimplemented");629}630 631uint32_t NativeRegisterContextWindows_arm::SetHardwareWatchpoint(632    lldb::addr_t addr, size_t size, uint32_t watch_flags) {633  return LLDB_INVALID_INDEX32;634}635 636lldb::addr_t637NativeRegisterContextWindows_arm::GetWatchpointAddress(uint32_t wp_index) {638  return LLDB_INVALID_ADDRESS;639}640 641uint32_t NativeRegisterContextWindows_arm::NumSupportedHardwareWatchpoints() {642  // Not implemented643  return 0;644}645 646#endif // defined(__arm__) || defined(_M_ARM)647