Vendor import of lld trunk r304222:

https://llvm.org/svn/llvm-project/lld/trunk@304222
This commit is contained in:
Dimitry Andric 2017-05-30 17:38:04 +00:00
parent bef2946c21
commit cbb560c9ba
11 changed files with 83 additions and 41 deletions

View file

@ -52,11 +52,12 @@ LinkerScript *elf::Script;
uint64_t ExprValue::getValue() const {
if (Sec) {
if (Sec->getOutputSection())
return Sec->getOffset(Val) + Sec->getOutputSection()->Addr;
return alignTo(Sec->getOffset(Val) + Sec->getOutputSection()->Addr,
Alignment);
error("unable to evaluate expression: input section " + Sec->Name +
" has no output section assigned");
}
return Val;
return alignTo(Val, Alignment);
}
uint64_t ExprValue::getSecAddr() const {
@ -143,7 +144,7 @@ void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) {
} else {
Sym->Section = V.Sec;
if (Sym->Section->Flags & SHF_ALLOC)
Sym->Value = V.Val;
Sym->Value = alignTo(V.Val, V.Alignment);
else
Sym->Value = V.getValue();
}
@ -290,6 +291,9 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) {
size_t SizeBefore = Ret.size();
for (InputSectionBase *Sec : InputSections) {
if (!isa<InputSection>(Sec))
continue;
if (Sec->Assigned)
continue;
@ -1076,6 +1080,9 @@ template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) {
return;
}
if (Sec->Type == SHT_NOBITS)
return;
// Write leading padding.
ArrayRef<InputSection *> Sections = Sec->Sections;
uint32_t Filler = getFiller();

View file

@ -41,7 +41,12 @@ struct ExprValue {
SectionBase *Sec;
uint64_t Val;
bool ForceAbsolute;
uint64_t Alignment = 1;
ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val,
uint64_t Alignment)
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute), Alignment(Alignment) {
}
ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val)
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute) {}
ExprValue(SectionBase *Sec, uint64_t Val) : ExprValue(Sec, false, Val) {}

View file

@ -100,7 +100,7 @@ getSymbolStrings(ArrayRef<DefinedRegular *> Syms) {
}
template <class ELFT>
void elf::writeMapFile(llvm::ArrayRef<BaseCommand *> Script) {
void elf::writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script) {
if (Config->MapFile.empty())
return;
@ -123,10 +123,7 @@ void elf::writeMapFile(llvm::ArrayRef<BaseCommand *> Script) {
<< " Align Out In Symbol\n";
// Print out file contents.
for (BaseCommand *Base : Script) {
auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
if (!Cmd)
continue;
for (OutputSectionCommand *Cmd : Script) {
OutputSection *OSec = Cmd->Sec;
writeHeader<ELFT>(OS, OSec->Addr, OSec->Size, OSec->Alignment);
OS << OSec->Name << '\n';
@ -147,7 +144,7 @@ void elf::writeMapFile(llvm::ArrayRef<BaseCommand *> Script) {
}
}
template void elf::writeMapFile<ELF32LE>(ArrayRef<BaseCommand *>);
template void elf::writeMapFile<ELF32BE>(ArrayRef<BaseCommand *>);
template void elf::writeMapFile<ELF64LE>(ArrayRef<BaseCommand *>);
template void elf::writeMapFile<ELF64BE>(ArrayRef<BaseCommand *>);
template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionCommand *>);
template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionCommand *>);
template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionCommand *>);
template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionCommand *>);

View file

@ -14,8 +14,9 @@
namespace lld {
namespace elf {
struct BaseCommand;
template <class ELFT> void writeMapFile(llvm::ArrayRef<BaseCommand *> Script);
struct OutputSectionCommand;
template <class ELFT>
void writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script);
}
}

View file

