[llvm] fix: recalculate .sxdata post strip (PR #222929)
Emily Sequeira via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 11 04:36:39 PDT 2026
https://github.com/noevembr created https://github.com/llvm/llvm-project/pull/222929
format
fix tests
>From 08e65f97a447da96a68a3f00348cec05ef429ccc Mon Sep 17 00:00:00 2001
From: Emily Sequeira <emily.sequeira at wibu.com>
Date: Fri, 11 Sep 2026 10:09:37 +0200
Subject: [PATCH] fix: recalculate .sxdata post strip
format
fix tests
---
llvm/lib/ObjCopy/COFF/COFFObject.cpp | 25 +++-
llvm/lib/ObjCopy/COFF/COFFObject.h | 4 +-
llvm/lib/ObjCopy/COFF/COFFWriter.cpp | 2 +-
.../COFF/strip-debug-seh-x86.test | 125 ++++++++++++++++++
4 files changed, 152 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/tools/llvm-objcopy/COFF/strip-debug-seh-x86.test
diff --git a/llvm/lib/ObjCopy/COFF/COFFObject.cpp b/llvm/lib/ObjCopy/COFF/COFFObject.cpp
index 91cf7e32a7396..0c0455e679b29 100644
--- a/llvm/lib/ObjCopy/COFF/COFFObject.cpp
+++ b/llvm/lib/ObjCopy/COFF/COFFObject.cpp
@@ -52,8 +52,11 @@ Error Object::removeSymbols(
}
Error Object::markSymbols() {
- for (Symbol &Sym : Symbols)
+ DenseMap<size_t, Symbol *> RawSymbolMap;
+ for (Symbol &Sym : Symbols) {
Sym.Referenced = false;
+ RawSymbolMap[Sym.OriginalRawIndex] = &Sym;
+ }
for (const Section &Sec : Sections) {
for (const Relocation &R : Sec.Relocs) {
auto It = SymbolMap.find(R.Target);
@@ -62,6 +65,26 @@ Error Object::markSymbols() {
"relocation target %zu not found", R.Target);
It->second->Referenced = true;
}
+ if (Sec.Name == ".sxdata") {
+ auto Contents = Sec.getContents();
+ if (Contents.size() % sizeof(uint32_t) != 0) {
+ return createStringError(object_error::parse_failed,
+ "section '.sxdata' has invalid size");
+ }
+
+ for (size_t Offset = 0; Offset < Contents.size();
+ Offset += sizeof(uint32_t)) {
+ const uint32_t RawIndex =
+ support::endian::read32le(Contents.data() + Offset);
+ auto It = RawSymbolMap.find(RawIndex);
+ if (It == RawSymbolMap.end()) {
+ return createStringError(object_error::invalid_symbol_index,
+ ".sxdata symbol index %u is invalid",
+ RawIndex);
+ }
+ It->second->Referenced = true;
+ }
+ }
}
return Error::success();
}
diff --git a/llvm/lib/ObjCopy/COFF/COFFObject.h b/llvm/lib/ObjCopy/COFF/COFFObject.h
index 1c04b7f64f3a0..edabbcb674fc0 100644
--- a/llvm/lib/ObjCopy/COFF/COFFObject.h
+++ b/llvm/lib/ObjCopy/COFF/COFFObject.h
@@ -119,8 +119,8 @@ struct Object {
void addSymbols(ArrayRef<Symbol> NewSymbols);
Error removeSymbols(function_ref<Expected<bool>(const Symbol &)> ToRemove);
- // Set the Referenced field on all Symbols, based on relocations in
- // all sections.
+ // Set the Referenced field on all Symbols based on relocations and other
+ // section data containing semantic symbol references, such as .sxdata.
Error markSymbols();
ArrayRef<Section> getSections() const { return Sections; }
diff --git a/llvm/lib/ObjCopy/COFF/COFFWriter.cpp b/llvm/lib/ObjCopy/COFF/COFFWriter.cpp
index fed67d67f13a7..7741d33ef0692 100644
--- a/llvm/lib/ObjCopy/COFF/COFFWriter.cpp
+++ b/llvm/lib/ObjCopy/COFF/COFFWriter.cpp
@@ -104,7 +104,7 @@ Error COFFWriter::finalizeSymIdxContents() {
// handling as they have more complex layout.
auto IsSymIdxSection = [](StringRef Name) {
return Name == ".gljmp$y" || Name == ".giats$y" || Name == ".gfids$y" ||
- Name == ".gehcont$y";
+ Name == ".gehcont$y" || Name == ".sxdata";
};
DenseMap<size_t, size_t> SymIdMap;
diff --git a/llvm/test/tools/llvm-objcopy/COFF/strip-debug-seh-x86.test b/llvm/test/tools/llvm-objcopy/COFF/strip-debug-seh-x86.test
new file mode 100644
index 0000000000000..7b7a867d12137
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/COFF/strip-debug-seh-x86.test
@@ -0,0 +1,125 @@
+## Check that --strip-debug preserves x86 SafeSEH handler references.
+## .sxdata contains raw COFF symbol-table indices, not relocations. Merely
+## retaining the section (or successfully reading the object) is insufficient.
+##
+## Removing .debug$S removes its section symbol AND its auxiliary record.
+## Consequently, _handler1 and _handler2 move from indices 7 and 8 to 5 and 6.
+## The .sxdata entries must change accordingly. The handlers have no ordinary
+## relocations referring to them, and one is a local symbol.
+##
+# RUN: yaml2obj %s -o %t.in.o
+# RUN: llvm-readobj --sections %t.in.o | FileCheck %s --check-prefix=BEFORE-SECTIONS
+# RUN: llvm-objdump --syms %t.in.o | FileCheck %s --check-prefix=BEFORE-SYMS
+# RUN: llvm-readobj --hex-dump=.sxdata %t.in.o | FileCheck %s --check-prefix=BEFORE-DATA
+# RUN: llvm-objcopy --strip-debug %t.in.o %t.out.o
+# RUN: llvm-readobj --sections --symbols %t.out.o | FileCheck %s --check-prefix=AFTER --implicit-check-not=.debug
+# RUN: llvm-objdump --syms %t.out.o | FileCheck %s --check-prefix=AFTER-SYMS
+# RUN: llvm-readobj --hex-dump=.sxdata %t.out.o | FileCheck %s --check-prefix=AFTER-DATA
+## Stripping again must not remap already-updated indices a second time.
+# RUN: llvm-objcopy --strip-debug %t.out.o %t.twice.o
+# RUN: llvm-objdump --syms %t.twice.o | FileCheck %s --check-prefix=AFTER-SYMS
+# RUN: llvm-readobj --hex-dump=.sxdata %t.twice.o | FileCheck %s --check-prefix=AFTER-DATA
+
+# BEFORE-SECTIONS: Name: .debug$S
+# BEFORE-SECTIONS: Name: .text
+# BEFORE-SECTIONS: Name: .sxdata
+# BEFORE-SYMS: [{{ *}}7]{{.*}} _handler1
+# BEFORE-SYMS: [{{ *}}8]{{.*}} _handler2
+# BEFORE-DATA: Hex dump of section '.sxdata':
+# BEFORE-DATA-NEXT: 0x00000000 07000000 08000000
+
+# AFTER: Sections [
+# AFTER-NEXT: Section {
+# AFTER-NEXT: Number: 1
+# AFTER-NEXT: Name: .text
+# AFTER: Section {
+# AFTER-NEXT: Number: 2
+# AFTER-NEXT: Name: .sxdata
+# AFTER: RelocationCount: 0
+# AFTER: Symbols [
+# AFTER: Name: @feat.00
+# AFTER-NEXT: Value: 1
+# AFTER: Name: _handler1
+# AFTER-NEXT: Value: 0
+# AFTER-NEXT: Section: .text (1)
+# AFTER: Name: _handler2
+# AFTER-NEXT: Value: 1
+# AFTER-NEXT: Section: .text (1)
+# AFTER-SYMS: [{{ *}}5]{{.*}} _handler1
+# AFTER-SYMS: [{{ *}}6]{{.*}} _handler2
+# AFTER-DATA: Hex dump of section '.sxdata':
+# AFTER-DATA-NEXT: 0x00000000 05000000 06000000
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: []
+sections:
+ - Name: '.debug$S'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_DISCARDABLE ]
+ Alignment: 4
+ SectionData: '04000000'
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: 'C3C3'
+ - Name: .sxdata
+ Characteristics: [ IMAGE_SCN_LNK_INFO ]
+ Alignment: 4
+ SectionData: '0700000008000000'
+symbols:
+ - Name: '.debug$S'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 4
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: .text
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 2
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 2
+ - Name: .sxdata
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 8
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: '@feat.00'
+ Value: 1
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: _handler1
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _handler2
+ Value: 1
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+...
More information about the llvm-commits
mailing list