Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[LLDB] Warn about truncated DWARF section names on Windows #145175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Nerixyz
Copy link
Contributor

@Nerixyz Nerixyz commented Jun 21, 2025

Linking executables with DWARF sections on Windows with the default link.exe will truncate the section names, as sections in PE/COFF executable images can't be longer than 8 bytes. There's no warning about this. When trying to debug these executables in LLDB, no debug info will be loaded, because LLDB won't find the required sections and it doesn't find CodeView debug info. There's no warning here, either (this PR adds one).

I ran into this myself while playing around with LLDB:

  • Compile some file with Clang and use DWARF: clang-cl foo.c -gdwarf -o foo.exe
  • Open in LLDB lldb foo.exe
  • Break at line 10: b foo.c:10 ⚡ → "Unable to resolve breakpoint to any actual locations." (because no debug info is loaded)

The fix would be to pass -fuse-ld=lld-link to Clang.


This PR adds a warning when LLDB detects truncated DWARF sections (i.e. sections matching ^\.debug_[a-z]$):

warning: (x86_64) foo.exe contains 5 truncated DWARF sections (.debug_a, .debug_i, .debug_r, .debug_s, .debug_l).
Note: Executable images on Windows can't include the required names when linking with the default link.exe. A third party linker like lld-link is required (compile with -fuse-ld=lld-link on Clang).

I included the additional note, because to get to this point, one would have to have used Clang on windows-msvc (on MinGW, the default linker doesn't truncate the names), so they should have lld-link available as well.

@Nerixyz Nerixyz requested a review from JDevlieghere as a code owner June 21, 2025 16:07
@llvmbot llvmbot added the lldb label Jun 21, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 21, 2025

@llvm/pr-subscribers-lldb

Author: nerix (Nerixyz)

Changes

Linking executables with DWARF sections on Windows with the default link.exe will truncate the section names, as sections in PE/COFF executable images can't be longer than 8 bytes. There's no warning about this. When trying to debug these executables in LLDB, no debug info will be loaded, because LLDB won't find the required sections and it doesn't find CodeView debug info. There's no warning here, either (this PR adds one).

I ran into this myself while playing around with LLDB:

  • Compile some file with Clang and use DWARF: clang-cl foo.c -gdwarf -o foo.exe
  • Open in LLDB lldb foo.exe
  • Break at line 10: b foo.c:10 ⚡ → "Unable to resolve breakpoint to any actual locations." (because no debug info is loaded)

The fix would be to pass -fuse-ld=lld-link to Clang.


This PR adds a warning when LLDB detects truncated DWARF sections (i.e. sections matching ^\.debug_[a-z]$):

warning: (x86_64) foo.exe contains 5 truncated DWARF sections (.debug_a, .debug_i, .debug_r, .debug_s, .debug_l).
Note: Executable images on Windows can't include the required names when linking with the default link.exe. A third party linker like lld-link is required (compile with -fuse-ld=lld-link on Clang).

I included the additional note, because to get to this point, one would have to have used Clang on windows-msvc (on MinGW, the default linker doesn't truncate the names), so they should have lld-link available as well.


Full diff: https://github.com/llvm/llvm-project/pull/145175.diff

4 Files Affected:

  • (modified) lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp (+17)
  • (modified) lldb/test/Shell/ObjectFile/PECOFF/lit.local.cfg (+1-1)
  • (added) lldb/test/Shell/ObjectFile/PECOFF/truncated-dwarf.c (+7)
  • (modified) lldb/test/Shell/helper/build.py (+28-5)
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 4984445dcbab9..343d7477c66c7 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -1036,12 +1036,19 @@ void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
     m_sections_up->AddSection(header_sp);
     unified_section_list.AddSection(header_sp);
 
+    std::vector<llvm::StringRef> truncated_dwarf_sections;
     const uint32_t nsects = m_sect_headers.size();
     for (uint32_t idx = 0; idx < nsects; ++idx) {
       llvm::StringRef sect_name = GetSectionName(m_sect_headers[idx]);
       ConstString const_sect_name(sect_name);
       SectionType section_type = GetSectionType(sect_name, m_sect_headers[idx]);
 
+      // Detect unknown sections matching ^\.debug_[a-z]$
+      if (section_type == eSectionTypeOther && sect_name.size() == 8 &&
+          sect_name.starts_with(".debug_") && llvm::isLower(sect_name.back())) {
+        truncated_dwarf_sections.emplace_back(sect_name);
+      }
+
       SectionSP section_sp(new Section(
           module_sp,       // Module to which this section belongs
           this,            // Object file to which this section belongs
@@ -1071,6 +1078,16 @@ void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
       m_sections_up->AddSection(section_sp);
       unified_section_list.AddSection(section_sp);
     }
+
+    if (!truncated_dwarf_sections.empty()) {
+      module_sp->ReportWarning(
+          "contains {} truncated DWARF sections ({}).\n"
+          "Note: Executable images on Windows can't include the required names "
+          "when linking with the default link.exe. A third party linker like "
+          "lld-link is required (compile with -fuse-ld=lld-link on Clang).",
+          truncated_dwarf_sections.size(),
+          llvm::join(truncated_dwarf_sections, ", "));
+    }
   }
 }
 
diff --git a/lldb/test/Shell/ObjectFile/PECOFF/lit.local.cfg b/lldb/test/Shell/ObjectFile/PECOFF/lit.local.cfg
index 9ef350be1dee2..1ae00d07fc3e6 100644
--- a/lldb/test/Shell/ObjectFile/PECOFF/lit.local.cfg
+++ b/lldb/test/Shell/ObjectFile/PECOFF/lit.local.cfg
@@ -1 +1 @@
-config.suffixes = ['.yaml', '.test']
+config.suffixes = ['.yaml', '.test', '.c']
diff --git a/lldb/test/Shell/ObjectFile/PECOFF/truncated-dwarf.c b/lldb/test/Shell/ObjectFile/PECOFF/truncated-dwarf.c
new file mode 100644
index 0000000000000..92cb61050142a
--- /dev/null
+++ b/lldb/test/Shell/ObjectFile/PECOFF/truncated-dwarf.c
@@ -0,0 +1,7 @@
+// REQUIRES: target-windows
+// RUN: %build --compiler=clang-cl --force-dwarf-symbols --force-ms-link -o %t.exe -- %s
+// RUN: %lldb -f %t.exe 2>&1 | FileCheck %s
+
+int main(void) {}
+
+// CHECK: warning: {{.*}} contains 4 truncated DWARF sections (.debug_{{[a-z]}}, .debug_{{[a-z]}}, .debug_{{[a-z]}}, .debug_{{[a-z]}})
diff --git a/lldb/test/Shell/helper/build.py b/lldb/test/Shell/helper/build.py
index caaa14f90af1c..ecb02c1d7c87f 100755
--- a/lldb/test/Shell/helper/build.py
+++ b/lldb/test/Shell/helper/build.py
@@ -173,6 +173,22 @@
     help="Specify the C/C++ standard.",
 )
 
+if sys.platform == "win32":
+    parser.add_argument(
+        "--force-dwarf-symbols",
+        dest="force_dwarf_symbols",
+        action="store_true",
+        default=False,
+        help="When compiling with clang-cl on Windows, use DWARF instead of CodeView",
+    )
+    parser.add_argument(
+        "--force-ms-link",
+        dest="force_ms_link",
+        action="store_true",
+        default=False,
+        help="When compiling with clang-cl on Windows, always use link.exe",
+    )
+
 
 args = parser.parse_args(args=sys.argv[1:])
 
@@ -379,15 +395,20 @@ def __init__(self, toolchain_type, args):
                     )
 
         if self.mode == "link" or self.mode == "compile-and-link":
