1d341c932SEugene Zelenko //===- Archive.cpp - ar File Format implementation ------------------------===//
2d3b7b126SMichael J. Spencer //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d3b7b126SMichael J. Spencer //
7d3b7b126SMichael J. Spencer //===----------------------------------------------------------------------===//
8d3b7b126SMichael J. Spencer //
9d3b7b126SMichael J. Spencer // This file defines the ArchiveObjectFile class.
10d3b7b126SMichael J. Spencer //
11d3b7b126SMichael J. Spencer //===----------------------------------------------------------------------===//
12d3b7b126SMichael J. Spencer 
136bda14b3SChandler Carruth #include "llvm/Object/Archive.h"
14d341c932SEugene Zelenko #include "llvm/ADT/Optional.h"
15747bc07bSRafael Espindola #include "llvm/ADT/SmallString.h"
16d341c932SEugene Zelenko #include "llvm/ADT/StringRef.h"
17747bc07bSRafael Espindola #include "llvm/ADT/Twine.h"
18d341c932SEugene Zelenko #include "llvm/Object/Binary.h"
19d341c932SEugene Zelenko #include "llvm/Object/Error.h"
20d341c932SEugene Zelenko #include "llvm/Support/Chrono.h"
21e03ea9cdSMichael J. Spencer #include "llvm/Support/Endian.h"
22d341c932SEugene Zelenko #include "llvm/Support/Error.h"
23d341c932SEugene Zelenko #include "llvm/Support/ErrorOr.h"
24d341c932SEugene Zelenko #include "llvm/Support/FileSystem.h"
2506624305SKeith Smiley #include "llvm/Support/Host.h"
264fae9329Szhijian #include "llvm/Support/MathExtras.h"
27d3b7b126SMichael J. Spencer #include "llvm/Support/MemoryBuffer.h"
284b83cb53SRafael Espindola #include "llvm/Support/Path.h"
29d341c932SEugene Zelenko #include "llvm/Support/raw_ostream.h"
30d341c932SEugene Zelenko #include <algorithm>
31d341c932SEugene Zelenko #include <cassert>
32d341c932SEugene Zelenko #include <cstddef>
33d341c932SEugene Zelenko #include <cstdint>
34d341c932SEugene Zelenko #include <memory>
35d341c932SEugene Zelenko #include <string>
36d341c932SEugene Zelenko #include <system_error>
37d3b7b126SMichael J. Spencer 
38d3b7b126SMichael J. Spencer using namespace llvm;
39d3b7b126SMichael J. Spencer using namespace object;
403206b79dSRui Ueyama using namespace llvm::support::endian;
41d3b7b126SMichael J. Spencer 
anchor()42a379b181SDavid Blaikie void Archive::anchor() {}
43a379b181SDavid Blaikie 
malformedError(Twine Msg)44e41aaea2SJordan Rupprecht static Error malformedError(Twine Msg) {
456524bd8cSKevin Enderby   std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")";
466524bd8cSKevin Enderby   return make_error<GenericBinaryError>(std::move(StringMsg),
476524bd8cSKevin Enderby                                         object_error::parse_failed);
486524bd8cSKevin Enderby }
496524bd8cSKevin Enderby 
504fae9329Szhijian static Error
createMemberHeaderParseError(const AbstractArchiveMemberHeader * ArMemHeader,const char * RawHeaderPtr,uint64_t Size)514fae9329Szhijian createMemberHeaderParseError(const AbstractArchiveMemberHeader *ArMemHeader,
524fae9329Szhijian                              const char *RawHeaderPtr, uint64_t Size) {
534fae9329Szhijian   StringRef Msg("remaining size of archive too small for next archive "
544fae9329Szhijian                 "member header ");
554fae9329Szhijian 
564fae9329Szhijian   Expected<StringRef> NameOrErr = ArMemHeader->getName(Size);
574fae9329Szhijian   if (NameOrErr)
584fae9329Szhijian     return malformedError(Msg + "for " + *NameOrErr);
594fae9329Szhijian 
604fae9329Szhijian   consumeError(NameOrErr.takeError());
614fae9329Szhijian   uint64_t Offset = RawHeaderPtr - ArMemHeader->Parent->getData().data();
624fae9329Szhijian   return malformedError(Msg + "at offset " + Twine(Offset));
634fae9329Szhijian }
644fae9329Szhijian 
654fae9329Szhijian template <class T, std::size_t N>
getFieldRawString(const T (& Field)[N])664fae9329Szhijian StringRef getFieldRawString(const T (&Field)[N]) {
674fae9329Szhijian   return StringRef(Field, N).rtrim(" ");
684fae9329Szhijian }
694fae9329Szhijian 
704fae9329Szhijian template <class T>
getRawAccessMode() const714fae9329Szhijian StringRef CommonArchiveMemberHeader<T>::getRawAccessMode() const {
724fae9329Szhijian   return getFieldRawString(ArMemHdr->AccessMode);
734fae9329Szhijian }
744fae9329Szhijian 
754fae9329Szhijian template <class T>
getRawLastModified() const764fae9329Szhijian StringRef CommonArchiveMemberHeader<T>::getRawLastModified() const {
774fae9329Szhijian   return getFieldRawString(ArMemHdr->LastModified);
784fae9329Szhijian }
794fae9329Szhijian 
getRawUID() const804fae9329Szhijian template <class T> StringRef CommonArchiveMemberHeader<T>::getRawUID() const {
814fae9329Szhijian   return getFieldRawString(ArMemHdr->UID);
824fae9329Szhijian }
834fae9329Szhijian 
getRawGID() const844fae9329Szhijian template <class T> StringRef CommonArchiveMemberHeader<T>::getRawGID() const {
854fae9329Szhijian   return getFieldRawString(ArMemHdr->GID);
864fae9329Szhijian }
874fae9329Szhijian 
getOffset() const884fae9329Szhijian template <class T> uint64_t CommonArchiveMemberHeader<T>::getOffset() const {
894fae9329Szhijian   return reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
904fae9329Szhijian }
914fae9329Szhijian 
924fae9329Szhijian template class object::CommonArchiveMemberHeader<UnixArMemHdrType>;
934fae9329Szhijian template class object::CommonArchiveMemberHeader<BigArMemHdrType>;
944fae9329Szhijian 
ArchiveMemberHeader(const Archive * Parent,const char * RawHeaderPtr,uint64_t Size,Error * Err)9595b0842eSKevin Enderby ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent,
9695b0842eSKevin Enderby                                          const char *RawHeaderPtr,
9795b0842eSKevin Enderby                                          uint64_t Size, Error *Err)
984fae9329Szhijian     : CommonArchiveMemberHeader<UnixArMemHdrType>(
994fae9329Szhijian           Parent, reinterpret_cast<const UnixArMemHdrType *>(RawHeaderPtr)) {
10095b0842eSKevin Enderby   if (RawHeaderPtr == nullptr)
10195b0842eSKevin Enderby     return;
10295b0842eSKevin Enderby   ErrorAsOutParameter ErrAsOutParam(Err);
10395b0842eSKevin Enderby 
1044fae9329Szhijian   if (Size < getSizeOf()) {
1054fae9329Szhijian     *Err = createMemberHeaderParseError(this, RawHeaderPtr, Size);
10695b0842eSKevin Enderby     return;
10795b0842eSKevin Enderby   }
10895b0842eSKevin Enderby   if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') {
10995b0842eSKevin Enderby     if (Err) {
11095b0842eSKevin Enderby       std::string Buf;
11195b0842eSKevin Enderby       raw_string_ostream OS(Buf);
112e41aaea2SJordan Rupprecht       OS.write_escaped(
113e41aaea2SJordan Rupprecht           StringRef(ArMemHdr->Terminator, sizeof(ArMemHdr->Terminator)));
11495b0842eSKevin Enderby       OS.flush();
11531b07f14SKevin Enderby       std::string Msg("terminator characters in archive member \"" + Buf +
11631b07f14SKevin Enderby                       "\" not the correct \"`\\n\" values for the archive "
11731b07f14SKevin Enderby                       "member header ");
118f4586039SKevin Enderby       Expected<StringRef> NameOrErr = getName(Size);
119f4586039SKevin Enderby       if (!NameOrErr) {
120f4586039SKevin Enderby         consumeError(NameOrErr.takeError());
12195b0842eSKevin Enderby         uint64_t Offset = RawHeaderPtr - Parent->getData().data();
122f4586039SKevin Enderby         *Err = malformedError(Msg + "at offset " + Twine(Offset));
123f4586039SKevin Enderby       } else
12431b07f14SKevin Enderby         *Err = malformedError(Msg + "for " + NameOrErr.get());
12595b0842eSKevin Enderby     }
12695b0842eSKevin Enderby     return;
12795b0842eSKevin Enderby   }
12895b0842eSKevin Enderby }
12995b0842eSKevin Enderby 
BigArchiveMemberHeader(const Archive * Parent,const char * RawHeaderPtr,uint64_t Size,Error * Err)1304fae9329Szhijian BigArchiveMemberHeader::BigArchiveMemberHeader(const Archive *Parent,
1314fae9329Szhijian                                                const char *RawHeaderPtr,
1324fae9329Szhijian                                                uint64_t Size, Error *Err)
1334fae9329Szhijian     : CommonArchiveMemberHeader<BigArMemHdrType>(
1344fae9329Szhijian           Parent, reinterpret_cast<const BigArMemHdrType *>(RawHeaderPtr)) {
1354fae9329Szhijian   if (RawHeaderPtr == nullptr)
1364fae9329Szhijian     return;
1374fae9329Szhijian   ErrorAsOutParameter ErrAsOutParam(Err);
1384fae9329Szhijian 
1394fae9329Szhijian   if (Size < getSizeOf())
1404fae9329Szhijian     *Err = createMemberHeaderParseError(this, RawHeaderPtr, Size);
1414fae9329Szhijian }
1424fae9329Szhijian 
143f4586039SKevin Enderby // This gets the raw name from the ArMemHdr->Name field and checks that it is
144f4586039SKevin Enderby // valid for the kind of archive.  If it is not valid it returns an Error.
getRawName() const145f4586039SKevin Enderby Expected<StringRef> ArchiveMemberHeader::getRawName() const {
146747bc07bSRafael Espindola   char EndCond;
147f4586039SKevin Enderby   auto Kind = Parent->kind();
148f4586039SKevin Enderby   if (Kind == Archive::K_BSD || Kind == Archive::K_DARWIN64) {
149f4586039SKevin Enderby     if (ArMemHdr->Name[0] == ' ') {
150e41aaea2SJordan Rupprecht       uint64_t Offset =
151e41aaea2SJordan Rupprecht           reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
152f4586039SKevin Enderby       return malformedError("name contains a leading space for archive member "
153e41aaea2SJordan Rupprecht                             "header at offset " +
154e41aaea2SJordan Rupprecht                             Twine(Offset));
155f4586039SKevin Enderby     }
156f4586039SKevin Enderby     EndCond = ' ';
157e41aaea2SJordan Rupprecht   } else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#')
158747bc07bSRafael Espindola     EndCond = ' ';
159747bc07bSRafael Espindola   else
160747bc07bSRafael Espindola     EndCond = '/';
161d341c932SEugene Zelenko   StringRef::size_type end =
162d341c932SEugene Zelenko       StringRef(ArMemHdr->Name, sizeof(ArMemHdr->Name)).find(EndCond);
163d341c932SEugene Zelenko   if (end == StringRef::npos)
16495b0842eSKevin Enderby     end = sizeof(ArMemHdr->Name);
16595b0842eSKevin Enderby   assert(end <= sizeof(ArMemHdr->Name) && end > 0);
166747bc07bSRafael Espindola   // Don't include the EndCond if there is one.
167d341c932SEugene Zelenko   return StringRef(ArMemHdr->Name, end);
168747bc07bSRafael Espindola }
169747bc07bSRafael Espindola 
1704fae9329Szhijian Expected<uint64_t>
getArchiveMemberDecField(Twine FieldName,const StringRef RawField,const Archive * Parent,const AbstractArchiveMemberHeader * MemHeader)1714fae9329Szhijian getArchiveMemberDecField(Twine FieldName, const StringRef RawField,
1724fae9329Szhijian                          const Archive *Parent,
1734fae9329Szhijian                          const AbstractArchiveMemberHeader *MemHeader) {
1744fae9329Szhijian   uint64_t Value;
1754fae9329Szhijian   if (RawField.getAsInteger(10, Value)) {
1764fae9329Szhijian     uint64_t Offset = MemHeader->getOffset();
1774fae9329Szhijian     return malformedError("characters in " + FieldName +
1784fae9329Szhijian                           " field in archive member header are not "
1794fae9329Szhijian                           "all decimal numbers: '" +
1804fae9329Szhijian                           RawField +
1814fae9329Szhijian                           "' for the archive "
1824fae9329Szhijian                           "member header at offset " +
1834fae9329Szhijian                           Twine(Offset));
1844fae9329Szhijian   }
1854fae9329Szhijian   return Value;
1864fae9329Szhijian }
1874fae9329Szhijian 
1884fae9329Szhijian Expected<uint64_t>
getArchiveMemberOctField(Twine FieldName,const StringRef RawField,const Archive * Parent,const AbstractArchiveMemberHeader * MemHeader)1894fae9329Szhijian getArchiveMemberOctField(Twine FieldName, const StringRef RawField,
1904fae9329Szhijian                          const Archive *Parent,
1914fae9329Szhijian                          const AbstractArchiveMemberHeader *MemHeader) {
1924fae9329Szhijian   uint64_t Value;
1934fae9329Szhijian   if (RawField.getAsInteger(8, Value)) {
1944fae9329Szhijian     uint64_t Offset = MemHeader->getOffset();
1954fae9329Szhijian     return malformedError("characters in " + FieldName +
1964fae9329Szhijian                           " field in archive member header are not "
1974fae9329Szhijian                           "all octal numbers: '" +
1984fae9329Szhijian                           RawField +
1994fae9329Szhijian                           "' for the archive "
2004fae9329Szhijian                           "member header at offset " +
2014fae9329Szhijian                           Twine(Offset));
2024fae9329Szhijian   }
2034fae9329Szhijian   return Value;
2044fae9329Szhijian }
2054fae9329Szhijian 
getRawName() const2064fae9329Szhijian Expected<StringRef> BigArchiveMemberHeader::getRawName() const {
2074fae9329Szhijian   Expected<uint64_t> NameLenOrErr = getArchiveMemberDecField(
2084fae9329Szhijian       "NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);
2094fae9329Szhijian   if (!NameLenOrErr)
2104fae9329Szhijian     // TODO: Out-of-line.
2114fae9329Szhijian     return NameLenOrErr.takeError();
2124fae9329Szhijian   uint64_t NameLen = NameLenOrErr.get();
2134fae9329Szhijian 
2144fae9329Szhijian   // If the name length is odd, pad with '\0' to get an even length. After
2154fae9329Szhijian   // padding, there is the name terminator "`\n".
2164fae9329Szhijian   uint64_t NameLenWithPadding = alignTo(NameLen, 2);
2174fae9329Szhijian   StringRef NameTerminator = "`\n";
2184fae9329Szhijian   StringRef NameStringWithNameTerminator =
2194fae9329Szhijian       StringRef(ArMemHdr->Name, NameLenWithPadding + NameTerminator.size());
2204fae9329Szhijian   if (!NameStringWithNameTerminator.endswith(NameTerminator)) {
2214fae9329Szhijian     uint64_t Offset =
2224fae9329Szhijian         reinterpret_cast<const char *>(ArMemHdr->Name + NameLenWithPadding) -
2234fae9329Szhijian         Parent->getData().data();
2244fae9329Szhijian     // TODO: Out-of-line.
2254fae9329Szhijian     return malformedError(
2264fae9329Szhijian         "name does not have name terminator \"`\\n\" for archive member"
2274fae9329Szhijian         "header at offset " +
2284fae9329Szhijian         Twine(Offset));
2294fae9329Szhijian   }
2304fae9329Szhijian   return StringRef(ArMemHdr->Name, NameLen);
2314fae9329Szhijian }
2324fae9329Szhijian 
233f4586039SKevin Enderby // member including the header, so the size of any name following the header
234f4586039SKevin Enderby // is checked to make sure it does not overflow.
getName(uint64_t Size) const235f4586039SKevin Enderby Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
236f4586039SKevin Enderby 
237f4586039SKevin Enderby   // This can be called from the ArchiveMemberHeader constructor when the
238f4586039SKevin Enderby   // archive header is truncated to produce an error message with the name.
239f4586039SKevin Enderby   // Make sure the name field is not truncated.
2404fae9329Szhijian   if (Size < offsetof(UnixArMemHdrType, Name) + sizeof(ArMemHdr->Name)) {
241e41aaea2SJordan Rupprecht     uint64_t ArchiveOffset =
242e41aaea2SJordan Rupprecht         reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
243f4586039SKevin Enderby     return malformedError("archive header truncated before the name field "
244f4586039SKevin Enderby                           "for archive member header at offset " +
245f4586039SKevin Enderby                           Twine(ArchiveOffset));
246f4586039SKevin Enderby   }
247f4586039SKevin Enderby 
248f4586039SKevin Enderby   // The raw name itself can be invalid.
249f4586039SKevin Enderby   Expected<StringRef> NameOrErr = getRawName();
250f4586039SKevin Enderby   if (!NameOrErr)
251f4586039SKevin Enderby     return NameOrErr.takeError();
252f4586039SKevin Enderby   StringRef Name = NameOrErr.get();
253f4586039SKevin Enderby 
254f4586039SKevin Enderby   // Check if it's a special name.
255f4586039SKevin Enderby   if (Name[0] == '/') {
256f4586039SKevin Enderby     if (Name.size() == 1) // Linker member.
257f4586039SKevin Enderby       return Name;
258f4586039SKevin Enderby     if (Name.size() == 2 && Name[1] == '/') // String table.
259f4586039SKevin Enderby       return Name;
2602397f671SPavel Samolysov     // System libraries from the Windows SDK for Windows 11 contain this symbol.
2612397f671SPavel Samolysov     // It looks like a CFG guard: we just skip it for now.
2622397f671SPavel Samolysov     if (Name.equals("/<XFGHASHMAP>/"))
2632397f671SPavel Samolysov       return Name;
264c1d3cfeaSPengxuan Zheng     // Some libraries (e.g., arm64rt.lib) from the Windows WDK
265c1d3cfeaSPengxuan Zheng     // (version 10.0.22000.0) contain this undocumented special member.
266c1d3cfeaSPengxuan Zheng     if (Name.equals("/<ECSYMBOLS>/"))
267c1d3cfeaSPengxuan Zheng       return Name;
268f4586039SKevin Enderby     // It's a long name.
269f4586039SKevin Enderby     // Get the string table offset.
270f4586039SKevin Enderby     std::size_t StringOffset;
271f4586039SKevin Enderby     if (Name.substr(1).rtrim(' ').getAsInteger(10, StringOffset)) {
272f4586039SKevin Enderby       std::string Buf;
273f4586039SKevin Enderby       raw_string_ostream OS(Buf);
27431b07f14SKevin Enderby       OS.write_escaped(Name.substr(1).rtrim(' '));
275f4586039SKevin Enderby       OS.flush();
276e41aaea2SJordan Rupprecht       uint64_t ArchiveOffset =
277e41aaea2SJordan Rupprecht           reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
278f4586039SKevin Enderby       return malformedError("long name offset characters after the '/' are "
279e41aaea2SJordan Rupprecht                             "not all decimal numbers: '" +
280e41aaea2SJordan Rupprecht                             Buf + "' for archive member header at offset " +
281f4586039SKevin Enderby                             Twine(ArchiveOffset));
282f4586039SKevin Enderby     }
283f4586039SKevin Enderby 
284f4586039SKevin Enderby     // Verify it.
285f4586039SKevin Enderby     if (StringOffset >= Parent->getStringTable().size()) {
286e41aaea2SJordan Rupprecht       uint64_t ArchiveOffset =
287e41aaea2SJordan Rupprecht           reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
288e41aaea2SJordan Rupprecht       return malformedError("long name offset " + Twine(StringOffset) +
289e41aaea2SJordan Rupprecht                             " past the end of the string table for archive "
290e41aaea2SJordan Rupprecht                             "member header at offset " +
291e41aaea2SJordan Rupprecht                             Twine(ArchiveOffset));
292f4586039SKevin Enderby     }
293f4586039SKevin Enderby 
294f4586039SKevin Enderby     // GNU long file names end with a "/\n".
295f4586039SKevin Enderby     if (Parent->kind() == Archive::K_GNU ||
2961b30d63aSJake Ehrlich         Parent->kind() == Archive::K_GNU64) {
2975e6e6cc7SHans Wennborg       size_t End = Parent->getStringTable().find('\n', /*From=*/StringOffset);
2985e6e6cc7SHans Wennborg       if (End == StringRef::npos || End < 1 ||
2995e6e6cc7SHans Wennborg           Parent->getStringTable()[End - 1] != '/') {
3005e6e6cc7SHans Wennborg         return malformedError("string table at long name offset " +
3015e6e6cc7SHans Wennborg                               Twine(StringOffset) + "not terminated");
302f4586039SKevin Enderby       }
3035e6e6cc7SHans Wennborg       return Parent->getStringTable().slice(StringOffset, End - 1);
3045e6e6cc7SHans Wennborg     }
3055e6e6cc7SHans Wennborg     return Parent->getStringTable().begin() + StringOffset;
306cd842eccSDavid Blaikie   }
307cd842eccSDavid Blaikie 
308cd842eccSDavid Blaikie   if (Name.startswith("#1/")) {
309f4586039SKevin Enderby     uint64_t NameLength;
310f4586039SKevin Enderby     if (Name.substr(3).rtrim(' ').getAsInteger(10, NameLength)) {
311f4586039SKevin Enderby       std::string Buf;
312f4586039SKevin Enderby       raw_string_ostream OS(Buf);
31331b07f14SKevin Enderby       OS.write_escaped(Name.substr(3).rtrim(' '));
314f4586039SKevin Enderby       OS.flush();
315e41aaea2SJordan Rupprecht       uint64_t ArchiveOffset =
316e41aaea2SJordan Rupprecht           reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
317f4586039SKevin Enderby       return malformedError("long name length characters after the #1/ are "
318e41aaea2SJordan Rupprecht                             "not all decimal numbers: '" +
319e41aaea2SJordan Rupprecht                             Buf + "' for archive member header at offset " +
320f4586039SKevin Enderby                             Twine(ArchiveOffset));
321f4586039SKevin Enderby     }
322f4586039SKevin Enderby     if (getSizeOf() + NameLength > Size) {
323e41aaea2SJordan Rupprecht       uint64_t ArchiveOffset =
324e41aaea2SJordan Rupprecht           reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
325f4586039SKevin Enderby       return malformedError("long name length: " + Twine(NameLength) +
326f4586039SKevin Enderby                             " extends past the end of the member or archive "
327f4586039SKevin Enderby                             "for archive member header at offset " +
328f4586039SKevin Enderby                             Twine(ArchiveOffset));
329f4586039SKevin Enderby     }
330f4586039SKevin Enderby     return StringRef(reinterpret_cast<const char *>(ArMemHdr) + getSizeOf(),
331e41aaea2SJordan Rupprecht                      NameLength)
332e41aaea2SJordan Rupprecht         .rtrim('\0');
333cd842eccSDavid Blaikie   }
334cd842eccSDavid Blaikie 
335f4586039SKevin Enderby   // It is not a long name so trim the blanks at the end of the name.
336cd842eccSDavid Blaikie   if (Name[Name.size() - 1] != '/')
337f4586039SKevin Enderby     return Name.rtrim(' ');
338cd842eccSDavid Blaikie 
339f4586039SKevin Enderby   // It's a simple name.
340cd842eccSDavid Blaikie   return Name.drop_back(1);
341f4586039SKevin Enderby }
342f4586039SKevin Enderby 
getName(uint64_t Size) const3434fae9329Szhijian Expected<StringRef> BigArchiveMemberHeader::getName(uint64_t Size) const {
3444fae9329Szhijian   return getRawName();
3453130134dSzhijian }
3462164c543Szhijian 
getSize() const3474fae9329Szhijian Expected<uint64_t> ArchiveMemberHeader::getSize() const {
3484fae9329Szhijian   return getArchiveMemberDecField("size", getFieldRawString(ArMemHdr->Size),
3494fae9329Szhijian                                   Parent, this);
3502164c543Szhijian }
3514fae9329Szhijian 
getSize() const3524fae9329Szhijian Expected<uint64_t> BigArchiveMemberHeader::getSize() const {
3534fae9329Szhijian   Expected<uint64_t> SizeOrErr = getArchiveMemberDecField(
3544fae9329Szhijian       "size", getFieldRawString(ArMemHdr->Size), Parent, this);
3554fae9329Szhijian   if (!SizeOrErr)
3564fae9329Szhijian     return SizeOrErr.takeError();
3574fae9329Szhijian 
3584fae9329Szhijian   Expected<uint64_t> NameLenOrErr = getRawNameSize();
3594fae9329Szhijian   if (!NameLenOrErr)
3604fae9329Szhijian     return NameLenOrErr.takeError();
3614fae9329Szhijian 
3624fae9329Szhijian   return *SizeOrErr + alignTo(*NameLenOrErr, 2);
3634fae9329Szhijian }
3644fae9329Szhijian 
getRawNameSize() const3654fae9329Szhijian Expected<uint64_t> BigArchiveMemberHeader::getRawNameSize() const {
3664fae9329Szhijian   return getArchiveMemberDecField(
3674fae9329Szhijian       "NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);
3684fae9329Szhijian }
3694fae9329Szhijian 
getNextOffset() const3704fae9329Szhijian Expected<uint64_t> BigArchiveMemberHeader::getNextOffset() const {
3714fae9329Szhijian   return getArchiveMemberDecField(
3724fae9329Szhijian       "NextOffset", getFieldRawString(ArMemHdr->NextOffset), Parent, this);
3734fae9329Szhijian }
3744fae9329Szhijian 
getAccessMode() const3754fae9329Szhijian Expected<sys::fs::perms> AbstractArchiveMemberHeader::getAccessMode() const {
3764fae9329Szhijian   Expected<uint64_t> AccessModeOrErr =
3774fae9329Szhijian       getArchiveMemberOctField("AccessMode", getRawAccessMode(), Parent, this);
3784fae9329Szhijian   if (!AccessModeOrErr)
3794fae9329Szhijian     return AccessModeOrErr.takeError();
3804fae9329Szhijian   return static_cast<sys::fs::perms>(*AccessModeOrErr);
3818115e1daSRafael Espindola }
3828115e1daSRafael Espindola 
383bff47b51SPavel Labath Expected<sys::TimePoint<std::chrono::seconds>>
getLastModified() const3844fae9329Szhijian AbstractArchiveMemberHeader::getLastModified() const {
3854fae9329Szhijian   Expected<uint64_t> SecondsOrErr = getArchiveMemberDecField(
3864fae9329Szhijian       "LastModified", getRawLastModified(), Parent, this);
3874fae9329Szhijian 
3884fae9329Szhijian   if (!SecondsOrErr)
3894fae9329Szhijian     return SecondsOrErr.takeError();
3904fae9329Szhijian 
3914fae9329Szhijian   return sys::toTimePoint(*SecondsOrErr);
3924031d9f8SVedant Kumar }
3938115e1daSRafael Espindola 
getUID() const3944fae9329Szhijian Expected<unsigned> AbstractArchiveMemberHeader::getUID() const {
3954fae9329Szhijian   StringRef User = getRawUID();
396aecbdf70SSaleem Abdulrasool   if (User.empty())
397aecbdf70SSaleem Abdulrasool     return 0;
3984fae9329Szhijian   return getArchiveMemberDecField("UID", User, Parent, this);
3998115e1daSRafael Espindola }
4008115e1daSRafael Espindola 
getGID() const4014fae9329Szhijian Expected<unsigned> AbstractArchiveMemberHeader::getGID() const {
4024fae9329Szhijian   StringRef Group = getRawGID();
403aecbdf70SSaleem Abdulrasool   if (Group.empty())
404aecbdf70SSaleem Abdulrasool     return 0;
4054fae9329Szhijian   return getArchiveMemberDecField("GID", Group, Parent, this);
4064031d9f8SVedant Kumar }
4074fae9329Szhijian 
isThin() const4084fae9329Szhijian Expected<bool> ArchiveMemberHeader::isThin() const {
4094fae9329Szhijian   Expected<StringRef> NameOrErr = getRawName();
4104fae9329Szhijian   if (!NameOrErr)
4114fae9329Szhijian     return NameOrErr.takeError();
4124fae9329Szhijian   StringRef Name = NameOrErr.get();
4134fae9329Szhijian   return Parent->isThin() && Name != "/" && Name != "//" && Name != "/SYM64/";
4144fae9329Szhijian }
4154fae9329Szhijian 
getNextChildLoc() const4164fae9329Szhijian Expected<const char *> ArchiveMemberHeader::getNextChildLoc() const {
4174fae9329Szhijian   uint64_t Size = getSizeOf();
4184fae9329Szhijian   Expected<bool> isThinOrErr = isThin();
4194fae9329Szhijian   if (!isThinOrErr)
4204fae9329Szhijian     return isThinOrErr.takeError();
4214fae9329Szhijian 
4224fae9329Szhijian   bool isThin = isThinOrErr.get();
4234fae9329Szhijian   if (!isThin) {
4244fae9329Szhijian     Expected<uint64_t> MemberSize = getSize();
4254fae9329Szhijian     if (!MemberSize)
4264fae9329Szhijian       return MemberSize.takeError();
4274fae9329Szhijian 
4284fae9329Szhijian     Size += MemberSize.get();
4294fae9329Szhijian   }
4304fae9329Szhijian 
4314fae9329Szhijian   // If Size is odd, add 1 to make it even.
4324fae9329Szhijian   const char *NextLoc =
4334fae9329Szhijian       reinterpret_cast<const char *>(ArMemHdr) + alignTo(Size, 2);
4344fae9329Szhijian 
4354fae9329Szhijian   if (NextLoc == Parent->getMemoryBufferRef().getBufferEnd())
4364fae9329Szhijian     return nullptr;
4374fae9329Szhijian 
4384fae9329Szhijian   return NextLoc;
4394fae9329Szhijian }
4404fae9329Szhijian 
getNextChildLoc() const4414fae9329Szhijian Expected<const char *> BigArchiveMemberHeader::getNextChildLoc() const {
4424fae9329Szhijian   if (getOffset() ==
4434fae9329Szhijian       static_cast<const BigArchive *>(Parent)->getLastChildOffset())
4444fae9329Szhijian     return nullptr;
4454fae9329Szhijian 
4464fae9329Szhijian   Expected<uint64_t> NextOffsetOrErr = getNextOffset();
4474fae9329Szhijian   if (!NextOffsetOrErr)
4484fae9329Szhijian     return NextOffsetOrErr.takeError();
4494fae9329Szhijian   return Parent->getData().data() + NextOffsetOrErr.get();
4508115e1daSRafael Espindola }
4518115e1daSRafael Espindola 
Child(const Archive * Parent,StringRef Data,uint16_t StartOfFile)45243358761SRafael Espindola Archive::Child::Child(const Archive *Parent, StringRef Data,
45343358761SRafael Espindola                       uint16_t StartOfFile)
4544fae9329Szhijian     : Parent(Parent), Data(Data), StartOfFile(StartOfFile) {
4554fae9329Szhijian   Header = Parent->createArchiveMemberHeader(Data.data(), Data.size(), nullptr);
4564fae9329Szhijian }
45743358761SRafael Espindola 
Child(const Archive * Parent,const char * Start,Error * Err)4586524bd8cSKevin Enderby Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
4594fae9329Szhijian     : Parent(Parent) {
4604fae9329Szhijian   if (!Start) {
4614fae9329Szhijian     Header = nullptr;
4621b9d323aSFlorian Hahn     return;
4634fae9329Szhijian   }
4644fae9329Szhijian 
4654fae9329Szhijian   Header = Parent->createArchiveMemberHeader(
4664fae9329Szhijian       Start,
4674fae9329Szhijian       Parent ? Parent->getData().size() - (Start - Parent->getData().data())
4684fae9329Szhijian              : 0,
4694fae9329Szhijian       Err);
4702c182700SKevin Enderby 
4712c182700SKevin Enderby   // If we are pointed to real data, Start is not a nullptr, then there must be
4722c182700SKevin Enderby   // a non-null Err pointer available to report malformed data on.  Only in
4732c182700SKevin Enderby   // the case sentinel value is being constructed is Err is permitted to be a
4742c182700SKevin Enderby   // nullptr.
4752c182700SKevin Enderby   assert(Err && "Err can't be nullptr if Start is not a nullptr");
4762c182700SKevin Enderby 
4775e51a2e3SLang Hames   ErrorAsOutParameter ErrAsOutParam(Err);
4780f3de64dSRafael Espindola 
4792c182700SKevin Enderby   // If there was an error in the construction of the Header
4802c182700SKevin Enderby   // then just return with the error now set.
4812c182700SKevin Enderby   if (*Err)
48295b0842eSKevin Enderby     return;
48395b0842eSKevin Enderby 
4844fae9329Szhijian   uint64_t Size = Header->getSizeOf();
4859d102064SRafael Espindola   Data = StringRef(Start, Size);
486f4586039SKevin Enderby   Expected<bool> isThinOrErr = isThinMember();
487f4586039SKevin Enderby   if (!isThinOrErr) {
488f4586039SKevin Enderby     *Err = isThinOrErr.takeError();
489f4586039SKevin Enderby     return;
490f4586039SKevin Enderby   }
491f4586039SKevin Enderby   bool isThin = isThinOrErr.get();
492f4586039SKevin Enderby   if (!isThin) {
4936524bd8cSKevin Enderby     Expected<uint64_t> MemberSize = getRawSize();
4946524bd8cSKevin Enderby     if (!MemberSize) {
4956524bd8cSKevin Enderby       *Err = MemberSize.takeError();
4967a96942aSKevin Enderby       return;
4976524bd8cSKevin Enderby     }
4987a96942aSKevin Enderby     Size += MemberSize.get();
499be9ab268SRafael Espindola     Data = StringRef(Start, Size);
500be9ab268SRafael Espindola   }
5010f3de64dSRafael Espindola 
502747bc07bSRafael Espindola   // Setup StartOfFile and PaddingBytes.
5034fae9329Szhijian   StartOfFile = Header->getSizeOf();
504747bc07bSRafael Espindola   // Don't include attached name.
505f4586039SKevin Enderby   Expected<StringRef> NameOrErr = getRawName();
506f4586039SKevin Enderby   if (!NameOrErr) {
507f4586039SKevin Enderby     *Err = NameOrErr.takeError();
508f4586039SKevin Enderby     return;
509f4586039SKevin Enderby   }
510f4586039SKevin Enderby   StringRef Name = NameOrErr.get();
5114fae9329Szhijian 
5124fae9329Szhijian   if (Parent->kind() == Archive::K_AIXBIG) {
5134fae9329Szhijian     // The actual start of the file is after the name and any necessary
5144fae9329Szhijian     // even-alignment padding.
5154fae9329Szhijian     StartOfFile += ((Name.size() + 1) >> 1) << 1;
5164fae9329Szhijian   } else if (Name.startswith("#1/")) {
517747bc07bSRafael Espindola     uint64_t NameSize;
5184fae9329Szhijian     StringRef RawNameSize = Name.substr(3).rtrim(' ');
5194fae9329Szhijian     if (RawNameSize.getAsInteger(10, NameSize)) {
520f4586039SKevin Enderby       uint64_t Offset = Start - Parent->getData().data();
521f4586039SKevin Enderby       *Err = malformedError("long name length characters after the #1/ are "
522e41aaea2SJordan Rupprecht                             "not all decimal numbers: '" +
5234fae9329Szhijian                             RawNameSize +
5244fae9329Szhijian                             "' for archive member header at offset " +
525f4586039SKevin Enderby                             Twine(Offset));
526f4586039SKevin Enderby       return;
527f4586039SKevin Enderby     }
528747bc07bSRafael Espindola     StartOfFile += NameSize;
529747bc07bSRafael Espindola   }
530747bc07bSRafael Espindola }
531747bc07bSRafael Espindola 
getSize() const5326524bd8cSKevin Enderby Expected<uint64_t> Archive::Child::getSize() const {
533326bc1daSJames Henderson   if (Parent->IsThin)
5344fae9329Szhijian     return Header->getSize();
5359d102064SRafael Espindola   return Data.size() - StartOfFile;
5369d102064SRafael Espindola }
5379d102064SRafael Espindola 
getRawSize() const5386524bd8cSKevin Enderby Expected<uint64_t> Archive::Child::getRawSize() const {
5394fae9329Szhijian   return Header->getSize();
54013023a1aSKevin Enderby }
54113023a1aSKevin Enderby 
isThinMember() const5424fae9329Szhijian Expected<bool> Archive::Child::isThinMember() const { return Header->isThin(); }
543be9ab268SRafael Espindola 
getFullName() const54427e85bd0SKevin Enderby Expected<std::string> Archive::Child::getFullName() const {
545f4586039SKevin Enderby   Expected<bool> isThin = isThinMember();
546f4586039SKevin Enderby   if (!isThin)
54727e85bd0SKevin Enderby     return isThin.takeError();
548f4586039SKevin Enderby   assert(isThin.get());
549f4586039SKevin Enderby   Expected<StringRef> NameOrErr = getName();
550f4586039SKevin Enderby   if (!NameOrErr)
55127e85bd0SKevin Enderby     return NameOrErr.takeError();
552694210cdSRafael Espindola   StringRef Name = *NameOrErr;
553694210cdSRafael Espindola   if (sys::path::is_absolute(Name))
554adcd0268SBenjamin Kramer     return std::string(Name);
555694210cdSRafael Espindola 
556694210cdSRafael Espindola   SmallString<128> FullName = sys::path::parent_path(
557694210cdSRafael Espindola       Parent->getMemoryBufferRef().getBufferIdentifier());
558694210cdSRafael Espindola   sys::path::append(FullName, Name);
559adcd0268SBenjamin Kramer   return std::string(FullName.str());
560694210cdSRafael Espindola }
561694210cdSRafael Espindola 
getBuffer() const56227e85bd0SKevin Enderby Expected<StringRef> Archive::Child::getBuffer() const {
563f4586039SKevin Enderby   Expected<bool> isThinOrErr = isThinMember();
564f4586039SKevin Enderby   if (!isThinOrErr)
56527e85bd0SKevin Enderby     return isThinOrErr.takeError();
566f4586039SKevin Enderby   bool isThin = isThinOrErr.get();
567f4586039SKevin Enderby   if (!isThin) {
568326bc1daSJames Henderson     Expected<uint64_t> Size = getSize();
5696524bd8cSKevin Enderby     if (!Size)
57027e85bd0SKevin Enderby       return Size.takeError();
5717a96942aSKevin Enderby     return StringRef(Data.data() + StartOfFile, Size.get());
5727a96942aSKevin Enderby   }
57327e85bd0SKevin Enderby   Expected<std::string> FullNameOrErr = getFullName();
57427e85bd0SKevin Enderby   if (!FullNameOrErr)
57527e85bd0SKevin Enderby     return FullNameOrErr.takeError();
57627e85bd0SKevin Enderby   const std::string &FullName = *FullNameOrErr;
5774b83cb53SRafael Espindola   ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName);
5784b83cb53SRafael Espindola   if (std::error_code EC = Buf.getError())
57927e85bd0SKevin Enderby     return errorCodeToError(EC);
5804b83cb53SRafael Espindola   Parent->ThinBuffers.push_back(std::move(*Buf));
5814b83cb53SRafael Espindola   return Parent->ThinBuffers.back()->getBuffer();
5824b83cb53SRafael Espindola }
5834b83cb53SRafael Espindola 
getNext() const5846524bd8cSKevin Enderby Expected<Archive::Child> Archive::Child::getNext() const {
5854fae9329Szhijian   Expected<const char *> NextLocOrErr = Header->getNextChildLoc();
5864fae9329Szhijian   if (!NextLocOrErr)
5874fae9329Szhijian     return NextLocOrErr.takeError();
588747bc07bSRafael Espindola 
5894fae9329Szhijian   const char *NextLoc = *NextLocOrErr;
590747bc07bSRafael Espindola 
5917a96942aSKevin Enderby   // Check to see if this is at the end of the archive.
5924fae9329Szhijian   if (NextLoc == nullptr)
593a5e873e2SLang Hames     return Child(nullptr, nullptr, nullptr);
594747bc07bSRafael Espindola 
5957a96942aSKevin Enderby   // Check to see if this is past the end of the archive.
59695b0842eSKevin Enderby   if (NextLoc > Parent->Data.getBufferEnd()) {
59731b07f14SKevin Enderby     std::string Msg("offset to next archive member past the end of the archive "
59831b07f14SKevin Enderby                     "after member ");
599f4586039SKevin Enderby     Expected<StringRef> NameOrErr = getName();
600f4586039SKevin Enderby     if (!NameOrErr) {
601f4586039SKevin Enderby       consumeError(NameOrErr.takeError());
60295b0842eSKevin Enderby       uint64_t Offset = Data.data() - Parent->getData().data();
60395b0842eSKevin Enderby       return malformedError(Msg + "at offset " + Twine(Offset));
60495b0842eSKevin Enderby     } else
60531b07f14SKevin Enderby       return malformedError(Msg + NameOrErr.get());
60695b0842eSKevin Enderby   }
6077a96942aSKevin Enderby 
60841af4309SMehdi Amini   Error Err = Error::success();
6096524bd8cSKevin Enderby   Child Ret(Parent, NextLoc, &Err);
6106524bd8cSKevin Enderby   if (Err)
611c55cf4afSBill Wendling     return std::move(Err);
6127a96942aSKevin Enderby   return Ret;
613747bc07bSRafael Espindola }
614747bc07bSRafael Espindola 
getChildOffset() const61513023a1aSKevin Enderby uint64_t Archive::Child::getChildOffset() const {
61613023a1aSKevin Enderby   const char *a = Parent->Data.getBuffer().data();
61713023a1aSKevin Enderby   const char *c = Data.data();
61813023a1aSKevin Enderby   uint64_t offset = c - a;
61913023a1aSKevin Enderby   return offset;
62013023a1aSKevin Enderby }
62113023a1aSKevin Enderby 
getName() const622f4586039SKevin Enderby Expected<StringRef> Archive::Child::getName() const {
623f4586039SKevin Enderby   Expected<uint64_t> RawSizeOrErr = getRawSize();
624f4586039SKevin Enderby   if (!RawSizeOrErr)
625f4586039SKevin Enderby     return RawSizeOrErr.takeError();
626f4586039SKevin Enderby   uint64_t RawSize = RawSizeOrErr.get();
6274fae9329Szhijian   Expected<StringRef> NameOrErr =
6284fae9329Szhijian       Header->getName(Header->getSizeOf() + RawSize);
629f4586039SKevin Enderby   if (!NameOrErr)
630f4586039SKevin Enderby     return NameOrErr.takeError();
631f4586039SKevin Enderby   StringRef Name = NameOrErr.get();
632f4586039SKevin Enderby   return Name;
633d3b7b126SMichael J. Spencer }
634d3b7b126SMichael J. Spencer 
getMemoryBufferRef() const635f4586039SKevin Enderby Expected<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {
636f4586039SKevin Enderby   Expected<StringRef> NameOrErr = getName();
637f4586039SKevin Enderby   if (!NameOrErr)
638f4586039SKevin Enderby     return NameOrErr.takeError();
639ae460027SRafael Espindola   StringRef Name = NameOrErr.get();
64027e85bd0SKevin Enderby   Expected<StringRef> Buf = getBuffer();
64127e85bd0SKevin Enderby   if (!Buf)
642d3a7e9d1SJordan Rupprecht     return createFileError(Name, Buf.takeError());
6434b83cb53SRafael Espindola   return MemoryBufferRef(*Buf, Name);
644747bc07bSRafael Espindola }
645747bc07bSRafael Espindola 
646ac9e1555SKevin Enderby Expected<std::unique_ptr<Binary>>
getAsBinary(LLVMContext * Context) const647ae460027SRafael Espindola Archive::Child::getAsBinary(LLVMContext *Context) const {
648f4586039SKevin Enderby   Expected<MemoryBufferRef> BuffOrErr = getMemoryBufferRef();
649f4586039SKevin Enderby   if (!BuffOrErr)
650f4586039SKevin Enderby     return BuffOrErr.takeError();
651c3f9b5a5SRafael Espindola 
6523fcdf6aeSKevin Enderby   auto BinaryOrErr = createBinary(BuffOrErr.get(), Context);
6533fcdf6aeSKevin Enderby   if (BinaryOrErr)
6543fcdf6aeSKevin Enderby     return std::move(*BinaryOrErr);
655ac9e1555SKevin Enderby   return BinaryOrErr.takeError();
656d3b7b126SMichael J. Spencer }
657d3b7b126SMichael J. Spencer 
create(MemoryBufferRef Source)658c60a321cSKevin Enderby Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {
65941af4309SMehdi Amini   Error Err = Error::success();
6604fae9329Szhijian   std::unique_ptr<Archive> Ret;
6614fae9329Szhijian   StringRef Buffer = Source.getBuffer();
6624fae9329Szhijian 
6634fae9329Szhijian   if (Buffer.startswith(BigArchiveMagic))
6644fae9329Szhijian     Ret = std::make_unique<BigArchive>(Source, Err);
6654fae9329Szhijian   else
6664fae9329Szhijian     Ret = std::make_unique<Archive>(Source, Err);
6674fae9329Szhijian 
668c60a321cSKevin Enderby   if (Err)
669c55cf4afSBill Wendling     return std::move(Err);
67076f1c396Szhijian   return std::move(Ret);
671692410efSRafael Espindola }
672692410efSRafael Espindola 
6734fae9329Szhijian std::unique_ptr<AbstractArchiveMemberHeader>
createArchiveMemberHeader(const char * RawHeaderPtr,uint64_t Size,Error * Err) const6744fae9329Szhijian Archive::createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size,
6754fae9329Szhijian                                    Error *Err) const {
6764fae9329Szhijian   ErrorAsOutParameter ErrAsOutParam(Err);
6774fae9329Szhijian   if (kind() != K_AIXBIG)
6784fae9329Szhijian     return std::make_unique<ArchiveMemberHeader>(this, RawHeaderPtr, Size, Err);
6794fae9329Szhijian   return std::make_unique<BigArchiveMemberHeader>(this, RawHeaderPtr, Size,
6804fae9329Szhijian                                                   Err);
6814fae9329Szhijian }
6824fae9329Szhijian 
getArchiveMagicLen() const6834fae9329Szhijian uint64_t Archive::getArchiveMagicLen() const {
6844fae9329Szhijian   if (isThin())
6854fae9329Szhijian     return sizeof(ThinArchiveMagic) - 1;
6864fae9329Szhijian 
6874fae9329Szhijian   if (Kind() == K_AIXBIG)
6884fae9329Szhijian     return sizeof(BigArchiveMagic) - 1;
6894fae9329Szhijian 
6904fae9329Szhijian   return sizeof(ArchiveMagic) - 1;
6914fae9329Szhijian }
6924fae9329Szhijian 
setFirstRegular(const Child & C)69343358761SRafael Espindola void Archive::setFirstRegular(const Child &C) {
69443358761SRafael Espindola   FirstRegularData = C.Data;
69543358761SRafael Espindola   FirstRegularStartOfFile = C.StartOfFile;
69643358761SRafael Espindola }
69743358761SRafael Espindola 
Archive(MemoryBufferRef Source,Error & Err)698c60a321cSKevin Enderby Archive::Archive(MemoryBufferRef Source, Error &Err)
69943358761SRafael Espindola     : Binary(Binary::ID_Archive, Source) {
7005e51a2e3SLang Hames   ErrorAsOutParameter ErrAsOutParam(&Err);
7019d102064SRafael Espindola   StringRef Buffer = Data.getBuffer();
702d3b7b126SMichael J. Spencer   // Check for sufficient magic.
7034fae9329Szhijian   if (Buffer.startswith(ThinArchiveMagic)) {
7049d102064SRafael Espindola     IsThin = true;
7054fae9329Szhijian   } else if (Buffer.startswith(ArchiveMagic)) {
7069d102064SRafael Espindola     IsThin = false;
7074fae9329Szhijian   } else if (Buffer.startswith(BigArchiveMagic)) {
7084fae9329Szhijian     Format = K_AIXBIG;
7094fae9329Szhijian     IsThin = false;
7104fae9329Szhijian     return;
7119d102064SRafael Espindola   } else {
712a5db9ee7SFangrui Song     Err = make_error<GenericBinaryError>("file too small to be an archive",
713c60a321cSKevin Enderby                                          object_error::invalid_file_type);
714d3b7b126SMichael J. Spencer     return;
715d3b7b126SMichael J. Spencer   }
716d3b7b126SMichael J. Spencer 
717f4586039SKevin Enderby   // Make sure Format is initialized before any call to
718f4586039SKevin Enderby   // ArchiveMemberHeader::getName() is made.  This could be a valid empty
719f4586039SKevin Enderby   // archive which is the same in all formats.  So claiming it to be gnu to is
720f4586039SKevin Enderby   // fine if not totally correct before we look for a string table or table of
721f4586039SKevin Enderby   // contents.
722f4586039SKevin Enderby   Format = K_GNU;
723f4586039SKevin Enderby 
724e03ea9cdSMichael J. Spencer   // Get the special members.
725fc209623SLang Hames   child_iterator I = child_begin(Err, false);
726fc209623SLang Hames   if (Err)
7277a96942aSKevin Enderby     return;
7287a96942aSKevin Enderby   child_iterator E = child_end();
729d3b7b126SMichael J. Spencer 
730f4586039SKevin Enderby   // See if this is a valid empty archive and if so return.
7317a96942aSKevin Enderby   if (I == E) {
732c60a321cSKevin Enderby     Err = Error::success();
73388ae7dd2SRafael Espindola     return;
73488ae7dd2SRafael Espindola   }
735fc209623SLang Hames   const Child *C = &*I;
73688ae7dd2SRafael Espindola 
7377a96942aSKevin Enderby   auto Increment = [&]() {
7387a96942aSKevin Enderby     ++I;
739fc209623SLang Hames     if (Err)
7407a96942aSKevin Enderby       return true;
741fc209623SLang Hames     C = &*I;
7427a96942aSKevin Enderby     return false;
7437a96942aSKevin Enderby   };
7447a96942aSKevin Enderby 
745f4586039SKevin Enderby   Expected<StringRef> NameOrErr = C->getRawName();
746f4586039SKevin Enderby   if (!NameOrErr) {
747f4586039SKevin Enderby     Err = NameOrErr.takeError();
748f4586039SKevin Enderby     return;
749f4586039SKevin Enderby   }
750f4586039SKevin Enderby   StringRef Name = NameOrErr.get();
75115b28be9SShankar Easwaran 
75215b28be9SShankar Easwaran   // Below is the pattern that is used to figure out the archive format
75315b28be9SShankar Easwaran   // GNU archive format
75488ae7dd2SRafael Espindola   //  First member : / (may exist, if it exists, points to the symbol table )
75515b28be9SShankar Easwaran   //  Second member : // (may exist, if it exists, points to the string table)
75615b28be9SShankar Easwaran   //  Note : The string table is used if the filename exceeds 15 characters
75715b28be9SShankar Easwaran   // BSD archive format
75855509920SRafael Espindola   //  First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table)
75915b28be9SShankar Easwaran   //  There is no string table, if the filename exceeds 15 characters or has a
76015b28be9SShankar Easwaran   //  embedded space, the filename has #1/<size>, The size represents the size
76115b28be9SShankar Easwaran   //  of the filename that needs to be read after the archive header
76215b28be9SShankar Easwaran   // COFF archive format
76315b28be9SShankar Easwaran   //  First member : /
76415b28be9SShankar Easwaran   //  Second member : / (provides a directory of symbols)
765f4d0a8c1SRui Ueyama   //  Third member : // (may exist, if it exists, contains the string table)
766f4d0a8c1SRui Ueyama   //  Note: Microsoft PE/COFF Spec 8.3 says that the third member is present
767f4d0a8c1SRui Ueyama   //  even if the string table is empty. However, lib.exe does not in fact
768f4d0a8c1SRui Ueyama   //  seem to create the third member if there's no member whose filename
769f4d0a8c1SRui Ueyama   //  exceeds 15 characters. So the third member is optional.
77088ae7dd2SRafael Espindola 
771ae108ffbSKevin Enderby   if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {
772ae108ffbSKevin Enderby     if (Name == "__.SYMDEF")
77388ae7dd2SRafael Espindola       Format = K_BSD;
774ae108ffbSKevin Enderby     else // Name == "__.SYMDEF_64"
775ae108ffbSKevin Enderby       Format = K_DARWIN64;
77627e85bd0SKevin Enderby     // We know that the symbol table is not an external file, but we still must
77727e85bd0SKevin Enderby     // check any Expected<> return value.
77827e85bd0SKevin Enderby     Expected<StringRef> BufOrErr = C->getBuffer();
77927e85bd0SKevin Enderby     if (!BufOrErr) {
78027e85bd0SKevin Enderby       Err = BufOrErr.takeError();
78127e85bd0SKevin Enderby       return;
78227e85bd0SKevin Enderby     }
78327e85bd0SKevin Enderby     SymbolTable = BufOrErr.get();
7847a96942aSKevin Enderby     if (Increment())
7857a96942aSKevin Enderby       return;
7867a96942aSKevin Enderby     setFirstRegular(*C);
7877a96942aSKevin Enderby 
788c60a321cSKevin Enderby     Err = Error::success();
78988ae7dd2SRafael Espindola     return;
79088ae7dd2SRafael Espindola   }
79188ae7dd2SRafael Espindola 
79255509920SRafael Espindola   if (Name.startswith("#1/")) {
79355509920SRafael Espindola     Format = K_BSD;
79455509920SRafael Espindola     // We know this is BSD, so getName will work since there is no string table.
795f4586039SKevin Enderby     Expected<StringRef> NameOrErr = C->getName();
796f4586039SKevin Enderby     if (!NameOrErr) {
797f4586039SKevin Enderby       Err = NameOrErr.takeError();
79855509920SRafael Espindola       return;
799c60a321cSKevin Enderby     }
800ae460027SRafael Espindola     Name = NameOrErr.get();
801f44dbda5SNick Kledzik     if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
80227e85bd0SKevin Enderby       // We know that the symbol table is not an external file, but we still
80327e85bd0SKevin Enderby       // must check any Expected<> return value.
80427e85bd0SKevin Enderby       Expected<StringRef> BufOrErr = C->getBuffer();
80527e85bd0SKevin Enderby       if (!BufOrErr) {
80627e85bd0SKevin Enderby         Err = BufOrErr.takeError();
80727e85bd0SKevin Enderby         return;
80827e85bd0SKevin Enderby       }
80927e85bd0SKevin Enderby       SymbolTable = BufOrErr.get();
8107a96942aSKevin Enderby       if (Increment())
8117a96942aSKevin Enderby         return;
812e41aaea2SJordan Rupprecht     } else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {
813ae108ffbSKevin Enderby       Format = K_DARWIN64;
81427e85bd0SKevin Enderby       // We know that the symbol table is not an external file, but we still
81527e85bd0SKevin Enderby       // must check any Expected<> return value.
81627e85bd0SKevin Enderby       Expected<StringRef> BufOrErr = C->getBuffer();
81727e85bd0SKevin Enderby       if (!BufOrErr) {
81827e85bd0SKevin Enderby         Err = BufOrErr.takeError();
81927e85bd0SKevin Enderby         return;
82027e85bd0SKevin Enderby       }
82127e85bd0SKevin Enderby       SymbolTable = BufOrErr.get();
822ae108ffbSKevin Enderby       if (Increment())
823ae108ffbSKevin Enderby         return;
824ae108ffbSKevin Enderby     }
8257a96942aSKevin Enderby     setFirstRegular(*C);
82655509920SRafael Espindola     return;
82755509920SRafael Espindola   }
82855509920SRafael Espindola 
8291d902b7cSSimon Atanasyan   // MIPS 64-bit ELF archives use a special format of a symbol table.
8301d902b7cSSimon Atanasyan   // This format is marked by `ar_name` field equals to "/SYM64/".
8311d902b7cSSimon Atanasyan   // For detailed description see page 96 in the following document:
8321d902b7cSSimon Atanasyan   // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
8331d902b7cSSimon Atanasyan 
8341d902b7cSSimon Atanasyan   bool has64SymTable = false;
8351d902b7cSSimon Atanasyan   if (Name == "/" || Name == "/SYM64/") {
83627e85bd0SKevin Enderby     // We know that the symbol table is not an external file, but we still
83727e85bd0SKevin Enderby     // must check any Expected<> return value.
83827e85bd0SKevin Enderby     Expected<StringRef> BufOrErr = C->getBuffer();
83927e85bd0SKevin Enderby     if (!BufOrErr) {
84027e85bd0SKevin Enderby       Err = BufOrErr.takeError();
84127e85bd0SKevin Enderby       return;
84227e85bd0SKevin Enderby     }
84327e85bd0SKevin Enderby     SymbolTable = BufOrErr.get();
8441d902b7cSSimon Atanasyan     if (Name == "/SYM64/")
8451d902b7cSSimon Atanasyan       has64SymTable = true;
84688ae7dd2SRafael Espindola 
8477a96942aSKevin Enderby     if (Increment())
8487a96942aSKevin Enderby       return;
8497a96942aSKevin Enderby     if (I == E) {
850c60a321cSKevin Enderby       Err = Error::success();
85104614ff6SMichael J. Spencer       return;
85204614ff6SMichael J. Spencer     }
853f4586039SKevin Enderby     Expected<StringRef> NameOrErr = C->getRawName();
854f4586039SKevin Enderby     if (!NameOrErr) {
855f4586039SKevin Enderby       Err = NameOrErr.takeError();
856f4586039SKevin Enderby       return;
857f4586039SKevin Enderby     }
858f4586039SKevin Enderby     Name = NameOrErr.get();
85988ae7dd2SRafael Espindola   }
86088ae7dd2SRafael Espindola 
8616cc2dc71SRafael Espindola   if (Name == "//") {
8621b30d63aSJake Ehrlich     Format = has64SymTable ? K_GNU64 : K_GNU;
86327e85bd0SKevin Enderby     // The string table is never an external member, but we still
86427e85bd0SKevin Enderby     // must check any Expected<> return value.
86527e85bd0SKevin Enderby     Expected<StringRef> BufOrErr = C->getBuffer();
86627e85bd0SKevin Enderby     if (!BufOrErr) {
86727e85bd0SKevin Enderby       Err = BufOrErr.takeError();
86827e85bd0SKevin Enderby       return;
86927e85bd0SKevin Enderby     }
87027e85bd0SKevin Enderby     StringTable = BufOrErr.get();
8717a96942aSKevin Enderby     if (Increment())
8727a96942aSKevin Enderby       return;
8737a96942aSKevin Enderby     setFirstRegular(*C);
874c60a321cSKevin Enderby     Err = Error::success();
87588ae7dd2SRafael Espindola     return;
87688ae7dd2SRafael Espindola   }
87788ae7dd2SRafael Espindola 
8786cc2dc71SRafael Espindola   if (Name[0] != '/') {
8791b30d63aSJake Ehrlich     Format = has64SymTable ? K_GNU64 : K_GNU;
8807a96942aSKevin Enderby     setFirstRegular(*C);
881c60a321cSKevin Enderby     Err = Error::success();
88288ae7dd2SRafael Espindola     return;
883e03ea9cdSMichael J. Spencer   }
88488ae7dd2SRafael Espindola 
8856cc2dc71SRafael Espindola   if (Name != "/") {
886c60a321cSKevin Enderby     Err = errorCodeToError(object_error::parse_failed);
88788ae7dd2SRafael Espindola     return;
88888ae7dd2SRafael Espindola   }
88988ae7dd2SRafael Espindola 
89088ae7dd2SRafael Espindola   Format = K_COFF;
89127e85bd0SKevin Enderby   // We know that the symbol table is not an external file, but we still
89227e85bd0SKevin Enderby   // must check any Expected<> return value.
89327e85bd0SKevin Enderby   Expected<StringRef> BufOrErr = C->getBuffer();
89427e85bd0SKevin Enderby   if (!BufOrErr) {
89527e85bd0SKevin Enderby     Err = BufOrErr.takeError();
89627e85bd0SKevin Enderby     return;
89727e85bd0SKevin Enderby   }
89827e85bd0SKevin Enderby   SymbolTable = BufOrErr.get();
89988ae7dd2SRafael Espindola 
9007a96942aSKevin Enderby   if (Increment())
9017a96942aSKevin Enderby     return;
9027a96942aSKevin Enderby 
9037a96942aSKevin Enderby   if (I == E) {
9047a96942aSKevin Enderby     setFirstRegular(*C);
905c60a321cSKevin Enderby     Err = Error::success();
90688ae7dd2SRafael Espindola     return;
90788ae7dd2SRafael Espindola   }
90888ae7dd2SRafael Espindola 
909f4586039SKevin Enderby   NameOrErr = C->getRawName();
910f4586039SKevin Enderby   if (!NameOrErr) {
911f4586039SKevin Enderby     Err = NameOrErr.takeError();
912f4586039SKevin Enderby     return;
913f4586039SKevin Enderby   }
914f4586039SKevin Enderby   Name = NameOrErr.get();
91588ae7dd2SRafael Espindola 
9163e2b21cdSRafael Espindola   if (Name == "//") {
91727e85bd0SKevin Enderby     // The string table is never an external member, but we still
91827e85bd0SKevin Enderby     // must check any Expected<> return value.
91927e85bd0SKevin Enderby     Expected<StringRef> BufOrErr = C->getBuffer();
92027e85bd0SKevin Enderby     if (!BufOrErr) {
92127e85bd0SKevin Enderby       Err = BufOrErr.takeError();
92227e85bd0SKevin Enderby       return;
92327e85bd0SKevin Enderby     }
92427e85bd0SKevin Enderby     StringTable = BufOrErr.get();
9257a96942aSKevin Enderby     if (Increment())
9267a96942aSKevin Enderby       return;
9273e2b21cdSRafael Espindola   }
92888ae7dd2SRafael Espindola 
9297a96942aSKevin Enderby   setFirstRegular(*C);
930c60a321cSKevin Enderby   Err = Error::success();
931d3b7b126SMichael J. Spencer }
932d3b7b126SMichael J. Spencer 
getDefaultKindForHost()93306624305SKeith Smiley object::Archive::Kind Archive::getDefaultKindForHost() {
93406624305SKeith Smiley   Triple HostTriple(sys::getProcessTriple());
93506624305SKeith Smiley   return HostTriple.isOSDarwin()
93606624305SKeith Smiley              ? object::Archive::K_DARWIN
93706624305SKeith Smiley              : (HostTriple.isOSAIX() ? object::Archive::K_AIXBIG
93806624305SKeith Smiley                                      : object::Archive::K_GNU);
93906624305SKeith Smiley }
94006624305SKeith Smiley 
child_begin(Error & Err,bool SkipInternal) const941fc209623SLang Hames Archive::child_iterator Archive::child_begin(Error &Err,
942fc209623SLang Hames                                              bool SkipInternal) const {
94314a5ca04SRui Ueyama   if (isEmpty())
94423a9750cSRafael Espindola     return child_end();
9453e2b21cdSRafael Espindola 
9463e2b21cdSRafael Espindola   if (SkipInternal)
9473e040e05SLang Hames     return child_iterator::itr(
9483e040e05SLang Hames         Child(this, FirstRegularData, FirstRegularStartOfFile), Err);
9493e2b21cdSRafael Espindola 
9504fae9329Szhijian   const char *Loc = Data.getBufferStart() + getFirstChildOffset();
9516524bd8cSKevin Enderby   Child C(this, Loc, &Err);
9526524bd8cSKevin Enderby   if (Err)
953fc209623SLang Hames     return child_end();
9543e040e05SLang Hames   return child_iterator::itr(C, Err);
955d3b7b126SMichael J. Spencer }
956d3b7b126SMichael J. Spencer 
child_end() const95723a9750cSRafael Espindola Archive::child_iterator Archive::child_end() const {
9583e040e05SLang Hames   return child_iterator::end(Child(nullptr, nullptr, nullptr));
959d3b7b126SMichael J. Spencer }
960e03ea9cdSMichael J. Spencer 
getName() const961ae460027SRafael Espindola StringRef Archive::Symbol::getName() const {
9622b05416bSRafael Espindola   return Parent->getSymbolTable().begin() + StringIndex;
963e03ea9cdSMichael J. Spencer }
964e03ea9cdSMichael J. Spencer 
getMember() const96527e85bd0SKevin Enderby Expected<Archive::Child> Archive::Symbol::getMember() const {
9662b05416bSRafael Espindola   const char *Buf = Parent->getSymbolTable().begin();
9671d902b7cSSimon Atanasyan   const char *Offsets = Buf;
968*a6316d6dSzhijian   if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64 ||
969*a6316d6dSzhijian       Parent->kind() == K_AIXBIG)
9701d902b7cSSimon Atanasyan     Offsets += sizeof(uint64_t);
9711d902b7cSSimon Atanasyan   else
9721d902b7cSSimon Atanasyan     Offsets += sizeof(uint32_t);
973de370414SJake Ehrlich   uint64_t Offset = 0;
97415b28be9SShankar Easwaran   if (Parent->kind() == K_GNU) {
9753206b79dSRui Ueyama     Offset = read32be(Offsets + SymbolIndex * 4);
976*a6316d6dSzhijian   } else if (Parent->kind() == K_GNU64 || Parent->kind() == K_AIXBIG) {
9773206b79dSRui Ueyama     Offset = read64be(Offsets + SymbolIndex * 8);
97815b28be9SShankar Easwaran   } else if (Parent->kind() == K_BSD) {
9798c50dbb8SKevin Enderby     // The SymbolIndex is an index into the ranlib structs that start at
9808c50dbb8SKevin Enderby     // Offsets (the first uint32_t is the number of bytes of the ranlib
9818c50dbb8SKevin Enderby     // structs).  The ranlib structs are a pair of uint32_t's the first
9828c50dbb8SKevin Enderby     // being a string table offset and the second being the offset into
9838c50dbb8SKevin Enderby     // the archive of the member that defines the symbol.  Which is what
9848c50dbb8SKevin Enderby     // is needed here.
9853206b79dSRui Ueyama     Offset = read32le(Offsets + SymbolIndex * 8 + 4);
986ae108ffbSKevin Enderby   } else if (Parent->kind() == K_DARWIN64) {
987ae108ffbSKevin Enderby     // The SymbolIndex is an index into the ranlib_64 structs that start at
988ae108ffbSKevin Enderby     // Offsets (the first uint64_t is the number of bytes of the ranlib_64
989ae108ffbSKevin Enderby     // structs).  The ranlib_64 structs are a pair of uint64_t's the first
990ae108ffbSKevin Enderby     // being a string table offset and the second being the offset into
991ae108ffbSKevin Enderby     // the archive of the member that defines the symbol.  Which is what
992ae108ffbSKevin Enderby     // is needed here.
993ae108ffbSKevin Enderby     Offset = read64le(Offsets + SymbolIndex * 16 + 8);
99415b28be9SShankar Easwaran   } else {
9954e92d5b9SMichael J. Spencer     // Skip offsets.
9963206b79dSRui Ueyama     uint32_t MemberCount = read32le(Buf);
9973206b79dSRui Ueyama     Buf += MemberCount * 4 + 4;
9984e92d5b9SMichael J. Spencer 
9993206b79dSRui Ueyama     uint32_t SymbolCount = read32le(Buf);
10004e92d5b9SMichael J. Spencer     if (SymbolIndex >= SymbolCount)
100127e85bd0SKevin Enderby       return errorCodeToError(object_error::parse_failed);
10024e92d5b9SMichael J. Spencer 
100368e0b6afSMatt Beaumont-Gay     // Skip SymbolCount to get to the indices table.
10043206b79dSRui Ueyama     const char *Indices = Buf + 4;
10054e92d5b9SMichael J. Spencer 
10064e92d5b9SMichael J. Spencer     // Get the index of the offset in the file member offset table for this
10074e92d5b9SMichael J. Spencer     // symbol.
10083206b79dSRui Ueyama     uint16_t OffsetIndex = read16le(Indices + SymbolIndex * 2);
10094e92d5b9SMichael J. Spencer     // Subtract 1 since OffsetIndex is 1 based.
10104e92d5b9SMichael J. Spencer     --OffsetIndex;
10114e92d5b9SMichael J. Spencer 
10124e92d5b9SMichael J. Spencer     if (OffsetIndex >= MemberCount)
101327e85bd0SKevin Enderby       return errorCodeToError(object_error::parse_failed);
10144e92d5b9SMichael J. Spencer 
10153206b79dSRui Ueyama     Offset = read32le(Offsets + OffsetIndex * 4);
101615b28be9SShankar Easwaran   }
1017e03ea9cdSMichael J. Spencer 
10184e92d5b9SMichael J. Spencer   const char *Loc = Parent->getData().begin() + Offset;
101941af4309SMehdi Amini   Error Err = Error::success();
10206524bd8cSKevin Enderby   Child C(Parent, Loc, &Err);
10216524bd8cSKevin Enderby   if (Err)
1022c55cf4afSBill Wendling     return std::move(Err);
10237a96942aSKevin Enderby   return C;
1024e03ea9cdSMichael J. Spencer }
1025e03ea9cdSMichael J. Spencer 
getNext() const1026e03ea9cdSMichael J. Spencer Archive::Symbol Archive::Symbol::getNext() const {
1027e03ea9cdSMichael J. Spencer   Symbol t(*this);
10288c50dbb8SKevin Enderby   if (Parent->kind() == K_BSD) {
10298c50dbb8SKevin Enderby     // t.StringIndex is an offset from the start of the __.SYMDEF or
10308c50dbb8SKevin Enderby     // "__.SYMDEF SORTED" member into the string table for the ranlib
10318c50dbb8SKevin Enderby     // struct indexed by t.SymbolIndex .  To change t.StringIndex to the
10328c50dbb8SKevin Enderby     // offset in the string table for t.SymbolIndex+1 we subtract the
10338c50dbb8SKevin Enderby     // its offset from the start of the string table for t.SymbolIndex
10348c50dbb8SKevin Enderby     // and add the offset of the string table for t.SymbolIndex+1.
10358c50dbb8SKevin Enderby 
10368c50dbb8SKevin Enderby     // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
10378c50dbb8SKevin Enderby     // which is the number of bytes of ranlib structs that follow.  The ranlib
10388c50dbb8SKevin Enderby     // structs are a pair of uint32_t's the first being a string table offset
10398c50dbb8SKevin Enderby     // and the second being the offset into the archive of the member that
10408c50dbb8SKevin Enderby     // define the symbol. After that the next uint32_t is the byte count of
10418c50dbb8SKevin Enderby     // the string table followed by the string table.
10422b05416bSRafael Espindola     const char *Buf = Parent->getSymbolTable().begin();
10438c50dbb8SKevin Enderby     uint32_t RanlibCount = 0;
10443206b79dSRui Ueyama     RanlibCount = read32le(Buf) / 8;
10458c50dbb8SKevin Enderby     // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount)
10468c50dbb8SKevin Enderby     // don't change the t.StringIndex as we don't want to reference a ranlib
10478c50dbb8SKevin Enderby     // past RanlibCount.
10488c50dbb8SKevin Enderby     if (t.SymbolIndex + 1 < RanlibCount) {
10498c50dbb8SKevin Enderby       const char *Ranlibs = Buf + 4;
10508c50dbb8SKevin Enderby       uint32_t CurRanStrx = 0;
10518c50dbb8SKevin Enderby       uint32_t NextRanStrx = 0;
10523206b79dSRui Ueyama       CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8);
10533206b79dSRui Ueyama       NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8);
10548c50dbb8SKevin Enderby       t.StringIndex -= CurRanStrx;
10558c50dbb8SKevin Enderby       t.StringIndex += NextRanStrx;
10568c50dbb8SKevin Enderby     }
10578c50dbb8SKevin Enderby   } else {
10584246ca40SBenjamin Kramer     // Go to one past next null.
10592b05416bSRafael Espindola     t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1;
10608c50dbb8SKevin Enderby   }
1061e03ea9cdSMichael J. Spencer   ++t.SymbolIndex;
1062e03ea9cdSMichael J. Spencer   return t;
1063e03ea9cdSMichael J. Spencer }
1064e03ea9cdSMichael J. Spencer 
symbol_begin() const106523a9750cSRafael Espindola Archive::symbol_iterator Archive::symbol_begin() const {
1066b6b5f52eSRafael Espindola   if (!hasSymbolTable())
1067fbcafc07SRafael Espindola     return symbol_iterator(Symbol(this, 0, 0));
1068fbcafc07SRafael Espindola 
10692b05416bSRafael Espindola   const char *buf = getSymbolTable().begin();
107015b28be9SShankar Easwaran   if (kind() == K_GNU) {
107115b28be9SShankar Easwaran     uint32_t symbol_count = 0;
10723206b79dSRui Ueyama     symbol_count = read32be(buf);
107315b28be9SShankar Easwaran     buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
10741b30d63aSJake Ehrlich   } else if (kind() == K_GNU64) {
10753206b79dSRui Ueyama     uint64_t symbol_count = read64be(buf);
10761d902b7cSSimon Atanasyan     buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));
107715b28be9SShankar Easwaran   } else if (kind() == K_BSD) {
10788c50dbb8SKevin Enderby     // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
10798c50dbb8SKevin Enderby     // which is the number of bytes of ranlib structs that follow.  The ranlib
10808c50dbb8SKevin Enderby     // structs are a pair of uint32_t's the first being a string table offset
10818c50dbb8SKevin Enderby     // and the second being the offset into the archive of the member that
10828c50dbb8SKevin Enderby     // define the symbol. After that the next uint32_t is the byte count of
10838c50dbb8SKevin Enderby     // the string table followed by the string table.
10848c50dbb8SKevin Enderby     uint32_t ranlib_count = 0;
10853206b79dSRui Ueyama     ranlib_count = read32le(buf) / 8;
10868c50dbb8SKevin Enderby     const char *ranlibs = buf + 4;
10878c50dbb8SKevin Enderby     uint32_t ran_strx = 0;
10883206b79dSRui Ueyama     ran_strx = read32le(ranlibs);
10898c50dbb8SKevin Enderby     buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t))));
10908c50dbb8SKevin Enderby     // Skip the byte count of the string table.
10918c50dbb8SKevin Enderby     buf += sizeof(uint32_t);
10928c50dbb8SKevin Enderby     buf += ran_strx;
1093ae108ffbSKevin Enderby   } else if (kind() == K_DARWIN64) {
1094ae108ffbSKevin Enderby     // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t
1095ae108ffbSKevin Enderby     // which is the number of bytes of ranlib_64 structs that follow.  The
1096ae108ffbSKevin Enderby     // ranlib_64 structs are a pair of uint64_t's the first being a string
1097ae108ffbSKevin Enderby     // table offset and the second being the offset into the archive of the
1098ae108ffbSKevin Enderby     // member that define the symbol. After that the next uint64_t is the byte
1099ae108ffbSKevin Enderby     // count of the string table followed by the string table.
1100ae108ffbSKevin Enderby     uint64_t ranlib_count = 0;
1101ae108ffbSKevin Enderby     ranlib_count = read64le(buf) / 16;
1102ae108ffbSKevin Enderby     const char *ranlibs = buf + 8;
1103ae108ffbSKevin Enderby     uint64_t ran_strx = 0;
1104ae108ffbSKevin Enderby     ran_strx = read64le(ranlibs);
1105ae108ffbSKevin Enderby     buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t))));
1106ae108ffbSKevin Enderby     // Skip the byte count of the string table.
1107ae108ffbSKevin Enderby     buf += sizeof(uint64_t);
1108ae108ffbSKevin Enderby     buf += ran_strx;
1109*a6316d6dSzhijian   } else if (kind() == K_AIXBIG) {
1110*a6316d6dSzhijian     buf = getStringTable().begin();
111115b28be9SShankar Easwaran   } else {
111215b28be9SShankar Easwaran     uint32_t member_count = 0;
111315b28be9SShankar Easwaran     uint32_t symbol_count = 0;
11143206b79dSRui Ueyama     member_count = read32le(buf);
1115e03ea9cdSMichael J. Spencer     buf += 4 + (member_count * 4); // Skip offsets.
11163206b79dSRui Ueyama     symbol_count = read32le(buf);
1117e03ea9cdSMichael J. Spencer     buf += 4 + (symbol_count * 2); // Skip indices.
111815b28be9SShankar Easwaran   }
11192b05416bSRafael Espindola   uint32_t string_start_offset = buf - getSymbolTable().begin();
1120e03ea9cdSMichael J. Spencer   return symbol_iterator(Symbol(this, 0, string_start_offset));
1121e03ea9cdSMichael J. Spencer }
1122e03ea9cdSMichael J. Spencer 
symbol_end() const112323a9750cSRafael Espindola Archive::symbol_iterator Archive::symbol_end() const {
1124407e0976SRui Ueyama   return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0));
1125407e0976SRui Ueyama }
1126fbcafc07SRafael Espindola 
getNumberOfSymbols() const1127407e0976SRui Ueyama uint32_t Archive::getNumberOfSymbols() const {
1128483ad200SRafael Espindola   if (!hasSymbolTable())
1129483ad200SRafael Espindola     return 0;
11302b05416bSRafael Espindola   const char *buf = getSymbolTable().begin();
1131407e0976SRui Ueyama   if (kind() == K_GNU)
1132407e0976SRui Ueyama     return read32be(buf);
1133*a6316d6dSzhijian   if (kind() == K_GNU64 || kind() == K_AIXBIG)
1134407e0976SRui Ueyama     return read64be(buf);
1135407e0976SRui Ueyama   if (kind() == K_BSD)
1136407e0976SRui Ueyama     return read32le(buf) / 8;
1137ae108ffbSKevin Enderby   if (kind() == K_DARWIN64)
1138ae108ffbSKevin Enderby     return read64le(buf) / 16;
113915b28be9SShankar Easwaran   uint32_t member_count = 0;
11403206b79dSRui Ueyama   member_count = read32le(buf);
1141e03ea9cdSMichael J. Spencer   buf += 4 + (member_count * 4); // Skip offsets.
1142407e0976SRui Ueyama   return read32le(buf);
1143e03ea9cdSMichael J. Spencer }
114415b28be9SShankar Easwaran 
findSym(StringRef name) const114569f4902bSLang Hames Expected<Optional<Archive::Child>> Archive::findSym(StringRef name) const {
114623a9750cSRafael Espindola   Archive::symbol_iterator bs = symbol_begin();
114723a9750cSRafael Espindola   Archive::symbol_iterator es = symbol_end();
114815b28be9SShankar Easwaran 
114915b28be9SShankar Easwaran   for (; bs != es; ++bs) {
1150ae460027SRafael Espindola     StringRef SymName = bs->getName();
1151ae460027SRafael Espindola     if (SymName == name) {
115269f4902bSLang Hames       if (auto MemberOrErr = bs->getMember())
115369f4902bSLang Hames         return Child(*MemberOrErr);
115469f4902bSLang Hames       else
115527e85bd0SKevin Enderby         return MemberOrErr.takeError();
1156fc209623SLang Hames     }
115715b28be9SShankar Easwaran   }
115869f4902bSLang Hames   return Optional<Child>();
115915b28be9SShankar Easwaran }
1160b6b5f52eSRafael Espindola 
116114a5ca04SRui Ueyama // Returns true if archive file contains no member file.
isEmpty() const11624fae9329Szhijian bool Archive::isEmpty() const {
11634fae9329Szhijian   return Data.getBufferSize() == getArchiveMagicLen();
11644fae9329Szhijian }
116514a5ca04SRui Ueyama 
hasSymbolTable() const11664a782fbfSRafael Espindola bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }
11674fae9329Szhijian 
BigArchive(MemoryBufferRef Source,Error & Err)11684fae9329Szhijian BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)
11694fae9329Szhijian     : Archive(Source, Err) {
11704fae9329Szhijian   ErrorAsOutParameter ErrAsOutParam(&Err);
11714fae9329Szhijian   StringRef Buffer = Data.getBuffer();
11724fae9329Szhijian   ArFixLenHdr = reinterpret_cast<const FixLenHdr *>(Buffer.data());
11734fae9329Szhijian 
11744fae9329Szhijian   StringRef RawOffset = getFieldRawString(ArFixLenHdr->FirstChildOffset);
11754fae9329Szhijian   if (RawOffset.getAsInteger(10, FirstChildOffset))
11764fae9329Szhijian     // TODO: Out-of-line.
11774fae9329Szhijian     Err = malformedError("malformed AIX big archive: first member offset \"" +
11784fae9329Szhijian                          RawOffset + "\" is not a number");
11794fae9329Szhijian 
11804fae9329Szhijian   RawOffset = getFieldRawString(ArFixLenHdr->LastChildOffset);
11814fae9329Szhijian   if (RawOffset.getAsInteger(10, LastChildOffset))
11824fae9329Szhijian     // TODO: Out-of-line.
11834fae9329Szhijian     Err = malformedError("malformed AIX big archive: last member offset \"" +
11844fae9329Szhijian                          RawOffset + "\" is not a number");
11854fae9329Szhijian 
1186*a6316d6dSzhijian   // Calculate the global symbol table.
1187*a6316d6dSzhijian   uint64_t GlobSymOffset = 0;
1188*a6316d6dSzhijian   RawOffset = getFieldRawString(ArFixLenHdr->GlobSymOffset);
1189*a6316d6dSzhijian   if (RawOffset.getAsInteger(10, GlobSymOffset))
1190*a6316d6dSzhijian     // TODO: add test case.
1191*a6316d6dSzhijian     Err = malformedError(
1192*a6316d6dSzhijian         "malformed AIX big archive: global symbol table offset \"" + RawOffset +
1193*a6316d6dSzhijian         "\" is not a number");
1194*a6316d6dSzhijian 
1195*a6316d6dSzhijian   if (Err)
1196*a6316d6dSzhijian     return;
1197*a6316d6dSzhijian 
1198*a6316d6dSzhijian   if (GlobSymOffset > 0) {
1199*a6316d6dSzhijian     uint64_t BufferSize = Data.getBufferSize();
1200*a6316d6dSzhijian     uint64_t GlobalSymTblContentOffset =
1201*a6316d6dSzhijian         GlobSymOffset + sizeof(BigArMemHdrType);
1202*a6316d6dSzhijian     if (GlobalSymTblContentOffset > BufferSize) {
1203*a6316d6dSzhijian       Err = malformedError("global symbol table header at offset 0x" +
1204*a6316d6dSzhijian                            Twine::utohexstr(GlobSymOffset) + " and size 0x" +
1205*a6316d6dSzhijian                            Twine::utohexstr(sizeof(BigArMemHdrType)) +
1206*a6316d6dSzhijian                            " goes past the end of file");
1207*a6316d6dSzhijian       return;
1208*a6316d6dSzhijian     }
1209*a6316d6dSzhijian 
1210*a6316d6dSzhijian     const char *GlobSymTblLoc = Data.getBufferStart() + GlobSymOffset;
1211*a6316d6dSzhijian     const BigArMemHdrType *GlobalSymHdr =
1212*a6316d6dSzhijian         reinterpret_cast<const BigArMemHdrType *>(GlobSymTblLoc);
1213*a6316d6dSzhijian     RawOffset = getFieldRawString(GlobalSymHdr->Size);
1214*a6316d6dSzhijian     uint64_t Size;
1215*a6316d6dSzhijian     if (RawOffset.getAsInteger(10, Size)) {
1216*a6316d6dSzhijian       // TODO: add test case.
1217*a6316d6dSzhijian       Err = malformedError(
1218*a6316d6dSzhijian           "malformed AIX big archive: global symbol table size \"" + RawOffset +
1219*a6316d6dSzhijian           "\" is not a number");
1220*a6316d6dSzhijian       return;
1221*a6316d6dSzhijian     }
1222*a6316d6dSzhijian     if (GlobalSymTblContentOffset + Size > BufferSize) {
1223*a6316d6dSzhijian       Err = malformedError("global symbol table content at offset 0x" +
1224*a6316d6dSzhijian                            Twine::utohexstr(GlobalSymTblContentOffset) +
1225*a6316d6dSzhijian                            " and size 0x" + Twine::utohexstr(Size) +
1226*a6316d6dSzhijian                            " goes past the end of file");
1227*a6316d6dSzhijian       return;
1228*a6316d6dSzhijian     }
1229*a6316d6dSzhijian     SymbolTable = StringRef(GlobSymTblLoc + sizeof(BigArMemHdrType), Size);
1230*a6316d6dSzhijian     unsigned SymNum = getNumberOfSymbols();
1231*a6316d6dSzhijian     unsigned SymOffsetsSize = 8 * (SymNum + 1);
1232*a6316d6dSzhijian     uint64_t SymbolTableStringSize = Size - SymOffsetsSize;
1233*a6316d6dSzhijian     StringTable =
1234*a6316d6dSzhijian         StringRef(GlobSymTblLoc + sizeof(BigArMemHdrType) + SymOffsetsSize,
1235*a6316d6dSzhijian                   SymbolTableStringSize);
1236*a6316d6dSzhijian   }
1237*a6316d6dSzhijian 
12384fae9329Szhijian   child_iterator I = child_begin(Err, false);
12394fae9329Szhijian   if (Err)
12404fae9329Szhijian     return;
12414fae9329Szhijian   child_iterator E = child_end();
12424fae9329Szhijian   if (I == E) {
12434fae9329Szhijian     Err = Error::success();
12444fae9329Szhijian     return;
12454fae9329Szhijian   }
12464fae9329Szhijian   setFirstRegular(*I);
12474fae9329Szhijian   Err = Error::success();
12484fae9329Szhijian }
1249