[Lldb-commits] [lldb] [lldb][AArch64][Linux] Add field information for the CPSR register (PR #70300)
David Spickett via lldb-commits
lldb-commits at lists.llvm.org
Tue Nov 7 02:24:19 PST 2023
================
@@ -0,0 +1,102 @@
+//===-- RegisterFlagsLinux_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 "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.
+
+#define HWCAP_DIT (1 << 24)
+#define HWCAP_SSBS (1 << 28)
+
+#define HWCAP2_BTI (1 << 17)
+#define HWCAP2_MTE (1 << 18)
+
+using namespace lldb_private;
+
+LinuxArm64RegisterFlags::Fields
+LinuxArm64RegisterFlags::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.
+
+ // Status bits that are always present.
+ std::vector<RegisterFlags::Field> cpsr_fields{
+ {"N", 31}, {"Z", 30}, {"C", 29}, {"V", 28},
+ // Bits 27-26 reserved.
+ };
+
+ if (hwcap2 & HWCAP2_MTE)
+ cpsr_fields.push_back({"TCO", 25});
+ if (hwcap & HWCAP_DIT)
+ 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.
+
+ cpsr_fields.push_back({"SS", 21});
+ cpsr_fields.push_back({"IL", 20});
+ // Bits 19-14 reserved.
+
+ // Bit 13, ALLINT, requires FEAT_NMI that isn't relevant to userspace, and we
+ // can't detect either, don't show this field.
+ if (hwcap & HWCAP_SSBS)
+ cpsr_fields.push_back({"SSBS", 12});
+ if (hwcap2 & HWCAP2_BTI)
+ cpsr_fields.push_back({"BTYPE", 10, 11});
+
+ cpsr_fields.push_back({"D", 9});
+ cpsr_fields.push_back({"A", 8});
+ cpsr_fields.push_back({"I", 7});
+ cpsr_fields.push_back({"F", 6});
+ // Bit 5 reserved
+ // Called "M" in the ARMARM.
+ cpsr_fields.push_back({"nRW", 4});
+ // This is a 4 bit field M[3:0] in the ARMARM, we split it into parts.
+ cpsr_fields.push_back({"EL", 2, 3});
+ // Bit 1 is unused and expected to be 0.
+ cpsr_fields.push_back({"SP", 0});
+
+ return cpsr_fields;
+}
+
+void LinuxArm64RegisterFlags::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) {
+ assert(m_has_detected &&
+ "Must call DetectFields before updating register info.");
+
+ // Register names will not be duplicated, so we do not want to compare against
+ // one if it has already been found. Each time we find one, we erase it from
+ // this list.
+ std::vector<std::pair<const char *, const RegisterFlags *>> search_registers;
+ for (const auto ® : m_registers) {
+ // It is possible that a register is all extension dependent fields, and
+ // none of them are present.
+ if (reg.m_flags.GetFields().size())
+ search_registers.push_back({reg.m_name, ®.m_flags});
+ }
+
+ uint32_t idx = 0;
+ for (; idx < num_regs && search_registers.size(); ++idx, ++reg_info) {
+ auto end = search_registers.cend();
+ for (auto it = search_registers.cbegin(); it != end; ++it) {
+ if (std::strcmp(reg_info->name, it->first) == 0) {
+ reg_info->flags_type = it->second;
+ search_registers.erase(it);
+ break;
+ }
+ }
+ }
+}
----------------
DavidSpickett wrote:
Remove if doesn't early exit, but I've switched to find_if as it means we're not (at least visually) mutating a container while we're iterating it.
Also added a comment to explain that we don't want to assert the search_registers are empty at the end, which won't always be the case.
https://github.com/llvm/llvm-project/pull/70300
More information about the lldb-commits
mailing list