summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-01-06 21:36:48 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-01-06 21:36:48 +0000
commit97dd191f563d0b295e4abc86dc95a4f6276c6d8f (patch)
treedc66d565f400b52657b1297dba15c40cf91b74a3
parentae1a339de31cf4065777531959a11e55a2e5fa00 (diff)
Notes
-rw-r--r--ELF/Driver.cpp3
-rw-r--r--ELF/Relocations.cpp18
-rw-r--r--ELF/SyntheticSections.cpp10
-rw-r--r--ELF/Writer.cpp26
-rw-r--r--docs/ReleaseNotes.rst8
-rw-r--r--test/ELF/Inputs/shlib-undefined-ref.s4
-rw-r--r--test/ELF/gnu-ifunc-dyntags.s41
-rw-r--r--test/ELF/linkerscript/nobits-offset.s18
-rw-r--r--test/ELF/relocation-size-err.s12
-rw-r--r--test/ELF/shlib-undefined-shared.s15
-rw-r--r--test/ELF/weak-undef-rw.s12
11 files changed, 146 insertions, 21 deletions
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index cc76fea2ad5e..b159fe63eb18 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -1043,7 +1043,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
return;
// Handle undefined symbols in DSOs.
- Symtab->scanShlibUndefined<ELFT>();
+ if (!Config->Shared)
+ Symtab->scanShlibUndefined<ELFT>();
// Handle the -exclude-libs option.
if (Args.hasArg(OPT_exclude_libs))
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp
index 1aa0957b1d01..37bc8bcbd571 100644
--- a/ELF/Relocations.cpp
+++ b/ELF/Relocations.cpp
@@ -367,7 +367,7 @@ static bool isRelExpr(RelExpr Expr) {
static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
InputSectionBase &S, uint64_t RelOff) {
// These expressions always compute a constant
- if (isRelExprOneOf<R_SIZE, R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
+ if (isRelExprOneOf<R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC,
R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_PC, R_TLSGD,
@@ -384,6 +384,10 @@ static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
if (!Config->Pic)
return true;
+ // The size of a non preemptible symbol is a constant.
+ if (E == R_SIZE)
+ return true;
+
// For the target and the relocation, we want to know if they are
// absolute or relative.
bool AbsVal = isAbsoluteValue(Sym);
@@ -592,6 +596,12 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
if (IsConstant)
return Expr;
+ // We can create any dynamic relocation supported by the dynamic linker if a
+ // section is writable or we are passed -z notext.
+ bool CanWrite = (S.Flags & SHF_WRITE) || !Config->ZText;
+ if (CanWrite && Target->isPicRel(Type))
+ return Expr;
+
// If the relocation is to a weak undef, and we are producing
// executable, give up on it and produce a non preemptible 0.
if (!Config->Shared && Sym.isUndefWeak()) {
@@ -600,12 +610,6 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
return Expr;
}
- // We can create any dynamic relocation supported by the dynamic linker if a
- // section is writable or we are passed -z notext.
- bool CanWrite = (S.Flags & SHF_WRITE) || !Config->ZText;
- if (CanWrite && Target->isPicRel(Type))
- return Expr;
-
// If we got here we know that this relocation would require the dynamic
// linker to write a value to read only memory or use an unsupported
// relocation.
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index a5e291b79a4d..f878acf8cf3f 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -1064,7 +1064,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
addInt(DT_DEBUG, 0);
this->Link = InX::DynStrTab->getParent()->SectionIndex;
- if (InX::RelaDyn->getParent() && !InX::RelaDyn->empty()) {
+ if (!InX::RelaDyn->empty()) {
addInSec(InX::RelaDyn->DynamicTag, InX::RelaDyn);
addSize(InX::RelaDyn->SizeDynamicTag, InX::RelaDyn->getParent());
@@ -1081,7 +1081,13 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels);
}
}
- if (InX::RelaPlt->getParent() && !InX::RelaPlt->empty()) {
+ // .rel[a].plt section usually consists of two parts, containing plt and
+ // iplt relocations. It is possible to have only iplt relocations in the
+ // output. In that case RelaPlt is empty and have zero offset, the same offset
+ // as RelaIplt have. And we still want to emit proper dynamic tags for that
+ // case, so here we always use RelaPlt as marker for the begining of
+ // .rel[a].plt section.
+ if (InX::RelaPlt->getParent()->Live) {
addInSec(DT_JMPREL, InX::RelaPlt);
addSize(DT_PLTRELSZ, InX::RelaPlt->getParent());
switch (Config->EMachine) {
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 15f382104756..24c3e1ee207c 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -1767,30 +1767,36 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
// virtual address (modulo the page size) so that the loader can load
// executables without any address adjustment.
static uint64_t getFileAlignment(uint64_t Off, OutputSection *Cmd) {
- // If the section is not in a PT_LOAD, we just have to align it.
- if (!Cmd->PtLoad)
- return alignTo(Off, Cmd->Alignment);
-
- OutputSection *First = Cmd->PtLoad->FirstSec;
+ OutputSection *First = Cmd->PtLoad ? Cmd->PtLoad->FirstSec : nullptr;
// The first section in a PT_LOAD has to have congruent offset and address
// module the page size.
if (Cmd == First)
return alignTo(Off, std::max<uint64_t>(Cmd->Alignment, Config->MaxPageSize),
Cmd->Addr);
+ // For SHT_NOBITS we don't want the alignment of the section to impact the
+ // offset of the sections that follow. Since nothing seems to care about the
+ // sh_offset of the SHT_NOBITS section itself, just ignore it.
+ if (Cmd->Type == SHT_NOBITS)
+ return Off;
+
+ // If the section is not in a PT_LOAD, we just have to align it.
+ if (!Cmd->PtLoad)
+ return alignTo(Off, Cmd->Alignment);
+
// If two sections share the same PT_LOAD the file offset is calculated
// using this formula: Off2 = Off1 + (VA2 - VA1).
return First->Offset + Cmd->Addr - First->Addr;
}
static uint64_t setOffset(OutputSection *Cmd, uint64_t Off) {
- if (Cmd->Type == SHT_NOBITS) {
- Cmd->Offset = Off;
- return Off;
- }
-
Off = getFileAlignment(Off, Cmd);
Cmd->Offset = Off;
+
+ // For SHT_NOBITS we should not count the size.
+ if (Cmd->Type == SHT_NOBITS)
+ return Off;
+
return Off + Cmd->Size;
}
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index dcd6ac0602d3..e7ea0c8845fd 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -29,7 +29,13 @@ ELF Improvements
COFF Improvements
-----------------
-* Item 1.
+* A GNU ld style frontend for the COFF linker has been added for MinGW.
+ In MinGW environments, the linker is invoked with GNU ld style parameters;
+ which LLD previously only supported when used as an ELF linker. When
+ a PE/COFF target is chosen, those parameters are rewritten into the
+ lld-link style parameters and the COFF linker is invoked instead.
+
+* Initial support for the ARM64 architecture has been added.
MachO Improvements
------------------
diff --git a/test/ELF/Inputs/shlib-undefined-ref.s b/test/ELF/Inputs/shlib-undefined-ref.s
new file mode 100644
index 000000000000..cfb7c60ebc01
--- /dev/null
+++ b/test/ELF/Inputs/shlib-undefined-ref.s
@@ -0,0 +1,4 @@
+.globl f
+f:
+ call should_not_be_exported@PLT
+ ret
diff --git a/test/ELF/gnu-ifunc-dyntags.s b/test/ELF/gnu-ifunc-dyntags.s
new file mode 100644
index 000000000000..81bd338d088d
--- /dev/null
+++ b/test/ELF/gnu-ifunc-dyntags.s
@@ -0,0 +1,41 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld -pie %t.o -o %tout
+# RUN: llvm-objdump -section-headers %tout | FileCheck %s
+# RUN: llvm-readobj -dynamic-table -r %tout | FileCheck %s --check-prefix=TAGS
+
+## Check we produce DT_PLTREL/DT_JMPREL/DT_PLTGOT and DT_PLTRELSZ tags
+## when there are no other relocations except R_*_IRELATIVE.
+
+# CHECK: Name Size Address
+# CHECK: .rela.plt 00000030 0000000000000210
+# CHECK: .got.plt 00000010 0000000000002000
+
+# TAGS: Relocations [
+# TAGS-NEXT: Section {{.*}} .rela.plt {
+# TAGS-NEXT: R_X86_64_IRELATIVE
+# TAGS-NEXT: R_X86_64_IRELATIVE
+# TAGS-NEXT: }
+# TAGS-NEXT: ]
+
+# TAGS: Tag Type Name/Value
+# TAGS: 0x0000000000000017 JMPREL 0x210
+# TAGS: 0x0000000000000002 PLTRELSZ 48
+# TAGS: 0x0000000000000003 PLTGOT 0x2000
+# TAGS: 0x0000000000000014 PLTREL RELA
+
+.text
+.type foo STT_GNU_IFUNC
+.globl foo
+foo:
+ ret
+
+.type bar STT_GNU_IFUNC
+.globl bar
+bar:
+ ret
+
+.globl _start
+_start:
+ call foo
+ call bar
diff --git a/test/ELF/linkerscript/nobits-offset.s b/test/ELF/linkerscript/nobits-offset.s
new file mode 100644
index 000000000000..c4141487630b
--- /dev/null
+++ b/test/ELF/linkerscript/nobits-offset.s
@@ -0,0 +1,18 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: echo "SECTIONS { \
+# RUN: .sec1 (NOLOAD) : { . += 1; } \
+# RUN: .text : { *(.text) } \
+# RUN: };" > %t.script
+# RUN: ld.lld %t.o -T %t.script -o %t
+# RUN: llvm-readelf --sections %t | FileCheck %s
+
+# We used to misalign section offsets if the first section in a
+# PT_LOAD was SHT_NOBITS.
+
+# CHECK: [ 2] .text PROGBITS 0000000000000010 001010 000010 00 AX 0 0 16
+
+.global _start
+_start:
+ nop
+.p2align 4
diff --git a/test/ELF/relocation-size-err.s b/test/ELF/relocation-size-err.s
new file mode 100644
index 000000000000..7bef45b66047
--- /dev/null
+++ b/test/ELF/relocation-size-err.s
@@ -0,0 +1,12 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s
+
+// CHECK: error: can't create dynamic relocation R_X86_64_SIZE64 against symbol: foo in readonly segment; recompile object files with -fPIC
+
+ .global foo
+foo:
+ .quad 42
+ .size foo, 8
+
+ .quad foo@SIZE
diff --git a/test/ELF/shlib-undefined-shared.s b/test/ELF/shlib-undefined-shared.s
new file mode 100644
index 000000000000..6d60d01bfabe
--- /dev/null
+++ b/test/ELF/shlib-undefined-shared.s
@@ -0,0 +1,15 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -o %t1.o %S/Inputs/shlib-undefined-ref.s
+# RUN: ld.lld -shared -o %t1.so %t1.o
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -o %t2.o %s
+# RUN: echo "{ local: *; };" > %t.script
+# RUN: ld.lld -shared -version-script %t.script -o %t2.so %t2.o %t1.so
+# RUN: llvm-nm -g %t2.so | FileCheck -allow-empty %s
+
+# CHECK-NOT: should_not_be_exported
+
+.globl should_not_be_exported
+should_not_be_exported:
+ ret
diff --git a/test/ELF/weak-undef-rw.s b/test/ELF/weak-undef-rw.s
new file mode 100644
index 000000000000..c75e7d67db3d
--- /dev/null
+++ b/test/ELF/weak-undef-rw.s
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t --export-dynamic
+# RUN: llvm-readobj -r %t | FileCheck %s
+
+# CHECK: R_X86_64_64 foobar 0x0
+
+ .global _start
+_start:
+ .data
+ .weak foobar
+ .quad foobar