Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[lldb][FreeBSD][AArch64] Enable register field detection #85058

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

DavidSpickett
Copy link
Collaborator

This extends the existing register fields support from AArch64 Linux
to AArch64 FreeBSD. So you will now see output like this:

(lldb) register read cpsr
    cpsr = 0x60000200
         = (N = 0, Z = 1, C = 1, V = 0, DIT = 0, SS = 0, IL = 0, SSBS = 0, D = 1, A = 0, I = 0, F = 0, nRW = 0, EL = 0, SP = 0) 

Linux and FreeBSD both have HWCAP/HWCAP2 so the detection mechanism
is the same and I've renamed the detector class to reflect that.

I have confirmed that FreeBSD's treatment of CPSR (spsr as the kernel
calls it) is similair enough that we can use the same field information.

(see sys/arm64/include/armreg.h and PSR_SETTABLE_64)

For testing I've enabled the same live process test as Linux
and added a shell test using an existing FreeBSD core file.

Note that the latter does not need XML support because when reading
a core file we are not sending the information via target.xml,
it's just internal to LLDB.

The svcr and mte_ctrl registers will not appear on FreeBSD
at all so I've not made their information conditional, it'll just
never be used.

@DavidSpickett
Copy link
Collaborator Author

This is a stacked PR, the first two commits are #84147 and #85057.

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 13, 2024

@llvm/pr-subscribers-lldb

Author: David Spickett (DavidSpickett)

Changes

This extends the existing register fields support from AArch64 Linux
to AArch64 FreeBSD. So you will now see output like this:

(lldb) register read cpsr
    cpsr = 0x60000200
         = (N = 0, Z = 1, C = 1, V = 0, DIT = 0, SS = 0, IL = 0, SSBS = 0, D = 1, A = 0, I = 0, F = 0, nRW = 0, EL = 0, SP = 0) 

Linux and FreeBSD both have HWCAP/HWCAP2 so the detection mechanism
is the same and I've renamed the detector class to reflect that.

I have confirmed that FreeBSD's treatment of CPSR (spsr as the kernel
calls it) is similair enough that we can use the same field information.

(see sys/arm64/include/armreg.h and PSR_SETTABLE_64)

For testing I've enabled the same live process test as Linux
and added a shell test using an existing FreeBSD core file.

Note that the latter does not need XML support because when reading
a core file we are not sending the information via target.xml,
it's just internal to LLDB.

The svcr and mte_ctrl registers will not appear on FreeBSD
at all so I've not made their information conditional, it'll just
never be used.


Patch is 31.18 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/85058.diff

20 Files Affected:

  • (modified) lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h (+2-3)
  • (modified) lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp (+2-2)
  • (modified) lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp (+22-2)
  • (modified) lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h (+1-1)
  • (modified) lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp (+2-2)
  • (modified) lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp (+2-2)
  • (modified) lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp (+2-2)
  • (modified) lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp (+4)
  • (modified) lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h (+2)
  • (modified) lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (+8-8)
  • (modified) lldb/source/Plugins/Process/Utility/AuxVector.h (+30-17)
  • (modified) lldb/source/Plugins/Process/Utility/CMakeLists.txt (+1-1)
  • (renamed) lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp (+24-22)
  • (renamed) lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h (+10-8)
  • (modified) lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp (+10-8)
  • (modified) lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h (+2-2)
  • (modified) lldb/test/API/commands/register/register/register_command/TestRegisters.py (+1-1)
  • (added) lldb/test/Shell/Register/Core/aarch64-freebsd-register-fields.test (+15)
  • (modified) llvm/docs/ReleaseNotes.rst (+3)
  • (modified) llvm/utils/gn/secondary/lldb/source/Plugins/Process/Utility/BUILD.gn (+1-1)
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
index 0000484beac999..b7f659ef24de2c 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
@@ -9,14 +9,13 @@
 #ifndef lldb_NativeRegisterContextFreeBSD_h
 #define lldb_NativeRegisterContextFreeBSD_h
 
-#include "lldb/Host/common/NativeThreadProtocol.h"
-
 #include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
 
 namespace lldb_private {
 namespace process_freebsd {
 
 class NativeProcessFreeBSD;
+class NativeThreadFreeBSD;
 
 class NativeRegisterContextFreeBSD
     : public virtual NativeRegisterContextRegisterInfo {
@@ -28,7 +27,7 @@ class NativeRegisterContextFreeBSD
   // executable.
   static NativeRegisterContextFreeBSD *
   CreateHostNativeRegisterContextFreeBSD(const ArchSpec &target_arch,
-                                         NativeThreadProtocol &native_thread);
+                                         NativeThreadFreeBSD &native_thread);
   virtual llvm::Error
   CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) = 0;
 
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp
index 2c50176643878d..f19085600d6c93 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp
@@ -29,12 +29,12 @@ using namespace lldb_private::process_freebsd;
 
 NativeRegisterContextFreeBSD *
 NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
-    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+    const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) {
   return new NativeRegisterContextFreeBSD_arm(target_arch, native_thread);
 }
 
 NativeRegisterContextFreeBSD_arm::NativeRegisterContextFreeBSD_arm(
-    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread)
     : NativeRegisterContextRegisterInfo(
           native_thread, new RegisterInfoPOSIX_arm(target_arch)) {}
 
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
index 9db5970af653e3..28ea8b7ac11826 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
@@ -16,6 +16,7 @@
 
 #include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+#include "Plugins/Process/Utility/RegisterFlagsDetector_arm64.h"
 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
 
 // clang-format off
@@ -28,14 +29,29 @@ using namespace lldb;
 using namespace lldb_private;
 using namespace lldb_private::process_freebsd;
 
+// A NativeRegisterContext is constructed per thread, but all threads' registers
+// will contain the same fields. Therefore this mutex prevents each instance
+// competing with the other, and subsequent instances from having to detect the
+// fields all over again.
+static std::mutex g_register_flags_detector_mutex;
+static Arm64RegisterFlagsDetector g_register_flags_detector;
+
 NativeRegisterContextFreeBSD *
 NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
-    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+    const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) {
+  std::lock_guard<std::mutex> lock(g_register_flags_detector_mutex);
+  if (!g_register_flags_detector.HasDetected()) {
+    NativeProcessFreeBSD &process = native_thread.GetProcess();
+    g_register_flags_detector.DetectFields(
+        process.GetAuxValue(AuxVector::AUXV_FREEBSD_AT_HWCAP).value_or(0),
+        process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2).value_or(0));
+  }
+
   return new NativeRegisterContextFreeBSD_arm64(target_arch, native_thread);
 }
 
 NativeRegisterContextFreeBSD_arm64::NativeRegisterContextFreeBSD_arm64(
-    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread)
     : NativeRegisterContextRegisterInfo(
           native_thread, new RegisterInfoPOSIX_arm64(target_arch, 0))
 #ifdef LLDB_HAS_FREEBSD_WATCHPOINT
@@ -43,6 +59,10 @@ NativeRegisterContextFreeBSD_arm64::NativeRegisterContextFreeBSD_arm64(
       m_read_dbreg(false)
 #endif
 {
+  g_register_flags_detector.UpdateRegisterInfo(
+      GetRegisterInfoInterface().GetRegisterInfo(),
+      GetRegisterInfoInterface().GetRegisterCount());
+
   ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
   ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
 }
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
index 799209e26e868d..ba876006c6c530 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
@@ -37,7 +37,7 @@ class NativeRegisterContextFreeBSD_arm64
       public NativeRegisterContextDBReg_arm64 {
 public:
   NativeRegisterContextFreeBSD_arm64(const ArchSpec &target_arch,
-                                     NativeThreadProtocol &native_thread);
+                                     NativeThreadFreeBSD &native_thread);
 
   uint32_t GetRegisterSetCount() const override;
 
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp
index 0349f13945e31c..090d0f3802c3bb 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp
@@ -30,12 +30,12 @@ using namespace lldb_private::process_freebsd;
 
 NativeRegisterContextFreeBSD *
 NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
-    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+    const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) {
   return new NativeRegisterContextFreeBSD_mips64(target_arch, native_thread);
 }
 
 NativeRegisterContextFreeBSD_mips64::NativeRegisterContextFreeBSD_mips64(
-    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread)
     : NativeRegisterContextRegisterInfo(
           native_thread, new RegisterContextFreeBSD_mips64(target_arch)) {}
 
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp
index bdb57251f706a4..fd5eb1ee2a1c84 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp
@@ -67,7 +67,7 @@ static const RegisterSet g_reg_sets_powerpc[k_num_register_sets] = {
 
 NativeRegisterContextFreeBSD *
 NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
-    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+    const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) {
   return new NativeRegisterContextFreeBSD_powerpc(target_arch, native_thread);
 }
 
@@ -83,7 +83,7 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) {
 }
 
 NativeRegisterContextFreeBSD_powerpc::NativeRegisterContextFreeBSD_powerpc(
-    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread)
     : NativeRegisterContextRegisterInfo(
           native_thread, CreateRegisterInfoInterface(target_arch)) {}
 
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
index f4171a134aeb79..5eed2d02b0a8ce 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
@@ -237,7 +237,7 @@ static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
 
 NativeRegisterContextFreeBSD *
 NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
-    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+    const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) {
   return new NativeRegisterContextFreeBSD_x86_64(target_arch, native_thread);
 }
 
@@ -258,7 +258,7 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) {
 }
 
 NativeRegisterContextFreeBSD_x86_64::NativeRegisterContextFreeBSD_x86_64(
-    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread)
     : NativeRegisterContextRegisterInfo(
           native_thread, CreateRegisterInfoInterface(target_arch)),
       NativeRegisterContextDBReg_x86(native_thread), m_regset_offsets({0}) {
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
index 449ec27e0da8fc..a0de7751c7e55c 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
@@ -316,6 +316,10 @@ NativeThreadFreeBSD::CopyWatchpointsFrom(NativeThreadFreeBSD &source) {
   return s;
 }
 
+NativeProcessFreeBSD &NativeThreadFreeBSD::GetProcess() {
+  return static_cast<NativeProcessFreeBSD &>(m_process);
+}
+
 llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
 NativeThreadFreeBSD::GetSiginfo() const {
   Log *log = GetLog(POSIXLog::Process);
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
index 6294a7a7096356..edfb07658e19c7 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
@@ -47,6 +47,8 @@ class NativeThreadFreeBSD : public NativeThreadProtocol {
 
   Status RemoveHardwareBreakpoint(lldb::addr_t addr) override;
 
+  NativeProcessFreeBSD &GetProcess();
+
   llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
   GetSiginfo() const override;
 
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 9b5f7aef1efe53..d72b6ce9b0c8e3 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -23,7 +23,7 @@
 #include "Plugins/Process/Linux/Procfs.h"
 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
 #include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"
-#include "Plugins/Process/Utility/RegisterFlagsLinux_arm64.h"
+#include "Plugins/Process/Utility/RegisterFlagsDetector_arm64.h"
 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
 
 // System includes - They have to be included after framework includes because
@@ -72,8 +72,8 @@ using namespace lldb_private::process_linux;
 // will contain the same fields. Therefore this mutex prevents each instance
 // competing with the other, and subsequent instances from having to detect the
 // fields all over again.
-static std::mutex g_register_flags_mutex;
-static LinuxArm64RegisterFlags g_register_flags;
+static std::mutex g_register_flags_detector_mutex;
+static Arm64RegisterFlagsDetector g_register_flags_detector;
 
 std::unique_ptr<NativeRegisterContextLinux>
 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
@@ -144,10 +144,10 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
 
     opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskTLS);
 
-    std::lock_guard<std::mutex> lock(g_register_flags_mutex);
-    if (!g_register_flags.HasDetected())
-      g_register_flags.DetectFields(auxv_at_hwcap.value_or(0),
-                                    auxv_at_hwcap2.value_or(0));
+    std::lock_guard<std::mutex> lock(g_register_flags_detector_mutex);
+    if (!g_register_flags_detector.HasDetected())
+      g_register_flags_detector.DetectFields(auxv_at_hwcap.value_or(0),
+                                             auxv_at_hwcap2.value_or(0));
 
     auto register_info_up =
         std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
@@ -171,7 +171,7 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
     : NativeRegisterContextRegisterInfo(native_thread,
                                         register_info_up.release()),
       NativeRegisterContextLinux(native_thread) {
-  g_register_flags.UpdateRegisterInfo(
+  g_register_flags_detector.UpdateRegisterInfo(
       GetRegisterInfoInterface().GetRegisterInfo(),
       GetRegisterInfoInterface().GetRegisterCount());
 
diff --git a/lldb/source/Plugins/Process/Utility/AuxVector.h b/lldb/source/Plugins/Process/Utility/AuxVector.h
index 3b0f55d35e5d11..9e489b05ab5ee6 100644
--- a/lldb/source/Plugins/Process/Utility/AuxVector.h
+++ b/lldb/source/Plugins/Process/Utility/AuxVector.h
@@ -20,25 +20,34 @@ class AuxVector {
   AuxVector(const lldb_private::DataExtractor &data);
 
   /// Constants describing the type of entry.
-  /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX
+  /// On Linux and FreeBSD, running "LD_SHOW_AUXV=1 ./executable" will spew AUX
   /// information. Added AUXV prefix to avoid potential conflicts with system-
-  /// defined macros
+  /// defined macros. For FreeBSD, the numbers can be found in sys/elf_common.h.
+  ///
+  /// Linux and FreeBSD values diverge, so the FreeBSD classes will convert
+  /// some entries to the Linux AT_ value so that LLDB only has to use
+  /// the constants listed here when asking the AuxVector for a value.
   enum EntryType {
-    AUXV_AT_NULL = 0,      ///< End of auxv.
-    AUXV_AT_IGNORE = 1,    ///< Ignore entry.
-    AUXV_AT_EXECFD = 2,    ///< File descriptor of program.
-    AUXV_AT_PHDR = 3,      ///< Program headers.
-    AUXV_AT_PHENT = 4,     ///< Size of program header.
-    AUXV_AT_PHNUM = 5,     ///< Number of program headers.
-    AUXV_AT_PAGESZ = 6,    ///< Page size.
-    AUXV_AT_BASE = 7,      ///< Interpreter base address.
-    AUXV_AT_FLAGS = 8,     ///< Flags.
-    AUXV_AT_ENTRY = 9,     ///< Program entry point.
-    AUXV_AT_NOTELF = 10,   ///< Set if program is not an ELF.
-    AUXV_AT_UID = 11,      ///< UID.
-    AUXV_AT_EUID = 12,     ///< Effective UID.
-    AUXV_AT_GID = 13,      ///< GID.
-    AUXV_AT_EGID = 14,     ///< Effective GID.
+    AUXV_AT_NULL = 0,    ///< End of auxv.
+    AUXV_AT_IGNORE = 1,  ///< Ignore entry.
+    AUXV_AT_EXECFD = 2,  ///< File descriptor of program.
+    AUXV_AT_PHDR = 3,    ///< Program headers.
+    AUXV_AT_PHENT = 4,   ///< Size of program header.
+    AUXV_AT_PHNUM = 5,   ///< Number of program headers.
+    AUXV_AT_PAGESZ = 6,  ///< Page size.
+    AUXV_AT_BASE = 7,    ///< Interpreter base address.
+    AUXV_AT_FLAGS = 8,   ///< Flags.
+    AUXV_AT_ENTRY = 9,   ///< Program entry point.
+    AUXV_AT_NOTELF = 10, ///< Set if program is not an ELF.
+    AUXV_AT_UID = 11,    ///< UID.
+    AUXV_AT_EUID = 12,   ///< Effective UID.
+    AUXV_AT_GID = 13,    ///< GID.
+    AUXV_AT_EGID = 14,   ///< Effective GID.
+
+    // At this point Linux and FreeBSD diverge and many of the following values
+    // are Linux specific. If you use them make sure you are in Linux specific
+    // code or they have the same value on other platforms.
+
     AUXV_AT_CLKTCK = 17,   ///< Clock frequency (e.g. times(2)).
     AUXV_AT_PLATFORM = 15, ///< String identifying platform.
     AUXV_AT_HWCAP =
@@ -60,6 +69,10 @@ class AuxVector {
     AUXV_AT_L1D_CACHESHAPE = 35,
     AUXV_AT_L2_CACHESHAPE = 36,
     AUXV_AT_L3_CACHESHAPE = 37,
+
+    // Platform specific values which may overlap the Linux values.
+
+    AUXV_FREEBSD_AT_HWCAP = 25, ///< FreeBSD specific AT_HWCAP value.
   };
 
   std::optional<uint64_t> GetAuxValue(enum EntryType entry_type) const;
diff --git a/lldb/source/Plugins/Process/Utility/CMakeLists.txt b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
index 37b53b7e3e7edd..5df4a9e5ac5c86 100644
--- a/lldb/source/Plugins/Process/Utility/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
@@ -47,7 +47,7 @@ add_lldb_library(lldbPluginProcessUtility
   RegisterContextThreadMemory.cpp
   RegisterContextWindows_i386.cpp
   RegisterContextWindows_x86_64.cpp
-  RegisterFlagsLinux_arm64.cpp
+  RegisterFlagsDetector_arm64.cpp
   RegisterInfos_x86_64_with_base_shared.cpp
   RegisterInfoPOSIX_arm.cpp
   RegisterInfoPOSIX_arm64.cpp
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
similarity index 80%
rename from lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
rename to lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
index 51553817921f35..54c1aae36f231c 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
@@ -1,4 +1,4 @@
-//===-- RegisterFlagsLinux_arm64.cpp --------------------------------------===//
+//===-- RegisterFlagsDetector_arm64.cpp -----------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,11 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "RegisterFlagsLinux_arm64.h"
+#include "RegisterFlagsDetector_arm64.h"
 #include "lldb/lldb-private-types.h"
 
 // This file is built on all systems because it is used by native processes and
 // core files, so we manually define the needed HWCAP values here.
+// These values are the same for Linux and FreeBSD.
 
 #define HWCAP_FPHP (1ULL << 9)
 #define HWCAP_ASIMDHP (1ULL << 10)
@@ -24,34 +25,35 @@
 
 using namespace lldb_private;
 
-LinuxArm64RegisterFlags::Fields
-LinuxArm64RegisterFlags::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::Fields
+Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
   (void)hwcap;
   (void)hwcap2;
-  // Represents the pseudo register that lldb-server builds, which itself
-  // matches the architectural register SCVR. The fields match SVCR in the Arm
-  // manual.
+  // Represents the pseudo register that lldb-server on Linux builds, which
+  // itself matches the architectural register SCVR. The fields match SVCR in
+  // the Arm manual.
   return {
       {"ZA", 1},
       {"SM", 0},
   };
 }
 
-LinuxArm64RegisterFlags::Fields
-LinuxArm64RegisterFlags::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::Fields
+Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap,
+                                                uint64_t hwcap2) {
   (void)hwcap;
   (void)hwcap2;
-  // Represents the contents of NT_ARM_TAGGED_ADDR_CTRL and the value passed
-  // to prctl(PR_TAGGED_ADDR_CTRL...). Fields are derived from the defines
-  // used to build the value.
+  // Represents the contents of Linux's NT_ARM_TAGGED_ADDR_CTRL and the value
+  // passed to prctl(PR_TAGGED_ADDR_CTRL...). Fields are derived from the
+  // defines used to build the value.
   return {{"TAGS", 3, 18}, // 16 bit bitfield shifted up by PR_MTE_TAG_SHIFT.
           {"TCF_ASYNC", 2},
           {"TCF_SYNC", 1},
           {"TAGGED_ADDR_ENABLE", 0}};
 }
 
-LinuxArm64RegisterFlags::Fields
-LinuxArm64RegisterFlags::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::Fields
+Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
   std::vector<RegisterFlags::Field> fpcr_fields{
       {"AHP", 26}, {"DN", 25}, {"FZ", 24}, {"RMode", 22, 23},
       // Bits 21-20 are "Stride" which is unused in AArch64 state.
@@ -86,8 +88,8 @@ LinuxArm64RegisterFlags::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
   return fpcr_fields;
 }
 
-LinuxArm64RegisterFlags...
[truncated]

This extends the existing register fields support from AArch64 Linux
to AArch64 FreeBSD. So you will now see output like this:
```
(lldb) register read cpsr
    cpsr = 0x60000200
         = (N = 0, Z = 1, C = 1, V = 0, DIT = 0, SS = 0, IL = 0, SSBS = 0, D = 1, A = 0, I = 0, F = 0, nRW = 0, EL = 0, SP = 0)
```

Linux and FreeBSD both have HWCAP/HWCAP2 so the detection mechanism
is the same and I've renamed the detector class to reflect that.

I have confirmed that FreeBSD's treatment of CPSR (spsr as the kernel
calls it) is similair enough that we can use the same field information.

(see `sys/arm64/include/armreg.h` and `PSR_SETTABLE_64`)

For testing I've enabled the same live process test as Linux
and added a shell test using an existing FreeBSD core file.

Note that the latter does not need XML support because when reading
a core file we are not sending the information via target.xml,
it's just internal to LLDB.

The `svcr` and `mte_ctrl` registers will not appear on FreeBSD
at all so I've not made their information conditional, it'll just
never be used.
@DavidSpickett
Copy link
Collaborator Author

@emaste the previous PRs have landed so this is just a single commit now, easier to review.

Copy link
Collaborator

@clayborg clayborg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a follow up patch, it would be nice to add the ability to expand registers that are ValueObjectRegister.h/.cpp to that a register value object can tell us how many children and vend a ValueObjectRegisterField object for each field where each one has the name, value and possibly summary if the field is an enum that has a string representation.

Like for the 32 bit ARM CPSR register's mode field which is 5 bits ([4:0]) with values like:

CPSR_M_USR = 0x10U
CPSR_M_FIQ = 0x11U
CPSR_M_IRQ = 0x12U
CPSR_M_SVC = 0x13U
CPSR_M_MON = 0x16U
CPSR_M_ABT = 0x17U
CPSR_M_HYP = 0x1AU
CPSR_M_UND = 0x1BU
CPSR_M_SYS = 0x1FU

Then if the value of M was 0x10, we would show "0x10" as the value of the ValueObjectRegisterField, and the summary would be "CPSR_M_USR".

@DavidSpickett
Copy link
Collaborator Author

https://discourse.llvm.org/t/rfc-adding-register-field-enums-to-lldb/77275 aims to add the type information we need for that, and that will initially be visible via register info. Register fields themselves do not have descriptions yet, but it is a simple addition that I want to do after enums.

I haven't done anything with value objects yet, just focused on from register read but I would like to make all this available in the API and later lldb-dap so it's on my radar.

@DavidSpickett
Copy link
Collaborator Author

@emaste ping!

@emaste
Copy link
Member

emaste commented May 1, 2024

@zxombie fyi

@zxombie
Copy link
Contributor

zxombie commented May 22, 2024

It looks like svcr is for SME & mte_ctrl is for MTE. Neither of these are currently supported in FreeBSD. When they are supported the appropriate HWCAP flags (and ID_AA64* registers) will be set to tell userspace it can use them.

@DavidSpickett
Copy link
Collaborator Author

I'm currently assuming that the process classes will check those HWCAPs and only add those registers to the register info if they exist. This code only patches registers that are already in the info, it doesn't add any new ones.

That said, explicit is better than implicit, and I already have the HWCAP values to hand, so I will try checking them to see what should exist or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants