blob: 437db2aea8aed6bd38b133d05a1de0a300d18b6f [file] [log] [blame]
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +00001//===- lib/ReaderWriter/ReaderArchive.cpp - Archive Library Reader--------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===---------------------------------------------------------------------===//
9#include "lld/ReaderWriter/ReaderArchive.h"
10
11namespace lld
12{
13// The FileArchive class represents an Archive Library file
14class FileArchive : public ArchiveLibraryFile {
15public:
16
17 virtual ~FileArchive() { }
18
19 /// Check if any member of the archive contains an Atom with the
20 /// specified name and return the File object for that member, or nullptr.
21 virtual const File *find(StringRef name, bool dataSymbolOnly) const {
22 error_code ec;
23 llvm::object::Archive::child_iterator ci;
24
25 ci = _archive.get()->findSym(name);
26 if (ci == _archive->end_children())
27 return nullptr;
28
29 if (dataSymbolOnly && (ec = isDataSymbol(ci->getBuffer(), name)))
30 return nullptr;
31
32 std::vector<std::unique_ptr<File>> result;
33
34 if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
35 (ci->getBuffer()), result)))
36 return nullptr;
37
38 assert(result.size() == 1);
39
40 // give up the pointer so that this object no longer manages it
41 for (std::unique_ptr<File> &f : result) {
42 return f.release();
43 }
44
45 return nullptr;
46 }
47
48 virtual void addAtom(const Atom&) {
49 llvm_unreachable("cannot add atoms to archive files");
50 }
51
52 virtual const atom_collection<DefinedAtom> &defined() const {
53 return _definedAtoms;
54 }
55
56 virtual const atom_collection<UndefinedAtom> &undefined() const {
57 return _undefinedAtoms;
58 }
59
60 virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
61 return _sharedLibraryAtoms;
62 }
63
64 virtual const atom_collection<AbsoluteAtom> &absolute() const {
65 return _absoluteAtoms;
66 }
67
68protected:
69 error_code isDataSymbol(MemoryBuffer *mb, StringRef symbol) const
70 {
71 llvm::object::ObjectFile *obj =
72 llvm::object::ObjectFile::createObjectFile(mb);
73 error_code ec;
74 llvm::object::SymbolRef::Type symtype;
75 uint32_t symflags;
76 llvm::object::symbol_iterator ibegin = obj->begin_symbols();
77 llvm::object::symbol_iterator iend = obj->end_symbols();
78 StringRef symbolname;
79
80 for (llvm::object::symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
81 if (ec) return ec;
82
83 // Get symbol name
84 if ((ec = (i->getName(symbolname)))) return ec;
85
86 if (symbolname != symbol)
87 continue;
88
89 // Get symbol flags
90 if ((ec = (i->getFlags(symflags)))) return ec;
91
92 if (symflags <= llvm::object::SymbolRef::SF_Undefined)
93 continue;
94
95 // Get Symbol Type
96 if ((ec = (i->getType(symtype)))) return ec;
97
98 if (symtype == llvm::object::SymbolRef::ST_Data) {
99 return error_code::success();
100 }
101 }
102 return llvm::object::object_error::parse_failed;
103 }
104
105private:
106 llvm::MemoryBuffer *_mb;
107 std::unique_ptr<llvm::object::Archive> _archive;
108 const ReaderOptionsArchive _options;
109 atom_collection_vector<DefinedAtom> _definedAtoms;
110 atom_collection_vector<UndefinedAtom> _undefinedAtoms;
111 atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
112 atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
113
114public:
115 /// only subclasses of ArchiveLibraryFile can be instantiated
116 explicit FileArchive(llvm::MemoryBuffer *mb,
117 const ReaderOptionsArchive &options,
118 error_code &ec)
119 :ArchiveLibraryFile(mb->getBufferIdentifier()),
120 _mb(mb),
121 _archive(nullptr),
122 _options(options) {
123 auto *archive_obj = new llvm::object::Archive(mb, ec);
124 if (ec)
125 return;
126 _archive.reset(archive_obj);
127 }
128}; // class FileArchive
129
130// Returns a vector of Files that are contained in the archive file
131// pointed to by the MemoryBuffer
132error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
133 std::vector<std::unique_ptr<File>> &result) {
134 error_code ec;
135
136 if (_options.isForceLoad())
137 {
138 _archive.reset(new llvm::object::Archive(mb.release(), ec));
139 if (ec)
140 return ec;
141
142 for (auto mf = _archive->begin_children(),
143 me = _archive->end_children(); mf != me; ++mf)
144 {
145 if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
146 (mf->getBuffer()), result)))
147 return ec;
148 }
149 } else {
150 std::unique_ptr<File> f;
151 f.reset(new FileArchive(mb.release(), _options, ec));
152 if (ec)
153 return ec;
154
155 result.push_back(std::move(f));
156 }
157 return llvm::error_code::success();
158}
159
160} // namespace lld