https://github.com/GeorgeHuyubo created 
https://github.com/llvm/llvm-project/pull/144406

In the context if locate_module callback is registered and debuginfod is 
enabled.
If debuginfod symbol locator is called first then we are double downloading the 
debuginfo file through locate module callback and debuginfod.

To fix this, we want to a way to define the priority of a plugin, so that we 
can adjust the order of each plugin gets called at runtime.

```
(lldb)settings set plugin.symbol-locator.debuginfod.priority 1
(lldb) image list
...
[  4] 581109F0-138B-AD5B-2E0B-1EB3E5174353-632286CF 0x00007f977c600000 
/tmp/symbol_cache/581109f0138bad5b2e0b1eb3e5174353632286cf/libcrypto.so.1.1 
      
/home/hyubo/.cache/llvm-debuginfod/client/llvmcache-581109f0138bad5b2e0b1eb3e5174353632286cf-libcrypto.so.1.1.debuginfo
```
Debuginfod plugin is prioritized

```
(lldb)settings set plugin.symbol-locator.debuginfod.priority 3
(lldb) image list
...
[  4] 581109F0-138B-AD5B-2E0B-1EB3E5174353-632286CF 0x00007f977c600000 
/tmp/symbol_cache/581109f0138bad5b2e0b1eb3e5174353632286cf/libcrypto.so.1.1 
      
/tmp/symbol_cache/581109f0138bad5b2e0b1eb3e5174353632286cf/libcrypto.so.1.1.debuginfo
```
Default plugin is prioritized, local debuginfo is used.

>From a60a15ee140a261c9902cdbfaa9811fe87c291fc Mon Sep 17 00:00:00 2001
From: George Hu <georgehuy...@gmail.com>
Date: Mon, 16 Jun 2025 10:57:26 -0700
Subject: [PATCH] [lldb] Implement priority system for symbol locator plugin

---
 lldb/include/lldb/Core/PluginManager.h        |  3 +-
 lldb/include/lldb/Symbol/SymbolLocator.h      |  3 +
 lldb/include/lldb/lldb-private-interfaces.h   |  1 +
 lldb/source/Core/PluginManager.cpp            | 60 ++++++++++++++++---
 .../Debuginfod/SymbolLocatorDebuginfod.cpp    | 20 ++++++-
 .../SymbolLocatorDebuginfodProperties.td      |  3 +
 6 files changed, 80 insertions(+), 10 deletions(-)

diff --git a/lldb/include/lldb/Core/PluginManager.h 
b/lldb/include/lldb/Core/PluginManager.h
index e7b1691031111..021f90f54abff 100644
--- a/lldb/include/lldb/Core/PluginManager.h
+++ b/lldb/include/lldb/Core/PluginManager.h
@@ -431,7 +431,8 @@ class PluginManager {
       SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file =
           nullptr,
       SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle = nullptr,
-      DebuggerInitializeCallback debugger_init_callback = nullptr);
+      DebuggerInitializeCallback debugger_init_callback = nullptr,
+      SymbolLocatorGetPriority get_priority_callback = nullptr);
 
   static bool UnregisterPlugin(SymbolLocatorCreateInstance create_callback);
 
