forked from OSchip/llvm-project
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
This commit is contained in:
parent
535ff80354
commit
4340aad144
|
@ -19,6 +19,7 @@ struct Configuration {
|
|||
llvm::StringRef OutputFile;
|
||||
llvm::StringRef DynamicLinker;
|
||||
std::string RPath;
|
||||
bool Shared = false;
|
||||
};
|
||||
|
||||
extern Configuration *Config;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
}
|
||||
|
||||
SymbolBody *getEntrySym() const {
|
||||
if (!EntrySym)
|
||||
return nullptr;
|
||||
return EntrySym->getReplacement();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
.global bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
|
||||
.global zed
|
||||
zed:
|
|
@ -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
|
||||
|
|
|
@ -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: ]
|
||||
|
||||
|
|
Loading…
Reference in New Issue