blob: 26c70dba9a93cbdcfef164a2f444ec1bb1ac363a [file] [log] [blame]
Rui Ueyama34efe772013-12-06 04:43:011//===- lld/ReaderWriter/FileArchive.cpp - Archive Library File -----------===//
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
10#include "lld/ReaderWriter/FileArchive.h"
11
12#include "llvm/ADT/Hashing.h"
13#include "llvm/Object/ObjectFile.h"
14#include "llvm/Object/Archive.h"
15#include "llvm/Support/MemoryBuffer.h"
16
17#include <unordered_map>
18
19namespace lld {
20
21/// \brief Check if any member of the archive contains an Atom with the
22/// specified name and return the File object for that member, or nullptr.
23const File *FileArchive::find(StringRef name, bool dataSymbolOnly) const {
24 auto member = _symbolMemberMap.find(name);
25 if (member == _symbolMemberMap.end())
26 return nullptr;
27
28 llvm::object::Archive::child_iterator ci = member->second;
29
30 if (dataSymbolOnly) {
31 OwningPtr<MemoryBuffer> buff;
32 if (ci->getMemoryBuffer(buff, true))
33 return nullptr;
34 if (isDataSymbol(buff.take(), name))
35 return nullptr;
36 }
37
38 std::vector<std::unique_ptr<File> > result;
39
40 OwningPtr<MemoryBuffer> buff;
41 if (ci->getMemoryBuffer(buff, true))
42 return nullptr;
43 if (_context.logInputFiles())
44 llvm::outs() << buff->getBufferIdentifier() << "\n";
45 std::unique_ptr<MemoryBuffer> mb(buff.take());
46 if (_context.getDefaultReader().parseFile(mb, result))
47 return nullptr;
48
49 assert(result.size() == 1);
50
51 // give up the pointer so that this object no longer manages it
52 return result[0].release();
53}
54
55/// \brief parse each member
56error_code FileArchive::parseAllMembers(
57 std::vector<std::unique_ptr<File> > &result) const {
58 for (auto mf = _archive->begin_children(), me = _archive->end_children();
59 mf != me; ++mf) {
60 OwningPtr<MemoryBuffer> buff;
Rui Ueyama6031c372013-12-06 04:48:0561 if (error_code ec = mf->getMemoryBuffer(buff, true))
Rui Ueyama34efe772013-12-06 04:43:0162 return ec;
63 if (_context.logInputFiles())
64 llvm::outs() << buff->getBufferIdentifier() << "\n";
65 std::unique_ptr<MemoryBuffer> mbc(buff.take());
Rui Ueyama6031c372013-12-06 04:48:0566 if (error_code ec = _context.getDefaultReader().parseFile(mbc, result))
Rui Ueyama34efe772013-12-06 04:43:0167 return ec;
68 }
69 return error_code::success();
70}
71
72const ArchiveLibraryFile::atom_collection<DefinedAtom> &
73FileArchive::defined() const {
74 return _definedAtoms;
75}
76
77const ArchiveLibraryFile::atom_collection<UndefinedAtom> &
78FileArchive::undefined() const {
79 return _undefinedAtoms;
80}
81
82const ArchiveLibraryFile::atom_collection<SharedLibraryAtom> &
83FileArchive::sharedLibrary() const {
84 return _sharedLibraryAtoms;
85}
86
87const ArchiveLibraryFile::atom_collection<AbsoluteAtom> &
88FileArchive::absolute() const {
89 return _absoluteAtoms;
90}
91
92error_code FileArchive::isDataSymbol(MemoryBuffer *mb, StringRef symbol) const {
93 std::unique_ptr<llvm::object::ObjectFile> obj(
94 llvm::object::ObjectFile::createObjectFile(mb));
95 error_code ec;
96 llvm::object::SymbolRef::Type symtype;
97 uint32_t symflags;
98 llvm::object::symbol_iterator ibegin = obj->begin_symbols();
99 llvm::object::symbol_iterator iend = obj->end_symbols();
100 StringRef symbolname;
101
102 for (llvm::object::symbol_iterator i = ibegin; i != iend; i.increment(ec)) {
103 if (ec)
104 return ec;
105
106 // Get symbol name
Rui Ueyama6031c372013-12-06 04:48:05107 if (error_code ec = i->getName(symbolname))
Rui Ueyama34efe772013-12-06 04:43:01108 return ec;
109
110 if (symbolname != symbol)
111 continue;
112
113 // Get symbol flags
Rui Ueyama6031c372013-12-06 04:48:05114 if (error_code ec = i->getFlags(symflags))
Rui Ueyama34efe772013-12-06 04:43:01115 return ec;
116
117 if (symflags <= llvm::object::SymbolRef::SF_Undefined)
118 continue;
119
120 // Get Symbol Type
Rui Ueyama6031c372013-12-06 04:48:05121 if (error_code ec = i->getType(symtype))
Rui Ueyama34efe772013-12-06 04:43:01122 return ec;
123
124 if (symtype == llvm::object::SymbolRef::ST_Data) {
125 return error_code::success();
126 }
127 }
128 return llvm::object::object_error::parse_failed;
129}
130
131FileArchive::FileArchive(const LinkingContext &context,
132 std::unique_ptr<MemoryBuffer> mb, error_code &ec,
133 bool isWholeArchive)
134 : ArchiveLibraryFile(context, mb->getBufferIdentifier()),
135 _isWholeArchive(isWholeArchive) {
136 std::unique_ptr<llvm::object::Archive> archive_obj(
137 new llvm::object::Archive(mb.release(), ec));
138 if (ec)
139 return;
140 _archive.swap(archive_obj);
141
142 // Cache symbols.
143 for (auto i = _archive->begin_symbols(), e = _archive->end_symbols(); i != e;
144 ++i) {
145 StringRef name;
146 llvm::object::Archive::child_iterator member;
147 if ((ec = i->getName(name)))
148 return;
149 if ((ec = i->getMember(member)))
150 return;
151 _symbolMemberMap[name] = member;
152 }
153}
154
155} // end namespace lld