1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
//===- lib/ReaderWriter/ELF/DynamicFile.cpp -------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DynamicFile.h"
#include "FileCommon.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/Path.h"
namespace lld {
namespace elf {
template <class ELFT>
DynamicFile<ELFT>::DynamicFile(std::unique_ptr<MemoryBuffer> mb,
ELFLinkingContext &ctx)
: SharedLibraryFile(mb->getBufferIdentifier()), _mb(std::move(mb)),
_ctx(ctx), _useShlibUndefines(ctx.useShlibUndefines()) {}
template <typename ELFT>
std::error_code DynamicFile<ELFT>::isCompatible(MemoryBufferRef mb,
ELFLinkingContext &ctx) {
return elf::isCompatible<ELFT>(mb, ctx);
}
template <class ELFT>
const SharedLibraryAtom *DynamicFile<ELFT>::exports(StringRef name,
bool dataSymbolOnly) const {
assert(!dataSymbolOnly && "Invalid option for ELF exports!");
// See if we have the symbol.
auto sym = _nameToSym.find(name);
if (sym == _nameToSym.end())
return nullptr;
// Have we already created a SharedLibraryAtom for it?
if (sym->second._atom)
return sym->second._atom;
// Create a SharedLibraryAtom for this symbol.
return sym->second._atom = new (_alloc)
ELFDynamicAtom<ELFT>(*this, name, _soname, sym->second._symbol);
}
template <class ELFT> StringRef DynamicFile<ELFT>::getDSOName() const {
return _soname;
}
template <class ELFT> bool DynamicFile<ELFT>::canParse(file_magic magic) {
return magic == file_magic::elf_shared_object;
}
template <class ELFT> std::error_code DynamicFile<ELFT>::doParse() {
std::error_code ec;
_objFile.reset(new llvm::object::ELFFile<ELFT>(_mb->getBuffer(), ec));
if (ec)
return ec;
llvm::object::ELFFile<ELFT> &obj = *_objFile;
_soname = obj.getLoadName();
if (_soname.empty())
_soname = llvm::sys::path::filename(path());
// Create a map from names to dynamic symbol table entries.
// TODO: This should use the object file's build in hash table instead if
// it exists.
for (auto i = obj.dynamic_symbol_begin(), e = obj.dynamic_symbol_end();
i != e; ++i) {
auto name = obj.getSymbolName(i, true);
if ((ec = name.getError()))
return ec;
// Dont add local symbols to dynamic entries. The first symbol in the
// dynamic symbol table is a local symbol.
if (i->getBinding() == llvm::ELF::STB_LOCAL)
continue;
// TODO: Add absolute symbols
if (i->st_shndx == llvm::ELF::SHN_ABS)
continue;
if (i->st_shndx == llvm::ELF::SHN_UNDEF) {
if (!_useShlibUndefines)
continue;
// Create an undefined atom.
if (!name->empty()) {
auto *newAtom = new (_alloc) ELFUndefinedAtom<ELFT>(*this, *name, &*i);
_undefinedAtoms.push_back(newAtom);
}
continue;
}
_nameToSym[*name]._symbol = &*i;
}
return std::error_code();
}
template class DynamicFile<ELF32LE>;
template class DynamicFile<ELF32BE>;
template class DynamicFile<ELF64LE>;
template class DynamicFile<ELF64BE>;
} // end namespace elf
} // end namespace lld
|