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