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 ®_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 ®_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