diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 53a7c4b1e673bf..e01e8ce2523be2 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 void Writer::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 ee86438ec4f350..00000000000000 --- 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 00000000000000..bb9adf5eef0545 --- /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",@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