[Lldb-commits] [lldb] [llvm] [lldb][FreeBSD][AArch64] Enable register field detection (PR #85058)
David Spickett via lldb-commits
lldb-commits at lists.llvm.org
Wed Jun 12 01:49:19 PDT 2024
https://github.com/DavidSpickett updated https://github.com/llvm/llvm-project/pull/85058
>From 60086c78d9be91704158f45e19813217289757b7 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Tue, 11 Jun 2024 13:41:18 +0000
Subject: [PATCH 1/2] [lldb] Do not produce field information for registers
known not to exist
Currently the logic is generate field information for all registers in
LinuxArm64RegisterFlags and then as we walk the existing register info,
only those that are in that existing info will get the new fields patched in.
This works fine but on a review for FreeBSD support it was pointed out
that this is not obvious from the source code.
So instead I've allowed the construction of empty lists of fields,
and field detection methods can return an empty field list if they
think that the register will never exist.
Then the pre-existing code will see the empty field list, and never
look for that register in the register info.
I think removing the assert is ok because the GDB classes filter
out empty field lists at runtime, and anyone updating the built in
field information would presumably notice if none of the fields they
intended to add were displayed.
mte_ctrl and svcr are the only registers that need this so far.
There is no extra testing here as the behaviour is the same, it
doesn't add field information to regiters that don't exist. The
mechanism is just clearer now.
---
.../Process/Utility/RegisterFlagsLinux_arm64.cpp | 11 +++++++++--
.../Process/Utility/RegisterFlagsLinux_arm64.h | 6 +++---
lldb/source/Target/RegisterFlags.cpp | 4 ----
3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
index 51553817921f3..8ed75d700f225 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
@@ -20,6 +20,7 @@
#define HWCAP2_BTI (1ULL << 17)
#define HWCAP2_MTE (1ULL << 18)
#define HWCAP2_AFP (1ULL << 20)
+#define HWCAP2_SME (1ULL << 23)
#define HWCAP2_EBF16 (1ULL << 32)
using namespace lldb_private;
@@ -27,7 +28,10 @@ using namespace lldb_private;
LinuxArm64RegisterFlags::Fields
LinuxArm64RegisterFlags::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
(void)hwcap;
- (void)hwcap2;
+
+ if (!(hwcap2 & HWCAP2_SME))
+ return {};
+
// Represents the pseudo register that lldb-server builds, which itself
// matches the architectural register SCVR. The fields match SVCR in the Arm
// manual.
@@ -40,7 +44,10 @@ LinuxArm64RegisterFlags::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
LinuxArm64RegisterFlags::Fields
LinuxArm64RegisterFlags::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2) {
(void)hwcap;
- (void)hwcap2;
+
+ if (!(hwcap2 & HWCAP2_MTE))
+ return {};
+
// 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.
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
index 660bef08700f4..49b1d90db64f6 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
@@ -38,8 +38,8 @@ class LinuxArm64RegisterFlags {
/// For the registers listed in this class, detect which fields are
/// present. Must be called before UpdateRegisterInfos.
/// If called more than once, fields will be redetected each time from
- /// scratch. If you do not have access to hwcap, just pass 0 for each one, you
- /// will only get unconditional fields.
+ /// scratch. If the target would not have this register at all, the list of
+ /// fields will be left empty.
void DetectFields(uint64_t hwcap, uint64_t hwcap2);
/// Add the field information of any registers named in this class,
@@ -63,7 +63,7 @@ class LinuxArm64RegisterFlags {
struct RegisterEntry {
RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
- : m_name(name), m_flags(std::string(name) + "_flags", size, {{"", 0}}),
+ : m_name(name), m_flags(std::string(name) + "_flags", size, {}),
m_detector(detector) {}
llvm::StringRef m_name;
diff --git a/lldb/source/Target/RegisterFlags.cpp b/lldb/source/Target/RegisterFlags.cpp
index 5274960587bf3..de9f12649e2ec 100644
--- a/lldb/source/Target/RegisterFlags.cpp
+++ b/lldb/source/Target/RegisterFlags.cpp
@@ -54,10 +54,6 @@ unsigned RegisterFlags::Field::PaddingDistance(const Field &other) const {
}
void RegisterFlags::SetFields(const std::vector<Field> &fields) {
- // We expect that the XML processor will discard anything describing flags but
- // with no fields.
- assert(fields.size() && "Some fields must be provided.");
-
// We expect that these are unsorted but do not overlap.
// They could fill the register but may have gaps.
std::vector<Field> provided_fields = fields;
>From 52f22cfe43bb02d05e791600ee35d65881f1b82c Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Mon, 4 Mar 2024 14:31:40 +0000
Subject: [PATCH 2/2] [lldb][FreeBSD][AArch64] Enable register field detection
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.
---
.../FreeBSD/NativeRegisterContextFreeBSD.h | 5 ++-
.../NativeRegisterContextFreeBSD_arm.cpp | 4 +--
.../NativeRegisterContextFreeBSD_arm64.cpp | 24 +++++++++++--
.../NativeRegisterContextFreeBSD_arm64.h | 2 +-
.../NativeRegisterContextFreeBSD_mips64.cpp | 4 +--
.../NativeRegisterContextFreeBSD_powerpc.cpp | 4 +--
.../NativeRegisterContextFreeBSD_x86_64.cpp | 4 +--
.../Process/FreeBSD/NativeThreadFreeBSD.cpp | 4 +++
.../Process/FreeBSD/NativeThreadFreeBSD.h | 2 ++
.../NativeRegisterContextLinux_arm64.cpp | 16 ++++-----
.../Plugins/Process/Utility/CMakeLists.txt | 2 +-
...64.cpp => RegisterFlagsDetector_arm64.cpp} | 36 ++++++++++---------
..._arm64.h => RegisterFlagsDetector_arm64.h} | 16 ++++-----
.../RegisterContextPOSIXCore_arm64.cpp | 18 +++++-----
.../elf-core/RegisterContextPOSIXCore_arm64.h | 4 +--
.../register_command/TestRegisters.py | 2 +-
.../Core/aarch64-freebsd-register-fields.test | 15 ++++++++
llvm/docs/ReleaseNotes.rst | 3 ++
.../source/Plugins/Process/Utility/BUILD.gn | 2 +-
19 files changed, 107 insertions(+), 60 deletions(-)
rename lldb/source/Plugins/Process/Utility/{RegisterFlagsLinux_arm64.cpp => RegisterFlagsDetector_arm64.cpp} (85%)
rename lldb/source/Plugins/Process/Utility/{RegisterFlagsLinux_arm64.h => RegisterFlagsDetector_arm64.h} (85%)
create mode 100644 lldb/test/Shell/Register/Core/aarch64-freebsd-register-fields.test
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
index 0000484beac99..b7f659ef24de2 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 2c50176643878..f19085600d6c9 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 9db5970af653e..28ea8b7ac1182 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 799209e26e868..ba876006c6c53 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 0349f13945e31..090d0f3802c3b 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 bdb57251f706a..fd5eb1ee2a1c8 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 f4171a134aeb7..5eed2d02b0a8c 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 449ec27e0da8f..a0de7751c7e55 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 6294a7a709635..edfb07658e19c 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 9b5f7aef1efe5..d72b6ce9b0c8e 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/CMakeLists.txt b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
index 37b53b7e3e7ed..5df4a9e5ac5c8 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 85%
rename from lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
rename to lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
index 8ed75d700f225..024c6ad208689 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)
@@ -25,8 +26,8 @@
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;
if (!(hwcap2 & HWCAP2_SME))
@@ -41,8 +42,9 @@ LinuxArm64RegisterFlags::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
};
}
-LinuxArm64RegisterFlags::Fields
-LinuxArm64RegisterFlags::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::Fields
+Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap,
+ uint64_t hwcap2) {
(void)hwcap;
if (!(hwcap2 & HWCAP2_MTE))
@@ -57,8 +59,8 @@ LinuxArm64RegisterFlags::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2) {
{"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.
@@ -93,8 +95,8 @@ LinuxArm64RegisterFlags::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
return fpcr_fields;
}
-LinuxArm64RegisterFlags::Fields
-LinuxArm64RegisterFlags::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::Fields
+Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) {
// fpsr's contents are constant.
(void)hwcap;
(void)hwcap2;
@@ -113,8 +115,8 @@ LinuxArm64RegisterFlags::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) {
};
}
-LinuxArm64RegisterFlags::Fields
-LinuxArm64RegisterFlags::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::Fields
+Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) {
// The fields here are a combination of the Arm manual's SPSR_EL1,
// plus a few changes where Linux has decided not to make use of them at all,
// or at least not from userspace.
@@ -131,7 +133,7 @@ LinuxArm64RegisterFlags::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) {
cpsr_fields.push_back({"DIT", 24});
// UAO and PAN are bits 23 and 22 and have no meaning for userspace so
- // are treated as reserved by the kernel.
+ // are treated as reserved by the kernels.
cpsr_fields.push_back({"SS", 21});
cpsr_fields.push_back({"IL", 20});
@@ -159,14 +161,14 @@ LinuxArm64RegisterFlags::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) {
return cpsr_fields;
}
-void LinuxArm64RegisterFlags::DetectFields(uint64_t hwcap, uint64_t hwcap2) {
+void Arm64RegisterFlagsDetector::DetectFields(uint64_t hwcap, uint64_t hwcap2) {
for (auto ® : m_registers)
reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2));
m_has_detected = true;
}
-void LinuxArm64RegisterFlags::UpdateRegisterInfo(const RegisterInfo *reg_info,
- uint32_t num_regs) {
+void Arm64RegisterFlagsDetector::UpdateRegisterInfo(
+ const RegisterInfo *reg_info, uint32_t num_regs) {
assert(m_has_detected &&
"Must call DetectFields before updating register info.");
@@ -206,4 +208,4 @@ void LinuxArm64RegisterFlags::UpdateRegisterInfo(const RegisterInfo *reg_info,
// We do not assert that search_registers is empty here, because it may
// contain registers from optional extensions that are not present on the
// current target.
-}
\ No newline at end of file
+}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
similarity index 85%
rename from lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
rename to lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
index 49b1d90db64f6..922a6387d6ed0 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
@@ -1,4 +1,4 @@
-//===-- RegisterFlagsLinux_arm64.h ------------------------------*- C++ -*-===//
+//===-- RegisterFlagsDetector_arm64.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.
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSLINUX_ARM64_H
-#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSLINUX_ARM64_H
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
#include "lldb/Target/RegisterFlags.h"
#include "llvm/ADT/StringRef.h"
@@ -18,9 +18,9 @@ namespace lldb_private {
struct RegisterInfo;
/// This class manages the storage and detection of register field information
-/// for Arm64 Linux registers. The same register may have different fields on
-/// different CPUs. This class abstracts out the field detection process so we
-/// can use it on live processes and core files.
+/// for Arm64 Linux and FreeBSD registers. The same register may have different
+/// fields on different CPUs. This class abstracts out the field detection
+/// process so we can use it on live processes and core files.
///
/// The general way to use this class is:
/// * Make an instance somewhere that will last as long as the debug session
@@ -33,7 +33,7 @@ struct RegisterInfo;
/// This must be done in that order, and you should ensure that if multiple
/// threads will reference the information, a mutex is used to make sure only
/// one calls DetectFields.
-class LinuxArm64RegisterFlags {
+class Arm64RegisterFlagsDetector {
public:
/// For the registers listed in this class, detect which fields are
/// present. Must be called before UpdateRegisterInfos.
@@ -83,4 +83,4 @@ class LinuxArm64RegisterFlags {
} // namespace lldb_private
-#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSLINUX_ARM64_H
\ No newline at end of file
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index 07501c10ec3c9..413bf1bbdb2a5 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -10,7 +10,7 @@
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
#include "Plugins/Process/Utility/AuxVector.h"
-#include "Plugins/Process/Utility/RegisterFlagsLinux_arm64.h"
+#include "Plugins/Process/Utility/RegisterFlagsDetector_arm64.h"
#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "Plugins/Process/elf-core/RegisterUtilities.h"
#include "lldb/Target/Thread.h"
@@ -79,17 +79,19 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
ProcessElfCore *process =
static_cast<ProcessElfCore *>(thread.GetProcess().get());
- if (process->GetArchitecture().GetTriple().getOS() == llvm::Triple::Linux) {
+ llvm::Triple::OSType os = process->GetArchitecture().GetTriple().getOS();
+ if ((os == llvm::Triple::Linux) || (os == llvm::Triple::FreeBSD)) {
AuxVector aux_vec(process->GetAuxvData());
- std::optional<uint64_t> auxv_at_hwcap =
- aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP);
+ std::optional<uint64_t> auxv_at_hwcap = aux_vec.GetAuxValue(
+ os == llvm::Triple::FreeBSD ? AuxVector::AUXV_FREEBSD_AT_HWCAP
+ : AuxVector::AUXV_AT_HWCAP);
std::optional<uint64_t> auxv_at_hwcap2 =
aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP2);
- m_linux_register_flags.DetectFields(auxv_at_hwcap.value_or(0),
- auxv_at_hwcap2.value_or(0));
- m_linux_register_flags.UpdateRegisterInfo(GetRegisterInfo(),
- GetRegisterCount());
+ m_register_flags_detector.DetectFields(auxv_at_hwcap.value_or(0),
+ auxv_at_hwcap2.value_or(0));
+ m_register_flags_detector.UpdateRegisterInfo(GetRegisterInfo(),
+ GetRegisterCount());
}
m_gpr_data.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
index 38e958851dfe2..ff94845e58d60 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
@@ -11,7 +11,7 @@
#include "Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
-#include "Plugins/Process/Utility/RegisterFlagsLinux_arm64.h"
+#include "Plugins/Process/Utility/RegisterFlagsDetector_arm64.h"
#include "Plugins/Process/elf-core/RegisterUtilities.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -75,7 +75,7 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
struct sme_pseudo_regs m_sme_pseudo_regs;
- lldb_private::LinuxArm64RegisterFlags m_linux_register_flags;
+ lldb_private::Arm64RegisterFlagsDetector m_register_flags_detector;
const uint8_t *GetSVEBuffer(uint64_t offset = 0);
diff --git a/lldb/test/API/commands/register/register/register_command/TestRegisters.py b/lldb/test/API/commands/register/register/register_command/TestRegisters.py
index 5c4f3a4bb374c..dd887740c3c12 100644
--- a/lldb/test/API/commands/register/register/register_command/TestRegisters.py
+++ b/lldb/test/API/commands/register/register/register_command/TestRegisters.py
@@ -619,7 +619,7 @@ def test_info_register(self):
self.expect("register info x30", substrs=["Name: lr (x30)"])
@skipIfXmlSupportMissing
- @skipUnlessPlatform(["linux"])
+ @skipUnlessPlatform(["linux", "freebsd"])
@skipIf(archs=no_match(["aarch64"]))
def test_register_read_fields(self):
"""Test that when debugging a live process, we see the fields of certain
diff --git a/lldb/test/Shell/Register/Core/aarch64-freebsd-register-fields.test b/lldb/test/Shell/Register/Core/aarch64-freebsd-register-fields.test
new file mode 100644
index 0000000000000..0c8b52c14b964
--- /dev/null
+++ b/lldb/test/Shell/Register/Core/aarch64-freebsd-register-fields.test
@@ -0,0 +1,15 @@
+# RUN: %lldb -b -s %s -c %p/Inputs/aarch64-freebsd-multithread.core | FileCheck %s
+
+# Check that we see register fields for control registers when using a core file.
+# As this is a corefile we check all fields as they will always be the same
+# (on real cores they may vary).
+
+register read cpsr
+# CHECK: cpsr = 0x60000200
+# CHECK-NEXT: = (N = 0, Z = 1, C = 1, V = 0, SS = 0, IL = 0, D = 1, A = 0, I = 0, F = 0, nRW = 0, EL = 0, SP = 0)
+register read fpsr
+# CHECK: fpsr = 0x00000000
+# CHECK-NEXT: = (QC = 0, IDC = 0, IXC = 0, UFC = 0, OFC = 0, DZC = 0, IOC = 0)
+register read fpcr
+# CHECK: fpcr = 0x02000000
+# CHECK-NEXT: = (AHP = 0, DN = 1, FZ = 0, RMode = 0, IDE = 0, IXE = 0, UFE = 0, OFE = 0, DZE = 0, IOE = 0)
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 50c43fef3ad12..28409b3909418 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -287,6 +287,9 @@ Changes to the LLVM tools
Changes to LLDB
---------------------------------
+* Register field information is now provided on AArch64 FreeBSD for live
+ processes and core files (previously only provided on AArch64 Linux).
+
Changes to Sanitizers
---------------------
diff --git a/llvm/utils/gn/secondary/lldb/source/Plugins/Process/Utility/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/Plugins/Process/Utility/BUILD.gn
index 4d98de81f3c26..acf279bf16373 100644
--- a/llvm/utils/gn/secondary/lldb/source/Plugins/Process/Utility/BUILD.gn
+++ b/llvm/utils/gn/secondary/lldb/source/Plugins/Process/Utility/BUILD.gn
@@ -66,7 +66,7 @@ static_library("Utility") {
"RegisterContextWindows_i386.cpp",
"RegisterContextWindows_x86_64.cpp",
"RegisterContext_x86.cpp",
- "RegisterFlagsLinux_arm64.cpp",
+ "RegisterFlagsDetector_arm64.cpp",
"RegisterInfoPOSIX_arm.cpp",
"RegisterInfoPOSIX_arm64.cpp",
"RegisterInfoPOSIX_loongarch64.cpp",
More information about the lldb-commits
mailing list