Start adding support for creating shared libraries.
They are not fully functional yet, but this implements enough support for lld
itself to read them.
With that, delete the .so binary we were using for tests and start eating our
own dog food.
llvm-svn: 247487
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index f844980..b4faef70 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -19,6 +19,7 @@
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 a2d7022..d1b6326 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -79,6 +79,9 @@
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 9ab0302..b3c244b 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -12,3 +12,6 @@
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 1d55c33..708ea54 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 @@
}
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 42c49c6..9c156b5 100644
--- a/lld/ELF/SymbolTable.h
+++ b/lld/ELF/SymbolTable.h
@@ -55,6 +55,8 @@
}
SymbolBody *getEntrySym() const {
+ if (!EntrySym)
+ return nullptr;
return EntrySym->getReplacement();
}
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index ef7199c..6d1c94e 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -311,6 +311,10 @@
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 @@
}
}
- 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 @@
// 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 @@
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 @@
// 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 @@
}
// 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 @@
// 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 @@
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 @@
++PHdrs;
}
- if (HasDynamicSegment) {
+ if (needsDynamicSections()) {
PHdrs->p_type = PT_DYNAMIC;
setValuesFromSection<ELFT>(*PHdrs, DynamicSec);
}