https://github.com/da-viper updated 
https://github.com/llvm/llvm-project/pull/178695

>From 8ef6eac983b5f31ddb75825180e1bd056f1a19d9 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <[email protected]>
Date: Thu, 29 Jan 2026 16:17:05 +0000
Subject: [PATCH 1/4] [lldb] Improve trampoline function detection

The mold linker adds a function symbol to the symbol table (.symtab) for
every shared library exported function.
So if we try to step into a library, lldb will fail because the symbol
at the address is not a trampline function.

Example:
```cpp
lib.c
int lib_add(int a, int b);
```
when we link the library to an executable, mold will create the normal
trampoline functions in the .plt section but add an extra symbol in
symbol table `lib_add$plt`.

This patch adds a new method Module::FindSymbolsContainingFileAddress()
to find symbols of a specific type that contain a given file address.
---
 lldb/include/lldb/Core/Module.h               |  4 +++
 lldb/source/Core/Module.cpp                   | 17 ++++++++++++
 .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp     | 27 +++++++++++++++++--
 3 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index 643b9a5c3bf54..87d828fb41eed 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -265,6 +265,10 @@ class Module : public std::enable_shared_from_this<Module>,
                                   lldb::SymbolType symbol_type,
                                   SymbolContextList &sc_list);
 
+  void FindSymbolsContainingFileAddress(const Address &addr,
+                                        lldb::SymbolType symbol_type,
+                                        SymbolContextList &sc_list);
+
   void FindSymbolsMatchingRegExAndType(
       const RegularExpression &regex, lldb::SymbolType symbol_type,
       SymbolContextList &sc_list,
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 486af1a053344..436c4ce027d84 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -1316,6 +1316,23 @@ void Module::FindSymbolsWithNameAndType(ConstString name,
   }
 }
 
+void Module::FindSymbolsContainingFileAddress(const Address &addr,
+                                              lldb::SymbolType symbol_type,
+                                              SymbolContextList &sc_list) {
+  if (Symtab *symtab = GetSymtab()) {
+    std::vector<uint32_t> symbol_indexes;
+    symtab->ForEachSymbolContainingFileAddress(
+        addr.GetFileAddress(), [&, symbol_type](Symbol *match_sym) {
+          if (const lldb::SymbolType curr_type = match_sym->GetType();
+              curr_type == lldb::eSymbolTypeAny || curr_type == symbol_type) {
+            symbol_indexes.push_back(symtab->GetIndexForSymbol(match_sym));
+          }
+          return true;
+        });
+    SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list);
+  }
+}
+
 void Module::FindSymbolsMatchingRegExAndType(
     const RegularExpression &regex, SymbolType symbol_type,
     SymbolContextList &sc_list, Mangled::NamePreference mangling_preference) {
diff --git 
a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp 
b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 6705ac139f0fb..8802b4b7cd27b 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -540,11 +540,34 @@ 
DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread,
 
   StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
   const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);
-  const Symbol *sym = context.symbol;
 
-  if (sym == nullptr || !sym->IsTrampoline())
+  Symbol *sym = context.symbol;
+  if (sym == nullptr)
     return thread_plan_sp;
 
+  if (!sym->IsTrampoline()) {
+    if (sym->GetType() != lldb::eSymbolTypeCode)
+      return thread_plan_sp;
+
+    SymbolContextList addr_ctx_list;
+    context.module_sp->FindSymbolsContainingFileAddress(
+        context.GetFunctionOrSymbolAddress(), eSymbolTypeTrampoline,
+        addr_ctx_list);
+    if (addr_ctx_list.IsEmpty())
+      return thread_plan_sp;
+
+    for (const auto &sym_ctx : addr_ctx_list.SymbolContexts()) {
+      if (sym_ctx.symbol != nullptr) {
+        sym = sym_ctx.symbol;
+        break;
+      }
+    }
+
+    // may not find a match
+    if (sym == nullptr)
+      return thread_plan_sp;
+  }
+
   ConstString sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
   if (!sym_name)
     return thread_plan_sp;