-            self.linker = (
-                self._find_linker("link")
-                if toolchain_type == "msvc"
-                else self._find_linker("lld-link", args.tools_dir)
-            )
+            if toolchain_type == "msvc" or args.force_ms_link:
+                search_paths = []
+                if toolchain_type != "msvc":
+                    search_paths.append(
+                        os.path.dirname(find_executable("cl", args.tools_dir))
+                    )
+                self.linker = self._find_linker("link", search_paths)
+            else:
+                self.linker = self._find_linker("lld-link", args.tools_dir)
             if not self.linker:
                 raise ValueError("Unable to find an appropriate linker.")
 
         self.compile_env, self.link_env = self._get_visual_studio_environment()
+        self.force_dwarf_symbols = args.force_dwarf_symbols
 
     def _find_linker(self, name, search_paths=[]):
         compiler_dir = os.path.dirname(self.compiler)
@@ -678,6 +699,8 @@ def _get_compilation_command(self, source, obj):
             args.append("/GR-")
         args.append("/Z7")
         if self.toolchain_type == "clang-cl":
+            if self.force_dwarf_symbols:
+                args.append("-gdwarf")
             args.append("-Xclang")
             args.append("-fkeep-static-consts")
             args.append("-fms-compatibility-version=19")

@Nerixyz Nerixyz force-pushed the feat/lldb-warn-on-trunc-dwarf-section branch from b58c2be to d2e8656 Compare June 21, 2025 16:24
Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable to me.

CC @charles-zablit

@Nerixyz Nerixyz force-pushed the feat/lldb-warn-on-trunc-dwarf-section branch from d2e8656 to c4ded34 Compare June 21, 2025 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants