Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -866,6 +866,10 @@ case OPT_no_whole_archive: InWholeArchive = false; break; + case OPT_just_symbols: + if (Optional MB = readFile(Arg->getValue())) + Files.push_back(createJustSymbolsFile(*MB)); + break; case OPT_start_lib: InLib = true; break; Index: lld/ELF/InputFiles.h =================================================================== --- lld/ELF/InputFiles.h +++ lld/ELF/InputFiles.h @@ -68,13 +68,14 @@ ArchiveKind, BitcodeKind, BinaryKind, + JustSymbolsKind, }; Kind kind() const { return FileKind; } bool isElf() const { Kind K = kind(); - return K == ObjKind || K == SharedKind; + return K == ObjKind || K == SharedKind || K == JustSymbolsKind; } StringRef getName() const { return MB.getBufferIdentifier(); } @@ -333,9 +334,22 @@ void parse(); }; +template class JustSymbolsFile : public ELFFileBase { +public: + explicit JustSymbolsFile(MemoryBufferRef M) + : ELFFileBase(InputFile::JustSymbolsKind, M) {} + + static bool classof(const InputFile *F) { + return F->kind() == InputFile::JustSymbolsKind; + } + + void parse(); +}; + InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "", uint64_t OffsetInArchive = 0); InputFile *createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName); +InputFile *createJustSymbolsFile(MemoryBufferRef MB); extern std::vector BinaryFiles; extern std::vector BitcodeFiles; Index: lld/ELF/InputFiles.cpp =================================================================== --- lld/ELF/InputFiles.cpp +++ lld/ELF/InputFiles.cpp @@ -1159,6 +1159,61 @@ } } +// This is for --just-symbols. +// +// This option allows you to link your output against other existing +// program, so that if you load both your program and the other program +// into memory, your output can use program's symbols. +// +// What we are doing here is to read defined symbols from a given ELF +// file and add them as absolute symbols. +template void JustSymbolsFile::parse() { + typedef typename ELFT::Shdr Elf_Shdr; + typedef typename ELFT::Sym Elf_Sym; + typedef typename ELFT::SymRange Elf_Sym_Range; + + StringRef ObjName = this->MB.getBufferIdentifier(); + ELFFile Obj = check(ELFFile::create(this->MB.getBuffer())); + ArrayRef Sections = CHECK(Obj.sections(), ObjName); + + if (Obj.getHeader()->e_type == ET_DYN) + error(ObjName + + ": --just-symbols does not make sense with a shared object"); + + for (const Elf_Shdr &Sec : Sections) { + if (Sec.sh_type != SHT_SYMTAB) + continue; + + Elf_Sym_Range Syms = CHECK(Obj.symbols(&Sec), ObjName); + uint32_t FirstNonLocal = Sec.sh_info; + StringRef StringTable = + CHECK(Obj.getStringTableForSymtab(Sec, Sections), ObjName); + + std::vector> Ret; + for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal)) + if (Sym.st_shndx != SHN_UNDEF) + Symtab->addRegular(CHECK(Sym.getName(StringTable), ObjName), + Sym.st_other, Sym.getType(), Sym.st_value, + Sym.st_size, Sym.getBinding(), nullptr, nullptr); + return; + } +} + +InputFile *elf::createJustSymbolsFile(MemoryBufferRef MB) { + switch (getELFKind(MB)) { + case ELF32LEKind: + return make>(MB); + case ELF32BEKind: + return make>(MB); + case ELF64LEKind: + return make>(MB); + case ELF64BEKind: + return make>(MB); + default: + llvm_unreachable("getELFKind"); + } +} + template void ArchiveFile::parse(); template void ArchiveFile::parse(); template void ArchiveFile::parse(); @@ -1188,3 +1243,8 @@ template class elf::SharedFile; template class elf::SharedFile; template class elf::SharedFile; + +template class elf::JustSymbolsFile; +template class elf::JustSymbolsFile; +template class elf::JustSymbolsFile; +template class elf::JustSymbolsFile; Index: lld/ELF/Options.td =================================================================== --- lld/ELF/Options.td +++ lld/ELF/Options.td @@ -156,6 +156,8 @@ defm init: Eq<"init">, HelpText<"Specify an initializer function">, MetaVarName<"">; +defm just_symbols: Eq<"just-symbols">, HelpText<"Just link symbols">; + defm library: Eq<"library">, HelpText<"Root name of library to use">, MetaVarName<"">; Index: lld/ELF/SymbolTable.cpp =================================================================== --- lld/ELF/SymbolTable.cpp +++ lld/ELF/SymbolTable.cpp @@ -107,6 +107,12 @@ return; } + // --just-symbols argument + if (auto *F = dyn_cast>(File)) { + F->parse(); + return; + } + // Regular object file ObjectFiles.push_back(File); cast>(File)->parse(ComdatGroups); Index: lld/test/ELF/Inputs/just-symbols.s =================================================================== --- /dev/null +++ lld/test/ELF/Inputs/just-symbols.s @@ -0,0 +1,9 @@ +.globl foo, bar +foo: + ret + +.section .data +.type bar, @object +.size bar, 40 +bar: + .zero 40 Index: lld/test/ELF/just-symbols.s =================================================================== --- /dev/null +++ lld/test/ELF/just-symbols.s @@ -0,0 +1,26 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/just-symbols.s -o %t1.o +# RUN: ld.lld %t1.o -o %t1.exe -Ttext=0x10000 + +# RUN: ld.lld -just-symbols=%t1.exe -o %t2.exe +# RUN: llvm-readelf -symbols %t2.exe | FileCheck %s + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3.o +# RUN: ld.lld %t3.o -just-symbols=%t1.exe -o %t3.exe +# RUN: llvm-readelf -symbols %t3.exe | FileCheck %s + +# CHECK: 0000000000011000 40 OBJECT GLOBAL DEFAULT ABS bar +# CHECK: 0000000000010000 0 NOTYPE GLOBAL DEFAULT ABS foo + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/just-symbols.s -o %t4.o +# RUN: ld.lld -shared -o %t4.so %t4.o +# RUN: not ld.lld -just-symbols=%t4.so 2>&1 | FileCheck -check-prefix=ERR %s + +# ERR: --just-symbols does not make sense with a shared object + +.globl _start +_start: + call foo + call bar + ret