xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/Archive.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- Archive.cpp - ar File Format implementation ------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the ArchiveObjectFile class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Object/Archive.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
150b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
160b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
170b57cec5SDimitry Andric #include "llvm/Object/Binary.h"
180b57cec5SDimitry Andric #include "llvm/Object/Error.h"
190b57cec5SDimitry Andric #include "llvm/Support/Chrono.h"
200b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
2106c3fb27SDimitry Andric #include "llvm/Support/EndianStream.h"
220b57cec5SDimitry Andric #include "llvm/Support/Error.h"
230b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h"
240b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
2504eeddc0SDimitry Andric #include "llvm/Support/MathExtras.h"
260b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
270b57cec5SDimitry Andric #include "llvm/Support/Path.h"
280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
2906c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
300b57cec5SDimitry Andric #include <algorithm>
310b57cec5SDimitry Andric #include <cassert>
320b57cec5SDimitry Andric #include <cstddef>
330b57cec5SDimitry Andric #include <cstdint>
340b57cec5SDimitry Andric #include <memory>
350b57cec5SDimitry Andric #include <string>
360b57cec5SDimitry Andric #include <system_error>
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric using namespace llvm;
390b57cec5SDimitry Andric using namespace object;
400b57cec5SDimitry Andric using namespace llvm::support::endian;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric void Archive::anchor() {}
430b57cec5SDimitry Andric 
44fe6060f1SDimitry Andric static Error malformedError(Twine Msg) {
450b57cec5SDimitry Andric   std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")";
460b57cec5SDimitry Andric   return make_error<GenericBinaryError>(std::move(StringMsg),
470b57cec5SDimitry Andric                                         object_error::parse_failed);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
5004eeddc0SDimitry Andric static Error
5104eeddc0SDimitry Andric createMemberHeaderParseError(const AbstractArchiveMemberHeader *ArMemHeader,
5204eeddc0SDimitry Andric                              const char *RawHeaderPtr, uint64_t Size) {
5304eeddc0SDimitry Andric   StringRef Msg("remaining size of archive too small for next archive "
5404eeddc0SDimitry Andric                 "member header ");
5504eeddc0SDimitry Andric 
5604eeddc0SDimitry Andric   Expected<StringRef> NameOrErr = ArMemHeader->getName(Size);
5704eeddc0SDimitry Andric   if (NameOrErr)
5804eeddc0SDimitry Andric     return malformedError(Msg + "for " + *NameOrErr);
5904eeddc0SDimitry Andric 
6004eeddc0SDimitry Andric   consumeError(NameOrErr.takeError());
6104eeddc0SDimitry Andric   uint64_t Offset = RawHeaderPtr - ArMemHeader->Parent->getData().data();
6204eeddc0SDimitry Andric   return malformedError(Msg + "at offset " + Twine(Offset));
6304eeddc0SDimitry Andric }
6404eeddc0SDimitry Andric 
6504eeddc0SDimitry Andric template <class T, std::size_t N>
6604eeddc0SDimitry Andric StringRef getFieldRawString(const T (&Field)[N]) {
6704eeddc0SDimitry Andric   return StringRef(Field, N).rtrim(" ");
6804eeddc0SDimitry Andric }
6904eeddc0SDimitry Andric 
7004eeddc0SDimitry Andric template <class T>
7104eeddc0SDimitry Andric StringRef CommonArchiveMemberHeader<T>::getRawAccessMode() const {
7204eeddc0SDimitry Andric   return getFieldRawString(ArMemHdr->AccessMode);
7304eeddc0SDimitry Andric }
7404eeddc0SDimitry Andric 
7504eeddc0SDimitry Andric template <class T>
7604eeddc0SDimitry Andric StringRef CommonArchiveMemberHeader<T>::getRawLastModified() const {
7704eeddc0SDimitry Andric   return getFieldRawString(ArMemHdr->LastModified);
7804eeddc0SDimitry Andric }
7904eeddc0SDimitry Andric 
8004eeddc0SDimitry Andric template <class T> StringRef CommonArchiveMemberHeader<T>::getRawUID() const {
8104eeddc0SDimitry Andric   return getFieldRawString(ArMemHdr->UID);
8204eeddc0SDimitry Andric }
8304eeddc0SDimitry Andric 
8404eeddc0SDimitry Andric template <class T> StringRef CommonArchiveMemberHeader<T>::getRawGID() const {
8504eeddc0SDimitry Andric   return getFieldRawString(ArMemHdr->GID);
8604eeddc0SDimitry Andric }
8704eeddc0SDimitry Andric 
8804eeddc0SDimitry Andric template <class T> uint64_t CommonArchiveMemberHeader<T>::getOffset() const {
8904eeddc0SDimitry Andric   return reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
9004eeddc0SDimitry Andric }
9104eeddc0SDimitry Andric 
9204eeddc0SDimitry Andric template class object::CommonArchiveMemberHeader<UnixArMemHdrType>;
9304eeddc0SDimitry Andric template class object::CommonArchiveMemberHeader<BigArMemHdrType>;
9404eeddc0SDimitry Andric 
950b57cec5SDimitry Andric ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent,
960b57cec5SDimitry Andric                                          const char *RawHeaderPtr,
970b57cec5SDimitry Andric                                          uint64_t Size, Error *Err)
9804eeddc0SDimitry Andric     : CommonArchiveMemberHeader<UnixArMemHdrType>(
9904eeddc0SDimitry Andric           Parent, reinterpret_cast<const UnixArMemHdrType *>(RawHeaderPtr)) {
1000b57cec5SDimitry Andric   if (RawHeaderPtr == nullptr)
1010b57cec5SDimitry Andric     return;
1020b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(Err);
1030b57cec5SDimitry Andric 
10404eeddc0SDimitry Andric   if (Size < getSizeOf()) {
10504eeddc0SDimitry Andric     *Err = createMemberHeaderParseError(this, RawHeaderPtr, Size);
1060b57cec5SDimitry Andric     return;
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric   if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') {
1090b57cec5SDimitry Andric     if (Err) {
1100b57cec5SDimitry Andric       std::string Buf;
1110b57cec5SDimitry Andric       raw_string_ostream OS(Buf);
112fe6060f1SDimitry Andric       OS.write_escaped(
113fe6060f1SDimitry Andric           StringRef(ArMemHdr->Terminator, sizeof(ArMemHdr->Terminator)));
1140b57cec5SDimitry Andric       OS.flush();
1150b57cec5SDimitry Andric       std::string Msg("terminator characters in archive member \"" + Buf +
1160b57cec5SDimitry Andric                       "\" not the correct \"`\\n\" values for the archive "
1170b57cec5SDimitry Andric                       "member header ");
1180b57cec5SDimitry Andric       Expected<StringRef> NameOrErr = getName(Size);
1190b57cec5SDimitry Andric       if (!NameOrErr) {
1200b57cec5SDimitry Andric         consumeError(NameOrErr.takeError());
1210b57cec5SDimitry Andric         uint64_t Offset = RawHeaderPtr - Parent->getData().data();
1220b57cec5SDimitry Andric         *Err = malformedError(Msg + "at offset " + Twine(Offset));
1230b57cec5SDimitry Andric       } else
1240b57cec5SDimitry Andric         *Err = malformedError(Msg + "for " + NameOrErr.get());
1250b57cec5SDimitry Andric     }
1260b57cec5SDimitry Andric     return;
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
13004eeddc0SDimitry Andric BigArchiveMemberHeader::BigArchiveMemberHeader(const Archive *Parent,
13104eeddc0SDimitry Andric                                                const char *RawHeaderPtr,
13204eeddc0SDimitry Andric                                                uint64_t Size, Error *Err)
13304eeddc0SDimitry Andric     : CommonArchiveMemberHeader<BigArMemHdrType>(
13404eeddc0SDimitry Andric           Parent, reinterpret_cast<const BigArMemHdrType *>(RawHeaderPtr)) {
13504eeddc0SDimitry Andric   if (RawHeaderPtr == nullptr)
13604eeddc0SDimitry Andric     return;
13704eeddc0SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(Err);
13804eeddc0SDimitry Andric 
13906c3fb27SDimitry Andric   if (RawHeaderPtr + getSizeOf() >= Parent->getData().end()) {
14006c3fb27SDimitry Andric     if (Err)
14106c3fb27SDimitry Andric       *Err = malformedError("malformed AIX big archive: remaining buffer is "
14206c3fb27SDimitry Andric                             "unable to contain next archive member");
14306c3fb27SDimitry Andric     return;
14406c3fb27SDimitry Andric   }
14506c3fb27SDimitry Andric 
146bdd1243dSDimitry Andric   if (Size < getSizeOf()) {
147bdd1243dSDimitry Andric     Error SubErr = createMemberHeaderParseError(this, RawHeaderPtr, Size);
148bdd1243dSDimitry Andric     if (Err)
149bdd1243dSDimitry Andric       *Err = std::move(SubErr);
150bdd1243dSDimitry Andric   }
15104eeddc0SDimitry Andric }
15204eeddc0SDimitry Andric 
1530b57cec5SDimitry Andric // This gets the raw name from the ArMemHdr->Name field and checks that it is
1540b57cec5SDimitry Andric // valid for the kind of archive.  If it is not valid it returns an Error.
1550b57cec5SDimitry Andric Expected<StringRef> ArchiveMemberHeader::getRawName() const {
1560b57cec5SDimitry Andric   char EndCond;
1570b57cec5SDimitry Andric   auto Kind = Parent->kind();
1580b57cec5SDimitry Andric   if (Kind == Archive::K_BSD || Kind == Archive::K_DARWIN64) {
1590b57cec5SDimitry Andric     if (ArMemHdr->Name[0] == ' ') {
160fe6060f1SDimitry Andric       uint64_t Offset =
161fe6060f1SDimitry Andric           reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
1620b57cec5SDimitry Andric       return malformedError("name contains a leading space for archive member "
163fe6060f1SDimitry Andric                             "header at offset " +
164fe6060f1SDimitry Andric                             Twine(Offset));
1650b57cec5SDimitry Andric     }
1660b57cec5SDimitry Andric     EndCond = ' ';
167fe6060f1SDimitry Andric   } else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#')
1680b57cec5SDimitry Andric     EndCond = ' ';
1690b57cec5SDimitry Andric   else
1700b57cec5SDimitry Andric     EndCond = '/';
1710b57cec5SDimitry Andric   StringRef::size_type end =
1720b57cec5SDimitry Andric       StringRef(ArMemHdr->Name, sizeof(ArMemHdr->Name)).find(EndCond);
1730b57cec5SDimitry Andric   if (end == StringRef::npos)
1740b57cec5SDimitry Andric     end = sizeof(ArMemHdr->Name);
1750b57cec5SDimitry Andric   assert(end <= sizeof(ArMemHdr->Name) && end > 0);
1760b57cec5SDimitry Andric   // Don't include the EndCond if there is one.
1770b57cec5SDimitry Andric   return StringRef(ArMemHdr->Name, end);
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
18004eeddc0SDimitry Andric Expected<uint64_t>
18104eeddc0SDimitry Andric getArchiveMemberDecField(Twine FieldName, const StringRef RawField,
18204eeddc0SDimitry Andric                          const Archive *Parent,
18304eeddc0SDimitry Andric                          const AbstractArchiveMemberHeader *MemHeader) {
18404eeddc0SDimitry Andric   uint64_t Value;
18504eeddc0SDimitry Andric   if (RawField.getAsInteger(10, Value)) {
18604eeddc0SDimitry Andric     uint64_t Offset = MemHeader->getOffset();
18704eeddc0SDimitry Andric     return malformedError("characters in " + FieldName +
18804eeddc0SDimitry Andric                           " field in archive member header are not "
18904eeddc0SDimitry Andric                           "all decimal numbers: '" +
19004eeddc0SDimitry Andric                           RawField +
19104eeddc0SDimitry Andric                           "' for the archive "
19204eeddc0SDimitry Andric                           "member header at offset " +
19304eeddc0SDimitry Andric                           Twine(Offset));
19404eeddc0SDimitry Andric   }
19504eeddc0SDimitry Andric   return Value;
19604eeddc0SDimitry Andric }
19704eeddc0SDimitry Andric 
19804eeddc0SDimitry Andric Expected<uint64_t>
19904eeddc0SDimitry Andric getArchiveMemberOctField(Twine FieldName, const StringRef RawField,
20004eeddc0SDimitry Andric                          const Archive *Parent,
20104eeddc0SDimitry Andric                          const AbstractArchiveMemberHeader *MemHeader) {
20204eeddc0SDimitry Andric   uint64_t Value;
20304eeddc0SDimitry Andric   if (RawField.getAsInteger(8, Value)) {
20404eeddc0SDimitry Andric     uint64_t Offset = MemHeader->getOffset();
20504eeddc0SDimitry Andric     return malformedError("characters in " + FieldName +
20604eeddc0SDimitry Andric                           " field in archive member header are not "
20704eeddc0SDimitry Andric                           "all octal numbers: '" +
20804eeddc0SDimitry Andric                           RawField +
20904eeddc0SDimitry Andric                           "' for the archive "
21004eeddc0SDimitry Andric                           "member header at offset " +
21104eeddc0SDimitry Andric                           Twine(Offset));
21204eeddc0SDimitry Andric   }
21304eeddc0SDimitry Andric   return Value;
21404eeddc0SDimitry Andric }
21504eeddc0SDimitry Andric 
21604eeddc0SDimitry Andric Expected<StringRef> BigArchiveMemberHeader::getRawName() const {
21704eeddc0SDimitry Andric   Expected<uint64_t> NameLenOrErr = getArchiveMemberDecField(
21804eeddc0SDimitry Andric       "NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);
21904eeddc0SDimitry Andric   if (!NameLenOrErr)
22004eeddc0SDimitry Andric     // TODO: Out-of-line.
22104eeddc0SDimitry Andric     return NameLenOrErr.takeError();
22204eeddc0SDimitry Andric   uint64_t NameLen = NameLenOrErr.get();
22304eeddc0SDimitry Andric 
22404eeddc0SDimitry Andric   // If the name length is odd, pad with '\0' to get an even length. After
22504eeddc0SDimitry Andric   // padding, there is the name terminator "`\n".
22604eeddc0SDimitry Andric   uint64_t NameLenWithPadding = alignTo(NameLen, 2);
22704eeddc0SDimitry Andric   StringRef NameTerminator = "`\n";
22804eeddc0SDimitry Andric   StringRef NameStringWithNameTerminator =
22904eeddc0SDimitry Andric       StringRef(ArMemHdr->Name, NameLenWithPadding + NameTerminator.size());
2305f757f3fSDimitry Andric   if (!NameStringWithNameTerminator.ends_with(NameTerminator)) {
23104eeddc0SDimitry Andric     uint64_t Offset =
23204eeddc0SDimitry Andric         reinterpret_cast<const char *>(ArMemHdr->Name + NameLenWithPadding) -
23304eeddc0SDimitry Andric         Parent->getData().data();
23404eeddc0SDimitry Andric     // TODO: Out-of-line.
23504eeddc0SDimitry Andric     return malformedError(
23604eeddc0SDimitry Andric         "name does not have name terminator \"`\\n\" for archive member"
23704eeddc0SDimitry Andric         "header at offset " +
23804eeddc0SDimitry Andric         Twine(Offset));
23904eeddc0SDimitry Andric   }
24004eeddc0SDimitry Andric   return StringRef(ArMemHdr->Name, NameLen);
24104eeddc0SDimitry Andric }
24204eeddc0SDimitry Andric 
2430b57cec5SDimitry Andric // member including the header, so the size of any name following the header
2440b57cec5SDimitry Andric // is checked to make sure it does not overflow.
2450b57cec5SDimitry Andric Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   // This can be called from the ArchiveMemberHeader constructor when the
2480b57cec5SDimitry Andric   // archive header is truncated to produce an error message with the name.
2490b57cec5SDimitry Andric   // Make sure the name field is not truncated.
25004eeddc0SDimitry Andric   if (Size < offsetof(UnixArMemHdrType, Name) + sizeof(ArMemHdr->Name)) {
251fe6060f1SDimitry Andric     uint64_t ArchiveOffset =
252fe6060f1SDimitry Andric         reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
2530b57cec5SDimitry Andric     return malformedError("archive header truncated before the name field "
2540b57cec5SDimitry Andric                           "for archive member header at offset " +
2550b57cec5SDimitry Andric                           Twine(ArchiveOffset));
2560b57cec5SDimitry Andric   }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   // The raw name itself can be invalid.
2590b57cec5SDimitry Andric   Expected<StringRef> NameOrErr = getRawName();
2600b57cec5SDimitry Andric   if (!NameOrErr)
2610b57cec5SDimitry Andric     return NameOrErr.takeError();
2620b57cec5SDimitry Andric   StringRef Name = NameOrErr.get();
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   // Check if it's a special name.
2650b57cec5SDimitry Andric   if (Name[0] == '/') {
2660b57cec5SDimitry Andric     if (Name.size() == 1) // Linker member.
2670b57cec5SDimitry Andric       return Name;
2680b57cec5SDimitry Andric     if (Name.size() == 2 && Name[1] == '/') // String table.
2690b57cec5SDimitry Andric       return Name;
27081ad6265SDimitry Andric     // System libraries from the Windows SDK for Windows 11 contain this symbol.
27181ad6265SDimitry Andric     // It looks like a CFG guard: we just skip it for now.
272*0fca6ea1SDimitry Andric     if (Name == "/<XFGHASHMAP>/")
27381ad6265SDimitry Andric       return Name;
27481ad6265SDimitry Andric     // Some libraries (e.g., arm64rt.lib) from the Windows WDK
27581ad6265SDimitry Andric     // (version 10.0.22000.0) contain this undocumented special member.
276*0fca6ea1SDimitry Andric     if (Name == "/<ECSYMBOLS>/")
27781ad6265SDimitry Andric       return Name;
2780b57cec5SDimitry Andric     // It's a long name.
2790b57cec5SDimitry Andric     // Get the string table offset.
2800b57cec5SDimitry Andric     std::size_t StringOffset;
2810b57cec5SDimitry Andric     if (Name.substr(1).rtrim(' ').getAsInteger(10, StringOffset)) {
2820b57cec5SDimitry Andric       std::string Buf;
2830b57cec5SDimitry Andric       raw_string_ostream OS(Buf);
2840b57cec5SDimitry Andric       OS.write_escaped(Name.substr(1).rtrim(' '));
2850b57cec5SDimitry Andric       OS.flush();
286fe6060f1SDimitry Andric       uint64_t ArchiveOffset =
287fe6060f1SDimitry Andric           reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
2880b57cec5SDimitry Andric       return malformedError("long name offset characters after the '/' are "
289fe6060f1SDimitry Andric                             "not all decimal numbers: '" +
290fe6060f1SDimitry Andric                             Buf + "' for archive member header at offset " +
2910b57cec5SDimitry Andric                             Twine(ArchiveOffset));
2920b57cec5SDimitry Andric     }
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric     // Verify it.
2950b57cec5SDimitry Andric     if (StringOffset >= Parent->getStringTable().size()) {
296fe6060f1SDimitry Andric       uint64_t ArchiveOffset =
297fe6060f1SDimitry Andric           reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
298fe6060f1SDimitry Andric       return malformedError("long name offset " + Twine(StringOffset) +
299fe6060f1SDimitry Andric                             " past the end of the string table for archive "
300fe6060f1SDimitry Andric                             "member header at offset " +
301fe6060f1SDimitry Andric                             Twine(ArchiveOffset));
3020b57cec5SDimitry Andric     }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric     // GNU long file names end with a "/\n".
3050b57cec5SDimitry Andric     if (Parent->kind() == Archive::K_GNU ||
3060b57cec5SDimitry Andric         Parent->kind() == Archive::K_GNU64) {
3070b57cec5SDimitry Andric       size_t End = Parent->getStringTable().find('\n', /*From=*/StringOffset);
3080b57cec5SDimitry Andric       if (End == StringRef::npos || End < 1 ||
3090b57cec5SDimitry Andric           Parent->getStringTable()[End - 1] != '/') {
3100b57cec5SDimitry Andric         return malformedError("string table at long name offset " +
3110b57cec5SDimitry Andric                               Twine(StringOffset) + "not terminated");
3120b57cec5SDimitry Andric       }
3130b57cec5SDimitry Andric       return Parent->getStringTable().slice(StringOffset, End - 1);
3140b57cec5SDimitry Andric     }
3150b57cec5SDimitry Andric     return Parent->getStringTable().begin() + StringOffset;
3160b57cec5SDimitry Andric   }
3170b57cec5SDimitry Andric 
3185f757f3fSDimitry Andric   if (Name.starts_with("#1/")) {
3190b57cec5SDimitry Andric     uint64_t NameLength;
3200b57cec5SDimitry Andric     if (Name.substr(3).rtrim(' ').getAsInteger(10, NameLength)) {
3210b57cec5SDimitry Andric       std::string Buf;
3220b57cec5SDimitry Andric       raw_string_ostream OS(Buf);
3230b57cec5SDimitry Andric       OS.write_escaped(Name.substr(3).rtrim(' '));
3240b57cec5SDimitry Andric       OS.flush();
325fe6060f1SDimitry Andric       uint64_t ArchiveOffset =
326fe6060f1SDimitry Andric           reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
3270b57cec5SDimitry Andric       return malformedError("long name length characters after the #1/ are "
328fe6060f1SDimitry Andric                             "not all decimal numbers: '" +
329fe6060f1SDimitry Andric                             Buf + "' for archive member header at offset " +
3300b57cec5SDimitry Andric                             Twine(ArchiveOffset));
3310b57cec5SDimitry Andric     }
3320b57cec5SDimitry Andric     if (getSizeOf() + NameLength > Size) {
333fe6060f1SDimitry Andric       uint64_t ArchiveOffset =
334fe6060f1SDimitry Andric           reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
3350b57cec5SDimitry Andric       return malformedError("long name length: " + Twine(NameLength) +
3360b57cec5SDimitry Andric                             " extends past the end of the member or archive "
3370b57cec5SDimitry Andric                             "for archive member header at offset " +
3380b57cec5SDimitry Andric                             Twine(ArchiveOffset));
3390b57cec5SDimitry Andric     }
3400b57cec5SDimitry Andric     return StringRef(reinterpret_cast<const char *>(ArMemHdr) + getSizeOf(),
341fe6060f1SDimitry Andric                      NameLength)
342fe6060f1SDimitry Andric         .rtrim('\0');
3430b57cec5SDimitry Andric   }
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric   // It is not a long name so trim the blanks at the end of the name.
3460b57cec5SDimitry Andric   if (Name[Name.size() - 1] != '/')
3470b57cec5SDimitry Andric     return Name.rtrim(' ');
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   // It's a simple name.
3500b57cec5SDimitry Andric   return Name.drop_back(1);
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric 
35304eeddc0SDimitry Andric Expected<StringRef> BigArchiveMemberHeader::getName(uint64_t Size) const {
35404eeddc0SDimitry Andric   return getRawName();
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric 
35704eeddc0SDimitry Andric Expected<uint64_t> ArchiveMemberHeader::getSize() const {
35804eeddc0SDimitry Andric   return getArchiveMemberDecField("size", getFieldRawString(ArMemHdr->Size),
35904eeddc0SDimitry Andric                                   Parent, this);
3600b57cec5SDimitry Andric }
36104eeddc0SDimitry Andric 
36204eeddc0SDimitry Andric Expected<uint64_t> BigArchiveMemberHeader::getSize() const {
36304eeddc0SDimitry Andric   Expected<uint64_t> SizeOrErr = getArchiveMemberDecField(
36404eeddc0SDimitry Andric       "size", getFieldRawString(ArMemHdr->Size), Parent, this);
36504eeddc0SDimitry Andric   if (!SizeOrErr)
36604eeddc0SDimitry Andric     return SizeOrErr.takeError();
36704eeddc0SDimitry Andric 
36804eeddc0SDimitry Andric   Expected<uint64_t> NameLenOrErr = getRawNameSize();
36904eeddc0SDimitry Andric   if (!NameLenOrErr)
37004eeddc0SDimitry Andric     return NameLenOrErr.takeError();
37104eeddc0SDimitry Andric 
37204eeddc0SDimitry Andric   return *SizeOrErr + alignTo(*NameLenOrErr, 2);
37304eeddc0SDimitry Andric }
37404eeddc0SDimitry Andric 
37504eeddc0SDimitry Andric Expected<uint64_t> BigArchiveMemberHeader::getRawNameSize() const {
37604eeddc0SDimitry Andric   return getArchiveMemberDecField(
37704eeddc0SDimitry Andric       "NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);
37804eeddc0SDimitry Andric }
37904eeddc0SDimitry Andric 
38004eeddc0SDimitry Andric Expected<uint64_t> BigArchiveMemberHeader::getNextOffset() const {
38104eeddc0SDimitry Andric   return getArchiveMemberDecField(
38204eeddc0SDimitry Andric       "NextOffset", getFieldRawString(ArMemHdr->NextOffset), Parent, this);
38304eeddc0SDimitry Andric }
38404eeddc0SDimitry Andric 
38504eeddc0SDimitry Andric Expected<sys::fs::perms> AbstractArchiveMemberHeader::getAccessMode() const {
38604eeddc0SDimitry Andric   Expected<uint64_t> AccessModeOrErr =
38704eeddc0SDimitry Andric       getArchiveMemberOctField("AccessMode", getRawAccessMode(), Parent, this);
38804eeddc0SDimitry Andric   if (!AccessModeOrErr)
38904eeddc0SDimitry Andric     return AccessModeOrErr.takeError();
39004eeddc0SDimitry Andric   return static_cast<sys::fs::perms>(*AccessModeOrErr);
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric Expected<sys::TimePoint<std::chrono::seconds>>
39404eeddc0SDimitry Andric AbstractArchiveMemberHeader::getLastModified() const {
39504eeddc0SDimitry Andric   Expected<uint64_t> SecondsOrErr = getArchiveMemberDecField(
39604eeddc0SDimitry Andric       "LastModified", getRawLastModified(), Parent, this);
39704eeddc0SDimitry Andric 
39804eeddc0SDimitry Andric   if (!SecondsOrErr)
39904eeddc0SDimitry Andric     return SecondsOrErr.takeError();
40004eeddc0SDimitry Andric 
40104eeddc0SDimitry Andric   return sys::toTimePoint(*SecondsOrErr);
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric 
40404eeddc0SDimitry Andric Expected<unsigned> AbstractArchiveMemberHeader::getUID() const {
40504eeddc0SDimitry Andric   StringRef User = getRawUID();
4060b57cec5SDimitry Andric   if (User.empty())
4070b57cec5SDimitry Andric     return 0;
40804eeddc0SDimitry Andric   return getArchiveMemberDecField("UID", User, Parent, this);
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric 
41104eeddc0SDimitry Andric Expected<unsigned> AbstractArchiveMemberHeader::getGID() const {
41204eeddc0SDimitry Andric   StringRef Group = getRawGID();
4130b57cec5SDimitry Andric   if (Group.empty())
4140b57cec5SDimitry Andric     return 0;
41504eeddc0SDimitry Andric   return getArchiveMemberDecField("GID", Group, Parent, this);
4160b57cec5SDimitry Andric }
41704eeddc0SDimitry Andric 
41804eeddc0SDimitry Andric Expected<bool> ArchiveMemberHeader::isThin() const {
41904eeddc0SDimitry Andric   Expected<StringRef> NameOrErr = getRawName();
42004eeddc0SDimitry Andric   if (!NameOrErr)
42104eeddc0SDimitry Andric     return NameOrErr.takeError();
42204eeddc0SDimitry Andric   StringRef Name = NameOrErr.get();
42304eeddc0SDimitry Andric   return Parent->isThin() && Name != "/" && Name != "//" && Name != "/SYM64/";
42404eeddc0SDimitry Andric }
42504eeddc0SDimitry Andric 
42604eeddc0SDimitry Andric Expected<const char *> ArchiveMemberHeader::getNextChildLoc() const {
42704eeddc0SDimitry Andric   uint64_t Size = getSizeOf();
42804eeddc0SDimitry Andric   Expected<bool> isThinOrErr = isThin();
42904eeddc0SDimitry Andric   if (!isThinOrErr)
43004eeddc0SDimitry Andric     return isThinOrErr.takeError();
43104eeddc0SDimitry Andric 
43204eeddc0SDimitry Andric   bool isThin = isThinOrErr.get();
43304eeddc0SDimitry Andric   if (!isThin) {
43404eeddc0SDimitry Andric     Expected<uint64_t> MemberSize = getSize();
43504eeddc0SDimitry Andric     if (!MemberSize)
43604eeddc0SDimitry Andric       return MemberSize.takeError();
43704eeddc0SDimitry Andric 
43804eeddc0SDimitry Andric     Size += MemberSize.get();
43904eeddc0SDimitry Andric   }
44004eeddc0SDimitry Andric 
44104eeddc0SDimitry Andric   // If Size is odd, add 1 to make it even.
44204eeddc0SDimitry Andric   const char *NextLoc =
44304eeddc0SDimitry Andric       reinterpret_cast<const char *>(ArMemHdr) + alignTo(Size, 2);
44404eeddc0SDimitry Andric 
44504eeddc0SDimitry Andric   if (NextLoc == Parent->getMemoryBufferRef().getBufferEnd())
44604eeddc0SDimitry Andric     return nullptr;
44704eeddc0SDimitry Andric 
44804eeddc0SDimitry Andric   return NextLoc;
44904eeddc0SDimitry Andric }
45004eeddc0SDimitry Andric 
45104eeddc0SDimitry Andric Expected<const char *> BigArchiveMemberHeader::getNextChildLoc() const {
45204eeddc0SDimitry Andric   if (getOffset() ==
45304eeddc0SDimitry Andric       static_cast<const BigArchive *>(Parent)->getLastChildOffset())
45404eeddc0SDimitry Andric     return nullptr;
45504eeddc0SDimitry Andric 
45604eeddc0SDimitry Andric   Expected<uint64_t> NextOffsetOrErr = getNextOffset();
45704eeddc0SDimitry Andric   if (!NextOffsetOrErr)
45804eeddc0SDimitry Andric     return NextOffsetOrErr.takeError();
45904eeddc0SDimitry Andric   return Parent->getData().data() + NextOffsetOrErr.get();
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric Archive::Child::Child(const Archive *Parent, StringRef Data,
4630b57cec5SDimitry Andric                       uint16_t StartOfFile)
46404eeddc0SDimitry Andric     : Parent(Parent), Data(Data), StartOfFile(StartOfFile) {
46504eeddc0SDimitry Andric   Header = Parent->createArchiveMemberHeader(Data.data(), Data.size(), nullptr);
46604eeddc0SDimitry Andric }
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
46904eeddc0SDimitry Andric     : Parent(Parent) {
47004eeddc0SDimitry Andric   if (!Start) {
47104eeddc0SDimitry Andric     Header = nullptr;
47206c3fb27SDimitry Andric     StartOfFile = -1;
4730b57cec5SDimitry Andric     return;
47404eeddc0SDimitry Andric   }
47504eeddc0SDimitry Andric 
47604eeddc0SDimitry Andric   Header = Parent->createArchiveMemberHeader(
47704eeddc0SDimitry Andric       Start,
47804eeddc0SDimitry Andric       Parent ? Parent->getData().size() - (Start - Parent->getData().data())
47904eeddc0SDimitry Andric              : 0,
48004eeddc0SDimitry Andric       Err);
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   // If we are pointed to real data, Start is not a nullptr, then there must be
4830b57cec5SDimitry Andric   // a non-null Err pointer available to report malformed data on.  Only in
4840b57cec5SDimitry Andric   // the case sentinel value is being constructed is Err is permitted to be a
4850b57cec5SDimitry Andric   // nullptr.
4860b57cec5SDimitry Andric   assert(Err && "Err can't be nullptr if Start is not a nullptr");
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(Err);
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   // If there was an error in the construction of the Header
4910b57cec5SDimitry Andric   // then just return with the error now set.
4920b57cec5SDimitry Andric   if (*Err)
4930b57cec5SDimitry Andric     return;
4940b57cec5SDimitry Andric 
49504eeddc0SDimitry Andric   uint64_t Size = Header->getSizeOf();
4960b57cec5SDimitry Andric   Data = StringRef(Start, Size);
4970b57cec5SDimitry Andric   Expected<bool> isThinOrErr = isThinMember();
4980b57cec5SDimitry Andric   if (!isThinOrErr) {
4990b57cec5SDimitry Andric     *Err = isThinOrErr.takeError();
5000b57cec5SDimitry Andric     return;
5010b57cec5SDimitry Andric   }
5020b57cec5SDimitry Andric   bool isThin = isThinOrErr.get();
5030b57cec5SDimitry Andric   if (!isThin) {
5040b57cec5SDimitry Andric     Expected<uint64_t> MemberSize = getRawSize();
5050b57cec5SDimitry Andric     if (!MemberSize) {
5060b57cec5SDimitry Andric       *Err = MemberSize.takeError();
5070b57cec5SDimitry Andric       return;
5080b57cec5SDimitry Andric     }
5090b57cec5SDimitry Andric     Size += MemberSize.get();
5100b57cec5SDimitry Andric     Data = StringRef(Start, Size);
5110b57cec5SDimitry Andric   }
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   // Setup StartOfFile and PaddingBytes.
51404eeddc0SDimitry Andric   StartOfFile = Header->getSizeOf();
5150b57cec5SDimitry Andric   // Don't include attached name.
5160b57cec5SDimitry Andric   Expected<StringRef> NameOrErr = getRawName();
5170b57cec5SDimitry Andric   if (!NameOrErr) {
5180b57cec5SDimitry Andric     *Err = NameOrErr.takeError();
5190b57cec5SDimitry Andric     return;
5200b57cec5SDimitry Andric   }
5210b57cec5SDimitry Andric   StringRef Name = NameOrErr.get();
52204eeddc0SDimitry Andric 
52304eeddc0SDimitry Andric   if (Parent->kind() == Archive::K_AIXBIG) {
52404eeddc0SDimitry Andric     // The actual start of the file is after the name and any necessary
52504eeddc0SDimitry Andric     // even-alignment padding.
52604eeddc0SDimitry Andric     StartOfFile += ((Name.size() + 1) >> 1) << 1;
5275f757f3fSDimitry Andric   } else if (Name.starts_with("#1/")) {
5280b57cec5SDimitry Andric     uint64_t NameSize;
52904eeddc0SDimitry Andric     StringRef RawNameSize = Name.substr(3).rtrim(' ');
53004eeddc0SDimitry Andric     if (RawNameSize.getAsInteger(10, NameSize)) {
5310b57cec5SDimitry Andric       uint64_t Offset = Start - Parent->getData().data();
5320b57cec5SDimitry Andric       *Err = malformedError("long name length characters after the #1/ are "
533fe6060f1SDimitry Andric                             "not all decimal numbers: '" +
53404eeddc0SDimitry Andric                             RawNameSize +
53504eeddc0SDimitry Andric                             "' for archive member header at offset " +
5360b57cec5SDimitry Andric                             Twine(Offset));
5370b57cec5SDimitry Andric       return;
5380b57cec5SDimitry Andric     }
5390b57cec5SDimitry Andric     StartOfFile += NameSize;
5400b57cec5SDimitry Andric   }
5410b57cec5SDimitry Andric }
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric Expected<uint64_t> Archive::Child::getSize() const {
5445ffd83dbSDimitry Andric   if (Parent->IsThin)
54504eeddc0SDimitry Andric     return Header->getSize();
5460b57cec5SDimitry Andric   return Data.size() - StartOfFile;
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric Expected<uint64_t> Archive::Child::getRawSize() const {
55004eeddc0SDimitry Andric   return Header->getSize();
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric 
55304eeddc0SDimitry Andric Expected<bool> Archive::Child::isThinMember() const { return Header->isThin(); }
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric Expected<std::string> Archive::Child::getFullName() const {
5560b57cec5SDimitry Andric   Expected<bool> isThin = isThinMember();
5570b57cec5SDimitry Andric   if (!isThin)
5580b57cec5SDimitry Andric     return isThin.takeError();
5590b57cec5SDimitry Andric   assert(isThin.get());
5600b57cec5SDimitry Andric   Expected<StringRef> NameOrErr = getName();
5610b57cec5SDimitry Andric   if (!NameOrErr)
5620b57cec5SDimitry Andric     return NameOrErr.takeError();
5630b57cec5SDimitry Andric   StringRef Name = *NameOrErr;
5640b57cec5SDimitry Andric   if (sys::path::is_absolute(Name))
5655ffd83dbSDimitry Andric     return std::string(Name);
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric   SmallString<128> FullName = sys::path::parent_path(
5680b57cec5SDimitry Andric       Parent->getMemoryBufferRef().getBufferIdentifier());
5690b57cec5SDimitry Andric   sys::path::append(FullName, Name);
5707a6dacacSDimitry Andric   return std::string(FullName);
5710b57cec5SDimitry Andric }
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric Expected<StringRef> Archive::Child::getBuffer() const {
5740b57cec5SDimitry Andric   Expected<bool> isThinOrErr = isThinMember();
5750b57cec5SDimitry Andric   if (!isThinOrErr)
5760b57cec5SDimitry Andric     return isThinOrErr.takeError();
5770b57cec5SDimitry Andric   bool isThin = isThinOrErr.get();
5780b57cec5SDimitry Andric   if (!isThin) {
5795ffd83dbSDimitry Andric     Expected<uint64_t> Size = getSize();
5800b57cec5SDimitry Andric     if (!Size)
5810b57cec5SDimitry Andric       return Size.takeError();
5820b57cec5SDimitry Andric     return StringRef(Data.data() + StartOfFile, Size.get());
5830b57cec5SDimitry Andric   }
5840b57cec5SDimitry Andric   Expected<std::string> FullNameOrErr = getFullName();
5850b57cec5SDimitry Andric   if (!FullNameOrErr)
5860b57cec5SDimitry Andric     return FullNameOrErr.takeError();
5870b57cec5SDimitry Andric   const std::string &FullName = *FullNameOrErr;
5880b57cec5SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName);
5890b57cec5SDimitry Andric   if (std::error_code EC = Buf.getError())
5900b57cec5SDimitry Andric     return errorCodeToError(EC);
5910b57cec5SDimitry Andric   Parent->ThinBuffers.push_back(std::move(*Buf));
5920b57cec5SDimitry Andric   return Parent->ThinBuffers.back()->getBuffer();
5930b57cec5SDimitry Andric }
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric Expected<Archive::Child> Archive::Child::getNext() const {
59604eeddc0SDimitry Andric   Expected<const char *> NextLocOrErr = Header->getNextChildLoc();
59704eeddc0SDimitry Andric   if (!NextLocOrErr)
59804eeddc0SDimitry Andric     return NextLocOrErr.takeError();
5990b57cec5SDimitry Andric 
60004eeddc0SDimitry Andric   const char *NextLoc = *NextLocOrErr;
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric   // Check to see if this is at the end of the archive.
60304eeddc0SDimitry Andric   if (NextLoc == nullptr)
6040b57cec5SDimitry Andric     return Child(nullptr, nullptr, nullptr);
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   // Check to see if this is past the end of the archive.
6070b57cec5SDimitry Andric   if (NextLoc > Parent->Data.getBufferEnd()) {
6080b57cec5SDimitry Andric     std::string Msg("offset to next archive member past the end of the archive "
6090b57cec5SDimitry Andric                     "after member ");
6100b57cec5SDimitry Andric     Expected<StringRef> NameOrErr = getName();
6110b57cec5SDimitry Andric     if (!NameOrErr) {
6120b57cec5SDimitry Andric       consumeError(NameOrErr.takeError());
6130b57cec5SDimitry Andric       uint64_t Offset = Data.data() - Parent->getData().data();
6140b57cec5SDimitry Andric       return malformedError(Msg + "at offset " + Twine(Offset));
6150b57cec5SDimitry Andric     } else
6160b57cec5SDimitry Andric       return malformedError(Msg + NameOrErr.get());
6170b57cec5SDimitry Andric   }
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   Error Err = Error::success();
6200b57cec5SDimitry Andric   Child Ret(Parent, NextLoc, &Err);
6210b57cec5SDimitry Andric   if (Err)
6220b57cec5SDimitry Andric     return std::move(Err);
6230b57cec5SDimitry Andric   return Ret;
6240b57cec5SDimitry Andric }
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric uint64_t Archive::Child::getChildOffset() const {
6270b57cec5SDimitry Andric   const char *a = Parent->Data.getBuffer().data();
6280b57cec5SDimitry Andric   const char *c = Data.data();
6290b57cec5SDimitry Andric   uint64_t offset = c - a;
6300b57cec5SDimitry Andric   return offset;
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric Expected<StringRef> Archive::Child::getName() const {
6340b57cec5SDimitry Andric   Expected<uint64_t> RawSizeOrErr = getRawSize();
6350b57cec5SDimitry Andric   if (!RawSizeOrErr)
6360b57cec5SDimitry Andric     return RawSizeOrErr.takeError();
6370b57cec5SDimitry Andric   uint64_t RawSize = RawSizeOrErr.get();
63804eeddc0SDimitry Andric   Expected<StringRef> NameOrErr =
63904eeddc0SDimitry Andric       Header->getName(Header->getSizeOf() + RawSize);
6400b57cec5SDimitry Andric   if (!NameOrErr)
6410b57cec5SDimitry Andric     return NameOrErr.takeError();
6420b57cec5SDimitry Andric   StringRef Name = NameOrErr.get();
6430b57cec5SDimitry Andric   return Name;
6440b57cec5SDimitry Andric }
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric Expected<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {
6470b57cec5SDimitry Andric   Expected<StringRef> NameOrErr = getName();
6480b57cec5SDimitry Andric   if (!NameOrErr)
6490b57cec5SDimitry Andric     return NameOrErr.takeError();
6500b57cec5SDimitry Andric   StringRef Name = NameOrErr.get();
6510b57cec5SDimitry Andric   Expected<StringRef> Buf = getBuffer();
6520b57cec5SDimitry Andric   if (!Buf)
6530b57cec5SDimitry Andric     return createFileError(Name, Buf.takeError());
6540b57cec5SDimitry Andric   return MemoryBufferRef(*Buf, Name);
6550b57cec5SDimitry Andric }
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric Expected<std::unique_ptr<Binary>>
6580b57cec5SDimitry Andric Archive::Child::getAsBinary(LLVMContext *Context) const {
6590b57cec5SDimitry Andric   Expected<MemoryBufferRef> BuffOrErr = getMemoryBufferRef();
6600b57cec5SDimitry Andric   if (!BuffOrErr)
6610b57cec5SDimitry Andric     return BuffOrErr.takeError();
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   auto BinaryOrErr = createBinary(BuffOrErr.get(), Context);
6640b57cec5SDimitry Andric   if (BinaryOrErr)
6650b57cec5SDimitry Andric     return std::move(*BinaryOrErr);
6660b57cec5SDimitry Andric   return BinaryOrErr.takeError();
6670b57cec5SDimitry Andric }
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {
6700b57cec5SDimitry Andric   Error Err = Error::success();
67104eeddc0SDimitry Andric   std::unique_ptr<Archive> Ret;
67204eeddc0SDimitry Andric   StringRef Buffer = Source.getBuffer();
67304eeddc0SDimitry Andric 
6745f757f3fSDimitry Andric   if (Buffer.starts_with(BigArchiveMagic))
67504eeddc0SDimitry Andric     Ret = std::make_unique<BigArchive>(Source, Err);
67604eeddc0SDimitry Andric   else
67704eeddc0SDimitry Andric     Ret = std::make_unique<Archive>(Source, Err);
67804eeddc0SDimitry Andric 
6790b57cec5SDimitry Andric   if (Err)
6800b57cec5SDimitry Andric     return std::move(Err);
6810b57cec5SDimitry Andric   return std::move(Ret);
6820b57cec5SDimitry Andric }
6830b57cec5SDimitry Andric 
68404eeddc0SDimitry Andric std::unique_ptr<AbstractArchiveMemberHeader>
68504eeddc0SDimitry Andric Archive::createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size,
68604eeddc0SDimitry Andric                                    Error *Err) const {
68704eeddc0SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(Err);
68804eeddc0SDimitry Andric   if (kind() != K_AIXBIG)
68904eeddc0SDimitry Andric     return std::make_unique<ArchiveMemberHeader>(this, RawHeaderPtr, Size, Err);
69004eeddc0SDimitry Andric   return std::make_unique<BigArchiveMemberHeader>(this, RawHeaderPtr, Size,
69104eeddc0SDimitry Andric                                                   Err);
69204eeddc0SDimitry Andric }
69304eeddc0SDimitry Andric 
69404eeddc0SDimitry Andric uint64_t Archive::getArchiveMagicLen() const {
69504eeddc0SDimitry Andric   if (isThin())
69604eeddc0SDimitry Andric     return sizeof(ThinArchiveMagic) - 1;
69704eeddc0SDimitry Andric 
69804eeddc0SDimitry Andric   if (Kind() == K_AIXBIG)
69904eeddc0SDimitry Andric     return sizeof(BigArchiveMagic) - 1;
70004eeddc0SDimitry Andric 
70104eeddc0SDimitry Andric   return sizeof(ArchiveMagic) - 1;
70204eeddc0SDimitry Andric }
70304eeddc0SDimitry Andric 
7040b57cec5SDimitry Andric void Archive::setFirstRegular(const Child &C) {
7050b57cec5SDimitry Andric   FirstRegularData = C.Data;
7060b57cec5SDimitry Andric   FirstRegularStartOfFile = C.StartOfFile;
7070b57cec5SDimitry Andric }
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric Archive::Archive(MemoryBufferRef Source, Error &Err)
7100b57cec5SDimitry Andric     : Binary(Binary::ID_Archive, Source) {
7110b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
7120b57cec5SDimitry Andric   StringRef Buffer = Data.getBuffer();
7130b57cec5SDimitry Andric   // Check for sufficient magic.
7145f757f3fSDimitry Andric   if (Buffer.starts_with(ThinArchiveMagic)) {
7150b57cec5SDimitry Andric     IsThin = true;
7165f757f3fSDimitry Andric   } else if (Buffer.starts_with(ArchiveMagic)) {
7170b57cec5SDimitry Andric     IsThin = false;
7185f757f3fSDimitry Andric   } else if (Buffer.starts_with(BigArchiveMagic)) {
71904eeddc0SDimitry Andric     Format = K_AIXBIG;
72004eeddc0SDimitry Andric     IsThin = false;
72104eeddc0SDimitry Andric     return;
7220b57cec5SDimitry Andric   } else {
7238bcb0991SDimitry Andric     Err = make_error<GenericBinaryError>("file too small to be an archive",
7240b57cec5SDimitry Andric                                          object_error::invalid_file_type);
7250b57cec5SDimitry Andric     return;
7260b57cec5SDimitry Andric   }
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric   // Make sure Format is initialized before any call to
7290b57cec5SDimitry Andric   // ArchiveMemberHeader::getName() is made.  This could be a valid empty
7300b57cec5SDimitry Andric   // archive which is the same in all formats.  So claiming it to be gnu to is
7310b57cec5SDimitry Andric   // fine if not totally correct before we look for a string table or table of
7320b57cec5SDimitry Andric   // contents.
7330b57cec5SDimitry Andric   Format = K_GNU;
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric   // Get the special members.
7360b57cec5SDimitry Andric   child_iterator I = child_begin(Err, false);
7370b57cec5SDimitry Andric   if (Err)
7380b57cec5SDimitry Andric     return;
7390b57cec5SDimitry Andric   child_iterator E = child_end();
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric   // See if this is a valid empty archive and if so return.
7420b57cec5SDimitry Andric   if (I == E) {
7430b57cec5SDimitry Andric     Err = Error::success();
7440b57cec5SDimitry Andric     return;
7450b57cec5SDimitry Andric   }
7460b57cec5SDimitry Andric   const Child *C = &*I;
7470b57cec5SDimitry Andric 
7480b57cec5SDimitry Andric   auto Increment = [&]() {
7490b57cec5SDimitry Andric     ++I;
7500b57cec5SDimitry Andric     if (Err)
7510b57cec5SDimitry Andric       return true;
7520b57cec5SDimitry Andric     C = &*I;
7530b57cec5SDimitry Andric     return false;
7540b57cec5SDimitry Andric   };
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric   Expected<StringRef> NameOrErr = C->getRawName();
7570b57cec5SDimitry Andric   if (!NameOrErr) {
7580b57cec5SDimitry Andric     Err = NameOrErr.takeError();
7590b57cec5SDimitry Andric     return;
7600b57cec5SDimitry Andric   }
7610b57cec5SDimitry Andric   StringRef Name = NameOrErr.get();
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric   // Below is the pattern that is used to figure out the archive format
7640b57cec5SDimitry Andric   // GNU archive format
7650b57cec5SDimitry Andric   //  First member : / (may exist, if it exists, points to the symbol table )
7660b57cec5SDimitry Andric   //  Second member : // (may exist, if it exists, points to the string table)
7670b57cec5SDimitry Andric   //  Note : The string table is used if the filename exceeds 15 characters
7680b57cec5SDimitry Andric   // BSD archive format
7690b57cec5SDimitry Andric   //  First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table)
7700b57cec5SDimitry Andric   //  There is no string table, if the filename exceeds 15 characters or has a
7710b57cec5SDimitry Andric   //  embedded space, the filename has #1/<size>, The size represents the size
7720b57cec5SDimitry Andric   //  of the filename that needs to be read after the archive header
7730b57cec5SDimitry Andric   // COFF archive format
7740b57cec5SDimitry Andric   //  First member : /
7750b57cec5SDimitry Andric   //  Second member : / (provides a directory of symbols)
7760b57cec5SDimitry Andric   //  Third member : // (may exist, if it exists, contains the string table)
7770b57cec5SDimitry Andric   //  Note: Microsoft PE/COFF Spec 8.3 says that the third member is present
7780b57cec5SDimitry Andric   //  even if the string table is empty. However, lib.exe does not in fact
7790b57cec5SDimitry Andric   //  seem to create the third member if there's no member whose filename
7800b57cec5SDimitry Andric   //  exceeds 15 characters. So the third member is optional.
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric   if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {
7830b57cec5SDimitry Andric     if (Name == "__.SYMDEF")
7840b57cec5SDimitry Andric       Format = K_BSD;
7850b57cec5SDimitry Andric     else // Name == "__.SYMDEF_64"
7860b57cec5SDimitry Andric       Format = K_DARWIN64;
7870b57cec5SDimitry Andric     // We know that the symbol table is not an external file, but we still must
7880b57cec5SDimitry Andric     // check any Expected<> return value.
7890b57cec5SDimitry Andric     Expected<StringRef> BufOrErr = C->getBuffer();
7900b57cec5SDimitry Andric     if (!BufOrErr) {
7910b57cec5SDimitry Andric       Err = BufOrErr.takeError();
7920b57cec5SDimitry Andric       return;
7930b57cec5SDimitry Andric     }
7940b57cec5SDimitry Andric     SymbolTable = BufOrErr.get();
7950b57cec5SDimitry Andric     if (Increment())
7960b57cec5SDimitry Andric       return;
7970b57cec5SDimitry Andric     setFirstRegular(*C);
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric     Err = Error::success();
8000b57cec5SDimitry Andric     return;
8010b57cec5SDimitry Andric   }
8020b57cec5SDimitry Andric 
8035f757f3fSDimitry Andric   if (Name.starts_with("#1/")) {
8040b57cec5SDimitry Andric     Format = K_BSD;
8050b57cec5SDimitry Andric     // We know this is BSD, so getName will work since there is no string table.
8060b57cec5SDimitry Andric     Expected<StringRef> NameOrErr = C->getName();
8070b57cec5SDimitry Andric     if (!NameOrErr) {
8080b57cec5SDimitry Andric       Err = NameOrErr.takeError();
8090b57cec5SDimitry Andric       return;
8100b57cec5SDimitry Andric     }
8110b57cec5SDimitry Andric     Name = NameOrErr.get();
8120b57cec5SDimitry Andric     if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
8130b57cec5SDimitry Andric       // We know that the symbol table is not an external file, but we still
8140b57cec5SDimitry Andric       // must check any Expected<> return value.
8150b57cec5SDimitry Andric       Expected<StringRef> BufOrErr = C->getBuffer();
8160b57cec5SDimitry Andric       if (!BufOrErr) {
8170b57cec5SDimitry Andric         Err = BufOrErr.takeError();
8180b57cec5SDimitry Andric         return;
8190b57cec5SDimitry Andric       }
8200b57cec5SDimitry Andric       SymbolTable = BufOrErr.get();
8210b57cec5SDimitry Andric       if (Increment())
8220b57cec5SDimitry Andric         return;
823fe6060f1SDimitry Andric     } else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {
8240b57cec5SDimitry Andric       Format = K_DARWIN64;
8250b57cec5SDimitry Andric       // We know that the symbol table is not an external file, but we still
8260b57cec5SDimitry Andric       // must check any Expected<> return value.
8270b57cec5SDimitry Andric       Expected<StringRef> BufOrErr = C->getBuffer();
8280b57cec5SDimitry Andric       if (!BufOrErr) {
8290b57cec5SDimitry Andric         Err = BufOrErr.takeError();
8300b57cec5SDimitry Andric         return;
8310b57cec5SDimitry Andric       }
8320b57cec5SDimitry Andric       SymbolTable = BufOrErr.get();
8330b57cec5SDimitry Andric       if (Increment())
8340b57cec5SDimitry Andric         return;
8350b57cec5SDimitry Andric     }
8360b57cec5SDimitry Andric     setFirstRegular(*C);
8370b57cec5SDimitry Andric     return;
8380b57cec5SDimitry Andric   }
8390b57cec5SDimitry Andric 
8400b57cec5SDimitry Andric   // MIPS 64-bit ELF archives use a special format of a symbol table.
8410b57cec5SDimitry Andric   // This format is marked by `ar_name` field equals to "/SYM64/".
8420b57cec5SDimitry Andric   // For detailed description see page 96 in the following document:
8430b57cec5SDimitry Andric   // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric   bool has64SymTable = false;
8460b57cec5SDimitry Andric   if (Name == "/" || Name == "/SYM64/") {
8470b57cec5SDimitry Andric     // We know that the symbol table is not an external file, but we still
8480b57cec5SDimitry Andric     // must check any Expected<> return value.
8490b57cec5SDimitry Andric     Expected<StringRef> BufOrErr = C->getBuffer();
8500b57cec5SDimitry Andric     if (!BufOrErr) {
8510b57cec5SDimitry Andric       Err = BufOrErr.takeError();
8520b57cec5SDimitry Andric       return;
8530b57cec5SDimitry Andric     }
8540b57cec5SDimitry Andric     SymbolTable = BufOrErr.get();
8550b57cec5SDimitry Andric     if (Name == "/SYM64/")
8560b57cec5SDimitry Andric       has64SymTable = true;
8570b57cec5SDimitry Andric 
8580b57cec5SDimitry Andric     if (Increment())
8590b57cec5SDimitry Andric       return;
8600b57cec5SDimitry Andric     if (I == E) {
8610b57cec5SDimitry Andric       Err = Error::success();
8620b57cec5SDimitry Andric       return;
8630b57cec5SDimitry Andric     }
8640b57cec5SDimitry Andric     Expected<StringRef> NameOrErr = C->getRawName();
8650b57cec5SDimitry Andric     if (!NameOrErr) {
8660b57cec5SDimitry Andric       Err = NameOrErr.takeError();
8670b57cec5SDimitry Andric       return;
8680b57cec5SDimitry Andric     }
8690b57cec5SDimitry Andric     Name = NameOrErr.get();
8700b57cec5SDimitry Andric   }
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric   if (Name == "//") {
8730b57cec5SDimitry Andric     Format = has64SymTable ? K_GNU64 : K_GNU;
8740b57cec5SDimitry Andric     // The string table is never an external member, but we still
8750b57cec5SDimitry Andric     // must check any Expected<> return value.
8760b57cec5SDimitry Andric     Expected<StringRef> BufOrErr = C->getBuffer();
8770b57cec5SDimitry Andric     if (!BufOrErr) {
8780b57cec5SDimitry Andric       Err = BufOrErr.takeError();
8790b57cec5SDimitry Andric       return;
8800b57cec5SDimitry Andric     }
8810b57cec5SDimitry Andric     StringTable = BufOrErr.get();
8820b57cec5SDimitry Andric     if (Increment())
8830b57cec5SDimitry Andric       return;
8840b57cec5SDimitry Andric     setFirstRegular(*C);
8850b57cec5SDimitry Andric     Err = Error::success();
8860b57cec5SDimitry Andric     return;
8870b57cec5SDimitry Andric   }
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric   if (Name[0] != '/') {
8900b57cec5SDimitry Andric     Format = has64SymTable ? K_GNU64 : K_GNU;
8910b57cec5SDimitry Andric     setFirstRegular(*C);
8920b57cec5SDimitry Andric     Err = Error::success();
8930b57cec5SDimitry Andric     return;
8940b57cec5SDimitry Andric   }
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric   if (Name != "/") {
8970b57cec5SDimitry Andric     Err = errorCodeToError(object_error::parse_failed);
8980b57cec5SDimitry Andric     return;
8990b57cec5SDimitry Andric   }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric   Format = K_COFF;
9020b57cec5SDimitry Andric   // We know that the symbol table is not an external file, but we still
9030b57cec5SDimitry Andric   // must check any Expected<> return value.
9040b57cec5SDimitry Andric   Expected<StringRef> BufOrErr = C->getBuffer();
9050b57cec5SDimitry Andric   if (!BufOrErr) {
9060b57cec5SDimitry Andric     Err = BufOrErr.takeError();
9070b57cec5SDimitry Andric     return;
9080b57cec5SDimitry Andric   }
9090b57cec5SDimitry Andric   SymbolTable = BufOrErr.get();
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric   if (Increment())
9120b57cec5SDimitry Andric     return;
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric   if (I == E) {
9150b57cec5SDimitry Andric     setFirstRegular(*C);
9160b57cec5SDimitry Andric     Err = Error::success();
9170b57cec5SDimitry Andric     return;
9180b57cec5SDimitry Andric   }
9190b57cec5SDimitry Andric 
9200b57cec5SDimitry Andric   NameOrErr = C->getRawName();
9210b57cec5SDimitry Andric   if (!NameOrErr) {
9220b57cec5SDimitry Andric     Err = NameOrErr.takeError();
9230b57cec5SDimitry Andric     return;
9240b57cec5SDimitry Andric   }
9250b57cec5SDimitry Andric   Name = NameOrErr.get();
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric   if (Name == "//") {
9280b57cec5SDimitry Andric     // The string table is never an external member, but we still
9290b57cec5SDimitry Andric     // must check any Expected<> return value.
9300b57cec5SDimitry Andric     Expected<StringRef> BufOrErr = C->getBuffer();
9310b57cec5SDimitry Andric     if (!BufOrErr) {
9320b57cec5SDimitry Andric       Err = BufOrErr.takeError();
9330b57cec5SDimitry Andric       return;
9340b57cec5SDimitry Andric     }
9350b57cec5SDimitry Andric     StringTable = BufOrErr.get();
9360b57cec5SDimitry Andric     if (Increment())
9370b57cec5SDimitry Andric       return;
93806c3fb27SDimitry Andric 
93906c3fb27SDimitry Andric     if (I == E) {
94006c3fb27SDimitry Andric       setFirstRegular(*C);
94106c3fb27SDimitry Andric       Err = Error::success();
94206c3fb27SDimitry Andric       return;
94306c3fb27SDimitry Andric     }
94406c3fb27SDimitry Andric 
94506c3fb27SDimitry Andric     NameOrErr = C->getRawName();
94606c3fb27SDimitry Andric     if (!NameOrErr) {
94706c3fb27SDimitry Andric       Err = NameOrErr.takeError();
94806c3fb27SDimitry Andric       return;
94906c3fb27SDimitry Andric     }
95006c3fb27SDimitry Andric     Name = NameOrErr.get();
95106c3fb27SDimitry Andric   }
95206c3fb27SDimitry Andric 
95306c3fb27SDimitry Andric   if (Name == "/<ECSYMBOLS>/") {
95406c3fb27SDimitry Andric     // ARM64EC-aware libraries contain an additional special member with
95506c3fb27SDimitry Andric     // an EC symbol map after the string table. Its format is similar to a
95606c3fb27SDimitry Andric     // regular symbol map, except it doesn't contain member offsets. Its indexes
95706c3fb27SDimitry Andric     // refer to member offsets from the regular symbol table instead.
95806c3fb27SDimitry Andric     Expected<StringRef> BufOrErr = C->getBuffer();
95906c3fb27SDimitry Andric     if (!BufOrErr) {
96006c3fb27SDimitry Andric       Err = BufOrErr.takeError();
96106c3fb27SDimitry Andric       return;
96206c3fb27SDimitry Andric     }
96306c3fb27SDimitry Andric     ECSymbolTable = BufOrErr.get();
96406c3fb27SDimitry Andric     if (Increment())
96506c3fb27SDimitry Andric       return;
9660b57cec5SDimitry Andric   }
9670b57cec5SDimitry Andric 
9680b57cec5SDimitry Andric   setFirstRegular(*C);
9690b57cec5SDimitry Andric   Err = Error::success();
9700b57cec5SDimitry Andric }
9710b57cec5SDimitry Andric 
972*0fca6ea1SDimitry Andric object::Archive::Kind Archive::getDefaultKindForTriple(Triple &T) {
973*0fca6ea1SDimitry Andric   if (T.isOSDarwin())
974*0fca6ea1SDimitry Andric     return object::Archive::K_DARWIN;
975*0fca6ea1SDimitry Andric   if (T.isOSAIX())
976*0fca6ea1SDimitry Andric     return object::Archive::K_AIXBIG;
977*0fca6ea1SDimitry Andric   if (T.isOSWindows())
978*0fca6ea1SDimitry Andric     return object::Archive::K_COFF;
979*0fca6ea1SDimitry Andric   return object::Archive::K_GNU;
980*0fca6ea1SDimitry Andric }
981*0fca6ea1SDimitry Andric 
982*0fca6ea1SDimitry Andric object::Archive::Kind Archive::getDefaultKind() {
983*0fca6ea1SDimitry Andric   Triple HostTriple(sys::getDefaultTargetTriple());
984*0fca6ea1SDimitry Andric   return getDefaultKindForTriple(HostTriple);
98581ad6265SDimitry Andric }
98681ad6265SDimitry Andric 
9870b57cec5SDimitry Andric Archive::child_iterator Archive::child_begin(Error &Err,
9880b57cec5SDimitry Andric                                              bool SkipInternal) const {
9890b57cec5SDimitry Andric   if (isEmpty())
9900b57cec5SDimitry Andric     return child_end();
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric   if (SkipInternal)
9930b57cec5SDimitry Andric     return child_iterator::itr(
9940b57cec5SDimitry Andric         Child(this, FirstRegularData, FirstRegularStartOfFile), Err);
9950b57cec5SDimitry Andric 
99604eeddc0SDimitry Andric   const char *Loc = Data.getBufferStart() + getFirstChildOffset();
9970b57cec5SDimitry Andric   Child C(this, Loc, &Err);
9980b57cec5SDimitry Andric   if (Err)
9990b57cec5SDimitry Andric     return child_end();
10000b57cec5SDimitry Andric   return child_iterator::itr(C, Err);
10010b57cec5SDimitry Andric }
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric Archive::child_iterator Archive::child_end() const {
10040b57cec5SDimitry Andric   return child_iterator::end(Child(nullptr, nullptr, nullptr));
10050b57cec5SDimitry Andric }
10060b57cec5SDimitry Andric 
100706c3fb27SDimitry Andric bool Archive::Symbol::isECSymbol() const {
100806c3fb27SDimitry Andric   // Symbols use SymbolCount..SymbolCount+getNumberOfECSymbols() for EC symbol
100906c3fb27SDimitry Andric   // indexes.
101006c3fb27SDimitry Andric   uint32_t SymbolCount = Parent->getNumberOfSymbols();
101106c3fb27SDimitry Andric   return SymbolCount <= SymbolIndex &&
101206c3fb27SDimitry Andric          SymbolIndex < SymbolCount + Parent->getNumberOfECSymbols();
101306c3fb27SDimitry Andric }
101406c3fb27SDimitry Andric 
10150b57cec5SDimitry Andric StringRef Archive::Symbol::getName() const {
101606c3fb27SDimitry Andric   if (isECSymbol())
101706c3fb27SDimitry Andric     return Parent->ECSymbolTable.begin() + StringIndex;
10180b57cec5SDimitry Andric   return Parent->getSymbolTable().begin() + StringIndex;
10190b57cec5SDimitry Andric }
10200b57cec5SDimitry Andric 
10210b57cec5SDimitry Andric Expected<Archive::Child> Archive::Symbol::getMember() const {
10220b57cec5SDimitry Andric   const char *Buf = Parent->getSymbolTable().begin();
10230b57cec5SDimitry Andric   const char *Offsets = Buf;
1024fcaf7f86SDimitry Andric   if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64 ||
1025fcaf7f86SDimitry Andric       Parent->kind() == K_AIXBIG)
10260b57cec5SDimitry Andric     Offsets += sizeof(uint64_t);
10270b57cec5SDimitry Andric   else
10280b57cec5SDimitry Andric     Offsets += sizeof(uint32_t);
10290b57cec5SDimitry Andric   uint64_t Offset = 0;
10300b57cec5SDimitry Andric   if (Parent->kind() == K_GNU) {
10310b57cec5SDimitry Andric     Offset = read32be(Offsets + SymbolIndex * 4);
1032fcaf7f86SDimitry Andric   } else if (Parent->kind() == K_GNU64 || Parent->kind() == K_AIXBIG) {
10330b57cec5SDimitry Andric     Offset = read64be(Offsets + SymbolIndex * 8);
10340b57cec5SDimitry Andric   } else if (Parent->kind() == K_BSD) {
10350b57cec5SDimitry Andric     // The SymbolIndex is an index into the ranlib structs that start at
10360b57cec5SDimitry Andric     // Offsets (the first uint32_t is the number of bytes of the ranlib
10370b57cec5SDimitry Andric     // structs).  The ranlib structs are a pair of uint32_t's the first
10380b57cec5SDimitry Andric     // being a string table offset and the second being the offset into
10390b57cec5SDimitry Andric     // the archive of the member that defines the symbol.  Which is what
10400b57cec5SDimitry Andric     // is needed here.
10410b57cec5SDimitry Andric     Offset = read32le(Offsets + SymbolIndex * 8 + 4);
10420b57cec5SDimitry Andric   } else if (Parent->kind() == K_DARWIN64) {
10430b57cec5SDimitry Andric     // The SymbolIndex is an index into the ranlib_64 structs that start at
10440b57cec5SDimitry Andric     // Offsets (the first uint64_t is the number of bytes of the ranlib_64
10450b57cec5SDimitry Andric     // structs).  The ranlib_64 structs are a pair of uint64_t's the first
10460b57cec5SDimitry Andric     // being a string table offset and the second being the offset into
10470b57cec5SDimitry Andric     // the archive of the member that defines the symbol.  Which is what
10480b57cec5SDimitry Andric     // is needed here.
10490b57cec5SDimitry Andric     Offset = read64le(Offsets + SymbolIndex * 16 + 8);
10500b57cec5SDimitry Andric   } else {
10510b57cec5SDimitry Andric     // Skip offsets.
10520b57cec5SDimitry Andric     uint32_t MemberCount = read32le(Buf);
10530b57cec5SDimitry Andric     Buf += MemberCount * 4 + 4;
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric     uint32_t SymbolCount = read32le(Buf);
105606c3fb27SDimitry Andric     uint16_t OffsetIndex;
105706c3fb27SDimitry Andric     if (SymbolIndex < SymbolCount) {
10580b57cec5SDimitry Andric       // Skip SymbolCount to get to the indices table.
10590b57cec5SDimitry Andric       const char *Indices = Buf + 4;
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric       // Get the index of the offset in the file member offset table for this
10620b57cec5SDimitry Andric       // symbol.
106306c3fb27SDimitry Andric       OffsetIndex = read16le(Indices + SymbolIndex * 2);
106406c3fb27SDimitry Andric     } else if (isECSymbol()) {
106506c3fb27SDimitry Andric       // Skip SymbolCount to get to the indices table.
106606c3fb27SDimitry Andric       const char *Indices = Parent->ECSymbolTable.begin() + 4;
106706c3fb27SDimitry Andric 
106806c3fb27SDimitry Andric       // Get the index of the offset in the file member offset table for this
106906c3fb27SDimitry Andric       // symbol.
107006c3fb27SDimitry Andric       OffsetIndex = read16le(Indices + (SymbolIndex - SymbolCount) * 2);
107106c3fb27SDimitry Andric     } else {
107206c3fb27SDimitry Andric       return errorCodeToError(object_error::parse_failed);
107306c3fb27SDimitry Andric     }
10740b57cec5SDimitry Andric     // Subtract 1 since OffsetIndex is 1 based.
10750b57cec5SDimitry Andric     --OffsetIndex;
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric     if (OffsetIndex >= MemberCount)
10780b57cec5SDimitry Andric       return errorCodeToError(object_error::parse_failed);
10790b57cec5SDimitry Andric 
10800b57cec5SDimitry Andric     Offset = read32le(Offsets + OffsetIndex * 4);
10810b57cec5SDimitry Andric   }
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric   const char *Loc = Parent->getData().begin() + Offset;
10840b57cec5SDimitry Andric   Error Err = Error::success();
10850b57cec5SDimitry Andric   Child C(Parent, Loc, &Err);
10860b57cec5SDimitry Andric   if (Err)
10870b57cec5SDimitry Andric     return std::move(Err);
10880b57cec5SDimitry Andric   return C;
10890b57cec5SDimitry Andric }
10900b57cec5SDimitry Andric 
10910b57cec5SDimitry Andric Archive::Symbol Archive::Symbol::getNext() const {
10920b57cec5SDimitry Andric   Symbol t(*this);
10930b57cec5SDimitry Andric   if (Parent->kind() == K_BSD) {
10940b57cec5SDimitry Andric     // t.StringIndex is an offset from the start of the __.SYMDEF or
10950b57cec5SDimitry Andric     // "__.SYMDEF SORTED" member into the string table for the ranlib
10960b57cec5SDimitry Andric     // struct indexed by t.SymbolIndex .  To change t.StringIndex to the
10970b57cec5SDimitry Andric     // offset in the string table for t.SymbolIndex+1 we subtract the
10980b57cec5SDimitry Andric     // its offset from the start of the string table for t.SymbolIndex
10990b57cec5SDimitry Andric     // and add the offset of the string table for t.SymbolIndex+1.
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric     // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
11020b57cec5SDimitry Andric     // which is the number of bytes of ranlib structs that follow.  The ranlib
11030b57cec5SDimitry Andric     // structs are a pair of uint32_t's the first being a string table offset
11040b57cec5SDimitry Andric     // and the second being the offset into the archive of the member that
11050b57cec5SDimitry Andric     // define the symbol. After that the next uint32_t is the byte count of
11060b57cec5SDimitry Andric     // the string table followed by the string table.
11070b57cec5SDimitry Andric     const char *Buf = Parent->getSymbolTable().begin();
11080b57cec5SDimitry Andric     uint32_t RanlibCount = 0;
11090b57cec5SDimitry Andric     RanlibCount = read32le(Buf) / 8;
11100b57cec5SDimitry Andric     // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount)
11110b57cec5SDimitry Andric     // don't change the t.StringIndex as we don't want to reference a ranlib
11120b57cec5SDimitry Andric     // past RanlibCount.
11130b57cec5SDimitry Andric     if (t.SymbolIndex + 1 < RanlibCount) {
11140b57cec5SDimitry Andric       const char *Ranlibs = Buf + 4;
11150b57cec5SDimitry Andric       uint32_t CurRanStrx = 0;
11160b57cec5SDimitry Andric       uint32_t NextRanStrx = 0;
11170b57cec5SDimitry Andric       CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8);
11180b57cec5SDimitry Andric       NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8);
11190b57cec5SDimitry Andric       t.StringIndex -= CurRanStrx;
11200b57cec5SDimitry Andric       t.StringIndex += NextRanStrx;
11210b57cec5SDimitry Andric     }
112206c3fb27SDimitry Andric   } else if (t.isECSymbol()) {
112306c3fb27SDimitry Andric     // Go to one past next null.
112406c3fb27SDimitry Andric     t.StringIndex = Parent->ECSymbolTable.find('\0', t.StringIndex) + 1;
11250b57cec5SDimitry Andric   } else {
11260b57cec5SDimitry Andric     // Go to one past next null.
11270b57cec5SDimitry Andric     t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1;
11280b57cec5SDimitry Andric   }
11290b57cec5SDimitry Andric   ++t.SymbolIndex;
11300b57cec5SDimitry Andric   return t;
11310b57cec5SDimitry Andric }
11320b57cec5SDimitry Andric 
11330b57cec5SDimitry Andric Archive::symbol_iterator Archive::symbol_begin() const {
11340b57cec5SDimitry Andric   if (!hasSymbolTable())
11350b57cec5SDimitry Andric     return symbol_iterator(Symbol(this, 0, 0));
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric   const char *buf = getSymbolTable().begin();
11380b57cec5SDimitry Andric   if (kind() == K_GNU) {
11390b57cec5SDimitry Andric     uint32_t symbol_count = 0;
11400b57cec5SDimitry Andric     symbol_count = read32be(buf);
11410b57cec5SDimitry Andric     buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
11420b57cec5SDimitry Andric   } else if (kind() == K_GNU64) {
11430b57cec5SDimitry Andric     uint64_t symbol_count = read64be(buf);
11440b57cec5SDimitry Andric     buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));
11450b57cec5SDimitry Andric   } else if (kind() == K_BSD) {
11460b57cec5SDimitry Andric     // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
11470b57cec5SDimitry Andric     // which is the number of bytes of ranlib structs that follow.  The ranlib
11480b57cec5SDimitry Andric     // structs are a pair of uint32_t's the first being a string table offset
11490b57cec5SDimitry Andric     // and the second being the offset into the archive of the member that
11500b57cec5SDimitry Andric     // define the symbol. After that the next uint32_t is the byte count of
11510b57cec5SDimitry Andric     // the string table followed by the string table.
11520b57cec5SDimitry Andric     uint32_t ranlib_count = 0;
11530b57cec5SDimitry Andric     ranlib_count = read32le(buf) / 8;
11540b57cec5SDimitry Andric     const char *ranlibs = buf + 4;
11550b57cec5SDimitry Andric     uint32_t ran_strx = 0;
11560b57cec5SDimitry Andric     ran_strx = read32le(ranlibs);
11570b57cec5SDimitry Andric     buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t))));
11580b57cec5SDimitry Andric     // Skip the byte count of the string table.
11590b57cec5SDimitry Andric     buf += sizeof(uint32_t);
11600b57cec5SDimitry Andric     buf += ran_strx;
11610b57cec5SDimitry Andric   } else if (kind() == K_DARWIN64) {
11620b57cec5SDimitry Andric     // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t
11630b57cec5SDimitry Andric     // which is the number of bytes of ranlib_64 structs that follow.  The
11640b57cec5SDimitry Andric     // ranlib_64 structs are a pair of uint64_t's the first being a string
11650b57cec5SDimitry Andric     // table offset and the second being the offset into the archive of the
11660b57cec5SDimitry Andric     // member that define the symbol. After that the next uint64_t is the byte
11670b57cec5SDimitry Andric     // count of the string table followed by the string table.
11680b57cec5SDimitry Andric     uint64_t ranlib_count = 0;
11690b57cec5SDimitry Andric     ranlib_count = read64le(buf) / 16;
11700b57cec5SDimitry Andric     const char *ranlibs = buf + 8;
11710b57cec5SDimitry Andric     uint64_t ran_strx = 0;
11720b57cec5SDimitry Andric     ran_strx = read64le(ranlibs);
11730b57cec5SDimitry Andric     buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t))));
11740b57cec5SDimitry Andric     // Skip the byte count of the string table.
11750b57cec5SDimitry Andric     buf += sizeof(uint64_t);
11760b57cec5SDimitry Andric     buf += ran_strx;
1177fcaf7f86SDimitry Andric   } else if (kind() == K_AIXBIG) {
1178fcaf7f86SDimitry Andric     buf = getStringTable().begin();
11790b57cec5SDimitry Andric   } else {
11800b57cec5SDimitry Andric     uint32_t member_count = 0;
11810b57cec5SDimitry Andric     uint32_t symbol_count = 0;
11820b57cec5SDimitry Andric     member_count = read32le(buf);
11830b57cec5SDimitry Andric     buf += 4 + (member_count * 4); // Skip offsets.
11840b57cec5SDimitry Andric     symbol_count = read32le(buf);
11850b57cec5SDimitry Andric     buf += 4 + (symbol_count * 2); // Skip indices.
11860b57cec5SDimitry Andric   }
11870b57cec5SDimitry Andric   uint32_t string_start_offset = buf - getSymbolTable().begin();
11880b57cec5SDimitry Andric   return symbol_iterator(Symbol(this, 0, string_start_offset));
11890b57cec5SDimitry Andric }
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric Archive::symbol_iterator Archive::symbol_end() const {
11920b57cec5SDimitry Andric   return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0));
11930b57cec5SDimitry Andric }
11940b57cec5SDimitry Andric 
119506c3fb27SDimitry Andric Expected<iterator_range<Archive::symbol_iterator>> Archive::ec_symbols() const {
119606c3fb27SDimitry Andric   uint32_t Count = 0;
119706c3fb27SDimitry Andric 
119806c3fb27SDimitry Andric   // Validate EC symbol table.
119906c3fb27SDimitry Andric   if (!ECSymbolTable.empty()) {
120006c3fb27SDimitry Andric     if (ECSymbolTable.size() < sizeof(uint32_t))
120106c3fb27SDimitry Andric       return malformedError("invalid EC symbols size (" +
120206c3fb27SDimitry Andric                             Twine(ECSymbolTable.size()) + ")");
120306c3fb27SDimitry Andric     if (SymbolTable.size() < sizeof(uint32_t))
120406c3fb27SDimitry Andric       return malformedError("invalid symbols size (" +
120506c3fb27SDimitry Andric                             Twine(ECSymbolTable.size()) + ")");
120606c3fb27SDimitry Andric 
120706c3fb27SDimitry Andric     Count = read32le(ECSymbolTable.begin());
120806c3fb27SDimitry Andric     size_t StringIndex = sizeof(uint32_t) + Count * sizeof(uint16_t);
120906c3fb27SDimitry Andric     if (ECSymbolTable.size() < StringIndex)
121006c3fb27SDimitry Andric       return malformedError("invalid EC symbols size. Size was " +
121106c3fb27SDimitry Andric                             Twine(ECSymbolTable.size()) + ", but expected " +
121206c3fb27SDimitry Andric                             Twine(StringIndex));
121306c3fb27SDimitry Andric 
121406c3fb27SDimitry Andric     uint32_t MemberCount = read32le(SymbolTable.begin());
121506c3fb27SDimitry Andric     const char *Indexes = ECSymbolTable.begin() + sizeof(uint32_t);
121606c3fb27SDimitry Andric 
121706c3fb27SDimitry Andric     for (uint32_t i = 0; i < Count; ++i) {
121806c3fb27SDimitry Andric       uint16_t Index = read16le(Indexes + i * sizeof(uint16_t));
121906c3fb27SDimitry Andric       if (!Index)
122006c3fb27SDimitry Andric         return malformedError("invalid EC symbol index 0");
122106c3fb27SDimitry Andric       if (Index > MemberCount)
122206c3fb27SDimitry Andric         return malformedError("invalid EC symbol index " + Twine(Index) +
122306c3fb27SDimitry Andric                               " is larger than member count " +
122406c3fb27SDimitry Andric                               Twine(MemberCount));
122506c3fb27SDimitry Andric 
122606c3fb27SDimitry Andric       StringIndex = ECSymbolTable.find('\0', StringIndex);
122706c3fb27SDimitry Andric       if (StringIndex == StringRef::npos)
122806c3fb27SDimitry Andric         return malformedError("malformed EC symbol names: not null-terminated");
122906c3fb27SDimitry Andric       ++StringIndex;
123006c3fb27SDimitry Andric     }
123106c3fb27SDimitry Andric   }
123206c3fb27SDimitry Andric 
123306c3fb27SDimitry Andric   uint32_t SymbolCount = getNumberOfSymbols();
123406c3fb27SDimitry Andric   return make_range(
123506c3fb27SDimitry Andric       symbol_iterator(Symbol(this, SymbolCount,
123606c3fb27SDimitry Andric                              sizeof(uint32_t) + Count * sizeof(uint16_t))),
123706c3fb27SDimitry Andric       symbol_iterator(Symbol(this, SymbolCount + Count, 0)));
123806c3fb27SDimitry Andric }
123906c3fb27SDimitry Andric 
12400b57cec5SDimitry Andric uint32_t Archive::getNumberOfSymbols() const {
12410b57cec5SDimitry Andric   if (!hasSymbolTable())
12420b57cec5SDimitry Andric     return 0;
12430b57cec5SDimitry Andric   const char *buf = getSymbolTable().begin();
12440b57cec5SDimitry Andric   if (kind() == K_GNU)
12450b57cec5SDimitry Andric     return read32be(buf);
1246fcaf7f86SDimitry Andric   if (kind() == K_GNU64 || kind() == K_AIXBIG)
12470b57cec5SDimitry Andric     return read64be(buf);
12480b57cec5SDimitry Andric   if (kind() == K_BSD)
12490b57cec5SDimitry Andric     return read32le(buf) / 8;
12500b57cec5SDimitry Andric   if (kind() == K_DARWIN64)
12510b57cec5SDimitry Andric     return read64le(buf) / 16;
12520b57cec5SDimitry Andric   uint32_t member_count = 0;
12530b57cec5SDimitry Andric   member_count = read32le(buf);
12540b57cec5SDimitry Andric   buf += 4 + (member_count * 4); // Skip offsets.
12550b57cec5SDimitry Andric   return read32le(buf);
12560b57cec5SDimitry Andric }
12570b57cec5SDimitry Andric 
125806c3fb27SDimitry Andric uint32_t Archive::getNumberOfECSymbols() const {
125906c3fb27SDimitry Andric   if (ECSymbolTable.size() < sizeof(uint32_t))
126006c3fb27SDimitry Andric     return 0;
126106c3fb27SDimitry Andric   return read32le(ECSymbolTable.begin());
126206c3fb27SDimitry Andric }
126306c3fb27SDimitry Andric 
1264bdd1243dSDimitry Andric Expected<std::optional<Archive::Child>> Archive::findSym(StringRef name) const {
12650b57cec5SDimitry Andric   Archive::symbol_iterator bs = symbol_begin();
12660b57cec5SDimitry Andric   Archive::symbol_iterator es = symbol_end();
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric   for (; bs != es; ++bs) {
12690b57cec5SDimitry Andric     StringRef SymName = bs->getName();
12700b57cec5SDimitry Andric     if (SymName == name) {
12710b57cec5SDimitry Andric       if (auto MemberOrErr = bs->getMember())
12720b57cec5SDimitry Andric         return Child(*MemberOrErr);
12730b57cec5SDimitry Andric       else
12740b57cec5SDimitry Andric         return MemberOrErr.takeError();
12750b57cec5SDimitry Andric     }
12760b57cec5SDimitry Andric   }
1277bdd1243dSDimitry Andric   return std::nullopt;
12780b57cec5SDimitry Andric }
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric // Returns true if archive file contains no member file.
128104eeddc0SDimitry Andric bool Archive::isEmpty() const {
128204eeddc0SDimitry Andric   return Data.getBufferSize() == getArchiveMagicLen();
128304eeddc0SDimitry Andric }
12840b57cec5SDimitry Andric 
12850b57cec5SDimitry Andric bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }
128604eeddc0SDimitry Andric 
128706c3fb27SDimitry Andric static Error getGlobalSymtabLocAndSize(const MemoryBufferRef &Data,
128806c3fb27SDimitry Andric                                        uint64_t GlobalSymtabOffset,
128906c3fb27SDimitry Andric                                        const char *&GlobalSymtabLoc,
129006c3fb27SDimitry Andric                                        uint64_t &Size, const char *BitMessage) {
129106c3fb27SDimitry Andric   uint64_t BufferSize = Data.getBufferSize();
129206c3fb27SDimitry Andric   uint64_t GlobalSymtabContentOffset =
129306c3fb27SDimitry Andric       GlobalSymtabOffset + sizeof(BigArMemHdrType);
129406c3fb27SDimitry Andric   if (GlobalSymtabContentOffset > BufferSize)
129506c3fb27SDimitry Andric     return malformedError(
129606c3fb27SDimitry Andric         Twine(BitMessage) + " global symbol table header at offset 0x" +
129706c3fb27SDimitry Andric         Twine::utohexstr(GlobalSymtabOffset) + " and size 0x" +
129806c3fb27SDimitry Andric         Twine::utohexstr(sizeof(BigArMemHdrType)) +
129906c3fb27SDimitry Andric         " goes past the end of file");
130006c3fb27SDimitry Andric 
130106c3fb27SDimitry Andric   GlobalSymtabLoc = Data.getBufferStart() + GlobalSymtabOffset;
130206c3fb27SDimitry Andric   const BigArMemHdrType *GlobalSymHdr =
130306c3fb27SDimitry Andric       reinterpret_cast<const BigArMemHdrType *>(GlobalSymtabLoc);
130406c3fb27SDimitry Andric   StringRef RawOffset = getFieldRawString(GlobalSymHdr->Size);
130506c3fb27SDimitry Andric   if (RawOffset.getAsInteger(10, Size))
130606c3fb27SDimitry Andric     return malformedError(Twine(BitMessage) + " global symbol table size \"" +
130706c3fb27SDimitry Andric                           RawOffset + "\" is not a number");
130806c3fb27SDimitry Andric 
130906c3fb27SDimitry Andric   if (GlobalSymtabContentOffset + Size > BufferSize)
131006c3fb27SDimitry Andric     return malformedError(
131106c3fb27SDimitry Andric         Twine(BitMessage) + " global symbol table content at offset 0x" +
131206c3fb27SDimitry Andric         Twine::utohexstr(GlobalSymtabContentOffset) + " and size 0x" +
131306c3fb27SDimitry Andric         Twine::utohexstr(Size) + " goes past the end of file");
131406c3fb27SDimitry Andric 
131506c3fb27SDimitry Andric   return Error::success();
131606c3fb27SDimitry Andric }
131706c3fb27SDimitry Andric 
131806c3fb27SDimitry Andric struct GlobalSymtabInfo {
131906c3fb27SDimitry Andric   uint64_t SymNum;
132006c3fb27SDimitry Andric   StringRef SymbolTable;
132106c3fb27SDimitry Andric   StringRef SymbolOffsetTable;
132206c3fb27SDimitry Andric   StringRef StringTable;
132306c3fb27SDimitry Andric };
132406c3fb27SDimitry Andric 
132506c3fb27SDimitry Andric static void
132606c3fb27SDimitry Andric appendGlobalSymbolTableInfo(SmallVector<GlobalSymtabInfo> &SymtabInfos,
132706c3fb27SDimitry Andric                             const char *GlobalSymtabLoc, uint64_t Size) {
132806c3fb27SDimitry Andric   // In a big archive, a global symbol table contains the following information:
132906c3fb27SDimitry Andric   // - The number of symbols.
133006c3fb27SDimitry Andric   // - The array of offsets into the archive file. The length is eight
133106c3fb27SDimitry Andric   //   times the number of symbols.
133206c3fb27SDimitry Andric   // - The name-string table. The size is:
133306c3fb27SDimitry Andric   //   Size-(8*(the number of symbols + 1)).
133406c3fb27SDimitry Andric 
133506c3fb27SDimitry Andric   StringRef SymbolTable =
133606c3fb27SDimitry Andric       StringRef(GlobalSymtabLoc + sizeof(BigArMemHdrType), Size);
133706c3fb27SDimitry Andric   uint64_t SymNum = read64be(GlobalSymtabLoc + sizeof(BigArMemHdrType));
133806c3fb27SDimitry Andric   StringRef SymbolOffsetTable = StringRef(SymbolTable.data() + 8, 8 * SymNum);
133906c3fb27SDimitry Andric   unsigned SymOffsetsSize = 8 * (SymNum + 1);
134006c3fb27SDimitry Andric   uint64_t SymbolTableStringSize = Size - SymOffsetsSize;
134106c3fb27SDimitry Andric   StringRef StringTable =
134206c3fb27SDimitry Andric       StringRef(SymbolTable.data() + SymOffsetsSize, SymbolTableStringSize);
134306c3fb27SDimitry Andric   SymtabInfos.push_back({SymNum, SymbolTable, SymbolOffsetTable, StringTable});
134406c3fb27SDimitry Andric }
134506c3fb27SDimitry Andric 
134604eeddc0SDimitry Andric BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)
134704eeddc0SDimitry Andric     : Archive(Source, Err) {
134804eeddc0SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
134904eeddc0SDimitry Andric   StringRef Buffer = Data.getBuffer();
135004eeddc0SDimitry Andric   ArFixLenHdr = reinterpret_cast<const FixLenHdr *>(Buffer.data());
135106c3fb27SDimitry Andric   uint64_t BufferSize = Data.getBufferSize();
135206c3fb27SDimitry Andric 
135306c3fb27SDimitry Andric   if (BufferSize < sizeof(FixLenHdr)) {
135406c3fb27SDimitry Andric     Err = malformedError("malformed AIX big archive: incomplete fixed length "
135506c3fb27SDimitry Andric                          "header, the archive is only" +
135606c3fb27SDimitry Andric                          Twine(BufferSize) + " byte(s)");
135706c3fb27SDimitry Andric     return;
135806c3fb27SDimitry Andric   }
135904eeddc0SDimitry Andric 
136004eeddc0SDimitry Andric   StringRef RawOffset = getFieldRawString(ArFixLenHdr->FirstChildOffset);
136104eeddc0SDimitry Andric   if (RawOffset.getAsInteger(10, FirstChildOffset))
136204eeddc0SDimitry Andric     // TODO: Out-of-line.
136304eeddc0SDimitry Andric     Err = malformedError("malformed AIX big archive: first member offset \"" +
136404eeddc0SDimitry Andric                          RawOffset + "\" is not a number");
136504eeddc0SDimitry Andric 
136604eeddc0SDimitry Andric   RawOffset = getFieldRawString(ArFixLenHdr->LastChildOffset);
136704eeddc0SDimitry Andric   if (RawOffset.getAsInteger(10, LastChildOffset))
136804eeddc0SDimitry Andric     // TODO: Out-of-line.
136904eeddc0SDimitry Andric     Err = malformedError("malformed AIX big archive: last member offset \"" +
137004eeddc0SDimitry Andric                          RawOffset + "\" is not a number");
137104eeddc0SDimitry Andric 
137206c3fb27SDimitry Andric   uint64_t GlobSymtab32Offset = 0;
1373fcaf7f86SDimitry Andric   RawOffset = getFieldRawString(ArFixLenHdr->GlobSymOffset);
137406c3fb27SDimitry Andric   if (RawOffset.getAsInteger(10, GlobSymtab32Offset)) {
137506c3fb27SDimitry Andric     Err = malformedError("global symbol table "
137606c3fb27SDimitry Andric                          "offset of 32-bit members \"" +
137706c3fb27SDimitry Andric                          RawOffset + "\" is not a number");
137806c3fb27SDimitry Andric     return;
137906c3fb27SDimitry Andric   }
1380fcaf7f86SDimitry Andric 
138106c3fb27SDimitry Andric   uint64_t GlobSymtab64Offset = 0;
138206c3fb27SDimitry Andric   RawOffset = getFieldRawString(ArFixLenHdr->GlobSym64Offset);
138306c3fb27SDimitry Andric   if (RawOffset.getAsInteger(10, GlobSymtab64Offset)) {
138406c3fb27SDimitry Andric     Err = malformedError("global symbol table "
138506c3fb27SDimitry Andric                          "offset of 64-bit members\"" +
138606c3fb27SDimitry Andric                          RawOffset + "\" is not a number");
138706c3fb27SDimitry Andric     return;
138806c3fb27SDimitry Andric   }
138906c3fb27SDimitry Andric 
139006c3fb27SDimitry Andric   const char *GlobSymtab32Loc = nullptr;
139106c3fb27SDimitry Andric   const char *GlobSymtab64Loc = nullptr;
139206c3fb27SDimitry Andric   uint64_t GlobSymtab32Size = 0;
139306c3fb27SDimitry Andric   uint64_t GlobSymtab64Size = 0;
139406c3fb27SDimitry Andric   const MemoryBufferRef &MemBuffRef = getMemoryBufferRef();
139506c3fb27SDimitry Andric 
139606c3fb27SDimitry Andric   if (GlobSymtab32Offset) {
139706c3fb27SDimitry Andric     Err =
139806c3fb27SDimitry Andric         getGlobalSymtabLocAndSize(MemBuffRef, GlobSymtab32Offset,
139906c3fb27SDimitry Andric                                   GlobSymtab32Loc, GlobSymtab32Size, "32-bit");
1400fcaf7f86SDimitry Andric     if (Err)
1401fcaf7f86SDimitry Andric       return;
14025f757f3fSDimitry Andric 
14035f757f3fSDimitry Andric     Has32BitGlobalSymtab = true;
140406c3fb27SDimitry Andric   }
1405fcaf7f86SDimitry Andric 
140606c3fb27SDimitry Andric   if (GlobSymtab64Offset) {
140706c3fb27SDimitry Andric     Err =
140806c3fb27SDimitry Andric         getGlobalSymtabLocAndSize(MemBuffRef, GlobSymtab64Offset,
140906c3fb27SDimitry Andric                                   GlobSymtab64Loc, GlobSymtab64Size, "64-bit");
141006c3fb27SDimitry Andric     if (Err)
1411fcaf7f86SDimitry Andric       return;
14125f757f3fSDimitry Andric 
14135f757f3fSDimitry Andric     Has64BitGlobalSymtab = true;
1414fcaf7f86SDimitry Andric   }
1415fcaf7f86SDimitry Andric 
141606c3fb27SDimitry Andric   SmallVector<GlobalSymtabInfo> SymtabInfos;
141706c3fb27SDimitry Andric 
141806c3fb27SDimitry Andric   if (GlobSymtab32Offset)
141906c3fb27SDimitry Andric     appendGlobalSymbolTableInfo(SymtabInfos, GlobSymtab32Loc, GlobSymtab32Size);
142006c3fb27SDimitry Andric   if (GlobSymtab64Offset)
142106c3fb27SDimitry Andric     appendGlobalSymbolTableInfo(SymtabInfos, GlobSymtab64Loc, GlobSymtab64Size);
142206c3fb27SDimitry Andric 
142306c3fb27SDimitry Andric   if (SymtabInfos.size() == 1) {
142406c3fb27SDimitry Andric     SymbolTable = SymtabInfos[0].SymbolTable;
142506c3fb27SDimitry Andric     StringTable = SymtabInfos[0].StringTable;
142606c3fb27SDimitry Andric   } else if (SymtabInfos.size() == 2) {
142706c3fb27SDimitry Andric     // In order to let the Archive::Symbol::getNext() work for both 32-bit and
142806c3fb27SDimitry Andric     // 64-bit global symbol tables, we need to merge them into a single table.
142906c3fb27SDimitry Andric     raw_string_ostream Out(MergedGlobalSymtabBuf);
143006c3fb27SDimitry Andric     uint64_t SymNum = SymtabInfos[0].SymNum + SymtabInfos[1].SymNum;
14315f757f3fSDimitry Andric     write(Out, SymNum, llvm::endianness::big);
143206c3fb27SDimitry Andric     // Merge symbol offset.
143306c3fb27SDimitry Andric     Out << SymtabInfos[0].SymbolOffsetTable;
143406c3fb27SDimitry Andric     Out << SymtabInfos[1].SymbolOffsetTable;
143506c3fb27SDimitry Andric     // Merge string table.
143606c3fb27SDimitry Andric     Out << SymtabInfos[0].StringTable;
143706c3fb27SDimitry Andric     Out << SymtabInfos[1].StringTable;
143806c3fb27SDimitry Andric     SymbolTable = MergedGlobalSymtabBuf;
143906c3fb27SDimitry Andric     // The size of the symbol offset to the member file is 8 bytes.
144006c3fb27SDimitry Andric     StringTable = StringRef(SymbolTable.begin() + (SymNum + 1) * 8,
144106c3fb27SDimitry Andric                             SymtabInfos[0].StringTable.size() +
144206c3fb27SDimitry Andric                                 SymtabInfos[1].StringTable.size());
1443fcaf7f86SDimitry Andric   }
1444fcaf7f86SDimitry Andric 
144504eeddc0SDimitry Andric   child_iterator I = child_begin(Err, false);
144604eeddc0SDimitry Andric   if (Err)
144704eeddc0SDimitry Andric     return;
144804eeddc0SDimitry Andric   child_iterator E = child_end();
144904eeddc0SDimitry Andric   if (I == E) {
145004eeddc0SDimitry Andric     Err = Error::success();
145104eeddc0SDimitry Andric     return;
145204eeddc0SDimitry Andric   }
145304eeddc0SDimitry Andric   setFirstRegular(*I);
145404eeddc0SDimitry Andric   Err = Error::success();
145504eeddc0SDimitry Andric }
1456