forked from OSchip/llvm-project
Allow adding start/end symbols to any section
Allows adding start and/or end symbols to special output sections, like .eh_frame_hdr, which aren't lists of regular input sections. Differential revision: https://reviews.llvm.org/D23716 llvm-svn: 280205
This commit is contained in:
parent
1e3b086749
commit
20889c51b7
|
@ -310,10 +310,43 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) {
|
|||
}
|
||||
}
|
||||
|
||||
template <class ELFT> void assignOffsets(OutputSectionBase<ELFT> *Sec) {
|
||||
// Linker script may define start and end symbols for special section types,
|
||||
// like .got, .eh_frame_hdr, .eh_frame and others. Those sections are not a list
|
||||
// of regular input input sections, therefore our way of defining symbols for
|
||||
// regular sections will not work. The approach we use for special section types
|
||||
// is not perfect - it handles only start and end symbols.
|
||||
template <class ELFT>
|
||||
void addStartEndSymbols(OutputSectionCommand *Cmd,
|
||||
OutputSectionBase<ELFT> *Sec) {
|
||||
bool Start = true;
|
||||
BaseCommand *PrevCmd = nullptr;
|
||||
|
||||
for (std::unique_ptr<BaseCommand> &Base : Cmd->Commands) {
|
||||
if (auto *AssignCmd = dyn_cast<SymbolAssignment>(Base.get())) {
|
||||
if (auto *Sym = cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
|
||||
Sym->Section = Sec;
|
||||
Sym->Value =
|
||||
AssignCmd->Expression(Sec->getVA() + (Start ? 0 : Sec->getSize())) -
|
||||
Sec->getVA();
|
||||
}
|
||||
} else {
|
||||
if (!Start && isa<SymbolAssignment>(PrevCmd))
|
||||
error("section '" + Sec->getName() +
|
||||
"' supports only start and end symbols");
|
||||
Start = false;
|
||||
}
|
||||
PrevCmd = Base.get();
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void assignOffsets(OutputSectionCommand *Cmd, OutputSectionBase<ELFT> *Sec) {
|
||||
auto *OutSec = dyn_cast<OutputSection<ELFT>>(Sec);
|
||||
if (!OutSec) {
|
||||
Sec->assignOffsets();
|
||||
// This section is not regular output section. However linker script may
|
||||
// have defined start/end symbols for it. This case is handled below.
|
||||
addStartEndSymbols(Cmd, Sec);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -404,19 +437,19 @@ template <class ELFT> void LinkerScript<ELFT>::assignAddresses() {
|
|||
uintX_t TVA = Dot + ThreadBssOffset;
|
||||
TVA = alignTo(TVA, Sec->getAlignment());
|
||||
Sec->setVA(TVA);
|
||||
assignOffsets(Sec);
|
||||
assignOffsets(Cmd, Sec);
|
||||
ThreadBssOffset = TVA - Dot + Sec->getSize();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(Sec->getFlags() & SHF_ALLOC)) {
|
||||
Sec->assignOffsets();
|
||||
assignOffsets(Cmd, Sec);
|
||||
continue;
|
||||
}
|
||||
|
||||
Dot = alignTo(Dot, Sec->getAlignment());
|
||||
Sec->setVA(Dot);
|
||||
assignOffsets(Sec);
|
||||
assignOffsets(Cmd, Sec);
|
||||
MinVA = std::min(MinVA, Dot);
|
||||
Dot += Sec->getSize();
|
||||
}
|
||||
|
|
|
@ -1,36 +1,69 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||
|
||||
# Simple symbol assignment within input section list. The '.' symbol
|
||||
# is not location counter but offset from the beginning of output
|
||||
# section .foo
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: .foo : { \
|
||||
# RUN: begin_foo = .; \
|
||||
# RUN: PROVIDE(_begin_foo = .); \
|
||||
# RUN: PROVIDE(_begin_sec = .); \
|
||||
# RUN: *(.foo) \
|
||||
# RUN: end_foo = .; \
|
||||
# RUN: PROVIDE_HIDDEN(_end_foo = .); \
|
||||
# RUN: PROVIDE_HIDDEN(_end_sec = .); \
|
||||
# RUN: size_foo_1 = SIZEOF(.foo); \
|
||||
# RUN: . = ALIGN(0x1000); \
|
||||
# RUN: begin_bar = .; \
|
||||
# RUN: *(.bar) \
|
||||
# RUN: end_bar = .; \
|
||||
# RUN: size_foo_2 = SIZEOF(.foo); \
|
||||
# RUN: } \
|
||||
# RUN: size_foo_3 = SIZEOF(.foo); }" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: size_foo_2 = SIZEOF(.foo); } \
|
||||
# RUN: size_foo_3 = SIZEOF(.foo); \
|
||||
# RUN: .eh_frame_hdr : { \
|
||||
# RUN: __eh_frame_hdr_start = .; \
|
||||
# RUN: __eh_frame_hdr_start2 = ALIGN(0x10); \
|
||||
# RUN: *(.eh_frame_hdr) \
|
||||
# RUN: __eh_frame_hdr_end = .; \
|
||||
# RUN: __eh_frame_hdr_end2 = ALIGN(0x10); } \
|
||||
# RUN: }" > %t.script
|
||||
# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s
|
||||
|
||||
# SIMPLE: 0000000000000128 .foo 00000000 .hidden _end_foo
|
||||
# SIMPLE: 0000000000000120 .foo 00000000 _begin_foo
|
||||
# SIMPLE-NEXT: 0000000000000120 .foo 00000000 begin_foo
|
||||
# SIMPLE-NEXT: 0000000000000128 .foo 00000000 end_foo
|
||||
# The script below contains symbols in the middle of .eh_frame_hdr section.
|
||||
# We don't support this.
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: .eh_frame_hdr : { \
|
||||
# RUN: PROVIDE_HIDDEN(_begin_sec = .); \
|
||||
# RUN: __eh_frame_hdr_start = .; \
|
||||
# RUN: *(.eh_frame_hdr) \
|
||||
# RUN: __eh_frame_hdr_end = .; \
|
||||
# RUN: *(.eh_frame_hdr) } \
|
||||
# RUN: PROVIDE_HIDDEN(_end_sec = .); \
|
||||
# RUN: }" > %t.script
|
||||
# RUN: not ld.lld -o %t1 --eh-frame-hdr --script %t.script %t 2>&1 | FileCheck --check-prefix=ERROR %s
|
||||
|
||||
# Check that the following script is processed without errors
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: .eh_frame_hdr : { \
|
||||
# RUN: PROVIDE_HIDDEN(_begin_sec = .); \
|
||||
# RUN: *(.eh_frame_hdr) \
|
||||
# RUN: *(.eh_frame_hdr) \
|
||||
# RUN: PROVIDE_HIDDEN(_end_sec = .); } \
|
||||
# RUN: }" > %t.script
|
||||
# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
|
||||
|
||||
# SIMPLE: 0000000000000160 .foo 00000000 .hidden _end_sec
|
||||
# SIMPLE: 0000000000000158 .foo 00000000 _begin_sec
|
||||
# SIMPLE-NEXT: 0000000000000158 .foo 00000000 begin_foo
|
||||
# SIMPLE-NEXT: 0000000000000160 .foo 00000000 end_foo
|
||||
# SIMPLE-NEXT: 0000000000000008 .foo 00000000 size_foo_1
|
||||
# SIMPLE-NEXT: 0000000000001000 .foo 00000000 begin_bar
|
||||
# SIMPLE-NEXT: 0000000000001004 .foo 00000000 end_bar
|
||||
# SIMPLE-NEXT: 0000000000000ee4 .foo 00000000 size_foo_2
|
||||
# SIMPLE-NEXT: 0000000000000ee4 *ABS* 00000000 size_foo_3
|
||||
# SIMPLE-NEXT: 0000000000000eac .foo 00000000 size_foo_2
|
||||
# SIMPLE-NEXT: 0000000000000eac *ABS* 00000000 size_foo_3
|
||||
# SIMPLE-NEXT: 0000000000001004 .eh_frame_hdr 00000000 __eh_frame_hdr_start
|
||||
# SIMPLE-NEXT: 0000000000001010 .eh_frame_hdr 00000000 __eh_frame_hdr_start2
|
||||
# SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end
|
||||
# SIMPLE-NEXT: 0000000000001020 .eh_frame_hdr 00000000 __eh_frame_hdr_end2
|
||||
# ERROR: section '.eh_frame_hdr' supports only start and end symbols
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
|
@ -42,4 +75,9 @@ _start:
|
|||
.section .bar,"a"
|
||||
.long 0
|
||||
|
||||
.global _begin_foo, _end_foo
|
||||
.section .dah,"ax",@progbits
|
||||
.cfi_startproc
|
||||
nop
|
||||
.cfi_endproc
|
||||
|
||||
.global _begin_sec, _end_sec
|
||||
|
|
Loading…
Reference in New Issue