[Lldb-commits] [lldb] 9d02936 - [lldb] [Process/FreeBSDRemote] Introduce arm (32-bit) support

Michał Górny via lldb-commits lldb-commits at lists.llvm.org
Sun Jan 31 10:52:24 PST 2021


Author: Michał Górny
Date: 2021-01-31T19:52:08+01:00
New Revision: 9d029362d1ed48c38565aeab0ca04bf4143d3e5b

URL: https://github.com/llvm/llvm-project/commit/9d029362d1ed48c38565aeab0ca04bf4143d3e5b
DIFF: https://github.com/llvm/llvm-project/commit/9d029362d1ed48c38565aeab0ca04bf4143d3e5b.diff

LOG: [lldb] [Process/FreeBSDRemote] Introduce arm (32-bit) support

Introduce a NativeRegisterContextFreeBSD for 32-bit ARM platform.
This includes support for GPR + VFP registers as exposed by FreeBSD's
ptrace(2) API.  Hardware breakpoints or watchpoints are not supported
due to missing kernel support.  The code is roughly based on the arm64
context.

It also includes an override for GetSoftwareBreakpointTrapOpcode() based
on the matching code in the PlatformFreeBSD plugin.

Differential Revision: https://reviews.llvm.org/D95696

Added: 
    lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_arm.cpp
    lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_arm.h

Modified: 
    lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
    lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt
    lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
    lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h
    lldb/unittests/Process/Utility/RegisterContextFreeBSDTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index 0c9068e5c421..40fef595752b 100644
