[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