>From 3c1a701b00f5b075b8f3d89c8ec3a6db98745a3d Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <[email protected]>
Date: Thu, 29 Jan 2026 16:35:09 +0000
Subject: [PATCH 2/4] missing comment

---
 .../Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp  | 1 +
 1 file changed, 1 insertion(+)

diff --git 
a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp 
b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 8802b4b7cd27b..97e3116029f25 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -549,6 +549,7 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread 
&thread,
     if (sym->GetType() != lldb::eSymbolTypeCode)
       return thread_plan_sp;
 
+    // Check if any trampoline symbols exists at the file address.
     SymbolContextList addr_ctx_list;
     context.module_sp->FindSymbolsContainingFileAddress(
         context.GetFunctionOrSymbolAddress(), eSymbolTypeTrampoline,

>From f583543276287d58b7788653c07cfc096120ecd5 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <[email protected]>
Date: Mon, 9 Feb 2026 13:12:37 +0000
Subject: [PATCH 3/4] add review changes

Add testcase
---
 .../Python/lldbsuite/test/configuration.py    |  11 ++
 lldb/packages/Python/lldbsuite/test/dotest.py |   1 +
 lldb/source/Core/Module.cpp                   |  26 ++---
 .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp     |   2 +-
 .../Makefile                                  |   7 ++
 .../TestStepThroughTrampolineWithSymbol.py    | 102 ++++++++++++++++++
 .../step-through-trampoline-with-symbol/add.c |   5 +
 .../step-through-trampoline-with-symbol/add.h |   1 +
 .../main.c                                    |   6 ++
 9 files changed, 148 insertions(+), 13 deletions(-)
 create mode 100644 
lldb/test/API/lang/c/step-through-trampoline-with-symbol/Makefile
 create mode 100644 
lldb/test/API/lang/c/step-through-trampoline-with-symbol/TestStepThroughTrampolineWithSymbol.py
 create mode 100644 
lldb/test/API/lang/c/step-through-trampoline-with-symbol/add.c
 create mode 100644 
lldb/test/API/lang/c/step-through-trampoline-with-symbol/add.h
 create mode 100644 
lldb/test/API/lang/c/step-through-trampoline-with-symbol/main.c

diff --git a/lldb/packages/Python/lldbsuite/test/configuration.py 
b/lldb/packages/Python/lldbsuite/test/configuration.py
index f96fd31b17a37..082e9a90c6d05 100644
--- a/lldb/packages/Python/lldbsuite/test/configuration.py
+++ b/lldb/packages/Python/lldbsuite/test/configuration.py
@@ -65,6 +65,9 @@
 # Path to the nm tool.
 nm: Optional[str] = None
 
+# Path to the objcopy tool
+objcopy: Optional[str] = None
+
 # Path to the yaml2obj tool. Not optional.
 yaml2obj = None
 
@@ -183,6 +186,14 @@ def get_nm_path():
         return nm
 
 
+def get_objcopy_path():
+    """
+    Get the path to the objcopy tool.
+    """
+    if objcopy and os.path.lexists(objcopy):
+        return objcopy
+
+
 def get_yaml2obj_path():
     """
     Get the path to the yaml2obj tool.
diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py 
b/lldb/packages/Python/lldbsuite/test/dotest.py
index 533be0a065e3a..f8595b50041e2 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest.py
@@ -283,6 +283,7 @@ def parseOptionsAndInitTestdirs():
         configuration.nm = shutil.which(
             "llvm-nm", path=args.llvm_tools_dir
         ) or shutil.which("nm", path=args.llvm_tools_dir)
+        configuration.objcopy = shutil.which("llvm-objcopy", 
path=args.llvm_tools_dir)
 
     if not configuration.get_filecheck_path():
         logging.warning("No valid FileCheck executable; some tests may 
fail...")
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 436c4ce027d84..3fe2a714be071 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -1319,18 +1319,20 @@ void Module::FindSymbolsWithNameAndType(ConstString 
name,
 void Module::FindSymbolsContainingFileAddress(const Address &addr,
                                               lldb::SymbolType symbol_type,
                                               SymbolContextList &sc_list) {
-  if (Symtab *symtab = GetSymtab()) {
-    std::vector<uint32_t> symbol_indexes;
-    symtab->ForEachSymbolContainingFileAddress(
-        addr.GetFileAddress(), [&, symbol_type](Symbol *match_sym) {
-          if (const lldb::SymbolType curr_type = match_sym->GetType();
-              curr_type == lldb::eSymbolTypeAny || curr_type == symbol_type) {
-            symbol_indexes.push_back(symtab->GetIndexForSymbol(match_sym));
-          }
-          return true;
-        });
-    SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list);
-  }
+  Symtab *symtab = GetSymtab();
+  if (!symtab)
+    return;
+
+  std::vector<uint32_t> symbol_indexes;
+  symtab->ForEachSymbolContainingFileAddress(
+      addr.GetFileAddress(), [&, symbol_type](Symbol *match_sym) {
+        if (const lldb::SymbolType curr_type = match_sym->GetType();
+            curr_type == lldb::eSymbolTypeAny || curr_type == symbol_type) {
+          symbol_indexes.push_back(symtab->GetIndexForSymbol(match_sym));
+        }
+        return true;
+      });
+  SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list);
 }
 
 void Module::FindSymbolsMatchingRegExAndType(
diff --git 
a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp 
b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 97e3116029f25..97890f77356ab 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -541,7 +541,7 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread 
&thread,
   StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
   const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);
 
-  Symbol *sym = context.symbol;
+  const Symbol *sym = context.symbol;
   if (sym == nullptr)
     return thread_plan_sp;
 
diff --git a/lldb/test/API/lang/c/step-through-trampoline-with-symbol/Makefile 
b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/Makefile
new file mode 100644
index 0000000000000..8ed10dfbb86ba
--- /dev/null
+++ b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/Makefile
@@ -0,0 +1,7 @@
+DYLIB_NAME := add
+DYLIB_C_SOURCES := add.c
+C_SOURCES := main.c
+LD_EXTRAS := -fcf-protection=none
+
+include Makefile.rules
+
diff --git 
a/lldb/test/API/lang/c/step-through-trampoline-with-symbol/TestStepThroughTrampolineWithSymbol.py
 
b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/TestStepThroughTrampolineWithSymbol.py
new file mode 100644
index 0000000000000..40d40df6daf75
--- /dev/null
+++ 
b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/TestStepThroughTrampolineWithSymbol.py
@@ -0,0 +1,102 @@
+"""
+Test case to verify stepping behavior into shared library functions.
+Specifically, this tests the scenario where a function's trampoline
+(PLT stub) has a different symbol at its file address,
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import TestBase, line_number, configuration
+import lldbsuite.test.lldbutil as lldbutil
+
+
+class StepThroughTrampolineWithSymbol(TestBase):
+    SYMBOL_NAME = "lib_add"
+    FAKE_SYMBOL_NAME = "fake_lib_add"
+
+    def test(self):
+        modified_exe = self.create_modified_exe()
+        (_target, _process, thread, _bkpt) = lldbutil.run_to_source_breakpoint(
+            self,
+            "// Set a breakpoint here",
+            lldb.SBFileSpec("main.c"),
+            exe_name=modified_exe,
+            extra_images=["add"],
+        )
+
+        error = lldb.SBError()
+        thread.StepInto(
+            None, lldb.LLDB_INVALID_LINE_NUMBER, error, 
lldb.eOnlyDuringStepping
+        )
+
+        self.assertTrue(error.Success(), f"step into failed: 
{error.GetCString()}")
+
+        # Check frame in cli.
+        add_stop_line = line_number("add.c", "// End up here")
+        self.expect(
+            "frame info", substrs=[self.SYMBOL_NAME, 
"add.c:{}:".format(add_stop_line)]
+        )
+
+        # Check frame in SBAPI.
+        current_frame = thread.selected_frame
+        self.assertTrue(current_frame.IsValid())
+        function_name = current_frame.function.name
+        self.assertEqual(function_name, self.SYMBOL_NAME)
+
+        frame_module = current_frame.module
+        self.assertTrue(frame_module.IsValid())
+        frame_module_name = frame_module.file.basename
+        self.assertEqual(frame_module_name, "libadd.so")
+
+    def create_modified_exe(self) -> str:
+        """
+        Build the executable, find the `lib_add` trampoline and add
+        an the symbol `fake_lib_add` at the trampoline's file address
+
+        Returns the modified executable.
+        """
+        self.build()
+        exe = self.getBuildArtifact("a.out")
+        modulespec = lldb.SBModuleSpec()
+        modulespec.SetFileSpec(lldb.SBFileSpec(exe))
+        module = lldb.SBModule(modulespec)
+        self.assertTrue(module.IsValid())
+
+        add_trampoline = lldb.SBSymbol()
+        for sym in module.symbols:
+            if sym.name == self.SYMBOL_NAME and sym.type == 
lldb.eSymbolTypeTrampoline:
+                add_trampoline = sym
+                break
+
+        self.assertTrue(add_trampoline.IsValid())
+
+        # Get the trampoline's section and offset.
+        add_address = add_trampoline.addr
+        self.assertTrue(add_address.IsValid())
+
+        add_section_name = add_address.section.name
+        self.assertIn(".plt", add_section_name)
+        add_section_offset = add_address.offset
+
+        # Add a new symbol to the file address of lib_add trampoline.
+        modified_exe = self.getBuildArtifact("mod_a.out")
+        objcopy_bin = configuration.get_objcopy_path()
+
+        build_command = [
+            objcopy_bin,
+            "--add-symbol",
+            
f"{self.FAKE_SYMBOL_NAME}={add_section_name}:{add_section_offset},function,local",
+            exe,
+            modified_exe,
+        ]
+        self.runBuildCommand(build_command)
+
+        # Verify we added the fake symbol.
+        modified_modulespec = lldb.SBModuleSpec()
+        modified_modulespec.SetFileSpec(lldb.SBFileSpec(modified_exe))
+        modified_module = lldb.SBModule(modified_modulespec)
+        self.assertTrue(modified_module.IsValid())
+
+        fake_symbol = modified_module.FindSymbol(self.FAKE_SYMBOL_NAME)
+        self.assertTrue(fake_symbol.IsValid())
+
+        return modified_exe
diff --git a/lldb/test/API/lang/c/step-through-trampoline-with-symbol/add.c 
b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/add.c
new file mode 100644
index 0000000000000..0169aa4649d44
--- /dev/null
+++ b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/add.c
@@ -0,0 +1,5 @@
+#include "add.h"
+
+int lib_add(int LHS, int RHS) {
+  return LHS + RHS; // End up here
+}
diff --git a/lldb/test/API/lang/c/step-through-trampoline-with-symbol/add.h 
b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/add.h
new file mode 100644
index 0000000000000..22f973b85ff23
--- /dev/null
+++ b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/add.h
@@ -0,0 +1 @@
+LLDB_TEST_API extern int lib_add(int LHS, int RHS);
diff --git a/lldb/test/API/lang/c/step-through-trampoline-with-symbol/main.c 
b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/main.c
new file mode 100644
index 0000000000000..62b0391bcb990
--- /dev/null
+++ b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/main.c
@@ -0,0 +1,6 @@
+#include "add.h"
+
+int main(void) {
+  int result = lib_add(10, 20); // Set a breakpoint here
+  return 0;
+}

>From e0d2d2b56c26a333ea87ae06dea0c96f7f12198c Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <[email protected]>
Date: Tue, 10 Feb 2026 18:08:28 +0000
Subject: [PATCH 4/4] add review changes

---
 lldb/include/lldb/Core/Module.h               | 21 ++++++++++++++++---
 lldb/source/Core/Module.cpp                   | 16 ++++++++------
 .../TestStepThroughTrampolineWithSymbol.py    |  2 ++
 3 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index 87d828fb41eed..4b4ce631f16e6 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -265,9 +265,24 @@ class Module : public std::enable_shared_from_this<Module>,
                                   lldb::SymbolType symbol_type,
                                   SymbolContextList &sc_list);
 
-  void FindSymbolsContainingFileAddress(const Address &addr,
-                                        lldb::SymbolType symbol_type,
-                                        SymbolContextList &sc_list);
+  /// Find all symbols at a given file address.
+  ///
+  /// This function searches for symbols of a specified type that contain
+  /// the provided file address within their address range.
+  ///
+  /// \param[in] addr
+  ///     The file address to search for within symbol ranges.
+  ///
+  /// \param[in] symbol_type
+  ///     The type of symbols to search for (e.g., code, data, trampoline).
+  ///     Use lldb::eSymbolTypeAny to search all symbol types.
+  ///
+  /// \return
+  ///     A SymbolContextList containing all matching symbols that contain
+  ///     the specified address. Returns an empty list if no symbols are found.
+  SymbolContextList
+  FindSymbolsContainingFileAddress(const Address &addr,
+                                   lldb::SymbolType symbol_type);
 
   void FindSymbolsMatchingRegExAndType(
       const RegularExpression &regex, lldb::SymbolType symbol_type,
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 3fe2a714be071..c7b178506192d 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -1316,23 +1316,27 @@ void Module::FindSymbolsWithNameAndType(ConstString 
name,
   }
 }
 
-void Module::FindSymbolsContainingFileAddress(const Address &addr,
-                                              lldb::SymbolType symbol_type,
-                                              SymbolContextList &sc_list) {
+SymbolContextList
+Module::FindSymbolsContainingFileAddress(const Address &addr,
+                                         lldb::SymbolType symbol_type) {
   Symtab *symtab = GetSymtab();
   if (!symtab)
-    return;
+    return {};
 
   std::vector<uint32_t> symbol_indexes;
   symtab->ForEachSymbolContainingFileAddress(
       addr.GetFileAddress(), [&, symbol_type](Symbol *match_sym) {
-        if (const lldb::SymbolType curr_type = match_sym->GetType();
-            curr_type == lldb::eSymbolTypeAny || curr_type == symbol_type) {
+        if (const lldb::SymbolType match_sym_type = match_sym->GetType();
+            match_sym_type == lldb::eSymbolTypeAny ||
+            match_sym_type == symbol_type) {
           symbol_indexes.push_back(symtab->GetIndexForSymbol(match_sym));
         }
         return true;
       });
+
+  SymbolContextList sc_list;
   SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list);
+  return sc_list;
 }
 
 void Module::FindSymbolsMatchingRegExAndType(
diff --git 
a/lldb/test/API/lang/c/step-through-trampoline-with-symbol/TestStepThroughTrampolineWithSymbol.py
 
b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/TestStepThroughTrampolineWithSymbol.py
index 40d40df6daf75..e738ab8553926 100644
--- 
a/lldb/test/API/lang/c/step-through-trampoline-with-symbol/TestStepThroughTrampolineWithSymbol.py
+++ 
b/lldb/test/API/lang/c/step-through-trampoline-with-symbol/TestStepThroughTrampolineWithSymbol.py
@@ -5,10 +5,12 @@
 """
 
 import lldb
+from lldbsuite.test.decorators import skipUnlessPlatform
 from lldbsuite.test.lldbtest import TestBase, line_number, configuration
 import lldbsuite.test.lldbutil as lldbutil
 
 
+@skipUnlessPlatform(["linux"])
 class StepThroughTrampolineWithSymbol(TestBase):
     SYMBOL_NAME = "lib_add"
     FAKE_SYMBOL_NAME = "fake_lib_add"

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to