summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp3
-rw-r--r--lld/ELF/Options.td3
-rw-r--r--lld/ELF/SymbolTable.cpp3
-rw-r--r--lld/ELF/SymbolTable.h2
-rw-r--r--lld/ELF/Writer.cpp24
-rwxr-xr-xlld/test/elf2/Inputs/i686-simple-library.sobin1204 -> 0 bytes
-rw-r--r--lld/test/elf2/Inputs/shared.s6
-rw-r--r--lld/test/elf2/incompatible.s14
-rw-r--r--lld/test/elf2/shared.s6
10 files changed, 42 insertions, 20 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index f8449806eff..b4faef70013 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -19,6 +19,7 @@ struct Configuration {
llvm::StringRef OutputFile;
llvm::StringRef DynamicLinker;
std::string RPath;
+ bool Shared = false;
};
extern Configuration *Config;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index a2d7022603a..d1b63260d30 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -79,6 +79,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
if (!RPaths.empty())
Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
+ if (Args.hasArg(OPT_shared))
+ Config->Shared = true;
+
// Create a list of input files.
std::vector<MemoryBufferRef> Inputs;
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 9ab03024240..b3c244be633 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -12,3 +12,6 @@ def dynamic_linker : Separate<["-"], "dynamic-linker">,
def rpath : Separate<["-"], "rpath">,
HelpText<"Add a DT_RUNPATH to the output">;
+
+def shared : Flag<["-"], "shared">,
+ HelpText<"Build a shared object">;
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 1d55c3331e2..708ea545d20 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "SymbolTable.h"
+#include "Config.h"
#include "Error.h"
#include "Symbols.h"
@@ -32,6 +33,8 @@ void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
}
template <class ELFT> void SymbolTable::init() {
+ if (Config->Shared)
+ return;
EntrySym = new (Alloc) Undefined<ELFT>("_start", Undefined<ELFT>::Synthetic);
resolve<ELFT>(EntrySym);
}
diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h
index 42c49c6fbbc..9c156b54f59 100644
--- a/lld/ELF/SymbolTable.h
+++ b/lld/ELF/SymbolTable.h
@@ -55,6 +55,8 @@ public:
}
SymbolBody *getEntrySym() const {
+ if (!EntrySym)
+ return nullptr;
return EntrySym->getReplacement();
}
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index ef7199c919c..6d1c94ea8f4 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -311,6 +311,10 @@ private:
return !SymTabSec.getSymTable().getSharedFiles().empty() &&
!Config->DynamicLinker.empty();
}
+ bool needsDynamicSections() const {
+ return !SymTabSec.getSymTable().getSharedFiles().empty() || Config->Shared;
+ }
+ unsigned getVAStart() const { return Config->Shared ? 0 : VAStart; }
std::unique_ptr<llvm::FileOutputBuffer> Buffer;
llvm::SpecificBumpPtrAllocator<OutputSection<ELFT>> CAlloc;
@@ -604,8 +608,6 @@ template <class ELFT> void Writer<ELFT>::createSections() {
}
}
- const std::vector<std::unique_ptr<SharedFileBase>> &SharedFiles =
- Symtab.getSharedFiles();
BSSSec = getSection(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
// FIXME: Try to avoid the extra walk over all global symbols.
std::vector<DefinedCommon<ELFT> *> CommonSymbols;
@@ -624,7 +626,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
// FIXME: This adds way too much to the dynamic symbol table. We only
// need to add the symbols use by dynamic relocations when producing
// an executable (ignoring --export-dynamic).
- if (!SharedFiles.empty())
+ if (needsDynamicSections())
DynSymSec.addSymbol(Name);
}
@@ -644,7 +646,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
OutputSections.push_back(&SymTabSec);
OutputSections.push_back(&StrTabSec);
- if (!SharedFiles.empty()) {
+ if (needsDynamicSections()) {
if (needsInterpSection())
OutputSections.push_back(&InterpSec);
OutputSections.push_back(&DynSymSec);
@@ -666,7 +668,7 @@ static bool outputSectionHasPHDR(OutputSectionBase<ELFT::Is64Bits> *Sec) {
// Visits all sections to assign incremental, non-overlapping RVAs and
// file offsets.
template <class ELFT> void Writer<ELFT>::assignAddresses() {
- uintX_t VA = VAStart;
+ uintX_t VA = getVAStart();
uintX_t FileOff = 0;
FileOff += sizeof(Elf_Ehdr);
@@ -711,7 +713,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
}
// Add a PHDR for the dynamic table.
- if (!SymTabSec.getSymTable().getSharedFiles().empty())
+ if (needsDynamicSections())
++NumPhdrs;
FileOff += OffsetToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
@@ -762,13 +764,13 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
// FIXME: Generalize the segment construction similar to how we create
// output sections.
const SymbolTable &Symtab = SymTabSec.getSymTable();
- bool HasDynamicSegment = !Symtab.getSharedFiles().empty();
- EHdr->e_type = ET_EXEC;
+ EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC;
auto &FirstObj = cast<ObjectFile<ELFT>>(*Symtab.getFirstELF());
EHdr->e_machine = FirstObj.getEMachine();
EHdr->e_version = EV_CURRENT;
- EHdr->e_entry = getSymVA(cast<DefinedRegular<ELFT>>(Symtab.getEntrySym()));
+ SymbolBody *Entry = Symtab.getEntrySym();
+ EHdr->e_entry = Entry ? getSymVA(cast<DefinedRegular<ELFT>>(Entry)) : 0;
EHdr->e_phoff = ProgramHeaderOff;
EHdr->e_shoff = SectionHeaderOff;
EHdr->e_ehsize = sizeof(Elf_Ehdr);
@@ -788,7 +790,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
PHdrs->p_type = PT_LOAD;
PHdrs->p_flags = PF_R;
PHdrs->p_offset = 0;
- PHdrs->p_vaddr = VAStart;
+ PHdrs->p_vaddr = getVAStart();
PHdrs->p_paddr = PHdrs->p_vaddr;
PHdrs->p_filesz = ProgramHeaderOff + NumPhdrs * sizeof(Elf_Phdr);
PHdrs->p_memsz = PHdrs->p_filesz;
@@ -809,7 +811,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
++PHdrs;
}
- if (HasDynamicSegment) {
+ if (needsDynamicSections()) {
PHdrs->p_type = PT_DYNAMIC;
setValuesFromSection<ELFT>(*PHdrs, DynamicSec);
}
diff --git a/lld/test/elf2/Inputs/i686-simple-library.so b/lld/test/elf2/Inputs/i686-simple-library.so
deleted file mode 100755
index 62da498a238..00000000000
--- a/lld/test/elf2/Inputs/i686-simple-library.so
+++ /dev/null
Binary files differ
diff --git a/lld/test/elf2/Inputs/shared.s b/lld/test/elf2/Inputs/shared.s
new file mode 100644
index 00000000000..1cfebbfaf37
--- /dev/null
+++ b/lld/test/elf2/Inputs/shared.s
@@ -0,0 +1,6 @@
+.global bar
+.type bar, @function
+bar:
+
+.global zed
+zed:
diff --git a/lld/test/elf2/incompatible.s b/lld/test/elf2/incompatible.s
index 61e89cf514a..46a8df1433a 100644
--- a/lld/test/elf2/incompatible.s
+++ b/lld/test/elf2/incompatible.s
@@ -1,5 +1,6 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %ta.o
// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %tb.o
+// RUN: lld -flavor gnu2 -shared %tb.o -o %ti686.so
// RUN: llvm-mc -filetype=obj -triple=arm-unknown-linux %s -o %tc.o
// RUN: not lld -flavor gnu2 %ta.o %tb.o -o %t 2>&1 | \
@@ -10,17 +11,16 @@
// RUN: FileCheck --check-prefix=B-AND-C %s
// B-AND-C: b.o is incompatible with {{.*}}c.o
-// FIMME: create the .so ourselves once we are able to
-// RUN: not lld -flavor gnu2 %ta.o %p/Inputs/i686-simple-library.so -o %t 2>&1 | \
+// RUN: not lld -flavor gnu2 %ta.o %ti686.so -o %t 2>&1 | \
// RUN: FileCheck --check-prefix=A-AND-SO %s
-// A-AND-SO: a.o is incompatible with {{.*}}/Inputs/i686-simple-library.so
+// A-AND-SO: a.o is incompatible with {{.*}}i686.so
-// RUN: not lld -flavor gnu2 %tc.o %p/Inputs/i686-simple-library.so -o %t 2>&1 | \
+// RUN: not lld -flavor gnu2 %tc.o %ti686.so -o %t 2>&1 | \
// RUN: FileCheck --check-prefix=C-AND-SO %s
-// C-AND-SO: c.o is incompatible with {{.*}}/Inputs/i686-simple-library.so
+// C-AND-SO: c.o is incompatible with {{.*}}i686.so
-// RUN: not lld -flavor gnu2 %p/Inputs/i686-simple-library.so %tc.o -o %t 2>&1 | \
+// RUN: not lld -flavor gnu2 %ti686.so %tc.o -o %t 2>&1 | \
// RUN: FileCheck --check-prefix=SO-AND-C %s
-// SO-AND-C: /Inputs/i686-simple-library.so is incompatible with {{.*}}c.o
+// SO-AND-C: i686.so is incompatible with {{.*}}c.o
// REQUIRES: x86,arm
diff --git a/lld/test/elf2/shared.s b/lld/test/elf2/shared.s
index c39941d2ca6..e0ad621fbef 100644
--- a/lld/test/elf2/shared.s
+++ b/lld/test/elf2/shared.s
@@ -1,5 +1,7 @@
// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
-// RUN: lld -flavor gnu2 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar %t.o %p/Inputs/i686-simple-library.so -o %t
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
+// RUN: lld -flavor gnu2 -shared %t2.o -o %t2.so
+// RUN: lld -flavor gnu2 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar %t.o %t2.so -o %t
// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck %s
// REQUIRES: x86
@@ -144,7 +146,7 @@
// CHECK-NEXT: 0x00000005 STRTAB [[DYNSTRADDR]]
// CHECK-NEXT: 0x0000000A STRSZ
// CHECK-NEXT: 0x0000001D RUNPATH foo:bar
-// CHECK-NEXT: 0x00000001 NEEDED SharedLibrary ({{.*}}/Inputs/i686-simple-library.so)
+// CHECK-NEXT: 0x00000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x00000000 NULL 0x0
// CHECK-NEXT: ]
OpenPOWER on IntegriCloud