1275072Semaste//===-- NativeRegisterContext.cpp -------------------------*- C++ -*-===//
2275072Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6275072Semaste//
7275072Semaste//===----------------------------------------------------------------------===//
8275072Semaste
9278425Semaste#include "lldb/Host/common/NativeRegisterContext.h"
10275072Semaste
11321369Sdim#include "lldb/Utility/Log.h"
12344779Sdim#include "lldb/Utility/RegisterValue.h"
13275072Semaste
14314564Sdim#include "lldb/Host/PosixApi.h"
15278425Semaste#include "lldb/Host/common/NativeProcessProtocol.h"
16278425Semaste#include "lldb/Host/common/NativeThreadProtocol.h"
17275072Semaste
18275072Semasteusing namespace lldb;
19275072Semasteusing namespace lldb_private;
20275072Semaste
21327952SdimNativeRegisterContext::NativeRegisterContext(NativeThreadProtocol &thread)
22327952Sdim    : m_thread(thread) {}
23275072Semaste
24275072Semaste// Destructor
25314564SdimNativeRegisterContext::~NativeRegisterContext() {}
26275072Semaste
27275072Semaste// FIXME revisit invalidation, process stop ids, etc.  Right now we don't
28341825Sdim// support caching in NativeRegisterContext.  We can do this later by utilizing
29341825Sdim// NativeProcessProtocol::GetStopID () and adding a stop id to
30275072Semaste// NativeRegisterContext.
31275072Semaste
32275072Semaste// void
33341825Sdim// NativeRegisterContext::InvalidateIfNeeded (bool force) {
34275072Semaste//     ProcessSP process_sp (m_thread.GetProcess());
35275072Semaste//     bool invalidate = force;
36275072Semaste//     uint32_t process_stop_id = UINT32_MAX;
37275072Semaste
38275072Semaste//     if (process_sp)
39275072Semaste//         process_stop_id = process_sp->GetStopID();
40275072Semaste//     else
41275072Semaste//         invalidate = true;
42275072Semaste
43275072Semaste//     if (!invalidate)
44275072Semaste//         invalidate = process_stop_id != GetStopID();
45275072Semaste
46275072Semaste//     if (invalidate)
47275072Semaste//     {
48275072Semaste//         InvalidateAllRegisters ();
49275072Semaste//         SetStopID (process_stop_id);
50275072Semaste//     }
51275072Semaste// }
52275072Semaste
53275072Semasteconst RegisterInfo *
54314564SdimNativeRegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name,
55314564Sdim                                             uint32_t start_idx) {
56314564Sdim  if (reg_name.empty())
57314564Sdim    return nullptr;
58275072Semaste
59314564Sdim  const uint32_t num_registers = GetRegisterCount();
60314564Sdim  for (uint32_t reg = start_idx; reg < num_registers; ++reg) {
61314564Sdim    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
62314564Sdim
63314564Sdim    if (reg_name.equals_lower(reg_info->name) ||
64314564Sdim        reg_name.equals_lower(reg_info->alt_name))
65314564Sdim      return reg_info;
66314564Sdim  }
67314564Sdim  return nullptr;
68314564Sdim}
69314564Sdim
70314564Sdimconst RegisterInfo *NativeRegisterContext::GetRegisterInfo(uint32_t kind,
71314564Sdim                                                           uint32_t num) {
72314564Sdim  const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num);
73314564Sdim  if (reg_num == LLDB_INVALID_REGNUM)
74275072Semaste    return nullptr;
75314564Sdim  return GetRegisterInfoAtIndex(reg_num);
76275072Semaste}
77275072Semaste
78314564Sdimconst char *NativeRegisterContext::GetRegisterName(uint32_t reg) {
79314564Sdim  const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
80314564Sdim  if (reg_info)
81314564Sdim    return reg_info->name;
82314564Sdim  return nullptr;
83275072Semaste}
84275072Semaste
85314564Sdimconst char *NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex(
86314564Sdim    uint32_t reg_index) const {
87314564Sdim  const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
88314564Sdim  if (!reg_info)
89275072Semaste    return nullptr;
90275072Semaste
91314564Sdim  for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) {
92314564Sdim    const RegisterSet *const reg_set = GetRegisterSet(set_index);
93314564Sdim    if (!reg_set)
94314564Sdim      continue;
95275072Semaste
96314564Sdim    for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers;
97314564Sdim         ++reg_num_index) {
98314564Sdim      const uint32_t reg_num = reg_set->registers[reg_num_index];
99314564Sdim      // FIXME double check we're checking the right register kind here.
100314564Sdim      if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num) {
101314564Sdim        // The given register is a member of this register set.  Return the
102314564Sdim        // register set name.
103314564Sdim        return reg_set->name;
104314564Sdim      }
105275072Semaste    }
106314564Sdim  }
107275072Semaste
108314564Sdim  // Didn't find it.
109314564Sdim  return nullptr;
110275072Semaste}
111275072Semaste
112314564Sdimlldb::addr_t NativeRegisterContext::GetPC(lldb::addr_t fail_value) {
113314564Sdim  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
114275072Semaste
115314564Sdim  uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
116314564Sdim                                                     LLDB_REGNUM_GENERIC_PC);
117360784Sdim  LLDB_LOGF(log,
118360784Sdim            "NativeRegisterContext::%s using reg index %" PRIu32
119360784Sdim            " (default %" PRIu64 ")",
120360784Sdim            __FUNCTION__, reg, fail_value);
121275072Semaste
122314564Sdim  const uint64_t retval = ReadRegisterAsUnsigned(reg, fail_value);
123275072Semaste
124360784Sdim  LLDB_LOGF(log, "NativeRegisterContext::%s " PRIu32 " retval %" PRIu64,
125360784Sdim            __FUNCTION__, retval);
126275072Semaste
127314564Sdim  return retval;
128275072Semaste}
129275072Semaste
130285101Semastelldb::addr_t
131314564SdimNativeRegisterContext::GetPCfromBreakpointLocation(lldb::addr_t fail_value) {
132314564Sdim  return GetPC(fail_value);
133285101Semaste}
134285101Semaste
135321369SdimStatus NativeRegisterContext::SetPC(lldb::addr_t pc) {
136314564Sdim  uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
137314564Sdim                                                     LLDB_REGNUM_GENERIC_PC);
138314564Sdim  return WriteRegisterFromUnsigned(reg, pc);
139275072Semaste}
140275072Semaste
141314564Sdimlldb::addr_t NativeRegisterContext::GetSP(lldb::addr_t fail_value) {
142314564Sdim  uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
143314564Sdim                                                     LLDB_REGNUM_GENERIC_SP);
144314564Sdim  return ReadRegisterAsUnsigned(reg, fail_value);
145275072Semaste}
146275072Semaste
147321369SdimStatus NativeRegisterContext::SetSP(lldb::addr_t sp) {
148314564Sdim  uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
149314564Sdim                                                     LLDB_REGNUM_GENERIC_SP);
150314564Sdim  return WriteRegisterFromUnsigned(reg, sp);
151275072Semaste}
152275072Semaste
153314564Sdimlldb::addr_t NativeRegisterContext::GetFP(lldb::addr_t fail_value) {
154314564Sdim  uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
155314564Sdim                                                     LLDB_REGNUM_GENERIC_FP);
156314564Sdim  return ReadRegisterAsUnsigned(reg, fail_value);
157275072Semaste}
158275072Semaste
159321369SdimStatus NativeRegisterContext::SetFP(lldb::addr_t fp) {
160314564Sdim  uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
161314564Sdim                                                     LLDB_REGNUM_GENERIC_FP);
162314564Sdim  return WriteRegisterFromUnsigned(reg, fp);
163275072Semaste}
164275072Semaste
165314564Sdimlldb::addr_t NativeRegisterContext::GetReturnAddress(lldb::addr_t fail_value) {
166314564Sdim  uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
167314564Sdim                                                     LLDB_REGNUM_GENERIC_RA);
168314564Sdim  return ReadRegisterAsUnsigned(reg, fail_value);
169275072Semaste}
170275072Semaste
171314564Sdimlldb::addr_t NativeRegisterContext::GetFlags(lldb::addr_t fail_value) {
172314564Sdim  uint32_t reg = ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
173314564Sdim                                                     LLDB_REGNUM_GENERIC_FLAGS);
174314564Sdim  return ReadRegisterAsUnsigned(reg, fail_value);
175275072Semaste}
176275072Semaste
177275072Semastelldb::addr_t
178314564SdimNativeRegisterContext::ReadRegisterAsUnsigned(uint32_t reg,
179314564Sdim                                              lldb::addr_t fail_value) {
180314564Sdim  if (reg != LLDB_INVALID_REGNUM)
181314564Sdim    return ReadRegisterAsUnsigned(GetRegisterInfoAtIndex(reg), fail_value);
182314564Sdim  return fail_value;
183275072Semaste}
184275072Semaste
185275072Semasteuint64_t
186314564SdimNativeRegisterContext::ReadRegisterAsUnsigned(const RegisterInfo *reg_info,
187314564Sdim                                              lldb::addr_t fail_value) {
188314564Sdim  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
189275072Semaste
190314564Sdim  if (reg_info) {
191314564Sdim    RegisterValue value;
192321369Sdim    Status error = ReadRegister(reg_info, value);
193314564Sdim    if (error.Success()) {
194360784Sdim      LLDB_LOGF(log,
195360784Sdim                "NativeRegisterContext::%s ReadRegister() succeeded, value "
196360784Sdim                "%" PRIu64,
197360784Sdim                __FUNCTION__, value.GetAsUInt64());
198314564Sdim      return value.GetAsUInt64();
199314564Sdim    } else {
200360784Sdim      LLDB_LOGF(log,
201360784Sdim                "NativeRegisterContext::%s ReadRegister() failed, error %s",
202360784Sdim                __FUNCTION__, error.AsCString());
203275072Semaste    }
204314564Sdim  } else {
205360784Sdim    LLDB_LOGF(log, "NativeRegisterContext::%s ReadRegister() null reg_info",
206360784Sdim              __FUNCTION__);
207314564Sdim  }
208314564Sdim  return fail_value;
209275072Semaste}
210275072Semaste
211321369SdimStatus NativeRegisterContext::WriteRegisterFromUnsigned(uint32_t reg,
212321369Sdim                                                        uint64_t uval) {
213314564Sdim  if (reg == LLDB_INVALID_REGNUM)
214321369Sdim    return Status("NativeRegisterContext::%s (): reg is invalid", __FUNCTION__);
215314564Sdim  return WriteRegisterFromUnsigned(GetRegisterInfoAtIndex(reg), uval);
216275072Semaste}
217275072Semaste
218321369SdimStatus
219321369SdimNativeRegisterContext::WriteRegisterFromUnsigned(const RegisterInfo *reg_info,
220321369Sdim                                                 uint64_t uval) {
221314564Sdim  assert(reg_info);
222314564Sdim  if (!reg_info)
223321369Sdim    return Status("reg_info is nullptr");
224275072Semaste
225314564Sdim  RegisterValue value;
226314564Sdim  if (!value.SetUInt(uval, reg_info->byte_size))
227321369Sdim    return Status("RegisterValue::SetUInt () failed");
228275072Semaste
229314564Sdim  return WriteRegister(reg_info, value);
230275072Semaste}
231275072Semaste
232314564Sdimlldb::tid_t NativeRegisterContext::GetThreadID() const {
233314564Sdim  return m_thread.GetID();
234275072Semaste}
235275072Semaste
236314564Sdimuint32_t NativeRegisterContext::NumSupportedHardwareBreakpoints() { return 0; }
237275072Semaste
238314564Sdimuint32_t NativeRegisterContext::SetHardwareBreakpoint(lldb::addr_t addr,
239314564Sdim                                                      size_t size) {
240314564Sdim  return LLDB_INVALID_INDEX32;
241275072Semaste}
242275072Semaste
243321369SdimStatus NativeRegisterContext::ClearAllHardwareBreakpoints() {
244321369Sdim  return Status("not implemented");
245321369Sdim}
246321369Sdim
247314564Sdimbool NativeRegisterContext::ClearHardwareBreakpoint(uint32_t hw_idx) {
248314564Sdim  return false;
249275072Semaste}
250275072Semaste
251321369SdimStatus NativeRegisterContext::GetHardwareBreakHitIndex(uint32_t &bp_index,
252321369Sdim                                                       lldb::addr_t trap_addr) {
253321369Sdim  bp_index = LLDB_INVALID_INDEX32;
254321369Sdim  return Status("not implemented");
255321369Sdim}
256321369Sdim
257314564Sdimuint32_t NativeRegisterContext::NumSupportedHardwareWatchpoints() { return 0; }
258275072Semaste
259314564Sdimuint32_t NativeRegisterContext::SetHardwareWatchpoint(lldb::addr_t addr,
260314564Sdim                                                      size_t size,
261314564Sdim                                                      uint32_t watch_flags) {
262314564Sdim  return LLDB_INVALID_INDEX32;
263275072Semaste}
264275072Semaste
265314564Sdimbool NativeRegisterContext::ClearHardwareWatchpoint(uint32_t hw_index) {
266314564Sdim  return false;
267275072Semaste}
268275072Semaste
269321369SdimStatus NativeRegisterContext::ClearAllHardwareWatchpoints() {
270321369Sdim  return Status("not implemented");
271275072Semaste}
272275072Semaste
273321369SdimStatus NativeRegisterContext::IsWatchpointHit(uint32_t wp_index, bool &is_hit) {
274314564Sdim  is_hit = false;
275321369Sdim  return Status("not implemented");
276278425Semaste}
277278425Semaste
278321369SdimStatus NativeRegisterContext::GetWatchpointHitIndex(uint32_t &wp_index,
279321369Sdim                                                    lldb::addr_t trap_addr) {
280314564Sdim  wp_index = LLDB_INVALID_INDEX32;
281321369Sdim  return Status("not implemented");
282285101Semaste}
283285101Semaste
284321369SdimStatus NativeRegisterContext::IsWatchpointVacant(uint32_t wp_index,
285321369Sdim                                                 bool &is_vacant) {
286314564Sdim  is_vacant = false;
287321369Sdim  return Status("not implemented");
288285101Semaste}
289285101Semaste
290314564Sdimlldb::addr_t NativeRegisterContext::GetWatchpointAddress(uint32_t wp_index) {
291314564Sdim  return LLDB_INVALID_ADDRESS;
292285101Semaste}
293285101Semaste
294314564Sdimlldb::addr_t NativeRegisterContext::GetWatchpointHitAddress(uint32_t wp_index) {
295314564Sdim  return LLDB_INVALID_ADDRESS;
296285101Semaste}
297285101Semaste
298314564Sdimbool NativeRegisterContext::HardwareSingleStep(bool enable) { return false; }
299287521Sdim
300321369SdimStatus NativeRegisterContext::ReadRegisterValueFromMemory(
301314564Sdim    const RegisterInfo *reg_info, lldb::addr_t src_addr, size_t src_len,
302314564Sdim    RegisterValue &reg_value) {
303321369Sdim  Status error;
304314564Sdim  if (reg_info == nullptr) {
305314564Sdim    error.SetErrorString("invalid register info argument.");
306314564Sdim    return error;
307314564Sdim  }
308275072Semaste
309314564Sdim  // Moving from addr into a register
310314564Sdim  //
311314564Sdim  // Case 1: src_len == dst_len
312314564Sdim  //
313314564Sdim  //   |AABBCCDD| Address contents
314314564Sdim  //   |AABBCCDD| Register contents
315314564Sdim  //
316314564Sdim  // Case 2: src_len > dst_len
317314564Sdim  //
318321369Sdim  //   Status!  (The register should always be big enough to hold the data)
319314564Sdim  //
320314564Sdim  // Case 3: src_len < dst_len
321314564Sdim  //
322314564Sdim  //   |AABB| Address contents
323314564Sdim  //   |AABB0000| Register contents [on little-endian hardware]
324314564Sdim  //   |0000AABB| Register contents [on big-endian hardware]
325314564Sdim  if (src_len > RegisterValue::kMaxRegisterByteSize) {
326314564Sdim    error.SetErrorString("register too small to receive memory data");
327314564Sdim    return error;
328314564Sdim  }
329275072Semaste
330314564Sdim  const size_t dst_len = reg_info->byte_size;
331275072Semaste
332314564Sdim  if (src_len > dst_len) {
333314564Sdim    error.SetErrorStringWithFormat(
334314564Sdim        "%" PRIu64 " bytes is too big to store in register %s (%" PRIu64
335314564Sdim        " bytes)",
336314564Sdim        static_cast<uint64_t>(src_len), reg_info->name,
337314564Sdim        static_cast<uint64_t>(dst_len));
338314564Sdim    return error;
339314564Sdim  }
340275072Semaste
341321369Sdim  NativeProcessProtocol &process = m_thread.GetProcess();
342314564Sdim  uint8_t src[RegisterValue::kMaxRegisterByteSize];
343275072Semaste
344314564Sdim  // Read the memory
345314564Sdim  size_t bytes_read;
346321369Sdim  error = process.ReadMemory(src_addr, src, src_len, bytes_read);
347314564Sdim  if (error.Fail())
348314564Sdim    return error;
349275072Semaste
350314564Sdim  // Make sure the memory read succeeded...
351314564Sdim  if (bytes_read != src_len) {
352314564Sdim    // This might happen if we read _some_ bytes but not all
353314564Sdim    error.SetErrorStringWithFormat("read %" PRIu64 " of %" PRIu64 " bytes",
354314564Sdim                                   static_cast<uint64_t>(bytes_read),
355314564Sdim                                   static_cast<uint64_t>(src_len));
356314564Sdim    return error;
357314564Sdim  }
358275072Semaste
359314564Sdim  // We now have a memory buffer that contains the part or all of the register
360314564Sdim  // value. Set the register value using this memory data.
361314564Sdim  // TODO: we might need to add a parameter to this function in case the byte
362341825Sdim  // order of the memory data doesn't match the process. For now we are
363341825Sdim  // assuming they are the same.
364327952Sdim  reg_value.SetFromMemoryData(reg_info, src, src_len, process.GetByteOrder(),
365327952Sdim                              error);
366275072Semaste
367314564Sdim  return error;
368314564Sdim}
369275072Semaste
370321369SdimStatus NativeRegisterContext::WriteRegisterValueToMemory(
371314564Sdim    const RegisterInfo *reg_info, lldb::addr_t dst_addr, size_t dst_len,
372314564Sdim    const RegisterValue &reg_value) {
373275072Semaste
374314564Sdim  uint8_t dst[RegisterValue::kMaxRegisterByteSize];
375275072Semaste
376321369Sdim  Status error;
377275072Semaste
378321369Sdim  NativeProcessProtocol &process = m_thread.GetProcess();
379275072Semaste
380321369Sdim  // TODO: we might need to add a parameter to this function in case the byte
381321369Sdim  // order of the memory data doesn't match the process. For now we are
382341825Sdim  // assuming they are the same.
383327952Sdim  const size_t bytes_copied = reg_value.GetAsMemoryData(
384327952Sdim      reg_info, dst, dst_len, process.GetByteOrder(), error);
385275072Semaste
386321369Sdim  if (error.Success()) {
387321369Sdim    if (bytes_copied == 0) {
388321369Sdim      error.SetErrorString("byte copy failed.");
389321369Sdim    } else {
390321369Sdim      size_t bytes_written;
391321369Sdim      error = process.WriteMemory(dst_addr, dst, bytes_copied, bytes_written);
392321369Sdim      if (error.Fail())
393321369Sdim        return error;
394275072Semaste
395321369Sdim      if (bytes_written != bytes_copied) {
396321369Sdim        // This might happen if we read _some_ bytes but not all
397321369Sdim        error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64
398321369Sdim                                       " bytes",
399321369Sdim                                       static_cast<uint64_t>(bytes_written),
400321369Sdim                                       static_cast<uint64_t>(bytes_copied));
401314564Sdim      }
402275072Semaste    }
403321369Sdim  }
404275072Semaste
405314564Sdim  return error;
406275072Semaste}
407275072Semaste
408275072Semasteuint32_t
409314564SdimNativeRegisterContext::ConvertRegisterKindToRegisterNumber(uint32_t kind,
410314564Sdim                                                           uint32_t num) const {
411314564Sdim  const uint32_t num_regs = GetRegisterCount();
412275072Semaste
413314564Sdim  assert(kind < kNumRegisterKinds);
414314564Sdim  for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
415314564Sdim    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);
416275072Semaste
417314564Sdim    if (reg_info->kinds[kind] == num)
418314564Sdim      return reg_idx;
419314564Sdim  }
420275072Semaste
421314564Sdim  return LLDB_INVALID_REGNUM;
422275072Semaste}
423