blob: 4bce5303d44e575b32af5ba8ffe2de15eaeced0f [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
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:
Michael J. Spencera5d22812012-11-13 19:58:58 +000069 error_code isDataSymbol(MemoryBuffer *mb, StringRef symbol) const {
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000070 llvm::object::ObjectFile *obj =
71 llvm::object::ObjectFile::createObjectFile(mb);
72 error_code ec;
73 llvm::object::SymbolRef::Type symtype;
74 uint32_t symflags;
75 llvm::object::symbol_iterator ibegin = obj->begin_symbols();
76 llvm::object::symbol_iterator iend = obj->end_symbols();
77 StringRef symbolname;
78
79 for (llvm::object::symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
80 if (ec) return ec;
81
82 // Get symbol name
83 if ((ec = (i->getName(symbolname)))) return ec;
84
85 if (symbolname != symbol)
86 continue;
87
88 // Get symbol flags
89 if ((ec = (i->getFlags(symflags)))) return ec;
90
91 if (symflags <= llvm::object::SymbolRef::SF_Undefined)
92 continue;
93
94 // Get Symbol Type
95 if ((ec = (i->getType(symtype)))) return ec;
96
97 if (symtype == llvm::object::SymbolRef::ST_Data) {
98 return error_code::success();
99 }
100 }
101 return llvm::object::object_error::parse_failed;
102 }
103
104private:
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000105 std::unique_ptr<llvm::object::Archive> _archive;
106 const ReaderOptionsArchive _options;
107 atom_collection_vector<DefinedAtom> _definedAtoms;
108 atom_collection_vector<UndefinedAtom> _undefinedAtoms;
109 atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
110 atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
111
112public:
113 /// only subclasses of ArchiveLibraryFile can be instantiated
114 explicit FileArchive(llvm::MemoryBuffer *mb,
115 const ReaderOptionsArchive &options,
116 error_code &ec)
117 :ArchiveLibraryFile(mb->getBufferIdentifier()),
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000118 _options(options) {
Michael J. Spencera5d22812012-11-13 19:58:58 +0000119 std::unique_ptr<llvm::object::Archive> archive_obj(
120 new llvm::object::Archive(mb, ec));
121 if (ec)
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000122 return;
Michael J. Spencera5d22812012-11-13 19:58:58 +0000123 _archive.swap(archive_obj);
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000124 }
125}; // class FileArchive
126
127// Returns a vector of Files that are contained in the archive file
128// pointed to by the MemoryBuffer
129error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
130 std::vector<std::unique_ptr<File>> &result) {
131 error_code ec;
132
Michael J. Spencera5d22812012-11-13 19:58:58 +0000133 if (_options.isForceLoad()) {
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000134 _archive.reset(new llvm::object::Archive(mb.release(), ec));
135 if (ec)
136 return ec;
137
138 for (auto mf = _archive->begin_children(),
Michael J. Spencera5d22812012-11-13 19:58:58 +0000139 me = _archive->end_children(); mf != me; ++mf) {
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000140 if ((ec = _options.reader()->parseFile(std::unique_ptr<MemoryBuffer>
141 (mf->getBuffer()), result)))
142 return ec;
143 }
144 } else {
145 std::unique_ptr<File> f;
146 f.reset(new FileArchive(mb.release(), _options, ec));
147 if (ec)
148 return ec;
149
150 result.push_back(std::move(f));
151 }
152 return llvm::error_code::success();
153}
154
155} // namespace lld