blob: 8ec115a5566cadfbf07bb961b3ac715e396afbb4 [file] [log] [blame]
Eugene Zelenko86bfc782017-04-19 23:02:10 +00001//===- Archive.cpp - ar File Format implementation ------------------------===//
Michael J. Spencera51d7d92011-09-27 19:36:55 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the ArchiveObjectFile class.
11//
12//===----------------------------------------------------------------------===//
13
Chandler Carruthe3e43d92017-06-06 11:49:48 +000014#include "llvm/Object/Archive.h"
Eugene Zelenko86bfc782017-04-19 23:02:10 +000015#include "llvm/ADT/Optional.h"
Rafael Espindola5263d0a2013-07-09 03:39:35 +000016#include "llvm/ADT/SmallString.h"
Eugene Zelenko86bfc782017-04-19 23:02:10 +000017#include "llvm/ADT/StringRef.h"
Rafael Espindola5263d0a2013-07-09 03:39:35 +000018#include "llvm/ADT/Twine.h"
Eugene Zelenko86bfc782017-04-19 23:02:10 +000019#include "llvm/Object/Binary.h"
20#include "llvm/Object/Error.h"
21#include "llvm/Support/Chrono.h"
Michael J. Spencerc8a55a62011-11-02 19:33:12 +000022#include "llvm/Support/Endian.h"
Eugene Zelenko86bfc782017-04-19 23:02:10 +000023#include "llvm/Support/Error.h"
24#include "llvm/Support/ErrorOr.h"
25#include "llvm/Support/FileSystem.h"
Michael J. Spencera51d7d92011-09-27 19:36:55 +000026#include "llvm/Support/MemoryBuffer.h"
Rafael Espindola7a6e3432015-07-14 22:18:43 +000027#include "llvm/Support/Path.h"
Eugene Zelenko86bfc782017-04-19 23:02:10 +000028#include "llvm/Support/raw_ostream.h"
29#include <algorithm>
30#include <cassert>
31#include <cstddef>
32#include <cstdint>
33#include <cstring>
34#include <memory>
35#include <string>
36#include <system_error>
Michael J. Spencera51d7d92011-09-27 19:36:55 +000037
38using namespace llvm;
39using namespace object;
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +000040using namespace llvm::support::endian;
Michael J. Spencera51d7d92011-09-27 19:36:55 +000041
Craig Topper4172a8a2013-07-16 01:17:10 +000042static const char *const Magic = "!<arch>\n";
Rafael Espindola96b79672014-12-16 01:43:41 +000043static const char *const ThinMagic = "!<thin>\n";
Michael J. Spencera51d7d92011-09-27 19:36:55 +000044
Eugene Zelenko86bfc782017-04-19 23:02:10 +000045void Archive::anchor() {}
David Blaikie2d24e2a2011-12-20 02:50:00 +000046
Kevin Enderbyfa907612016-07-19 20:47:07 +000047static Error
48malformedError(Twine Msg) {
49 std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")";
50 return make_error<GenericBinaryError>(std::move(StringMsg),
51 object_error::parse_failed);
52}
53
Kevin Enderbydc025542016-07-25 20:36:36 +000054ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent,
55 const char *RawHeaderPtr,
56 uint64_t Size, Error *Err)
57 : Parent(Parent),
58 ArMemHdr(reinterpret_cast<const ArMemHdrType *>(RawHeaderPtr)) {
59 if (RawHeaderPtr == nullptr)
60 return;
61 ErrorAsOutParameter ErrAsOutParam(Err);
62
Kevin Enderbydc025542016-07-25 20:36:36 +000063 if (Size < sizeof(ArMemHdrType)) {
64 if (Err) {
Kevin Enderbyebd83362016-07-29 22:32:02 +000065 std::string Msg("remaining size of archive too small for next archive "
66 "member header ");
Kevin Enderby2a715172016-07-29 17:44:13 +000067 Expected<StringRef> NameOrErr = getName(Size);
68 if (!NameOrErr) {
69 consumeError(NameOrErr.takeError());
70 uint64_t Offset = RawHeaderPtr - Parent->getData().data();
71 *Err = malformedError(Msg + "at offset " + Twine(Offset));
72 } else
Kevin Enderbyebd83362016-07-29 22:32:02 +000073 *Err = malformedError(Msg + "for " + NameOrErr.get());
Kevin Enderbydc025542016-07-25 20:36:36 +000074 }
75 return;
76 }
77 if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') {
78 if (Err) {
79 std::string Buf;
80 raw_string_ostream OS(Buf);
Eugene Zelenko86bfc782017-04-19 23:02:10 +000081 OS.write_escaped(StringRef(ArMemHdr->Terminator,
82 sizeof(ArMemHdr->Terminator)));
Kevin Enderbydc025542016-07-25 20:36:36 +000083 OS.flush();
Kevin Enderbyebd83362016-07-29 22:32:02 +000084 std::string Msg("terminator characters in archive member \"" + Buf +
85 "\" not the correct \"`\\n\" values for the archive "
86 "member header ");
Kevin Enderby2a715172016-07-29 17:44:13 +000087 Expected<StringRef> NameOrErr = getName(Size);
88 if (!NameOrErr) {
89 consumeError(NameOrErr.takeError());
90 uint64_t Offset = RawHeaderPtr - Parent->getData().data();
91 *Err = malformedError(Msg + "at offset " + Twine(Offset));
92 } else
Kevin Enderbyebd83362016-07-29 22:32:02 +000093 *Err = malformedError(Msg + "for " + NameOrErr.get());
Kevin Enderbydc025542016-07-25 20:36:36 +000094 }
95 return;
96 }
97}
98
Kevin Enderby2a715172016-07-29 17:44:13 +000099// This gets the raw name from the ArMemHdr->Name field and checks that it is
100// valid for the kind of archive. If it is not valid it returns an Error.
101Expected<StringRef> ArchiveMemberHeader::getRawName() const {
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000102 char EndCond;
Kevin Enderby2a715172016-07-29 17:44:13 +0000103 auto Kind = Parent->kind();
104 if (Kind == Archive::K_BSD || Kind == Archive::K_DARWIN64) {
105 if (ArMemHdr->Name[0] == ' ') {
106 uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
107 Parent->getData().data();
108 return malformedError("name contains a leading space for archive member "
109 "header at offset " + Twine(Offset));
110 }
111 EndCond = ' ';
112 }
113 else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#')
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000114 EndCond = ' ';
115 else
116 EndCond = '/';
Eugene Zelenko86bfc782017-04-19 23:02:10 +0000117 StringRef::size_type end =
118 StringRef(ArMemHdr->Name, sizeof(ArMemHdr->Name)).find(EndCond);
119 if (end == StringRef::npos)
Kevin Enderbydc025542016-07-25 20:36:36 +0000120 end = sizeof(ArMemHdr->Name);
121 assert(end <= sizeof(ArMemHdr->Name) && end > 0);
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000122 // Don't include the EndCond if there is one.
Eugene Zelenko86bfc782017-04-19 23:02:10 +0000123 return StringRef(ArMemHdr->Name, end);
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000124}
125
Kevin Enderby2a715172016-07-29 17:44:13 +0000126// This gets the name looking up long names. Size is the size of the archive
127// member including the header, so the size of any name following the header
128// is checked to make sure it does not overflow.
129Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
130
131 // This can be called from the ArchiveMemberHeader constructor when the
132 // archive header is truncated to produce an error message with the name.
133 // Make sure the name field is not truncated.
134 if (Size < offsetof(ArMemHdrType, Name) + sizeof(ArMemHdr->Name)) {
135 uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) -
136 Parent->getData().data();
137 return malformedError("archive header truncated before the name field "
138 "for archive member header at offset " +
139 Twine(ArchiveOffset));
140 }
141
142 // The raw name itself can be invalid.
143 Expected<StringRef> NameOrErr = getRawName();
144 if (!NameOrErr)
145 return NameOrErr.takeError();
146 StringRef Name = NameOrErr.get();
147
148 // Check if it's a special name.
149 if (Name[0] == '/') {
150 if (Name.size() == 1) // Linker member.
151 return Name;
152 if (Name.size() == 2 && Name[1] == '/') // String table.
153 return Name;
154 // It's a long name.
155 // Get the string table offset.
156 std::size_t StringOffset;
157 if (Name.substr(1).rtrim(' ').getAsInteger(10, StringOffset)) {
158 std::string Buf;
159 raw_string_ostream OS(Buf);
Kevin Enderbyebd83362016-07-29 22:32:02 +0000160 OS.write_escaped(Name.substr(1).rtrim(' '));
Kevin Enderby2a715172016-07-29 17:44:13 +0000161 OS.flush();
162 uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) -
163 Parent->getData().data();
164 return malformedError("long name offset characters after the '/' are "
165 "not all decimal numbers: '" + Buf + "' for "
166 "archive member header at offset " +
167 Twine(ArchiveOffset));
168 }
169
170 // Verify it.
171 if (StringOffset >= Parent->getStringTable().size()) {
172 uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) -
173 Parent->getData().data();
174 return malformedError("long name offset " + Twine(StringOffset) + " past "
175 "the end of the string table for archive member "
176 "header at offset " + Twine(ArchiveOffset));
177 }
Kevin Enderby2a715172016-07-29 17:44:13 +0000178
179 // GNU long file names end with a "/\n".
180 if (Parent->kind() == Archive::K_GNU ||
Jake Ehrlichf45adc22017-09-20 18:23:01 +0000181 Parent->kind() == Archive::K_GNU64) {
Hans Wennborgaa4eef72018-05-08 08:22:58 +0000182 size_t End = Parent->getStringTable().find('\n', /*From=*/StringOffset);
183 if (End == StringRef::npos || End < 1 ||
184 Parent->getStringTable()[End - 1] != '/') {
185 return malformedError("string table at long name offset " +
186 Twine(StringOffset) + "not terminated");
187 }
188 return Parent->getStringTable().slice(StringOffset, End - 1);
Kevin Enderby2a715172016-07-29 17:44:13 +0000189 }
Hans Wennborgaa4eef72018-05-08 08:22:58 +0000190 return Parent->getStringTable().begin() + StringOffset;
David Blaikie4c028792016-08-01 21:50:43 +0000191 }
192
193 if (Name.startswith("#1/")) {
Kevin Enderby2a715172016-07-29 17:44:13 +0000194 uint64_t NameLength;
195 if (Name.substr(3).rtrim(' ').getAsInteger(10, NameLength)) {
196 std::string Buf;
197 raw_string_ostream OS(Buf);
Kevin Enderbyebd83362016-07-29 22:32:02 +0000198 OS.write_escaped(Name.substr(3).rtrim(' '));
Kevin Enderby2a715172016-07-29 17:44:13 +0000199 OS.flush();
200 uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) -
201 Parent->getData().data();
202 return malformedError("long name length characters after the #1/ are "
203 "not all decimal numbers: '" + Buf + "' for "
204 "archive member header at offset " +
205 Twine(ArchiveOffset));
206 }
207 if (getSizeOf() + NameLength > Size) {
208 uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) -
209 Parent->getData().data();
210 return malformedError("long name length: " + Twine(NameLength) +
211 " extends past the end of the member or archive "
212 "for archive member header at offset " +
213 Twine(ArchiveOffset));
214 }
215 return StringRef(reinterpret_cast<const char *>(ArMemHdr) + getSizeOf(),
216 NameLength).rtrim('\0');
Kevin Enderby2a715172016-07-29 17:44:13 +0000217 }
David Blaikie4c028792016-08-01 21:50:43 +0000218
219 // It is not a long name so trim the blanks at the end of the name.
220 if (Name[Name.size() - 1] != '/')
221 return Name.rtrim(' ');
222
Kevin Enderby2a715172016-07-29 17:44:13 +0000223 // It's a simple name.
David Blaikie4c028792016-08-01 21:50:43 +0000224 return Name.drop_back(1);
Kevin Enderby2a715172016-07-29 17:44:13 +0000225}
226
Kevin Enderbyfa907612016-07-19 20:47:07 +0000227Expected<uint32_t> ArchiveMemberHeader::getSize() const {
Rafael Espindola20125932013-07-09 12:45:11 +0000228 uint32_t Ret;
Eugene Zelenko86bfc782017-04-19 23:02:10 +0000229 if (StringRef(ArMemHdr->Size,
230 sizeof(ArMemHdr->Size)).rtrim(" ").getAsInteger(10, Ret)) {
Kevin Enderbyfa907612016-07-19 20:47:07 +0000231 std::string Buf;
232 raw_string_ostream OS(Buf);
Eugene Zelenko86bfc782017-04-19 23:02:10 +0000233 OS.write_escaped(StringRef(ArMemHdr->Size,
234 sizeof(ArMemHdr->Size)).rtrim(" "));
Kevin Enderbyfa907612016-07-19 20:47:07 +0000235 OS.flush();
Kevin Enderbydc025542016-07-25 20:36:36 +0000236 uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
237 Parent->getData().data();
Kevin Enderbyfa907612016-07-19 20:47:07 +0000238 return malformedError("characters in size field in archive header are not "
Kevin Enderbydc025542016-07-25 20:36:36 +0000239 "all decimal numbers: '" + Buf + "' for archive "
240 "member header at offset " + Twine(Offset));
Kevin Enderbyfa907612016-07-19 20:47:07 +0000241 }
Rafael Espindola20125932013-07-09 12:45:11 +0000242 return Ret;
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000243}
244
Vedant Kumare5d15782016-08-03 19:02:50 +0000245Expected<sys::fs::perms> ArchiveMemberHeader::getAccessMode() const {
Rafael Espindola9941bdd2013-07-09 12:49:24 +0000246 unsigned Ret;
Kevin Enderbydc025542016-07-25 20:36:36 +0000247 if (StringRef(ArMemHdr->AccessMode,
Vedant Kumare5d15782016-08-03 19:02:50 +0000248 sizeof(ArMemHdr->AccessMode)).rtrim(' ').getAsInteger(8, Ret)) {
249 std::string Buf;
250 raw_string_ostream OS(Buf);
Eugene Zelenko86bfc782017-04-19 23:02:10 +0000251 OS.write_escaped(StringRef(ArMemHdr->AccessMode,
252 sizeof(ArMemHdr->AccessMode)).rtrim(" "));
Vedant Kumare5d15782016-08-03 19:02:50 +0000253 OS.flush();
254 uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
255 Parent->getData().data();
256 return malformedError("characters in AccessMode field in archive header "
257 "are not all decimal numbers: '" + Buf + "' for the "
258 "archive member header at offset " + Twine(Offset));
259 }
Rafael Espindola9941bdd2013-07-09 12:49:24 +0000260 return static_cast<sys::fs::perms>(Ret);
261}
262
Pavel Labath6df95622016-10-24 13:38:27 +0000263Expected<sys::TimePoint<std::chrono::seconds>>
264ArchiveMemberHeader::getLastModified() const {
Rafael Espindola9941bdd2013-07-09 12:49:24 +0000265 unsigned Seconds;
Kevin Enderbydc025542016-07-25 20:36:36 +0000266 if (StringRef(ArMemHdr->LastModified,
267 sizeof(ArMemHdr->LastModified)).rtrim(' ')
Vedant Kumare5d15782016-08-03 19:02:50 +0000268 .getAsInteger(10, Seconds)) {
269 std::string Buf;
270 raw_string_ostream OS(Buf);
Eugene Zelenko86bfc782017-04-19 23:02:10 +0000271 OS.write_escaped(StringRef(ArMemHdr->LastModified,
272 sizeof(ArMemHdr->LastModified)).rtrim(" "));
Vedant Kumare5d15782016-08-03 19:02:50 +0000273 OS.flush();
274 uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
275 Parent->getData().data();
276 return malformedError("characters in LastModified field in archive header "
277 "are not all decimal numbers: '" + Buf + "' for the "
278 "archive member header at offset " + Twine(Offset));
279 }
Rafael Espindola9941bdd2013-07-09 12:49:24 +0000280
Pavel Labath6df95622016-10-24 13:38:27 +0000281 return sys::toTimePoint(Seconds);
Rafael Espindola9941bdd2013-07-09 12:49:24 +0000282}
283
Vedant Kumare5d15782016-08-03 19:02:50 +0000284Expected<unsigned> ArchiveMemberHeader::getUID() const {
Rafael Espindola9941bdd2013-07-09 12:49:24 +0000285 unsigned Ret;
Kevin Enderbydc025542016-07-25 20:36:36 +0000286 StringRef User = StringRef(ArMemHdr->UID, sizeof(ArMemHdr->UID)).rtrim(' ');
Saleem Abdulrasoole88f1b32016-07-05 00:23:05 +0000287 if (User.empty())
288 return 0;
Vedant Kumare5d15782016-08-03 19:02:50 +0000289 if (User.getAsInteger(10, Ret)) {
290 std::string Buf;
291 raw_string_ostream OS(Buf);
292 OS.write_escaped(User);
293 OS.flush();
294 uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
295 Parent->getData().data();
296 return malformedError("characters in UID field in archive header "
297 "are not all decimal numbers: '" + Buf + "' for the "
298 "archive member header at offset " + Twine(Offset));
299 }
Rafael Espindola9941bdd2013-07-09 12:49:24 +0000300 return Ret;
301}
302
Vedant Kumare5d15782016-08-03 19:02:50 +0000303Expected<unsigned> ArchiveMemberHeader::getGID() const {
Rafael Espindola9941bdd2013-07-09 12:49:24 +0000304 unsigned Ret;
Kevin Enderbydc025542016-07-25 20:36:36 +0000305 StringRef Group = StringRef(ArMemHdr->GID, sizeof(ArMemHdr->GID)).rtrim(' ');
Saleem Abdulrasoole88f1b32016-07-05 00:23:05 +0000306 if (Group.empty())
307 return 0;
Vedant Kumare5d15782016-08-03 19:02:50 +0000308 if (Group.getAsInteger(10, Ret)) {
309 std::string Buf;
310 raw_string_ostream OS(Buf);
311 OS.write_escaped(Group);
312 OS.flush();
313 uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
314 Parent->getData().data();
315 return malformedError("characters in GID field in archive header "
316 "are not all decimal numbers: '" + Buf + "' for the "
317 "archive member header at offset " + Twine(Offset));
318 }
Rafael Espindola9941bdd2013-07-09 12:49:24 +0000319 return Ret;
320}
321
Rafael Espindolad3ca2392015-10-31 21:44:42 +0000322Archive::Child::Child(const Archive *Parent, StringRef Data,
323 uint16_t StartOfFile)
Kevin Enderbydc025542016-07-25 20:36:36 +0000324 : Parent(Parent), Header(Parent, Data.data(), Data.size(), nullptr),
325 Data(Data), StartOfFile(StartOfFile) {
326}
Rafael Espindolad3ca2392015-10-31 21:44:42 +0000327
Kevin Enderbyfa907612016-07-19 20:47:07 +0000328Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
Lang Hames19118732016-10-05 21:20:00 +0000329 : Parent(Parent),
330 Header(Parent, Start,
331 Parent
332 ? Parent->getData().size() - (Start - Parent->getData().data())
333 : 0, Err) {
Rafael Espindolabe6b9102013-07-09 05:26:25 +0000334 if (!Start)
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000335 return;
Kevin Enderby74bccc32016-08-04 21:54:19 +0000336
337 // If we are pointed to real data, Start is not a nullptr, then there must be
338 // a non-null Err pointer available to report malformed data on. Only in
339 // the case sentinel value is being constructed is Err is permitted to be a
340 // nullptr.
341 assert(Err && "Err can't be nullptr if Start is not a nullptr");
342
Lang Hames78095432016-07-22 16:11:25 +0000343 ErrorAsOutParameter ErrAsOutParam(Err);
Rafael Espindolabe6b9102013-07-09 05:26:25 +0000344
Jake Ehrlichf45adc22017-09-20 18:23:01 +0000345 // If there was an error in the construction of the Header
Kevin Enderby74bccc32016-08-04 21:54:19 +0000346 // then just return with the error now set.
347 if (*Err)
Kevin Enderbydc025542016-07-25 20:36:36 +0000348 return;
349
350 uint64_t Size = Header.getSizeOf();
Rafael Espindola96b79672014-12-16 01:43:41 +0000351 Data = StringRef(Start, Size);
Kevin Enderby2a715172016-07-29 17:44:13 +0000352 Expected<bool> isThinOrErr = isThinMember();
353 if (!isThinOrErr) {
Kevin Enderby74bccc32016-08-04 21:54:19 +0000354 *Err = isThinOrErr.takeError();
Kevin Enderby2a715172016-07-29 17:44:13 +0000355 return;
356 }
357 bool isThin = isThinOrErr.get();
358 if (!isThin) {
Kevin Enderbyfa907612016-07-19 20:47:07 +0000359 Expected<uint64_t> MemberSize = getRawSize();
360 if (!MemberSize) {
Kevin Enderby74bccc32016-08-04 21:54:19 +0000361 *Err = MemberSize.takeError();
Kevin Enderby268709a2015-11-05 19:24:56 +0000362 return;
Kevin Enderbyfa907612016-07-19 20:47:07 +0000363 }
Kevin Enderby268709a2015-11-05 19:24:56 +0000364 Size += MemberSize.get();
Rafael Espindola9db135a2015-07-22 19:34:26 +0000365 Data = StringRef(Start, Size);
366 }
Rafael Espindolabe6b9102013-07-09 05:26:25 +0000367
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000368 // Setup StartOfFile and PaddingBytes.
Kevin Enderbydc025542016-07-25 20:36:36 +0000369 StartOfFile = Header.getSizeOf();
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000370 // Don't include attached name.
Kevin Enderby2a715172016-07-29 17:44:13 +0000371 Expected<StringRef> NameOrErr = getRawName();
372 if (!NameOrErr){
Kevin Enderby74bccc32016-08-04 21:54:19 +0000373 *Err = NameOrErr.takeError();
Kevin Enderby2a715172016-07-29 17:44:13 +0000374 return;
375 }
376 StringRef Name = NameOrErr.get();
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000377 if (Name.startswith("#1/")) {
378 uint64_t NameSize;
Kevin Enderby2a715172016-07-29 17:44:13 +0000379 if (Name.substr(3).rtrim(' ').getAsInteger(10, NameSize)) {
Kevin Enderby74bccc32016-08-04 21:54:19 +0000380 std::string Buf;
381 raw_string_ostream OS(Buf);
382 OS.write_escaped(Name.substr(3).rtrim(' '));
383 OS.flush();
384 uint64_t Offset = Start - Parent->getData().data();
385 *Err = malformedError("long name length characters after the #1/ are "
386 "not all decimal numbers: '" + Buf + "' for "
387 "archive member header at offset " +
388 Twine(Offset));
389 return;
Kevin Enderby2a715172016-07-29 17:44:13 +0000390 }
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000391 StartOfFile += NameSize;
392 }
393}
394
Kevin Enderbyfa907612016-07-19 20:47:07 +0000395Expected<uint64_t> Archive::Child::getSize() const {
Kevin Enderby1cd4c562015-10-13 20:48:04 +0000396 if (Parent->IsThin) {
Kevin Enderbydc025542016-07-25 20:36:36 +0000397 Expected<uint32_t> Size = Header.getSize();
Kevin Enderbyfa907612016-07-19 20:47:07 +0000398 if (!Size)
399 return Size.takeError();
Kevin Enderby1cd4c562015-10-13 20:48:04 +0000400 return Size.get();
401 }
Rafael Espindola96b79672014-12-16 01:43:41 +0000402 return Data.size() - StartOfFile;
403}
404
Kevin Enderbyfa907612016-07-19 20:47:07 +0000405Expected<uint64_t> Archive::Child::getRawSize() const {
Kevin Enderbydc025542016-07-25 20:36:36 +0000406 return Header.getSize();
Kevin Enderbycdfe54f2015-01-15 23:19:11 +0000407}
408
Kevin Enderby2a715172016-07-29 17:44:13 +0000409Expected<bool> Archive::Child::isThinMember() const {
410 Expected<StringRef> NameOrErr = Header.getRawName();
411 if (!NameOrErr)
412 return NameOrErr.takeError();
413 StringRef Name = NameOrErr.get();
Rafael Espindola9db135a2015-07-22 19:34:26 +0000414 return Parent->IsThin && Name != "/" && Name != "//";
415}
416
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000417Expected<std::string> Archive::Child::getFullName() const {
Kevin Enderby2a715172016-07-29 17:44:13 +0000418 Expected<bool> isThin = isThinMember();
419 if (!isThin)
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000420 return isThin.takeError();
Kevin Enderby2a715172016-07-29 17:44:13 +0000421 assert(isThin.get());
422 Expected<StringRef> NameOrErr = getName();
423 if (!NameOrErr)
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000424 return NameOrErr.takeError();
Rafael Espindola4c7d1662016-05-02 13:45:06 +0000425 StringRef Name = *NameOrErr;
426 if (sys::path::is_absolute(Name))
427 return Name;
428
429 SmallString<128> FullName = sys::path::parent_path(
430 Parent->getMemoryBufferRef().getBufferIdentifier());
431 sys::path::append(FullName, Name);
432 return StringRef(FullName);
433}
434
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000435Expected<StringRef> Archive::Child::getBuffer() const {
Kevin Enderby2a715172016-07-29 17:44:13 +0000436 Expected<bool> isThinOrErr = isThinMember();
437 if (!isThinOrErr)
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000438 return isThinOrErr.takeError();
Kevin Enderby2a715172016-07-29 17:44:13 +0000439 bool isThin = isThinOrErr.get();
440 if (!isThin) {
Kevin Enderbyfa907612016-07-19 20:47:07 +0000441 Expected<uint32_t> Size = getSize();
442 if (!Size)
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000443 return Size.takeError();
Kevin Enderby268709a2015-11-05 19:24:56 +0000444 return StringRef(Data.data() + StartOfFile, Size.get());
445 }
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000446 Expected<std::string> FullNameOrErr = getFullName();
447 if (!FullNameOrErr)
448 return FullNameOrErr.takeError();
449 const std::string &FullName = *FullNameOrErr;
Rafael Espindola7a6e3432015-07-14 22:18:43 +0000450 ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName);
451 if (std::error_code EC = Buf.getError())
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000452 return errorCodeToError(EC);
Rafael Espindola7a6e3432015-07-14 22:18:43 +0000453 Parent->ThinBuffers.push_back(std::move(*Buf));
454 return Parent->ThinBuffers.back()->getBuffer();
455}
456
Kevin Enderbyfa907612016-07-19 20:47:07 +0000457Expected<Archive::Child> Archive::Child::getNext() const {
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000458 size_t SpaceToSkip = Data.size();
459 // If it's odd, add 1 to make it even.
460 if (SpaceToSkip & 1)
Kevin Enderbyda785372015-10-21 17:13:20 +0000461 ++SpaceToSkip;
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000462
Kevin Enderbyda785372015-10-21 17:13:20 +0000463 const char *NextLoc = Data.data() + SpaceToSkip;
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000464
Kevin Enderby268709a2015-11-05 19:24:56 +0000465 // Check to see if this is at the end of the archive.
466 if (NextLoc == Parent->Data.getBufferEnd())
Lang Hames19118732016-10-05 21:20:00 +0000467 return Child(nullptr, nullptr, nullptr);
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000468
Kevin Enderby268709a2015-11-05 19:24:56 +0000469 // Check to see if this is past the end of the archive.
Kevin Enderbydc025542016-07-25 20:36:36 +0000470 if (NextLoc > Parent->Data.getBufferEnd()) {
Kevin Enderbyebd83362016-07-29 22:32:02 +0000471 std::string Msg("offset to next archive member past the end of the archive "
472 "after member ");
Kevin Enderby2a715172016-07-29 17:44:13 +0000473 Expected<StringRef> NameOrErr = getName();
474 if (!NameOrErr) {
475 consumeError(NameOrErr.takeError());
Kevin Enderbydc025542016-07-25 20:36:36 +0000476 uint64_t Offset = Data.data() - Parent->getData().data();
477 return malformedError(Msg + "at offset " + Twine(Offset));
478 } else
Kevin Enderbyebd83362016-07-29 22:32:02 +0000479 return malformedError(Msg + NameOrErr.get());
Kevin Enderbydc025542016-07-25 20:36:36 +0000480 }
Kevin Enderby268709a2015-11-05 19:24:56 +0000481
Mehdi Aminidf0b8bc2016-11-11 04:28:40 +0000482 Error Err = Error::success();
Kevin Enderbyfa907612016-07-19 20:47:07 +0000483 Child Ret(Parent, NextLoc, &Err);
484 if (Err)
485 return std::move(Err);
Kevin Enderby268709a2015-11-05 19:24:56 +0000486 return Ret;
Rafael Espindola5263d0a2013-07-09 03:39:35 +0000487}
488
Kevin Enderbycdfe54f2015-01-15 23:19:11 +0000489uint64_t Archive::Child::getChildOffset() const {
490 const char *a = Parent->Data.getBuffer().data();
491 const char *c = Data.data();
492 uint64_t offset = c - a;
493 return offset;
494}
495
Kevin Enderby2a715172016-07-29 17:44:13 +0000496Expected<StringRef> Archive::Child::getName() const {
497 Expected<uint64_t> RawSizeOrErr = getRawSize();
498 if (!RawSizeOrErr)
499 return RawSizeOrErr.takeError();
500 uint64_t RawSize = RawSizeOrErr.get();
501 Expected<StringRef> NameOrErr = Header.getName(Header.getSizeOf() + RawSize);
502 if (!NameOrErr)
503 return NameOrErr.takeError();
504 StringRef Name = NameOrErr.get();
505 return Name;
Michael J. Spencera51d7d92011-09-27 19:36:55 +0000506}
507
Kevin Enderby2a715172016-07-29 17:44:13 +0000508Expected<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {
509 Expected<StringRef> NameOrErr = getName();
510 if (!NameOrErr)
511 return NameOrErr.takeError();
Rafael Espindola06599282014-06-16 16:08:36 +0000512 StringRef Name = NameOrErr.get();
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000513 Expected<StringRef> Buf = getBuffer();
514 if (!Buf)
515 return Buf.takeError();
Rafael Espindola7a6e3432015-07-14 22:18:43 +0000516 return MemoryBufferRef(*Buf, Name);
Rafael Espindola06599282014-06-16 16:08:36 +0000517}
518
Kevin Enderby77be0942016-05-17 17:10:12 +0000519Expected<std::unique_ptr<Binary>>
Rafael Espindola06599282014-06-16 16:08:36 +0000520Archive::Child::getAsBinary(LLVMContext *Context) const {
Kevin Enderby2a715172016-07-29 17:44:13 +0000521 Expected<MemoryBufferRef> BuffOrErr = getMemoryBufferRef();
522 if (!BuffOrErr)
523 return BuffOrErr.takeError();
Rafael Espindola1f659322014-06-23 21:53:12 +0000524
Kevin Enderbyc6bf9be2016-04-06 22:14:09 +0000525 auto BinaryOrErr = createBinary(BuffOrErr.get(), Context);
526 if (BinaryOrErr)
527 return std::move(*BinaryOrErr);
Kevin Enderby77be0942016-05-17 17:10:12 +0000528 return BinaryOrErr.takeError();
Michael J. Spencera51d7d92011-09-27 19:36:55 +0000529}
530
Kevin Enderby0b21d882016-06-29 20:35:44 +0000531Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {
Mehdi Aminidf0b8bc2016-11-11 04:28:40 +0000532 Error Err = Error::success();
Kevin Enderby0b21d882016-06-29 20:35:44 +0000533 std::unique_ptr<Archive> Ret(new Archive(Source, Err));
534 if (Err)
535 return std::move(Err);
Rafael Espindola1c9b9822014-07-31 03:36:00 +0000536 return std::move(Ret);
Rafael Espindola3d218152014-01-21 23:06:54 +0000537}
538
Rafael Espindolad3ca2392015-10-31 21:44:42 +0000539void Archive::setFirstRegular(const Child &C) {
540 FirstRegularData = C.Data;
541 FirstRegularStartOfFile = C.StartOfFile;
542}
543
Kevin Enderby0b21d882016-06-29 20:35:44 +0000544Archive::Archive(MemoryBufferRef Source, Error &Err)
Rafael Espindolad3ca2392015-10-31 21:44:42 +0000545 : Binary(Binary::ID_Archive, Source) {
Lang Hames78095432016-07-22 16:11:25 +0000546 ErrorAsOutParameter ErrAsOutParam(&Err);
Rafael Espindola96b79672014-12-16 01:43:41 +0000547 StringRef Buffer = Data.getBuffer();
Michael J. Spencera51d7d92011-09-27 19:36:55 +0000548 // Check for sufficient magic.
Rafael Espindola96b79672014-12-16 01:43:41 +0000549 if (Buffer.startswith(ThinMagic)) {
550 IsThin = true;
551 } else if (Buffer.startswith(Magic)) {
552 IsThin = false;
553 } else {
Kevin Enderby0b21d882016-06-29 20:35:44 +0000554 Err = make_error<GenericBinaryError>("File too small to be an archive",
555 object_error::invalid_file_type);
Michael J. Spencera51d7d92011-09-27 19:36:55 +0000556 return;
557 }
558
Kevin Enderby2a715172016-07-29 17:44:13 +0000559 // Make sure Format is initialized before any call to
560 // ArchiveMemberHeader::getName() is made. This could be a valid empty
561 // archive which is the same in all formats. So claiming it to be gnu to is
562 // fine if not totally correct before we look for a string table or table of
563 // contents.
564 Format = K_GNU;
565
Michael J. Spencerc8a55a62011-11-02 19:33:12 +0000566 // Get the special members.
Lang Hamesaacf2fb2016-07-14 02:24:01 +0000567 child_iterator I = child_begin(Err, false);
568 if (Err)
Kevin Enderby268709a2015-11-05 19:24:56 +0000569 return;
570 child_iterator E = child_end();
Michael J. Spencera51d7d92011-09-27 19:36:55 +0000571
Kevin Enderby2a715172016-07-29 17:44:13 +0000572 // See if this is a valid empty archive and if so return.
Kevin Enderby268709a2015-11-05 19:24:56 +0000573 if (I == E) {
Kevin Enderby0b21d882016-06-29 20:35:44 +0000574 Err = Error::success();
Rafael Espindola09a7f602013-07-03 15:57:14 +0000575 return;
576 }
Lang Hamesaacf2fb2016-07-14 02:24:01 +0000577 const Child *C = &*I;
Rafael Espindola09a7f602013-07-03 15:57:14 +0000578
Kevin Enderby268709a2015-11-05 19:24:56 +0000579 auto Increment = [&]() {
580 ++I;
Lang Hamesaacf2fb2016-07-14 02:24:01 +0000581 if (Err)
Kevin Enderby268709a2015-11-05 19:24:56 +0000582 return true;
Lang Hamesaacf2fb2016-07-14 02:24:01 +0000583 C = &*I;
Kevin Enderby268709a2015-11-05 19:24:56 +0000584 return false;
585 };
586
Kevin Enderby2a715172016-07-29 17:44:13 +0000587 Expected<StringRef> NameOrErr = C->getRawName();
588 if (!NameOrErr) {
589 Err = NameOrErr.takeError();
590 return;
591 }
592 StringRef Name = NameOrErr.get();
Michael J. Spencera51d7d92011-09-27 19:36:55 +0000593
Shankar Easwaran206252c2012-11-13 18:38:42 +0000594 // Below is the pattern that is used to figure out the archive format
595 // GNU archive format
Rafael Espindola09a7f602013-07-03 15:57:14 +0000596 // First member : / (may exist, if it exists, points to the symbol table )
Shankar Easwaran206252c2012-11-13 18:38:42 +0000597 // Second member : // (may exist, if it exists, points to the string table)
598 // Note : The string table is used if the filename exceeds 15 characters
599 // BSD archive format
Rafael Espindolaa7397592013-07-10 22:07:59 +0000600 // First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table)
601 // There is no string table, if the filename exceeds 15 characters or has a
602 // embedded space, the filename has #1/<size>, The size represents the size
Shankar Easwaran206252c2012-11-13 18:38:42 +0000603 // of the filename that needs to be read after the archive header
604 // COFF archive format
605 // First member : /
606 // Second member : / (provides a directory of symbols)
Rui Ueyama891c0cd2013-06-03 00:27:03 +0000607 // Third member : // (may exist, if it exists, contains the string table)
608 // Note: Microsoft PE/COFF Spec 8.3 says that the third member is present
609 // even if the string table is empty. However, lib.exe does not in fact
610 // seem to create the third member if there's no member whose filename
611 // exceeds 15 characters. So the third member is optional.
Rafael Espindola09a7f602013-07-03 15:57:14 +0000612
Kevin Enderby68806ff2016-06-17 22:16:06 +0000613 if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {
614 if (Name == "__.SYMDEF")
615 Format = K_BSD;
616 else // Name == "__.SYMDEF_64"
617 Format = K_DARWIN64;
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000618 // We know that the symbol table is not an external file, but we still must
619 // check any Expected<> return value.
620 Expected<StringRef> BufOrErr = C->getBuffer();
621 if (!BufOrErr) {
622 Err = BufOrErr.takeError();
623 return;
624 }
625 SymbolTable = BufOrErr.get();
Kevin Enderby268709a2015-11-05 19:24:56 +0000626 if (Increment())
627 return;
628 setFirstRegular(*C);
629
Kevin Enderby0b21d882016-06-29 20:35:44 +0000630 Err = Error::success();
Rafael Espindola09a7f602013-07-03 15:57:14 +0000631 return;
632 }
633
Rafael Espindolaa7397592013-07-10 22:07:59 +0000634 if (Name.startswith("#1/")) {
635 Format = K_BSD;
636 // We know this is BSD, so getName will work since there is no string table.
Kevin Enderby2a715172016-07-29 17:44:13 +0000637 Expected<StringRef> NameOrErr = C->getName();
638 if (!NameOrErr) {
639 Err = NameOrErr.takeError();
Rafael Espindolaa7397592013-07-10 22:07:59 +0000640 return;
Kevin Enderby0b21d882016-06-29 20:35:44 +0000641 }
Rafael Espindola06599282014-06-16 16:08:36 +0000642 Name = NameOrErr.get();
Nick Kledzik9abbcb72014-11-12 01:37:45 +0000643 if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000644 // We know that the symbol table is not an external file, but we still
645 // must check any Expected<> return value.
646 Expected<StringRef> BufOrErr = C->getBuffer();
647 if (!BufOrErr) {
648 Err = BufOrErr.takeError();
649 return;
650 }
651 SymbolTable = BufOrErr.get();
Kevin Enderby268709a2015-11-05 19:24:56 +0000652 if (Increment())
653 return;
Rafael Espindola34ac52d2013-07-12 20:21:39 +0000654 }
Kevin Enderby68806ff2016-06-17 22:16:06 +0000655 else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {
656 Format = K_DARWIN64;
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000657 // We know that the symbol table is not an external file, but we still
658 // must check any Expected<> return value.
659 Expected<StringRef> BufOrErr = C->getBuffer();
660 if (!BufOrErr) {
661 Err = BufOrErr.takeError();
662 return;
663 }
664 SymbolTable = BufOrErr.get();
Kevin Enderby68806ff2016-06-17 22:16:06 +0000665 if (Increment())
666 return;
667 }
Kevin Enderby268709a2015-11-05 19:24:56 +0000668 setFirstRegular(*C);
Rafael Espindolaa7397592013-07-10 22:07:59 +0000669 return;
670 }
671
Simon Atanasyan602706e2015-02-17 18:54:22 +0000672 // MIPS 64-bit ELF archives use a special format of a symbol table.
673 // This format is marked by `ar_name` field equals to "/SYM64/".
674 // For detailed description see page 96 in the following document:
675 // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
676
677 bool has64SymTable = false;
678 if (Name == "/" || Name == "/SYM64/") {
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000679 // We know that the symbol table is not an external file, but we still
680 // must check any Expected<> return value.
681 Expected<StringRef> BufOrErr = C->getBuffer();
682 if (!BufOrErr) {
683 Err = BufOrErr.takeError();
684 return;
685 }
686 SymbolTable = BufOrErr.get();
Simon Atanasyan602706e2015-02-17 18:54:22 +0000687 if (Name == "/SYM64/")
688 has64SymTable = true;
Rafael Espindola09a7f602013-07-03 15:57:14 +0000689
Kevin Enderby268709a2015-11-05 19:24:56 +0000690 if (Increment())
691 return;
692 if (I == E) {
Kevin Enderby0b21d882016-06-29 20:35:44 +0000693 Err = Error::success();
Michael J. Spencerbf82b072013-01-10 00:07:38 +0000694 return;
695 }
Kevin Enderby2a715172016-07-29 17:44:13 +0000696 Expected<StringRef> NameOrErr = C->getRawName();
697 if (!NameOrErr) {
698 Err = NameOrErr.takeError();
699 return;
700 }
701 Name = NameOrErr.get();
Rafael Espindola09a7f602013-07-03 15:57:14 +0000702 }
703
Rafael Espindola4a0bf542013-07-05 03:35:15 +0000704 if (Name == "//") {
Jake Ehrlichf45adc22017-09-20 18:23:01 +0000705 Format = has64SymTable ? K_GNU64 : K_GNU;
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000706 // The string table is never an external member, but we still
707 // must check any Expected<> return value.
708 Expected<StringRef> BufOrErr = C->getBuffer();
709 if (!BufOrErr) {
710 Err = BufOrErr.takeError();
711 return;
712 }
713 StringTable = BufOrErr.get();
Kevin Enderby268709a2015-11-05 19:24:56 +0000714 if (Increment())
715 return;
716 setFirstRegular(*C);
Kevin Enderby0b21d882016-06-29 20:35:44 +0000717 Err = Error::success();
Rafael Espindola09a7f602013-07-03 15:57:14 +0000718 return;
719 }
720
Rafael Espindola4a0bf542013-07-05 03:35:15 +0000721 if (Name[0] != '/') {
Jake Ehrlichf45adc22017-09-20 18:23:01 +0000722 Format = has64SymTable ? K_GNU64 : K_GNU;
Kevin Enderby268709a2015-11-05 19:24:56 +0000723 setFirstRegular(*C);
Kevin Enderby0b21d882016-06-29 20:35:44 +0000724 Err = Error::success();
Rafael Espindola09a7f602013-07-03 15:57:14 +0000725 return;
726 }
727
Rafael Espindola4a0bf542013-07-05 03:35:15 +0000728 if (Name != "/") {
Kevin Enderby0b21d882016-06-29 20:35:44 +0000729 Err = errorCodeToError(object_error::parse_failed);
Rafael Espindola09a7f602013-07-03 15:57:14 +0000730 return;
731 }
732
733 Format = K_COFF;
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000734 // We know that the symbol table is not an external file, but we still
735 // must check any Expected<> return value.
736 Expected<StringRef> BufOrErr = C->getBuffer();
737 if (!BufOrErr) {
738 Err = BufOrErr.takeError();
739 return;
740 }
741 SymbolTable = BufOrErr.get();
Rafael Espindola09a7f602013-07-03 15:57:14 +0000742
Kevin Enderby268709a2015-11-05 19:24:56 +0000743 if (Increment())
744 return;
745
746 if (I == E) {
747 setFirstRegular(*C);
Kevin Enderby0b21d882016-06-29 20:35:44 +0000748 Err = Error::success();
Rafael Espindola09a7f602013-07-03 15:57:14 +0000749 return;
750 }
751
Kevin Enderby2a715172016-07-29 17:44:13 +0000752 NameOrErr = C->getRawName();
753 if (!NameOrErr) {
754 Err = NameOrErr.takeError();
755 return;
756 }
757 Name = NameOrErr.get();
Rafael Espindola09a7f602013-07-03 15:57:14 +0000758
Rafael Espindola34ac52d2013-07-12 20:21:39 +0000759 if (Name == "//") {
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000760 // The string table is never an external member, but we still
761 // must check any Expected<> return value.
762 Expected<StringRef> BufOrErr = C->getBuffer();
763 if (!BufOrErr) {
764 Err = BufOrErr.takeError();
765 return;
766 }
767 StringTable = BufOrErr.get();
Kevin Enderby268709a2015-11-05 19:24:56 +0000768 if (Increment())
769 return;
Rafael Espindola34ac52d2013-07-12 20:21:39 +0000770 }
Rafael Espindola09a7f602013-07-03 15:57:14 +0000771
Kevin Enderby268709a2015-11-05 19:24:56 +0000772 setFirstRegular(*C);
Kevin Enderby0b21d882016-06-29 20:35:44 +0000773 Err = Error::success();
Michael J. Spencera51d7d92011-09-27 19:36:55 +0000774}
775
Lang Hamesaacf2fb2016-07-14 02:24:01 +0000776Archive::child_iterator Archive::child_begin(Error &Err,
777 bool SkipInternal) const {
Rui Ueyamaeabc8ab2016-09-30 17:54:31 +0000778 if (isEmpty())
Rafael Espindola94ad5a12014-01-21 16:09:45 +0000779 return child_end();
Rafael Espindola34ac52d2013-07-12 20:21:39 +0000780
781 if (SkipInternal)
Lang Hamesaacf2fb2016-07-14 02:24:01 +0000782 return child_iterator(Child(this, FirstRegularData,
783 FirstRegularStartOfFile),
784 &Err);
Rafael Espindola34ac52d2013-07-12 20:21:39 +0000785
Rafael Espindola548f2b62014-08-19 18:44:46 +0000786 const char *Loc = Data.getBufferStart() + strlen(Magic);
Kevin Enderbyfa907612016-07-19 20:47:07 +0000787 Child C(this, Loc, &Err);
788 if (Err)
Lang Hamesaacf2fb2016-07-14 02:24:01 +0000789 return child_end();
Lang Hamesaacf2fb2016-07-14 02:24:01 +0000790 return child_iterator(C, &Err);
Michael J. Spencera51d7d92011-09-27 19:36:55 +0000791}
792
Rafael Espindola94ad5a12014-01-21 16:09:45 +0000793Archive::child_iterator Archive::child_end() const {
Lang Hames19118732016-10-05 21:20:00 +0000794 return child_iterator(Child(nullptr, nullptr, nullptr), nullptr);
Michael J. Spencera51d7d92011-09-27 19:36:55 +0000795}
Michael J. Spencerc8a55a62011-11-02 19:33:12 +0000796
Rafael Espindola06599282014-06-16 16:08:36 +0000797StringRef Archive::Symbol::getName() const {
Rafael Espindolaec6cc052015-07-14 01:06:16 +0000798 return Parent->getSymbolTable().begin() + StringIndex;
Michael J. Spencerc8a55a62011-11-02 19:33:12 +0000799}
800
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000801Expected<Archive::Child> Archive::Symbol::getMember() const {
Rafael Espindolaec6cc052015-07-14 01:06:16 +0000802 const char *Buf = Parent->getSymbolTable().begin();
Simon Atanasyan602706e2015-02-17 18:54:22 +0000803 const char *Offsets = Buf;
Jake Ehrlichf45adc22017-09-20 18:23:01 +0000804 if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64)
Simon Atanasyan602706e2015-02-17 18:54:22 +0000805 Offsets += sizeof(uint64_t);
806 else
807 Offsets += sizeof(uint32_t);
Jake Ehrlich9a8a8152017-10-27 21:47:38 +0000808 uint64_t Offset = 0;
Shankar Easwaran206252c2012-11-13 18:38:42 +0000809 if (Parent->kind() == K_GNU) {
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000810 Offset = read32be(Offsets + SymbolIndex * 4);
Jake Ehrlichf45adc22017-09-20 18:23:01 +0000811 } else if (Parent->kind() == K_GNU64) {
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000812 Offset = read64be(Offsets + SymbolIndex * 8);
Shankar Easwaran206252c2012-11-13 18:38:42 +0000813 } else if (Parent->kind() == K_BSD) {
Kevin Enderbyd2ae1152014-07-08 22:10:02 +0000814 // The SymbolIndex is an index into the ranlib structs that start at
815 // Offsets (the first uint32_t is the number of bytes of the ranlib
816 // structs). The ranlib structs are a pair of uint32_t's the first
817 // being a string table offset and the second being the offset into
818 // the archive of the member that defines the symbol. Which is what
819 // is needed here.
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000820 Offset = read32le(Offsets + SymbolIndex * 8 + 4);
Kevin Enderby68806ff2016-06-17 22:16:06 +0000821 } else if (Parent->kind() == K_DARWIN64) {
822 // The SymbolIndex is an index into the ranlib_64 structs that start at
823 // Offsets (the first uint64_t is the number of bytes of the ranlib_64
824 // structs). The ranlib_64 structs are a pair of uint64_t's the first
825 // being a string table offset and the second being the offset into
826 // the archive of the member that defines the symbol. Which is what
827 // is needed here.
828 Offset = read64le(Offsets + SymbolIndex * 16 + 8);
Shankar Easwaran206252c2012-11-13 18:38:42 +0000829 } else {
Michael J. Spencer768a7072012-11-14 00:04:13 +0000830 // Skip offsets.
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000831 uint32_t MemberCount = read32le(Buf);
832 Buf += MemberCount * 4 + 4;
Michael J. Spencer768a7072012-11-14 00:04:13 +0000833
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000834 uint32_t SymbolCount = read32le(Buf);
Michael J. Spencer768a7072012-11-14 00:04:13 +0000835 if (SymbolIndex >= SymbolCount)
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000836 return errorCodeToError(object_error::parse_failed);
Michael J. Spencer768a7072012-11-14 00:04:13 +0000837
Matt Beaumont-Gayf1c2a6b2012-11-14 00:21:27 +0000838 // Skip SymbolCount to get to the indices table.
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000839 const char *Indices = Buf + 4;
Michael J. Spencer768a7072012-11-14 00:04:13 +0000840
841 // Get the index of the offset in the file member offset table for this
842 // symbol.
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000843 uint16_t OffsetIndex = read16le(Indices + SymbolIndex * 2);
Michael J. Spencer768a7072012-11-14 00:04:13 +0000844 // Subtract 1 since OffsetIndex is 1 based.
845 --OffsetIndex;
846
847 if (OffsetIndex >= MemberCount)
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000848 return errorCodeToError(object_error::parse_failed);
Michael J. Spencer768a7072012-11-14 00:04:13 +0000849
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000850 Offset = read32le(Offsets + OffsetIndex * 4);
Shankar Easwaran206252c2012-11-13 18:38:42 +0000851 }
Michael J. Spencerc8a55a62011-11-02 19:33:12 +0000852
Michael J. Spencer768a7072012-11-14 00:04:13 +0000853 const char *Loc = Parent->getData().begin() + Offset;
Mehdi Aminidf0b8bc2016-11-11 04:28:40 +0000854 Error Err = Error::success();
Kevin Enderbyfa907612016-07-19 20:47:07 +0000855 Child C(Parent, Loc, &Err);
856 if (Err)
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000857 return std::move(Err);
Kevin Enderby268709a2015-11-05 19:24:56 +0000858 return C;
Michael J. Spencerc8a55a62011-11-02 19:33:12 +0000859}
860
861Archive::Symbol Archive::Symbol::getNext() const {
862 Symbol t(*this);
Kevin Enderbyd2ae1152014-07-08 22:10:02 +0000863 if (Parent->kind() == K_BSD) {
864 // t.StringIndex is an offset from the start of the __.SYMDEF or
865 // "__.SYMDEF SORTED" member into the string table for the ranlib
866 // struct indexed by t.SymbolIndex . To change t.StringIndex to the
867 // offset in the string table for t.SymbolIndex+1 we subtract the
868 // its offset from the start of the string table for t.SymbolIndex
869 // and add the offset of the string table for t.SymbolIndex+1.
870
871 // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
872 // which is the number of bytes of ranlib structs that follow. The ranlib
873 // structs are a pair of uint32_t's the first being a string table offset
874 // and the second being the offset into the archive of the member that
875 // define the symbol. After that the next uint32_t is the byte count of
876 // the string table followed by the string table.
Rafael Espindolaec6cc052015-07-14 01:06:16 +0000877 const char *Buf = Parent->getSymbolTable().begin();
Kevin Enderbyd2ae1152014-07-08 22:10:02 +0000878 uint32_t RanlibCount = 0;
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000879 RanlibCount = read32le(Buf) / 8;
Kevin Enderbyd2ae1152014-07-08 22:10:02 +0000880 // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount)
881 // don't change the t.StringIndex as we don't want to reference a ranlib
882 // past RanlibCount.
883 if (t.SymbolIndex + 1 < RanlibCount) {
884 const char *Ranlibs = Buf + 4;
885 uint32_t CurRanStrx = 0;
886 uint32_t NextRanStrx = 0;
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000887 CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8);
888 NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8);
Kevin Enderbyd2ae1152014-07-08 22:10:02 +0000889 t.StringIndex -= CurRanStrx;
890 t.StringIndex += NextRanStrx;
891 }
892 } else {
893 // Go to one past next null.
Rafael Espindolaec6cc052015-07-14 01:06:16 +0000894 t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1;
Kevin Enderbyd2ae1152014-07-08 22:10:02 +0000895 }
Michael J. Spencerc8a55a62011-11-02 19:33:12 +0000896 ++t.SymbolIndex;
897 return t;
898}
899
Rafael Espindola94ad5a12014-01-21 16:09:45 +0000900Archive::symbol_iterator Archive::symbol_begin() const {
Rafael Espindolacf48cf22013-07-29 12:40:31 +0000901 if (!hasSymbolTable())
Rafael Espindola51597182013-07-10 20:14:22 +0000902 return symbol_iterator(Symbol(this, 0, 0));
903
Rafael Espindolaec6cc052015-07-14 01:06:16 +0000904 const char *buf = getSymbolTable().begin();
Shankar Easwaran206252c2012-11-13 18:38:42 +0000905 if (kind() == K_GNU) {
906 uint32_t symbol_count = 0;
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000907 symbol_count = read32be(buf);
Shankar Easwaran206252c2012-11-13 18:38:42 +0000908 buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
Jake Ehrlichf45adc22017-09-20 18:23:01 +0000909 } else if (kind() == K_GNU64) {
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000910 uint64_t symbol_count = read64be(buf);
Simon Atanasyan602706e2015-02-17 18:54:22 +0000911 buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));
Shankar Easwaran206252c2012-11-13 18:38:42 +0000912 } else if (kind() == K_BSD) {
Kevin Enderbyd2ae1152014-07-08 22:10:02 +0000913 // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
914 // which is the number of bytes of ranlib structs that follow. The ranlib
915 // structs are a pair of uint32_t's the first being a string table offset
916 // and the second being the offset into the archive of the member that
917 // define the symbol. After that the next uint32_t is the byte count of
918 // the string table followed by the string table.
919 uint32_t ranlib_count = 0;
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000920 ranlib_count = read32le(buf) / 8;
Kevin Enderbyd2ae1152014-07-08 22:10:02 +0000921 const char *ranlibs = buf + 4;
922 uint32_t ran_strx = 0;
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000923 ran_strx = read32le(ranlibs);
Kevin Enderbyd2ae1152014-07-08 22:10:02 +0000924 buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t))));
925 // Skip the byte count of the string table.
926 buf += sizeof(uint32_t);
927 buf += ran_strx;
Kevin Enderby68806ff2016-06-17 22:16:06 +0000928 } else if (kind() == K_DARWIN64) {
929 // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t
930 // which is the number of bytes of ranlib_64 structs that follow. The
931 // ranlib_64 structs are a pair of uint64_t's the first being a string
932 // table offset and the second being the offset into the archive of the
933 // member that define the symbol. After that the next uint64_t is the byte
934 // count of the string table followed by the string table.
935 uint64_t ranlib_count = 0;
936 ranlib_count = read64le(buf) / 16;
937 const char *ranlibs = buf + 8;
938 uint64_t ran_strx = 0;
939 ran_strx = read64le(ranlibs);
940 buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t))));
941 // Skip the byte count of the string table.
942 buf += sizeof(uint64_t);
943 buf += ran_strx;
Shankar Easwaran206252c2012-11-13 18:38:42 +0000944 } else {
945 uint32_t member_count = 0;
946 uint32_t symbol_count = 0;
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000947 member_count = read32le(buf);
Shankar Easwaran206252c2012-11-13 18:38:42 +0000948 buf += 4 + (member_count * 4); // Skip offsets.
Rui Ueyama4d1d4ba2015-03-02 21:19:12 +0000949 symbol_count = read32le(buf);
Shankar Easwaran206252c2012-11-13 18:38:42 +0000950 buf += 4 + (symbol_count * 2); // Skip indices.
951 }
Rafael Espindolaec6cc052015-07-14 01:06:16 +0000952 uint32_t string_start_offset = buf - getSymbolTable().begin();
Michael J. Spencerc8a55a62011-11-02 19:33:12 +0000953 return symbol_iterator(Symbol(this, 0, string_start_offset));
954}
955
Rafael Espindola94ad5a12014-01-21 16:09:45 +0000956Archive::symbol_iterator Archive::symbol_end() const {
Rui Ueyama5a22e842015-05-26 16:20:40 +0000957 return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0));
958}
Rafael Espindola51597182013-07-10 20:14:22 +0000959
Rui Ueyama5a22e842015-05-26 16:20:40 +0000960uint32_t Archive::getNumberOfSymbols() const {
Rafael Espindola8a8ae262015-10-08 18:06:20 +0000961 if (!hasSymbolTable())
962 return 0;
Rafael Espindolaec6cc052015-07-14 01:06:16 +0000963 const char *buf = getSymbolTable().begin();
Rui Ueyama5a22e842015-05-26 16:20:40 +0000964 if (kind() == K_GNU)
965 return read32be(buf);
Jake Ehrlichf45adc22017-09-20 18:23:01 +0000966 if (kind() == K_GNU64)
Rui Ueyama5a22e842015-05-26 16:20:40 +0000967 return read64be(buf);
968 if (kind() == K_BSD)
969 return read32le(buf) / 8;
Kevin Enderby68806ff2016-06-17 22:16:06 +0000970 if (kind() == K_DARWIN64)
971 return read64le(buf) / 16;
Rui Ueyama5a22e842015-05-26 16:20:40 +0000972 uint32_t member_count = 0;
973 member_count = read32le(buf);
974 buf += 4 + (member_count * 4); // Skip offsets.
975 return read32le(buf);
Michael J. Spencerc8a55a62011-11-02 19:33:12 +0000976}
Shankar Easwaran206252c2012-11-13 18:38:42 +0000977
Lang Hames36105c02016-07-14 20:44:27 +0000978Expected<Optional<Archive::Child>> Archive::findSym(StringRef name) const {
Rafael Espindola94ad5a12014-01-21 16:09:45 +0000979 Archive::symbol_iterator bs = symbol_begin();
980 Archive::symbol_iterator es = symbol_end();
Rafael Espindola06599282014-06-16 16:08:36 +0000981
Shankar Easwaran206252c2012-11-13 18:38:42 +0000982 for (; bs != es; ++bs) {
Rafael Espindola06599282014-06-16 16:08:36 +0000983 StringRef SymName = bs->getName();
984 if (SymName == name) {
Lang Hames36105c02016-07-14 20:44:27 +0000985 if (auto MemberOrErr = bs->getMember())
986 return Child(*MemberOrErr);
987 else
Kevin Enderbyb48816b2016-08-03 21:57:47 +0000988 return MemberOrErr.takeError();
Shankar Easwaran206252c2012-11-13 18:38:42 +0000989 }
990 }
Lang Hames36105c02016-07-14 20:44:27 +0000991 return Optional<Child>();
Shankar Easwaran206252c2012-11-13 18:38:42 +0000992}
Rafael Espindolacf48cf22013-07-29 12:40:31 +0000993
Rui Ueyamaeabc8ab2016-09-30 17:54:31 +0000994// Returns true if archive file contains no member file.
995bool Archive::isEmpty() const { return Data.getBufferSize() == 8; }
996
Rafael Espindola2825a232015-10-31 21:03:29 +0000997bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }