[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