xref: /src/contrib/llvm-project/lldb/source/Target/RegisterContext.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1cfca06d7SDimitry Andric //===-- RegisterContext.cpp -----------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
1014f1b3e8SDimitry Andric #include "lldb/Core/Module.h"
1114f1b3e8SDimitry Andric #include "lldb/Core/Value.h"
1214f1b3e8SDimitry Andric #include "lldb/Expression/DWARFExpression.h"
13f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
14f034231aSEd Maste #include "lldb/Target/Process.h"
1514f1b3e8SDimitry Andric #include "lldb/Target/StackFrame.h"
16e81d9d49SDimitry Andric #include "lldb/Target/Target.h"
1714f1b3e8SDimitry Andric #include "lldb/Target/Thread.h"
1874a628f7SDimitry Andric #include "lldb/Utility/DataExtractor.h"
1974a628f7SDimitry Andric #include "lldb/Utility/Endian.h"
2094994d37SDimitry Andric #include "lldb/Utility/RegisterValue.h"
2194994d37SDimitry Andric #include "lldb/Utility/Scalar.h"
22f034231aSEd Maste 
23f034231aSEd Maste using namespace lldb;
24f034231aSEd Maste using namespace lldb_private;
25f034231aSEd Maste 
RegisterContext(Thread & thread,uint32_t concrete_frame_idx)2614f1b3e8SDimitry Andric RegisterContext::RegisterContext(Thread &thread, uint32_t concrete_frame_idx)
2714f1b3e8SDimitry Andric     : m_thread(thread), m_concrete_frame_idx(concrete_frame_idx),
2814f1b3e8SDimitry Andric       m_stop_id(thread.GetProcess()->GetStopID()) {}
29f034231aSEd Maste 
30f3fbd1c0SDimitry Andric RegisterContext::~RegisterContext() = default;
31f034231aSEd Maste 
InvalidateIfNeeded(bool force)3214f1b3e8SDimitry Andric void RegisterContext::InvalidateIfNeeded(bool force) {
33f034231aSEd Maste   ProcessSP process_sp(m_thread.GetProcess());
34f034231aSEd Maste   bool invalidate = force;
35f034231aSEd Maste   uint32_t process_stop_id = UINT32_MAX;
36f034231aSEd Maste 
37f034231aSEd Maste   if (process_sp)
38f034231aSEd Maste     process_stop_id = process_sp->GetStopID();
39f034231aSEd Maste   else
40f034231aSEd Maste     invalidate = true;
41f034231aSEd Maste 
42f034231aSEd Maste   if (!invalidate)
43f034231aSEd Maste     invalidate = process_stop_id != GetStopID();
44f034231aSEd Maste 
4514f1b3e8SDimitry Andric   if (invalidate) {
46f034231aSEd Maste     InvalidateAllRegisters();
47f034231aSEd Maste     SetStopID(process_stop_id);
48f034231aSEd Maste   }
49f034231aSEd Maste }
50f034231aSEd Maste 
51f034231aSEd Maste const RegisterInfo *
GetRegisterInfoByName(llvm::StringRef reg_name,uint32_t start_idx)5214f1b3e8SDimitry Andric RegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name,
5314f1b3e8SDimitry Andric                                        uint32_t start_idx) {
5414f1b3e8SDimitry Andric   if (reg_name.empty())
5514f1b3e8SDimitry Andric     return nullptr;
5614f1b3e8SDimitry Andric 
57c0981da4SDimitry Andric   // Generic register names take precedence over specific register names.
58c0981da4SDimitry Andric   // For example, on x86 we want "sp" to refer to the complete RSP/ESP register
59c0981da4SDimitry Andric   // rather than the 16-bit SP pseudo-register.
60c0981da4SDimitry Andric   uint32_t generic_reg = Args::StringToGenericRegister(reg_name);
61c0981da4SDimitry Andric   if (generic_reg != LLDB_INVALID_REGNUM) {
62c0981da4SDimitry Andric     const RegisterInfo *reg_info =
63c0981da4SDimitry Andric         GetRegisterInfo(eRegisterKindGeneric, generic_reg);
64c0981da4SDimitry Andric     if (reg_info)
65c0981da4SDimitry Andric       return reg_info;
66c0981da4SDimitry Andric   }
67c0981da4SDimitry Andric 
68f034231aSEd Maste   const uint32_t num_registers = GetRegisterCount();
6914f1b3e8SDimitry Andric   for (uint32_t reg = start_idx; reg < num_registers; ++reg) {
70f034231aSEd Maste     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
71f034231aSEd Maste 
72344a3780SDimitry Andric     if (reg_name.equals_insensitive(reg_info->name) ||
73344a3780SDimitry Andric         reg_name.equals_insensitive(reg_info->alt_name))
74f034231aSEd Maste       return reg_info;
75f034231aSEd Maste   }
76c0981da4SDimitry Andric 
77f3fbd1c0SDimitry Andric   return nullptr;
78f034231aSEd Maste }
79f034231aSEd Maste 
GetRegisterInfo(lldb::RegisterKind kind,uint32_t num)8014f1b3e8SDimitry Andric const RegisterInfo *RegisterContext::GetRegisterInfo(lldb::RegisterKind kind,
8114f1b3e8SDimitry Andric                                                      uint32_t num) {
82f21a844fSEd Maste   const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num);
83f21a844fSEd Maste   if (reg_num == LLDB_INVALID_REGNUM)
84f3fbd1c0SDimitry Andric     return nullptr;
85f21a844fSEd Maste   return GetRegisterInfoAtIndex(reg_num);
86f21a844fSEd Maste }
87f21a844fSEd Maste 
GetRegisterName(uint32_t reg)8814f1b3e8SDimitry Andric const char *RegisterContext::GetRegisterName(uint32_t reg) {
89f034231aSEd Maste   const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
90f034231aSEd Maste   if (reg_info)
91f034231aSEd Maste     return reg_info->name;
92f3fbd1c0SDimitry Andric   return nullptr;
93f034231aSEd Maste }
94f034231aSEd Maste 
GetPC(uint64_t fail_value)9514f1b3e8SDimitry Andric uint64_t RegisterContext::GetPC(uint64_t fail_value) {
9614f1b3e8SDimitry Andric   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
9714f1b3e8SDimitry Andric                                                      LLDB_REGNUM_GENERIC_PC);
98e81d9d49SDimitry Andric   uint64_t pc = ReadRegisterAsUnsigned(reg, fail_value);
99e81d9d49SDimitry Andric 
10014f1b3e8SDimitry Andric   if (pc != fail_value) {
101e81d9d49SDimitry Andric     TargetSP target_sp = m_thread.CalculateTarget();
10214f1b3e8SDimitry Andric     if (target_sp) {
103e81d9d49SDimitry Andric       Target *target = target_sp.get();
104e81d9d49SDimitry Andric       if (target)
105f73363f1SDimitry Andric         pc = target->GetOpcodeLoadAddress(pc, AddressClass::eCode);
106e81d9d49SDimitry Andric     }
107e81d9d49SDimitry Andric   }
108e81d9d49SDimitry Andric 
109e81d9d49SDimitry Andric   return pc;
110f034231aSEd Maste }
111f034231aSEd Maste 
GetThreadPointer(uint64_t fail_value)112b1c73532SDimitry Andric uint64_t RegisterContext::GetThreadPointer(uint64_t fail_value) {
113b1c73532SDimitry Andric   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
114b1c73532SDimitry Andric                                                      LLDB_REGNUM_GENERIC_TP);
115b1c73532SDimitry Andric   return ReadRegisterAsUnsigned(reg, fail_value);
116b1c73532SDimitry Andric }
117b1c73532SDimitry Andric 
SetPC(uint64_t pc)11814f1b3e8SDimitry Andric bool RegisterContext::SetPC(uint64_t pc) {
11914f1b3e8SDimitry Andric   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
12014f1b3e8SDimitry Andric                                                      LLDB_REGNUM_GENERIC_PC);
121f034231aSEd Maste   bool success = WriteRegisterFromUnsigned(reg, pc);
12214f1b3e8SDimitry Andric   if (success) {
12314f1b3e8SDimitry Andric     StackFrameSP frame_sp(
12414f1b3e8SDimitry Andric         m_thread.GetFrameWithConcreteFrameIndex(m_concrete_frame_idx));
125f034231aSEd Maste     if (frame_sp)
126f034231aSEd Maste       frame_sp->ChangePC(pc);
127f034231aSEd Maste     else
128f034231aSEd Maste       m_thread.ClearStackFrames();
129f034231aSEd Maste   }
130f034231aSEd Maste   return success;
131f034231aSEd Maste }
132f034231aSEd Maste 
GetPCForSymbolication(Address & address)133344a3780SDimitry Andric bool RegisterContext::GetPCForSymbolication(Address &address) {
134344a3780SDimitry Andric   addr_t pc = GetPC(LLDB_INVALID_ADDRESS);
135344a3780SDimitry Andric   if (pc == LLDB_INVALID_ADDRESS)
136344a3780SDimitry Andric     return false;
137344a3780SDimitry Andric   TargetSP target_sp = m_thread.CalculateTarget();
138344a3780SDimitry Andric   if (!target_sp.get())
139344a3780SDimitry Andric     return false;
140344a3780SDimitry Andric 
141344a3780SDimitry Andric   if (!BehavesLikeZerothFrame() && pc != 0)
142344a3780SDimitry Andric     pc--;
143344a3780SDimitry Andric   address.SetLoadAddress(pc, target_sp.get());
144344a3780SDimitry Andric   return true;
145344a3780SDimitry Andric }
146344a3780SDimitry Andric 
SetPC(Address addr)14714f1b3e8SDimitry Andric bool RegisterContext::SetPC(Address addr) {
148f21a844fSEd Maste   TargetSP target_sp = m_thread.CalculateTarget();
149f21a844fSEd Maste   Target *target = target_sp.get();
150f21a844fSEd Maste 
151f21a844fSEd Maste   lldb::addr_t callAddr = addr.GetCallableLoadAddress(target);
152f21a844fSEd Maste   if (callAddr == LLDB_INVALID_ADDRESS)
153f21a844fSEd Maste     return false;
154f21a844fSEd Maste 
155f21a844fSEd Maste   return SetPC(callAddr);
156f21a844fSEd Maste }
157f21a844fSEd Maste 
GetSP(uint64_t fail_value)15814f1b3e8SDimitry Andric uint64_t RegisterContext::GetSP(uint64_t fail_value) {
15914f1b3e8SDimitry Andric   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
16014f1b3e8SDimitry Andric                                                      LLDB_REGNUM_GENERIC_SP);
161f034231aSEd Maste   return ReadRegisterAsUnsigned(reg, fail_value);
162f034231aSEd Maste }
163f034231aSEd Maste 
SetSP(uint64_t sp)16414f1b3e8SDimitry Andric bool RegisterContext::SetSP(uint64_t sp) {
16514f1b3e8SDimitry Andric   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
16614f1b3e8SDimitry Andric                                                      LLDB_REGNUM_GENERIC_SP);
167f034231aSEd Maste   return WriteRegisterFromUnsigned(reg, sp);
168f034231aSEd Maste }
169f034231aSEd Maste 
GetFP(uint64_t fail_value)17014f1b3e8SDimitry Andric uint64_t RegisterContext::GetFP(uint64_t fail_value) {
17114f1b3e8SDimitry Andric   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
17214f1b3e8SDimitry Andric                                                      LLDB_REGNUM_GENERIC_FP);
173f034231aSEd Maste   return ReadRegisterAsUnsigned(reg, fail_value);
174f034231aSEd Maste }
175f034231aSEd Maste 
SetFP(uint64_t fp)17614f1b3e8SDimitry Andric bool RegisterContext::SetFP(uint64_t fp) {
17714f1b3e8SDimitry Andric   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
17814f1b3e8SDimitry Andric                                                      LLDB_REGNUM_GENERIC_FP);
179f034231aSEd Maste   return WriteRegisterFromUnsigned(reg, fp);
180f034231aSEd Maste }
181f034231aSEd Maste 
GetReturnAddress(uint64_t fail_value)18214f1b3e8SDimitry Andric uint64_t RegisterContext::GetReturnAddress(uint64_t fail_value) {
18314f1b3e8SDimitry Andric   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
18414f1b3e8SDimitry Andric                                                      LLDB_REGNUM_GENERIC_RA);
185f034231aSEd Maste   return ReadRegisterAsUnsigned(reg, fail_value);
186f034231aSEd Maste }
187f034231aSEd Maste 
GetFlags(uint64_t fail_value)18814f1b3e8SDimitry Andric uint64_t RegisterContext::GetFlags(uint64_t fail_value) {
18914f1b3e8SDimitry Andric   uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
19014f1b3e8SDimitry Andric                                                      LLDB_REGNUM_GENERIC_FLAGS);
191f034231aSEd Maste   return ReadRegisterAsUnsigned(reg, fail_value);
192f034231aSEd Maste }
193f034231aSEd Maste 
ReadRegisterAsUnsigned(uint32_t reg,uint64_t fail_value)19414f1b3e8SDimitry Andric uint64_t RegisterContext::ReadRegisterAsUnsigned(uint32_t reg,
19514f1b3e8SDimitry Andric                                                  uint64_t fail_value) {
196f034231aSEd Maste   if (reg != LLDB_INVALID_REGNUM)
197f034231aSEd Maste     return ReadRegisterAsUnsigned(GetRegisterInfoAtIndex(reg), fail_value);
198f034231aSEd Maste   return fail_value;
199f034231aSEd Maste }
200f034231aSEd Maste 
ReadRegisterAsUnsigned(const RegisterInfo * reg_info,uint64_t fail_value)20114f1b3e8SDimitry Andric uint64_t RegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info,
20214f1b3e8SDimitry Andric                                                  uint64_t fail_value) {
20314f1b3e8SDimitry Andric   if (reg_info) {
204f034231aSEd Maste     RegisterValue value;
205f034231aSEd Maste     if (ReadRegister(reg_info, value))
206f034231aSEd Maste       return value.GetAsUInt64();
207f034231aSEd Maste   }
208f034231aSEd Maste   return fail_value;
209f034231aSEd Maste }
210f034231aSEd Maste 
WriteRegisterFromUnsigned(uint32_t reg,uint64_t uval)21114f1b3e8SDimitry Andric bool RegisterContext::WriteRegisterFromUnsigned(uint32_t reg, uint64_t uval) {
212f034231aSEd Maste   if (reg == LLDB_INVALID_REGNUM)
213f034231aSEd Maste     return false;
214f034231aSEd Maste   return WriteRegisterFromUnsigned(GetRegisterInfoAtIndex(reg), uval);
215f034231aSEd Maste }
216f034231aSEd Maste 
WriteRegisterFromUnsigned(const RegisterInfo * reg_info,uint64_t uval)21714f1b3e8SDimitry Andric bool RegisterContext::WriteRegisterFromUnsigned(const RegisterInfo *reg_info,
21814f1b3e8SDimitry Andric                                                 uint64_t uval) {
21914f1b3e8SDimitry Andric   if (reg_info) {
220f034231aSEd Maste     RegisterValue value;
221f034231aSEd Maste     if (value.SetUInt(uval, reg_info->byte_size))
222f034231aSEd Maste       return WriteRegister(reg_info, value);
223f034231aSEd Maste   }
224f034231aSEd Maste   return false;
225f034231aSEd Maste }
226f034231aSEd Maste 
CopyFromRegisterContext(lldb::RegisterContextSP context)22714f1b3e8SDimitry Andric bool RegisterContext::CopyFromRegisterContext(lldb::RegisterContextSP context) {
228f034231aSEd Maste   uint32_t num_register_sets = context->GetRegisterSetCount();
22914f1b3e8SDimitry Andric   // We don't know that two threads have the same register context, so require
23014f1b3e8SDimitry Andric   // the threads to be the same.
231f034231aSEd Maste   if (context->GetThreadID() != GetThreadID())
232f034231aSEd Maste     return false;
233f034231aSEd Maste 
234f034231aSEd Maste   if (num_register_sets != GetRegisterSetCount())
235f034231aSEd Maste     return false;
236f034231aSEd Maste 
237f034231aSEd Maste   RegisterContextSP frame_zero_context = m_thread.GetRegisterContext();
238f034231aSEd Maste 
23914f1b3e8SDimitry Andric   for (uint32_t set_idx = 0; set_idx < num_register_sets; ++set_idx) {
240f034231aSEd Maste     const RegisterSet *const reg_set = GetRegisterSet(set_idx);
241f034231aSEd Maste 
242f034231aSEd Maste     const uint32_t num_registers = reg_set->num_registers;
24314f1b3e8SDimitry Andric     for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) {
244f034231aSEd Maste       const uint32_t reg = reg_set->registers[reg_idx];
245f034231aSEd Maste       const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
246f034231aSEd Maste       if (!reg_info || reg_info->value_regs)
247f034231aSEd Maste         continue;
248f034231aSEd Maste       RegisterValue reg_value;
249f034231aSEd Maste 
25014f1b3e8SDimitry Andric       // If we can reconstruct the register from the frame we are copying from,
251f73363f1SDimitry Andric       // then do so, otherwise use the value from frame 0.
25214f1b3e8SDimitry Andric       if (context->ReadRegister(reg_info, reg_value)) {
253f034231aSEd Maste         WriteRegister(reg_info, reg_value);
25414f1b3e8SDimitry Andric       } else if (frame_zero_context->ReadRegister(reg_info, reg_value)) {
255f034231aSEd Maste         WriteRegister(reg_info, reg_value);
256f034231aSEd Maste       }
257f034231aSEd Maste     }
258f034231aSEd Maste   }
259f034231aSEd Maste   return true;
260f034231aSEd Maste }
261f034231aSEd Maste 
GetThreadID() const26214f1b3e8SDimitry Andric lldb::tid_t RegisterContext::GetThreadID() const { return m_thread.GetID(); }
263f034231aSEd Maste 
NumSupportedHardwareBreakpoints()26414f1b3e8SDimitry Andric uint32_t RegisterContext::NumSupportedHardwareBreakpoints() { return 0; }
265f034231aSEd Maste 
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)26614f1b3e8SDimitry Andric uint32_t RegisterContext::SetHardwareBreakpoint(lldb::addr_t addr,
26714f1b3e8SDimitry Andric                                                 size_t size) {
268f034231aSEd Maste   return LLDB_INVALID_INDEX32;
269f034231aSEd Maste }
270f034231aSEd Maste 
271cfca06d7SDimitry Andric // Used when parsing DWARF and EH frame information and any other object file
272cfca06d7SDimitry Andric // sections that contain register numbers in them.
273cfca06d7SDimitry Andric uint32_t
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)274cfca06d7SDimitry Andric RegisterContext::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
275cfca06d7SDimitry Andric                                                      uint32_t num) {
276cfca06d7SDimitry Andric   const uint32_t num_regs = GetRegisterCount();
277cfca06d7SDimitry Andric 
278cfca06d7SDimitry Andric   assert(kind < kNumRegisterKinds);
279cfca06d7SDimitry Andric   for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
280cfca06d7SDimitry Andric     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);
281cfca06d7SDimitry Andric 
282cfca06d7SDimitry Andric     if (reg_info->kinds[kind] == num)
283cfca06d7SDimitry Andric       return reg_idx;
284cfca06d7SDimitry Andric   }
285cfca06d7SDimitry Andric 
286cfca06d7SDimitry Andric   return LLDB_INVALID_REGNUM;
287cfca06d7SDimitry Andric }
288cfca06d7SDimitry Andric 
ClearHardwareBreakpoint(uint32_t hw_idx)28914f1b3e8SDimitry Andric bool RegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) { return false; }
290f034231aSEd Maste 
NumSupportedHardwareWatchpoints()29114f1b3e8SDimitry Andric uint32_t RegisterContext::NumSupportedHardwareWatchpoints() { return 0; }
292f034231aSEd Maste 
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,bool read,bool write)29314f1b3e8SDimitry Andric uint32_t RegisterContext::SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
29414f1b3e8SDimitry Andric                                                 bool read, bool write) {
295f034231aSEd Maste   return LLDB_INVALID_INDEX32;
296f034231aSEd Maste }
297f034231aSEd Maste 
ClearHardwareWatchpoint(uint32_t hw_index)29814f1b3e8SDimitry Andric bool RegisterContext::ClearHardwareWatchpoint(uint32_t hw_index) {
299f034231aSEd Maste   return false;
300f034231aSEd Maste }
301f034231aSEd Maste 
HardwareSingleStep(bool enable)30214f1b3e8SDimitry Andric bool RegisterContext::HardwareSingleStep(bool enable) { return false; }
303f034231aSEd Maste 
ReadRegisterValueFromMemory(const RegisterInfo * reg_info,lldb::addr_t src_addr,uint32_t src_len,RegisterValue & reg_value)304b76161e4SDimitry Andric Status RegisterContext::ReadRegisterValueFromMemory(
305b76161e4SDimitry Andric     const RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len,
30614f1b3e8SDimitry Andric     RegisterValue &reg_value) {
307b76161e4SDimitry Andric   Status error;
30814f1b3e8SDimitry Andric   if (reg_info == nullptr) {
309f034231aSEd Maste     error.SetErrorString("invalid register info argument.");
310f034231aSEd Maste     return error;
311f034231aSEd Maste   }
312f034231aSEd Maste 
313f034231aSEd Maste   // Moving from addr into a register
314f034231aSEd Maste   //
315f034231aSEd Maste   // Case 1: src_len == dst_len
316f034231aSEd Maste   //
317f034231aSEd Maste   //   |AABBCCDD| Address contents
318f034231aSEd Maste   //   |AABBCCDD| Register contents
319f034231aSEd Maste   //
320f034231aSEd Maste   // Case 2: src_len > dst_len
321f034231aSEd Maste   //
322b76161e4SDimitry Andric   //   Status!  (The register should always be big enough to hold the data)
323f034231aSEd Maste   //
324f034231aSEd Maste   // Case 3: src_len < dst_len
325f034231aSEd Maste   //
326f034231aSEd Maste   //   |AABB| Address contents
327f034231aSEd Maste   //   |AABB0000| Register contents [on little-endian hardware]
328f034231aSEd Maste   //   |0000AABB| Register contents [on big-endian hardware]
329f034231aSEd Maste   const uint32_t dst_len = reg_info->byte_size;
330f034231aSEd Maste 
33114f1b3e8SDimitry Andric   if (src_len > dst_len) {
33214f1b3e8SDimitry Andric     error.SetErrorStringWithFormat(
33314f1b3e8SDimitry Andric         "%u bytes is too big to store in register %s (%u bytes)", src_len,
33414f1b3e8SDimitry Andric         reg_info->name, dst_len);
335f034231aSEd Maste     return error;
336f034231aSEd Maste   }
337f034231aSEd Maste 
338f034231aSEd Maste   ProcessSP process_sp(m_thread.GetProcess());
33914f1b3e8SDimitry Andric   if (process_sp) {
3407fa27ce4SDimitry Andric     RegisterValue::BytesContainer src(src_len);
341f034231aSEd Maste 
342f034231aSEd Maste     // Read the memory
34314f1b3e8SDimitry Andric     const uint32_t bytes_read =
3447fa27ce4SDimitry Andric         process_sp->ReadMemory(src_addr, src.data(), src_len, error);
345f034231aSEd Maste 
346f034231aSEd Maste     // Make sure the memory read succeeded...
34714f1b3e8SDimitry Andric     if (bytes_read != src_len) {
34814f1b3e8SDimitry Andric       if (error.Success()) {
349f034231aSEd Maste         // This might happen if we read _some_ bytes but not all
35014f1b3e8SDimitry Andric         error.SetErrorStringWithFormat("read %u of %u bytes", bytes_read,
35114f1b3e8SDimitry Andric                                        src_len);
352f034231aSEd Maste       }
353f034231aSEd Maste       return error;
354f034231aSEd Maste     }
355f034231aSEd Maste 
356f73363f1SDimitry Andric     // We now have a memory buffer that contains the part or all of the
357f73363f1SDimitry Andric     // register value. Set the register value using this memory data.
358f034231aSEd Maste     // TODO: we might need to add a parameter to this function in case the byte
35914f1b3e8SDimitry Andric     // order of the memory data doesn't match the process. For now we are
360f73363f1SDimitry Andric     // assuming they are the same.
3617fa27ce4SDimitry Andric     reg_value.SetFromMemoryData(*reg_info, src.data(), src_len,
36214f1b3e8SDimitry Andric                                 process_sp->GetByteOrder(), error);
36314f1b3e8SDimitry Andric   } else
364f034231aSEd Maste     error.SetErrorString("invalid process");
365f034231aSEd Maste 
366f034231aSEd Maste   return error;
367f034231aSEd Maste }
368f034231aSEd Maste 
WriteRegisterValueToMemory(const RegisterInfo * reg_info,lldb::addr_t dst_addr,uint32_t dst_len,const RegisterValue & reg_value)369b76161e4SDimitry Andric Status RegisterContext::WriteRegisterValueToMemory(
37014f1b3e8SDimitry Andric     const RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len,
37114f1b3e8SDimitry Andric     const RegisterValue &reg_value) {
372b76161e4SDimitry Andric   Status error;
373f034231aSEd Maste   ProcessSP process_sp(m_thread.GetProcess());
374e3b55780SDimitry Andric 
375e3b55780SDimitry Andric   if (!process_sp) {
376e3b55780SDimitry Andric     error.SetErrorString("invalid process");
377e3b55780SDimitry Andric     return error;
378e3b55780SDimitry Andric   }
379e3b55780SDimitry Andric 
380e3b55780SDimitry Andric   if (reg_info == nullptr) {
381e3b55780SDimitry Andric     error.SetErrorString("Invalid register info argument.");
382e3b55780SDimitry Andric     return error;
383e3b55780SDimitry Andric   }
384f034231aSEd Maste 
385f034231aSEd Maste   // TODO: we might need to add a parameter to this function in case the byte
38614f1b3e8SDimitry Andric   // order of the memory data doesn't match the process. For now we are
387f73363f1SDimitry Andric   // assuming they are the same.
3887fa27ce4SDimitry Andric   RegisterValue::BytesContainer dst(dst_len);
38914f1b3e8SDimitry Andric   const uint32_t bytes_copied = reg_value.GetAsMemoryData(
3907fa27ce4SDimitry Andric       *reg_info, dst.data(), dst_len, process_sp->GetByteOrder(), error);
391f034231aSEd Maste 
39214f1b3e8SDimitry Andric   if (error.Success()) {
39314f1b3e8SDimitry Andric     if (bytes_copied == 0) {
394f034231aSEd Maste       error.SetErrorString("byte copy failed.");
39514f1b3e8SDimitry Andric     } else {
39614f1b3e8SDimitry Andric       const uint32_t bytes_written =
3977fa27ce4SDimitry Andric           process_sp->WriteMemory(dst_addr, dst.data(), bytes_copied, error);
39814f1b3e8SDimitry Andric       if (bytes_written != bytes_copied) {
39914f1b3e8SDimitry Andric         if (error.Success()) {
400f034231aSEd Maste           // This might happen if we read _some_ bytes but not all
40114f1b3e8SDimitry Andric           error.SetErrorStringWithFormat("only wrote %u of %u bytes",
40214f1b3e8SDimitry Andric                                          bytes_written, bytes_copied);
403f034231aSEd Maste         }
404f034231aSEd Maste       }
405f034231aSEd Maste     }
406f034231aSEd Maste   }
407f034231aSEd Maste 
408f034231aSEd Maste   return error;
409f034231aSEd Maste }
410f034231aSEd Maste 
GetByteOrder()411cfca06d7SDimitry Andric lldb::ByteOrder RegisterContext::GetByteOrder() {
412cfca06d7SDimitry Andric   // Get the target process whose privileged thread was used for the register
413cfca06d7SDimitry Andric   // read.
414cfca06d7SDimitry Andric   lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
415cfca06d7SDimitry Andric   lldb_private::Process *process = CalculateProcess().get();
416cfca06d7SDimitry Andric 
417cfca06d7SDimitry Andric   if (process)
418cfca06d7SDimitry Andric     byte_order = process->GetByteOrder();
419cfca06d7SDimitry Andric   return byte_order;
420cfca06d7SDimitry Andric }
421cfca06d7SDimitry Andric 
ReadAllRegisterValues(lldb_private::RegisterCheckpoint & reg_checkpoint)42214f1b3e8SDimitry Andric bool RegisterContext::ReadAllRegisterValues(
42314f1b3e8SDimitry Andric     lldb_private::RegisterCheckpoint &reg_checkpoint) {
42486758c71SEd Maste   return ReadAllRegisterValues(reg_checkpoint.GetData());
42586758c71SEd Maste }
42686758c71SEd Maste 
WriteAllRegisterValues(const lldb_private::RegisterCheckpoint & reg_checkpoint)42714f1b3e8SDimitry Andric bool RegisterContext::WriteAllRegisterValues(
42814f1b3e8SDimitry Andric     const lldb_private::RegisterCheckpoint &reg_checkpoint) {
42986758c71SEd Maste   return WriteAllRegisterValues(reg_checkpoint.GetData());
43086758c71SEd Maste }
43186758c71SEd Maste 
CalculateTarget()43214f1b3e8SDimitry Andric TargetSP RegisterContext::CalculateTarget() {
433f034231aSEd Maste   return m_thread.CalculateTarget();
434f034231aSEd Maste }
435f034231aSEd Maste 
CalculateProcess()43614f1b3e8SDimitry Andric ProcessSP RegisterContext::CalculateProcess() {
437f034231aSEd Maste   return m_thread.CalculateProcess();
438f034231aSEd Maste }
439f034231aSEd Maste 
CalculateThread()44014f1b3e8SDimitry Andric ThreadSP RegisterContext::CalculateThread() {
441f034231aSEd Maste   return m_thread.shared_from_this();
442f034231aSEd Maste }
443f034231aSEd Maste 
CalculateStackFrame()44414f1b3e8SDimitry Andric StackFrameSP RegisterContext::CalculateStackFrame() {
445f73363f1SDimitry Andric   // Register contexts might belong to many frames if we have inlined functions
446f73363f1SDimitry Andric   // inside a frame since all inlined functions share the same registers, so we
447f73363f1SDimitry Andric   // can't definitively say which frame we come from...
448f034231aSEd Maste   return StackFrameSP();
449f034231aSEd Maste }
450f034231aSEd Maste 
CalculateExecutionContext(ExecutionContext & exe_ctx)45114f1b3e8SDimitry Andric void RegisterContext::CalculateExecutionContext(ExecutionContext &exe_ctx) {
452f034231aSEd Maste   m_thread.CalculateExecutionContext(exe_ctx);
453f034231aSEd Maste }
454f034231aSEd Maste 
ConvertBetweenRegisterKinds(lldb::RegisterKind source_rk,uint32_t source_regnum,lldb::RegisterKind target_rk,uint32_t & target_regnum)45514f1b3e8SDimitry Andric bool RegisterContext::ConvertBetweenRegisterKinds(lldb::RegisterKind source_rk,
45614f1b3e8SDimitry Andric                                                   uint32_t source_regnum,
45714f1b3e8SDimitry Andric                                                   lldb::RegisterKind target_rk,
45814f1b3e8SDimitry Andric                                                   uint32_t &target_regnum) {
459f034231aSEd Maste   const uint32_t num_registers = GetRegisterCount();
46014f1b3e8SDimitry Andric   for (uint32_t reg = 0; reg < num_registers; ++reg) {
461f034231aSEd Maste     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
462f034231aSEd Maste 
46314f1b3e8SDimitry Andric     if (reg_info->kinds[source_rk] == source_regnum) {
464f034231aSEd Maste       target_regnum = reg_info->kinds[target_rk];
465f3fbd1c0SDimitry Andric       return (target_regnum != LLDB_INVALID_REGNUM);
466f034231aSEd Maste     }
467f034231aSEd Maste   }
468f034231aSEd Maste   return false;
469f034231aSEd Maste }
470