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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
//===- lib/ReaderWriter/ReaderArchive.cpp - Archive Library Reader--------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
#include "lld/ReaderWriter/ReaderArchive.h"
namespace lld {
/// \brief The FileArchive class represents an Archive Library file
class FileArchive : public ArchiveLibraryFile {
public:
virtual ~FileArchive() { }
/// \brief Check if any member of the archive contains an Atom with the
/// specified name and return the File object for that member, or nullptr.
virtual const File *find(StringRef name, bool dataSymbolOnly) const {
error_code ec;
llvm::object::Archive::child_iterator ci;
ci = _archive.get()->findSym(name);
if (ci == _archive->end_children())
return nullptr;
if (dataSymbolOnly && (ec = isDataSymbol(ci->getBuffer(), name)))
return nullptr;
std::vector<std::unique_ptr<File>> result;
if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
(ci->getBuffer()), result)))
return nullptr;
assert(result.size() == 1);
// give up the pointer so that this object no longer manages it
return result[0].release();
}
virtual void addAtom(const Atom&) {
llvm_unreachable("cannot add atoms to archive files");
}
virtual const atom_collection<DefinedAtom> &defined() const {
return _definedAtoms;
}
virtual const atom_collection<UndefinedAtom> &undefined() const {
return _undefinedAtoms;
}
virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
return _sharedLibraryAtoms;
}
virtual const atom_collection<AbsoluteAtom> &absolute() const {
return _absoluteAtoms;
}
protected:
error_code isDataSymbol(MemoryBuffer *mb, StringRef symbol) const {
std::unique_ptr<llvm::object::ObjectFile>
obj(llvm::object::ObjectFile::createObjectFile(mb));
error_code ec;
llvm::object::SymbolRef::Type symtype;
uint32_t symflags;
llvm::object::symbol_iterator ibegin = obj->begin_symbols();
llvm::object::symbol_iterator iend = obj->end_symbols();
StringRef symbolname;
for (llvm::object::symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
if (ec) return ec;
// Get symbol name
if ((ec = (i->getName(symbolname)))) return ec;
if (symbolname != symbol)
continue;
// Get symbol flags
if ((ec = (i->getFlags(symflags)))) return ec;
if (symflags <= llvm::object::SymbolRef::SF_Undefined)
continue;
// Get Symbol Type
if ((ec = (i->getType(symtype)))) return ec;
if (symtype == llvm::object::SymbolRef::ST_Data) {
return error_code::success();
}
}
return llvm::object::object_error::parse_failed;
}
private:
std::unique_ptr<llvm::object::Archive> _archive;
const ReaderOptionsArchive _options;
atom_collection_vector<DefinedAtom> _definedAtoms;
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
public:
/// only subclasses of ArchiveLibraryFile can be instantiated
explicit FileArchive(llvm::MemoryBuffer *mb,
const ReaderOptionsArchive &options,
error_code &ec)
:ArchiveLibraryFile(mb->getBufferIdentifier()),
_options(options) {
std::unique_ptr<llvm::object::Archive> archive_obj(
new llvm::object::Archive(mb, ec));
if (ec)
return;
_archive.swap(archive_obj);
}
}; // class FileArchive
// Returns a vector of Files that are contained in the archive file
// pointed to by the MemoryBuffer
error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
std::vector<std::unique_ptr<File>> &result) {
error_code ec;
if (_options.isForceLoad()) {
_archive.reset(new llvm::object::Archive(mb.release(), ec));
if (ec)
return ec;
for (auto mf = _archive->begin_children(),
me = _archive->end_children(); mf != me; ++mf) {
if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
(mf->getBuffer()), result)))
return ec;
}
} else {
std::unique_ptr<File> f;
f.reset(new FileArchive(mb.release(), _options, ec));
if (ec)
return ec;
result.push_back(std::move(f));
}
return llvm::error_code::success();
}
} // namespace lld
|