180814287SRaphael Isemann //===-- NativeRegisterContext.cpp -----------------------------------------===//
22fe1d0abSChaoren Lin //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62fe1d0abSChaoren Lin //
72fe1d0abSChaoren Lin //===----------------------------------------------------------------------===//
82fe1d0abSChaoren Lin 
92fe1d0abSChaoren Lin #include "lldb/Host/common/NativeRegisterContext.h"
10*c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
11d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h"
122fe1d0abSChaoren Lin 
13b9c1b51eSKate Stone #include "lldb/Host/PosixApi.h"
142fe1d0abSChaoren Lin #include "lldb/Host/common/NativeProcessProtocol.h"
152fe1d0abSChaoren Lin #include "lldb/Host/common/NativeThreadProtocol.h"
162fe1d0abSChaoren Lin 
172fe1d0abSChaoren Lin using namespace lldb;
182fe1d0abSChaoren Lin using namespace lldb_private;
192fe1d0abSChaoren Lin 
NativeRegisterContext(NativeThreadProtocol & thread)20d37349f3SPavel Labath NativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread)
21d37349f3SPavel Labath     : m_thread(thread) {}
222fe1d0abSChaoren Lin 
232fe1d0abSChaoren Lin // Destructor
24fd2433e1SJonas Devlieghere NativeRegisterContext::~NativeRegisterContext() = default;
252fe1d0abSChaoren Lin 
262fe1d0abSChaoren Lin // FIXME revisit invalidation, process stop ids, etc.  Right now we don't
2705097246SAdrian Prantl // support caching in NativeRegisterContext.  We can do this later by utilizing
2805097246SAdrian Prantl // NativeProcessProtocol::GetStopID () and adding a stop id to
292fe1d0abSChaoren Lin // NativeRegisterContext.
302fe1d0abSChaoren Lin 
312fe1d0abSChaoren Lin // void
3205097246SAdrian Prantl // NativeRegisterContext::InvalidateIfNeeded (bool force) {
332fe1d0abSChaoren Lin //     ProcessSP process_sp (m_thread.GetProcess());
342fe1d0abSChaoren Lin //     bool invalidate = force;
352fe1d0abSChaoren Lin //     uint32_t process_stop_id = UINT32_MAX;
362fe1d0abSChaoren Lin 
372fe1d0abSChaoren Lin //     if (process_sp)
382fe1d0abSChaoren Lin //         process_stop_id = process_sp->GetStopID();
392fe1d0abSChaoren Lin //     else
402fe1d0abSChaoren Lin //         invalidate = true;
412fe1d0abSChaoren Lin 
422fe1d0abSChaoren Lin //     if (!invalidate)
432fe1d0abSChaoren Lin //         invalidate = process_stop_id != GetStopID();
442fe1d0abSChaoren Lin 
452fe1d0abSChaoren Lin //     if (invalidate)
462fe1d0abSChaoren Lin //     {
472fe1d0abSChaoren Lin //         InvalidateAllRegisters ();
482fe1d0abSChaoren Lin //         SetStopID (process_stop_id);
492fe1d0abSChaoren Lin //     }
502fe1d0abSChaoren Lin // }
512fe1d0abSChaoren Lin 
522fe1d0abSChaoren Lin const RegisterInfo *
GetRegisterInfoByName(llvm::StringRef reg_name,uint32_t start_idx)53e00e64caSZachary Turner NativeRegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name,
54b9c1b51eSKate Stone                                              uint32_t start_idx) {
55e00e64caSZachary Turner   if (reg_name.empty())
56e00e64caSZachary Turner     return nullptr;
57e00e64caSZachary Turner 
588567f4d4SMichał Górny   // Generic register names take precedence over specific register names.
598567f4d4SMichał Górny   // For example, on x86 we want "sp" to refer to the complete RSP/ESP register
608567f4d4SMichał Górny   // rather than the 16-bit SP pseudo-register.
618567f4d4SMichał Górny   uint32_t generic_reg = Args::StringToGenericRegister(reg_name);
628567f4d4SMichał Górny   if (generic_reg != LLDB_INVALID_REGNUM) {
638567f4d4SMichał Górny     const RegisterInfo *reg_info =
648567f4d4SMichał Górny         GetRegisterInfo(eRegisterKindGeneric, generic_reg);
658567f4d4SMichał Górny     if (reg_info)
668567f4d4SMichał Górny       return reg_info;
678567f4d4SMichał Górny   }
688567f4d4SMichał Górny 
692fe1d0abSChaoren Lin   const uint32_t num_registers = GetRegisterCount();
70b9c1b51eSKate Stone   for (uint32_t reg = start_idx; reg < num_registers; ++reg) {
712fe1d0abSChaoren Lin     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
722fe1d0abSChaoren Lin 
73e50f9c41SMartin Storsjö     if (reg_name.equals_insensitive(reg_info->name) ||
74e50f9c41SMartin Storsjö         reg_name.equals_insensitive(reg_info->alt_name))
752fe1d0abSChaoren Lin       return reg_info;
762fe1d0abSChaoren Lin   }
778567f4d4SMichał Górny 
782fe1d0abSChaoren Lin   return nullptr;
792fe1d0abSChaoren Lin }
802fe1d0abSChaoren Lin 
GetRegisterInfo(uint32_t kind,uint32_t num)81b9c1b51eSKate Stone const RegisterInfo *NativeRegisterContext::GetRegisterInfo(uint32_t kind,
82b9c1b51eSKate Stone                                                            uint32_t num) {
832fe1d0abSChaoren Lin   const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num);
842fe1d0abSChaoren Lin   if (reg_num == LLDB_INVALID_REGNUM)
852fe1d0abSChaoren Lin     return nullptr;
862fe1d0abSChaoren Lin   return GetRegisterInfoAtIndex(reg_num);
872fe1d0abSChaoren Lin }
882fe1d0abSChaoren Lin 
GetRegisterName(uint32_t reg)89b9c1b51eSKate Stone const char *NativeRegisterContext::GetRegisterName(uint32_t reg) {
902fe1d0abSChaoren Lin   const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
912fe1d0abSChaoren Lin   if (reg_info)
922fe1d0abSChaoren Lin     return reg_info->name;
932fe1d0abSChaoren Lin   return nullptr;
942fe1d0abSChaoren Lin }
952fe1d0abSChaoren Lin 
GetRegisterSetNameForRegisterAtIndex(uint32_t reg_index) const96b9c1b51eSKate Stone const char *NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex(
97b9c1b51eSKate Stone     uint32_t reg_index) const {
982fe1d0abSChaoren Lin   const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
992fe1d0abSChaoren Lin   if (!reg_info)
1002fe1d0abSChaoren Lin     return nullptr;
1012fe1d0abSChaoren Lin 
102b9c1b51eSKate Stone   for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) {
1032fe1d0abSChaoren Lin     const RegisterSet *const reg_set = GetRegisterSet(set_index);
1042fe1d0abSChaoren Lin     if (!reg_set)
1052fe1d0abSChaoren Lin       continue;
1062fe1d0abSChaoren Lin 
107b9c1b51eSKate Stone     for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers;
108b9c1b51eSKate Stone          ++reg_num_index) {
1092fe1d0abSChaoren Lin       const uint32_t reg_num = reg_set->registers[reg_num_index];
1102fe1d0abSChaoren Lin       // FIXME double check we're checking the right register kind here.
111b9c1b51eSKate Stone       if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num) {
112b9c1b51eSKate Stone         // The given register is a member of this register set.  Return the
113b9c1b51eSKate Stone         // register set name.
1142fe1d0abSChaoren Lin         return reg_set->name;
1152fe1d0abSChaoren Lin       }
1162fe1d0abSChaoren Lin     }
1172fe1d0abSChaoren Lin   }
1182fe1d0abSChaoren Lin 
1192fe1d0abSChaoren Lin   // Didn't find it.
1202fe1d0abSChaoren Lin   return nullptr;
1212fe1d0abSChaoren Lin }
1222fe1d0abSChaoren Lin 
GetPC(lldb::addr_t fail_value)123b9c1b51eSKate Stone lldb::addr_t NativeRegisterContext::GetPC(lldb::addr_t fail_value) {
124a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::Thread);
1252fe1d0abSChaoren Lin 
126b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
127b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_PC);
12863e5fb76SJonas Devlieghere   LLDB_LOGF(log,
12963e5fb76SJonas Devlieghere             "NativeRegisterContext::%s using reg index %" PRIu32
130b9c1b51eSKate Stone             " (default %" PRIu64 ")",
131b9c1b51eSKate Stone             __FUNCTION__, reg, fail_value);
1322fe1d0abSChaoren Lin 
1332fe1d0abSChaoren Lin   const uint64_t retval = ReadRegisterAsUnsigned(reg, fail_value);
1342fe1d0abSChaoren Lin 
13563e5fb76SJonas Devlieghere   LLDB_LOGF(log, "NativeRegisterContext::%s " PRIu32 " retval %" PRIu64,
136b9c1b51eSKate Stone             __FUNCTION__, retval);
1372fe1d0abSChaoren Lin 
1382fe1d0abSChaoren Lin   return retval;
1392fe1d0abSChaoren Lin }
1402fe1d0abSChaoren Lin 
141c60c9452SJaydeep Patil lldb::addr_t
GetPCfromBreakpointLocation(lldb::addr_t fail_value)142b9c1b51eSKate Stone NativeRegisterContext::GetPCfromBreakpointLocation(lldb::addr_t fail_value) {
143c60c9452SJaydeep Patil   return GetPC(fail_value);
144c60c9452SJaydeep Patil }
145c60c9452SJaydeep Patil 
SetPC(lldb::addr_t pc)14697206d57SZachary Turner Status NativeRegisterContext::SetPC(lldb::addr_t pc) {
147b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
148b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_PC);
1492fe1d0abSChaoren Lin   return WriteRegisterFromUnsigned(reg, pc);
1502fe1d0abSChaoren Lin }
1512fe1d0abSChaoren Lin 
GetSP(lldb::addr_t fail_value)152b9c1b51eSKate Stone lldb::addr_t NativeRegisterContext::GetSP(lldb::addr_t fail_value) {
153b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
154b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_SP);
1552fe1d0abSChaoren Lin   return ReadRegisterAsUnsigned(reg, fail_value);
1562fe1d0abSChaoren Lin }
1572fe1d0abSChaoren Lin 
SetSP(lldb::addr_t sp)15897206d57SZachary Turner Status NativeRegisterContext::SetSP(lldb::addr_t sp) {
159b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
160b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_SP);
1612fe1d0abSChaoren Lin   return WriteRegisterFromUnsigned(reg, sp);
1622fe1d0abSChaoren Lin }
1632fe1d0abSChaoren Lin 
GetFP(lldb::addr_t fail_value)164b9c1b51eSKate Stone lldb::addr_t NativeRegisterContext::GetFP(lldb::addr_t fail_value) {
165b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
166b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_FP);
1672fe1d0abSChaoren Lin   return ReadRegisterAsUnsigned(reg, fail_value);
1682fe1d0abSChaoren Lin }
1692fe1d0abSChaoren Lin 
SetFP(lldb::addr_t fp)17097206d57SZachary Turner Status NativeRegisterContext::SetFP(lldb::addr_t fp) {
171b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
172b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_FP);
1732fe1d0abSChaoren Lin   return WriteRegisterFromUnsigned(reg, fp);
1742fe1d0abSChaoren Lin }
1752fe1d0abSChaoren Lin 
GetReturnAddress(lldb::addr_t fail_value)176b9c1b51eSKate Stone lldb::addr_t NativeRegisterContext::GetReturnAddress(lldb::addr_t fail_value) {
177b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
178b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_RA);
179b9c1b51eSKate Stone   return ReadRegisterAsUnsigned(reg, fail_value);
180b9c1b51eSKate Stone }
181b9c1b51eSKate Stone 
GetFlags(lldb::addr_t fail_value)182b9c1b51eSKate Stone lldb::addr_t NativeRegisterContext::GetFlags(lldb::addr_t fail_value) {
183b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
184b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_FLAGS);
1852fe1d0abSChaoren Lin   return ReadRegisterAsUnsigned(reg, fail_value);
1862fe1d0abSChaoren Lin }
1872fe1d0abSChaoren Lin 
1882fe1d0abSChaoren Lin lldb::addr_t
ReadRegisterAsUnsigned(uint32_t reg,lldb::addr_t fail_value)189b9c1b51eSKate Stone NativeRegisterContext::ReadRegisterAsUnsigned(uint32_t reg,
190b9c1b51eSKate Stone                                               lldb::addr_t fail_value) {
1912fe1d0abSChaoren Lin   if (reg != LLDB_INVALID_REGNUM)
1922fe1d0abSChaoren Lin     return ReadRegisterAsUnsigned(GetRegisterInfoAtIndex(reg), fail_value);
1932fe1d0abSChaoren Lin   return fail_value;
1942fe1d0abSChaoren Lin }
1952fe1d0abSChaoren Lin 
1962fe1d0abSChaoren Lin uint64_t
ReadRegisterAsUnsigned(const RegisterInfo * reg_info,lldb::addr_t fail_value)197b9c1b51eSKate Stone NativeRegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info,
198b9c1b51eSKate Stone                                               lldb::addr_t fail_value) {
199a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::Thread);
2002fe1d0abSChaoren Lin 
201b9c1b51eSKate Stone   if (reg_info) {
2022fe1d0abSChaoren Lin     RegisterValue value;
20397206d57SZachary Turner     Status error = ReadRegister(reg_info, value);
204b9c1b51eSKate Stone     if (error.Success()) {
20563e5fb76SJonas Devlieghere       LLDB_LOGF(log,
20663e5fb76SJonas Devlieghere                 "NativeRegisterContext::%s ReadRegister() succeeded, value "
207b9c1b51eSKate Stone                 "%" PRIu64,
208b9c1b51eSKate Stone                 __FUNCTION__, value.GetAsUInt64());
2092fe1d0abSChaoren Lin       return value.GetAsUInt64();
210b9c1b51eSKate Stone     } else {
21163e5fb76SJonas Devlieghere       LLDB_LOGF(log,
21263e5fb76SJonas Devlieghere                 "NativeRegisterContext::%s ReadRegister() failed, error %s",
213b9c1b51eSKate Stone                 __FUNCTION__, error.AsCString());
2142fe1d0abSChaoren Lin     }
215b9c1b51eSKate Stone   } else {
21663e5fb76SJonas Devlieghere     LLDB_LOGF(log, "NativeRegisterContext::%s ReadRegister() null reg_info",
217b9c1b51eSKate Stone               __FUNCTION__);
2182fe1d0abSChaoren Lin   }
2192fe1d0abSChaoren Lin   return fail_value;
2202fe1d0abSChaoren Lin }
2212fe1d0abSChaoren Lin 
WriteRegisterFromUnsigned(uint32_t reg,uint64_t uval)22297206d57SZachary Turner Status NativeRegisterContext::WriteRegisterFromUnsigned(uint32_t reg,
223b9c1b51eSKate Stone                                                         uint64_t uval) {
2242fe1d0abSChaoren Lin   if (reg == LLDB_INVALID_REGNUM)
22597206d57SZachary Turner     return Status("NativeRegisterContext::%s (): reg is invalid", __FUNCTION__);
2262fe1d0abSChaoren Lin   return WriteRegisterFromUnsigned(GetRegisterInfoAtIndex(reg), uval);
2272fe1d0abSChaoren Lin }
2282fe1d0abSChaoren Lin 
22997206d57SZachary Turner Status
WriteRegisterFromUnsigned(const RegisterInfo * reg_info,uint64_t uval)23097206d57SZachary Turner NativeRegisterContext::WriteRegisterFromUnsigned(const RegisterInfo *reg_info,
23197206d57SZachary Turner                                                  uint64_t uval) {
2322fe1d0abSChaoren Lin   assert(reg_info);
2332fe1d0abSChaoren Lin   if (!reg_info)
23497206d57SZachary Turner     return Status("reg_info is nullptr");
2352fe1d0abSChaoren Lin 
2362fe1d0abSChaoren Lin   RegisterValue value;
2372fe1d0abSChaoren Lin   if (!value.SetUInt(uval, reg_info->byte_size))
23897206d57SZachary Turner     return Status("RegisterValue::SetUInt () failed");
2392fe1d0abSChaoren Lin 
2402fe1d0abSChaoren Lin   return WriteRegister(reg_info, value);
2412fe1d0abSChaoren Lin }
2422fe1d0abSChaoren Lin 
GetThreadID() const243b9c1b51eSKate Stone lldb::tid_t NativeRegisterContext::GetThreadID() const {
2442fe1d0abSChaoren Lin   return m_thread.GetID();
2452fe1d0abSChaoren Lin }
2462fe1d0abSChaoren Lin 
NumSupportedHardwareBreakpoints()247b9c1b51eSKate Stone uint32_t NativeRegisterContext::NumSupportedHardwareBreakpoints() { return 0; }
2482fe1d0abSChaoren Lin 
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)249b9c1b51eSKate Stone uint32_t NativeRegisterContext::SetHardwareBreakpoint(lldb::addr_t addr,
250b9c1b51eSKate Stone                                                       size_t size) {
2512fe1d0abSChaoren Lin   return LLDB_INVALID_INDEX32;
2522fe1d0abSChaoren Lin }
2532fe1d0abSChaoren Lin 
ClearAllHardwareBreakpoints()25497206d57SZachary Turner Status NativeRegisterContext::ClearAllHardwareBreakpoints() {
25597206d57SZachary Turner   return Status("not implemented");
256d5ffbad2SOmair Javaid }
257d5ffbad2SOmair Javaid 
ClearHardwareBreakpoint(uint32_t hw_idx)258b9c1b51eSKate Stone bool NativeRegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) {
2592fe1d0abSChaoren Lin   return false;
2602fe1d0abSChaoren Lin }
2612fe1d0abSChaoren Lin 
GetHardwareBreakHitIndex(uint32_t & bp_index,lldb::addr_t trap_addr)26297206d57SZachary Turner Status NativeRegisterContext::GetHardwareBreakHitIndex(uint32_t &bp_index,
263d5ffbad2SOmair Javaid                                                        lldb::addr_t trap_addr) {
264d5ffbad2SOmair Javaid   bp_index = LLDB_INVALID_INDEX32;
26597206d57SZachary Turner   return Status("not implemented");
266d5ffbad2SOmair Javaid }
267d5ffbad2SOmair Javaid 
NumSupportedHardwareWatchpoints()268b9c1b51eSKate Stone uint32_t NativeRegisterContext::NumSupportedHardwareWatchpoints() { return 0; }
2692fe1d0abSChaoren Lin 
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,uint32_t watch_flags)270b9c1b51eSKate Stone uint32_t NativeRegisterContext::SetHardwareWatchpoint(lldb::addr_t addr,
271b9c1b51eSKate Stone                                                       size_t size,
272b9c1b51eSKate Stone                                                       uint32_t watch_flags) {
2732fe1d0abSChaoren Lin   return LLDB_INVALID_INDEX32;
2742fe1d0abSChaoren Lin }
2752fe1d0abSChaoren Lin 
ClearHardwareWatchpoint(uint32_t hw_index)276b9c1b51eSKate Stone bool NativeRegisterContext::ClearHardwareWatchpoint(uint32_t hw_index) {
2772fe1d0abSChaoren Lin   return false;
2782fe1d0abSChaoren Lin }
2792fe1d0abSChaoren Lin 
ClearWatchpointHit(uint32_t hw_index)280dae7b100SMichał Górny Status NativeRegisterContext::ClearWatchpointHit(uint32_t hw_index) {
281dae7b100SMichał Górny   return Status("not implemented");
282dae7b100SMichał Górny }
283dae7b100SMichał Górny 
ClearAllHardwareWatchpoints()28497206d57SZachary Turner Status NativeRegisterContext::ClearAllHardwareWatchpoints() {
28597206d57SZachary Turner   return Status("not implemented");
28618fe6404SChaoren Lin }
28718fe6404SChaoren Lin 
IsWatchpointHit(uint32_t wp_index,bool & is_hit)28897206d57SZachary Turner Status NativeRegisterContext::IsWatchpointHit(uint32_t wp_index, bool &is_hit) {
289c16f5dcaSChaoren Lin   is_hit = false;
29097206d57SZachary Turner   return Status("not implemented");
291eadb2a9eSTamas Berghammer }
292eadb2a9eSTamas Berghammer 
GetWatchpointHitIndex(uint32_t & wp_index,lldb::addr_t trap_addr)29397206d57SZachary Turner Status NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index,
294b9c1b51eSKate Stone                                                     lldb::addr_t trap_addr) {
295c16f5dcaSChaoren Lin   wp_index = LLDB_INVALID_INDEX32;
29697206d57SZachary Turner   return Status("not implemented");
297c16f5dcaSChaoren Lin }
298c16f5dcaSChaoren Lin 
IsWatchpointVacant(uint32_t wp_index,bool & is_vacant)29997206d57SZachary Turner Status NativeRegisterContext::IsWatchpointVacant(uint32_t wp_index,
300b9c1b51eSKate Stone                                                  bool &is_vacant) {
301c16f5dcaSChaoren Lin   is_vacant = false;
30297206d57SZachary Turner   return Status("not implemented");
303eadb2a9eSTamas Berghammer }
304eadb2a9eSTamas Berghammer 
GetWatchpointAddress(uint32_t wp_index)305b9c1b51eSKate Stone lldb::addr_t NativeRegisterContext::GetWatchpointAddress(uint32_t wp_index) {
306eadb2a9eSTamas Berghammer   return LLDB_INVALID_ADDRESS;
307eadb2a9eSTamas Berghammer }
308eadb2a9eSTamas Berghammer 
GetWatchpointHitAddress(uint32_t wp_index)309b9c1b51eSKate Stone lldb::addr_t NativeRegisterContext::GetWatchpointHitAddress(uint32_t wp_index) {
31083143504SJaydeep Patil   return LLDB_INVALID_ADDRESS;
31183143504SJaydeep Patil }
31283143504SJaydeep Patil 
HardwareSingleStep(bool enable)313b9c1b51eSKate Stone bool NativeRegisterContext::HardwareSingleStep(bool enable) { return false; }
3142fe1d0abSChaoren Lin 
ReadRegisterValueFromMemory(const RegisterInfo * reg_info,lldb::addr_t src_addr,size_t src_len,RegisterValue & reg_value)31597206d57SZachary Turner Status NativeRegisterContext::ReadRegisterValueFromMemory(
316b9c1b51eSKate Stone     const RegisterInfo *reg_info, lldb::addr_t src_addr, size_t src_len,
317b9c1b51eSKate Stone     RegisterValue &reg_value) {
31897206d57SZachary Turner   Status error;
319b9c1b51eSKate Stone   if (reg_info == nullptr) {
3202fe1d0abSChaoren Lin     error.SetErrorString("invalid register info argument.");
3212fe1d0abSChaoren Lin     return error;
3222fe1d0abSChaoren Lin   }
3232fe1d0abSChaoren Lin 
3242fe1d0abSChaoren Lin   // Moving from addr into a register
3252fe1d0abSChaoren Lin   //
3262fe1d0abSChaoren Lin   // Case 1: src_len == dst_len
3272fe1d0abSChaoren Lin   //
3282fe1d0abSChaoren Lin   //   |AABBCCDD| Address contents
3292fe1d0abSChaoren Lin   //   |AABBCCDD| Register contents
3302fe1d0abSChaoren Lin   //
3312fe1d0abSChaoren Lin   // Case 2: src_len > dst_len
3322fe1d0abSChaoren Lin   //
33397206d57SZachary Turner   //   Status!  (The register should always be big enough to hold the data)
3342fe1d0abSChaoren Lin   //
3352fe1d0abSChaoren Lin   // Case 3: src_len < dst_len
3362fe1d0abSChaoren Lin   //
3372fe1d0abSChaoren Lin   //   |AABB| Address contents
3382fe1d0abSChaoren Lin   //   |AABB0000| Register contents [on little-endian hardware]
3392fe1d0abSChaoren Lin   //   |0000AABB| Register contents [on big-endian hardware]
340b9c1b51eSKate Stone   if (src_len > RegisterValue::kMaxRegisterByteSize) {
3412fe1d0abSChaoren Lin     error.SetErrorString("register too small to receive memory data");
3422fe1d0abSChaoren Lin     return error;
3432fe1d0abSChaoren Lin   }
3442fe1d0abSChaoren Lin 
3453eb4b458SChaoren Lin   const size_t dst_len = reg_info->byte_size;
3462fe1d0abSChaoren Lin 
347b9c1b51eSKate Stone   if (src_len > dst_len) {
348b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
349b9c1b51eSKate Stone         "%" PRIu64 " bytes is too big to store in register %s (%" PRIu64
350b9c1b51eSKate Stone         " bytes)",
351b9c1b51eSKate Stone         static_cast<uint64_t>(src_len), reg_info->name,
352b9c1b51eSKate Stone         static_cast<uint64_t>(dst_len));
3532fe1d0abSChaoren Lin     return error;
3542fe1d0abSChaoren Lin   }
3552fe1d0abSChaoren Lin 
35682abefa4SPavel Labath   NativeProcessProtocol &process = m_thread.GetProcess();
3572fe1d0abSChaoren Lin   uint8_t src[RegisterValue::kMaxRegisterByteSize];
3582fe1d0abSChaoren Lin 
3592fe1d0abSChaoren Lin   // Read the memory
3603eb4b458SChaoren Lin   size_t bytes_read;
36182abefa4SPavel Labath   error = process.ReadMemory(src_addr, src, src_len, bytes_read);
3622fe1d0abSChaoren Lin   if (error.Fail())
3632fe1d0abSChaoren Lin     return error;
3642fe1d0abSChaoren Lin 
3652fe1d0abSChaoren Lin   // Make sure the memory read succeeded...
366b9c1b51eSKate Stone   if (bytes_read != src_len) {
3672fe1d0abSChaoren Lin     // This might happen if we read _some_ bytes but not all
368b2b3ff18SChaoren Lin     error.SetErrorStringWithFormat("read %" PRIu64 " of %" PRIu64 " bytes",
369b9c1b51eSKate Stone                                    static_cast<uint64_t>(bytes_read),
370b9c1b51eSKate Stone                                    static_cast<uint64_t>(src_len));
3712fe1d0abSChaoren Lin     return error;
3722fe1d0abSChaoren Lin   }
3732fe1d0abSChaoren Lin 
3742fe1d0abSChaoren Lin   // We now have a memory buffer that contains the part or all of the register
3752fe1d0abSChaoren Lin   // value. Set the register value using this memory data.
3762fe1d0abSChaoren Lin   // TODO: we might need to add a parameter to this function in case the byte
37705097246SAdrian Prantl   // order of the memory data doesn't match the process. For now we are
37805097246SAdrian Prantl   // assuming they are the same.
379578a4258SPavel Labath   reg_value.SetFromMemoryData(reg_info, src, src_len, process.GetByteOrder(),
380578a4258SPavel Labath                               error);
3812fe1d0abSChaoren Lin 
3822fe1d0abSChaoren Lin   return error;
3832fe1d0abSChaoren Lin }
3842fe1d0abSChaoren Lin 
WriteRegisterValueToMemory(const RegisterInfo * reg_info,lldb::addr_t dst_addr,size_t dst_len,const RegisterValue & reg_value)38597206d57SZachary Turner Status NativeRegisterContext::WriteRegisterValueToMemory(
386b9c1b51eSKate Stone     const RegisterInfo *reg_info, lldb::addr_t dst_addr, size_t dst_len,
387b9c1b51eSKate Stone     const RegisterValue &reg_value) {
3882fe1d0abSChaoren Lin 
3892fe1d0abSChaoren Lin   uint8_t dst[RegisterValue::kMaxRegisterByteSize];
3902fe1d0abSChaoren Lin 
39197206d57SZachary Turner   Status error;
3922fe1d0abSChaoren Lin 
39382abefa4SPavel Labath   NativeProcessProtocol &process = m_thread.GetProcess();
3942fe1d0abSChaoren Lin 
3952fe1d0abSChaoren Lin   // TODO: we might need to add a parameter to this function in case the byte
396b9c1b51eSKate Stone   // order of the memory data doesn't match the process. For now we are
39705097246SAdrian Prantl   // assuming they are the same.
398578a4258SPavel Labath   const size_t bytes_copied = reg_value.GetAsMemoryData(
399578a4258SPavel Labath       reg_info, dst, dst_len, process.GetByteOrder(), error);
4002fe1d0abSChaoren Lin 
401b9c1b51eSKate Stone   if (error.Success()) {
402b9c1b51eSKate Stone     if (bytes_copied == 0) {
4032fe1d0abSChaoren Lin       error.SetErrorString("byte copy failed.");
404b9c1b51eSKate Stone     } else {
4053eb4b458SChaoren Lin       size_t bytes_written;
40682abefa4SPavel Labath       error = process.WriteMemory(dst_addr, dst, bytes_copied, bytes_written);
4072fe1d0abSChaoren Lin       if (error.Fail())
4082fe1d0abSChaoren Lin         return error;
4092fe1d0abSChaoren Lin 
410b9c1b51eSKate Stone       if (bytes_written != bytes_copied) {
4112fe1d0abSChaoren Lin         // This might happen if we read _some_ bytes but not all
412b9c1b51eSKate Stone         error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64
413b9c1b51eSKate Stone                                        " bytes",
414b9c1b51eSKate Stone                                        static_cast<uint64_t>(bytes_written),
415b9c1b51eSKate Stone                                        static_cast<uint64_t>(bytes_copied));
4162fe1d0abSChaoren Lin       }
4172fe1d0abSChaoren Lin     }
4182fe1d0abSChaoren Lin   }
4192fe1d0abSChaoren Lin 
4202fe1d0abSChaoren Lin   return error;
4212fe1d0abSChaoren Lin }
4222fe1d0abSChaoren Lin 
4232fe1d0abSChaoren Lin uint32_t
ConvertRegisterKindToRegisterNumber(uint32_t kind,uint32_t num) const424b9c1b51eSKate Stone NativeRegisterContext::ConvertRegisterKindToRegisterNumber(uint32_t kind,
425b9c1b51eSKate Stone                                                            uint32_t num) const {
4262fe1d0abSChaoren Lin   const uint32_t num_regs = GetRegisterCount();
4272fe1d0abSChaoren Lin 
4282fe1d0abSChaoren Lin   assert(kind < kNumRegisterKinds);
429b9c1b51eSKate Stone   for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
4302fe1d0abSChaoren Lin     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);
4312fe1d0abSChaoren Lin 
4322fe1d0abSChaoren Lin     if (reg_info->kinds[kind] == num)
4332fe1d0abSChaoren Lin       return reg_idx;
4342fe1d0abSChaoren Lin   }
4352fe1d0abSChaoren Lin 
4362fe1d0abSChaoren Lin   return LLDB_INVALID_REGNUM;
4372fe1d0abSChaoren Lin }
438b69c09bfSMuhammad Omair Javaid 
439b69c09bfSMuhammad Omair Javaid std::vector<uint32_t>
GetExpeditedRegisters(ExpeditedRegs expType) const440b69c09bfSMuhammad Omair Javaid NativeRegisterContext::GetExpeditedRegisters(ExpeditedRegs expType) const {
441b69c09bfSMuhammad Omair Javaid   if (expType == ExpeditedRegs::Minimal) {
442b69c09bfSMuhammad Omair Javaid     // Expedite only a minimum set of important generic registers.
443b69c09bfSMuhammad Omair Javaid     static const uint32_t k_expedited_registers[] = {
444b69c09bfSMuhammad Omair Javaid         LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP,
445b69c09bfSMuhammad Omair Javaid         LLDB_REGNUM_GENERIC_RA};
446b69c09bfSMuhammad Omair Javaid 
447b69c09bfSMuhammad Omair Javaid     std::vector<uint32_t> expedited_reg_nums;
448b69c09bfSMuhammad Omair Javaid     for (uint32_t gen_reg : k_expedited_registers) {
449b69c09bfSMuhammad Omair Javaid       uint32_t reg_num =
450b69c09bfSMuhammad Omair Javaid           ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, gen_reg);
451b69c09bfSMuhammad Omair Javaid       if (reg_num == LLDB_INVALID_REGNUM)
452b69c09bfSMuhammad Omair Javaid         continue; // Target does not support the given register.
453b69c09bfSMuhammad Omair Javaid       else
454b69c09bfSMuhammad Omair Javaid         expedited_reg_nums.push_back(reg_num);
455b69c09bfSMuhammad Omair Javaid     }
456b69c09bfSMuhammad Omair Javaid 
457b69c09bfSMuhammad Omair Javaid     return expedited_reg_nums;
458b69c09bfSMuhammad Omair Javaid   }
459b69c09bfSMuhammad Omair Javaid 
460b69c09bfSMuhammad Omair Javaid   if (GetRegisterSetCount() > 0 && expType == ExpeditedRegs::Full)
461b69c09bfSMuhammad Omair Javaid     return std::vector<uint32_t>(GetRegisterSet(0)->registers,
462b69c09bfSMuhammad Omair Javaid                                  GetRegisterSet(0)->registers +
463b69c09bfSMuhammad Omair Javaid                                      GetRegisterSet(0)->num_registers);
464b69c09bfSMuhammad Omair Javaid 
465b69c09bfSMuhammad Omair Javaid   return std::vector<uint32_t>();
466b69c09bfSMuhammad Omair Javaid }
467