Skip to content

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

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

Merged
merged 2 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -28,21 +29,40 @@ 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
,
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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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)) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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}) {
Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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);
Expand All @@ -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());

Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Process/Utility/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
//===-- 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.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#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)
Expand All @@ -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))
Expand All @@ -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))
Expand All @@ -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.
Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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});
Expand Down Expand Up @@ -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 &reg : 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.");

Expand Down Expand Up @@ -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.
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//===-- 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.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#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"
Expand All @@ -17,12 +17,12 @@ 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.
/// This class manages the storage and detection of register field information.
/// 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:
/// The way to use this class is:
/// * Make an instance somewhere that will last as long as the debug session
/// (because your final register info will point to this instance).
/// * Read hardware capabilities from a core note, binary, prctl, etc.
Expand All @@ -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.
Expand Down Expand Up @@ -83,4 +83,4 @@ class LinuxArm64RegisterFlags {

} // namespace lldb_private

#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSLINUX_ARM64_H
#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
Loading
Loading