blob: 370348b8990fac62397ef586f47aa08d31c0fd77 [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. Spencer64afcb42013-01-23 01:18:43 +000012#include "lld/Core/ArchiveLibraryFile.h"
13#include "lld/Core/LinkerOptions.h"
14
Michael J. Spencerad5f00e2013-01-10 01:27:45 +000015#include "llvm/ADT/Hashing.h"
Michael J. Spencer64afcb42013-01-23 01:18:43 +000016#include "llvm/Object/ObjectFile.h"
Michael J. Spencerad5f00e2013-01-10 01:27:45 +000017
18#include <unordered_map>
19
Michael J. Spencera5d22812012-11-13 19:58:58 +000020namespace lld {
21/// \brief The FileArchive class represents an Archive Library file
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000022class FileArchive : public ArchiveLibraryFile {
23public:
24
25 virtual ~FileArchive() { }
26
Michael J. Spencera5d22812012-11-13 19:58:58 +000027 /// \brief Check if any member of the archive contains an Atom with the
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000028 /// specified name and return the File object for that member, or nullptr.
29 virtual const File *find(StringRef name, bool dataSymbolOnly) const {
Michael J. Spencerad5f00e2013-01-10 01:27:45 +000030 auto member = _symbolMemberMap.find(name);
31 if (member == _symbolMemberMap.end())
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000032 return nullptr;
Michael J. Spencerad5f00e2013-01-10 01:27:45 +000033
Michael J. Spencerad5f00e2013-01-10 01:27:45 +000034 llvm::object::Archive::child_iterator ci = member->second;
Shankar Easwaran8962feb2013-03-14 16:09:49 +000035
Michael J. Spencer4673da22013-02-03 10:49:26 +000036 if (dataSymbolOnly) {
37 OwningPtr<MemoryBuffer> buff;
38 if (ci->getMemoryBuffer(buff, true))
39 return nullptr;
40 if (isDataSymbol(buff.take(), name))
41 return nullptr;
42 }
Shankar Easwaran8962feb2013-03-14 16:09:49 +000043
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000044 std::vector<std::unique_ptr<File>> result;
45
Michael J. Spencer4673da22013-02-03 10:49:26 +000046 OwningPtr<MemoryBuffer> buff;
47 if (ci->getMemoryBuffer(buff, true))
48 return nullptr;
49 LinkerInput li(std::unique_ptr<MemoryBuffer>(buff.take()));
50 if (_getReader(li)->parseFile(li.takeBuffer(), result))
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000051 return nullptr;
52
53 assert(result.size() == 1);
54
Michael J. Spencer6580d1f2013-03-20 18:56:57 +000055 result[0]->setOrdinalAndIncrement(_curChildOrd);
Shankar Easwaran8962feb2013-03-14 16:09:49 +000056
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000057 // give up the pointer so that this object no longer manages it
Shankar Easwaran85bb0452012-11-13 20:34:55 +000058 return result[0].release();
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000059 }
60
Nick Kledzik36293f62013-01-23 22:32:56 +000061 virtual void setOrdinalAndIncrement(uint64_t &ordinal) const {
62 _ordinal = ordinal++;
Michael J. Spencer6580d1f2013-03-20 18:56:57 +000063 _curChildOrd = _ordinal;
Nick Kledzik36293f62013-01-23 22:32:56 +000064 // Leave space in ordinal range for all children
Shankar Easwaran8962feb2013-03-14 16:09:49 +000065 for (auto mf = _archive->begin_children(),
Nick Kledzik36293f62013-01-23 22:32:56 +000066 me = _archive->end_children(); mf != me; ++mf) {
67 ordinal++;
68 }
69 }
70
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000071 virtual const atom_collection<DefinedAtom> &defined() const {
72 return _definedAtoms;
73 }
74
75 virtual const atom_collection<UndefinedAtom> &undefined() const {
76 return _undefinedAtoms;
77 }
78
79 virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
80 return _sharedLibraryAtoms;
81 }
82
83 virtual const atom_collection<AbsoluteAtom> &absolute() const {
84 return _absoluteAtoms;
85 }
86
87protected:
Michael J. Spencera5d22812012-11-13 19:58:58 +000088 error_code isDataSymbol(MemoryBuffer *mb, StringRef symbol) const {
Shankar Easwaran8962feb2013-03-14 16:09:49 +000089 std::unique_ptr<llvm::object::ObjectFile>
Shankar Easwaran85bb0452012-11-13 20:34:55 +000090 obj(llvm::object::ObjectFile::createObjectFile(mb));
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000091 error_code ec;
92 llvm::object::SymbolRef::Type symtype;
93 uint32_t symflags;
94 llvm::object::symbol_iterator ibegin = obj->begin_symbols();
95 llvm::object::symbol_iterator iend = obj->end_symbols();
96 StringRef symbolname;
97
98 for (llvm::object::symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
99 if (ec) return ec;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000100
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000101 // Get symbol name
102 if ((ec = (i->getName(symbolname)))) return ec;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000103
104 if (symbolname != symbol)
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000105 continue;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000106
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000107 // Get symbol flags
108 if ((ec = (i->getFlags(symflags)))) return ec;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000109
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000110 if (symflags <= llvm::object::SymbolRef::SF_Undefined)
111 continue;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000112
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000113 // Get Symbol Type
114 if ((ec = (i->getType(symtype)))) return ec;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000115
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000116 if (symtype == llvm::object::SymbolRef::ST_Data) {
117 return error_code::success();
118 }
119 }
120 return llvm::object::object_error::parse_failed;
121 }
122
123private:
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000124 std::function<ErrorOr<Reader&> (const LinkerInput &)> _getReader;
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000125 std::unique_ptr<llvm::object::Archive> _archive;
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000126 atom_collection_vector<DefinedAtom> _definedAtoms;
127 atom_collection_vector<UndefinedAtom> _undefinedAtoms;
128 atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
129 atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
Michael J. Spencer6580d1f2013-03-20 18:56:57 +0000130 mutable uint64_t _curChildOrd;
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000131
132public:
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000133 /// only subclasses of ArchiveLibraryFile can be instantiated
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000134 FileArchive(const TargetInfo &ti,
Shankar Easwaran3256d4f2013-01-25 07:39:18 +0000135 std::function<ErrorOr<Reader &>(const LinkerInput &)> getReader,
136 std::unique_ptr<llvm::MemoryBuffer> mb, error_code &ec)
137 : ArchiveLibraryFile(ti, mb->getBufferIdentifier()),
138 _getReader(getReader) {
Michael J. Spencera5d22812012-11-13 19:58:58 +0000139 std::unique_ptr<llvm::object::Archive> archive_obj(
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000140 new llvm::object::Archive(mb.release(), ec));
Michael J. Spencera5d22812012-11-13 19:58:58 +0000141 if (ec)
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000142 return;
Michael J. Spencera5d22812012-11-13 19:58:58 +0000143 _archive.swap(archive_obj);
Michael J. Spencerad5f00e2013-01-10 01:27:45 +0000144
145 // Cache symbols.
146 for (auto i = _archive->begin_symbols(), e = _archive->end_symbols();
147 i != e; ++i) {
148 StringRef name;
149 llvm::object::Archive::child_iterator member;
150 if ((ec = i->getName(name)))
151 return;
152 if ((ec = i->getMember(member)))
153 return;
154 _symbolMemberMap[name] = member;
155 }
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000156 }
Michael J. Spencerad5f00e2013-01-10 01:27:45 +0000157
158 std::unordered_map<StringRef, llvm::object::Archive::child_iterator> _symbolMemberMap;
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000159}; // class FileArchive
160
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000161// Returns a vector of Files that are contained in the archive file
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000162// pointed to by the MemoryBuffer
163error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000164 std::vector<std::unique_ptr<File>> &result){
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000165 error_code ec;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000166
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000167 if (_options._forceLoadArchives) {
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000168 _archive.reset(new llvm::object::Archive(mb.release(), ec));
169 if (ec)
170 return ec;
Shankar Easwaran8962feb2013-03-14 16:09:49 +0000171
172 for (auto mf = _archive->begin_children(),
Michael J. Spencera5d22812012-11-13 19:58:58 +0000173 me = _archive->end_children(); mf != me; ++mf) {
Michael J. Spencer4673da22013-02-03 10:49:26 +0000174 OwningPtr<MemoryBuffer> buff;
175 if ((ec = mf->getMemoryBuffer(buff, true)))
176 return ec;
177 LinkerInput li(std::unique_ptr<MemoryBuffer>(buff.take()));
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000178 if ((ec = _getReader(li)->parseFile(li.takeBuffer(), result)))
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000179 return ec;
180 }
181 } else {
182 std::unique_ptr<File> f;
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000183 f.reset(new FileArchive(_targetInfo, _getReader, std::move(mb), ec));
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000184 if (ec)
185 return ec;
186
187 result.push_back(std::move(f));
188 }
189 return llvm::error_code::success();
190}
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000191} // end namespace lld