xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Object/Archive.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
17330f729Sjoerg //===- Archive.cpp - ar File Format implementation ------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file defines the ArchiveObjectFile class.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "llvm/Object/Archive.h"
147330f729Sjoerg #include "llvm/ADT/Optional.h"
157330f729Sjoerg #include "llvm/ADT/SmallString.h"
167330f729Sjoerg #include "llvm/ADT/StringRef.h"
177330f729Sjoerg #include "llvm/ADT/Twine.h"
187330f729Sjoerg #include "llvm/Object/Binary.h"
197330f729Sjoerg #include "llvm/Object/Error.h"
207330f729Sjoerg #include "llvm/Support/Chrono.h"
217330f729Sjoerg #include "llvm/Support/Endian.h"
227330f729Sjoerg #include "llvm/Support/Error.h"
237330f729Sjoerg #include "llvm/Support/ErrorOr.h"
247330f729Sjoerg #include "llvm/Support/FileSystem.h"
257330f729Sjoerg #include "llvm/Support/MemoryBuffer.h"
267330f729Sjoerg #include "llvm/Support/Path.h"
277330f729Sjoerg #include "llvm/Support/raw_ostream.h"
287330f729Sjoerg #include <algorithm>
297330f729Sjoerg #include <cassert>
307330f729Sjoerg #include <cstddef>
317330f729Sjoerg #include <cstdint>
327330f729Sjoerg #include <cstring>
337330f729Sjoerg #include <memory>
347330f729Sjoerg #include <string>
357330f729Sjoerg #include <system_error>
367330f729Sjoerg 
377330f729Sjoerg using namespace llvm;
387330f729Sjoerg using namespace object;
397330f729Sjoerg using namespace llvm::support::endian;
407330f729Sjoerg 
41*82d56013Sjoerg const char Magic[] = "!<arch>\n";
42*82d56013Sjoerg const char ThinMagic[] = "!<thin>\n";
437330f729Sjoerg 
anchor()447330f729Sjoerg void Archive::anchor() {}
457330f729Sjoerg 
467330f729Sjoerg static Error
malformedError(Twine Msg)477330f729Sjoerg malformedError(Twine Msg) {
487330f729Sjoerg   std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")";
497330f729Sjoerg   return make_error<GenericBinaryError>(std::move(StringMsg),
507330f729Sjoerg                                         object_error::parse_failed);
517330f729Sjoerg }
527330f729Sjoerg 
ArchiveMemberHeader(const Archive * Parent,const char * RawHeaderPtr,uint64_t Size,Error * Err)537330f729Sjoerg ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent,
547330f729Sjoerg                                          const char *RawHeaderPtr,
557330f729Sjoerg                                          uint64_t Size, Error *Err)
567330f729Sjoerg     : Parent(Parent),
577330f729Sjoerg       ArMemHdr(reinterpret_cast<const ArMemHdrType *>(RawHeaderPtr)) {
587330f729Sjoerg   if (RawHeaderPtr == nullptr)
597330f729Sjoerg     return;
607330f729Sjoerg   ErrorAsOutParameter ErrAsOutParam(Err);
617330f729Sjoerg 
627330f729Sjoerg   if (Size < sizeof(ArMemHdrType)) {
637330f729Sjoerg     if (Err) {
647330f729Sjoerg       std::string Msg("remaining size of archive too small for next archive "
657330f729Sjoerg                       "member header ");
667330f729Sjoerg       Expected<StringRef> NameOrErr = getName(Size);
677330f729Sjoerg       if (!NameOrErr) {
687330f729Sjoerg         consumeError(NameOrErr.takeError());
697330f729Sjoerg         uint64_t Offset = RawHeaderPtr - Parent->getData().data();
707330f729Sjoerg         *Err = malformedError(Msg + "at offset " + Twine(Offset));
717330f729Sjoerg       } else
727330f729Sjoerg         *Err = malformedError(Msg + "for " + NameOrErr.get());
737330f729Sjoerg     }
747330f729Sjoerg     return;
757330f729Sjoerg   }
767330f729Sjoerg   if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') {
777330f729Sjoerg     if (Err) {
787330f729Sjoerg       std::string Buf;
797330f729Sjoerg       raw_string_ostream OS(Buf);
807330f729Sjoerg       OS.write_escaped(StringRef(ArMemHdr->Terminator,
817330f729Sjoerg                                  sizeof(ArMemHdr->Terminator)));
827330f729Sjoerg       OS.flush();
837330f729Sjoerg       std::string Msg("terminator characters in archive member \"" + Buf +
847330f729Sjoerg                       "\" not the correct \"`\\n\" values for the archive "
857330f729Sjoerg                       "member header ");
867330f729Sjoerg       Expected<StringRef> NameOrErr = getName(Size);
877330f729Sjoerg       if (!NameOrErr) {
887330f729Sjoerg         consumeError(NameOrErr.takeError());
897330f729Sjoerg         uint64_t Offset = RawHeaderPtr - Parent->getData().data();
907330f729Sjoerg         *Err = malformedError(Msg + "at offset " + Twine(Offset));
917330f729Sjoerg       } else
927330f729Sjoerg         *Err = malformedError(Msg + "for " + NameOrErr.get());
937330f729Sjoerg     }
947330f729Sjoerg     return;
957330f729Sjoerg   }
967330f729Sjoerg }
977330f729Sjoerg 
987330f729Sjoerg // This gets the raw name from the ArMemHdr->Name field and checks that it is
997330f729Sjoerg // valid for the kind of archive.  If it is not valid it returns an Error.
getRawName() const1007330f729Sjoerg Expected<StringRef> ArchiveMemberHeader::getRawName() const {
1017330f729Sjoerg   char EndCond;
1027330f729Sjoerg   auto Kind = Parent->kind();
1037330f729Sjoerg   if (Kind == Archive::K_BSD || Kind == Archive::K_DARWIN64) {
1047330f729Sjoerg     if (ArMemHdr->Name[0] == ' ') {
1057330f729Sjoerg       uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
1067330f729Sjoerg                         Parent->getData().data();
1077330f729Sjoerg       return malformedError("name contains a leading space for archive member "
1087330f729Sjoerg                             "header at offset " + Twine(Offset));
1097330f729Sjoerg     }
1107330f729Sjoerg     EndCond = ' ';
1117330f729Sjoerg   }
1127330f729Sjoerg   else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#')
1137330f729Sjoerg     EndCond = ' ';
1147330f729Sjoerg   else
1157330f729Sjoerg     EndCond = '/';
1167330f729Sjoerg   StringRef::size_type end =
1177330f729Sjoerg       StringRef(ArMemHdr->Name, sizeof(ArMemHdr->Name)).find(EndCond);
1187330f729Sjoerg   if (end == StringRef::npos)
1197330f729Sjoerg     end = sizeof(ArMemHdr->Name);
1207330f729Sjoerg   assert(end <= sizeof(ArMemHdr->Name) && end > 0);
1217330f729Sjoerg   // Don't include the EndCond if there is one.
1227330f729Sjoerg   return StringRef(ArMemHdr->Name, end);
1237330f729Sjoerg }
1247330f729Sjoerg 
1257330f729Sjoerg // This gets the name looking up long names. Size is the size of the archive
1267330f729Sjoerg // member including the header, so the size of any name following the header
1277330f729Sjoerg // is checked to make sure it does not overflow.
getName(uint64_t Size) const1287330f729Sjoerg Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
1297330f729Sjoerg 
1307330f729Sjoerg   // This can be called from the ArchiveMemberHeader constructor when the
1317330f729Sjoerg   // archive header is truncated to produce an error message with the name.
1327330f729Sjoerg   // Make sure the name field is not truncated.
1337330f729Sjoerg   if (Size < offsetof(ArMemHdrType, Name) + sizeof(ArMemHdr->Name)) {
1347330f729Sjoerg     uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) -
1357330f729Sjoerg                       Parent->getData().data();
1367330f729Sjoerg     return malformedError("archive header truncated before the name field "
1377330f729Sjoerg                           "for archive member header at offset " +
1387330f729Sjoerg                           Twine(ArchiveOffset));
1397330f729Sjoerg   }
1407330f729Sjoerg 
1417330f729Sjoerg   // The raw name itself can be invalid.
1427330f729Sjoerg   Expected<StringRef> NameOrErr = getRawName();
1437330f729Sjoerg   if (!NameOrErr)
1447330f729Sjoerg     return NameOrErr.takeError();
1457330f729Sjoerg   StringRef Name = NameOrErr.get();
1467330f729Sjoerg 
1477330f729Sjoerg   // Check if it's a special name.
1487330f729Sjoerg   if (Name[0] == '/') {
1497330f729Sjoerg     if (Name.size() == 1) // Linker member.
1507330f729Sjoerg       return Name;
1517330f729Sjoerg     if (Name.size() == 2 && Name[1] == '/') // String table.
1527330f729Sjoerg       return Name;
1537330f729Sjoerg     // It's a long name.
1547330f729Sjoerg     // Get the string table offset.
1557330f729Sjoerg     std::size_t StringOffset;
1567330f729Sjoerg     if (Name.substr(1).rtrim(' ').getAsInteger(10, StringOffset)) {
1577330f729Sjoerg       std::string Buf;
1587330f729Sjoerg       raw_string_ostream OS(Buf);
1597330f729Sjoerg       OS.write_escaped(Name.substr(1).rtrim(' '));
1607330f729Sjoerg       OS.flush();
1617330f729Sjoerg       uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) -
1627330f729Sjoerg                                Parent->getData().data();
1637330f729Sjoerg       return malformedError("long name offset characters after the '/' are "
1647330f729Sjoerg                             "not all decimal numbers: '" + Buf + "' for "
1657330f729Sjoerg                             "archive member header at offset " +
1667330f729Sjoerg                             Twine(ArchiveOffset));
1677330f729Sjoerg     }
1687330f729Sjoerg 
1697330f729Sjoerg     // Verify it.
1707330f729Sjoerg     if (StringOffset >= Parent->getStringTable().size()) {
1717330f729Sjoerg       uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) -
1727330f729Sjoerg                                Parent->getData().data();
1737330f729Sjoerg       return malformedError("long name offset " + Twine(StringOffset) + " past "
1747330f729Sjoerg                             "the end of the string table for archive member "
1757330f729Sjoerg                             "header at offset " + Twine(ArchiveOffset));
1767330f729Sjoerg     }
1777330f729Sjoerg 
1787330f729Sjoerg     // GNU long file names end with a "/\n".
1797330f729Sjoerg     if (Parent->kind() == Archive::K_GNU ||
1807330f729Sjoerg         Parent->kind() == Archive::K_GNU64) {
1817330f729Sjoerg       size_t End = Parent->getStringTable().find('\n', /*From=*/StringOffset);
1827330f729Sjoerg       if (End == StringRef::npos || End < 1 ||
1837330f729Sjoerg           Parent->getStringTable()[End - 1] != '/') {
1847330f729Sjoerg         return malformedError("string table at long name offset " +
1857330f729Sjoerg                               Twine(StringOffset) + "not terminated");
1867330f729Sjoerg       }
1877330f729Sjoerg       return Parent->getStringTable().slice(StringOffset, End - 1);
1887330f729Sjoerg     }
1897330f729Sjoerg     return Parent->getStringTable().begin() + StringOffset;
1907330f729Sjoerg   }
1917330f729Sjoerg 
1927330f729Sjoerg   if (Name.startswith("#1/")) {
1937330f729Sjoerg     uint64_t NameLength;
1947330f729Sjoerg     if (Name.substr(3).rtrim(' ').getAsInteger(10, NameLength)) {
1957330f729Sjoerg       std::string Buf;
1967330f729Sjoerg       raw_string_ostream OS(Buf);
1977330f729Sjoerg       OS.write_escaped(Name.substr(3).rtrim(' '));
1987330f729Sjoerg       OS.flush();
1997330f729Sjoerg       uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) -
2007330f729Sjoerg                         Parent->getData().data();
2017330f729Sjoerg       return malformedError("long name length characters after the #1/ are "
2027330f729Sjoerg                             "not all decimal numbers: '" + Buf + "' for "
2037330f729Sjoerg                             "archive member header at offset " +
2047330f729Sjoerg                             Twine(ArchiveOffset));
2057330f729Sjoerg     }
2067330f729Sjoerg     if (getSizeOf() + NameLength > Size) {
2077330f729Sjoerg       uint64_t ArchiveOffset = reinterpret_cast<const char *>(ArMemHdr) -
2087330f729Sjoerg                         Parent->getData().data();
2097330f729Sjoerg       return malformedError("long name length: " + Twine(NameLength) +
2107330f729Sjoerg                             " extends past the end of the member or archive "
2117330f729Sjoerg                             "for archive member header at offset " +
2127330f729Sjoerg                             Twine(ArchiveOffset));
2137330f729Sjoerg     }
2147330f729Sjoerg     return StringRef(reinterpret_cast<const char *>(ArMemHdr) + getSizeOf(),
2157330f729Sjoerg                      NameLength).rtrim('\0');
2167330f729Sjoerg   }
2177330f729Sjoerg 
2187330f729Sjoerg   // It is not a long name so trim the blanks at the end of the name.
2197330f729Sjoerg   if (Name[Name.size() - 1] != '/')
2207330f729Sjoerg     return Name.rtrim(' ');
2217330f729Sjoerg 
2227330f729Sjoerg   // It's a simple name.
2237330f729Sjoerg   return Name.drop_back(1);
2247330f729Sjoerg }
2257330f729Sjoerg 
getSize() const2267330f729Sjoerg Expected<uint64_t> ArchiveMemberHeader::getSize() const {
2277330f729Sjoerg   uint64_t Ret;
2287330f729Sjoerg   if (StringRef(ArMemHdr->Size,
2297330f729Sjoerg                 sizeof(ArMemHdr->Size)).rtrim(" ").getAsInteger(10, Ret)) {
2307330f729Sjoerg     std::string Buf;
2317330f729Sjoerg     raw_string_ostream OS(Buf);
2327330f729Sjoerg     OS.write_escaped(StringRef(ArMemHdr->Size,
2337330f729Sjoerg                                sizeof(ArMemHdr->Size)).rtrim(" "));
2347330f729Sjoerg     OS.flush();
2357330f729Sjoerg     uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
2367330f729Sjoerg                       Parent->getData().data();
2377330f729Sjoerg     return malformedError("characters in size field in archive header are not "
2387330f729Sjoerg                           "all decimal numbers: '" + Buf + "' for archive "
2397330f729Sjoerg                           "member header at offset " + Twine(Offset));
2407330f729Sjoerg   }
2417330f729Sjoerg   return Ret;
2427330f729Sjoerg }
2437330f729Sjoerg 
getAccessMode() const2447330f729Sjoerg Expected<sys::fs::perms> ArchiveMemberHeader::getAccessMode() const {
2457330f729Sjoerg   unsigned Ret;
2467330f729Sjoerg   if (StringRef(ArMemHdr->AccessMode,
2477330f729Sjoerg                 sizeof(ArMemHdr->AccessMode)).rtrim(' ').getAsInteger(8, Ret)) {
2487330f729Sjoerg     std::string Buf;
2497330f729Sjoerg     raw_string_ostream OS(Buf);
2507330f729Sjoerg     OS.write_escaped(StringRef(ArMemHdr->AccessMode,
2517330f729Sjoerg                                sizeof(ArMemHdr->AccessMode)).rtrim(" "));
2527330f729Sjoerg     OS.flush();
2537330f729Sjoerg     uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
2547330f729Sjoerg                       Parent->getData().data();
2557330f729Sjoerg     return malformedError("characters in AccessMode field in archive header "
2567330f729Sjoerg                           "are not all decimal numbers: '" + Buf + "' for the "
2577330f729Sjoerg                           "archive member header at offset " + Twine(Offset));
2587330f729Sjoerg   }
2597330f729Sjoerg   return static_cast<sys::fs::perms>(Ret);
2607330f729Sjoerg }
2617330f729Sjoerg 
2627330f729Sjoerg Expected<sys::TimePoint<std::chrono::seconds>>
getLastModified() const2637330f729Sjoerg ArchiveMemberHeader::getLastModified() const {
2647330f729Sjoerg   unsigned Seconds;
2657330f729Sjoerg   if (StringRef(ArMemHdr->LastModified,
2667330f729Sjoerg                 sizeof(ArMemHdr->LastModified)).rtrim(' ')
2677330f729Sjoerg           .getAsInteger(10, Seconds)) {
2687330f729Sjoerg     std::string Buf;
2697330f729Sjoerg     raw_string_ostream OS(Buf);
2707330f729Sjoerg     OS.write_escaped(StringRef(ArMemHdr->LastModified,
2717330f729Sjoerg                                sizeof(ArMemHdr->LastModified)).rtrim(" "));
2727330f729Sjoerg     OS.flush();
2737330f729Sjoerg     uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
2747330f729Sjoerg                       Parent->getData().data();
2757330f729Sjoerg     return malformedError("characters in LastModified field in archive header "
2767330f729Sjoerg                           "are not all decimal numbers: '" + Buf + "' for the "
2777330f729Sjoerg                           "archive member header at offset " + Twine(Offset));
2787330f729Sjoerg   }
2797330f729Sjoerg 
2807330f729Sjoerg   return sys::toTimePoint(Seconds);
2817330f729Sjoerg }
2827330f729Sjoerg 
getUID() const2837330f729Sjoerg Expected<unsigned> ArchiveMemberHeader::getUID() const {
2847330f729Sjoerg   unsigned Ret;
2857330f729Sjoerg   StringRef User = StringRef(ArMemHdr->UID, sizeof(ArMemHdr->UID)).rtrim(' ');
2867330f729Sjoerg   if (User.empty())
2877330f729Sjoerg     return 0;
2887330f729Sjoerg   if (User.getAsInteger(10, Ret)) {
2897330f729Sjoerg     std::string Buf;
2907330f729Sjoerg     raw_string_ostream OS(Buf);
2917330f729Sjoerg     OS.write_escaped(User);
2927330f729Sjoerg     OS.flush();
2937330f729Sjoerg     uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
2947330f729Sjoerg                       Parent->getData().data();
2957330f729Sjoerg     return malformedError("characters in UID field in archive header "
2967330f729Sjoerg                           "are not all decimal numbers: '" + Buf + "' for the "
2977330f729Sjoerg                           "archive member header at offset " + Twine(Offset));
2987330f729Sjoerg   }
2997330f729Sjoerg   return Ret;
3007330f729Sjoerg }
3017330f729Sjoerg 
getGID() const3027330f729Sjoerg Expected<unsigned> ArchiveMemberHeader::getGID() const {
3037330f729Sjoerg   unsigned Ret;
3047330f729Sjoerg   StringRef Group = StringRef(ArMemHdr->GID, sizeof(ArMemHdr->GID)).rtrim(' ');
3057330f729Sjoerg   if (Group.empty())
3067330f729Sjoerg     return 0;
3077330f729Sjoerg   if (Group.getAsInteger(10, Ret)) {
3087330f729Sjoerg     std::string Buf;
3097330f729Sjoerg     raw_string_ostream OS(Buf);
3107330f729Sjoerg     OS.write_escaped(Group);
3117330f729Sjoerg     OS.flush();
3127330f729Sjoerg     uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
3137330f729Sjoerg                       Parent->getData().data();
3147330f729Sjoerg     return malformedError("characters in GID field in archive header "
3157330f729Sjoerg                           "are not all decimal numbers: '" + Buf + "' for the "
3167330f729Sjoerg                           "archive member header at offset " + Twine(Offset));
3177330f729Sjoerg   }
3187330f729Sjoerg   return Ret;
3197330f729Sjoerg }
3207330f729Sjoerg 
Child(const Archive * Parent,StringRef Data,uint16_t StartOfFile)3217330f729Sjoerg Archive::Child::Child(const Archive *Parent, StringRef Data,
3227330f729Sjoerg                       uint16_t StartOfFile)
3237330f729Sjoerg     : Parent(Parent), Header(Parent, Data.data(), Data.size(), nullptr),
3247330f729Sjoerg       Data(Data), StartOfFile(StartOfFile) {
3257330f729Sjoerg }
3267330f729Sjoerg 
Child(const Archive * Parent,const char * Start,Error * Err)3277330f729Sjoerg Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
3287330f729Sjoerg     : Parent(Parent),
3297330f729Sjoerg       Header(Parent, Start,
3307330f729Sjoerg              Parent
3317330f729Sjoerg                ? Parent->getData().size() - (Start - Parent->getData().data())
3327330f729Sjoerg                : 0, Err) {
3337330f729Sjoerg   if (!Start)
3347330f729Sjoerg     return;
3357330f729Sjoerg 
3367330f729Sjoerg   // If we are pointed to real data, Start is not a nullptr, then there must be
3377330f729Sjoerg   // a non-null Err pointer available to report malformed data on.  Only in
3387330f729Sjoerg   // the case sentinel value is being constructed is Err is permitted to be a
3397330f729Sjoerg   // nullptr.
3407330f729Sjoerg   assert(Err && "Err can't be nullptr if Start is not a nullptr");
3417330f729Sjoerg 
3427330f729Sjoerg   ErrorAsOutParameter ErrAsOutParam(Err);
3437330f729Sjoerg 
3447330f729Sjoerg   // If there was an error in the construction of the Header
3457330f729Sjoerg   // then just return with the error now set.
3467330f729Sjoerg   if (*Err)
3477330f729Sjoerg     return;
3487330f729Sjoerg 
3497330f729Sjoerg   uint64_t Size = Header.getSizeOf();
3507330f729Sjoerg   Data = StringRef(Start, Size);
3517330f729Sjoerg   Expected<bool> isThinOrErr = isThinMember();
3527330f729Sjoerg   if (!isThinOrErr) {
3537330f729Sjoerg     *Err = isThinOrErr.takeError();
3547330f729Sjoerg     return;
3557330f729Sjoerg   }
3567330f729Sjoerg   bool isThin = isThinOrErr.get();
3577330f729Sjoerg   if (!isThin) {
3587330f729Sjoerg     Expected<uint64_t> MemberSize = getRawSize();
3597330f729Sjoerg     if (!MemberSize) {
3607330f729Sjoerg       *Err = MemberSize.takeError();
3617330f729Sjoerg       return;
3627330f729Sjoerg     }
3637330f729Sjoerg     Size += MemberSize.get();
3647330f729Sjoerg     Data = StringRef(Start, Size);
3657330f729Sjoerg   }
3667330f729Sjoerg 
3677330f729Sjoerg   // Setup StartOfFile and PaddingBytes.
3687330f729Sjoerg   StartOfFile = Header.getSizeOf();
3697330f729Sjoerg   // Don't include attached name.
3707330f729Sjoerg   Expected<StringRef> NameOrErr = getRawName();
3717330f729Sjoerg   if (!NameOrErr){
3727330f729Sjoerg     *Err = NameOrErr.takeError();
3737330f729Sjoerg     return;
3747330f729Sjoerg   }
3757330f729Sjoerg   StringRef Name = NameOrErr.get();
3767330f729Sjoerg   if (Name.startswith("#1/")) {
3777330f729Sjoerg     uint64_t NameSize;
3787330f729Sjoerg     if (Name.substr(3).rtrim(' ').getAsInteger(10, NameSize)) {
3797330f729Sjoerg       std::string Buf;
3807330f729Sjoerg       raw_string_ostream OS(Buf);
3817330f729Sjoerg       OS.write_escaped(Name.substr(3).rtrim(' '));
3827330f729Sjoerg       OS.flush();
3837330f729Sjoerg       uint64_t Offset = Start - Parent->getData().data();
3847330f729Sjoerg       *Err = malformedError("long name length characters after the #1/ are "
3857330f729Sjoerg                             "not all decimal numbers: '" + Buf + "' for "
3867330f729Sjoerg                             "archive member header at offset " +
3877330f729Sjoerg                             Twine(Offset));
3887330f729Sjoerg       return;
3897330f729Sjoerg     }
3907330f729Sjoerg     StartOfFile += NameSize;
3917330f729Sjoerg   }
3927330f729Sjoerg }
3937330f729Sjoerg 
getSize() const3947330f729Sjoerg Expected<uint64_t> Archive::Child::getSize() const {
395*82d56013Sjoerg   if (Parent->IsThin)
396*82d56013Sjoerg     return Header.getSize();
3977330f729Sjoerg   return Data.size() - StartOfFile;
3987330f729Sjoerg }
3997330f729Sjoerg 
getRawSize() const4007330f729Sjoerg Expected<uint64_t> Archive::Child::getRawSize() const {
4017330f729Sjoerg   return Header.getSize();
4027330f729Sjoerg }
4037330f729Sjoerg 
isThinMember() const4047330f729Sjoerg Expected<bool> Archive::Child::isThinMember() const {
4057330f729Sjoerg   Expected<StringRef> NameOrErr = Header.getRawName();
4067330f729Sjoerg   if (!NameOrErr)
4077330f729Sjoerg     return NameOrErr.takeError();
4087330f729Sjoerg   StringRef Name = NameOrErr.get();
4097330f729Sjoerg   return Parent->IsThin && Name != "/" && Name != "//";
4107330f729Sjoerg }
4117330f729Sjoerg 
getFullName() const4127330f729Sjoerg Expected<std::string> Archive::Child::getFullName() const {
4137330f729Sjoerg   Expected<bool> isThin = isThinMember();
4147330f729Sjoerg   if (!isThin)
4157330f729Sjoerg     return isThin.takeError();
4167330f729Sjoerg   assert(isThin.get());
4177330f729Sjoerg   Expected<StringRef> NameOrErr = getName();
4187330f729Sjoerg   if (!NameOrErr)
4197330f729Sjoerg     return NameOrErr.takeError();
4207330f729Sjoerg   StringRef Name = *NameOrErr;
4217330f729Sjoerg   if (sys::path::is_absolute(Name))
422*82d56013Sjoerg     return std::string(Name);
4237330f729Sjoerg 
4247330f729Sjoerg   SmallString<128> FullName = sys::path::parent_path(
4257330f729Sjoerg       Parent->getMemoryBufferRef().getBufferIdentifier());
4267330f729Sjoerg   sys::path::append(FullName, Name);
427*82d56013Sjoerg   return std::string(FullName.str());
4287330f729Sjoerg }
4297330f729Sjoerg 
getBuffer() const4307330f729Sjoerg Expected<StringRef> Archive::Child::getBuffer() const {
4317330f729Sjoerg   Expected<bool> isThinOrErr = isThinMember();
4327330f729Sjoerg   if (!isThinOrErr)
4337330f729Sjoerg     return isThinOrErr.takeError();
4347330f729Sjoerg   bool isThin = isThinOrErr.get();
4357330f729Sjoerg   if (!isThin) {
436*82d56013Sjoerg     Expected<uint64_t> Size = getSize();
4377330f729Sjoerg     if (!Size)
4387330f729Sjoerg       return Size.takeError();
4397330f729Sjoerg     return StringRef(Data.data() + StartOfFile, Size.get());
4407330f729Sjoerg   }
4417330f729Sjoerg   Expected<std::string> FullNameOrErr = getFullName();
4427330f729Sjoerg   if (!FullNameOrErr)
4437330f729Sjoerg     return FullNameOrErr.takeError();
4447330f729Sjoerg   const std::string &FullName = *FullNameOrErr;
4457330f729Sjoerg   ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName);
4467330f729Sjoerg   if (std::error_code EC = Buf.getError())
4477330f729Sjoerg     return errorCodeToError(EC);
4487330f729Sjoerg   Parent->ThinBuffers.push_back(std::move(*Buf));
4497330f729Sjoerg   return Parent->ThinBuffers.back()->getBuffer();
4507330f729Sjoerg }
4517330f729Sjoerg 
getNext() const4527330f729Sjoerg Expected<Archive::Child> Archive::Child::getNext() const {
4537330f729Sjoerg   size_t SpaceToSkip = Data.size();
4547330f729Sjoerg   // If it's odd, add 1 to make it even.
4557330f729Sjoerg   if (SpaceToSkip & 1)
4567330f729Sjoerg     ++SpaceToSkip;
4577330f729Sjoerg 
4587330f729Sjoerg   const char *NextLoc = Data.data() + SpaceToSkip;
4597330f729Sjoerg 
4607330f729Sjoerg   // Check to see if this is at the end of the archive.
4617330f729Sjoerg   if (NextLoc == Parent->Data.getBufferEnd())
4627330f729Sjoerg     return Child(nullptr, nullptr, nullptr);
4637330f729Sjoerg 
4647330f729Sjoerg   // Check to see if this is past the end of the archive.
4657330f729Sjoerg   if (NextLoc > Parent->Data.getBufferEnd()) {
4667330f729Sjoerg     std::string Msg("offset to next archive member past the end of the archive "
4677330f729Sjoerg                     "after member ");
4687330f729Sjoerg     Expected<StringRef> NameOrErr = getName();
4697330f729Sjoerg     if (!NameOrErr) {
4707330f729Sjoerg       consumeError(NameOrErr.takeError());
4717330f729Sjoerg       uint64_t Offset = Data.data() - Parent->getData().data();
4727330f729Sjoerg       return malformedError(Msg + "at offset " + Twine(Offset));
4737330f729Sjoerg     } else
4747330f729Sjoerg       return malformedError(Msg + NameOrErr.get());
4757330f729Sjoerg   }
4767330f729Sjoerg 
4777330f729Sjoerg   Error Err = Error::success();
4787330f729Sjoerg   Child Ret(Parent, NextLoc, &Err);
4797330f729Sjoerg   if (Err)
4807330f729Sjoerg     return std::move(Err);
4817330f729Sjoerg   return Ret;
4827330f729Sjoerg }
4837330f729Sjoerg 
getChildOffset() const4847330f729Sjoerg uint64_t Archive::Child::getChildOffset() const {
4857330f729Sjoerg   const char *a = Parent->Data.getBuffer().data();
4867330f729Sjoerg   const char *c = Data.data();
4877330f729Sjoerg   uint64_t offset = c - a;
4887330f729Sjoerg   return offset;
4897330f729Sjoerg }
4907330f729Sjoerg 
getName() const4917330f729Sjoerg Expected<StringRef> Archive::Child::getName() const {
4927330f729Sjoerg   Expected<uint64_t> RawSizeOrErr = getRawSize();
4937330f729Sjoerg   if (!RawSizeOrErr)
4947330f729Sjoerg     return RawSizeOrErr.takeError();
4957330f729Sjoerg   uint64_t RawSize = RawSizeOrErr.get();
4967330f729Sjoerg   Expected<StringRef> NameOrErr = Header.getName(Header.getSizeOf() + RawSize);
4977330f729Sjoerg   if (!NameOrErr)
4987330f729Sjoerg     return NameOrErr.takeError();
4997330f729Sjoerg   StringRef Name = NameOrErr.get();
5007330f729Sjoerg   return Name;
5017330f729Sjoerg }
5027330f729Sjoerg 
getMemoryBufferRef() const5037330f729Sjoerg Expected<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {
5047330f729Sjoerg   Expected<StringRef> NameOrErr = getName();
5057330f729Sjoerg   if (!NameOrErr)
5067330f729Sjoerg     return NameOrErr.takeError();
5077330f729Sjoerg   StringRef Name = NameOrErr.get();
5087330f729Sjoerg   Expected<StringRef> Buf = getBuffer();
5097330f729Sjoerg   if (!Buf)
5107330f729Sjoerg     return createFileError(Name, Buf.takeError());
5117330f729Sjoerg   return MemoryBufferRef(*Buf, Name);
5127330f729Sjoerg }
5137330f729Sjoerg 
5147330f729Sjoerg Expected<std::unique_ptr<Binary>>
getAsBinary(LLVMContext * Context) const5157330f729Sjoerg Archive::Child::getAsBinary(LLVMContext *Context) const {
5167330f729Sjoerg   Expected<MemoryBufferRef> BuffOrErr = getMemoryBufferRef();
5177330f729Sjoerg   if (!BuffOrErr)
5187330f729Sjoerg     return BuffOrErr.takeError();
5197330f729Sjoerg 
5207330f729Sjoerg   auto BinaryOrErr = createBinary(BuffOrErr.get(), Context);
5217330f729Sjoerg   if (BinaryOrErr)
5227330f729Sjoerg     return std::move(*BinaryOrErr);
5237330f729Sjoerg   return BinaryOrErr.takeError();
5247330f729Sjoerg }
5257330f729Sjoerg 
create(MemoryBufferRef Source)5267330f729Sjoerg Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {
5277330f729Sjoerg   Error Err = Error::success();
5287330f729Sjoerg   std::unique_ptr<Archive> Ret(new Archive(Source, Err));
5297330f729Sjoerg   if (Err)
5307330f729Sjoerg     return std::move(Err);
5317330f729Sjoerg   return std::move(Ret);
5327330f729Sjoerg }
5337330f729Sjoerg 
setFirstRegular(const Child & C)5347330f729Sjoerg void Archive::setFirstRegular(const Child &C) {
5357330f729Sjoerg   FirstRegularData = C.Data;
5367330f729Sjoerg   FirstRegularStartOfFile = C.StartOfFile;
5377330f729Sjoerg }
5387330f729Sjoerg 
Archive(MemoryBufferRef Source,Error & Err)5397330f729Sjoerg Archive::Archive(MemoryBufferRef Source, Error &Err)
5407330f729Sjoerg     : Binary(Binary::ID_Archive, Source) {
5417330f729Sjoerg   ErrorAsOutParameter ErrAsOutParam(&Err);
5427330f729Sjoerg   StringRef Buffer = Data.getBuffer();
5437330f729Sjoerg   // Check for sufficient magic.
5447330f729Sjoerg   if (Buffer.startswith(ThinMagic)) {
5457330f729Sjoerg     IsThin = true;
5467330f729Sjoerg   } else if (Buffer.startswith(Magic)) {
5477330f729Sjoerg     IsThin = false;
5487330f729Sjoerg   } else {
5497330f729Sjoerg     Err = make_error<GenericBinaryError>("file too small to be an archive",
5507330f729Sjoerg                                          object_error::invalid_file_type);
5517330f729Sjoerg     return;
5527330f729Sjoerg   }
5537330f729Sjoerg 
5547330f729Sjoerg   // Make sure Format is initialized before any call to
5557330f729Sjoerg   // ArchiveMemberHeader::getName() is made.  This could be a valid empty
5567330f729Sjoerg   // archive which is the same in all formats.  So claiming it to be gnu to is
5577330f729Sjoerg   // fine if not totally correct before we look for a string table or table of
5587330f729Sjoerg   // contents.
5597330f729Sjoerg   Format = K_GNU;
5607330f729Sjoerg 
5617330f729Sjoerg   // Get the special members.
5627330f729Sjoerg   child_iterator I = child_begin(Err, false);
5637330f729Sjoerg   if (Err)
5647330f729Sjoerg     return;
5657330f729Sjoerg   child_iterator E = child_end();
5667330f729Sjoerg 
5677330f729Sjoerg   // See if this is a valid empty archive and if so return.
5687330f729Sjoerg   if (I == E) {
5697330f729Sjoerg     Err = Error::success();
5707330f729Sjoerg     return;
5717330f729Sjoerg   }
5727330f729Sjoerg   const Child *C = &*I;
5737330f729Sjoerg 
5747330f729Sjoerg   auto Increment = [&]() {
5757330f729Sjoerg     ++I;
5767330f729Sjoerg     if (Err)
5777330f729Sjoerg       return true;
5787330f729Sjoerg     C = &*I;
5797330f729Sjoerg     return false;
5807330f729Sjoerg   };
5817330f729Sjoerg 
5827330f729Sjoerg   Expected<StringRef> NameOrErr = C->getRawName();
5837330f729Sjoerg   if (!NameOrErr) {
5847330f729Sjoerg     Err = NameOrErr.takeError();
5857330f729Sjoerg     return;
5867330f729Sjoerg   }
5877330f729Sjoerg   StringRef Name = NameOrErr.get();
5887330f729Sjoerg 
5897330f729Sjoerg   // Below is the pattern that is used to figure out the archive format
5907330f729Sjoerg   // GNU archive format
5917330f729Sjoerg   //  First member : / (may exist, if it exists, points to the symbol table )
5927330f729Sjoerg   //  Second member : // (may exist, if it exists, points to the string table)
5937330f729Sjoerg   //  Note : The string table is used if the filename exceeds 15 characters
5947330f729Sjoerg   // BSD archive format
5957330f729Sjoerg   //  First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table)
5967330f729Sjoerg   //  There is no string table, if the filename exceeds 15 characters or has a
5977330f729Sjoerg   //  embedded space, the filename has #1/<size>, The size represents the size
5987330f729Sjoerg   //  of the filename that needs to be read after the archive header
5997330f729Sjoerg   // COFF archive format
6007330f729Sjoerg   //  First member : /
6017330f729Sjoerg   //  Second member : / (provides a directory of symbols)
6027330f729Sjoerg   //  Third member : // (may exist, if it exists, contains the string table)
6037330f729Sjoerg   //  Note: Microsoft PE/COFF Spec 8.3 says that the third member is present
6047330f729Sjoerg   //  even if the string table is empty. However, lib.exe does not in fact
6057330f729Sjoerg   //  seem to create the third member if there's no member whose filename
6067330f729Sjoerg   //  exceeds 15 characters. So the third member is optional.
6077330f729Sjoerg 
6087330f729Sjoerg   if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {
6097330f729Sjoerg     if (Name == "__.SYMDEF")
6107330f729Sjoerg       Format = K_BSD;
6117330f729Sjoerg     else // Name == "__.SYMDEF_64"
6127330f729Sjoerg       Format = K_DARWIN64;
6137330f729Sjoerg     // We know that the symbol table is not an external file, but we still must
6147330f729Sjoerg     // check any Expected<> return value.
6157330f729Sjoerg     Expected<StringRef> BufOrErr = C->getBuffer();
6167330f729Sjoerg     if (!BufOrErr) {
6177330f729Sjoerg       Err = BufOrErr.takeError();
6187330f729Sjoerg       return;
6197330f729Sjoerg     }
6207330f729Sjoerg     SymbolTable = BufOrErr.get();
6217330f729Sjoerg     if (Increment())
6227330f729Sjoerg       return;
6237330f729Sjoerg     setFirstRegular(*C);
6247330f729Sjoerg 
6257330f729Sjoerg     Err = Error::success();
6267330f729Sjoerg     return;
6277330f729Sjoerg   }
6287330f729Sjoerg 
6297330f729Sjoerg   if (Name.startswith("#1/")) {
6307330f729Sjoerg     Format = K_BSD;
6317330f729Sjoerg     // We know this is BSD, so getName will work since there is no string table.
6327330f729Sjoerg     Expected<StringRef> NameOrErr = C->getName();
6337330f729Sjoerg     if (!NameOrErr) {
6347330f729Sjoerg       Err = NameOrErr.takeError();
6357330f729Sjoerg       return;
6367330f729Sjoerg     }
6377330f729Sjoerg     Name = NameOrErr.get();
6387330f729Sjoerg     if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
6397330f729Sjoerg       // We know that the symbol table is not an external file, but we still
6407330f729Sjoerg       // must check any Expected<> return value.
6417330f729Sjoerg       Expected<StringRef> BufOrErr = C->getBuffer();
6427330f729Sjoerg       if (!BufOrErr) {
6437330f729Sjoerg         Err = BufOrErr.takeError();
6447330f729Sjoerg         return;
6457330f729Sjoerg       }
6467330f729Sjoerg       SymbolTable = BufOrErr.get();
6477330f729Sjoerg       if (Increment())
6487330f729Sjoerg         return;
6497330f729Sjoerg     }
6507330f729Sjoerg     else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {
6517330f729Sjoerg       Format = K_DARWIN64;
6527330f729Sjoerg       // We know that the symbol table is not an external file, but we still
6537330f729Sjoerg       // must check any Expected<> return value.
6547330f729Sjoerg       Expected<StringRef> BufOrErr = C->getBuffer();
6557330f729Sjoerg       if (!BufOrErr) {
6567330f729Sjoerg         Err = BufOrErr.takeError();
6577330f729Sjoerg         return;
6587330f729Sjoerg       }
6597330f729Sjoerg       SymbolTable = BufOrErr.get();
6607330f729Sjoerg       if (Increment())
6617330f729Sjoerg         return;
6627330f729Sjoerg     }
6637330f729Sjoerg     setFirstRegular(*C);
6647330f729Sjoerg     return;
6657330f729Sjoerg   }
6667330f729Sjoerg 
6677330f729Sjoerg   // MIPS 64-bit ELF archives use a special format of a symbol table.
6687330f729Sjoerg   // This format is marked by `ar_name` field equals to "/SYM64/".
6697330f729Sjoerg   // For detailed description see page 96 in the following document:
6707330f729Sjoerg   // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
6717330f729Sjoerg 
6727330f729Sjoerg   bool has64SymTable = false;
6737330f729Sjoerg   if (Name == "/" || Name == "/SYM64/") {
6747330f729Sjoerg     // We know that the symbol table is not an external file, but we still
6757330f729Sjoerg     // must check any Expected<> return value.
6767330f729Sjoerg     Expected<StringRef> BufOrErr = C->getBuffer();
6777330f729Sjoerg     if (!BufOrErr) {
6787330f729Sjoerg       Err = BufOrErr.takeError();
6797330f729Sjoerg       return;
6807330f729Sjoerg     }
6817330f729Sjoerg     SymbolTable = BufOrErr.get();
6827330f729Sjoerg     if (Name == "/SYM64/")
6837330f729Sjoerg       has64SymTable = true;
6847330f729Sjoerg 
6857330f729Sjoerg     if (Increment())
6867330f729Sjoerg       return;
6877330f729Sjoerg     if (I == E) {
6887330f729Sjoerg       Err = Error::success();
6897330f729Sjoerg       return;
6907330f729Sjoerg     }
6917330f729Sjoerg     Expected<StringRef> NameOrErr = C->getRawName();
6927330f729Sjoerg     if (!NameOrErr) {
6937330f729Sjoerg       Err = NameOrErr.takeError();
6947330f729Sjoerg       return;
6957330f729Sjoerg     }
6967330f729Sjoerg     Name = NameOrErr.get();
6977330f729Sjoerg   }
6987330f729Sjoerg 
6997330f729Sjoerg   if (Name == "//") {
7007330f729Sjoerg     Format = has64SymTable ? K_GNU64 : K_GNU;
7017330f729Sjoerg     // The string table is never an external member, but we still
7027330f729Sjoerg     // must check any Expected<> return value.
7037330f729Sjoerg     Expected<StringRef> BufOrErr = C->getBuffer();
7047330f729Sjoerg     if (!BufOrErr) {
7057330f729Sjoerg       Err = BufOrErr.takeError();
7067330f729Sjoerg       return;
7077330f729Sjoerg     }
7087330f729Sjoerg     StringTable = BufOrErr.get();
7097330f729Sjoerg     if (Increment())
7107330f729Sjoerg       return;
7117330f729Sjoerg     setFirstRegular(*C);
7127330f729Sjoerg     Err = Error::success();
7137330f729Sjoerg     return;
7147330f729Sjoerg   }
7157330f729Sjoerg 
7167330f729Sjoerg   if (Name[0] != '/') {
7177330f729Sjoerg     Format = has64SymTable ? K_GNU64 : K_GNU;
7187330f729Sjoerg     setFirstRegular(*C);
7197330f729Sjoerg     Err = Error::success();
7207330f729Sjoerg     return;
7217330f729Sjoerg   }
7227330f729Sjoerg 
7237330f729Sjoerg   if (Name != "/") {
7247330f729Sjoerg     Err = errorCodeToError(object_error::parse_failed);
7257330f729Sjoerg     return;
7267330f729Sjoerg   }
7277330f729Sjoerg 
7287330f729Sjoerg   Format = K_COFF;
7297330f729Sjoerg   // We know that the symbol table is not an external file, but we still
7307330f729Sjoerg   // must check any Expected<> return value.
7317330f729Sjoerg   Expected<StringRef> BufOrErr = C->getBuffer();
7327330f729Sjoerg   if (!BufOrErr) {
7337330f729Sjoerg     Err = BufOrErr.takeError();
7347330f729Sjoerg     return;
7357330f729Sjoerg   }
7367330f729Sjoerg   SymbolTable = BufOrErr.get();
7377330f729Sjoerg 
7387330f729Sjoerg   if (Increment())
7397330f729Sjoerg     return;
7407330f729Sjoerg 
7417330f729Sjoerg   if (I == E) {
7427330f729Sjoerg     setFirstRegular(*C);
7437330f729Sjoerg     Err = Error::success();
7447330f729Sjoerg     return;
7457330f729Sjoerg   }
7467330f729Sjoerg 
7477330f729Sjoerg   NameOrErr = C->getRawName();
7487330f729Sjoerg   if (!NameOrErr) {
7497330f729Sjoerg     Err = NameOrErr.takeError();
7507330f729Sjoerg     return;
7517330f729Sjoerg   }
7527330f729Sjoerg   Name = NameOrErr.get();
7537330f729Sjoerg 
7547330f729Sjoerg   if (Name == "//") {
7557330f729Sjoerg     // The string table is never an external member, but we still
7567330f729Sjoerg     // must check any Expected<> return value.
7577330f729Sjoerg     Expected<StringRef> BufOrErr = C->getBuffer();
7587330f729Sjoerg     if (!BufOrErr) {
7597330f729Sjoerg       Err = BufOrErr.takeError();
7607330f729Sjoerg       return;
7617330f729Sjoerg     }
7627330f729Sjoerg     StringTable = BufOrErr.get();
7637330f729Sjoerg     if (Increment())
7647330f729Sjoerg       return;
7657330f729Sjoerg   }
7667330f729Sjoerg 
7677330f729Sjoerg   setFirstRegular(*C);
7687330f729Sjoerg   Err = Error::success();
7697330f729Sjoerg }
7707330f729Sjoerg 
child_begin(Error & Err,bool SkipInternal) const7717330f729Sjoerg Archive::child_iterator Archive::child_begin(Error &Err,
7727330f729Sjoerg                                              bool SkipInternal) const {
7737330f729Sjoerg   if (isEmpty())
7747330f729Sjoerg     return child_end();
7757330f729Sjoerg 
7767330f729Sjoerg   if (SkipInternal)
7777330f729Sjoerg     return child_iterator::itr(
7787330f729Sjoerg         Child(this, FirstRegularData, FirstRegularStartOfFile), Err);
7797330f729Sjoerg 
7807330f729Sjoerg   const char *Loc = Data.getBufferStart() + strlen(Magic);
7817330f729Sjoerg   Child C(this, Loc, &Err);
7827330f729Sjoerg   if (Err)
7837330f729Sjoerg     return child_end();
7847330f729Sjoerg   return child_iterator::itr(C, Err);
7857330f729Sjoerg }
7867330f729Sjoerg 
child_end() const7877330f729Sjoerg Archive::child_iterator Archive::child_end() const {
7887330f729Sjoerg   return child_iterator::end(Child(nullptr, nullptr, nullptr));
7897330f729Sjoerg }
7907330f729Sjoerg 
getName() const7917330f729Sjoerg StringRef Archive::Symbol::getName() const {
7927330f729Sjoerg   return Parent->getSymbolTable().begin() + StringIndex;
7937330f729Sjoerg }
7947330f729Sjoerg 
getMember() const7957330f729Sjoerg Expected<Archive::Child> Archive::Symbol::getMember() const {
7967330f729Sjoerg   const char *Buf = Parent->getSymbolTable().begin();
7977330f729Sjoerg   const char *Offsets = Buf;
7987330f729Sjoerg   if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64)
7997330f729Sjoerg     Offsets += sizeof(uint64_t);
8007330f729Sjoerg   else
8017330f729Sjoerg     Offsets += sizeof(uint32_t);
8027330f729Sjoerg   uint64_t Offset = 0;
8037330f729Sjoerg   if (Parent->kind() == K_GNU) {
8047330f729Sjoerg     Offset = read32be(Offsets + SymbolIndex * 4);
8057330f729Sjoerg   } else if (Parent->kind() == K_GNU64) {
8067330f729Sjoerg     Offset = read64be(Offsets + SymbolIndex * 8);
8077330f729Sjoerg   } else if (Parent->kind() == K_BSD) {
8087330f729Sjoerg     // The SymbolIndex is an index into the ranlib structs that start at
8097330f729Sjoerg     // Offsets (the first uint32_t is the number of bytes of the ranlib
8107330f729Sjoerg     // structs).  The ranlib structs are a pair of uint32_t's the first
8117330f729Sjoerg     // being a string table offset and the second being the offset into
8127330f729Sjoerg     // the archive of the member that defines the symbol.  Which is what
8137330f729Sjoerg     // is needed here.
8147330f729Sjoerg     Offset = read32le(Offsets + SymbolIndex * 8 + 4);
8157330f729Sjoerg   } else if (Parent->kind() == K_DARWIN64) {
8167330f729Sjoerg     // The SymbolIndex is an index into the ranlib_64 structs that start at
8177330f729Sjoerg     // Offsets (the first uint64_t is the number of bytes of the ranlib_64
8187330f729Sjoerg     // structs).  The ranlib_64 structs are a pair of uint64_t's the first
8197330f729Sjoerg     // being a string table offset and the second being the offset into
8207330f729Sjoerg     // the archive of the member that defines the symbol.  Which is what
8217330f729Sjoerg     // is needed here.
8227330f729Sjoerg     Offset = read64le(Offsets + SymbolIndex * 16 + 8);
8237330f729Sjoerg   } else {
8247330f729Sjoerg     // Skip offsets.
8257330f729Sjoerg     uint32_t MemberCount = read32le(Buf);
8267330f729Sjoerg     Buf += MemberCount * 4 + 4;
8277330f729Sjoerg 
8287330f729Sjoerg     uint32_t SymbolCount = read32le(Buf);
8297330f729Sjoerg     if (SymbolIndex >= SymbolCount)
8307330f729Sjoerg       return errorCodeToError(object_error::parse_failed);
8317330f729Sjoerg 
8327330f729Sjoerg     // Skip SymbolCount to get to the indices table.
8337330f729Sjoerg     const char *Indices = Buf + 4;
8347330f729Sjoerg 
8357330f729Sjoerg     // Get the index of the offset in the file member offset table for this
8367330f729Sjoerg     // symbol.
8377330f729Sjoerg     uint16_t OffsetIndex = read16le(Indices + SymbolIndex * 2);
8387330f729Sjoerg     // Subtract 1 since OffsetIndex is 1 based.
8397330f729Sjoerg     --OffsetIndex;
8407330f729Sjoerg 
8417330f729Sjoerg     if (OffsetIndex >= MemberCount)
8427330f729Sjoerg       return errorCodeToError(object_error::parse_failed);
8437330f729Sjoerg 
8447330f729Sjoerg     Offset = read32le(Offsets + OffsetIndex * 4);
8457330f729Sjoerg   }
8467330f729Sjoerg 
8477330f729Sjoerg   const char *Loc = Parent->getData().begin() + Offset;
8487330f729Sjoerg   Error Err = Error::success();
8497330f729Sjoerg   Child C(Parent, Loc, &Err);
8507330f729Sjoerg   if (Err)
8517330f729Sjoerg     return std::move(Err);
8527330f729Sjoerg   return C;
8537330f729Sjoerg }
8547330f729Sjoerg 
getNext() const8557330f729Sjoerg Archive::Symbol Archive::Symbol::getNext() const {
8567330f729Sjoerg   Symbol t(*this);
8577330f729Sjoerg   if (Parent->kind() == K_BSD) {
8587330f729Sjoerg     // t.StringIndex is an offset from the start of the __.SYMDEF or
8597330f729Sjoerg     // "__.SYMDEF SORTED" member into the string table for the ranlib
8607330f729Sjoerg     // struct indexed by t.SymbolIndex .  To change t.StringIndex to the
8617330f729Sjoerg     // offset in the string table for t.SymbolIndex+1 we subtract the
8627330f729Sjoerg     // its offset from the start of the string table for t.SymbolIndex
8637330f729Sjoerg     // and add the offset of the string table for t.SymbolIndex+1.
8647330f729Sjoerg 
8657330f729Sjoerg     // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
8667330f729Sjoerg     // which is the number of bytes of ranlib structs that follow.  The ranlib
8677330f729Sjoerg     // structs are a pair of uint32_t's the first being a string table offset
8687330f729Sjoerg     // and the second being the offset into the archive of the member that
8697330f729Sjoerg     // define the symbol. After that the next uint32_t is the byte count of
8707330f729Sjoerg     // the string table followed by the string table.
8717330f729Sjoerg     const char *Buf = Parent->getSymbolTable().begin();
8727330f729Sjoerg     uint32_t RanlibCount = 0;
8737330f729Sjoerg     RanlibCount = read32le(Buf) / 8;
8747330f729Sjoerg     // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount)
8757330f729Sjoerg     // don't change the t.StringIndex as we don't want to reference a ranlib
8767330f729Sjoerg     // past RanlibCount.
8777330f729Sjoerg     if (t.SymbolIndex + 1 < RanlibCount) {
8787330f729Sjoerg       const char *Ranlibs = Buf + 4;
8797330f729Sjoerg       uint32_t CurRanStrx = 0;
8807330f729Sjoerg       uint32_t NextRanStrx = 0;
8817330f729Sjoerg       CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8);
8827330f729Sjoerg       NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8);
8837330f729Sjoerg       t.StringIndex -= CurRanStrx;
8847330f729Sjoerg       t.StringIndex += NextRanStrx;
8857330f729Sjoerg     }
8867330f729Sjoerg   } else {
8877330f729Sjoerg     // Go to one past next null.
8887330f729Sjoerg     t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1;
8897330f729Sjoerg   }
8907330f729Sjoerg   ++t.SymbolIndex;
8917330f729Sjoerg   return t;
8927330f729Sjoerg }
8937330f729Sjoerg 
symbol_begin() const8947330f729Sjoerg Archive::symbol_iterator Archive::symbol_begin() const {
8957330f729Sjoerg   if (!hasSymbolTable())
8967330f729Sjoerg     return symbol_iterator(Symbol(this, 0, 0));
8977330f729Sjoerg 
8987330f729Sjoerg   const char *buf = getSymbolTable().begin();
8997330f729Sjoerg   if (kind() == K_GNU) {
9007330f729Sjoerg     uint32_t symbol_count = 0;
9017330f729Sjoerg     symbol_count = read32be(buf);
9027330f729Sjoerg     buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
9037330f729Sjoerg   } else if (kind() == K_GNU64) {
9047330f729Sjoerg     uint64_t symbol_count = read64be(buf);
9057330f729Sjoerg     buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));
9067330f729Sjoerg   } else if (kind() == K_BSD) {
9077330f729Sjoerg     // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
9087330f729Sjoerg     // which is the number of bytes of ranlib structs that follow.  The ranlib
9097330f729Sjoerg     // structs are a pair of uint32_t's the first being a string table offset
9107330f729Sjoerg     // and the second being the offset into the archive of the member that
9117330f729Sjoerg     // define the symbol. After that the next uint32_t is the byte count of
9127330f729Sjoerg     // the string table followed by the string table.
9137330f729Sjoerg     uint32_t ranlib_count = 0;
9147330f729Sjoerg     ranlib_count = read32le(buf) / 8;
9157330f729Sjoerg     const char *ranlibs = buf + 4;
9167330f729Sjoerg     uint32_t ran_strx = 0;
9177330f729Sjoerg     ran_strx = read32le(ranlibs);
9187330f729Sjoerg     buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t))));
9197330f729Sjoerg     // Skip the byte count of the string table.
9207330f729Sjoerg     buf += sizeof(uint32_t);
9217330f729Sjoerg     buf += ran_strx;
9227330f729Sjoerg   } else if (kind() == K_DARWIN64) {
9237330f729Sjoerg     // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t
9247330f729Sjoerg     // which is the number of bytes of ranlib_64 structs that follow.  The
9257330f729Sjoerg     // ranlib_64 structs are a pair of uint64_t's the first being a string
9267330f729Sjoerg     // table offset and the second being the offset into the archive of the
9277330f729Sjoerg     // member that define the symbol. After that the next uint64_t is the byte
9287330f729Sjoerg     // count of the string table followed by the string table.
9297330f729Sjoerg     uint64_t ranlib_count = 0;
9307330f729Sjoerg     ranlib_count = read64le(buf) / 16;
9317330f729Sjoerg     const char *ranlibs = buf + 8;
9327330f729Sjoerg     uint64_t ran_strx = 0;
9337330f729Sjoerg     ran_strx = read64le(ranlibs);
9347330f729Sjoerg     buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t))));
9357330f729Sjoerg     // Skip the byte count of the string table.
9367330f729Sjoerg     buf += sizeof(uint64_t);
9377330f729Sjoerg     buf += ran_strx;
9387330f729Sjoerg   } else {
9397330f729Sjoerg     uint32_t member_count = 0;
9407330f729Sjoerg     uint32_t symbol_count = 0;
9417330f729Sjoerg     member_count = read32le(buf);
9427330f729Sjoerg     buf += 4 + (member_count * 4); // Skip offsets.
9437330f729Sjoerg     symbol_count = read32le(buf);
9447330f729Sjoerg     buf += 4 + (symbol_count * 2); // Skip indices.
9457330f729Sjoerg   }
9467330f729Sjoerg   uint32_t string_start_offset = buf - getSymbolTable().begin();
9477330f729Sjoerg   return symbol_iterator(Symbol(this, 0, string_start_offset));
9487330f729Sjoerg }
9497330f729Sjoerg 
symbol_end() const9507330f729Sjoerg Archive::symbol_iterator Archive::symbol_end() const {
9517330f729Sjoerg   return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0));
9527330f729Sjoerg }
9537330f729Sjoerg 
getNumberOfSymbols() const9547330f729Sjoerg uint32_t Archive::getNumberOfSymbols() const {
9557330f729Sjoerg   if (!hasSymbolTable())
9567330f729Sjoerg     return 0;
9577330f729Sjoerg   const char *buf = getSymbolTable().begin();
9587330f729Sjoerg   if (kind() == K_GNU)
9597330f729Sjoerg     return read32be(buf);
9607330f729Sjoerg   if (kind() == K_GNU64)
9617330f729Sjoerg     return read64be(buf);
9627330f729Sjoerg   if (kind() == K_BSD)
9637330f729Sjoerg     return read32le(buf) / 8;
9647330f729Sjoerg   if (kind() == K_DARWIN64)
9657330f729Sjoerg     return read64le(buf) / 16;
9667330f729Sjoerg   uint32_t member_count = 0;
9677330f729Sjoerg   member_count = read32le(buf);
9687330f729Sjoerg   buf += 4 + (member_count * 4); // Skip offsets.
9697330f729Sjoerg   return read32le(buf);
9707330f729Sjoerg }
9717330f729Sjoerg 
findSym(StringRef name) const9727330f729Sjoerg Expected<Optional<Archive::Child>> Archive::findSym(StringRef name) const {
9737330f729Sjoerg   Archive::symbol_iterator bs = symbol_begin();
9747330f729Sjoerg   Archive::symbol_iterator es = symbol_end();
9757330f729Sjoerg 
9767330f729Sjoerg   for (; bs != es; ++bs) {
9777330f729Sjoerg     StringRef SymName = bs->getName();
9787330f729Sjoerg     if (SymName == name) {
9797330f729Sjoerg       if (auto MemberOrErr = bs->getMember())
9807330f729Sjoerg         return Child(*MemberOrErr);
9817330f729Sjoerg       else
9827330f729Sjoerg         return MemberOrErr.takeError();
9837330f729Sjoerg     }
9847330f729Sjoerg   }
9857330f729Sjoerg   return Optional<Child>();
9867330f729Sjoerg }
9877330f729Sjoerg 
9887330f729Sjoerg // Returns true if archive file contains no member file.
isEmpty() const9897330f729Sjoerg bool Archive::isEmpty() const { return Data.getBufferSize() == 8; }
9907330f729Sjoerg 
hasSymbolTable() const9917330f729Sjoerg bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }
992