[Lldb-commits] [lldb] 36e1dfd - [lldb][NativePDB] don't assert when a public symbol sits past its section (#225734)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Sep 23 10:51:52 PDT 2026
Author: Charles Zablit
Date: 2026-09-23T18:51:44+01:00
New Revision: 36e1dfd58c07b213a5d57095247629f63381ed75
URL: https://github.com/llvm/llvm-project/commit/36e1dfd58c07b213a5d57095247629f63381ed75
DIFF: https://github.com/llvm/llvm-project/commit/36e1dfd58c07b213a5d57095247629f63381ed75.diff
LOG: [lldb][NativePDB] don't assert when a public symbol sits past its section (#225734)
Fix an assertion failure in `SymbolFileNativePDB::AddSymbols` when a
public symbol's offset doesn't agree with its section's size (happens
with real-world PDBs after incremental linking). Instead of asserting,
we now log and skip the size estimate for that symbol.
Also adds a regression test that crafts such a PDB and checks lldb
doesn't crash.
This fixes crashes in swiftlang.
Added:
lldb/test/Shell/SymbolFile/NativePDB/Inputs/corrupt-public-offset.py
lldb/test/Shell/SymbolFile/NativePDB/public-symbol-offset-past-section-end.cpp
Modified:
lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
Removed:
################################################################################
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index aa16ab713527df..33547f8fa06114 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -1290,12 +1290,25 @@ void SymbolFileNativePDB::AddSymbols(Symtab &symtab) {
return;
if (next && last_sym.Segment == next->Segment) {
- assert(last_sym.Offset <= next->Offset);
+ if (next->Offset < last_sym.Offset) {
+ LLDB_LOG(GetLog(LLDBLog::Symbols),
+ "Ignoring size estimate for '{0}': segment {1} offset {2} is "
+ "greater than the following offset {3}",
+ last_sym.Name, last_sym.Segment, last_sym.Offset,
+ next->Offset);
+ return;
+ }
last->SetByteSize(next->Offset - last_sym.Offset);
} else {
// the last symbol was the last in its section
- assert(section_sp->GetByteSize() >= last_sym.Offset);
- assert(!next || next->Segment > last_sym.Segment);
+ if (section_sp->GetByteSize() < last_sym.Offset) {
+ LLDB_LOG(GetLog(LLDBLog::Symbols),
+ "Ignoring size estimate for '{0}': segment {1} offset {2} is "
+ "past the end of section '{3}' (size {4})",
+ last_sym.Name, last_sym.Segment, last_sym.Offset,
+ section_sp->GetName(), section_sp->GetByteSize());
+ return;
+ }
last->SetByteSize(section_sp->GetByteSize() - last_sym.Offset);
}
};
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/corrupt-public-offset.py b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/corrupt-public-offset.py
new file mode 100644
index 00000000000000..7d650c39c6f062
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/corrupt-public-offset.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+"""Rewrite the Offset of a S_PUB32 record in a llvm-pdbutil pdb2yaml dump.
+
+Used to simulate a PDB whose public symbol records disagree with the
+executable's section table (as can happen with real-world PDBs).
+"""
+
+import re
+import sys
+
+if len(sys.argv) != 4:
+ sys.exit("usage: corrupt-public-offset.py <yaml-file> <symbol-name> <new-offset>")
+
+yaml_path, symbol_name, new_offset = sys.argv[1:4]
+new_offset = int(new_offset, 0)
+
+with open(yaml_path) as f:
+ text = f.read()
+
+pattern = re.compile(
+ r"(Offset:\s+)\d+(\s*\n\s*Segment:\s+\d+\s*\n\s*Name:\s+"
+ + re.escape(symbol_name)
+ + r"\b\s*\n)"
+)
+text, count = pattern.subn(r"\g<1>" + str(new_offset) + r"\g<2>", text, count=1)
+if count != 1:
+ sys.exit(f"could not find a S_PUB32 record named '{symbol_name}' in {yaml_path}")
+
+with open(yaml_path, "w") as f:
+ f.write(text)
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/public-symbol-offset-past-section-end.cpp b/lldb/test/Shell/SymbolFile/NativePDB/public-symbol-offset-past-section-end.cpp
new file mode 100644
index 00000000000000..f10a4935ec9a5f
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/public-symbol-offset-past-section-end.cpp
@@ -0,0 +1,23 @@
+// REQUIRES: lld, x86
+
+// A public symbol's offset is not guaranteed to agree with
+// the size of the section its segment maps to (this can happen with
+// real-world PDBs, e.g. after incremental linking).
+//
+// RUN: %build --compiler=clang-cl --arch=64 --nodefaultlib -o %t.exe -- %s
+// RUN: llvm-pdbutil pdb2yaml --all %t.pdb > %t.yaml
+// RUN: %python %S/Inputs/corrupt-public-offset.py %t.yaml main 0x0fffffff
+// RUN: llvm-pdbutil yaml2pdb %t.yaml -pdb=%t.pdb
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symtab %t.exe \
+// RUN: --find-symbols-by-regex=".*" | FileCheck %s
+
+int global_one = 1;
+int global_two = 2;
+
+int main() { return global_one + global_two; }
+
+// `main`'s offset was rewritten to a value past the end of its section, so
+// its size estimate must be left at 0 rather than underflowing.
+// CHECK-DAG: Code{{.*}}0x0000000000000000 0x00000000 main
+// CHECK-DAG: Data{{.*}}global_one
+// CHECK-DAG: Data{{.*}}global_two
More information about the lldb-commits
mailing list