diff options
-rw-r--r-- | lld/ELF/Driver.cpp | 6 | ||||
-rw-r--r-- | lld/ELF/InputFiles.cpp | 41 | ||||
-rw-r--r-- | lld/ELF/InputFiles.h | 3 | ||||
-rw-r--r-- | lld/ELF/Options.td | 2 | ||||
-rw-r--r-- | lld/test/ELF/Inputs/just-symbols.s | 9 | ||||
-rw-r--r-- | lld/test/ELF/just-symbols.s | 17 |
6 files changed, 78 insertions, 0 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 8abac814fee..ebfab486c01 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1072,6 +1072,12 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { for (StringRef S : Config->Undefined) Symtab->fetchIfLazy<ELFT>(S); + // Handle the --just-symbols option. This may add absolute symbols + // to the symbol table. + for (auto *Arg : Args.filtered(OPT_just_symbols)) + if (Optional<MemoryBufferRef> MB = readFile(Arg->getValue())) + readJustSymbolsFile<ELFT>(*MB); + // If an entry symbol is in a static archive, pull out that file now // to complete the symbol table. After this, no new names except a // few linker-synthesized ones will be added to the symbol table. diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 0bff0350e6b..04034aee4fa 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1175,6 +1175,42 @@ std::vector<StringRef> LazyObjFile::getSymbolNames() { } } +// 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 <class ELFT> void elf::readJustSymbolsFile(MemoryBufferRef MB) { + typedef typename ELFT::Shdr Elf_Shdr; + typedef typename ELFT::Sym Elf_Sym; + typedef typename ELFT::SymRange Elf_Sym_Range; + + StringRef ObjName = MB.getBufferIdentifier(); + ELFFile<ELFT> Obj = check(ELFFile<ELFT>::create(MB.getBuffer())); + ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), ObjName); + + 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<std::pair<StringRef, uint64_t>> 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; + } +} + template void ArchiveFile::parse<ELF32LE>(); template void ArchiveFile::parse<ELF32BE>(); template void ArchiveFile::parse<ELF64LE>(); @@ -1204,3 +1240,8 @@ template class elf::SharedFile<ELF32LE>; template class elf::SharedFile<ELF32BE>; template class elf::SharedFile<ELF64LE>; template class elf::SharedFile<ELF64BE>; + +template void elf::readJustSymbolsFile<ELF32LE>(MemoryBufferRef); +template void elf::readJustSymbolsFile<ELF32BE>(MemoryBufferRef); +template void elf::readJustSymbolsFile<ELF64LE>(MemoryBufferRef); +template void elf::readJustSymbolsFile<ELF64BE>(MemoryBufferRef); diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 5b9e9d79eba..862fde62584 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -332,6 +332,9 @@ InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "", uint64_t OffsetInArchive = 0); InputFile *createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName); +// For --just-symbols +template <class ELFT> void readJustSymbolsFile(MemoryBufferRef MB); + extern std::vector<BinaryFile *> BinaryFiles; extern std::vector<BitcodeFile *> BitcodeFiles; extern std::vector<InputFile *> ObjectFiles; diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index b1c7a1d4046..40b996e07d1 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -180,6 +180,8 @@ defm image_base : Eq<"image-base">, HelpText<"Set the base address">; defm init: Eq<"init">, HelpText<"Specify an initializer function">, MetaVarName<"<symbol>">; +defm just_symbols: Eq<"just-symbols">, HelpText<"Just link symbols">; + defm library: Eq<"library">, HelpText<"Root name of library to use">, MetaVarName<"<libName>">; diff --git a/lld/test/ELF/Inputs/just-symbols.s b/lld/test/ELF/Inputs/just-symbols.s new file mode 100644 index 00000000000..922bbdf9d68 --- /dev/null +++ b/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 diff --git a/lld/test/ELF/just-symbols.s b/lld/test/ELF/just-symbols.s new file mode 100644 index 00000000000..d71345d382d --- /dev/null +++ b/lld/test/ELF/just-symbols.s @@ -0,0 +1,17 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/just-symbols.s -o %t1 +# RUN: ld.lld %t1 -o %t1.exe -Ttext=0x10000 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2 +# RUN: ld.lld %t2 -just-symbols=%t1.exe -o %t2.exe +# RUN: llvm-readelf -symbols %t2.exe | FileCheck %s + +# CHECK: 0000000000011000 40 OBJECT GLOBAL DEFAULT ABS bar +# CHECK: 0000000000010000 0 NOTYPE GLOBAL DEFAULT ABS foo + +.globl _start +_start: + call foo + call bar + ret |