--- a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -254,6 +254,7 @@ bool PlatformFreeBSD::CanDebugProcess() {
 
     switch (host_triple.getArch()) {
       case llvm::Triple::aarch64:
+      case llvm::Triple::arm:
       case llvm::Triple::x86:
       case llvm::Triple::x86_64:
         use_legacy_plugin = !!getenv("FREEBSD_LEGACY_PLUGIN");

diff  --git a/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt b/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt
index 2b192559d059..9d102bee24b6 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_lldb_library(lldbPluginProcessFreeBSDRemote
   NativeProcessFreeBSD.cpp
   NativeRegisterContextFreeBSD.cpp
+  NativeRegisterContextFreeBSD_arm.cpp
   NativeRegisterContextFreeBSD_arm64.cpp
   NativeRegisterContextFreeBSD_x86_64.cpp
   NativeThreadFreeBSD.cpp

diff  --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
index 163093c2ab1f..139313bb5310 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
+++ b/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
@@ -354,6 +354,27 @@ Status NativeProcessFreeBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
   return error;
 }
 
+llvm::Expected<llvm::ArrayRef<uint8_t>>
+NativeProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
+  static const uint8_t g_arm_opcode[] = {0xfe, 0xde, 0xff, 0xe7};
+  static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
+
+  switch (GetArchitecture().GetMachine()) {
+  case llvm::Triple::arm:
+    switch (size_hint) {
+    case 2:
+      return llvm::makeArrayRef(g_thumb_opcode);
+    case 4:
+      return llvm::makeArrayRef(g_arm_opcode);
+    default:
+      return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                     "Unrecognised trap opcode size hint!");
+    }
+  default:
+    return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint);
+  }
+}
+
 Status NativeProcessFreeBSD::Resume(const ResumeActionList &resume_actions) {
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
   LLDB_LOG(log, "pid {0}", GetID());

diff  --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h b/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h
index 3c7a9400f9c4..99123d598186 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h
+++ b/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h
@@ -84,6 +84,10 @@ class NativeProcessFreeBSD : public NativeProcessELF {
   static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr,
                               int data = 0, int *result = nullptr);
 
+protected:
+  llvm::Expected<llvm::ArrayRef<uint8_t>>
+  GetSoftwareBreakpointTrapOpcode(size_t size_hint) override;
+
 private:
   MainLoop::SignalHandleUP m_sigchld_handle;
   ArchSpec m_arch;

diff  --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_arm.cpp b/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_arm.cpp
new file mode 100644
index 000000000000..18926d7e7fa6
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_arm.cpp
@@ -0,0 +1,202 @@
+//===-- NativeRegisterContextFreeBSD_arm.cpp ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm__)
+
+#include "NativeRegisterContextFreeBSD_arm.h"
+
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+
+#include "Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_freebsd;
+
+NativeRegisterContextFreeBSD *
+NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+  return new NativeRegisterContextFreeBSD_arm(target_arch, native_thread);
+}
+
+NativeRegisterContextFreeBSD_arm::NativeRegisterContextFreeBSD_arm(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    : NativeRegisterContextRegisterInfo(
+          native_thread, new RegisterInfoPOSIX_arm(target_arch)) {}
+
+RegisterInfoPOSIX_arm &
+NativeRegisterContextFreeBSD_arm::GetRegisterInfo() const {
+  return static_cast<RegisterInfoPOSIX_arm &>(*m_register_info_interface_up);
+}
+
+uint32_t NativeRegisterContextFreeBSD_arm::GetRegisterSetCount() const {
+  return GetRegisterInfo().GetRegisterSetCount();
+}
+
+const RegisterSet *
+NativeRegisterContextFreeBSD_arm::GetRegisterSet(uint32_t set_index) const {
+  return GetRegisterInfo().GetRegisterSet(set_index);
+}
+
+uint32_t NativeRegisterContextFreeBSD_arm::GetUserRegisterCount() const {
+  uint32_t count = 0;
+  for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
+    count += GetRegisterSet(set_index)->num_registers;
+  return count;
+}
+
+Status NativeRegisterContextFreeBSD_arm::ReadRegisterSet(uint32_t set) {
+  switch (set) {
+  case RegisterInfoPOSIX_arm::GPRegSet:
+    return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
+                                               m_reg_data.data());
+  case RegisterInfoPOSIX_arm::FPRegSet:
+    return NativeProcessFreeBSD::PtraceWrapper(
+        PT_GETVFPREGS, m_thread.GetID(),
+        m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm::GPR));
+  }
+  llvm_unreachable("NativeRegisterContextFreeBSD_arm::ReadRegisterSet");
+}
+
+Status NativeRegisterContextFreeBSD_arm::WriteRegisterSet(uint32_t set) {
+  switch (set) {
+  case RegisterInfoPOSIX_arm::GPRegSet:
+    return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
+                                               m_reg_data.data());
+  case RegisterInfoPOSIX_arm::FPRegSet:
+    return NativeProcessFreeBSD::PtraceWrapper(
+        PT_SETVFPREGS, m_thread.GetID(),
+        m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm::GPR));
+  }
+  llvm_unreachable("NativeRegisterContextFreeBSD_arm::WriteRegisterSet");
+}
+
+Status
+NativeRegisterContextFreeBSD_arm::ReadRegister(const RegisterInfo *reg_info,
+                                               RegisterValue &reg_value) {
+  Status error;
+
+  if (!reg_info) {
+    error.SetErrorString("reg_info NULL");
+    return error;
+  }
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+  if (reg == LLDB_INVALID_REGNUM)
+    return Status("no lldb regnum for %s", reg_info && reg_info->name
+                                               ? reg_info->name
+                                               : "<unknown register>");
+
+  uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
+  error = ReadRegisterSet(set);
+  if (error.Fail())
+    return error;
+
+  assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+  reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
+                     reg_info->byte_size, endian::InlHostByteOrder());
+  return error;
+}
+
+Status NativeRegisterContextFreeBSD_arm::WriteRegister(
+    const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+  Status error;
+
+  if (!reg_info)
+    return Status("reg_info NULL");
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+  if (reg == LLDB_INVALID_REGNUM)
+    return Status("no lldb regnum for %s", reg_info && reg_info->name
+                                               ? reg_info->name
+                                               : "<unknown register>");
+
+  uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
+  error = ReadRegisterSet(set);
+  if (error.Fail())
+    return error;
+
+  assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+  ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
+           reg_info->byte_size);
+
+  return WriteRegisterSet(set);
+}
+
+Status NativeRegisterContextFreeBSD_arm::ReadAllRegisterValues(
+    lldb::DataBufferSP &data_sp) {
+  Status error;
+
+  error = ReadRegisterSet(RegisterInfoPOSIX_arm::GPRegSet);
+  if (error.Fail())
+    return error;
+
+  error = ReadRegisterSet(RegisterInfoPOSIX_arm::FPRegSet);
+  if (error.Fail())
+    return error;
+
+  data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
+  uint8_t *dst = data_sp->GetBytes();
+  ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
+
+  return error;
+}
+
+Status NativeRegisterContextFreeBSD_arm::WriteAllRegisterValues(
+    const lldb::DataBufferSP &data_sp) {
+  Status error;
+
+  if (!data_sp) {
+    error.SetErrorStringWithFormat(
+        "NativeRegisterContextFreeBSD_arm::%s invalid data_sp provided",
+        __FUNCTION__);
+    return error;
+  }
+
+  if (data_sp->GetByteSize() != m_reg_data.size()) {
+    error.SetErrorStringWithFormat(
+        "NativeRegisterContextFreeBSD_arm::%s data_sp contained mismatched "
+        "data size, expected %" PRIu64 ", actual %" PRIu64,
+        __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
+    return error;
+  }
+
+  uint8_t *src = data_sp->GetBytes();
+  if (src == nullptr) {
+    error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_arm::%s "
+                                   "DataBuffer::GetBytes() returned a null "
+                                   "pointer",
+                                   __FUNCTION__);
+    return error;
+  }
+  ::memcpy(m_reg_data.data(), src, m_reg_data.size());
+
+  error = WriteRegisterSet(RegisterInfoPOSIX_arm::GPRegSet);
+  if (error.Fail())
+    return error;
+
+  return WriteRegisterSet(RegisterInfoPOSIX_arm::FPRegSet);
+}
+
+llvm::Error NativeRegisterContextFreeBSD_arm::CopyHardwareWatchpointsFrom(
+    NativeRegisterContextFreeBSD &source) {
+  return llvm::Error::success();
+}
+
+#endif // defined (__arm__)

