[Lldb-commits] [lldb] [lldb][FreeBSDKernel] Implement trapframe unwinding (PR #192184)
David Spickett via lldb-commits
lldb-commits at lists.llvm.org
Wed Apr 15 03:43:17 PDT 2026
================
@@ -0,0 +1,260 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "PlatformFreeBSDKernel.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/Symtab.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/StreamString.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <set>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::platform_freebsdkernel;
+
+LLDB_PLUGIN_DEFINE(PlatformFreeBSDKernel)
+
+static uint32_t g_initialize_count = 0;
+
+PlatformFreeBSDKernel::PlatformFreeBSDKernel() : Platform(/*is_host=*/false) {
+ const llvm::Triple::ArchType arches[] = {
+ llvm::Triple::arm, // arm32 (legacy)
+ llvm::Triple::aarch64, // arm64
+ llvm::Triple::ppc64le, // powerpc64le
+ llvm::Triple::riscv64, // riscv64
+ llvm::Triple::x86, // i386 (legacy)
+ llvm::Triple::x86_64, // amd64
+ };
+
+ for (auto arch : arches) {
+ ArchSpec spec;
+ spec.SetTriple(llvm::Triple(llvm::Triple::getArchTypeName(arch), "unknown",
+ "freebsd"));
+ m_supported_architectures.push_back(spec);
+ }
+}
+
+void PlatformFreeBSDKernel::Initialize() {
+ Platform::Initialize();
+ if (g_initialize_count++ == 0) {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ nullptr);
+ }
+}
+
+void PlatformFreeBSDKernel::Terminate() {
+ if (g_initialize_count > 0) {
+ if (--g_initialize_count == 0)
+ PluginManager::UnregisterPlugin(CreateInstance);
+ }
+ Platform::Terminate();
+}
+
+lldb::PlatformSP PlatformFreeBSDKernel::CreateInstance(bool force,
+ const ArchSpec *arch) {
+ // PlatformFreeBSDKernel is never auto-selected. ProcessFreeBSDKernelCore sets
+ // this platform explicitly (force=true).
+ if (!force)
+ return nullptr;
+ return std::make_shared<PlatformFreeBSDKernel>();
+}
+
+void PlatformFreeBSDKernel::GetStatus(Stream &strm) {
+ Platform::GetStatus(strm);
+ strm.Printf(" Kernel Mode: yes\n");
+}
+
+std::vector<ArchSpec> PlatformFreeBSDKernel::GetSupportedArchitectures(
+ const ArchSpec &process_host_arch) {
+ return m_supported_architectures;
+}
+
+bool PlatformFreeBSDKernel::IsCompatibleArchitecture(
+ const ArchSpec &arch, const ArchSpec &process_host_arch,
+ ArchSpec::MatchType match, ArchSpec *compatible_arch_ptr) {
+ for (const auto &supported : m_supported_architectures) {
+ if (arch.IsCompatibleMatch(supported)) {
+ if (compatible_arch_ptr)
+ *compatible_arch_ptr = supported;
+ return true;
+ }
+ }
+ return false;
+}
+
+lldb::UnwindPlanSP
+PlatformFreeBSDKernel::GetTrapHandlerUnwindPlan(const ArchSpec &arch,
+ ConstString name) {
+ switch (arch.GetMachine()) {
+ case llvm::Triple::aarch64:
+ return GetTrapframeUnwindPlan_arm64(name);
+ case llvm::Triple::ppc64le:
+ return GetTrapframeUnwindPlan_ppc64le(name);
+ case llvm::Triple::riscv64:
+ return GetTrapframeUnwindPlan_riscv64(name);
+ case llvm::Triple::x86_64:
+ return GetTrapframeUnwindPlan_x86_64(name);
+
+ // UnwindPlan is not implemented for the archs below as they are not
+ // expressible as a static UnwindPlan.
+ case llvm::Triple::arm:
+ // SP/LR offsets depend on saved PSR mode bits (runtime memory read
+ // required.
+ case llvm::Triple::x86:
+ // Trapframe base depends on stub identity, kernel version opcode probe, and
+ // CPL of the interrupted context.
+ default:
+ return {};
+ }
+}
+
+void PlatformFreeBSDKernel::CalculateTrapHandlerSymbolNames() {
+ // Intentionally empty. All trap handler names are populated in
+ // PopulateTrapHandlerNames() once the target architecture is known.
+ // This override exists only to suppress the default implementation.
+}
----------------
DavidSpickett wrote:
If I understand correctly, for a "normal" platform your trap handler name is the same regardless of arch. For example FreeBSD userspace just lists _sigtramp. So I get why this does nothing.
What worries me is the ordering of these calls. Platform::GetTrapHandlerSymbolNames calls this and expects to get a reference to a vector of names. Which will be an empty vector at first.
But because it's a reference even if it thinks that it's calculated them at least when it later goes to look at the vector, your other function will have filled it in.
So it's not great but I see why it has to work this way.
Process already has m_calculated_trap_handlers, which makes m_trap_handlers_calculated rather confusing. I suggest m_arch_trap_handlers_calculated.
Or even simpler, will PopulateTrapHandlerNames ever be called more than once anyway? (aka will DoLoadCore be called more than once)
I see why you'd follow the pattern of the parent class, but you're changing the ordering anyway so I don't think you need to copy over the bool if you don't need it.
https://github.com/llvm/llvm-project/pull/192184
More information about the lldb-commits
mailing list