@ -117,7 +117,7 @@ template <class ELFT> static void finalizeShtGroup(OutputSection *Sec) {
// the symbol table.
Sec->Link = InX::SymTab->OutSec->SectionIndex;
// sh_link then contain index of an entry in symbol table section which
// sh_info then contain index of an entry in symbol table section which
// provides signature of the section group.
elf::ObjectFile<ELFT> *Obj = Sec->Sections[0]->getFile<ELFT>();
assert(Config->Relocatable && Sec->Sections.size() == 1);

View file

@ -859,7 +859,11 @@ Expr ScriptParser::readPrimary() {
expect(",");
Expr E2 = readExpr();
expect(")");
return [=] { return alignTo(E().getValue(), E2().getValue()); };
return [=] {
ExprValue V = E();
V.Alignment = E2().getValue();
return V;
};
}
if (Tok == "ALIGNOF") {
StringRef Name = readParenLiteral();

View file

@ -74,6 +74,7 @@ private:
std::unique_ptr<FileOutputBuffer> Buffer;
std::vector<OutputSection *> OutputSections;
std::vector<OutputSectionCommand *> OutputSectionCommands;
OutputSectionFactory Factory{OutputSections};
void addRelIpltSymbols();
@ -262,6 +263,10 @@ template <class ELFT> void Writer<ELFT>::run() {
Script->fabricateDefaultCommands();
}
for (BaseCommand *Base : Script->Opt.Commands)
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
OutputSectionCommands.push_back(Cmd);
// If -compressed-debug-sections is specified, we need to compress
// .debug_* sections. Do it right now because it changes the size of
// output sections.
@ -311,7 +316,7 @@ template <class ELFT> void Writer<ELFT>::run() {
// Handle -Map option.
writeMapFile<ELFT>(Script->Opt.Commands);
writeMapFile<ELFT>(OutputSectionCommands);
if (ErrorCount)
return;
@ -1201,8 +1206,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (ErrorCount)
return;
// So far we have added sections from input object files.
// This function adds linker-created Out::* sections.
addPredefinedSections();
removeUnusedSyntheticSections(OutputSections);
@ -1270,8 +1273,20 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
// ARM ABI requires .ARM.exidx to be terminated by some piece of data.
// We have the terminater synthetic section class. Add that at the end.
auto *OS = dyn_cast_or_null<OutputSection>(findSection(".ARM.exidx"));
if (OS && !OS->Sections.empty() && !Config->Relocatable)
OS->addSection(make<ARMExidxSentinelSection>());
if (!OS || OS->Sections.empty() || Config->Relocatable)
return;
auto *Sentinel = make<ARMExidxSentinelSection>();
OS->addSection(Sentinel);
// If there are linker script commands existing at this point then add the
// sentinel to the last of these too.
if (OutputSectionCommand *C = Script->getCmd(OS)) {
auto ISD = std::find_if(C->Commands.rbegin(), C->Commands.rend(),
[](const BaseCommand *Base) {
return isa<InputSectionDescription>(Base);
});
cast<InputSectionDescription>(*ISD)->Sections.push_back(Sentinel);
}
}
// The linker is expected to define SECNAME_start and SECNAME_end
@ -1315,10 +1330,9 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) {
template <class ELFT>
OutputSectionCommand *Writer<ELFT>::findSectionCommand(StringRef Name) {
for (BaseCommand *Base : Script->Opt.Commands)
if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
if (Cmd->Name == Name)
return Cmd;
for (OutputSectionCommand *Cmd : OutputSectionCommands)
if (Cmd->Name == Name)
return Cmd;
return nullptr;
}
@ -1713,7 +1727,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
EHdr->e_ehsize = sizeof(Elf_Ehdr);
EHdr->e_phnum = Phdrs.size();
EHdr->e_shentsize = sizeof(Elf_Shdr);
EHdr->e_shnum = OutputSections.size() + 1;
EHdr->e_shnum = OutputSectionCommands.size() + 1;
EHdr->e_shstrndx = InX::ShStrTab->OutSec->SectionIndex;
if (Config->EMachine == EM_ARM)
@ -1745,8 +1759,8 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
// Write the section header table. Note that the first table entry is null.
auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
for (OutputSection *Sec : OutputSections)
Sec->writeHeaderTo<ELFT>(++SHdrs);
for (OutputSectionCommand *Cmd : OutputSectionCommands)
Cmd->Sec->writeHeaderTo<ELFT>(++SHdrs);
}
// Open a result file.
@ -1769,10 +1783,7 @@ template <class ELFT> void Writer<ELFT>::openFile() {
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
uint8_t *Buf = Buffer->getBufferStart();
for (BaseCommand *Base : Script->Opt.Commands) {
auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
if (!Cmd)
continue;
for (OutputSectionCommand *Cmd : OutputSectionCommands) {
OutputSection *Sec = Cmd->Sec;
if (Sec->Flags & SHF_ALLOC)
Cmd->writeTo<ELFT>(Buf + Sec->Offset);
@ -1799,19 +1810,13 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
// In -r or -emit-relocs mode, write the relocation sections first as in
// ELf_Rel targets we might find out that we need to modify the relocated
// section while doing it.
for (BaseCommand *Base : Script->Opt.Commands) {
auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
if (!Cmd)
continue;
for (OutputSectionCommand *Cmd : OutputSectionCommands) {
OutputSection *Sec = Cmd->Sec;
if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)
Cmd->writeTo<ELFT>(Buf + Sec->Offset);
}
for (BaseCommand *Base : Script->Opt.Commands) {
auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
if (!Cmd)
continue;
for (OutputSectionCommand *Cmd : OutputSectionCommands) {
OutputSection *Sec = Cmd->Sec;
if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL &&
Sec->Type != SHT_RELA)

View file

@ -64,7 +64,7 @@
# SYMBOLS-NEXT: 0000000000010000 *ABS* 00000000 __code_base__
# SYMBOLS-NEXT: 0000000000001000 *ABS* 00000000 VAR
# SYMBOLS-NEXT: 0000000000011000 .bbb 00000000 __start_bbb
# SYMBOLS-NEXT: 0000000000012000 *ABS* 00000000 __end_bbb
# SYMBOLS-NEXT: 0000000000012000 .bbb 00000000 __end_bbb
.global _start
_start:

View file

@ -0,0 +1,7 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
# RUN: echo "SECTIONS { .bss : { . += 0x10000; *(.bss) } =0xFF };" > %t.script
# RUN: ld.lld -o %t --script %t.script %t.o
.section .bss,"",@nobits
.short 0

View file

@ -31,6 +31,16 @@
# 0x19E = begin + sizeof(.foo) = 0x190 + 0xE
# CHECK-NEXT: Value: 0x19E
# Check that we don't crash with --gc-sections
# RUN: ld.lld --gc-sections -o %t2 --script %t.script %t -shared
# RUN: llvm-readobj -s -t %t2 | FileCheck %s --check-prefix=GC
# GC: Name: .foo
# GC-NEXT: Type: SHT_PROGBITS
# GC-NEXT: Flags [
# GC-NEXT: SHF_ALLOC
# GC-NEXT: ]
.section .foo.1a,"aMS",@progbits,1
.asciz "foo"

View file

@ -11,6 +11,12 @@
# SHARED: 0000000000000005 .dynsym 00000000 .hidden newsym
# RUN: echo "PROVIDE_HIDDEN(newsym = ALIGN(__ehdr_start, CONSTANT(MAXPAGESIZE)) + 5);" > %t.script
# RUN: ld.lld -o %t1 %t.script %t
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=ALIGNED %s
# ALIGNED: 0000000000200005 .text 00000000 .hidden newsym
.global _start
_start:
lea newsym(%rip),%rax