[lld] 07d0a4f - [ELF][RISCV] Make .sdata and .sbss closer

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 7 10:37:08 PST 2023


Author: Fangrui Song
Date: 2023-03-07T10:37:04-08:00
New Revision: 07d0a4fb537f15d68385c0598d3b0dbf9e99763d

URL: https://github.com/llvm/llvm-project/commit/07d0a4fb537f15d68385c0598d3b0dbf9e99763d
DIFF: https://github.com/llvm/llvm-project/commit/07d0a4fb537f15d68385c0598d3b0dbf9e99763d.diff

LOG: [ELF][RISCV] Make .sdata and .sbss closer

GNU ld's internal linker scripts for RISC-V place .sdata and .sbss close.
This makes GP relaxation more profitable.

While here, when .sbss is present, set `__bss_start` to the start of
.sbss instead of .bss, to match GNU ld.

Note: GNU ld's internal linker scripts have symbol assignments and input
section descriptions which are not relevant for modern systems. We only
add things that make sense.

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D145118

Added: 
    lld/test/ELF/riscv-section-layout.s

Modified: 
    lld/ELF/Writer.cpp

Removed: 
    lld/test/ELF/riscv-gp-no-sdata.s


################################################################################
diff  --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 53a7c4b1e673b..e01e8ce2523be 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -846,7 +846,8 @@ enum RankFlags {
   RF_PPC_GOT = 1 << 3,
   RF_PPC_BRANCH_LT = 1 << 2,
   RF_MIPS_GPREL = 1 << 1,
-  RF_MIPS_NOT_GOT = 1 << 0
+  RF_MIPS_NOT_GOT = 1 << 0,
+  RF_RISCV_SDATA = 1 << 0,
 };
 
 static unsigned getSectionRank(const OutputSection &osec) {
@@ -972,6 +973,14 @@ static unsigned getSectionRank(const OutputSection &osec) {
       rank |= RF_MIPS_NOT_GOT;
   }
 
+  if (config->emachine == EM_RISCV) {
+    // .sdata and .sbss are placed closer to make GP relaxation more profitable
+    // and match GNU ld.
+    StringRef name = osec.name;
+    if (name == ".sdata" || (osec.type == SHT_NOBITS && name != ".sbss"))
+      rank |= RF_RISCV_SDATA;
+  }
+
   return rank;
 }
 
@@ -1087,8 +1096,12 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
       ElfSym::end2->section = last->lastSec;
   }
 
-  if (ElfSym::bss)
-    ElfSym::bss->section = findSection(".bss");
+  if (ElfSym::bss) {
+    // On RISC-V, set __bss_start to the start of .sbss if present.
+    OutputSection *sbss =
+        config->emachine == EM_RISCV ? findSection(".sbss") : nullptr;
+    ElfSym::bss->section = sbss ? sbss : findSection(".bss");
+  }
 
   // Setup MIPS _gp_disp/__gnu_local_gp symbols which should
   // be equal to the _gp symbol's value.

diff  --git a/lld/test/ELF/riscv-gp-no-sdata.s b/lld/test/ELF/riscv-gp-no-sdata.s
deleted file mode 100644
index ee86438ec4f35..0000000000000
--- a/lld/test/ELF/riscv-gp-no-sdata.s
+++ /dev/null
@@ -1,15 +0,0 @@
-# REQUIRES: riscv
-# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32.o
-# RUN: ld.lld -pie %t.32.o -o %t.32
-# RUN: llvm-readelf -s %t.32 | FileCheck --check-prefix=SYM %s
-
-# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
-# RUN: ld.lld -pie %t.64.o -o %t.64
-# RUN: llvm-readelf -s %t.64 | FileCheck --check-prefix=SYM %s
-
-## If there is an undefined reference to __global_pointer$ but .sdata doesn't
-## exist, define __global_pointer$ and set its st_shndx arbitrarily to 1.
-
-# SYM: {{0*}}00000800 0 NOTYPE GLOBAL DEFAULT 1 __global_pointer$
-
-lla gp, __global_pointer$

