180814287SRaphael Isemann //===-- RegisterContext.cpp -----------------------------------------------===//
230fdc8d8SChris Lattner //
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
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
930fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
10b9c1b51eSKate Stone #include "lldb/Core/Module.h"
11b9c1b51eSKate Stone #include "lldb/Core/Value.h"
12b9c1b51eSKate Stone #include "lldb/Expression/DWARFExpression.h"
1330fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h"
143e06bd90SGreg Clayton #include "lldb/Target/Process.h"
15b9c1b51eSKate Stone #include "lldb/Target/StackFrame.h"
1644d07fccSJaydeep Patil #include "lldb/Target/Target.h"
17b9c1b51eSKate Stone #include "lldb/Target/Thread.h"
18666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h"
1901c3243fSZachary Turner #include "lldb/Utility/Endian.h"
20d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h"
21d821c997SPavel Labath #include "lldb/Utility/Scalar.h"
2230fdc8d8SChris Lattner 
2330fdc8d8SChris Lattner using namespace lldb;
2430fdc8d8SChris Lattner using namespace lldb_private;
2530fdc8d8SChris Lattner 
RegisterContext(Thread & thread,uint32_t concrete_frame_idx)26b9c1b51eSKate Stone RegisterContext::RegisterContext(Thread &thread, uint32_t concrete_frame_idx)
27b9c1b51eSKate Stone     : m_thread(thread), m_concrete_frame_idx(concrete_frame_idx),
28b9c1b51eSKate Stone       m_stop_id(thread.GetProcess()->GetStopID()) {}
29ab4f1924SJason Molenda 
309394d772SEugene Zelenko RegisterContext::~RegisterContext() = default;
3130fdc8d8SChris Lattner 
InvalidateIfNeeded(bool force)32b9c1b51eSKate Stone void RegisterContext::InvalidateIfNeeded(bool force) {
331ac04c30SGreg Clayton   ProcessSP process_sp(m_thread.GetProcess());
341ac04c30SGreg Clayton   bool invalidate = force;
351ac04c30SGreg Clayton   uint32_t process_stop_id = UINT32_MAX;
361ac04c30SGreg Clayton 
371ac04c30SGreg Clayton   if (process_sp)
381ac04c30SGreg Clayton     process_stop_id = process_sp->GetStopID();
391ac04c30SGreg Clayton   else
401ac04c30SGreg Clayton     invalidate = true;
411ac04c30SGreg Clayton 
421ac04c30SGreg Clayton   if (!invalidate)
431ac04c30SGreg Clayton     invalidate = process_stop_id != GetStopID();
441ac04c30SGreg Clayton 
45b9c1b51eSKate Stone   if (invalidate) {
463e06bd90SGreg Clayton     InvalidateAllRegisters();
473e06bd90SGreg Clayton     SetStopID(process_stop_id);
483e06bd90SGreg Clayton   }
493e06bd90SGreg Clayton }
503e06bd90SGreg Clayton 
51e00e64caSZachary Turner const RegisterInfo *
GetRegisterInfoByName(llvm::StringRef reg_name,uint32_t start_idx)52e00e64caSZachary Turner RegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name,
53b9c1b51eSKate Stone                                        uint32_t start_idx) {
54e00e64caSZachary Turner   if (reg_name.empty())
55e00e64caSZachary Turner     return nullptr;
56e00e64caSZachary Turner 
57*8567f4d4SMichał Górny   // Generic register names take precedence over specific register names.
58*8567f4d4SMichał Górny   // For example, on x86 we want "sp" to refer to the complete RSP/ESP register
59*8567f4d4SMichał Górny   // rather than the 16-bit SP pseudo-register.
60*8567f4d4SMichał Górny   uint32_t generic_reg = Args::StringToGenericRegister(reg_name);
61*8567f4d4SMichał Górny   if (generic_reg != LLDB_INVALID_REGNUM) {
62*8567f4d4SMichał Górny     const RegisterInfo *reg_info =
63*8567f4d4SMichał Górny         GetRegisterInfo(eRegisterKindGeneric, generic_reg);
64*8567f4d4SMichał Górny     if (reg_info)
65*8567f4d4SMichał Górny       return reg_info;
66*8567f4d4SMichał Górny   }
67*8567f4d4SMichał Górny 
6830fdc8d8SChris Lattner   const uint32_t num_registers = GetRegisterCount();
69b9c1b51eSKate Stone   for (uint32_t reg = start_idx; reg < num_registers; ++reg) {
7030fdc8d8SChris Lattner     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
7130fdc8d8SChris Lattner 
72e50f9c41SMartin Storsjö     if (reg_name.equals_insensitive(reg_info->name) ||
73e50f9c41SMartin Storsjö         reg_name.equals_insensitive(reg_info->alt_name))
7430fdc8d8SChris Lattner       return reg_info;
7530fdc8d8SChris Lattner   }
76*8567f4d4SMichał Górny 
779394d772SEugene Zelenko   return nullptr;
7830fdc8d8SChris Lattner }
7930fdc8d8SChris Lattner 
GetRegisterInfo(lldb::RegisterKind kind,uint32_t num)80b9c1b51eSKate Stone const RegisterInfo *RegisterContext::GetRegisterInfo(lldb::RegisterKind kind,
81b9c1b51eSKate Stone                                                      uint32_t num) {
82bb3a9b74SGreg Clayton   const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num);
83bb3a9b74SGreg Clayton   if (reg_num == LLDB_INVALID_REGNUM)
849394d772SEugene Zelenko     return nullptr;
85bb3a9b74SGreg Clayton   return GetRegisterInfoAtIndex(reg_num);
86bb3a9b74SGreg Clayton }
87bb3a9b74SGreg Clayton 
GetRegisterName(uint32_t reg)88b9c1b51eSKate Stone const char *RegisterContext::GetRegisterName(uint32_t reg) {
8930fdc8d8SChris Lattner   const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
9030fdc8d8SChris Lattner   if (reg_info)
9130fdc8d8SChris Lattner     return reg_info->name;
929394d772SEugene Zelenko   return nullptr;
9330fdc8d8SChris Lattner }
9430fdc8d8SChris Lattner 
GetPC(uint64_t fail_value)95b9c1b51eSKate Stone uint64_t RegisterContext::GetPC(uint64_t fail_value) {
96b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
97b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_PC);
9844d07fccSJaydeep Patil   uint64_t pc = ReadRegisterAsUnsigned(reg, fail_value);
9944d07fccSJaydeep Patil 
100b9c1b51eSKate Stone   if (pc != fail_value) {
10144d07fccSJaydeep Patil     TargetSP target_sp = m_thread.CalculateTarget();
102b9c1b51eSKate Stone     if (target_sp) {
10344d07fccSJaydeep Patil       Target *target = target_sp.get();
10444d07fccSJaydeep Patil       if (target)
10504803b3eSTatyana Krasnukha         pc = target->GetOpcodeLoadAddress(pc, AddressClass::eCode);
10644d07fccSJaydeep Patil     }
10744d07fccSJaydeep Patil   }
10844d07fccSJaydeep Patil 
10944d07fccSJaydeep Patil   return pc;
11030fdc8d8SChris Lattner }
11130fdc8d8SChris Lattner 
SetPC(uint64_t pc)112b9c1b51eSKate Stone bool RegisterContext::SetPC(uint64_t pc) {
113b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
114b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_PC);
11530fdc8d8SChris Lattner   bool success = WriteRegisterFromUnsigned(reg, pc);
116b9c1b51eSKate Stone   if (success) {
117b9c1b51eSKate Stone     StackFrameSP frame_sp(
118b9c1b51eSKate Stone         m_thread.GetFrameWithConcreteFrameIndex(m_concrete_frame_idx));
1195ccbd294SGreg Clayton     if (frame_sp)
1205ccbd294SGreg Clayton       frame_sp->ChangePC(pc);
12130fdc8d8SChris Lattner     else
12230fdc8d8SChris Lattner       m_thread.ClearStackFrames();
12330fdc8d8SChris Lattner   }
12430fdc8d8SChris Lattner   return success;
12530fdc8d8SChris Lattner }
12630fdc8d8SChris Lattner 
GetPCForSymbolication(Address & address)127266bb78fSJason Molenda bool RegisterContext::GetPCForSymbolication(Address &address) {
128266bb78fSJason Molenda   addr_t pc = GetPC(LLDB_INVALID_ADDRESS);
129266bb78fSJason Molenda   if (pc == LLDB_INVALID_ADDRESS)
130266bb78fSJason Molenda     return false;
131266bb78fSJason Molenda   TargetSP target_sp = m_thread.CalculateTarget();
132266bb78fSJason Molenda   if (!target_sp.get())
133266bb78fSJason Molenda     return false;
134266bb78fSJason Molenda 
135266bb78fSJason Molenda   if (!BehavesLikeZerothFrame() && pc != 0)
136266bb78fSJason Molenda     pc--;
137266bb78fSJason Molenda   address.SetLoadAddress(pc, target_sp.get());
138266bb78fSJason Molenda   return true;
139266bb78fSJason Molenda }
140266bb78fSJason Molenda 
SetPC(Address addr)141b9c1b51eSKate Stone bool RegisterContext::SetPC(Address addr) {
142f86248d9SRichard Mitton   TargetSP target_sp = m_thread.CalculateTarget();
143f86248d9SRichard Mitton   Target *target = target_sp.get();
144f86248d9SRichard Mitton 
145f86248d9SRichard Mitton   lldb::addr_t callAddr = addr.GetCallableLoadAddress(target);
146f86248d9SRichard Mitton   if (callAddr == LLDB_INVALID_ADDRESS)
147f86248d9SRichard Mitton     return false;
148f86248d9SRichard Mitton 
149f86248d9SRichard Mitton   return SetPC(callAddr);
150f86248d9SRichard Mitton }
151f86248d9SRichard Mitton 
GetSP(uint64_t fail_value)152b9c1b51eSKate Stone uint64_t RegisterContext::GetSP(uint64_t fail_value) {
153b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
154b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_SP);
15530fdc8d8SChris Lattner   return ReadRegisterAsUnsigned(reg, fail_value);
15630fdc8d8SChris Lattner }
15730fdc8d8SChris Lattner 
SetSP(uint64_t sp)158b9c1b51eSKate Stone bool RegisterContext::SetSP(uint64_t sp) {
159b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
160b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_SP);
16130fdc8d8SChris Lattner   return WriteRegisterFromUnsigned(reg, sp);
16230fdc8d8SChris Lattner }
16330fdc8d8SChris Lattner 
GetFP(uint64_t fail_value)164b9c1b51eSKate Stone uint64_t RegisterContext::GetFP(uint64_t fail_value) {
165b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
166b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_FP);
16730fdc8d8SChris Lattner   return ReadRegisterAsUnsigned(reg, fail_value);
16830fdc8d8SChris Lattner }
16930fdc8d8SChris Lattner 
SetFP(uint64_t fp)170b9c1b51eSKate Stone bool RegisterContext::SetFP(uint64_t fp) {
171b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
172b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_FP);
17330fdc8d8SChris Lattner   return WriteRegisterFromUnsigned(reg, fp);
17430fdc8d8SChris Lattner }
17530fdc8d8SChris Lattner 
GetReturnAddress(uint64_t fail_value)176b9c1b51eSKate Stone uint64_t RegisterContext::GetReturnAddress(uint64_t fail_value) {
177b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
178b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_RA);
17930fdc8d8SChris Lattner   return ReadRegisterAsUnsigned(reg, fail_value);
18030fdc8d8SChris Lattner }
18130fdc8d8SChris Lattner 
GetFlags(uint64_t fail_value)182b9c1b51eSKate Stone uint64_t RegisterContext::GetFlags(uint64_t fail_value) {
183b9c1b51eSKate Stone   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
184b9c1b51eSKate Stone                                                      LLDB_REGNUM_GENERIC_FLAGS);
18530fdc8d8SChris Lattner   return ReadRegisterAsUnsigned(reg, fail_value);
18630fdc8d8SChris Lattner }
18730fdc8d8SChris Lattner 
ReadRegisterAsUnsigned(uint32_t reg,uint64_t fail_value)188b9c1b51eSKate Stone uint64_t RegisterContext::ReadRegisterAsUnsigned(uint32_t reg,
189b9c1b51eSKate Stone                                                  uint64_t fail_value) {
19030fdc8d8SChris Lattner   if (reg != LLDB_INVALID_REGNUM)
19170b57657SGreg Clayton     return ReadRegisterAsUnsigned(GetRegisterInfoAtIndex(reg), fail_value);
19270b57657SGreg Clayton   return fail_value;
19370b57657SGreg Clayton }
19470b57657SGreg Clayton 
ReadRegisterAsUnsigned(const RegisterInfo * reg_info,uint64_t fail_value)195b9c1b51eSKate Stone uint64_t RegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info,
196b9c1b51eSKate Stone                                                  uint64_t fail_value) {
197b9c1b51eSKate Stone   if (reg_info) {
1987349bd90SGreg Clayton     RegisterValue value;
1997349bd90SGreg Clayton     if (ReadRegister(reg_info, value))
2007349bd90SGreg Clayton       return value.GetAsUInt64();
2017349bd90SGreg Clayton   }
20230fdc8d8SChris Lattner   return fail_value;
20330fdc8d8SChris Lattner }
20430fdc8d8SChris Lattner 
WriteRegisterFromUnsigned(uint32_t reg,uint64_t uval)205b9c1b51eSKate Stone bool RegisterContext::WriteRegisterFromUnsigned(uint32_t reg, uint64_t uval) {
20630fdc8d8SChris Lattner   if (reg == LLDB_INVALID_REGNUM)
20730fdc8d8SChris Lattner     return false;
20870b57657SGreg Clayton   return WriteRegisterFromUnsigned(GetRegisterInfoAtIndex(reg), uval);
20970b57657SGreg Clayton }
21070b57657SGreg Clayton 
WriteRegisterFromUnsigned(const RegisterInfo * reg_info,uint64_t uval)211b9c1b51eSKate Stone bool RegisterContext::WriteRegisterFromUnsigned(const RegisterInfo *reg_info,
212b9c1b51eSKate Stone                                                 uint64_t uval) {
213b9c1b51eSKate Stone   if (reg_info) {
2147349bd90SGreg Clayton     RegisterValue value;
2157349bd90SGreg Clayton     if (value.SetUInt(uval, reg_info->byte_size))
2167349bd90SGreg Clayton       return WriteRegister(reg_info, value);
2177349bd90SGreg Clayton   }
2187349bd90SGreg Clayton   return false;
21930fdc8d8SChris Lattner }
22030fdc8d8SChris Lattner 
CopyFromRegisterContext(lldb::RegisterContextSP context)221b9c1b51eSKate Stone bool RegisterContext::CopyFromRegisterContext(lldb::RegisterContextSP context) {
222cb640dd8SJim Ingham   uint32_t num_register_sets = context->GetRegisterSetCount();
223b9c1b51eSKate Stone   // We don't know that two threads have the same register context, so require
224b9c1b51eSKate Stone   // the threads to be the same.
225cb640dd8SJim Ingham   if (context->GetThreadID() != GetThreadID())
226cb640dd8SJim Ingham     return false;
227cb640dd8SJim Ingham 
228cb640dd8SJim Ingham   if (num_register_sets != GetRegisterSetCount())
229cb640dd8SJim Ingham     return false;
230cb640dd8SJim Ingham 
231cb640dd8SJim Ingham   RegisterContextSP frame_zero_context = m_thread.GetRegisterContext();
232cb640dd8SJim Ingham 
233b9c1b51eSKate Stone   for (uint32_t set_idx = 0; set_idx < num_register_sets; ++set_idx) {
234cb640dd8SJim Ingham     const RegisterSet *const reg_set = GetRegisterSet(set_idx);
235cb640dd8SJim Ingham 
236cb640dd8SJim Ingham     const uint32_t num_registers = reg_set->num_registers;
237b9c1b51eSKate Stone     for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
238cb640dd8SJim Ingham       const uint32_t reg = reg_set->registers[reg_idx];
239cb640dd8SJim Ingham       const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
240cb640dd8SJim Ingham       if (!reg_info || reg_info->value_regs)
241cb640dd8SJim Ingham         continue;
242cb640dd8SJim Ingham       RegisterValue reg_value;
243cb640dd8SJim Ingham 
244b9c1b51eSKate Stone       // If we can reconstruct the register from the frame we are copying from,
24505097246SAdrian Prantl       // then do so, otherwise use the value from frame 0.
246b9c1b51eSKate Stone       if (context->ReadRegister(reg_info, reg_value)) {
247cb640dd8SJim Ingham         WriteRegister(reg_info, reg_value);
248b9c1b51eSKate Stone       } else if (frame_zero_context->ReadRegister(reg_info, reg_value)) {
249cb640dd8SJim Ingham         WriteRegister(reg_info, reg_value);
250cb640dd8SJim Ingham       }
251cb640dd8SJim Ingham     }
252cb640dd8SJim Ingham   }
253cb640dd8SJim Ingham   return true;
254cb640dd8SJim Ingham }
255cb640dd8SJim Ingham 
GetThreadID() const256b9c1b51eSKate Stone lldb::tid_t RegisterContext::GetThreadID() const { return m_thread.GetID(); }
25730fdc8d8SChris Lattner 
NumSupportedHardwareBreakpoints()258b9c1b51eSKate Stone uint32_t RegisterContext::NumSupportedHardwareBreakpoints() { return 0; }
25930fdc8d8SChris Lattner 
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)260b9c1b51eSKate Stone uint32_t RegisterContext::SetHardwareBreakpoint(lldb::addr_t addr,
261b9c1b51eSKate Stone                                                 size_t size) {
26230fdc8d8SChris Lattner   return LLDB_INVALID_INDEX32;
26330fdc8d8SChris Lattner }
26430fdc8d8SChris Lattner 
2656c455329SMuhammad Omair Javaid // Used when parsing DWARF and EH frame information and any other object file
2666c455329SMuhammad Omair Javaid // sections that contain register numbers in them.
2676c455329SMuhammad Omair Javaid uint32_t
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)2686c455329SMuhammad Omair Javaid RegisterContext::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
2696c455329SMuhammad Omair Javaid                                                      uint32_t num) {
2706c455329SMuhammad Omair Javaid   const uint32_t num_regs = GetRegisterCount();
2716c455329SMuhammad Omair Javaid 
2726c455329SMuhammad Omair Javaid   assert(kind < kNumRegisterKinds);
2736c455329SMuhammad Omair Javaid   for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
2746c455329SMuhammad Omair Javaid     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);
2756c455329SMuhammad Omair Javaid 
2766c455329SMuhammad Omair Javaid     if (reg_info->kinds[kind] == num)
2776c455329SMuhammad Omair Javaid       return reg_idx;
2786c455329SMuhammad Omair Javaid   }
2796c455329SMuhammad Omair Javaid 
2806c455329SMuhammad Omair Javaid   return LLDB_INVALID_REGNUM;
2816c455329SMuhammad Omair Javaid }
2826c455329SMuhammad Omair Javaid 
ClearHardwareBreakpoint(uint32_t hw_idx)283b9c1b51eSKate Stone bool RegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) { return false; }
28430fdc8d8SChris Lattner 
NumSupportedHardwareWatchpoints()285b9c1b51eSKate Stone uint32_t RegisterContext::NumSupportedHardwareWatchpoints() { return 0; }
28630fdc8d8SChris Lattner 
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)287b9c1b51eSKate Stone uint32_t RegisterContext::SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
288b9c1b51eSKate Stone                                                 bool read, bool write) {
28930fdc8d8SChris Lattner   return LLDB_INVALID_INDEX32;
29030fdc8d8SChris Lattner }
29130fdc8d8SChris Lattner 
ClearHardwareWatchpoint(uint32_t hw_index)292b9c1b51eSKate Stone bool RegisterContext::ClearHardwareWatchpoint(uint32_t hw_index) {
29330fdc8d8SChris Lattner   return false;
29430fdc8d8SChris Lattner }
29530fdc8d8SChris Lattner 
HardwareSingleStep(bool enable)296b9c1b51eSKate Stone bool RegisterContext::HardwareSingleStep(bool enable) { return false; }
29730fdc8d8SChris Lattner 
ReadRegisterValueFromMemory(const RegisterInfo * reg_info,lldb::addr_t src_addr,uint32_t src_len,RegisterValue & reg_value)29897206d57SZachary Turner Status RegisterContext::ReadRegisterValueFromMemory(
29997206d57SZachary Turner     const RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len,
300b9c1b51eSKate Stone     RegisterValue &reg_value) {
30197206d57SZachary Turner   Status error;
302b9c1b51eSKate Stone   if (reg_info == nullptr) {
3037349bd90SGreg Clayton     error.SetErrorString("invalid register info argument.");
3047349bd90SGreg Clayton     return error;
3057349bd90SGreg Clayton   }
3067349bd90SGreg Clayton 
3077349bd90SGreg Clayton   // Moving from addr into a register
3087349bd90SGreg Clayton   //
3097349bd90SGreg Clayton   // Case 1: src_len == dst_len
3107349bd90SGreg Clayton   //
3117349bd90SGreg Clayton   //   |AABBCCDD| Address contents
3127349bd90SGreg Clayton   //   |AABBCCDD| Register contents
3137349bd90SGreg Clayton   //
3147349bd90SGreg Clayton   // Case 2: src_len > dst_len
3157349bd90SGreg Clayton   //
31697206d57SZachary Turner   //   Status!  (The register should always be big enough to hold the data)
3177349bd90SGreg Clayton   //
3187349bd90SGreg Clayton   // Case 3: src_len < dst_len
3197349bd90SGreg Clayton   //
3207349bd90SGreg Clayton   //   |AABB| Address contents
3217349bd90SGreg Clayton   //   |AABB0000| Register contents [on little-endian hardware]
3227349bd90SGreg Clayton   //   |0000AABB| Register contents [on big-endian hardware]
323b9c1b51eSKate Stone   if (src_len > RegisterValue::kMaxRegisterByteSize) {
3247349bd90SGreg Clayton     error.SetErrorString("register too small to receive memory data");
3257349bd90SGreg Clayton     return error;
3267349bd90SGreg Clayton   }
3277349bd90SGreg Clayton 
3287349bd90SGreg Clayton   const uint32_t dst_len = reg_info->byte_size;
3297349bd90SGreg Clayton 
330b9c1b51eSKate Stone   if (src_len > dst_len) {
331b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
332b9c1b51eSKate Stone         "%u bytes is too big to store in register %s (%u bytes)", src_len,
333b9c1b51eSKate Stone         reg_info->name, dst_len);
3347349bd90SGreg Clayton     return error;
3357349bd90SGreg Clayton   }
3367349bd90SGreg Clayton 
3371ac04c30SGreg Clayton   ProcessSP process_sp(m_thread.GetProcess());
338b9c1b51eSKate Stone   if (process_sp) {
3397349bd90SGreg Clayton     uint8_t src[RegisterValue::kMaxRegisterByteSize];
3407349bd90SGreg Clayton 
3417349bd90SGreg Clayton     // Read the memory
342b9c1b51eSKate Stone     const uint32_t bytes_read =
343b9c1b51eSKate Stone         process_sp->ReadMemory(src_addr, src, src_len, error);
3447349bd90SGreg Clayton 
3457349bd90SGreg Clayton     // Make sure the memory read succeeded...
346b9c1b51eSKate Stone     if (bytes_read != src_len) {
347b9c1b51eSKate Stone       if (error.Success()) {
3487349bd90SGreg Clayton         // This might happen if we read _some_ bytes but not all
349b9c1b51eSKate Stone         error.SetErrorStringWithFormat("read %u of %u bytes", bytes_read,
350b9c1b51eSKate Stone                                        src_len);
3517349bd90SGreg Clayton       }
3527349bd90SGreg Clayton       return error;
3537349bd90SGreg Clayton     }
3547349bd90SGreg Clayton 
35505097246SAdrian Prantl     // We now have a memory buffer that contains the part or all of the
35605097246SAdrian Prantl     // register value. Set the register value using this memory data.
3577349bd90SGreg Clayton     // TODO: we might need to add a parameter to this function in case the byte
358b9c1b51eSKate Stone     // order of the memory data doesn't match the process. For now we are
35905097246SAdrian Prantl     // assuming they are the same.
360b9c1b51eSKate Stone     reg_value.SetFromMemoryData(reg_info, src, src_len,
361b9c1b51eSKate Stone                                 process_sp->GetByteOrder(), error);
362b9c1b51eSKate Stone   } else
3631ac04c30SGreg Clayton     error.SetErrorString("invalid process");
3641ac04c30SGreg Clayton 
3657349bd90SGreg Clayton   return error;
3667349bd90SGreg Clayton }
3677349bd90SGreg Clayton 
WriteRegisterValueToMemory(const RegisterInfo * reg_info,lldb::addr_t dst_addr,uint32_t dst_len,const RegisterValue & reg_value)36897206d57SZachary Turner Status RegisterContext::WriteRegisterValueToMemory(
369b9c1b51eSKate Stone     const RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len,
370b9c1b51eSKate Stone     const RegisterValue &reg_value) {
3717349bd90SGreg Clayton   uint8_t dst[RegisterValue::kMaxRegisterByteSize];
3727349bd90SGreg Clayton 
37397206d57SZachary Turner   Status error;
3747349bd90SGreg Clayton 
3751ac04c30SGreg Clayton   ProcessSP process_sp(m_thread.GetProcess());
376b9c1b51eSKate Stone   if (process_sp) {
3777349bd90SGreg Clayton 
3787349bd90SGreg Clayton     // TODO: we might need to add a parameter to this function in case the byte
379b9c1b51eSKate Stone     // order of the memory data doesn't match the process. For now we are
38005097246SAdrian Prantl     // assuming they are the same.
3817349bd90SGreg Clayton 
382b9c1b51eSKate Stone     const uint32_t bytes_copied = reg_value.GetAsMemoryData(
383b9c1b51eSKate Stone         reg_info, dst, dst_len, process_sp->GetByteOrder(), error);
3847349bd90SGreg Clayton 
385b9c1b51eSKate Stone     if (error.Success()) {
386b9c1b51eSKate Stone       if (bytes_copied == 0) {
3877349bd90SGreg Clayton         error.SetErrorString("byte copy failed.");
388b9c1b51eSKate Stone       } else {
389b9c1b51eSKate Stone         const uint32_t bytes_written =
390b9c1b51eSKate Stone             process_sp->WriteMemory(dst_addr, dst, bytes_copied, error);
391b9c1b51eSKate Stone         if (bytes_written != bytes_copied) {
392b9c1b51eSKate Stone           if (error.Success()) {
3937349bd90SGreg Clayton             // This might happen if we read _some_ bytes but not all
394b9c1b51eSKate Stone             error.SetErrorStringWithFormat("only wrote %u of %u bytes",
395b9c1b51eSKate Stone                                            bytes_written, bytes_copied);
3967349bd90SGreg Clayton           }
3977349bd90SGreg Clayton         }
3987349bd90SGreg Clayton       }
3997349bd90SGreg Clayton     }
400b9c1b51eSKate Stone   } else
4011ac04c30SGreg Clayton     error.SetErrorString("invalid process");
4027349bd90SGreg Clayton 
4037349bd90SGreg Clayton   return error;
4047349bd90SGreg Clayton }
4057349bd90SGreg Clayton 
GetByteOrder()4066c455329SMuhammad Omair Javaid lldb::ByteOrder RegisterContext::GetByteOrder() {
4076c455329SMuhammad Omair Javaid   // Get the target process whose privileged thread was used for the register
4086c455329SMuhammad Omair Javaid   // read.
4096c455329SMuhammad Omair Javaid   lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
4106c455329SMuhammad Omair Javaid   lldb_private::Process *process = CalculateProcess().get();
4116c455329SMuhammad Omair Javaid 
4126c455329SMuhammad Omair Javaid   if (process)
4136c455329SMuhammad Omair Javaid     byte_order = process->GetByteOrder();
4146c455329SMuhammad Omair Javaid   return byte_order;
4156c455329SMuhammad Omair Javaid }
4166c455329SMuhammad Omair Javaid 
ReadAllRegisterValues(lldb_private::RegisterCheckpoint & reg_checkpoint)417b9c1b51eSKate Stone bool RegisterContext::ReadAllRegisterValues(
418b9c1b51eSKate Stone     lldb_private::RegisterCheckpoint &reg_checkpoint) {
419f74cf86bSGreg Clayton   return ReadAllRegisterValues(reg_checkpoint.GetData());
420f74cf86bSGreg Clayton }
421f74cf86bSGreg Clayton 
WriteAllRegisterValues(const lldb_private::RegisterCheckpoint & reg_checkpoint)422b9c1b51eSKate Stone bool RegisterContext::WriteAllRegisterValues(
423b9c1b51eSKate Stone     const lldb_private::RegisterCheckpoint &reg_checkpoint) {
424f74cf86bSGreg Clayton   return WriteAllRegisterValues(reg_checkpoint.GetData());
425f74cf86bSGreg Clayton }
426f74cf86bSGreg Clayton 
CalculateTarget()427b9c1b51eSKate Stone TargetSP RegisterContext::CalculateTarget() {
42830fdc8d8SChris Lattner   return m_thread.CalculateTarget();
42930fdc8d8SChris Lattner }
43030fdc8d8SChris Lattner 
CalculateProcess()431b9c1b51eSKate Stone ProcessSP RegisterContext::CalculateProcess() {
43230fdc8d8SChris Lattner   return m_thread.CalculateProcess();
43330fdc8d8SChris Lattner }
43430fdc8d8SChris Lattner 
CalculateThread()435b9c1b51eSKate Stone ThreadSP RegisterContext::CalculateThread() {
436d9e416c0SGreg Clayton   return m_thread.shared_from_this();
43730fdc8d8SChris Lattner }
43830fdc8d8SChris Lattner 
CalculateStackFrame()439b9c1b51eSKate Stone StackFrameSP RegisterContext::CalculateStackFrame() {
44005097246SAdrian Prantl   // Register contexts might belong to many frames if we have inlined functions
44105097246SAdrian Prantl   // inside a frame since all inlined functions share the same registers, so we
44205097246SAdrian Prantl   // can't definitively say which frame we come from...
443b57e4a1bSJason Molenda   return StackFrameSP();
44430fdc8d8SChris Lattner }
44530fdc8d8SChris Lattner 
CalculateExecutionContext(ExecutionContext & exe_ctx)446b9c1b51eSKate Stone void RegisterContext::CalculateExecutionContext(ExecutionContext &exe_ctx) {
4470603aa9dSGreg Clayton   m_thread.CalculateExecutionContext(exe_ctx);
44830fdc8d8SChris Lattner }
44930fdc8d8SChris Lattner 
ConvertBetweenRegisterKinds(lldb::RegisterKind source_rk,uint32_t source_regnum,lldb::RegisterKind target_rk,uint32_t & target_regnum)450b9c1b51eSKate Stone bool RegisterContext::ConvertBetweenRegisterKinds(lldb::RegisterKind source_rk,
451b9c1b51eSKate Stone                                                   uint32_t source_regnum,
452b9c1b51eSKate Stone                                                   lldb::RegisterKind target_rk,
453b9c1b51eSKate Stone                                                   uint32_t &target_regnum) {
454fbcb7f2cSJason Molenda   const uint32_t num_registers = GetRegisterCount();
455b9c1b51eSKate Stone   for (uint32_t reg = 0; reg < num_registers; ++reg) {
456fbcb7f2cSJason Molenda     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
45730fdc8d8SChris Lattner 
458b9c1b51eSKate Stone     if (reg_info->kinds[source_rk] == source_regnum) {
459fbcb7f2cSJason Molenda       target_regnum = reg_info->kinds[target_rk];
4609394d772SEugene Zelenko       return (target_regnum != LLDB_INVALID_REGNUM);
461fbcb7f2cSJason Molenda     }
462fbcb7f2cSJason Molenda   }
463fbcb7f2cSJason Molenda   return false;
464fbcb7f2cSJason Molenda }
465