[lld] [lld][ELF] Introduce an option to keep data section prefix. (PR #148985)

Mingming Liu via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 4 14:25:18 PDT 2025


https://github.com/mingmingl-llvm updated https://github.com/llvm/llvm-project/pull/148985

>From 24c1c62b584fb42fcd91b9343bbe61e521038dd0 Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Sun, 30 Mar 2025 23:32:41 +0000
Subject: [PATCH 1/8] lld keep data section prefix

---
 lld/ELF/Config.h         |  1 +
 lld/ELF/Driver.cpp       |  4 +++
 lld/ELF/LinkerScript.cpp | 69 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+)

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 03b3cd4771f49..0a01eddf20271 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -372,6 +372,7 @@ struct Config {
   bool zInitfirst;
   bool zInterpose;
   bool zKeepTextSectionPrefix;
+  bool zKeepDataSectionPrefix;
   bool zLrodataAfterBss;
   bool zNoBtCfi;
   bool zNodefaultlib;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 0a220432333cc..32ebd7a1a2ad9 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1566,6 +1566,10 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   ctx.arg.zInterpose = hasZOption(args, "interpose");
   ctx.arg.zKeepTextSectionPrefix = getZFlag(
       args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
+  ctx.arg.zKeepDataSectionPrefix = getZFlag(
+      args, "keep-data-section-prefix", "nokeep-data-section-prefix", false);
+  errs() << "ELF/Driver.cpp:1540\t" << ctx.arg.zKeepDataSectionPrefix << "\n";
+
   ctx.arg.zLrodataAfterBss =
       getZFlag(args, "lrodata-after-bss", "nolrodata-after-bss", false);
   ctx.arg.zNoBtCfi = hasZOption(args, "nobtcfi");
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index e19823f2ea752..17432e65bb1bf 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -48,6 +48,11 @@ static bool isSectionPrefix(StringRef prefix, StringRef name) {
   return name.consume_front(prefix) && (name.empty() || name[0] == '.');
 }
 
+bool hasUnlikelySuffix(StringRef name) {
+  return name.ends_with(".unlikely") || name.ends_with(".unlikely.") ||
+         name.ends_with("unlikely");
+}
+
 StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
   // This is for --emit-relocs and -r. If .text.foo is emitted as .text.bar, we
   // want to emit .rela.text.foo as .rela.text.bar for consistency (this is not
@@ -105,6 +110,70 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
     return ".text";
   }
 
+  if (isSectionPrefix(".data.rel.ro", s->name)) {
+    // Map input sections' .rodata and rodata.hot into .rodata.hot in the
+    // output. Map input sections' .rodata.unlikely into .rodata in the output.
+    if (ctx.arg.zKeepDataSectionPrefix) {
+      if (isSectionPrefix(".data.rel.ro.unlikely", s->name) ||
+          hasUnlikelySuffix(s->name)) {
+        return ".data.rel.ro.unlikely";
+      }
+
+      return ".data.rel.ro";
+    }
+    return ".data.rel.ro";
+  }
+
+  if (isSectionPrefix(".data", s->name)) {
+    //  Map input sections' .rodata and rodata.hot into .rodata.hot in the
+    //  output. Map input sections' .rodata.unlikely into .rodata in the output.
+    if (ctx.arg.zKeepDataSectionPrefix) {
+      if (isSectionPrefix(".data.unlikely", s->name) ||
+          hasUnlikelySuffix(s->name)) {
+        // errs() << "LinkerScript.cpp:100\t" << s->name << "\n";
+        return ".data.unlikely";
+      }
+
+      return ".data";
+    }
+    return ".data";
+  }
+
+  if (isSectionPrefix(".rodata", s->name)) {
+    // Map input sections' .rodata and rodata.hot into .rodata.hot in the
+    // output. Map input sections' .rodata.unlikely into .rodata in the output.
+    if (ctx.arg.zKeepDataSectionPrefix) {
+      // if (isSectionPrefix(".rodata.cst", s->name)) {
+      // errs() << "LinkerScript.cpp:100\t" << s->name << "\n";
+      //}
+      //  .rodata.cst<N>.unlikely
+      //  .rodata.str4.16.unlikely
+      if (isSectionPrefix(".rodata.unlikely", s->name) ||
+          hasUnlikelySuffix(s->name)) {
+        // return ".rodata.unlikely";
+        return ".rodata.unlikely";
+      }
+      return ".rodata";
+    }
+    return ".rodata";
+  }
+
+  if (isSectionPrefix(".bss.rel.ro", s->name)) {
+    return ".bss.rel.ro";
+  }
+
+  if (isSectionPrefix(".bss", s->name)) {
+    if (ctx.arg.zKeepDataSectionPrefix) {
+      if (isSectionPrefix(".bss.unlikely", s->name)) {
+        // errs() << "LinkerScript.cpp:100\t" << s->name << "\n";
+        return ".bss.unlikely";
+      }
+
+      return ".bss";
+    }
+    return ".bss";
+  }
+
   for (StringRef v : {".data.rel.ro", ".data",       ".rodata",
                       ".bss.rel.ro",  ".bss",        ".ldata",
                       ".lrodata",     ".lbss",       ".gcc_except_table",

>From 6328b71a44ebe50babcf766f9258df1f0dd8bb3d Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Sun, 20 Jul 2025 18:22:20 -0700
Subject: [PATCH 2/8] simplify implementation

---
 lld/ELF/Config.h         |  2 +-
 lld/ELF/Driver.cpp       |  5 +-
 lld/ELF/LinkerScript.cpp | 99 ++++++++++++----------------------------
 3 files changed, 33 insertions(+), 73 deletions(-)

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 0a01eddf20271..d3f6103fde4b7 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -371,8 +371,8 @@ struct Config {
   bool zIfuncNoplt;
   bool zInitfirst;
   bool zInterpose;
-  bool zKeepTextSectionPrefix;
   bool zKeepDataSectionPrefix;
+  bool zKeepTextSectionPrefix;
   bool zLrodataAfterBss;
   bool zNoBtCfi;
   bool zNodefaultlib;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 32ebd7a1a2ad9..cd48f0f64ce29 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1564,11 +1564,10 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
   ctx.arg.zIfuncNoplt = hasZOption(args, "ifunc-noplt");
   ctx.arg.zInitfirst = hasZOption(args, "initfirst");
   ctx.arg.zInterpose = hasZOption(args, "interpose");
-  ctx.arg.zKeepTextSectionPrefix = getZFlag(
-      args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
   ctx.arg.zKeepDataSectionPrefix = getZFlag(
       args, "keep-data-section-prefix", "nokeep-data-section-prefix", false);
-  errs() << "ELF/Driver.cpp:1540\t" << ctx.arg.zKeepDataSectionPrefix << "\n";
+  ctx.arg.zKeepTextSectionPrefix = getZFlag(
+      args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
 
   ctx.arg.zLrodataAfterBss =
       getZFlag(args, "lrodata-after-bss", "nolrodata-after-bss", false);
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 17432e65bb1bf..f1f8f6c776c7a 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -48,9 +48,9 @@ static bool isSectionPrefix(StringRef prefix, StringRef name) {
   return name.consume_front(prefix) && (name.empty() || name[0] == '.');
 }
 
-bool hasUnlikelySuffix(StringRef name) {
-  return name.ends_with(".unlikely") || name.ends_with(".unlikely.") ||
-         name.ends_with("unlikely");
+static bool isSectionSuffix(StringRef suffix, StringRef name) {
+  name.consume_back(".");
+  return name.ends_with(suffix);
 }
 
 StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
@@ -110,77 +110,38 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
     return ".text";
   }
 
-  if (isSectionPrefix(".data.rel.ro", s->name)) {
-    // Map input sections' .rodata and rodata.hot into .rodata.hot in the
-    // output. Map input sections' .rodata.unlikely into .rodata in the output.
-    if (ctx.arg.zKeepDataSectionPrefix) {
-      if (isSectionPrefix(".data.rel.ro.unlikely", s->name) ||
-          hasUnlikelySuffix(s->name)) {
-        return ".data.rel.ro.unlikely";
-      }
-
-      return ".data.rel.ro";
-    }
-    return ".data.rel.ro";
-  }
-
-  if (isSectionPrefix(".data", s->name)) {
-    //  Map input sections' .rodata and rodata.hot into .rodata.hot in the
-    //  output. Map input sections' .rodata.unlikely into .rodata in the output.
-    if (ctx.arg.zKeepDataSectionPrefix) {
-      if (isSectionPrefix(".data.unlikely", s->name) ||
-          hasUnlikelySuffix(s->name)) {
-        // errs() << "LinkerScript.cpp:100\t" << s->name << "\n";
-        return ".data.unlikely";
-      }
-
-      return ".data";
-    }
-    return ".data";
-  }
-
-  if (isSectionPrefix(".rodata", s->name)) {
-    // Map input sections' .rodata and rodata.hot into .rodata.hot in the
-    // output. Map input sections' .rodata.unlikely into .rodata in the output.
-    if (ctx.arg.zKeepDataSectionPrefix) {
-      // if (isSectionPrefix(".rodata.cst", s->name)) {
-      // errs() << "LinkerScript.cpp:100\t" << s->name << "\n";
-      //}
-      //  .rodata.cst<N>.unlikely
-      //  .rodata.str4.16.unlikely
-      if (isSectionPrefix(".rodata.unlikely", s->name) ||
-          hasUnlikelySuffix(s->name)) {
-        // return ".rodata.unlikely";
-        return ".rodata.unlikely";
-      }
-      return ".rodata";
-    }
-    return ".rodata";
-  }
-
-  if (isSectionPrefix(".bss.rel.ro", s->name)) {
-    return ".bss.rel.ro";
-  }
+  // When zKeepDataSectionPrefix is true, keep .hot and .unlikely suffixes
+  // in data sections.
+  static constexpr StringRef dataSectionPrefixes[] = {
+      ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss",
+  };
 
-  if (isSectionPrefix(".bss", s->name)) {
-    if (ctx.arg.zKeepDataSectionPrefix) {
-      if (isSectionPrefix(".bss.unlikely", s->name)) {
-        // errs() << "LinkerScript.cpp:100\t" << s->name << "\n";
-        return ".bss.unlikely";
+  for (auto [index, v] : llvm::enumerate(dataSectionPrefixes)) {
+    if (isSectionPrefix(v, s->name)) {
+      if (ctx.arg.zKeepDataSectionPrefix) {
+        if (isSectionPrefix(".hot", s->name.substr(v.size())))
+          return s->name.substr(0, v.size() + 4);
+        if (isSectionPrefix(".unlikely", s->name.substr(v.size())))
+          return s->name.substr(0, v.size() + 9);
+        // for .rodata,  a section could be`.rodata.cst<N>.hot.` for constant
+        // pool or  `rodata.str<N>.hot.` for string literals.
+        if (index == 2) {
+          if (isSectionSuffix(".hot", s->name)) {
+            return ".rodata.hot";
+          }
+          if (isSectionSuffix(".unlikely", s->name)) {
+            return ".rodata.unlikely";
+          }
+        }
       }
-
-      return ".bss";
+      return v;
     }
-    return ".bss";
   }
 
-  for (StringRef v : {".data.rel.ro", ".data",       ".rodata",
-                      ".bss.rel.ro",  ".bss",        ".ldata",
-                      ".lrodata",     ".lbss",       ".gcc_except_table",
-                      ".init_array",  ".fini_array", ".tbss",
-                      ".tdata",       ".ARM.exidx",  ".ARM.extab",
-                      ".ctors",       ".dtors",      ".sbss",
-                      ".sdata",       ".srodata"})
+  for (StringRef v :
+       {".ldata", ".lrodata", ".lbss", ".gcc_except_table", ".init_array",
+        ".fini_array", ".tbss", ".tdata", ".ARM.exidx", ".ARM.extab", ".ctors",
+        ".dtors", ".sbss", ".sdata", ".srodata"})
     if (isSectionPrefix(v, s->name))
       return v;
 

>From 25c61499fb130bf5d8827afde108aa8a2f3952b2 Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Mon, 21 Jul 2025 13:42:50 -0700
Subject: [PATCH 3/8] update code comment, and add a regression test

---
 lld/ELF/Driver.cpp                 |   1 -
 lld/ELF/LinkerScript.cpp           |   7 +-
 lld/ELF/Writer.cpp                 |  23 +++++-
 lld/test/ELF/data-section-prefix.s | 127 +++++++++++++++++++++++++++++
 4 files changed, 154 insertions(+), 4 deletions(-)
 create mode 100644 lld/test/ELF/data-section-prefix.s

diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index cd48f0f64ce29..b1b55247388a3 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1568,7 +1568,6 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
       args, "keep-data-section-prefix", "nokeep-data-section-prefix", false);
   ctx.arg.zKeepTextSectionPrefix = getZFlag(
       args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
-
   ctx.arg.zLrodataAfterBss =
       getZFlag(args, "lrodata-after-bss", "nolrodata-after-bss", false);
   ctx.arg.zNoBtCfi = hasZOption(args, "nobtcfi");
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index f1f8f6c776c7a..f2b20db7b0521 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -118,12 +118,15 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
 
   for (auto [index, v] : llvm::enumerate(dataSectionPrefixes)) {
     if (isSectionPrefix(v, s->name)) {
-      if (ctx.arg.zKeepDataSectionPrefix) {
+      // The .bss.rel.ro section is considered rarely accessed. So this section
+      // is not partitioned and zKeepDataSectionPrefix is not applied to
+      // make the executable simpler with fewer elf sections.
+      if (ctx.arg.zKeepDataSectionPrefix && index != 3) {
         if (isSectionPrefix(".hot", s->name.substr(v.size())))
           return s->name.substr(0, v.size() + 4);
         if (isSectionPrefix(".unlikely", s->name.substr(v.size())))
           return s->name.substr(0, v.size() + 9);
-        // for .rodata,  a section could be`.rodata.cst<N>.hot.` for constant
+        // For .rodata,  a section could be`.rodata.cst<N>.hot.` for constant
         // pool or  `rodata.str<N>.hot.` for string literals.
         if (index == 2) {
           if (isSectionSuffix(".hot", s->name)) {
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 2cea6a44b391a..82e5ba6d9e6a8 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -555,6 +555,27 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
   }
 }
 
+// Returns true if the section is a data section that's read only and
+// relocatable per its section name.
+static bool isRelRoDataSection(Ctx &ctx, StringRef secName) {
+  // The section name should start with ".data.rel.ro".
+  if (!secName.consume_front(".data.rel.ro"))
+    return false;
+
+  // If the section name is .data.rel.ro, it is a relocatable read-only data
+  // section.
+  if (secName.empty())
+    return true;
+  //  If  -z keep-data-section-prefix is given, '.data.rel.ro.hot' and
+  //  '.data.rel.ro.unlikely' are considered a split of '.data.rel.ro' based on
+  //  hotness.
+  if (ctx.arg.zKeepDataSectionPrefix) {
+    return secName == ".hot" || secName == ".unlikely";
+  }
+
+  return false;
+}
+
 // Today's loaders have a feature to make segments read-only after
 // processing dynamic relocations to enhance security. PT_GNU_RELRO
 // is defined for that.
@@ -631,7 +652,7 @@ static bool isRelroSection(Ctx &ctx, const OutputSection *sec) {
   // magic section names.
   StringRef s = sec->name;
 
-  bool abiAgnostic = s == ".data.rel.ro" || s == ".bss.rel.ro" ||
+  bool abiAgnostic = isRelRoDataSection(ctx, s) || s == ".bss.rel.ro" ||
                      s == ".ctors" || s == ".dtors" || s == ".jcr" ||
                      s == ".eh_frame" || s == ".fini_array" ||
                      s == ".init_array" || s == ".preinit_array";
diff --git a/lld/test/ELF/data-section-prefix.s b/lld/test/ELF/data-section-prefix.s
new file mode 100644
index 0000000000000..5012039e438a7
--- /dev/null
+++ b/lld/test/ELF/data-section-prefix.s
@@ -0,0 +1,127 @@
+# REQUIRES: x86
+## -z keep-data-section-prefix separates static data sections with prefix
+## .<section>.hot, .<section>.unlikely in the absence of a SECTIONS command.
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
+
+# RUN: ld.lld a.o -o out1
+# RUN: llvm-readelf -S out1 | FileCheck --check-prefix=BASIC %s
+# RUN: ld.lld -z nokeep-text-section-prefix a.o -o out2
+# RUN: cmp out1 out2
+
+# RUN: ld.lld -z keep-data-section-prefix a.o -o out3
+# RUN: llvm-readelf -S out3 | FileCheck --check-prefix=KEEP %s
+
+## With a SECTIONS command, orphan sections are created verbatim.
+## No grouping is performed for them.
+# RUN: ld.lld -T x.lds -z keep-data-section-prefix a.o -o out4
+# RUN: llvm-readelf -S out4 | FileCheck --check-prefix=SCRIPT %s
+
+# BASIC:         [Nr] Name              Type            Address          Off    Size              
+# BASIC:         [ 1] .text       
+# BASIC-NEXT:    [ 2] .data.rel.ro      PROGBITS        00000000002021c9 0001c9 00000f
+# BASIC-NEXT:    [ 3] .bss.rel.ro       NOBITS          00000000002021d8 0001d8 000008
+# BASIC-NEXT:    [ 4] .relro_padding    NOBITS          00000000002021e0 0001d8 000e20
+# BASIC-NEXT:    [ 5] .rodata           PROGBITS        00000000002031e0 0001e0 000006
+# BASIC-NEXT:    [ 6] .data             PROGBITS        00000000002031e6 0001e6 000004
+# BASIC-NEXT:    [ 7] .bss              NOBITS          00000000002031ea 0001ea 000004
+
+# KEEP:       [Nr]  Name                    Type            Address          Off    Size
+# KEEP:       [ 1] .text
+# KEEP-NEXT:  [ 2] .data.rel.ro             PROGBITS        00000000002021c9 0001c9 000009
+# KEEP-NEXT:  [ 3] .data.rel.ro.hot         PROGBITS        00000000002021d2 0001d2 000004
+# KEEP-NEXT:  [ 4] .data.rel.ro.unlikely    PROGBITS        00000000002021d6 0001d6 000002
+# KEEP-NEXT:  [ 5] .bss.rel.ro              NOBITS          00000000002021d8 0001d8 000008
+# KEEP-NEXT:  [ 6] .relro_padding           NOBITS          00000000002021e0 0001d8 000e20
+# KEEP-NEXT:  [ 7] .rodata                  PROGBITS        00000000002031e0 0001e0 000002
+# KEEP-NEXT:  [ 8] .rodata.hot              PROGBITS        00000000002031e2 0001e2 000002
+# KEEP-NEXT:  [ 9] .rodata.unlikely         PROGBITS        00000000002031e4 0001e4 000002
+# KEEP-NEXT:  [10] .data                    PROGBITS        00000000002031e6 0001e6 000002
+# KEEP-NEXT:  [11] .data.hot                PROGBITS        00000000002031e8 0001e8 000001
+# KEEP-NEXT:  [12] .data.unlikely           PROGBITS        00000000002031e9 0001e9 000001
+# KEEP-NEXT:  [13] .bss                     NOBITS          00000000002031ea 0001ea 000002
+# KEEP-NEXT:  [14] .bss.hot                 NOBITS          00000000002031ec 0001ea 000001
+# KEEP-NEXT:  [15] .bss.unlikely            NOBITS          00000000002031ed 0001ea 000001
+
+# SCRIPT:      .text
+# SCRIPT-NEXT: .rodata.i
+# SCRIPT-NEXT: .rodata.hot.j
+# SCRIPT-NEXT: .rodata.unlikely.k
+# SCRIPT-NEXT: .rodata.split.l
+# SCRIPT-NEXT: .rodata.cst32.hot.
+# SCRIPT-NEXT: .rodata.str1.1.unlikely.
+# SCRIPT-NEXT: .data.m
+# SCRIPT-NEXT: .data.hot.n
+# SCRIPT-NEXT: .data.unlikely.o
+# SCRIPT-NEXT: .data.split.p
+# SCRIPT-NEXT: .data.rel.ro.q
+# SCRIPT-NEXT: .data.rel.ro.hot.r
+# SCRIPT-NEXT: .data.rel.ro.unlikely.s
+# SCRIPT-NEXT: .data.rel.ro.split.t
+# SCRIPT-NEXT: .bss.a
+# SCRIPT-NEXT: .bss.hot.b
+# SCRIPT-NEXT: .bss.unlikely.c
+# SCRIPT-NEXT: .bss.split.d
+# SCRIPT-NEXT: .bss.rel.ro.e
+# SCRIPT-NEXT: .bss.rel.ro.hot.f
+# SCRIPT-NEXT: .bss.rel.ro.unlikely.g
+# SCRIPT-NEXT: .bss.rel.ro.split.h
+
+#--- a.s
+.globl _start
+_start:
+  ret
+
+.section .bss.a,"aw"
+  .byte 0
+.section .bss.hot.b,"aw"
+  .byte 0
+.section .bss.unlikely.c,"aw"
+  .byte 0
+.section .bss.split.d,"aw"
+  .byte 0
+
+.section .bss.rel.ro.e, "aw"
+  .space 2
+.section .bss.rel.ro.hot.f, "aw"
+  .space 2
+.section .bss.rel.ro.unlikely.g, "aw"
+  .space 2
+.section .bss.rel.ro.split.h, "aw"
+  .space 2
+
+.section .rodata.i,"aw"
+  .byte 1
+.section .rodata.hot.j,"aw"
+  .byte 2
+.section .rodata.unlikely.k,"aw"
+  .byte 3
+.section .rodata.split.l,"aw"
+  .byte 4
+.section .rodata.cst32.hot.,"aw"
+  .byte 5
+.section .rodata.str1.1.unlikely.,"aw"
+  .byte 6
+
+.section .data.m,"aw"
+  .byte 5
+.section .data.hot.n,"aw"
+  .byte 6
+.section .data.unlikely.o,"aw"
+  .byte 7
+.section .data.split.p,"aw"
+  .byte 8
+
+.section .data.rel.ro.q,"aw"
+  .quad 0 
+.section .data.rel.ro.hot.r,"aw"
+  .long 255
+.section .data.rel.ro.unlikely.s,"aw"
+  .word 1
+.section .data.rel.ro.split.t,"aw"
+  .byte 0
+
+#--- x.lds
+SECTIONS {}

>From 67e44ed7a9ccd089b142bb6e52cd181ed8ed2cbb Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Mon, 21 Jul 2025 22:32:54 -0700
Subject: [PATCH 4/8] resolve comments

---
 lld/ELF/LinkerScript.cpp           | 6 ++++--
 lld/test/ELF/data-section-prefix.s | 8 ++++----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index f2b20db7b0521..1351e1686c3e2 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -118,10 +118,12 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
 
   for (auto [index, v] : llvm::enumerate(dataSectionPrefixes)) {
     if (isSectionPrefix(v, s->name)) {
+      if (!ctx.arg.zKeepDataSectionPrefix)
+        return v;
       // The .bss.rel.ro section is considered rarely accessed. So this section
       // is not partitioned and zKeepDataSectionPrefix is not applied to
       // make the executable simpler with fewer elf sections.
-      if (ctx.arg.zKeepDataSectionPrefix && index != 3) {
+
         if (isSectionPrefix(".hot", s->name.substr(v.size())))
           return s->name.substr(0, v.size() + 4);
         if (isSectionPrefix(".unlikely", s->name.substr(v.size())))
@@ -136,7 +138,7 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
             return ".rodata.unlikely";
           }
         }
-      }
+
       return v;
     }
   }
diff --git a/lld/test/ELF/data-section-prefix.s b/lld/test/ELF/data-section-prefix.s
index 5012039e438a7..a5c347ec275c6 100644
--- a/lld/test/ELF/data-section-prefix.s
+++ b/lld/test/ELF/data-section-prefix.s
@@ -83,13 +83,13 @@ _start:
 .section .bss.split.d,"aw"
   .byte 0
 
-.section .bss.rel.ro.e, "aw"
+.section .bss.rel.ro, "aw"
   .space 2
-.section .bss.rel.ro.hot.f, "aw"
+.section .bss.rel.ro, "aw"
   .space 2
-.section .bss.rel.ro.unlikely.g, "aw"
+.section .bss.rel.ro, "aw"
   .space 2
-.section .bss.rel.ro.split.h, "aw"
+.section .bss.rel.ro, "aw"
   .space 2
 
 .section .rodata.i,"aw"

>From ed70327841c951a57b07d1a628e8c9c40d347fe8 Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Wed, 23 Jul 2025 11:23:46 -0700
Subject: [PATCH 5/8] resolve comments

---
 lld/ELF/LinkerScript.cpp                      | 46 ++++++++--------
 ...on-prefix.s => keep-data-section-prefix.s} | 53 +++++++++----------
 2 files changed, 48 insertions(+), 51 deletions(-)
 rename lld/test/ELF/{data-section-prefix.s => keep-data-section-prefix.s} (51%)

diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 1351e1686c3e2..e4274e95241db 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -48,9 +48,10 @@ static bool isSectionPrefix(StringRef prefix, StringRef name) {
   return name.consume_front(prefix) && (name.empty() || name[0] == '.');
 }
 
-static bool isSectionSuffix(StringRef suffix, StringRef name) {
-  name.consume_back(".");
-  return name.ends_with(suffix);
+// If name starts with prefix, trim the prefix and return true.
+// Otherwise, leave the name unchanged and return false.
+static bool trimSectionPrefix(StringRef prefix, StringRef &name) {
+  return name.consume_front(prefix) && (name.empty() || name[0] == '.');
 }
 
 StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
@@ -117,28 +118,27 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
   };
 
   for (auto [index, v] : llvm::enumerate(dataSectionPrefixes)) {
-    if (isSectionPrefix(v, s->name)) {
+    StringRef secName = s->name;
+    if (trimSectionPrefix(v, secName)) {
       if (!ctx.arg.zKeepDataSectionPrefix)
         return v;
-      // The .bss.rel.ro section is considered rarely accessed. So this section
-      // is not partitioned and zKeepDataSectionPrefix is not applied to
-      // make the executable simpler with fewer elf sections.
-
-        if (isSectionPrefix(".hot", s->name.substr(v.size())))
-          return s->name.substr(0, v.size() + 4);
-        if (isSectionPrefix(".unlikely", s->name.substr(v.size())))
-          return s->name.substr(0, v.size() + 9);
-        // For .rodata,  a section could be`.rodata.cst<N>.hot.` for constant
-        // pool or  `rodata.str<N>.hot.` for string literals.
-        if (index == 2) {
-          if (isSectionSuffix(".hot", s->name)) {
-            return ".rodata.hot";
-          }
-          if (isSectionSuffix(".unlikely", s->name)) {
-            return ".rodata.unlikely";
-          }
-        }
-
+      if (isSectionPrefix(".hot", secName))
+        return s->name.substr(0, v.size() + 4);
+      if (isSectionPrefix(".unlikely", secName))
+        return s->name.substr(0, v.size() + 9);
+      // For .rodata,  a section could be`.rodata.cst<N>.hot.` for constant
+      // pool or  `rodata.str<N>.hot.` for string literals.
+      if (index == 2) {
+        // The reason to specialize this path is to spell out .rodata.hot and
+        // .rodata.unlikely as string literals for StringRef lifetime
+        // considerations. We cannot use the pattern above to get substr from
+        // section names.
+        if (s->name.ends_with(".hot."))
+          return ".rodata.hot";
+
+        if (s->name.ends_with(".unlikely."))
+          return ".rodata.unlikely";
+      }
       return v;
     }
   }
diff --git a/lld/test/ELF/data-section-prefix.s b/lld/test/ELF/keep-data-section-prefix.s
similarity index 51%
rename from lld/test/ELF/data-section-prefix.s
rename to lld/test/ELF/keep-data-section-prefix.s
index a5c347ec275c6..a33eb0c2d609f 100644
--- a/lld/test/ELF/data-section-prefix.s
+++ b/lld/test/ELF/keep-data-section-prefix.s
@@ -19,35 +19,36 @@
 # RUN: ld.lld -T x.lds -z keep-data-section-prefix a.o -o out4
 # RUN: llvm-readelf -S out4 | FileCheck --check-prefix=SCRIPT %s
 
-# BASIC:         [Nr] Name              Type            Address          Off    Size              
+# BASIC:         [Nr] Name              Type            {{.*}}   Size              
 # BASIC:         [ 1] .text       
-# BASIC-NEXT:    [ 2] .data.rel.ro      PROGBITS        00000000002021c9 0001c9 00000f
-# BASIC-NEXT:    [ 3] .bss.rel.ro       NOBITS          00000000002021d8 0001d8 000008
-# BASIC-NEXT:    [ 4] .relro_padding    NOBITS          00000000002021e0 0001d8 000e20
-# BASIC-NEXT:    [ 5] .rodata           PROGBITS        00000000002031e0 0001e0 000006
-# BASIC-NEXT:    [ 6] .data             PROGBITS        00000000002031e6 0001e6 000004
-# BASIC-NEXT:    [ 7] .bss              NOBITS          00000000002031ea 0001ea 000004
+# BASIC-NEXT:    [ 2] .data.rel.ro      PROGBITS        {{.*}}   00000f
+# BASIC-NEXT:    [ 3] .bss.rel.ro       NOBITS          {{.*}}   000008
+# BASIC-NEXT:    [ 4] .relro_padding    NOBITS          {{.*}}   000e20
+# BASIC-NEXT:    [ 5] .rodata           PROGBITS        {{.*}}   000006
+# BASIC-NEXT:    [ 6] .data             PROGBITS        {{.*}}   000004
+# BASIC-NEXT:    [ 7] .bss              NOBITS          {{.*}}  000004
 
-# KEEP:       [Nr]  Name                    Type            Address          Off    Size
+# KEEP:       [Nr]  Name                    Type            {{.*}}    Size
 # KEEP:       [ 1] .text
-# KEEP-NEXT:  [ 2] .data.rel.ro             PROGBITS        00000000002021c9 0001c9 000009
-# KEEP-NEXT:  [ 3] .data.rel.ro.hot         PROGBITS        00000000002021d2 0001d2 000004
-# KEEP-NEXT:  [ 4] .data.rel.ro.unlikely    PROGBITS        00000000002021d6 0001d6 000002
-# KEEP-NEXT:  [ 5] .bss.rel.ro              NOBITS          00000000002021d8 0001d8 000008
-# KEEP-NEXT:  [ 6] .relro_padding           NOBITS          00000000002021e0 0001d8 000e20
-# KEEP-NEXT:  [ 7] .rodata                  PROGBITS        00000000002031e0 0001e0 000002
-# KEEP-NEXT:  [ 8] .rodata.hot              PROGBITS        00000000002031e2 0001e2 000002
-# KEEP-NEXT:  [ 9] .rodata.unlikely         PROGBITS        00000000002031e4 0001e4 000002
-# KEEP-NEXT:  [10] .data                    PROGBITS        00000000002031e6 0001e6 000002
-# KEEP-NEXT:  [11] .data.hot                PROGBITS        00000000002031e8 0001e8 000001
-# KEEP-NEXT:  [12] .data.unlikely           PROGBITS        00000000002031e9 0001e9 000001
-# KEEP-NEXT:  [13] .bss                     NOBITS          00000000002031ea 0001ea 000002
-# KEEP-NEXT:  [14] .bss.hot                 NOBITS          00000000002031ec 0001ea 000001
-# KEEP-NEXT:  [15] .bss.unlikely            NOBITS          00000000002031ed 0001ea 000001
+# KEEP-NEXT:  [ 2] .data.rel.ro             PROGBITS        {{.*}} 000009
+# KEEP-NEXT:  [ 3] .data.rel.ro.hot         PROGBITS        {{.*}} 000004
+# KEEP-NEXT:  [ 4] .data.rel.ro.unlikely    PROGBITS        {{.*}} 000002
+# KEEP-NEXT:  [ 5] .bss.rel.ro              NOBITS          {{.*}} 000008
+# KEEP-NEXT:  [ 6] .relro_padding           NOBITS          {{.*}} 000e20
+# KEEP-NEXT:  [ 7] .rodata                  PROGBITS        {{.*}} 000002
+# KEEP-NEXT:  [ 8] .rodata.hot              PROGBITS        {{.*}} 000002
+# KEEP-NEXT:  [ 9] .rodata.unlikely         PROGBITS        {{.*}} 000002
+# KEEP-NEXT:  [10] .data                    PROGBITS        {{.*}} 000002
+# KEEP-NEXT:  [11] .data.hot                PROGBITS        {{.*}} 000001
+# KEEP-NEXT:  [12] .data.unlikely           PROGBITS        {{.*}} 000001
+# KEEP-NEXT:  [13] .bss                     NOBITS          {{.*}} 000002
+# KEEP-NEXT:  [14] .bss.hot                 NOBITS          {{.*}} 000001
+# KEEP-NEXT:  [15] .bss.unlikely            NOBITS          {{.*}} 000001
 
 # SCRIPT:      .text
+# SCRIPT-NEXT: .bss.rel.ro
 # SCRIPT-NEXT: .rodata.i
-# SCRIPT-NEXT: .rodata.hot.j
+# SCRIPT-NEXT: .rodata.hot.
 # SCRIPT-NEXT: .rodata.unlikely.k
 # SCRIPT-NEXT: .rodata.split.l
 # SCRIPT-NEXT: .rodata.cst32.hot.
@@ -64,10 +65,6 @@
 # SCRIPT-NEXT: .bss.hot.b
 # SCRIPT-NEXT: .bss.unlikely.c
 # SCRIPT-NEXT: .bss.split.d
-# SCRIPT-NEXT: .bss.rel.ro.e
-# SCRIPT-NEXT: .bss.rel.ro.hot.f
-# SCRIPT-NEXT: .bss.rel.ro.unlikely.g
-# SCRIPT-NEXT: .bss.rel.ro.split.h
 
 #--- a.s
 .globl _start
@@ -94,7 +91,7 @@ _start:
 
 .section .rodata.i,"aw"
   .byte 1
-.section .rodata.hot.j,"aw"
+.section .rodata.hot.,"aw"
   .byte 2
 .section .rodata.unlikely.k,"aw"
   .byte 3

>From b66eceebbf47540539f9aa9b4f4d544b0bfed897 Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Wed, 23 Jul 2025 12:27:40 -0700
Subject: [PATCH 6/8] use {{.*}} to omit irrelevant columns in the test case

---
 lld/test/ELF/keep-data-section-prefix.s | 36 ++++++++++++-------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/lld/test/ELF/keep-data-section-prefix.s b/lld/test/ELF/keep-data-section-prefix.s
index 0521ff0b7519a..a44be263e821f 100644
--- a/lld/test/ELF/keep-data-section-prefix.s
+++ b/lld/test/ELF/keep-data-section-prefix.s
@@ -38,12 +38,12 @@
 
 ## The first RW PT_LOAD segment has FileSiz 0x126f (0x1000 + 0x200 + 0x60 + 0xf),
 ## and its p_offset p_vaddr p_paddr p_filesz should match PT_GNU_RELRO.
-#           Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
-# SEG:      LOAD           0x0001c8 0x00000000002011c8 0x00000000002011c8 0x000001 0x000001 R E 0x1000
-# SEG-NEXT: LOAD           0x0001c9 0x00000000002021c9 0x00000000002021c9 0x00126f 0x001e37 RW  0x1000
-# SEG-NEXT: LOAD           0x001438 0x0000000000204438 0x0000000000204438 0x000001 0x000002 RW  0x1000
-# SEG-NEXT: GNU_RELRO      0x0001c9 0x00000000002021c9 0x00000000002021c9 0x00126f 0x001e37 R   0x1
-# SEG-NEXT: GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x0
+#           Type           {{.*}}           FileSiz  MemSiz   Flg
+# SEG:      LOAD           {{.*}}           0x000001 0x000001 R E
+# SEG-NEXT: LOAD           {{.*}}           0x00126f 0x001e37 RW
+# SEG-NEXT: LOAD           {{.*}}           0x000001 0x000002 RW
+# SEG-NEXT: GNU_RELRO      {{.*}}           0x00126f 0x001e37 R
+# SEG-NEXT: GNU_STACK      {{.*}}           0x000000 0x000000 RW
 
 ## Input to output mapping per linker script
 ##   .data.rel.ro.split -> .data.rel.ro
@@ -54,13 +54,13 @@
 # LS-NEXT: .data.rel.ro.hot .data.rel.ro .data.rel.ro.unlikely .relro_padding
 # LS-NEXT: .data .bss
 
-#        [Nr] Name                    Type            Address          Off    Size
-# CHECK-LS:      .data.rel.ro.hot        PROGBITS        00000000002021c9 0001c9 00000f
-# CHECK-LS-NEXT: .data.rel.ro            PROGBITS        00000000002021d8 0001d8 000260
-# CHECK-LS-NEXT: .data.rel.ro.unlikely   PROGBITS        0000000000202438 000438 001000
-# CHECK-LS-NEXT: .relro_padding          NOBITS          0000000000203438 001438 000bc8
-# CHECK-LS-NEXT: .data                   PROGBITS        0000000000204438 001438 000001
-# CHECK-LS-NEXT: .bss                    NOBITS          0000000000204439 001439 000001
+#        [Nr] Name                    Type           {{.*}}    Size
+# CHECK-LS:      .data.rel.ro.hot        PROGBITS    {{.*}} 00000f
+# CHECK-LS-NEXT: .data.rel.ro            PROGBITS    {{.*}} 000260
+# CHECK-LS-NEXT: .data.rel.ro.unlikely   PROGBITS    {{.*}} 001000
+# CHECK-LS-NEXT: .relro_padding          NOBITS      {{.*}} 000bc8
+# CHECK-LS-NEXT: .data                   PROGBITS    {{.*}} 000001
+# CHECK-LS-NEXT: .bss                    NOBITS      {{.*}} 000001
 
 ## Linker script is not provided to map data sections.
 ## So all input sections with prefix .data.rel.ro will map to .data.rel.ro in the output.
@@ -68,11 +68,11 @@
 # PRE-NEXT: .data.rel.ro .relro_padding
 # PRE-NEXT: .data .bss
 
-#        [Nr] Name                    Type            Address          Off    Size
-# CHECK-PRE:      .data.rel.ro            PROGBITS        00000000002021c9 0001c9 00126f
-# CHECK-PRE-NEXT: .relro_padding          NOBITS          0000000000203438 001438 000bc8
-# CHECK-PRE-NEXT: .data                   PROGBITS        0000000000204438 001438 000001
-# CHECK-PRE-NEXT: .bss                    NOBITS          0000000000204439 001439 000001
+#        [Nr] Name                    Type            {{.*}}    Size
+# CHECK-PRE:      .data.rel.ro            PROGBITS    {{.*}}    00126f
+# CHECK-PRE-NEXT: .relro_padding          NOBITS      {{.*}}    000bc8
+# CHECK-PRE-NEXT: .data                   PROGBITS    {{.*}}    000001
+# CHECK-PRE-NEXT: .bss                    NOBITS      {{.*}}    000001
 
 # BASIC:         [Nr] Name              Type            {{.*}}   Size              
 # BASIC:         [ 1] .text       

>From 5dbe4df4a8cbcfcd5b5d702a54c315ed334743cb Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Sat, 26 Jul 2025 19:28:46 -0700
Subject: [PATCH 7/8] resolve comment

---
 lld/ELF/LinkerScript.cpp                | 52 ++++++++++++-------------
 lld/test/ELF/keep-data-section-prefix.s | 14 ++-----
 2 files changed, 30 insertions(+), 36 deletions(-)

diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index c0f524eda2c33..2991b03d2ef2b 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -46,12 +46,6 @@ static bool isSectionPrefix(StringRef prefix, StringRef name) {
   return name.consume_front(prefix) && (name.empty() || name[0] == '.');
 }
 
-// If name starts with prefix, trim the prefix and return true.
-// Otherwise, leave the name unchanged and return false.
-static bool trimSectionPrefix(StringRef prefix, StringRef &name) {
-  return name.consume_front(prefix) && (name.empty() || name[0] == '.');
-}
-
 StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
   // This is for --emit-relocs and -r. If .text.foo is emitted as .text.bar, we
   // want to emit .rela.text.foo as .rela.text.bar for consistency (this is not
@@ -117,28 +111,34 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
 
   for (auto [index, v] : llvm::enumerate(dataSectionPrefixes)) {
     StringRef secName = s->name;
-    if (trimSectionPrefix(v, secName)) {
-      if (!ctx.arg.zKeepDataSectionPrefix)
-        return v;
-      if (isSectionPrefix(".hot", secName))
-        return s->name.substr(0, v.size() + 4);
-      if (isSectionPrefix(".unlikely", secName))
-        return s->name.substr(0, v.size() + 9);
-      // For .rodata,  a section could be`.rodata.cst<N>.hot.` for constant
-      // pool or  `rodata.str<N>.hot.` for string literals.
-      if (index == 2) {
-        // The reason to specialize this path is to spell out .rodata.hot and
-        // .rodata.unlikely as string literals for StringRef lifetime
-        // considerations. We cannot use the pattern above to get substr from
-        // section names.
-        if (s->name.ends_with(".hot."))
-          return ".rodata.hot";
-
-        if (s->name.ends_with(".unlikely."))
-          return ".rodata.unlikely";
-      }
+    if (!secName.consume_front(v))
+      continue;
+    if (!secName.empty() && secName[0] != '.') {
+      continue;
+    }
+
+    // The section name starts with 'v', and the remaining string is either
+    // empty or starts with a '.' character. If keep-data-section-prefix is
+    // false, map s to output section with name 'v'.
+    if (!ctx.arg.zKeepDataSectionPrefix)
       return v;
+    // Preserve .hot or .unlikely suffixes in data sections with
+    // keep-data-section-prefix=true.
+    if (isSectionPrefix(".hot", secName))
+      return s->name.substr(0, v.size() + 4);
+    if (isSectionPrefix(".unlikely", secName))
+      return s->name.substr(0, v.size() + 9);
+    if (index == 2) {
+      // Place input .rodata.str<N>.hot. or .rodata.cst<N>.hot. into the
+      // .rodata.hot section.
+      if (s->name.ends_with(".hot."))
+        return ".rodata.hot";
+      // Place input .rodata.str<N>.hot. or .rodata.cst<N>.unlikely. into the
+      // .rodata.unlikely section.
+      if (s->name.ends_with(".unlikely."))
+        return ".rodata.unlikely";
     }
+    return v;
   }
 
   for (StringRef v :
diff --git a/lld/test/ELF/keep-data-section-prefix.s b/lld/test/ELF/keep-data-section-prefix.s
index a44be263e821f..a539cd66b9205 100644
--- a/lld/test/ELF/keep-data-section-prefix.s
+++ b/lld/test/ELF/keep-data-section-prefix.s
@@ -77,8 +77,8 @@
 # BASIC:         [Nr] Name              Type            {{.*}}   Size              
 # BASIC:         [ 1] .text       
 # BASIC-NEXT:    [ 2] .data.rel.ro      PROGBITS        {{.*}}   00000f
-# BASIC-NEXT:    [ 3] .bss.rel.ro       NOBITS          {{.*}}   000008
-# BASIC-NEXT:    [ 4] .relro_padding    NOBITS          {{.*}}   000e20
+# BASIC-NEXT:    [ 3] .bss.rel.ro       NOBITS          {{.*}}   000002
+# BASIC-NEXT:    [ 4] .relro_padding    NOBITS          {{.*}}   000e26
 # BASIC-NEXT:    [ 5] .rodata           PROGBITS        {{.*}}   000006
 # BASIC-NEXT:    [ 6] .data             PROGBITS        {{.*}}   000004
 # BASIC-NEXT:    [ 7] .bss              NOBITS          {{.*}}  000004
@@ -88,8 +88,8 @@
 # KEEP-NEXT:  [ 2] .data.rel.ro             PROGBITS        {{.*}} 000009
 # KEEP-NEXT:  [ 3] .data.rel.ro.hot         PROGBITS        {{.*}} 000004
 # KEEP-NEXT:  [ 4] .data.rel.ro.unlikely    PROGBITS        {{.*}} 000002
-# KEEP-NEXT:  [ 5] .bss.rel.ro              NOBITS          {{.*}} 000008
-# KEEP-NEXT:  [ 6] .relro_padding           NOBITS          {{.*}} 000e20
+# KEEP-NEXT:  [ 5] .bss.rel.ro              NOBITS          {{.*}} 000002
+# KEEP-NEXT:  [ 6] .relro_padding           NOBITS          {{.*}} 000e26
 # KEEP-NEXT:  [ 7] .rodata                  PROGBITS        {{.*}} 000002
 # KEEP-NEXT:  [ 8] .rodata.hot              PROGBITS        {{.*}} 000002
 # KEEP-NEXT:  [ 9] .rodata.unlikely         PROGBITS        {{.*}} 000002
@@ -165,12 +165,6 @@ _start:
 .section .bss.split.d,"aw"
   .byte 0
 
-.section .bss.rel.ro, "aw"
-  .space 2
-.section .bss.rel.ro, "aw"
-  .space 2
-.section .bss.rel.ro, "aw"
-  .space 2
 .section .bss.rel.ro, "aw"
   .space 2
 

>From 28b26f8643454cb891c034dd6385e6eca383b92d Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Mon, 4 Aug 2025 14:24:54 -0700
Subject: [PATCH 8/8] drop braces for single-line if

---
 lld/ELF/LinkerScript.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 2991b03d2ef2b..9652d39f72616 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -113,9 +113,8 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
     StringRef secName = s->name;
     if (!secName.consume_front(v))
       continue;
-    if (!secName.empty() && secName[0] != '.') {
+    if (!secName.empty() && secName[0] != '.')
       continue;
-    }
 
     // The section name starts with 'v', and the remaining string is either
     // empty or starts with a '.' character. If keep-data-section-prefix is



More information about the llvm-commits mailing list