forked from OSchip/llvm-project
[ELF] Define symbols "_end" and "end" if referenced.
These symbols are expected to point to the end of the data segment. Implements http://llvm.org/pr25528. Differential Revision: http://reviews.llvm.org/D14833 llvm-svn: 253637
This commit is contained in:
parent
dcb5653516
commit
b044af50f2
|
@ -85,6 +85,7 @@ std::unique_ptr<InputFile> Lazy::getMember() {
|
|||
}
|
||||
|
||||
template <class ELFT> static void doInitSymbols() {
|
||||
DefinedAbsolute<ELFT>::End.setBinding(STB_GLOBAL);
|
||||
DefinedAbsolute<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
|
||||
DefinedAbsolute<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
|
||||
Undefined<ELFT>::Optional.setVisibility(STV_HIDDEN);
|
||||
|
|
|
@ -177,9 +177,14 @@ template <class ELFT> class DefinedAbsolute : public Defined<ELFT> {
|
|||
public:
|
||||
static Elf_Sym IgnoreUndef;
|
||||
|
||||
// The following symbols must be added early to reserve their places
|
||||
// in symbol tables. The value of the symbols are set when all sections
|
||||
// are finalized and their addresses are determined.
|
||||
|
||||
// The content for _end and end symbols.
|
||||
static Elf_Sym End;
|
||||
|
||||
// The content for _gp symbol for MIPS target.
|
||||
// The symbol has to be added early to reserve a place in symbol tables.
|
||||
// The value of the symbol is computed later by Writer.
|
||||
static Elf_Sym MipsGp;
|
||||
|
||||
DefinedAbsolute(StringRef N, const Elf_Sym &Sym)
|
||||
|
@ -193,6 +198,9 @@ public:
|
|||
template <class ELFT>
|
||||
typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::IgnoreUndef;
|
||||
|
||||
template <class ELFT>
|
||||
typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::End;
|
||||
|
||||
template <class ELFT>
|
||||
typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::MipsGp;
|
||||
|
||||
|
|
|
@ -623,6 +623,23 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
|||
if (!isOutputDynamic())
|
||||
Symtab.addIgnoredSym("__tls_get_addr");
|
||||
|
||||
// If the "_end" symbol is referenced, it is expected to point to the address
|
||||
// right after the data segment. Usually, this symbol points to the end
|
||||
// of .bss section or to the end of .data section if .bss section is absent.
|
||||
// The order of the sections can be affected by linker script,
|
||||
// so it is hard to predict which section will be the last one.
|
||||
// So, if this symbol is referenced, we just add the placeholder here
|
||||
// and update its value later.
|
||||
if (Symtab.find("_end"))
|
||||
Symtab.addAbsoluteSym("_end", DefinedAbsolute<ELFT>::End);
|
||||
|
||||
// If there is an undefined symbol "end", we should initialize it
|
||||
// with the same value as "_end". In any other case it should stay intact,
|
||||
// because it is an allowable name for a user symbol.
|
||||
if (SymbolBody *B = Symtab.find("end"))
|
||||
if (B->isUndefined())
|
||||
Symtab.addAbsoluteSym("end", DefinedAbsolute<ELFT>::End);
|
||||
|
||||
// Scan relocations. This must be done after every symbol is declared so that
|
||||
// we can correctly decide if a dynamic relocation is needed.
|
||||
for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
|
||||
|
@ -879,6 +896,10 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
|||
SectionHeaderOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
|
||||
FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
|
||||
|
||||
// Update "_end" and "end" symbols so that they
|
||||
// point to the end of the data segment.
|
||||
DefinedAbsolute<ELFT>::End.st_value = VA;
|
||||
|
||||
// Update MIPS _gp absolute symbol so that it points to the static data.
|
||||
if (Config->EMachine == EM_MIPS)
|
||||
DefinedAbsolute<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>();
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// Should preserve the value of the "end" symbol if it is defined.
|
||||
// REQUIRES: x86
|
||||
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
// RUN: ld.lld %t.o -o %t
|
||||
// RUN: llvm-nm %t | FileCheck %s
|
||||
|
||||
// CHECK: 0000000000000005 A end
|
||||
|
||||
.global _start,end
|
||||
end = 5
|
||||
.text
|
||||
_start:
|
||||
nop
|
||||
.bss
|
||||
.space 6
|
|
@ -0,0 +1,29 @@
|
|||
// Should set the value of the "end" symbol if it is undefined.
|
||||
// REQUIRES: x86
|
||||
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
// RUN: ld.lld %t.o -o %t
|
||||
// RUN: llvm-readobj -sections -symbols %t | FileCheck %s
|
||||
|
||||
// CHECK: Sections [
|
||||
// CHECK: Name: .bss
|
||||
// CHECK-NEXT: Type:
|
||||
// CHECK-NEXT: Flags [
|
||||
// CHECK-NEXT: SHF_ALLOC
|
||||
// CHECK-NEXT: SHF_WRITE
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: 0x12000
|
||||
// CHECK-NEXT: Offset:
|
||||
// CHECK-NEXT: Size: 6
|
||||
// CHECK: ]
|
||||
// CHECK: Symbols [
|
||||
// CHECK: Name: end
|
||||
// CHECK-NEXT: Value: 0x12006
|
||||
// CHECK: ]
|
||||
|
||||
.global _start,end
|
||||
.text
|
||||
_start:
|
||||
nop
|
||||
.bss
|
||||
.space 6
|
|
@ -0,0 +1,79 @@
|
|||
// Should set the value of the "_end" symbol to the end of the data segment.
|
||||
// REQUIRES: x86
|
||||
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
|
||||
// By default, the .bss section is the latest section of the data segment.
|
||||
// RUN: ld.lld %t.o -o %t
|
||||
// RUN: llvm-readobj -sections -symbols %t | FileCheck %s --check-prefix=DEFAULT
|
||||
|
||||
// DEFAULT: Sections [
|
||||
// DEFAULT: Name: .bss
|
||||
// DEFAULT-NEXT: Type:
|
||||
// DEFAULT-NEXT: Flags [
|
||||
// DEFAULT-NEXT: SHF_ALLOC
|
||||
// DEFAULT-NEXT: SHF_WRITE
|
||||
// DEFAULT-NEXT: ]
|
||||
// DEFAULT-NEXT: Address: 0x12002
|
||||
// DEFAULT-NEXT: Offset:
|
||||
// DEFAULT-NEXT: Size: 6
|
||||
// DEFAULT: ]
|
||||
// DEFAULT: Symbols [
|
||||
// DEFAULT: Name: _end
|
||||
// DEFAULT-NEXT: Value: 0x12008
|
||||
// DEFAULT: ]
|
||||
|
||||
// If there is no .bss section, "_end" should point to the end of the .data section.
|
||||
// RUN: echo "SECTIONS { \
|
||||
// RUN: /DISCARD/ : { *(.bss) } }" > %t.script
|
||||
// RUN: ld.lld %t.o --script %t.script -o %t
|
||||
// RUN: llvm-readobj -sections -symbols %t | FileCheck %s --check-prefix=NOBSS
|
||||
|
||||
// NOBSS: Sections [
|
||||
// NOBSS: Name: .data
|
||||
// NOBSS-NEXT: Type:
|
||||
// NOBSS-NEXT: Flags [
|
||||
// NOBSS-NEXT: SHF_ALLOC
|
||||
// NOBSS-NEXT: SHF_WRITE
|
||||
// NOBSS-NEXT: ]
|
||||
// NOBSS-NEXT: Address: 0x12000
|
||||
// NOBSS-NEXT: Offset:
|
||||
// NOBSS-NEXT: Size: 2
|
||||
// NOBSS: ]
|
||||
// NOBSS: Symbols [
|
||||
// NOBSS: Name: _end
|
||||
// NOBSS-NEXT: Value: 0x12002
|
||||
// NOBSS: ]
|
||||
|
||||
// If the layout of the sections is changed, "_end" should point to the end of allocated address space.
|
||||
// RUN: echo "SECTIONS { \
|
||||
// RUN: .bss : { *(.bss) } \
|
||||
// RUN: .data : { *(.data) } \
|
||||
// RUN: .text : { *(.text) } }" > %t.script
|
||||
// RUN: ld.lld %t.o --script %t.script -o %t
|
||||
// RUN: llvm-readobj -sections -symbols %t | FileCheck %s --check-prefix=TEXTATEND
|
||||
|
||||
// TEXTATEND: Sections [
|
||||
// TEXTATEND: Name: .text
|
||||
// TEXTATEND-NEXT: Type:
|
||||
// TEXTATEND-NEXT: Flags [
|
||||
// TEXTATEND-NEXT: SHF_ALLOC
|
||||
// TEXTATEND-NEXT: SHF_EXECINSTR
|
||||
// TEXTATEND-NEXT: ]
|
||||
// TEXTATEND-NEXT: Address: 0x12000
|
||||
// TEXTATEND-NEXT: Offset:
|
||||
// TEXTATEND-NEXT: Size: 1
|
||||
// TEXTATEND: ]
|
||||
// TEXTATEND: Symbols [
|
||||
// TEXTATEND: Name: _end
|
||||
// TEXTATEND-NEXT: Value: 0x12001
|
||||
// TEXTATEND: ]
|
||||
|
||||
.global _start,_end
|
||||
.text
|
||||
_start:
|
||||
nop
|
||||
.data
|
||||
.word 1
|
||||
.bss
|
||||
.space 6
|
|
@ -1,6 +1,6 @@
|
|||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
|
||||
# RUN: not ld.lld %t1 -o %t2
|
||||
# RUN: ld.lld %t1 -o %t2 -e _end
|
||||
# RUN: ld.lld %t1 -o %t2 -e entry
|
||||
|
||||
# RUN: ld.lld %t1 -o %t2 -e 4096
|
||||
# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=DEC %s
|
||||
|
@ -13,5 +13,5 @@
|
|||
# HEX: Entry: 0xCAFE
|
||||
# OCT: Entry: 0x1FF
|
||||
|
||||
.globl _end
|
||||
_end:
|
||||
.globl entry
|
||||
entry:
|
||||
|
|
Loading…
Reference in New Issue