brintos

brintos / llvm-project-archived public Read only

0
0
Text · 49.6 KiB · 8e4a5ea Raw
1454 lines · cpp
1//===- Archive.cpp - ar File Format implementation ------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines the ArchiveObjectFile class.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/Object/Archive.h"14#include "llvm/ADT/SmallString.h"15#include "llvm/ADT/StringRef.h"16#include "llvm/ADT/Twine.h"17#include "llvm/Object/Binary.h"18#include "llvm/Object/Error.h"19#include "llvm/Support/Chrono.h"20#include "llvm/Support/Endian.h"21#include "llvm/Support/EndianStream.h"22#include "llvm/Support/Error.h"23#include "llvm/Support/ErrorOr.h"24#include "llvm/Support/FileSystem.h"25#include "llvm/Support/MathExtras.h"26#include "llvm/Support/MemoryBuffer.h"27#include "llvm/Support/Path.h"28#include "llvm/Support/raw_ostream.h"29#include "llvm/TargetParser/Host.h"30#include <cassert>31#include <cstddef>32#include <cstdint>33#include <memory>34#include <string>35#include <system_error>36 37using namespace llvm;38using namespace object;39using namespace llvm::support::endian;40 41void Archive::anchor() {}42 43static Error malformedError(Twine Msg) {44  std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")";45  return make_error<GenericBinaryError>(std::move(StringMsg),46                                        object_error::parse_failed);47}48 49static Error50createMemberHeaderParseError(const AbstractArchiveMemberHeader *ArMemHeader,51                             const char *RawHeaderPtr, uint64_t Size) {52  StringRef Msg("remaining size of archive too small for next archive "53                "member header ");54 55  Expected<StringRef> NameOrErr = ArMemHeader->getName(Size);56  if (NameOrErr)57    return malformedError(Msg + "for " + *NameOrErr);58 59  consumeError(NameOrErr.takeError());60  uint64_t Offset = RawHeaderPtr - ArMemHeader->Parent->getData().data();61  return malformedError(Msg + "at offset " + Twine(Offset));62}63 64template <class T, std::size_t N>65StringRef getFieldRawString(const T (&Field)[N]) {66  return StringRef(Field, N).rtrim(" ");67}68 69template <class T>70StringRef CommonArchiveMemberHeader<T>::getRawAccessMode() const {71  return getFieldRawString(ArMemHdr->AccessMode);72}73 74template <class T>75StringRef CommonArchiveMemberHeader<T>::getRawLastModified() const {76  return getFieldRawString(ArMemHdr->LastModified);77}78 79template <class T> StringRef CommonArchiveMemberHeader<T>::getRawUID() const {80  return getFieldRawString(ArMemHdr->UID);81}82 83template <class T> StringRef CommonArchiveMemberHeader<T>::getRawGID() const {84  return getFieldRawString(ArMemHdr->GID);85}86 87template <class T> uint64_t CommonArchiveMemberHeader<T>::getOffset() const {88  return reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();89}90 91template class object::CommonArchiveMemberHeader<UnixArMemHdrType>;92template class object::CommonArchiveMemberHeader<BigArMemHdrType>;93 94ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent,95                                         const char *RawHeaderPtr,96                                         uint64_t Size, Error *Err)97    : CommonArchiveMemberHeader<UnixArMemHdrType>(98          Parent, reinterpret_cast<const UnixArMemHdrType *>(RawHeaderPtr)) {99  if (RawHeaderPtr == nullptr)100    return;101  ErrorAsOutParameter ErrAsOutParam(Err);102 103  if (Size < getSizeOf()) {104    *Err = createMemberHeaderParseError(this, RawHeaderPtr, Size);105    return;106  }107  if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') {108    if (Err) {109      std::string Buf;110      raw_string_ostream OS(Buf);111      OS.write_escaped(112          StringRef(ArMemHdr->Terminator, sizeof(ArMemHdr->Terminator)));113      OS.flush();114      std::string Msg("terminator characters in archive member \"" + Buf +115                      "\" not the correct \"`\\n\" values for the archive "116                      "member header ");117      Expected<StringRef> NameOrErr = getName(Size);118      if (!NameOrErr) {119        consumeError(NameOrErr.takeError());120        uint64_t Offset = RawHeaderPtr - Parent->getData().data();121        *Err = malformedError(Msg + "at offset " + Twine(Offset));122      } else123        *Err = malformedError(Msg + "for " + NameOrErr.get());124    }125    return;126  }127}128 129BigArchiveMemberHeader::BigArchiveMemberHeader(const Archive *Parent,130                                               const char *RawHeaderPtr,131                                               uint64_t Size, Error *Err)132    : CommonArchiveMemberHeader<BigArMemHdrType>(133          Parent, reinterpret_cast<const BigArMemHdrType *>(RawHeaderPtr)) {134  if (RawHeaderPtr == nullptr)135    return;136  ErrorAsOutParameter ErrAsOutParam(Err);137 138  if (RawHeaderPtr + getSizeOf() >= Parent->getData().end()) {139    if (Err)140      *Err = malformedError("malformed AIX big archive: remaining buffer is "141                            "unable to contain next archive member");142    return;143  }144 145  if (Size < getSizeOf()) {146    Error SubErr = createMemberHeaderParseError(this, RawHeaderPtr, Size);147    if (Err)148      *Err = std::move(SubErr);149  }150}151 152// This gets the raw name from the ArMemHdr->Name field and checks that it is153// valid for the kind of archive.  If it is not valid it returns an Error.154Expected<StringRef> ArchiveMemberHeader::getRawName() const {155  char EndCond;156  auto Kind = Parent->kind();157  if (Kind == Archive::K_BSD || Kind == Archive::K_DARWIN64) {158    if (ArMemHdr->Name[0] == ' ') {159      uint64_t Offset =160          reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();161      return malformedError("name contains a leading space for archive member "162                            "header at offset " +163                            Twine(Offset));164    }165    EndCond = ' ';166  } else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#')167    EndCond = ' ';168  else169    EndCond = '/';170  StringRef::size_type end =171      StringRef(ArMemHdr->Name, sizeof(ArMemHdr->Name)).find(EndCond);172  if (end == StringRef::npos)173    end = sizeof(ArMemHdr->Name);174  assert(end <= sizeof(ArMemHdr->Name) && end > 0);175  // Don't include the EndCond if there is one.176  return StringRef(ArMemHdr->Name, end);177}178 179Expected<uint64_t>180getArchiveMemberDecField(Twine FieldName, const StringRef RawField,181                         const Archive *Parent,182                         const AbstractArchiveMemberHeader *MemHeader) {183  uint64_t Value;184  if (RawField.getAsInteger(10, Value)) {185    uint64_t Offset = MemHeader->getOffset();186    return malformedError("characters in " + FieldName +187                          " field in archive member header are not "188                          "all decimal numbers: '" +189                          RawField +190                          "' for the archive "191                          "member header at offset " +192                          Twine(Offset));193  }194  return Value;195}196 197Expected<uint64_t>198getArchiveMemberOctField(Twine FieldName, const StringRef RawField,199                         const Archive *Parent,200                         const AbstractArchiveMemberHeader *MemHeader) {201  uint64_t Value;202  if (RawField.getAsInteger(8, Value)) {203    uint64_t Offset = MemHeader->getOffset();204    return malformedError("characters in " + FieldName +205                          " field in archive member header are not "206                          "all octal numbers: '" +207                          RawField +208                          "' for the archive "209                          "member header at offset " +210                          Twine(Offset));211  }212  return Value;213}214 215Expected<StringRef> BigArchiveMemberHeader::getRawName() const {216  Expected<uint64_t> NameLenOrErr = getArchiveMemberDecField(217      "NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);218  if (!NameLenOrErr)219    // TODO: Out-of-line.220    return NameLenOrErr.takeError();221  uint64_t NameLen = NameLenOrErr.get();222 223  // If the name length is odd, pad with '\0' to get an even length. After224  // padding, there is the name terminator "`\n".225  uint64_t NameLenWithPadding = alignTo(NameLen, 2);226  StringRef NameTerminator = "`\n";227  StringRef NameStringWithNameTerminator =228      StringRef(ArMemHdr->Name, NameLenWithPadding + NameTerminator.size());229  if (!NameStringWithNameTerminator.ends_with(NameTerminator)) {230    uint64_t Offset =231        reinterpret_cast<const char *>(ArMemHdr->Name + NameLenWithPadding) -232        Parent->getData().data();233    // TODO: Out-of-line.234    return malformedError(235        "name does not have name terminator \"`\\n\" for archive member"236        "header at offset " +237        Twine(Offset));238  }239  return StringRef(ArMemHdr->Name, NameLen);240}241 242// member including the header, so the size of any name following the header243// is checked to make sure it does not overflow.244Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {245 246  // This can be called from the ArchiveMemberHeader constructor when the247  // archive header is truncated to produce an error message with the name.248  // Make sure the name field is not truncated.249  if (Size < offsetof(UnixArMemHdrType, Name) + sizeof(ArMemHdr->Name)) {250    uint64_t ArchiveOffset =251        reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();252    return malformedError("archive header truncated before the name field "253                          "for archive member header at offset " +254                          Twine(ArchiveOffset));255  }256 257  // The raw name itself can be invalid.258  Expected<StringRef> NameOrErr = getRawName();259  if (!NameOrErr)260    return NameOrErr.takeError();261  StringRef Name = NameOrErr.get();262 263  // Check if it's a special name.264  if (Name[0] == '/') {265    if (Name.size() == 1) // Linker member.266      return Name;267    if (Name.size() == 2 && Name[1] == '/') // String table.268      return Name;269    // System libraries from the Windows SDK for Windows 11 contain this symbol.270    // It looks like a CFG guard: we just skip it for now.271    if (Name == "/<XFGHASHMAP>/")272      return Name;273    // Some libraries (e.g., arm64rt.lib) from the Windows WDK274    // (version 10.0.22000.0) contain this undocumented special member.275    if (Name == "/<ECSYMBOLS>/")276      return Name;277    // It's a long name.278    // Get the string table offset.279    std::size_t StringOffset;280    if (Name.substr(1).rtrim(' ').getAsInteger(10, StringOffset)) {281      std::string Buf;282      raw_string_ostream OS(Buf);283      OS.write_escaped(Name.substr(1).rtrim(' '));284      OS.flush();285      uint64_t ArchiveOffset =286          reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();287      return malformedError("long name offset characters after the '/' are "288                            "not all decimal numbers: '" +289                            Buf + "' for archive member header at offset " +290                            Twine(ArchiveOffset));291    }292 293    // Verify it.294    if (StringOffset >= Parent->getStringTable().size()) {295      uint64_t ArchiveOffset =296          reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();297      return malformedError("long name offset " + Twine(StringOffset) +298                            " past the end of the string table for archive "299                            "member header at offset " +300                            Twine(ArchiveOffset));301    }302 303    // GNU long file names end with a "/\n".304    if (Parent->kind() == Archive::K_GNU ||305        Parent->kind() == Archive::K_GNU64) {306      size_t End = Parent->getStringTable().find('\n', /*From=*/StringOffset);307      if (End == StringRef::npos || End < 1 ||308          Parent->getStringTable()[End - 1] != '/') {309        return malformedError("string table at long name offset " +310                              Twine(StringOffset) + " not terminated");311      }312      return Parent->getStringTable().slice(StringOffset, End - 1);313    }314    return Parent->getStringTable().begin() + StringOffset;315  }316 317  if (Name.starts_with("#1/")) {318    uint64_t NameLength;319    if (Name.substr(3).rtrim(' ').getAsInteger(10, NameLength)) {320      std::string Buf;321      raw_string_ostream OS(Buf);322      OS.write_escaped(Name.substr(3).rtrim(' '));323      OS.flush();324      uint64_t ArchiveOffset =325          reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();326      return malformedError("long name length characters after the #1/ are "327                            "not all decimal numbers: '" +328                            Buf + "' for archive member header at offset " +329                            Twine(ArchiveOffset));330    }331    if (getSizeOf() + NameLength > Size) {332      uint64_t ArchiveOffset =333          reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();334      return malformedError("long name length: " + Twine(NameLength) +335                            " extends past the end of the member or archive "336                            "for archive member header at offset " +337                            Twine(ArchiveOffset));338    }339    return StringRef(reinterpret_cast<const char *>(ArMemHdr) + getSizeOf(),340                     NameLength)341        .rtrim('\0');342  }343 344  // It is not a long name so trim the blanks at the end of the name.345  if (Name[Name.size() - 1] != '/')346    return Name.rtrim(' ');347 348  // It's a simple name.349  return Name.drop_back(1);350}351 352Expected<StringRef> BigArchiveMemberHeader::getName(uint64_t Size) const {353  return getRawName();354}355 356Expected<uint64_t> ArchiveMemberHeader::getSize() const {357  return getArchiveMemberDecField("size", getFieldRawString(ArMemHdr->Size),358                                  Parent, this);359}360 361Expected<uint64_t> BigArchiveMemberHeader::getSize() const {362  Expected<uint64_t> SizeOrErr = getArchiveMemberDecField(363      "size", getFieldRawString(ArMemHdr->Size), Parent, this);364  if (!SizeOrErr)365    return SizeOrErr.takeError();366 367  Expected<uint64_t> NameLenOrErr = getRawNameSize();368  if (!NameLenOrErr)369    return NameLenOrErr.takeError();370 371  return *SizeOrErr + alignTo(*NameLenOrErr, 2);372}373 374Expected<uint64_t> BigArchiveMemberHeader::getRawNameSize() const {375  return getArchiveMemberDecField(376      "NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);377}378 379Expected<uint64_t> BigArchiveMemberHeader::getNextOffset() const {380  return getArchiveMemberDecField(381      "NextOffset", getFieldRawString(ArMemHdr->NextOffset), Parent, this);382}383 384Expected<sys::fs::perms> AbstractArchiveMemberHeader::getAccessMode() const {385  Expected<uint64_t> AccessModeOrErr =386      getArchiveMemberOctField("AccessMode", getRawAccessMode(), Parent, this);387  if (!AccessModeOrErr)388    return AccessModeOrErr.takeError();389  return static_cast<sys::fs::perms>(*AccessModeOrErr);390}391 392Expected<sys::TimePoint<std::chrono::seconds>>393AbstractArchiveMemberHeader::getLastModified() const {394  Expected<uint64_t> SecondsOrErr = getArchiveMemberDecField(395      "LastModified", getRawLastModified(), Parent, this);396 397  if (!SecondsOrErr)398    return SecondsOrErr.takeError();399 400  return sys::toTimePoint(*SecondsOrErr);401}402 403Expected<unsigned> AbstractArchiveMemberHeader::getUID() const {404  StringRef User = getRawUID();405  if (User.empty())406    return 0;407  return getArchiveMemberDecField("UID", User, Parent, this);408}409 410Expected<unsigned> AbstractArchiveMemberHeader::getGID() const {411  StringRef Group = getRawGID();412  if (Group.empty())413    return 0;414  return getArchiveMemberDecField("GID", Group, Parent, this);415}416 417Expected<bool> ArchiveMemberHeader::isThin() const {418  Expected<StringRef> NameOrErr = getRawName();419  if (!NameOrErr)420    return NameOrErr.takeError();421  StringRef Name = NameOrErr.get();422  return Parent->isThin() && Name != "/" && Name != "//" && Name != "/SYM64/";423}424 425Expected<const char *> ArchiveMemberHeader::getNextChildLoc() const {426  uint64_t Size = getSizeOf();427  Expected<bool> isThinOrErr = isThin();428  if (!isThinOrErr)429    return isThinOrErr.takeError();430 431  bool isThin = isThinOrErr.get();432  if (!isThin) {433    Expected<uint64_t> MemberSize = getSize();434    if (!MemberSize)435      return MemberSize.takeError();436 437    Size += MemberSize.get();438  }439 440  // If Size is odd, add 1 to make it even.441  const char *NextLoc =442      reinterpret_cast<const char *>(ArMemHdr) + alignTo(Size, 2);443 444  if (NextLoc == Parent->getMemoryBufferRef().getBufferEnd())445    return nullptr;446 447  return NextLoc;448}449 450Expected<const char *> BigArchiveMemberHeader::getNextChildLoc() const {451  if (getOffset() ==452      static_cast<const BigArchive *>(Parent)->getLastChildOffset())453    return nullptr;454 455  Expected<uint64_t> NextOffsetOrErr = getNextOffset();456  if (!NextOffsetOrErr)457    return NextOffsetOrErr.takeError();458  return Parent->getData().data() + NextOffsetOrErr.get();459}460 461Archive::Child::Child(const Archive *Parent, StringRef Data,462                      uint16_t StartOfFile)463    : Parent(Parent), Data(Data), StartOfFile(StartOfFile) {464  Header = Parent->createArchiveMemberHeader(Data.data(), Data.size(), nullptr);465}466 467Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)468    : Parent(Parent) {469  if (!Start) {470    Header = nullptr;471    StartOfFile = -1;472    return;473  }474 475  Header = Parent->createArchiveMemberHeader(476      Start, Parent->getData().size() - (Start - Parent->getData().data()),477      Err);478 479  // If we are pointed to real data, Start is not a nullptr, then there must be480  // a non-null Err pointer available to report malformed data on.  Only in481  // the case sentinel value is being constructed is Err is permitted to be a482  // nullptr.483  assert(Err && "Err can't be nullptr if Start is not a nullptr");484 485  ErrorAsOutParameter ErrAsOutParam(Err);486 487  // If there was an error in the construction of the Header488  // then just return with the error now set.489  if (*Err)490    return;491 492  uint64_t Size = Header->getSizeOf();493  Data = StringRef(Start, Size);494  Expected<bool> isThinOrErr = isThinMember();495  if (!isThinOrErr) {496    *Err = isThinOrErr.takeError();497    return;498  }499  bool isThin = isThinOrErr.get();500  if (!isThin) {501    Expected<uint64_t> MemberSize = getRawSize();502    if (!MemberSize) {503      *Err = MemberSize.takeError();504      return;505    }506    Size += MemberSize.get();507    Data = StringRef(Start, Size);508  }509 510  // Setup StartOfFile and PaddingBytes.511  StartOfFile = Header->getSizeOf();512  // Don't include attached name.513  Expected<StringRef> NameOrErr = getRawName();514  if (!NameOrErr) {515    *Err = NameOrErr.takeError();516    return;517  }518  StringRef Name = NameOrErr.get();519 520  if (Parent->kind() == Archive::K_AIXBIG) {521    // The actual start of the file is after the name and any necessary522    // even-alignment padding.523    StartOfFile += ((Name.size() + 1) >> 1) << 1;524  } else if (Name.starts_with("#1/")) {525    uint64_t NameSize;526    StringRef RawNameSize = Name.substr(3).rtrim(' ');527    if (RawNameSize.getAsInteger(10, NameSize)) {528      uint64_t Offset = Start - Parent->getData().data();529      *Err = malformedError("long name length characters after the #1/ are "530                            "not all decimal numbers: '" +531                            RawNameSize +532                            "' for archive member header at offset " +533                            Twine(Offset));534      return;535    }536    StartOfFile += NameSize;537  }538}539 540Expected<uint64_t> Archive::Child::getSize() const {541  if (Parent->IsThin)542    return Header->getSize();543  return Data.size() - StartOfFile;544}545 546Expected<uint64_t> Archive::Child::getRawSize() const {547  return Header->getSize();548}549 550Expected<bool> Archive::Child::isThinMember() const { return Header->isThin(); }551 552Expected<std::string> Archive::Child::getFullName() const {553  Expected<bool> isThin = isThinMember();554  if (!isThin)555    return isThin.takeError();556  assert(isThin.get());557  Expected<StringRef> NameOrErr = getName();558  if (!NameOrErr)559    return NameOrErr.takeError();560  StringRef Name = *NameOrErr;561  if (sys::path::is_absolute(Name))562    return std::string(Name);563 564  SmallString<128> FullName = sys::path::parent_path(565      Parent->getMemoryBufferRef().getBufferIdentifier());566  sys::path::append(FullName, Name);567  return std::string(FullName);568}569 570Expected<StringRef> Archive::Child::getBuffer() const {571  Expected<bool> isThinOrErr = isThinMember();572  if (!isThinOrErr)573    return isThinOrErr.takeError();574  bool isThin = isThinOrErr.get();575  if (!isThin) {576    Expected<uint64_t> Size = getSize();577    if (!Size)578      return Size.takeError();579    return StringRef(Data.data() + StartOfFile, Size.get());580  }581  Expected<std::string> FullNameOrErr = getFullName();582  if (!FullNameOrErr)583    return FullNameOrErr.takeError();584  const std::string &FullName = *FullNameOrErr;585  ErrorOr<std::unique_ptr<MemoryBuffer>> Buf =586      MemoryBuffer::getFile(FullName, false, /*RequiresNullTerminator=*/false);587  if (std::error_code EC = Buf.getError())588    return errorCodeToError(EC);589  Parent->ThinBuffers.push_back(std::move(*Buf));590  return Parent->ThinBuffers.back()->getBuffer();591}592 593Expected<Archive::Child> Archive::Child::getNext() const {594  Expected<const char *> NextLocOrErr = Header->getNextChildLoc();595  if (!NextLocOrErr)596    return NextLocOrErr.takeError();597 598  const char *NextLoc = *NextLocOrErr;599 600  // Check to see if this is at the end of the archive.601  if (NextLoc == nullptr)602    return Child(nullptr, nullptr, nullptr);603 604  // Check to see if this is past the end of the archive.605  if (NextLoc > Parent->Data.getBufferEnd()) {606    std::string Msg("offset to next archive member past the end of the archive "607                    "after member ");608    Expected<StringRef> NameOrErr = getName();609    if (!NameOrErr) {610      consumeError(NameOrErr.takeError());611      uint64_t Offset = Data.data() - Parent->getData().data();612      return malformedError(Msg + "at offset " + Twine(Offset));613    } else614      return malformedError(Msg + NameOrErr.get());615  }616 617  Error Err = Error::success();618  Child Ret(Parent, NextLoc, &Err);619  if (Err)620    return std::move(Err);621  return Ret;622}623 624uint64_t Archive::Child::getChildOffset() const {625  const char *a = Parent->Data.getBuffer().data();626  const char *c = Data.data();627  uint64_t offset = c - a;628  return offset;629}630 631Expected<StringRef> Archive::Child::getName() const {632  Expected<uint64_t> RawSizeOrErr = getRawSize();633  if (!RawSizeOrErr)634    return RawSizeOrErr.takeError();635  uint64_t RawSize = RawSizeOrErr.get();636  Expected<StringRef> NameOrErr =637      Header->getName(Header->getSizeOf() + RawSize);638  if (!NameOrErr)639    return NameOrErr.takeError();640  StringRef Name = NameOrErr.get();641  return Name;642}643 644Expected<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {645  Expected<StringRef> NameOrErr = getName();646  if (!NameOrErr)647    return NameOrErr.takeError();648  StringRef Name = NameOrErr.get();649  Expected<StringRef> Buf = getBuffer();650  if (!Buf)651    return createFileError(Name, Buf.takeError());652  return MemoryBufferRef(*Buf, Name);653}654 655Expected<std::unique_ptr<Binary>>656Archive::Child::getAsBinary(LLVMContext *Context) const {657  Expected<MemoryBufferRef> BuffOrErr = getMemoryBufferRef();658  if (!BuffOrErr)659    return BuffOrErr.takeError();660 661  auto BinaryOrErr = createBinary(BuffOrErr.get(), Context);662  if (BinaryOrErr)663    return std::move(*BinaryOrErr);664  return BinaryOrErr.takeError();665}666 667Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {668  Error Err = Error::success();669  std::unique_ptr<Archive> Ret;670  StringRef Buffer = Source.getBuffer();671 672  if (Buffer.starts_with(BigArchiveMagic))673    Ret = std::make_unique<BigArchive>(Source, Err);674  else675    Ret = std::make_unique<Archive>(Source, Err);676 677  if (Err)678    return std::move(Err);679  return std::move(Ret);680}681 682std::unique_ptr<AbstractArchiveMemberHeader>683Archive::createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size,684                                   Error *Err) const {685  ErrorAsOutParameter ErrAsOutParam(Err);686  if (kind() != K_AIXBIG)687    return std::make_unique<ArchiveMemberHeader>(this, RawHeaderPtr, Size, Err);688  return std::make_unique<BigArchiveMemberHeader>(this, RawHeaderPtr, Size,689                                                  Err);690}691 692uint64_t Archive::getArchiveMagicLen() const {693  if (isThin())694    return sizeof(ThinArchiveMagic) - 1;695 696  if (Kind() == K_AIXBIG)697    return sizeof(BigArchiveMagic) - 1;698 699  return sizeof(ArchiveMagic) - 1;700}701 702void Archive::setFirstRegular(const Child &C) {703  FirstRegularData = C.Data;704  FirstRegularStartOfFile = C.StartOfFile;705}706 707Archive::Archive(MemoryBufferRef Source, Error &Err)708    : Binary(Binary::ID_Archive, Source) {709  ErrorAsOutParameter ErrAsOutParam(Err);710  StringRef Buffer = Data.getBuffer();711  // Check for sufficient magic.712  if (Buffer.starts_with(ThinArchiveMagic)) {713    IsThin = true;714  } else if (Buffer.starts_with(ArchiveMagic)) {715    IsThin = false;716  } else if (Buffer.starts_with(BigArchiveMagic)) {717    Format = K_AIXBIG;718    IsThin = false;719    return;720  } else {721    Err = make_error<GenericBinaryError>("file too small to be an archive",722                                         object_error::invalid_file_type);723    return;724  }725 726  // Make sure Format is initialized before any call to727  // ArchiveMemberHeader::getName() is made.  This could be a valid empty728  // archive which is the same in all formats.  So claiming it to be gnu to is729  // fine if not totally correct before we look for a string table or table of730  // contents.731  Format = K_GNU;732 733  // Get the special members.734  child_iterator I = child_begin(Err, false);735  if (Err)736    return;737  child_iterator E = child_end();738 739  // See if this is a valid empty archive and if so return.740  if (I == E) {741    Err = Error::success();742    return;743  }744  const Child *C = &*I;745 746  auto Increment = [&]() {747    ++I;748    if (Err)749      return true;750    C = &*I;751    return false;752  };753 754  Expected<StringRef> NameOrErr = C->getRawName();755  if (!NameOrErr) {756    Err = NameOrErr.takeError();757    return;758  }759  StringRef Name = NameOrErr.get();760 761  // Below is the pattern that is used to figure out the archive format762  // GNU archive format763  //  First member : / (may exist, if it exists, points to the symbol table )764  //  Second member : // (may exist, if it exists, points to the string table)765  //  Note : The string table is used if the filename exceeds 15 characters766  // BSD archive format767  //  First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table)768  //  There is no string table, if the filename exceeds 15 characters or has a769  //  embedded space, the filename has #1/<size>, The size represents the size770  //  of the filename that needs to be read after the archive header771  // COFF archive format772  //  First member : /773  //  Second member : / (provides a directory of symbols)774  //  Third member : // (may exist, if it exists, contains the string table)775  //  Note: Microsoft PE/COFF Spec 8.3 says that the third member is present776  //  even if the string table is empty. However, lib.exe does not in fact777  //  seem to create the third member if there's no member whose filename778  //  exceeds 15 characters. So the third member is optional.779 780  if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {781    if (Name == "__.SYMDEF")782      Format = K_BSD;783    else // Name == "__.SYMDEF_64"784      Format = K_DARWIN64;785    // We know that the symbol table is not an external file, but we still must786    // check any Expected<> return value.787    Expected<StringRef> BufOrErr = C->getBuffer();788    if (!BufOrErr) {789      Err = BufOrErr.takeError();790      return;791    }792    SymbolTable = BufOrErr.get();793    if (Increment())794      return;795    setFirstRegular(*C);796 797    Err = Error::success();798    return;799  }800 801  if (Name.starts_with("#1/")) {802    Format = K_BSD;803    // We know this is BSD, so getName will work since there is no string table.804    Expected<StringRef> NameOrErr = C->getName();805    if (!NameOrErr) {806      Err = NameOrErr.takeError();807      return;808    }809    Name = NameOrErr.get();810    if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {811      // We know that the symbol table is not an external file, but we still812      // must check any Expected<> return value.813      Expected<StringRef> BufOrErr = C->getBuffer();814      if (!BufOrErr) {815        Err = BufOrErr.takeError();816        return;817      }818      SymbolTable = BufOrErr.get();819      if (Increment())820        return;821    } else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {822      Format = K_DARWIN64;823      // We know that the symbol table is not an external file, but we still824      // must check any Expected<> return value.825      Expected<StringRef> BufOrErr = C->getBuffer();826      if (!BufOrErr) {827        Err = BufOrErr.takeError();828        return;829      }830      SymbolTable = BufOrErr.get();831      if (Increment())832        return;833    }834    setFirstRegular(*C);835    return;836  }837 838  // MIPS 64-bit ELF archives use a special format of a symbol table.839  // This format is marked by `ar_name` field equals to "/SYM64/".840  // For detailed description see page 96 in the following document:841  // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf842 843  bool has64SymTable = false;844  if (Name == "/" || Name == "/SYM64/") {845    // We know that the symbol table is not an external file, but we still846    // must check any Expected<> return value.847    Expected<StringRef> BufOrErr = C->getBuffer();848    if (!BufOrErr) {849      Err = BufOrErr.takeError();850      return;851    }852    SymbolTable = BufOrErr.get();853    if (Name == "/SYM64/")854      has64SymTable = true;855 856    if (Increment())857      return;858    if (I == E) {859      Err = Error::success();860      return;861    }862    Expected<StringRef> NameOrErr = C->getRawName();863    if (!NameOrErr) {864      Err = NameOrErr.takeError();865      return;866    }867    Name = NameOrErr.get();868  }869 870  if (Name == "//") {871    Format = has64SymTable ? K_GNU64 : K_GNU;872    // The string table is never an external member, but we still873    // must check any Expected<> return value.874    Expected<StringRef> BufOrErr = C->getBuffer();875    if (!BufOrErr) {876      Err = BufOrErr.takeError();877      return;878    }879    StringTable = BufOrErr.get();880    if (Increment())881      return;882    setFirstRegular(*C);883    Err = Error::success();884    return;885  }886 887  if (Name[0] != '/') {888    Format = has64SymTable ? K_GNU64 : K_GNU;889    setFirstRegular(*C);890    Err = Error::success();891    return;892  }893 894  if (Name != "/") {895    Err = errorCodeToError(object_error::parse_failed);896    return;897  }898 899  Format = K_COFF;900  // We know that the symbol table is not an external file, but we still901  // must check any Expected<> return value.902  Expected<StringRef> BufOrErr = C->getBuffer();903  if (!BufOrErr) {904    Err = BufOrErr.takeError();905    return;906  }907  SymbolTable = BufOrErr.get();908 909  if (Increment())910    return;911 912  if (I == E) {913    setFirstRegular(*C);914    Err = Error::success();915    return;916  }917 918  NameOrErr = C->getRawName();919  if (!NameOrErr) {920    Err = NameOrErr.takeError();921    return;922  }923  Name = NameOrErr.get();924 925  if (Name == "//") {926    // The string table is never an external member, but we still927    // must check any Expected<> return value.928    Expected<StringRef> BufOrErr = C->getBuffer();929    if (!BufOrErr) {930      Err = BufOrErr.takeError();931      return;932    }933    StringTable = BufOrErr.get();934    if (Increment())935      return;936 937    if (I == E) {938      setFirstRegular(*C);939      Err = Error::success();940      return;941    }942 943    NameOrErr = C->getRawName();944    if (!NameOrErr) {945      Err = NameOrErr.takeError();946      return;947    }948    Name = NameOrErr.get();949  }950 951  if (Name == "/<ECSYMBOLS>/") {952    // ARM64EC-aware libraries contain an additional special member with953    // an EC symbol map after the string table. Its format is similar to a954    // regular symbol map, except it doesn't contain member offsets. Its indexes955    // refer to member offsets from the regular symbol table instead.956    Expected<StringRef> BufOrErr = C->getBuffer();957    if (!BufOrErr) {958      Err = BufOrErr.takeError();959      return;960    }961    ECSymbolTable = BufOrErr.get();962    if (Increment())963      return;964  }965 966  setFirstRegular(*C);967  Err = Error::success();968}969 970object::Archive::Kind Archive::getDefaultKindForTriple(const Triple &T) {971  if (T.isOSDarwin())972    return object::Archive::K_DARWIN;973  if (T.isOSAIX())974    return object::Archive::K_AIXBIG;975  if (T.isOSWindows())976    return object::Archive::K_COFF;977  return object::Archive::K_GNU;978}979 980object::Archive::Kind Archive::getDefaultKind() {981  Triple HostTriple(sys::getDefaultTargetTriple());982  return getDefaultKindForTriple(HostTriple);983}984 985Archive::child_iterator Archive::child_begin(Error &Err,986                                             bool SkipInternal) const {987  if (isEmpty())988    return child_end();989 990  if (SkipInternal)991    return child_iterator::itr(992        Child(this, FirstRegularData, FirstRegularStartOfFile), Err);993 994  const char *Loc = Data.getBufferStart() + getFirstChildOffset();995  Child C(this, Loc, &Err);996  if (Err)997    return child_end();998  return child_iterator::itr(C, Err);999}1000 1001Archive::child_iterator Archive::child_end() const {1002  return child_iterator::end(Child(nullptr, nullptr, nullptr));1003}1004 1005bool Archive::Symbol::isECSymbol() const {1006  // Symbols use SymbolCount..SymbolCount+getNumberOfECSymbols() for EC symbol1007  // indexes.1008  uint32_t SymbolCount = Parent->getNumberOfSymbols();1009  return SymbolCount <= SymbolIndex &&1010         SymbolIndex < SymbolCount + Parent->getNumberOfECSymbols();1011}1012 1013StringRef Archive::Symbol::getName() const {1014  if (isECSymbol())1015    return Parent->ECSymbolTable.begin() + StringIndex;1016  return Parent->getSymbolTable().begin() + StringIndex;1017}1018 1019Expected<Archive::Child> Archive::Symbol::getMember() const {1020  const char *Buf = Parent->getSymbolTable().begin();1021  const char *Offsets = Buf;1022  if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64 ||1023      Parent->kind() == K_AIXBIG)1024    Offsets += sizeof(uint64_t);1025  else1026    Offsets += sizeof(uint32_t);1027  uint64_t Offset = 0;1028  if (Parent->kind() == K_GNU) {1029    Offset = read32be(Offsets + SymbolIndex * 4);1030  } else if (Parent->kind() == K_GNU64 || Parent->kind() == K_AIXBIG) {1031    Offset = read64be(Offsets + SymbolIndex * 8);1032  } else if (Parent->kind() == K_BSD) {1033    // The SymbolIndex is an index into the ranlib structs that start at1034    // Offsets (the first uint32_t is the number of bytes of the ranlib1035    // structs).  The ranlib structs are a pair of uint32_t's the first1036    // being a string table offset and the second being the offset into1037    // the archive of the member that defines the symbol.  Which is what1038    // is needed here.1039    Offset = read32le(Offsets + SymbolIndex * 8 + 4);1040  } else if (Parent->kind() == K_DARWIN64) {1041    // The SymbolIndex is an index into the ranlib_64 structs that start at1042    // Offsets (the first uint64_t is the number of bytes of the ranlib_641043    // structs).  The ranlib_64 structs are a pair of uint64_t's the first1044    // being a string table offset and the second being the offset into1045    // the archive of the member that defines the symbol.  Which is what1046    // is needed here.1047    Offset = read64le(Offsets + SymbolIndex * 16 + 8);1048  } else {1049    // Skip offsets.1050    uint32_t MemberCount = read32le(Buf);1051    Buf += MemberCount * 4 + 4;1052 1053    uint32_t SymbolCount = read32le(Buf);1054    uint16_t OffsetIndex;1055    if (SymbolIndex < SymbolCount) {1056      // Skip SymbolCount to get to the indices table.1057      const char *Indices = Buf + 4;1058 1059      // Get the index of the offset in the file member offset table for this1060      // symbol.1061      OffsetIndex = read16le(Indices + SymbolIndex * 2);1062    } else if (isECSymbol()) {1063      // Skip SymbolCount to get to the indices table.1064      const char *Indices = Parent->ECSymbolTable.begin() + 4;1065 1066      // Get the index of the offset in the file member offset table for this1067      // symbol.1068      OffsetIndex = read16le(Indices + (SymbolIndex - SymbolCount) * 2);1069    } else {1070      return errorCodeToError(object_error::parse_failed);1071    }1072    // Subtract 1 since OffsetIndex is 1 based.1073    --OffsetIndex;1074 1075    if (OffsetIndex >= MemberCount)1076      return errorCodeToError(object_error::parse_failed);1077 1078    Offset = read32le(Offsets + OffsetIndex * 4);1079  }1080 1081  const char *Loc = Parent->getData().begin() + Offset;1082  Error Err = Error::success();1083  Child C(Parent, Loc, &Err);1084  if (Err)1085    return std::move(Err);1086  return C;1087}1088 1089Archive::Symbol Archive::Symbol::getNext() const {1090  Symbol t(*this);1091  if (Parent->kind() == K_BSD) {1092    // t.StringIndex is an offset from the start of the __.SYMDEF or1093    // "__.SYMDEF SORTED" member into the string table for the ranlib1094    // struct indexed by t.SymbolIndex .  To change t.StringIndex to the1095    // offset in the string table for t.SymbolIndex+1 we subtract the1096    // its offset from the start of the string table for t.SymbolIndex1097    // and add the offset of the string table for t.SymbolIndex+1.1098 1099    // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t1100    // which is the number of bytes of ranlib structs that follow.  The ranlib1101    // structs are a pair of uint32_t's the first being a string table offset1102    // and the second being the offset into the archive of the member that1103    // define the symbol. After that the next uint32_t is the byte count of1104    // the string table followed by the string table.1105    const char *Buf = Parent->getSymbolTable().begin();1106    uint32_t RanlibCount = 0;1107    RanlibCount = read32le(Buf) / 8;1108    // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount)1109    // don't change the t.StringIndex as we don't want to reference a ranlib1110    // past RanlibCount.1111    if (t.SymbolIndex + 1 < RanlibCount) {1112      const char *Ranlibs = Buf + 4;1113      uint32_t CurRanStrx = 0;1114      uint32_t NextRanStrx = 0;1115      CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8);1116      NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8);1117      t.StringIndex -= CurRanStrx;1118      t.StringIndex += NextRanStrx;1119    }1120  } else if (t.isECSymbol()) {1121    // Go to one past next null.1122    t.StringIndex = Parent->ECSymbolTable.find('\0', t.StringIndex) + 1;1123  } else {1124    // Go to one past next null.1125    t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1;1126  }1127  ++t.SymbolIndex;1128  return t;1129}1130 1131Archive::symbol_iterator Archive::symbol_begin() const {1132  if (!hasSymbolTable())1133    return symbol_iterator(Symbol(this, 0, 0));1134 1135  const char *buf = getSymbolTable().begin();1136  if (kind() == K_GNU) {1137    uint32_t symbol_count = 0;1138    symbol_count = read32be(buf);1139    buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));1140  } else if (kind() == K_GNU64) {1141    uint64_t symbol_count = read64be(buf);1142    buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));1143  } else if (kind() == K_BSD) {1144    // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t1145    // which is the number of bytes of ranlib structs that follow.  The ranlib1146    // structs are a pair of uint32_t's the first being a string table offset1147    // and the second being the offset into the archive of the member that1148    // define the symbol. After that the next uint32_t is the byte count of1149    // the string table followed by the string table.1150    uint32_t ranlib_count = 0;1151    ranlib_count = read32le(buf) / 8;1152    const char *ranlibs = buf + 4;1153    uint32_t ran_strx = 0;1154    ran_strx = read32le(ranlibs);1155    buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t))));1156    // Skip the byte count of the string table.1157    buf += sizeof(uint32_t);1158    buf += ran_strx;1159  } else if (kind() == K_DARWIN64) {1160    // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t1161    // which is the number of bytes of ranlib_64 structs that follow.  The1162    // ranlib_64 structs are a pair of uint64_t's the first being a string1163    // table offset and the second being the offset into the archive of the1164    // member that define the symbol. After that the next uint64_t is the byte1165    // count of the string table followed by the string table.1166    uint64_t ranlib_count = 0;1167    ranlib_count = read64le(buf) / 16;1168    const char *ranlibs = buf + 8;1169    uint64_t ran_strx = 0;1170    ran_strx = read64le(ranlibs);1171    buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t))));1172    // Skip the byte count of the string table.1173    buf += sizeof(uint64_t);1174    buf += ran_strx;1175  } else if (kind() == K_AIXBIG) {1176    buf = getStringTable().begin();1177  } else {1178    uint32_t member_count = 0;1179    uint32_t symbol_count = 0;1180    member_count = read32le(buf);1181    buf += 4 + (member_count * 4); // Skip offsets.1182    symbol_count = read32le(buf);1183    buf += 4 + (symbol_count * 2); // Skip indices.1184  }1185  uint32_t string_start_offset = buf - getSymbolTable().begin();1186  return symbol_iterator(Symbol(this, 0, string_start_offset));1187}1188 1189Archive::symbol_iterator Archive::symbol_end() const {1190  return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0));1191}1192 1193Expected<iterator_range<Archive::symbol_iterator>> Archive::ec_symbols() const {1194  uint32_t Count = 0;1195 1196  // Validate EC symbol table.1197  if (!ECSymbolTable.empty()) {1198    if (ECSymbolTable.size() < sizeof(uint32_t))1199      return malformedError("invalid EC symbols size (" +1200                            Twine(ECSymbolTable.size()) + ")");1201    if (SymbolTable.size() < sizeof(uint32_t))1202      return malformedError("invalid symbols size (" +1203                            Twine(ECSymbolTable.size()) + ")");1204 1205    Count = read32le(ECSymbolTable.begin());1206    size_t StringIndex = sizeof(uint32_t) + Count * sizeof(uint16_t);1207    if (ECSymbolTable.size() < StringIndex)1208      return malformedError("invalid EC symbols size. Size was " +1209                            Twine(ECSymbolTable.size()) + ", but expected " +1210                            Twine(StringIndex));1211 1212    uint32_t MemberCount = read32le(SymbolTable.begin());1213    const char *Indexes = ECSymbolTable.begin() + sizeof(uint32_t);1214 1215    for (uint32_t i = 0; i < Count; ++i) {1216      uint16_t Index = read16le(Indexes + i * sizeof(uint16_t));1217      if (!Index)1218        return malformedError("invalid EC symbol index 0");1219      if (Index > MemberCount)1220        return malformedError("invalid EC symbol index " + Twine(Index) +1221                              " is larger than member count " +1222                              Twine(MemberCount));1223 1224      StringIndex = ECSymbolTable.find('\0', StringIndex);1225      if (StringIndex == StringRef::npos)1226        return malformedError("malformed EC symbol names: not null-terminated");1227      ++StringIndex;1228    }1229  }1230 1231  uint32_t SymbolCount = getNumberOfSymbols();1232  return make_range(1233      symbol_iterator(Symbol(this, SymbolCount,1234                             sizeof(uint32_t) + Count * sizeof(uint16_t))),1235      symbol_iterator(Symbol(this, SymbolCount + Count, 0)));1236}1237 1238uint32_t Archive::getNumberOfSymbols() const {1239  if (!hasSymbolTable())1240    return 0;1241  const char *buf = getSymbolTable().begin();1242  if (kind() == K_GNU)1243    return read32be(buf);1244  if (kind() == K_GNU64 || kind() == K_AIXBIG)1245    return read64be(buf);1246  if (kind() == K_BSD)1247    return read32le(buf) / 8;1248  if (kind() == K_DARWIN64)1249    return read64le(buf) / 16;1250  uint32_t member_count = 0;1251  member_count = read32le(buf);1252  buf += 4 + (member_count * 4); // Skip offsets.1253  return read32le(buf);1254}1255 1256uint32_t Archive::getNumberOfECSymbols() const {1257  if (ECSymbolTable.size() < sizeof(uint32_t))1258    return 0;1259  return read32le(ECSymbolTable.begin());1260}1261 1262Expected<std::optional<Archive::Child>> Archive::findSym(StringRef name) const {1263  Archive::symbol_iterator bs = symbol_begin();1264  Archive::symbol_iterator es = symbol_end();1265 1266  for (; bs != es; ++bs) {1267    StringRef SymName = bs->getName();1268    if (SymName == name) {1269      if (auto MemberOrErr = bs->getMember())1270        return Child(*MemberOrErr);1271      else1272        return MemberOrErr.takeError();1273    }1274  }1275  return std::nullopt;1276}1277 1278// Returns true if archive file contains no member file.1279bool Archive::isEmpty() const {1280  return Data.getBufferSize() == getArchiveMagicLen();1281}1282 1283bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }1284 1285static Error getGlobalSymtabLocAndSize(const MemoryBufferRef &Data,1286                                       uint64_t GlobalSymtabOffset,1287                                       const char *&GlobalSymtabLoc,1288                                       uint64_t &Size, const char *BitMessage) {1289  uint64_t BufferSize = Data.getBufferSize();1290  uint64_t GlobalSymtabContentOffset =1291      GlobalSymtabOffset + sizeof(BigArMemHdrType);1292  if (GlobalSymtabContentOffset > BufferSize)1293    return malformedError(1294        Twine(BitMessage) + " global symbol table header at offset 0x" +1295        Twine::utohexstr(GlobalSymtabOffset) + " and size 0x" +1296        Twine::utohexstr(sizeof(BigArMemHdrType)) +1297        " goes past the end of file");1298 1299  GlobalSymtabLoc = Data.getBufferStart() + GlobalSymtabOffset;1300  const BigArMemHdrType *GlobalSymHdr =1301      reinterpret_cast<const BigArMemHdrType *>(GlobalSymtabLoc);1302  StringRef RawOffset = getFieldRawString(GlobalSymHdr->Size);1303  if (RawOffset.getAsInteger(10, Size))1304    return malformedError(Twine(BitMessage) + " global symbol table size \"" +1305                          RawOffset + "\" is not a number");1306 1307  if (GlobalSymtabContentOffset + Size > BufferSize)1308    return malformedError(1309        Twine(BitMessage) + " global symbol table content at offset 0x" +1310        Twine::utohexstr(GlobalSymtabContentOffset) + " and size 0x" +1311        Twine::utohexstr(Size) + " goes past the end of file");1312 1313  return Error::success();1314}1315 1316struct GlobalSymtabInfo {1317  uint64_t SymNum;1318  StringRef SymbolTable;1319  StringRef SymbolOffsetTable;1320  StringRef StringTable;1321};1322 1323static void1324appendGlobalSymbolTableInfo(SmallVector<GlobalSymtabInfo> &SymtabInfos,1325                            const char *GlobalSymtabLoc, uint64_t Size) {1326  // In a big archive, a global symbol table contains the following information:1327  // - The number of symbols.1328  // - The array of offsets into the archive file. The length is eight1329  //   times the number of symbols.1330  // - The name-string table. The size is:1331  //   Size-(8*(the number of symbols + 1)).1332 1333  StringRef SymbolTable =1334      StringRef(GlobalSymtabLoc + sizeof(BigArMemHdrType), Size);1335  uint64_t SymNum = read64be(GlobalSymtabLoc + sizeof(BigArMemHdrType));1336  StringRef SymbolOffsetTable = StringRef(SymbolTable.data() + 8, 8 * SymNum);1337  unsigned SymOffsetsSize = 8 * (SymNum + 1);1338  uint64_t SymbolTableStringSize = Size - SymOffsetsSize;1339  StringRef StringTable =1340      StringRef(SymbolTable.data() + SymOffsetsSize, SymbolTableStringSize);1341  SymtabInfos.push_back({SymNum, SymbolTable, SymbolOffsetTable, StringTable});1342}1343 1344BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)1345    : Archive(Source, Err) {1346  ErrorAsOutParameter ErrAsOutParam(&Err);1347  StringRef Buffer = Data.getBuffer();1348  ArFixLenHdr = reinterpret_cast<const FixLenHdr *>(Buffer.data());1349  uint64_t BufferSize = Data.getBufferSize();1350 1351  if (BufferSize < sizeof(FixLenHdr)) {1352    Err = malformedError("malformed AIX big archive: incomplete fixed length "1353                         "header, the archive is only" +1354                         Twine(BufferSize) + " byte(s)");1355    return;1356  }1357 1358  StringRef RawOffset = getFieldRawString(ArFixLenHdr->FirstChildOffset);1359  if (RawOffset.getAsInteger(10, FirstChildOffset))1360    // TODO: Out-of-line.1361    Err = malformedError("malformed AIX big archive: first member offset \"" +1362                         RawOffset + "\" is not a number");1363 1364  RawOffset = getFieldRawString(ArFixLenHdr->LastChildOffset);1365  if (RawOffset.getAsInteger(10, LastChildOffset))1366    // TODO: Out-of-line.1367    Err = malformedError("malformed AIX big archive: last member offset \"" +1368                         RawOffset + "\" is not a number");1369 1370  uint64_t GlobSymtab32Offset = 0;1371  RawOffset = getFieldRawString(ArFixLenHdr->GlobSymOffset);1372  if (RawOffset.getAsInteger(10, GlobSymtab32Offset)) {1373    Err = malformedError("global symbol table "1374                         "offset of 32-bit members \"" +1375                         RawOffset + "\" is not a number");1376    return;1377  }1378 1379  uint64_t GlobSymtab64Offset = 0;1380  RawOffset = getFieldRawString(ArFixLenHdr->GlobSym64Offset);1381  if (RawOffset.getAsInteger(10, GlobSymtab64Offset)) {1382    Err = malformedError("global symbol table "1383                         "offset of 64-bit members\"" +1384                         RawOffset + "\" is not a number");1385    return;1386  }1387 1388  const char *GlobSymtab32Loc = nullptr;1389  const char *GlobSymtab64Loc = nullptr;1390  uint64_t GlobSymtab32Size = 0;1391  uint64_t GlobSymtab64Size = 0;1392  const MemoryBufferRef &MemBuffRef = getMemoryBufferRef();1393 1394  if (GlobSymtab32Offset) {1395    Err =1396        getGlobalSymtabLocAndSize(MemBuffRef, GlobSymtab32Offset,1397                                  GlobSymtab32Loc, GlobSymtab32Size, "32-bit");1398    if (Err)1399      return;1400 1401    Has32BitGlobalSymtab = true;1402  }1403 1404  if (GlobSymtab64Offset) {1405    Err =1406        getGlobalSymtabLocAndSize(MemBuffRef, GlobSymtab64Offset,1407                                  GlobSymtab64Loc, GlobSymtab64Size, "64-bit");1408    if (Err)1409      return;1410 1411    Has64BitGlobalSymtab = true;1412  }1413 1414  SmallVector<GlobalSymtabInfo> SymtabInfos;1415 1416  if (GlobSymtab32Offset)1417    appendGlobalSymbolTableInfo(SymtabInfos, GlobSymtab32Loc, GlobSymtab32Size);1418  if (GlobSymtab64Offset)1419    appendGlobalSymbolTableInfo(SymtabInfos, GlobSymtab64Loc, GlobSymtab64Size);1420 1421  if (SymtabInfos.size() == 1) {1422    SymbolTable = SymtabInfos[0].SymbolTable;1423    StringTable = SymtabInfos[0].StringTable;1424  } else if (SymtabInfos.size() == 2) {1425    // In order to let the Archive::Symbol::getNext() work for both 32-bit and1426    // 64-bit global symbol tables, we need to merge them into a single table.1427    raw_string_ostream Out(MergedGlobalSymtabBuf);1428    uint64_t SymNum = SymtabInfos[0].SymNum + SymtabInfos[1].SymNum;1429    write(Out, SymNum, llvm::endianness::big);1430    // Merge symbol offset.1431    Out << SymtabInfos[0].SymbolOffsetTable;1432    Out << SymtabInfos[1].SymbolOffsetTable;1433    // Merge string table.1434    Out << SymtabInfos[0].StringTable;1435    Out << SymtabInfos[1].StringTable;1436    SymbolTable = MergedGlobalSymtabBuf;1437    // The size of the symbol offset to the member file is 8 bytes.1438    StringTable = StringRef(SymbolTable.begin() + (SymNum + 1) * 8,1439                            SymtabInfos[0].StringTable.size() +1440                                SymtabInfos[1].StringTable.size());1441  }1442 1443  child_iterator I = child_begin(Err, false);1444  if (Err)1445    return;1446  child_iterator E = child_end();1447  if (I == E) {1448    Err = Error::success();1449    return;1450  }1451  setFirstRegular(*I);1452  Err = Error::success();1453}1454