[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:
parent
508b4510de
commit
07d0a4fb53
|
@ -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.
|
||||
|
|
|
@ -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$
|
58
lld/test/ELF/riscv-section-layout.s
Normal file
58
lld/test/ELF/riscv-section-layout.s
Normal 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
|
Loading…
Reference in New Issue
Block a user