Author: Jonas Devlieghere
Date: 2026-07-01T15:58:21-07:00
New Revision: 0a2fb2a2269da0e2a3e230beb6cad39ca314db33

URL: 
https://github.com/llvm/llvm-project/commit/0a2fb2a2269da0e2a3e230beb6cad39ca314db33
DIFF: 
https://github.com/llvm/llvm-project/commit/0a2fb2a2269da0e2a3e230beb6cad39ca314db33.diff

LOG: [lldb] Find the default source file's main by base name (#207043)

SourceManager::GetDefaultFileAndLine locates the executable's main to
pick a default source file, used for input like "break set -l N" with no
file specified. It searched for main by full name, but a function's
linkage name can differ from its source name, in which case a full-name
search for "main" does not find it and no default file is chosen.

For example, wasi-libc renames main to __main_argc_argv, so on
WebAssembly the debug function for main was never matched and "break set
-l N" failed with "no default file available".

When we can't find "main", fall back to searching by base name.

Added: 
    lldb/test/API/functionalities/breakpoint/default_source_file/Makefile
    
lldb/test/API/functionalities/breakpoint/default_source_file/TestDefaultSourceFile.py
    lldb/test/API/functionalities/breakpoint/default_source_file/main.cpp
    lldb/test/API/functionalities/breakpoint/default_source_file/other.cpp

Modified: 
    lldb/source/Core/SourceManager.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Core/SourceManager.cpp 
b/lldb/source/Core/SourceManager.cpp
index d3e1bb5d332f0..d34d3c1cd8585 100644
--- a/lldb/source/Core/SourceManager.cpp
+++ b/lldb/source/Core/SourceManager.cpp
@@ -432,6 +432,12 @@ SourceManager::GetDefaultFileAndLine() {
         executable_ptr->FindFunctions(main_name, CompilerDeclContext(),
                                       lldb::eFunctionNameTypeFull,
                                       function_options, sc_list);
+        // The linkage name can 
diff er from the source name, so match on the
+        // base name as a fallback.
+        if (sc_list.GetSize() == 0)
+          executable_ptr->FindFunctions(main_name, CompilerDeclContext(),
+                                        lldb::eFunctionNameTypeBase,
+                                        function_options, sc_list);
         for (const SymbolContext &sc : sc_list) {
           if (sc.function) {
             lldb_private::LineEntry line_entry;

diff  --git 
a/lldb/test/API/functionalities/breakpoint/default_source_file/Makefile 
b/lldb/test/API/functionalities/breakpoint/default_source_file/Makefile
new file mode 100644
index 0000000000000..020dce7c31d11
--- /dev/null
+++ b/lldb/test/API/functionalities/breakpoint/default_source_file/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp other.cpp
+
+include Makefile.rules

diff  --git 
a/lldb/test/API/functionalities/breakpoint/default_source_file/TestDefaultSourceFile.py
 
b/lldb/test/API/functionalities/breakpoint/default_source_file/TestDefaultSourceFile.py
new file mode 100644
index 0000000000000..bf9349d570921
--- /dev/null
+++ 
b/lldb/test/API/functionalities/breakpoint/default_source_file/TestDefaultSourceFile.py
@@ -0,0 +1,27 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class DefaultSourceFileTestCase(TestBase):
+    def test_default_source_file_is_entry_point(self):
+        """The default file for a line breakpoint is main's file, not 
Foo::main's."""
+        self.build()
+        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+        self.assertTrue(target, VALID_TARGET)
+
+        entry_line = line_number("main.cpp", "BREAK: entry point")
+
+        # "break set -l" with no file picks the default source file: the one
+        # containing the entry point. Foo::main in other.cpp shares the base
+        # name "main" and must not be chosen instead.
+        lldbutil.run_break_set_by_file_and_line(
+            self, None, entry_line, num_expected_locations=1, loc_exact=True
+        )
+
+        bp = target.GetBreakpointAtIndex(0)
+        loc = bp.GetLocationAtIndex(0)
+        line_entry = loc.GetAddress().GetLineEntry()
+        self.assertEqual(line_entry.GetFileSpec().GetFilename(), "main.cpp")
+        self.assertEqual(line_entry.GetLine(), entry_line)

diff  --git 
a/lldb/test/API/functionalities/breakpoint/default_source_file/main.cpp 
b/lldb/test/API/functionalities/breakpoint/default_source_file/main.cpp
new file mode 100644
index 0000000000000..fb21ba7fd8ec8
--- /dev/null
+++ b/lldb/test/API/functionalities/breakpoint/default_source_file/main.cpp
@@ -0,0 +1,10 @@
+// The real entry point. The default source file for line-only breakpoints
+// should resolve to this file, not to other.cpp's ns::main.
+namespace ns {
+int main();
+}
+
+int main(int argc, char **argv) {
+  int local = argc; // BREAK: entry point
+  return ns::main() + local;
+}

diff  --git 
a/lldb/test/API/functionalities/breakpoint/default_source_file/other.cpp 
b/lldb/test/API/functionalities/breakpoint/default_source_file/other.cpp
new file mode 100644
index 0000000000000..418a275a21f8f
--- /dev/null
+++ b/lldb/test/API/functionalities/breakpoint/default_source_file/other.cpp
@@ -0,0 +1,9 @@
+// A function whose base name is also "main". Being a real debug function (not
+// just a symbol), it competes with the entry point in a base-name lookup and
+// must not be mistaken for it when choosing the default source file.
+namespace ns {
+int main() {
+  int value = 1;
+  return value; // ns::main body
+}
+} // namespace ns


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

Reply via email to