[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
This commit is contained in:
Fangrui Song 2023-03-07 10:37:04 -08:00
parent 508b4510de
commit 07d0a4fb53
3 changed files with 74 additions and 18 deletions

View File

@ -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.

View File

@ -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$

View File

@ -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",@progbits; .long _GLOBAL_OFFSET_TABLE_ - .
.section .bss,"aw",@nobits; .space 1
.section .tdata,"awT",@progbits; .space 1
.section .tbss,"awT",@nobits; .space 1
.ifdef SDATA
.section .sdata,"aw",@progbits; .space 1
.section .sbss,"aw",@nobits; .space 1
.endif