Skip to content

Commit

Permalink
Re-implement --just-symbols as a regular object file.
Browse files Browse the repository at this point in the history
I tried a few different designs to find a way to implement it without
too much hassle and settled down with this. Unlike before, object files
given as arguments for --just-symbols are handled as object files, with
an exception that their section tables are handled as if they were all
null.

Differential Revision: https://reviews.llvm.org/D42025

llvm-svn: 328852
  • Loading branch information
rui314 committed Mar 30, 2018
1 parent 208fe67 commit 5a67a6e
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 68 deletions.
12 changes: 6 additions & 6 deletions lld/ELF/Driver.cpp
Expand Up @@ -912,6 +912,12 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
case OPT_no_whole_archive:
InWholeArchive = false;
break;
case OPT_just_symbols:
if (Optional<MemoryBufferRef> MB = readFile(Arg->getValue())) {
Files.push_back(createObjectFile(*MB));
Files.back()->JustSymbols = true;
}
break;
case OPT_start_lib:
InLib = true;
break;
Expand Down Expand Up @@ -1074,12 +1080,6 @@ 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.
Expand Down
70 changes: 28 additions & 42 deletions lld/ELF/InputFiles.cpp
Expand Up @@ -271,8 +271,13 @@ template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getGlobalSymbols() {

template <class ELFT>
void ObjFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) {
// Read section and symbol tables.
initializeSections(ComdatGroups);
// Read a section table. JustSymbols is usually false.
if (this->JustSymbols)
initializeJustSymbols();
else
initializeSections(ComdatGroups);

// Read a symbol table.
initializeSymbols();
}

Expand Down Expand Up @@ -359,6 +364,27 @@ template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
return true;
}

// This is for --just-symbols.
//
// --just-symbols is a very minor feature that 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 refer the
// other program's symbols.
//
// When the option is given, we link "just symbols". The section table is
// initialized with null pointers.
template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
ArrayRef<Elf_Shdr> ObjSections = CHECK(this->getObj().sections(), this);
this->Sections.resize(ObjSections.size());

for (const Elf_Shdr &Sec : ObjSections) {
if (Sec.sh_type != SHT_SYMTAB)
continue;
this->initSymtab(ObjSections, &Sec);
return;
}
}

template <class ELFT>
void ObjFile<ELFT>::initializeSections(
DenseSet<CachedHashStringRef> &ComdatGroups) {
Expand Down Expand Up @@ -1190,41 +1216,6 @@ template <class ELFT> void LazyObjFile::addElfSymbols() {
}
}

// 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 FirstGlobal = Sec.sh_info;
StringRef StringTable =
CHECK(Obj.getStringTableForSymtab(Sec, Sections), ObjName);

for (const Elf_Sym &Sym : Syms.slice(FirstGlobal))
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>();
Expand Down Expand Up @@ -1254,8 +1245,3 @@ 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);
7 changes: 4 additions & 3 deletions lld/ELF/InputFiles.h
Expand Up @@ -110,6 +110,9 @@ class InputFile {
std::string getSrcMsg(const Symbol &Sym, InputSectionBase &Sec,
uint64_t Offset);

// True if this is an argument for --just-symbols. Usually false.
bool JustSymbols = false;

protected:
InputFile(Kind K, MemoryBufferRef M);
std::vector<InputSectionBase *> Sections;
Expand Down Expand Up @@ -201,6 +204,7 @@ template <class ELFT> class ObjFile : public ELFFileBase<ELFT> {
void
initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups);
void initializeSymbols();
void initializeJustSymbols();
void initializeDwarf();
InputSectionBase *getRelocTarget(const Elf_Shdr &Sec);
InputSectionBase *createInputSection(const Elf_Shdr &Sec);
Expand Down Expand Up @@ -340,9 +344,6 @@ 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;
Expand Down
9 changes: 0 additions & 9 deletions lld/test/ELF/Inputs/just-symbols.s

This file was deleted.

20 changes: 20 additions & 0 deletions lld/test/ELF/just-symbols-cref.s
@@ -0,0 +1,20 @@
# REQUIRES: x86

# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
# RUN: ld.lld %t.o -o %t1.exe -Ttext=0x10000

# RUN: ld.lld -just-symbols=%t1.exe -o %t2.exe -cref | FileCheck %s

# CHECK: Symbol File
# CHECK-NEXT: bar {{.*exe}}
# CHECK-NEXT: foo {{.*exe}}

.globl foo, bar
foo:
ret

.section .data
.type bar, @object
.size bar, 40
bar:
.zero 40
19 changes: 11 additions & 8 deletions lld/test/ELF/just-symbols.s
@@ -1,17 +1,20 @@
# 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 %t.o
# RUN: ld.lld %t.o -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: ld.lld -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
.globl foo, bar
foo:
ret

.section .data
.type bar, @object
.size bar, 40
bar:
.zero 40

0 comments on commit 5a67a6e

Please sign in to comment.