forked from OSchip/llvm-project
[ELF] - Linkerscript: implemented output section [address] attribute.
Output section description in SECTIONS looks like that: section [address] [(type)] : ... { ... } Patch implements support of address atribute. Differential revision: https://reviews.llvm.org/D22689 llvm-svn: 276619
This commit is contained in:
parent
ebf866213c
commit
58e5c4dcfe
|
@ -194,6 +194,9 @@ void LinkerScript<ELFT>::assignAddresses(
|
||||||
if (Sec->getName() != Cmd->Name)
|
if (Sec->getName() != Cmd->Name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (Cmd->AddrExpr)
|
||||||
|
Dot = Cmd->AddrExpr(Dot);
|
||||||
|
|
||||||
if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
|
if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
|
||||||
uintX_t TVA = Dot + ThreadBssOffset;
|
uintX_t TVA = Dot + ThreadBssOffset;
|
||||||
TVA = alignTo(TVA, Sec->getAlignment());
|
TVA = alignTo(TVA, Sec->getAlignment());
|
||||||
|
@ -648,6 +651,12 @@ static int precedence(StringRef Op) {
|
||||||
void ScriptParser::readOutputSectionDescription(StringRef OutSec) {
|
void ScriptParser::readOutputSectionDescription(StringRef OutSec) {
|
||||||
OutputSectionCommand *Cmd = new OutputSectionCommand(OutSec);
|
OutputSectionCommand *Cmd = new OutputSectionCommand(OutSec);
|
||||||
Opt.Commands.emplace_back(Cmd);
|
Opt.Commands.emplace_back(Cmd);
|
||||||
|
|
||||||
|
// Read an address expression.
|
||||||
|
// https://sourceware.org/binutils/docs/ld/Output-Section-Address.html#Output-Section-Address
|
||||||
|
if (peek() != ":")
|
||||||
|
Cmd->AddrExpr = readExpr();
|
||||||
|
|
||||||
expect(":");
|
expect(":");
|
||||||
|
|
||||||
// Parse constraints.
|
// Parse constraints.
|
||||||
|
|
|
@ -72,6 +72,7 @@ struct OutputSectionCommand : BaseCommand {
|
||||||
: BaseCommand(OutputSectionKind), Name(Name) {}
|
: BaseCommand(OutputSectionKind), Name(Name) {}
|
||||||
static bool classof(const BaseCommand *C);
|
static bool classof(const BaseCommand *C);
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
|
Expr AddrExpr;
|
||||||
std::vector<std::unique_ptr<BaseCommand>> Commands;
|
std::vector<std::unique_ptr<BaseCommand>> Commands;
|
||||||
std::vector<StringRef> Phdrs;
|
std::vector<StringRef> Phdrs;
|
||||||
std::vector<uint8_t> Filler;
|
std::vector<uint8_t> Filler;
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
# REQUIRES: x86
|
||||||
|
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||||
|
# RUN: echo "SECTIONS { \
|
||||||
|
# RUN: .aaa 0x2000 : \
|
||||||
|
# RUN: { \
|
||||||
|
# RUN: *(.aaa) \
|
||||||
|
# RUN: } \
|
||||||
|
# RUN: .bbb 0x1 ? 0x3000 : 0x4000 : \
|
||||||
|
# RUN: { \
|
||||||
|
# RUN: *(.bbb) \
|
||||||
|
# RUN: } \
|
||||||
|
# RUN: .ccc ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : \
|
||||||
|
# RUN: { \
|
||||||
|
# RUN: *(.ccc) \
|
||||||
|
# RUN: } \
|
||||||
|
# RUN: .ddd 0x5001 : \
|
||||||
|
# RUN: { \
|
||||||
|
# RUN: *(.ddd) \
|
||||||
|
# RUN: } \
|
||||||
|
# RUN: }" > %t.script
|
||||||
|
# RUN: ld.lld %t --script %t.script -o %tout
|
||||||
|
# RUN: llvm-readobj -s %tout | FileCheck %s
|
||||||
|
|
||||||
|
## Check:
|
||||||
|
## 1) Simple constant as address.
|
||||||
|
## 2) That something that contains ":" character, like ternary
|
||||||
|
## operator works as expression.
|
||||||
|
## 3) That complex expressions work.
|
||||||
|
## 4) That section alignment still applied to explicitly specified address.
|
||||||
|
|
||||||
|
#CHECK:Sections [
|
||||||
|
#CHECK: Section {
|
||||||
|
#CHECK: Index: 0
|
||||||
|
#CHECK: Name:
|
||||||
|
#CHECK: Type: SHT_NULL
|
||||||
|
#CHECK: Flags [
|
||||||
|
#CHECK: ]
|
||||||
|
#CHECK: Address: 0x0
|
||||||
|
#CHECK: Offset: 0x0
|
||||||
|
#CHECK: Size: 0
|
||||||
|
#CHECK: Link: 0
|
||||||
|
#CHECK: Info: 0
|
||||||
|
#CHECK: AddressAlignment: 0
|
||||||
|
#CHECK: EntrySize: 0
|
||||||
|
#CHECK: }
|
||||||
|
#CHECK: Section {
|
||||||
|
#CHECK: Index: 1
|
||||||
|
#CHECK: Name: .aaa
|
||||||
|
#CHECK: Type: SHT_PROGBITS
|
||||||
|
#CHECK: Flags [
|
||||||
|
#CHECK: SHF_ALLOC
|
||||||
|
#CHECK: ]
|
||||||
|
#CHECK: Address: 0x2000
|
||||||
|
#CHECK: Offset: 0x1000
|
||||||
|
#CHECK: Size: 8
|
||||||
|
#CHECK: Link: 0
|
||||||
|
#CHECK: Info: 0
|
||||||
|
#CHECK: AddressAlignment: 1
|
||||||
|
#CHECK: EntrySize: 0
|
||||||
|
#CHECK: }
|
||||||
|
#CHECK: Section {
|
||||||
|
#CHECK: Index: 2
|
||||||
|
#CHECK: Name: .bbb
|
||||||
|
#CHECK: Type: SHT_PROGBITS
|
||||||
|
#CHECK: Flags [
|
||||||
|
#CHECK: SHF_ALLOC
|
||||||
|
#CHECK: ]
|
||||||
|
#CHECK: Address: 0x3000
|
||||||
|
#CHECK: Offset: 0x2000
|
||||||
|
#CHECK: Size: 8
|
||||||
|
#CHECK: Link: 0
|
||||||
|
#CHECK: Info: 0
|
||||||
|
#CHECK: AddressAlignment: 1
|
||||||
|
#CHECK: EntrySize: 0
|
||||||
|
#CHECK: }
|
||||||
|
#CHECK: Section {
|
||||||
|
#CHECK: Index: 3
|
||||||
|
#CHECK: Name: .ccc
|
||||||
|
#CHECK: Type: SHT_PROGBITS
|
||||||
|
#CHECK: Flags [
|
||||||
|
#CHECK: SHF_ALLOC
|
||||||
|
#CHECK: ]
|
||||||
|
#CHECK: Address: 0x4008
|
||||||
|
#CHECK: Offset: 0x2008
|
||||||
|
#CHECK: Size: 8
|
||||||
|
#CHECK: Link: 0
|
||||||
|
#CHECK: Info: 0
|
||||||
|
#CHECK: AddressAlignment: 1
|
||||||
|
#CHECK: EntrySize: 0
|
||||||
|
#CHECK: }
|
||||||
|
#CHECK: Section {
|
||||||
|
#CHECK: Index: 4
|
||||||
|
#CHECK: Name: .ddd
|
||||||
|
#CHECK: Type: SHT_PROGBITS
|
||||||
|
#CHECK: Flags [
|
||||||
|
#CHECK: SHF_ALLOC
|
||||||
|
#CHECK: ]
|
||||||
|
#CHECK: Address: 0x5010
|
||||||
|
#CHECK: Offset: 0x2010
|
||||||
|
#CHECK: Size: 8
|
||||||
|
#CHECK: Link: 0
|
||||||
|
#CHECK: Info: 0
|
||||||
|
#CHECK: AddressAlignment: 16
|
||||||
|
#CHECK: EntrySize: 0
|
||||||
|
#CHECK: }
|
||||||
|
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
nop
|
||||||
|
|
||||||
|
.section .aaa, "a"
|
||||||
|
.quad 0
|
||||||
|
|
||||||
|
.section .bbb, "a"
|
||||||
|
.quad 0
|
||||||
|
|
||||||
|
.section .ccc, "a"
|
||||||
|
.quad 0
|
||||||
|
|
||||||
|
.section .ddd, "a"
|
||||||
|
.align 16
|
||||||
|
.quad 0
|
|
@ -61,6 +61,6 @@
|
||||||
# RUN: echo "boom .temp : { *(.temp) } }" >> %t.script
|
# RUN: echo "boom .temp : { *(.temp) } }" >> %t.script
|
||||||
# RUN: not ld.lld -shared %t -o %t1 --script %t.script > %t.log 2>&1
|
# RUN: not ld.lld -shared %t -o %t1 --script %t.script > %t.log 2>&1
|
||||||
# RUN: FileCheck -check-prefix=ERR7 %s < %t.log
|
# RUN: FileCheck -check-prefix=ERR7 %s < %t.log
|
||||||
# ERR7: line 4: : expected, but got .temp
|
# ERR7: line 4: malformed number: .temp
|
||||||
# ERR7-NEXT: boom .temp : { *(.temp) } }
|
# ERR7-NEXT: boom .temp : { *(.temp) } }
|
||||||
# RUN: grep '^ ^' %t.log
|
# RUN: grep '^ ^' %t.log
|
||||||
|
|
Loading…
Reference in New Issue