diff  --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_arm.h b/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_arm.h
new file mode 100644
index 000000000000..106aa07b1f75
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_arm.h
@@ -0,0 +1,68 @@
+//===-- NativeRegisterContextFreeBSD_arm.h ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm__)
+
+#ifndef lldb_NativeRegisterContextFreeBSD_arm_h
+#define lldb_NativeRegisterContextFreeBSD_arm_h
+
+// clang-format off
+#include <sys/types.h>
+#include <machine/reg.h>
+#include <machine/vfp.h>
+// clang-format on
+
+#include "Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
+
+#include <array>
+
+namespace lldb_private {
+namespace process_freebsd {
+
+class NativeProcessFreeBSD;
+
+class NativeRegisterContextFreeBSD_arm : public NativeRegisterContextFreeBSD {
+public:
+  NativeRegisterContextFreeBSD_arm(const ArchSpec &target_arch,
+                                   NativeThreadProtocol &native_thread);
+
+  uint32_t GetRegisterSetCount() const override;
+
+  uint32_t GetUserRegisterCount() const override;
+
+  const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+  Status ReadRegister(const RegisterInfo *reg_info,
+                      RegisterValue &reg_value) override;
+
+  Status WriteRegister(const RegisterInfo *reg_info,
+                       const RegisterValue &reg_value) override;
+
+  Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+  Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+  llvm::Error
+  CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
+private:
+  std::array<uint8_t, sizeof(reg) + sizeof(vfp_state)> m_reg_data;
+
+  Status ReadRegisterSet(uint32_t set);
+  Status WriteRegisterSet(uint32_t set);
+
+  RegisterInfoPOSIX_arm &GetRegisterInfo() const;
+};
+
+} // namespace process_freebsd
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextFreeBSD_arm_h
+
+#endif // defined (__arm__)

diff  --git a/lldb/unittests/Process/Utility/RegisterContextFreeBSDTest.cpp b/lldb/unittests/Process/Utility/RegisterContextFreeBSDTest.cpp
index 083e29d228b5..145b8b25059f 100644
--- a/lldb/unittests/Process/Utility/RegisterContextFreeBSDTest.cpp
+++ b/lldb/unittests/Process/Utility/RegisterContextFreeBSDTest.cpp
@@ -9,6 +9,9 @@
 // clang-format off
 #include <sys/types.h>
 #include <machine/reg.h>
+#if defined(__arm__)
+#include <machine/vfp.h>
+#endif
 // clang-format on
 
 #include "gmock/gmock.h"
@@ -17,7 +20,9 @@
 #include "Plugins/Process/Utility/lldb-x86-register-enums.h"
 #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
 #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
+#include "Plugins/Process/Utility/lldb-arm-register-enums.h"
 #include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
 
 using namespace lldb;
@@ -234,6 +239,77 @@ TEST(RegisterContextFreeBSDTest, i386) {
 
 #endif // defined(__i386__) || defined(__x86_64__)
 
+#if defined(__arm__)
+
+#define EXPECT_GPR_ARM(lldb_reg, fbsd_reg)                                     \
+  EXPECT_THAT(GetRegParams(reg_ctx, gpr_##lldb_reg##_arm),                     \
+              ::testing::Pair(offsetof(reg, fbsd_reg), sizeof(reg::fbsd_reg)))
+#define EXPECT_FPU_ARM(lldb_reg, fbsd_reg)                                     \
+  EXPECT_THAT(GetRegParams(reg_ctx, fpu_##lldb_reg##_arm),                     \
+              ::testing::Pair(offsetof(vfp_state, fbsd_reg) + base_offset,     \
+                              sizeof(vfp_state::fbsd_reg)))
+
+TEST(RegisterContextFreeBSDTest, arm) {
+  ArchSpec arch{"arm-unknown-freebsd"};
+  RegisterInfoPOSIX_arm reg_ctx{arch};
+
+  EXPECT_GPR_ARM(r0, r[0]);
+  EXPECT_GPR_ARM(r1, r[1]);
+  EXPECT_GPR_ARM(r2, r[2]);
+  EXPECT_GPR_ARM(r3, r[3]);
+  EXPECT_GPR_ARM(r4, r[4]);
+  EXPECT_GPR_ARM(r5, r[5]);
+  EXPECT_GPR_ARM(r6, r[6]);
+  EXPECT_GPR_ARM(r7, r[7]);
+  EXPECT_GPR_ARM(r8, r[8]);
+  EXPECT_GPR_ARM(r9, r[9]);
+  EXPECT_GPR_ARM(r10, r[10]);
+  EXPECT_GPR_ARM(r11, r[11]);
+  EXPECT_GPR_ARM(r12, r[12]);
+  EXPECT_GPR_ARM(sp, r_sp);
+  EXPECT_GPR_ARM(lr, r_lr);
+  EXPECT_GPR_ARM(pc, r_pc);
+  EXPECT_GPR_ARM(cpsr, r_cpsr);
+
+  size_t base_offset = reg_ctx.GetRegisterInfo()[fpu_d0_arm].byte_offset;
+
+  EXPECT_FPU_ARM(d0, reg[0]);
+  EXPECT_FPU_ARM(d1, reg[1]);
+  EXPECT_FPU_ARM(d2, reg[2]);
+  EXPECT_FPU_ARM(d3, reg[3]);
+  EXPECT_FPU_ARM(d4, reg[4]);
+  EXPECT_FPU_ARM(d5, reg[5]);
+  EXPECT_FPU_ARM(d6, reg[6]);
+  EXPECT_FPU_ARM(d7, reg[7]);
+  EXPECT_FPU_ARM(d8, reg[8]);
+  EXPECT_FPU_ARM(d9, reg[9]);
+  EXPECT_FPU_ARM(d10, reg[10]);
+  EXPECT_FPU_ARM(d11, reg[11]);
+  EXPECT_FPU_ARM(d12, reg[12]);
+  EXPECT_FPU_ARM(d13, reg[13]);
+  EXPECT_FPU_ARM(d14, reg[14]);
+  EXPECT_FPU_ARM(d15, reg[15]);
+  EXPECT_FPU_ARM(d16, reg[16]);
+  EXPECT_FPU_ARM(d17, reg[17]);
+  EXPECT_FPU_ARM(d18, reg[18]);
+  EXPECT_FPU_ARM(d19, reg[19]);
+  EXPECT_FPU_ARM(d20, reg[20]);
+  EXPECT_FPU_ARM(d21, reg[21]);
+  EXPECT_FPU_ARM(d22, reg[22]);
+  EXPECT_FPU_ARM(d23, reg[23]);
+  EXPECT_FPU_ARM(d24, reg[24]);
+  EXPECT_FPU_ARM(d25, reg[25]);
+  EXPECT_FPU_ARM(d26, reg[26]);
+  EXPECT_FPU_ARM(d27, reg[27]);
+  EXPECT_FPU_ARM(d28, reg[28]);
+  EXPECT_FPU_ARM(d29, reg[29]);
+  EXPECT_FPU_ARM(d30, reg[30]);
+  EXPECT_FPU_ARM(d31, reg[31]);
+  EXPECT_FPU_ARM(fpscr, fpscr);
+}
+
+#endif // defined(__arm__)
+
 #if defined(__aarch64__)
 
 #define EXPECT_GPR_ARM64(lldb_reg, fbsd_reg)                                   \


        


More information about the lldb-commits mailing list