diff --git a/lldb/include/lldb/Symbol/SymbolLocator.h 
b/lldb/include/lldb/Symbol/SymbolLocator.h
index 8d2f26b3d0cca..0eb9d34cb1cc6 100644
--- a/lldb/include/lldb/Symbol/SymbolLocator.h
+++ b/lldb/include/lldb/Symbol/SymbolLocator.h
@@ -14,6 +14,9 @@
 
 namespace lldb_private {
 
+// Default priority for symbol locator plugins
+static constexpr uint32_t kDefaultSymbolLocatorPriority = 2;
+
 class SymbolLocator : public PluginInterface {
 public:
   SymbolLocator() = default;
diff --git a/lldb/include/lldb/lldb-private-interfaces.h 
b/lldb/include/lldb/lldb-private-interfaces.h
index d366dbd1d7832..0fe59e28adaa6 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -100,6 +100,7 @@ typedef std::optional<FileSpec> 
(*SymbolLocatorLocateExecutableSymbolFile)(
 typedef bool (*SymbolLocatorDownloadObjectAndSymbolFile)(
     ModuleSpec &module_spec, Status &error, bool force_lookup,
     bool copy_executable);
+typedef uint64_t (*SymbolLocatorGetPriority)();
 using BreakpointHitCallback =
     std::function<bool(void *baton, StoppointCallbackContext *context,
                        lldb::user_id_t break_id, lldb::user_id_t 
break_loc_id)>;
diff --git a/lldb/source/Core/PluginManager.cpp 
b/lldb/source/Core/PluginManager.cpp
index 5d44434033c55..fedfd3f1e7b6f 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -13,6 +13,7 @@
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Interpreter/OptionValueProperties.h"
 #include "lldb/Symbol/SaveCoreOptions.h"
+#include "lldb/Symbol/SymbolLocator.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/Status.h"
@@ -25,6 +26,7 @@
 #include <map>
 #include <memory>
 #include <mutex>
+#include <queue>
 #include <string>
 #include <utility>
 #include <vector>
@@ -323,6 +325,29 @@ template <typename Instance> class PluginInstances {
     return enabled_instances;
   }
 
+  // Return a priority queue of all enabled instances, ordered by priority
+  // (lower priority values = higher priority in queue)
+  template <typename PriorityGetter>
+  std::priority_queue<Instance, std::vector<Instance>,
+                      std::function<bool(const Instance &, const Instance &)>>
+  GetPriorityQueue(PriorityGetter get_priority) {
+    // Create comparator that orders by priority (lower values = higher
+    // priority)
+    auto comparator = [get_priority](const Instance &a, const Instance &b) {
+      return get_priority(a) > get_priority(b); // Reverse for min-heap 
behavior
+    };
+
+    std::priority_queue<Instance, std::vector<Instance>,
+                        std::function<bool(const Instance &, const Instance 
&)>>
+        pq(comparator);
+
+    for (const auto &instance : m_instances) {
+      if (instance.enabled)
+        pq.push(instance);
+    }
+    return pq;
+  }
+
   const Instance *GetInstanceAtIndex(uint32_t idx) {
     uint32_t count = 0;
 
@@ -1223,18 +1248,26 @@ struct SymbolLocatorInstance
       SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file,
       SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file,
       SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle,
-      DebuggerInitializeCallback debugger_init_callback)
+      DebuggerInitializeCallback debugger_init_callback,
+      SymbolLocatorGetPriority get_priority_callback)
       : PluginInstance<SymbolLocatorCreateInstance>(
             name, description, create_callback, debugger_init_callback),
         locate_executable_object_file(locate_executable_object_file),
         locate_executable_symbol_file(locate_executable_symbol_file),
         download_object_symbol_file(download_object_symbol_file),
-        find_symbol_file_in_bundle(find_symbol_file_in_bundle) {}
+        find_symbol_file_in_bundle(find_symbol_file_in_bundle),
+        get_priority_callback(get_priority_callback) {}
+
+  uint64_t GetPriority() const {
+    return get_priority_callback ? get_priority_callback()
+                                 : kDefaultSymbolLocatorPriority;
+  }
 
   SymbolLocatorLocateExecutableObjectFile locate_executable_object_file;
   SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file;
   SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file;
   SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle;
+  SymbolLocatorGetPriority get_priority_callback;
 };
 typedef PluginInstances<SymbolLocatorInstance> SymbolLocatorInstances;
 
@@ -1250,11 +1283,13 @@ bool PluginManager::RegisterPlugin(
     SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file,
     SymbolLocatorDownloadObjectAndSymbolFile download_object_symbol_file,
     SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle,
-    DebuggerInitializeCallback debugger_init_callback) {
+    DebuggerInitializeCallback debugger_init_callback,
+    SymbolLocatorGetPriority get_priority_callback) {
   return GetSymbolLocatorInstances().RegisterPlugin(
       name, description, create_callback, locate_executable_object_file,
       locate_executable_symbol_file, download_object_symbol_file,
-      find_symbol_file_in_bundle, debugger_init_callback);
+      find_symbol_file_in_bundle, debugger_init_callback,
+      get_priority_callback);
 }
 
 bool PluginManager::UnregisterPlugin(
@@ -1270,8 +1305,13 @@ 
PluginManager::GetSymbolLocatorCreateCallbackAtIndex(uint32_t idx) {
 ModuleSpec
 PluginManager::LocateExecutableObjectFile(const ModuleSpec &module_spec,
                                           StatisticsMap &map) {
-  auto instances = GetSymbolLocatorInstances().GetSnapshot();
-  for (auto &instance : instances) {
+  auto pq = GetSymbolLocatorInstances().GetPriorityQueue(
+      [](const auto &instance) { return instance.GetPriority(); });
+
+  while (!pq.empty()) {
+    auto instance = pq.top();
+    pq.pop();
+
     if (instance.locate_executable_object_file) {
       StatsDuration time;
       std::optional<ModuleSpec> result;
@@ -1290,8 +1330,12 @@ PluginManager::LocateExecutableObjectFile(const 
ModuleSpec &module_spec,
 FileSpec PluginManager::LocateExecutableSymbolFile(
     const ModuleSpec &module_spec, const FileSpecList &default_search_paths,
     StatisticsMap &map) {
-  auto instances = GetSymbolLocatorInstances().GetSnapshot();
-  for (auto &instance : instances) {
+  auto pq = GetSymbolLocatorInstances().GetPriorityQueue(
+      [](const auto &instance) { return instance.GetPriority(); });
+
+  while (!pq.empty()) {
+    auto instance = pq.top();
+    pq.pop();
     if (instance.locate_executable_symbol_file) {
       StatsDuration time;
       std::optional<FileSpec> result;
diff --git 
a/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp 
b/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp
index f9aa6b1a98765..3e2d863d0d20e 100644
--- a/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp
+++ b/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfod.cpp
@@ -83,6 +83,16 @@ class PluginProperties : public Properties {
     }
   }
 
+  uint32_t GetPriority() const {
+    std::optional<uint32_t> priority =
+        m_collection_sp->GetPropertyAtIndexAs<uint64_t>(ePropertyPriority);
+    if (priority && *priority > 0) {
+      return priority.value();
+    } else {
+      return kDefaultSymbolLocatorPriority;
+    }
+  }
+
 private:
   void ServerURLsChangedCallback() {
     m_server_urls = GetDebugInfoDURLs();
@@ -103,6 +113,13 @@ static PluginProperties &GetGlobalPluginProperties() {
   return g_settings;
 }
 
+static uint64_t GetDebuginfodPriority() {
+  // Grab LLDB's Debuginfod overrides from the
+  // plugin.symbol-locator.debuginfod.* settings.
+  PluginProperties &plugin_props = GetGlobalPluginProperties();
+  return plugin_props.GetPriority();
+}
+
 SymbolLocatorDebuginfod::SymbolLocatorDebuginfod() : SymbolLocator() {}
 
 void SymbolLocatorDebuginfod::Initialize() {
@@ -112,7 +129,8 @@ void SymbolLocatorDebuginfod::Initialize() {
     PluginManager::RegisterPlugin(
         GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
         LocateExecutableObjectFile, LocateExecutableSymbolFile, nullptr,
-        nullptr, SymbolLocatorDebuginfod::DebuggerInitialize);
+        nullptr, SymbolLocatorDebuginfod::DebuggerInitialize,
+        GetDebuginfodPriority);
     llvm::HTTPClient::initialize();
   });
 }
diff --git 
a/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfodProperties.td
 
b/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfodProperties.td
index 0ff02674b8ea3..32389f8808b6f 100644
--- 
a/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfodProperties.td
+++ 
b/lldb/source/Plugins/SymbolLocator/Debuginfod/SymbolLocatorDebuginfodProperties.td
@@ -10,4 +10,7 @@ let Definition = "symbollocatordebuginfod" in {
   def Timeout : Property<"timeout", "UInt64">,
     DefaultUnsignedValue<0>,
     Desc<"Timeout (in seconds) for requests made to a DEBUGINFOD server. A 
value of zero means we use the debuginfod default timeout: DEBUGINFOD_TIMEOUT 
if the environment variable is set and 90 seconds otherwise.">;
+  def Priority : Property<"priority", "UInt64">,
+    DefaultUnsignedValue<2>,
+    Desc<"The priority order for this symbol locator plugin when multiple 
symbol locators are available. Lower values indicate higher priority. The 
default symbol locator priority is 2">;
 }

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to