blob: be02645579ccf3c370d3154a1d71bb772012c2d2 [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//===---------------------------------------------------------------------===//
Michael J. Spencera5d22812012-11-13 19:58:58 +00009
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000010#include "lld/ReaderWriter/ReaderArchive.h"
11
Michael J. Spencera5d22812012-11-13 19:58:58 +000012namespace lld {
13/// \brief The FileArchive class represents an Archive Library file
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000014class FileArchive : public ArchiveLibraryFile {
15public:
16
17 virtual ~FileArchive() { }
18
Michael J. Spencera5d22812012-11-13 19:58:58 +000019 /// \brief Check if any member of the archive contains an Atom with the
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000020 /// 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
Shankar Easwaran85bb0452012-11-13 20:34:55 +000041 return result[0].release();
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000042 }
43
44 virtual void addAtom(const Atom&) {
45 llvm_unreachable("cannot add atoms to archive files");
46 }
47
48 virtual const atom_collection<DefinedAtom> &defined() const {
49 return _definedAtoms;
50 }
51
52 virtual const atom_collection<UndefinedAtom> &undefined() const {
53 return _undefinedAtoms;
54 }
55
56 virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
57 return _sharedLibraryAtoms;
58 }
59
60 virtual const atom_collection<AbsoluteAtom> &absolute() const {
61 return _absoluteAtoms;
62 }
63
64protected:
Michael J. Spencera5d22812012-11-13 19:58:58 +000065 error_code isDataSymbol(MemoryBuffer *mb, StringRef symbol) const {
Shankar Easwaran85bb0452012-11-13 20:34:55 +000066 std::unique_ptr<llvm::object::ObjectFile>
67 obj(llvm::object::ObjectFile::createObjectFile(mb));
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000068 error_code ec;
69 llvm::object::SymbolRef::Type symtype;
70 uint32_t symflags;
71 llvm::object::symbol_iterator ibegin = obj->begin_symbols();
72 llvm::object::symbol_iterator iend = obj->end_symbols();
73 StringRef symbolname;
74
75 for (llvm::object::symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
76 if (ec) return ec;
77
78 // Get symbol name
79 if ((ec = (i->getName(symbolname)))) return ec;
80
81 if (symbolname != symbol)
82 continue;
83
84 // Get symbol flags
85 if ((ec = (i->getFlags(symflags)))) return ec;
86
87 if (symflags <= llvm::object::SymbolRef::SF_Undefined)
88 continue;
89
90 // Get Symbol Type
91 if ((ec = (i->getType(symtype)))) return ec;
92
93 if (symtype == llvm::object::SymbolRef::ST_Data) {
94 return error_code::success();
95 }
96 }
97 return llvm::object::object_error::parse_failed;
98 }
99
100private:
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000101 std::unique_ptr<llvm::object::Archive> _archive;
102 const ReaderOptionsArchive _options;
103 atom_collection_vector<DefinedAtom> _definedAtoms;
104 atom_collection_vector<UndefinedAtom> _undefinedAtoms;
105 atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
106 atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
107
108public:
109 /// only subclasses of ArchiveLibraryFile can be instantiated
110 explicit FileArchive(llvm::MemoryBuffer *mb,
111 const ReaderOptionsArchive &options,
112 error_code &ec)
113 :ArchiveLibraryFile(mb->getBufferIdentifier()),
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000114 _options(options) {
Michael J. Spencera5d22812012-11-13 19:58:58 +0000115 std::unique_ptr<llvm::object::Archive> archive_obj(
116 new llvm::object::Archive(mb, ec));
117 if (ec)
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000118 return;
Michael J. Spencera5d22812012-11-13 19:58:58 +0000119 _archive.swap(archive_obj);
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000120 }
121}; // class FileArchive
122
123// Returns a vector of Files that are contained in the archive file
124// pointed to by the MemoryBuffer
125error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
126 std::vector<std::unique_ptr<File>> &result) {
127 error_code ec;
128
Michael J. Spencera5d22812012-11-13 19:58:58 +0000129 if (_options.isForceLoad()) {
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000130 _archive.reset(new llvm::object::Archive(mb.release(), ec));
131 if (ec)
132 return ec;
133
134 for (auto mf = _archive->begin_children(),
Michael J. Spencera5d22812012-11-13 19:58:58 +0000135 me = _archive->end_children(); mf != me; ++mf) {
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000136 if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
137 (mf->getBuffer()), result)))
138 return ec;
139 }
140 } else {
141 std::unique_ptr<File> f;
142 f.reset(new FileArchive(mb.release(), _options, ec));
143 if (ec)
144 return ec;
145
146 result.push_back(std::move(f));
147 }
148 return llvm::error_code::success();
149}
150
151} // namespace lld