diff  --git a/lld/test/ELF/riscv-section-layout.s b/lld/test/ELF/riscv-section-layout.s
new file mode 100644
index 0000000000000..bb9adf5eef054
--- /dev/null
+++ b/lld/test/ELF/riscv-section-layout.s
@@ -0,0 +1,58 @@
+# REQUIRES: riscv
+## Test RISC-V specific section layout. See also section-layout.s and riscv-gp.s.
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32.o
+# RUN: ld.lld -pie %t.32.o -o %t.32
+# RUN: llvm-readelf -S -s %t.32 | FileCheck %s --check-prefix=NOSDATA
+# RUN: llvm-mc -filetype=obj -triple=riscv32 --defsym=SDATA=1 %s -o %t.32s.o
+# RUN: ld.lld -pie %t.32s.o -o %t.32s
+# RUN: llvm-readelf -S -s %t.32s | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
+# RUN: ld.lld -pie %t.64.o -o %t.64
+# RUN: llvm-readelf -S -s %t.64 | FileCheck %s --check-prefix=NOSDATA
+# RUN: llvm-mc -filetype=obj -triple=riscv64 --defsym=SDATA=1 %s -o %t.64s.o
+# RUN: ld.lld -pie %t.64s.o -o %t.64s
+# RUN: llvm-readelf -S -s %t.64s | FileCheck %s
+
+# NOSDATA:      .text
+# NOSDATA-NEXT: .tdata
+# NOSDATA-NEXT: .tbss
+# NOSDATA-NEXT: .dynamic
+# NOSDATA-NEXT: .got
+# NOSDATA-NEXT: .data    PROGBITS [[#%x,DATA:]]
+# NOSDATA-NEXT: .bss     NOBITS   [[#%x,BSS:]]
+
+## If there is an undefined reference to __global_pointer$ but .sdata doesn't
+## exist, define __global_pointer$ and set its st_shndx arbitrarily to 1.
+## The symbol value should not be used by the program.
+
+# NOSDATA-DAG:  [[#]]: {{0*}}[[#BSS]]         0 NOTYPE  GLOBAL DEFAULT [[#]] _edata
+# NOSDATA-DAG:  [[#]]: {{0*}}[[#BSS]]         0 NOTYPE  GLOBAL DEFAULT [[#]] __bss_start
+# NOSDATA-DAG:  [[#]]: {{0*}}800              0 NOTYPE  GLOBAL DEFAULT     1 __global_pointer$
+
+# CHECK:      .text
+# CHECK-NEXT: .tdata
+# CHECK-NEXT: .tbss
+# CHECK-NEXT: .dynamic
+# CHECK-NEXT: .got
+# CHECK-NEXT: .data
+# CHECK-NEXT: .sdata     PROGBITS [[#%x,SDATA:]]
+# CHECK-NEXT: .sbss      NOBITS   [[#%x,SBSS:]]
+# CHECK-NEXT: .bss
+
+# CHECK-DAG:  [[#]]: {{0*}}[[#SBSS]]        0 NOTYPE  GLOBAL DEFAULT [[#]] _edata
+# CHECK-DAG:  [[#]]: {{0*}}[[#SBSS]]        0 NOTYPE  GLOBAL DEFAULT [[#]] __bss_start
+# CHECK-DAG:  [[#]]: {{0*}}[[#SDATA+0x800]] 0 NOTYPE  GLOBAL DEFAULT [[#]] __global_pointer$
+
+.globl _edata, __bss_start
+  lla gp, __global_pointer$
+
+.section .data,"aw", at progbits; .long _GLOBAL_OFFSET_TABLE_ - .
+.section .bss,"aw", at nobits; .space 1
+.section .tdata,"awT", at progbits; .space 1
+.section .tbss,"awT", at nobits; .space 1
+.ifdef SDATA
+.section .sdata,"aw", at progbits; .space 1
+.section .sbss,"aw", at nobits; .space 1
+.endif


        


More information about the llvm-commits mailing list