Path: blob/main/contrib/llvm-project/llvm/lib/Object/Archive.cpp
35232 views
//===- Archive.cpp - ar File Format implementation ------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the ArchiveObjectFile class.9//10//===----------------------------------------------------------------------===//1112#include "llvm/Object/Archive.h"13#include "llvm/ADT/SmallString.h"14#include "llvm/ADT/StringRef.h"15#include "llvm/ADT/Twine.h"16#include "llvm/Object/Binary.h"17#include "llvm/Object/Error.h"18#include "llvm/Support/Chrono.h"19#include "llvm/Support/Endian.h"20#include "llvm/Support/EndianStream.h"21#include "llvm/Support/Error.h"22#include "llvm/Support/ErrorOr.h"23#include "llvm/Support/FileSystem.h"24#include "llvm/Support/MathExtras.h"25#include "llvm/Support/MemoryBuffer.h"26#include "llvm/Support/Path.h"27#include "llvm/Support/raw_ostream.h"28#include "llvm/TargetParser/Host.h"29#include <algorithm>30#include <cassert>31#include <cstddef>32#include <cstdint>33#include <memory>34#include <string>35#include <system_error>3637using namespace llvm;38using namespace object;39using namespace llvm::support::endian;4041void Archive::anchor() {}4243static Error malformedError(Twine Msg) {44std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")";45return make_error<GenericBinaryError>(std::move(StringMsg),46object_error::parse_failed);47}4849static Error50createMemberHeaderParseError(const AbstractArchiveMemberHeader *ArMemHeader,51const char *RawHeaderPtr, uint64_t Size) {52StringRef Msg("remaining size of archive too small for next archive "53"member header ");5455Expected<StringRef> NameOrErr = ArMemHeader->getName(Size);56if (NameOrErr)57return malformedError(Msg + "for " + *NameOrErr);5859consumeError(NameOrErr.takeError());60uint64_t Offset = RawHeaderPtr - ArMemHeader->Parent->getData().data();61return malformedError(Msg + "at offset " + Twine(Offset));62}6364template <class T, std::size_t N>65StringRef getFieldRawString(const T (&Field)[N]) {66return StringRef(Field, N).rtrim(" ");67}6869template <class T>70StringRef CommonArchiveMemberHeader<T>::getRawAccessMode() const {71return getFieldRawString(ArMemHdr->AccessMode);72}7374template <class T>75StringRef CommonArchiveMemberHeader<T>::getRawLastModified() const {76return getFieldRawString(ArMemHdr->LastModified);77}7879template <class T> StringRef CommonArchiveMemberHeader<T>::getRawUID() const {80return getFieldRawString(ArMemHdr->UID);81}8283template <class T> StringRef CommonArchiveMemberHeader<T>::getRawGID() const {84return getFieldRawString(ArMemHdr->GID);85}8687template <class T> uint64_t CommonArchiveMemberHeader<T>::getOffset() const {88return reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();89}9091template class object::CommonArchiveMemberHeader<UnixArMemHdrType>;92template class object::CommonArchiveMemberHeader<BigArMemHdrType>;9394ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent,95const char *RawHeaderPtr,96uint64_t Size, Error *Err)97: CommonArchiveMemberHeader<UnixArMemHdrType>(98Parent, reinterpret_cast<const UnixArMemHdrType *>(RawHeaderPtr)) {99if (RawHeaderPtr == nullptr)100return;101ErrorAsOutParameter ErrAsOutParam(Err);102103if (Size < getSizeOf()) {104*Err = createMemberHeaderParseError(this, RawHeaderPtr, Size);105return;106}107if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') {108if (Err) {109std::string Buf;110raw_string_ostream OS(Buf);111OS.write_escaped(112StringRef(ArMemHdr->Terminator, sizeof(ArMemHdr->Terminator)));113OS.flush();114std::string Msg("terminator characters in archive member \"" + Buf +115"\" not the correct \"`\\n\" values for the archive "116"member header ");117Expected<StringRef> NameOrErr = getName(Size);118if (!NameOrErr) {119consumeError(NameOrErr.takeError());120uint64_t Offset = RawHeaderPtr - Parent->getData().data();121*Err = malformedError(Msg + "at offset " + Twine(Offset));122} else123*Err = malformedError(Msg + "for " + NameOrErr.get());124}125return;126}127}128129BigArchiveMemberHeader::BigArchiveMemberHeader(const Archive *Parent,130const char *RawHeaderPtr,131uint64_t Size, Error *Err)132: CommonArchiveMemberHeader<BigArMemHdrType>(133Parent, reinterpret_cast<const BigArMemHdrType *>(RawHeaderPtr)) {134if (RawHeaderPtr == nullptr)135return;136ErrorAsOutParameter ErrAsOutParam(Err);137138if (RawHeaderPtr + getSizeOf() >= Parent->getData().end()) {139if (Err)140*Err = malformedError("malformed AIX big archive: remaining buffer is "141"unable to contain next archive member");142return;143}144145if (Size < getSizeOf()) {146Error SubErr = createMemberHeaderParseError(this, RawHeaderPtr, Size);147if (Err)148*Err = std::move(SubErr);149}150}151152// 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 {155char EndCond;156auto Kind = Parent->kind();157if (Kind == Archive::K_BSD || Kind == Archive::K_DARWIN64) {158if (ArMemHdr->Name[0] == ' ') {159uint64_t Offset =160reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();161return malformedError("name contains a leading space for archive member "162"header at offset " +163Twine(Offset));164}165EndCond = ' ';166} else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#')167EndCond = ' ';168else169EndCond = '/';170StringRef::size_type end =171StringRef(ArMemHdr->Name, sizeof(ArMemHdr->Name)).find(EndCond);172if (end == StringRef::npos)173end = sizeof(ArMemHdr->Name);174assert(end <= sizeof(ArMemHdr->Name) && end > 0);175// Don't include the EndCond if there is one.176return StringRef(ArMemHdr->Name, end);177}178179Expected<uint64_t>180getArchiveMemberDecField(Twine FieldName, const StringRef RawField,181const Archive *Parent,182const AbstractArchiveMemberHeader *MemHeader) {183uint64_t Value;184if (RawField.getAsInteger(10, Value)) {185uint64_t Offset = MemHeader->getOffset();186return malformedError("characters in " + FieldName +187" field in archive member header are not "188"all decimal numbers: '" +189RawField +190"' for the archive "191"member header at offset " +192Twine(Offset));193}194return Value;195}196197Expected<uint64_t>198getArchiveMemberOctField(Twine FieldName, const StringRef RawField,199const Archive *Parent,200const AbstractArchiveMemberHeader *MemHeader) {201uint64_t Value;202if (RawField.getAsInteger(8, Value)) {203uint64_t Offset = MemHeader->getOffset();204return malformedError("characters in " + FieldName +205" field in archive member header are not "206"all octal numbers: '" +207RawField +208"' for the archive "209"member header at offset " +210Twine(Offset));211}212return Value;213}214215Expected<StringRef> BigArchiveMemberHeader::getRawName() const {216Expected<uint64_t> NameLenOrErr = getArchiveMemberDecField(217"NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);218if (!NameLenOrErr)219// TODO: Out-of-line.220return NameLenOrErr.takeError();221uint64_t NameLen = NameLenOrErr.get();222223// If the name length is odd, pad with '\0' to get an even length. After224// padding, there is the name terminator "`\n".225uint64_t NameLenWithPadding = alignTo(NameLen, 2);226StringRef NameTerminator = "`\n";227StringRef NameStringWithNameTerminator =228StringRef(ArMemHdr->Name, NameLenWithPadding + NameTerminator.size());229if (!NameStringWithNameTerminator.ends_with(NameTerminator)) {230uint64_t Offset =231reinterpret_cast<const char *>(ArMemHdr->Name + NameLenWithPadding) -232Parent->getData().data();233// TODO: Out-of-line.234return malformedError(235"name does not have name terminator \"`\\n\" for archive member"236"header at offset " +237Twine(Offset));238}239return StringRef(ArMemHdr->Name, NameLen);240}241242// 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 {245246// 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.249if (Size < offsetof(UnixArMemHdrType, Name) + sizeof(ArMemHdr->Name)) {250uint64_t ArchiveOffset =251reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();252return malformedError("archive header truncated before the name field "253"for archive member header at offset " +254Twine(ArchiveOffset));255}256257// The raw name itself can be invalid.258Expected<StringRef> NameOrErr = getRawName();259if (!NameOrErr)260return NameOrErr.takeError();261StringRef Name = NameOrErr.get();262263// Check if it's a special name.264if (Name[0] == '/') {265if (Name.size() == 1) // Linker member.266return Name;267if (Name.size() == 2 && Name[1] == '/') // String table.268return 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.271if (Name == "/<XFGHASHMAP>/")272return Name;273// Some libraries (e.g., arm64rt.lib) from the Windows WDK274// (version 10.0.22000.0) contain this undocumented special member.275if (Name == "/<ECSYMBOLS>/")276return Name;277// It's a long name.278// Get the string table offset.279std::size_t StringOffset;280if (Name.substr(1).rtrim(' ').getAsInteger(10, StringOffset)) {281std::string Buf;282raw_string_ostream OS(Buf);283OS.write_escaped(Name.substr(1).rtrim(' '));284OS.flush();285uint64_t ArchiveOffset =286reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();287return malformedError("long name offset characters after the '/' are "288"not all decimal numbers: '" +289Buf + "' for archive member header at offset " +290Twine(ArchiveOffset));291}292293// Verify it.294if (StringOffset >= Parent->getStringTable().size()) {295uint64_t ArchiveOffset =296reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();297return malformedError("long name offset " + Twine(StringOffset) +298" past the end of the string table for archive "299"member header at offset " +300Twine(ArchiveOffset));301}302303// GNU long file names end with a "/\n".304if (Parent->kind() == Archive::K_GNU ||305Parent->kind() == Archive::K_GNU64) {306size_t End = Parent->getStringTable().find('\n', /*From=*/StringOffset);307if (End == StringRef::npos || End < 1 ||308Parent->getStringTable()[End - 1] != '/') {309return malformedError("string table at long name offset " +310Twine(StringOffset) + "not terminated");311}312return Parent->getStringTable().slice(StringOffset, End - 1);313}314return Parent->getStringTable().begin() + StringOffset;315}316317if (Name.starts_with("#1/")) {318uint64_t NameLength;319if (Name.substr(3).rtrim(' ').getAsInteger(10, NameLength)) {320std::string Buf;321raw_string_ostream OS(Buf);322OS.write_escaped(Name.substr(3).rtrim(' '));323OS.flush();324uint64_t ArchiveOffset =325reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();326return malformedError("long name length characters after the #1/ are "327"not all decimal numbers: '" +328Buf + "' for archive member header at offset " +329Twine(ArchiveOffset));330}331if (getSizeOf() + NameLength > Size) {332uint64_t ArchiveOffset =333reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();334return malformedError("long name length: " + Twine(NameLength) +335" extends past the end of the member or archive "336"for archive member header at offset " +337Twine(ArchiveOffset));338}339return StringRef(reinterpret_cast<const char *>(ArMemHdr) + getSizeOf(),340NameLength)341.rtrim('\0');342}343344// It is not a long name so trim the blanks at the end of the name.345if (Name[Name.size() - 1] != '/')346return Name.rtrim(' ');347348// It's a simple name.349return Name.drop_back(1);350}351352Expected<StringRef> BigArchiveMemberHeader::getName(uint64_t Size) const {353return getRawName();354}355356Expected<uint64_t> ArchiveMemberHeader::getSize() const {357return getArchiveMemberDecField("size", getFieldRawString(ArMemHdr->Size),358Parent, this);359}360361Expected<uint64_t> BigArchiveMemberHeader::getSize() const {362Expected<uint64_t> SizeOrErr = getArchiveMemberDecField(363"size", getFieldRawString(ArMemHdr->Size), Parent, this);364if (!SizeOrErr)365return SizeOrErr.takeError();366367Expected<uint64_t> NameLenOrErr = getRawNameSize();368if (!NameLenOrErr)369return NameLenOrErr.takeError();370371return *SizeOrErr + alignTo(*NameLenOrErr, 2);372}373374Expected<uint64_t> BigArchiveMemberHeader::getRawNameSize() const {375return getArchiveMemberDecField(376"NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);377}378379Expected<uint64_t> BigArchiveMemberHeader::getNextOffset() const {380return getArchiveMemberDecField(381"NextOffset", getFieldRawString(ArMemHdr->NextOffset), Parent, this);382}383384Expected<sys::fs::perms> AbstractArchiveMemberHeader::getAccessMode() const {385Expected<uint64_t> AccessModeOrErr =386getArchiveMemberOctField("AccessMode", getRawAccessMode(), Parent, this);387if (!AccessModeOrErr)388return AccessModeOrErr.takeError();389return static_cast<sys::fs::perms>(*AccessModeOrErr);390}391392Expected<sys::TimePoint<std::chrono::seconds>>393AbstractArchiveMemberHeader::getLastModified() const {394Expected<uint64_t> SecondsOrErr = getArchiveMemberDecField(395"LastModified", getRawLastModified(), Parent, this);396397if (!SecondsOrErr)398return SecondsOrErr.takeError();399400return sys::toTimePoint(*SecondsOrErr);401}402403Expected<unsigned> AbstractArchiveMemberHeader::getUID() const {404StringRef User = getRawUID();405if (User.empty())406return 0;407return getArchiveMemberDecField("UID", User, Parent, this);408}409410Expected<unsigned> AbstractArchiveMemberHeader::getGID() const {411StringRef Group = getRawGID();412if (Group.empty())413return 0;414return getArchiveMemberDecField("GID", Group, Parent, this);415}416417Expected<bool> ArchiveMemberHeader::isThin() const {418Expected<StringRef> NameOrErr = getRawName();419if (!NameOrErr)420return NameOrErr.takeError();421StringRef Name = NameOrErr.get();422return Parent->isThin() && Name != "/" && Name != "//" && Name != "/SYM64/";423}424425Expected<const char *> ArchiveMemberHeader::getNextChildLoc() const {426uint64_t Size = getSizeOf();427Expected<bool> isThinOrErr = isThin();428if (!isThinOrErr)429return isThinOrErr.takeError();430431bool isThin = isThinOrErr.get();432if (!isThin) {433Expected<uint64_t> MemberSize = getSize();434if (!MemberSize)435return MemberSize.takeError();436437Size += MemberSize.get();438}439440// If Size is odd, add 1 to make it even.441const char *NextLoc =442reinterpret_cast<const char *>(ArMemHdr) + alignTo(Size, 2);443444if (NextLoc == Parent->getMemoryBufferRef().getBufferEnd())445return nullptr;446447return NextLoc;448}449450Expected<const char *> BigArchiveMemberHeader::getNextChildLoc() const {451if (getOffset() ==452static_cast<const BigArchive *>(Parent)->getLastChildOffset())453return nullptr;454455Expected<uint64_t> NextOffsetOrErr = getNextOffset();456if (!NextOffsetOrErr)457return NextOffsetOrErr.takeError();458return Parent->getData().data() + NextOffsetOrErr.get();459}460461Archive::Child::Child(const Archive *Parent, StringRef Data,462uint16_t StartOfFile)463: Parent(Parent), Data(Data), StartOfFile(StartOfFile) {464Header = Parent->createArchiveMemberHeader(Data.data(), Data.size(), nullptr);465}466467Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)468: Parent(Parent) {469if (!Start) {470Header = nullptr;471StartOfFile = -1;472return;473}474475Header = Parent->createArchiveMemberHeader(476Start,477Parent ? Parent->getData().size() - (Start - Parent->getData().data())478: 0,479Err);480481// If we are pointed to real data, Start is not a nullptr, then there must be482// a non-null Err pointer available to report malformed data on. Only in483// the case sentinel value is being constructed is Err is permitted to be a484// nullptr.485assert(Err && "Err can't be nullptr if Start is not a nullptr");486487ErrorAsOutParameter ErrAsOutParam(Err);488489// If there was an error in the construction of the Header490// then just return with the error now set.491if (*Err)492return;493494uint64_t Size = Header->getSizeOf();495Data = StringRef(Start, Size);496Expected<bool> isThinOrErr = isThinMember();497if (!isThinOrErr) {498*Err = isThinOrErr.takeError();499return;500}501bool isThin = isThinOrErr.get();502if (!isThin) {503Expected<uint64_t> MemberSize = getRawSize();504if (!MemberSize) {505*Err = MemberSize.takeError();506return;507}508Size += MemberSize.get();509Data = StringRef(Start, Size);510}511512// Setup StartOfFile and PaddingBytes.513StartOfFile = Header->getSizeOf();514// Don't include attached name.515Expected<StringRef> NameOrErr = getRawName();516if (!NameOrErr) {517*Err = NameOrErr.takeError();518return;519}520StringRef Name = NameOrErr.get();521522if (Parent->kind() == Archive::K_AIXBIG) {523// The actual start of the file is after the name and any necessary524// even-alignment padding.525StartOfFile += ((Name.size() + 1) >> 1) << 1;526} else if (Name.starts_with("#1/")) {527uint64_t NameSize;528StringRef RawNameSize = Name.substr(3).rtrim(' ');529if (RawNameSize.getAsInteger(10, NameSize)) {530uint64_t Offset = Start - Parent->getData().data();531*Err = malformedError("long name length characters after the #1/ are "532"not all decimal numbers: '" +533RawNameSize +534"' for archive member header at offset " +535Twine(Offset));536return;537}538StartOfFile += NameSize;539}540}541542Expected<uint64_t> Archive::Child::getSize() const {543if (Parent->IsThin)544return Header->getSize();545return Data.size() - StartOfFile;546}547548Expected<uint64_t> Archive::Child::getRawSize() const {549return Header->getSize();550}551552Expected<bool> Archive::Child::isThinMember() const { return Header->isThin(); }553554Expected<std::string> Archive::Child::getFullName() const {555Expected<bool> isThin = isThinMember();556if (!isThin)557return isThin.takeError();558assert(isThin.get());559Expected<StringRef> NameOrErr = getName();560if (!NameOrErr)561return NameOrErr.takeError();562StringRef Name = *NameOrErr;563if (sys::path::is_absolute(Name))564return std::string(Name);565566SmallString<128> FullName = sys::path::parent_path(567Parent->getMemoryBufferRef().getBufferIdentifier());568sys::path::append(FullName, Name);569return std::string(FullName);570}571572Expected<StringRef> Archive::Child::getBuffer() const {573Expected<bool> isThinOrErr = isThinMember();574if (!isThinOrErr)575return isThinOrErr.takeError();576bool isThin = isThinOrErr.get();577if (!isThin) {578Expected<uint64_t> Size = getSize();579if (!Size)580return Size.takeError();581return StringRef(Data.data() + StartOfFile, Size.get());582}583Expected<std::string> FullNameOrErr = getFullName();584if (!FullNameOrErr)585return FullNameOrErr.takeError();586const std::string &FullName = *FullNameOrErr;587ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName);588if (std::error_code EC = Buf.getError())589return errorCodeToError(EC);590Parent->ThinBuffers.push_back(std::move(*Buf));591return Parent->ThinBuffers.back()->getBuffer();592}593594Expected<Archive::Child> Archive::Child::getNext() const {595Expected<const char *> NextLocOrErr = Header->getNextChildLoc();596if (!NextLocOrErr)597return NextLocOrErr.takeError();598599const char *NextLoc = *NextLocOrErr;600601// Check to see if this is at the end of the archive.602if (NextLoc == nullptr)603return Child(nullptr, nullptr, nullptr);604605// Check to see if this is past the end of the archive.606if (NextLoc > Parent->Data.getBufferEnd()) {607std::string Msg("offset to next archive member past the end of the archive "608"after member ");609Expected<StringRef> NameOrErr = getName();610if (!NameOrErr) {611consumeError(NameOrErr.takeError());612uint64_t Offset = Data.data() - Parent->getData().data();613return malformedError(Msg + "at offset " + Twine(Offset));614} else615return malformedError(Msg + NameOrErr.get());616}617618Error Err = Error::success();619Child Ret(Parent, NextLoc, &Err);620if (Err)621return std::move(Err);622return Ret;623}624625uint64_t Archive::Child::getChildOffset() const {626const char *a = Parent->Data.getBuffer().data();627const char *c = Data.data();628uint64_t offset = c - a;629return offset;630}631632Expected<StringRef> Archive::Child::getName() const {633Expected<uint64_t> RawSizeOrErr = getRawSize();634if (!RawSizeOrErr)635return RawSizeOrErr.takeError();636uint64_t RawSize = RawSizeOrErr.get();637Expected<StringRef> NameOrErr =638Header->getName(Header->getSizeOf() + RawSize);639if (!NameOrErr)640return NameOrErr.takeError();641StringRef Name = NameOrErr.get();642return Name;643}644645Expected<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {646Expected<StringRef> NameOrErr = getName();647if (!NameOrErr)648return NameOrErr.takeError();649StringRef Name = NameOrErr.get();650Expected<StringRef> Buf = getBuffer();651if (!Buf)652return createFileError(Name, Buf.takeError());653return MemoryBufferRef(*Buf, Name);654}655656Expected<std::unique_ptr<Binary>>657Archive::Child::getAsBinary(LLVMContext *Context) const {658Expected<MemoryBufferRef> BuffOrErr = getMemoryBufferRef();659if (!BuffOrErr)660return BuffOrErr.takeError();661662auto BinaryOrErr = createBinary(BuffOrErr.get(), Context);663if (BinaryOrErr)664return std::move(*BinaryOrErr);665return BinaryOrErr.takeError();666}667668Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {669Error Err = Error::success();670std::unique_ptr<Archive> Ret;671StringRef Buffer = Source.getBuffer();672673if (Buffer.starts_with(BigArchiveMagic))674Ret = std::make_unique<BigArchive>(Source, Err);675else676Ret = std::make_unique<Archive>(Source, Err);677678if (Err)679return std::move(Err);680return std::move(Ret);681}682683std::unique_ptr<AbstractArchiveMemberHeader>684Archive::createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size,685Error *Err) const {686ErrorAsOutParameter ErrAsOutParam(Err);687if (kind() != K_AIXBIG)688return std::make_unique<ArchiveMemberHeader>(this, RawHeaderPtr, Size, Err);689return std::make_unique<BigArchiveMemberHeader>(this, RawHeaderPtr, Size,690Err);691}692693uint64_t Archive::getArchiveMagicLen() const {694if (isThin())695return sizeof(ThinArchiveMagic) - 1;696697if (Kind() == K_AIXBIG)698return sizeof(BigArchiveMagic) - 1;699700return sizeof(ArchiveMagic) - 1;701}702703void Archive::setFirstRegular(const Child &C) {704FirstRegularData = C.Data;705FirstRegularStartOfFile = C.StartOfFile;706}707708Archive::Archive(MemoryBufferRef Source, Error &Err)709: Binary(Binary::ID_Archive, Source) {710ErrorAsOutParameter ErrAsOutParam(&Err);711StringRef Buffer = Data.getBuffer();712// Check for sufficient magic.713if (Buffer.starts_with(ThinArchiveMagic)) {714IsThin = true;715} else if (Buffer.starts_with(ArchiveMagic)) {716IsThin = false;717} else if (Buffer.starts_with(BigArchiveMagic)) {718Format = K_AIXBIG;719IsThin = false;720return;721} else {722Err = make_error<GenericBinaryError>("file too small to be an archive",723object_error::invalid_file_type);724return;725}726727// Make sure Format is initialized before any call to728// ArchiveMemberHeader::getName() is made. This could be a valid empty729// archive which is the same in all formats. So claiming it to be gnu to is730// fine if not totally correct before we look for a string table or table of731// contents.732Format = K_GNU;733734// Get the special members.735child_iterator I = child_begin(Err, false);736if (Err)737return;738child_iterator E = child_end();739740// See if this is a valid empty archive and if so return.741if (I == E) {742Err = Error::success();743return;744}745const Child *C = &*I;746747auto Increment = [&]() {748++I;749if (Err)750return true;751C = &*I;752return false;753};754755Expected<StringRef> NameOrErr = C->getRawName();756if (!NameOrErr) {757Err = NameOrErr.takeError();758return;759}760StringRef Name = NameOrErr.get();761762// Below is the pattern that is used to figure out the archive format763// GNU archive format764// First member : / (may exist, if it exists, points to the symbol table )765// Second member : // (may exist, if it exists, points to the string table)766// Note : The string table is used if the filename exceeds 15 characters767// BSD archive format768// First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table)769// There is no string table, if the filename exceeds 15 characters or has a770// embedded space, the filename has #1/<size>, The size represents the size771// of the filename that needs to be read after the archive header772// COFF archive format773// First member : /774// Second member : / (provides a directory of symbols)775// Third member : // (may exist, if it exists, contains the string table)776// Note: Microsoft PE/COFF Spec 8.3 says that the third member is present777// even if the string table is empty. However, lib.exe does not in fact778// seem to create the third member if there's no member whose filename779// exceeds 15 characters. So the third member is optional.780781if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {782if (Name == "__.SYMDEF")783Format = K_BSD;784else // Name == "__.SYMDEF_64"785Format = K_DARWIN64;786// We know that the symbol table is not an external file, but we still must787// check any Expected<> return value.788Expected<StringRef> BufOrErr = C->getBuffer();789if (!BufOrErr) {790Err = BufOrErr.takeError();791return;792}793SymbolTable = BufOrErr.get();794if (Increment())795return;796setFirstRegular(*C);797798Err = Error::success();799return;800}801802if (Name.starts_with("#1/")) {803Format = K_BSD;804// We know this is BSD, so getName will work since there is no string table.805Expected<StringRef> NameOrErr = C->getName();806if (!NameOrErr) {807Err = NameOrErr.takeError();808return;809}810Name = NameOrErr.get();811if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {812// We know that the symbol table is not an external file, but we still813// must check any Expected<> return value.814Expected<StringRef> BufOrErr = C->getBuffer();815if (!BufOrErr) {816Err = BufOrErr.takeError();817return;818}819SymbolTable = BufOrErr.get();820if (Increment())821return;822} else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {823Format = K_DARWIN64;824// We know that the symbol table is not an external file, but we still825// must check any Expected<> return value.826Expected<StringRef> BufOrErr = C->getBuffer();827if (!BufOrErr) {828Err = BufOrErr.takeError();829return;830}831SymbolTable = BufOrErr.get();832if (Increment())833return;834}835setFirstRegular(*C);836return;837}838839// MIPS 64-bit ELF archives use a special format of a symbol table.840// This format is marked by `ar_name` field equals to "/SYM64/".841// For detailed description see page 96 in the following document:842// http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf843844bool has64SymTable = false;845if (Name == "/" || Name == "/SYM64/") {846// We know that the symbol table is not an external file, but we still847// must check any Expected<> return value.848Expected<StringRef> BufOrErr = C->getBuffer();849if (!BufOrErr) {850Err = BufOrErr.takeError();851return;852}853SymbolTable = BufOrErr.get();854if (Name == "/SYM64/")855has64SymTable = true;856857if (Increment())858return;859if (I == E) {860Err = Error::success();861return;862}863Expected<StringRef> NameOrErr = C->getRawName();864if (!NameOrErr) {865Err = NameOrErr.takeError();866return;867}868Name = NameOrErr.get();869}870871if (Name == "//") {872Format = has64SymTable ? K_GNU64 : K_GNU;873// The string table is never an external member, but we still874// must check any Expected<> return value.875Expected<StringRef> BufOrErr = C->getBuffer();876if (!BufOrErr) {877Err = BufOrErr.takeError();878return;879}880StringTable = BufOrErr.get();881if (Increment())882return;883setFirstRegular(*C);884Err = Error::success();885return;886}887888if (Name[0] != '/') {889Format = has64SymTable ? K_GNU64 : K_GNU;890setFirstRegular(*C);891Err = Error::success();892return;893}894895if (Name != "/") {896Err = errorCodeToError(object_error::parse_failed);897return;898}899900Format = K_COFF;901// We know that the symbol table is not an external file, but we still902// must check any Expected<> return value.903Expected<StringRef> BufOrErr = C->getBuffer();904if (!BufOrErr) {905Err = BufOrErr.takeError();906return;907}908SymbolTable = BufOrErr.get();909910if (Increment())911return;912913if (I == E) {914setFirstRegular(*C);915Err = Error::success();916return;917}918919NameOrErr = C->getRawName();920if (!NameOrErr) {921Err = NameOrErr.takeError();922return;923}924Name = NameOrErr.get();925926if (Name == "//") {927// The string table is never an external member, but we still928// must check any Expected<> return value.929Expected<StringRef> BufOrErr = C->getBuffer();930if (!BufOrErr) {931Err = BufOrErr.takeError();932return;933}934StringTable = BufOrErr.get();935if (Increment())936return;937938if (I == E) {939setFirstRegular(*C);940Err = Error::success();941return;942}943944NameOrErr = C->getRawName();945if (!NameOrErr) {946Err = NameOrErr.takeError();947return;948}949Name = NameOrErr.get();950}951952if (Name == "/<ECSYMBOLS>/") {953// ARM64EC-aware libraries contain an additional special member with954// an EC symbol map after the string table. Its format is similar to a955// regular symbol map, except it doesn't contain member offsets. Its indexes956// refer to member offsets from the regular symbol table instead.957Expected<StringRef> BufOrErr = C->getBuffer();958if (!BufOrErr) {959Err = BufOrErr.takeError();960return;961}962ECSymbolTable = BufOrErr.get();963if (Increment())964return;965}966967setFirstRegular(*C);968Err = Error::success();969}970971object::Archive::Kind Archive::getDefaultKindForTriple(Triple &T) {972if (T.isOSDarwin())973return object::Archive::K_DARWIN;974if (T.isOSAIX())975return object::Archive::K_AIXBIG;976if (T.isOSWindows())977return object::Archive::K_COFF;978return object::Archive::K_GNU;979}980981object::Archive::Kind Archive::getDefaultKind() {982Triple HostTriple(sys::getDefaultTargetTriple());983return getDefaultKindForTriple(HostTriple);984}985986Archive::child_iterator Archive::child_begin(Error &Err,987bool SkipInternal) const {988if (isEmpty())989return child_end();990991if (SkipInternal)992return child_iterator::itr(993Child(this, FirstRegularData, FirstRegularStartOfFile), Err);994995const char *Loc = Data.getBufferStart() + getFirstChildOffset();996Child C(this, Loc, &Err);997if (Err)998return child_end();999return child_iterator::itr(C, Err);1000}10011002Archive::child_iterator Archive::child_end() const {1003return child_iterator::end(Child(nullptr, nullptr, nullptr));1004}10051006bool Archive::Symbol::isECSymbol() const {1007// Symbols use SymbolCount..SymbolCount+getNumberOfECSymbols() for EC symbol1008// indexes.1009uint32_t SymbolCount = Parent->getNumberOfSymbols();1010return SymbolCount <= SymbolIndex &&1011SymbolIndex < SymbolCount + Parent->getNumberOfECSymbols();1012}10131014StringRef Archive::Symbol::getName() const {1015if (isECSymbol())1016return Parent->ECSymbolTable.begin() + StringIndex;1017return Parent->getSymbolTable().begin() + StringIndex;1018}10191020Expected<Archive::Child> Archive::Symbol::getMember() const {1021const char *Buf = Parent->getSymbolTable().begin();1022const char *Offsets = Buf;1023if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64 ||1024Parent->kind() == K_AIXBIG)1025Offsets += sizeof(uint64_t);1026else1027Offsets += sizeof(uint32_t);1028uint64_t Offset = 0;1029if (Parent->kind() == K_GNU) {1030Offset = read32be(Offsets + SymbolIndex * 4);1031} else if (Parent->kind() == K_GNU64 || Parent->kind() == K_AIXBIG) {1032Offset = read64be(Offsets + SymbolIndex * 8);1033} else if (Parent->kind() == K_BSD) {1034// The SymbolIndex is an index into the ranlib structs that start at1035// Offsets (the first uint32_t is the number of bytes of the ranlib1036// structs). The ranlib structs are a pair of uint32_t's the first1037// being a string table offset and the second being the offset into1038// the archive of the member that defines the symbol. Which is what1039// is needed here.1040Offset = read32le(Offsets + SymbolIndex * 8 + 4);1041} else if (Parent->kind() == K_DARWIN64) {1042// The SymbolIndex is an index into the ranlib_64 structs that start at1043// Offsets (the first uint64_t is the number of bytes of the ranlib_641044// structs). The ranlib_64 structs are a pair of uint64_t's the first1045// being a string table offset and the second being the offset into1046// the archive of the member that defines the symbol. Which is what1047// is needed here.1048Offset = read64le(Offsets + SymbolIndex * 16 + 8);1049} else {1050// Skip offsets.1051uint32_t MemberCount = read32le(Buf);1052Buf += MemberCount * 4 + 4;10531054uint32_t SymbolCount = read32le(Buf);1055uint16_t OffsetIndex;1056if (SymbolIndex < SymbolCount) {1057// Skip SymbolCount to get to the indices table.1058const char *Indices = Buf + 4;10591060// Get the index of the offset in the file member offset table for this1061// symbol.1062OffsetIndex = read16le(Indices + SymbolIndex * 2);1063} else if (isECSymbol()) {1064// Skip SymbolCount to get to the indices table.1065const char *Indices = Parent->ECSymbolTable.begin() + 4;10661067// Get the index of the offset in the file member offset table for this1068// symbol.1069OffsetIndex = read16le(Indices + (SymbolIndex - SymbolCount) * 2);1070} else {1071return errorCodeToError(object_error::parse_failed);1072}1073// Subtract 1 since OffsetIndex is 1 based.1074--OffsetIndex;10751076if (OffsetIndex >= MemberCount)1077return errorCodeToError(object_error::parse_failed);10781079Offset = read32le(Offsets + OffsetIndex * 4);1080}10811082const char *Loc = Parent->getData().begin() + Offset;1083Error Err = Error::success();1084Child C(Parent, Loc, &Err);1085if (Err)1086return std::move(Err);1087return C;1088}10891090Archive::Symbol Archive::Symbol::getNext() const {1091Symbol t(*this);1092if (Parent->kind() == K_BSD) {1093// t.StringIndex is an offset from the start of the __.SYMDEF or1094// "__.SYMDEF SORTED" member into the string table for the ranlib1095// struct indexed by t.SymbolIndex . To change t.StringIndex to the1096// offset in the string table for t.SymbolIndex+1 we subtract the1097// its offset from the start of the string table for t.SymbolIndex1098// and add the offset of the string table for t.SymbolIndex+1.10991100// The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t1101// which is the number of bytes of ranlib structs that follow. The ranlib1102// structs are a pair of uint32_t's the first being a string table offset1103// and the second being the offset into the archive of the member that1104// define the symbol. After that the next uint32_t is the byte count of1105// the string table followed by the string table.1106const char *Buf = Parent->getSymbolTable().begin();1107uint32_t RanlibCount = 0;1108RanlibCount = read32le(Buf) / 8;1109// If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount)1110// don't change the t.StringIndex as we don't want to reference a ranlib1111// past RanlibCount.1112if (t.SymbolIndex + 1 < RanlibCount) {1113const char *Ranlibs = Buf + 4;1114uint32_t CurRanStrx = 0;1115uint32_t NextRanStrx = 0;1116CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8);1117NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8);1118t.StringIndex -= CurRanStrx;1119t.StringIndex += NextRanStrx;1120}1121} else if (t.isECSymbol()) {1122// Go to one past next null.1123t.StringIndex = Parent->ECSymbolTable.find('\0', t.StringIndex) + 1;1124} else {1125// Go to one past next null.1126t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1;1127}1128++t.SymbolIndex;1129return t;1130}11311132Archive::symbol_iterator Archive::symbol_begin() const {1133if (!hasSymbolTable())1134return symbol_iterator(Symbol(this, 0, 0));11351136const char *buf = getSymbolTable().begin();1137if (kind() == K_GNU) {1138uint32_t symbol_count = 0;1139symbol_count = read32be(buf);1140buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));1141} else if (kind() == K_GNU64) {1142uint64_t symbol_count = read64be(buf);1143buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));1144} else if (kind() == K_BSD) {1145// The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t1146// which is the number of bytes of ranlib structs that follow. The ranlib1147// structs are a pair of uint32_t's the first being a string table offset1148// and the second being the offset into the archive of the member that1149// define the symbol. After that the next uint32_t is the byte count of1150// the string table followed by the string table.1151uint32_t ranlib_count = 0;1152ranlib_count = read32le(buf) / 8;1153const char *ranlibs = buf + 4;1154uint32_t ran_strx = 0;1155ran_strx = read32le(ranlibs);1156buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t))));1157// Skip the byte count of the string table.1158buf += sizeof(uint32_t);1159buf += ran_strx;1160} else if (kind() == K_DARWIN64) {1161// The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t1162// which is the number of bytes of ranlib_64 structs that follow. The1163// ranlib_64 structs are a pair of uint64_t's the first being a string1164// table offset and the second being the offset into the archive of the1165// member that define the symbol. After that the next uint64_t is the byte1166// count of the string table followed by the string table.1167uint64_t ranlib_count = 0;1168ranlib_count = read64le(buf) / 16;1169const char *ranlibs = buf + 8;1170uint64_t ran_strx = 0;1171ran_strx = read64le(ranlibs);1172buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t))));1173// Skip the byte count of the string table.1174buf += sizeof(uint64_t);1175buf += ran_strx;1176} else if (kind() == K_AIXBIG) {1177buf = getStringTable().begin();1178} else {1179uint32_t member_count = 0;1180uint32_t symbol_count = 0;1181member_count = read32le(buf);1182buf += 4 + (member_count * 4); // Skip offsets.1183symbol_count = read32le(buf);1184buf += 4 + (symbol_count * 2); // Skip indices.1185}1186uint32_t string_start_offset = buf - getSymbolTable().begin();1187return symbol_iterator(Symbol(this, 0, string_start_offset));1188}11891190Archive::symbol_iterator Archive::symbol_end() const {1191return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0));1192}11931194Expected<iterator_range<Archive::symbol_iterator>> Archive::ec_symbols() const {1195uint32_t Count = 0;11961197// Validate EC symbol table.1198if (!ECSymbolTable.empty()) {1199if (ECSymbolTable.size() < sizeof(uint32_t))1200return malformedError("invalid EC symbols size (" +1201Twine(ECSymbolTable.size()) + ")");1202if (SymbolTable.size() < sizeof(uint32_t))1203return malformedError("invalid symbols size (" +1204Twine(ECSymbolTable.size()) + ")");12051206Count = read32le(ECSymbolTable.begin());1207size_t StringIndex = sizeof(uint32_t) + Count * sizeof(uint16_t);1208if (ECSymbolTable.size() < StringIndex)1209return malformedError("invalid EC symbols size. Size was " +1210Twine(ECSymbolTable.size()) + ", but expected " +1211Twine(StringIndex));12121213uint32_t MemberCount = read32le(SymbolTable.begin());1214const char *Indexes = ECSymbolTable.begin() + sizeof(uint32_t);12151216for (uint32_t i = 0; i < Count; ++i) {1217uint16_t Index = read16le(Indexes + i * sizeof(uint16_t));1218if (!Index)1219return malformedError("invalid EC symbol index 0");1220if (Index > MemberCount)1221return malformedError("invalid EC symbol index " + Twine(Index) +1222" is larger than member count " +1223Twine(MemberCount));12241225StringIndex = ECSymbolTable.find('\0', StringIndex);1226if (StringIndex == StringRef::npos)1227return malformedError("malformed EC symbol names: not null-terminated");1228++StringIndex;1229}1230}12311232uint32_t SymbolCount = getNumberOfSymbols();1233return make_range(1234symbol_iterator(Symbol(this, SymbolCount,1235sizeof(uint32_t) + Count * sizeof(uint16_t))),1236symbol_iterator(Symbol(this, SymbolCount + Count, 0)));1237}12381239uint32_t Archive::getNumberOfSymbols() const {1240if (!hasSymbolTable())1241return 0;1242const char *buf = getSymbolTable().begin();1243if (kind() == K_GNU)1244return read32be(buf);1245if (kind() == K_GNU64 || kind() == K_AIXBIG)1246return read64be(buf);1247if (kind() == K_BSD)1248return read32le(buf) / 8;1249if (kind() == K_DARWIN64)1250return read64le(buf) / 16;1251uint32_t member_count = 0;1252member_count = read32le(buf);1253buf += 4 + (member_count * 4); // Skip offsets.1254return read32le(buf);1255}12561257uint32_t Archive::getNumberOfECSymbols() const {1258if (ECSymbolTable.size() < sizeof(uint32_t))1259return 0;1260return read32le(ECSymbolTable.begin());1261}12621263Expected<std::optional<Archive::Child>> Archive::findSym(StringRef name) const {1264Archive::symbol_iterator bs = symbol_begin();1265Archive::symbol_iterator es = symbol_end();12661267for (; bs != es; ++bs) {1268StringRef SymName = bs->getName();1269if (SymName == name) {1270if (auto MemberOrErr = bs->getMember())1271return Child(*MemberOrErr);1272else1273return MemberOrErr.takeError();1274}1275}1276return std::nullopt;1277}12781279// Returns true if archive file contains no member file.1280bool Archive::isEmpty() const {1281return Data.getBufferSize() == getArchiveMagicLen();1282}12831284bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }12851286static Error getGlobalSymtabLocAndSize(const MemoryBufferRef &Data,1287uint64_t GlobalSymtabOffset,1288const char *&GlobalSymtabLoc,1289uint64_t &Size, const char *BitMessage) {1290uint64_t BufferSize = Data.getBufferSize();1291uint64_t GlobalSymtabContentOffset =1292GlobalSymtabOffset + sizeof(BigArMemHdrType);1293if (GlobalSymtabContentOffset > BufferSize)1294return malformedError(1295Twine(BitMessage) + " global symbol table header at offset 0x" +1296Twine::utohexstr(GlobalSymtabOffset) + " and size 0x" +1297Twine::utohexstr(sizeof(BigArMemHdrType)) +1298" goes past the end of file");12991300GlobalSymtabLoc = Data.getBufferStart() + GlobalSymtabOffset;1301const BigArMemHdrType *GlobalSymHdr =1302reinterpret_cast<const BigArMemHdrType *>(GlobalSymtabLoc);1303StringRef RawOffset = getFieldRawString(GlobalSymHdr->Size);1304if (RawOffset.getAsInteger(10, Size))1305return malformedError(Twine(BitMessage) + " global symbol table size \"" +1306RawOffset + "\" is not a number");13071308if (GlobalSymtabContentOffset + Size > BufferSize)1309return malformedError(1310Twine(BitMessage) + " global symbol table content at offset 0x" +1311Twine::utohexstr(GlobalSymtabContentOffset) + " and size 0x" +1312Twine::utohexstr(Size) + " goes past the end of file");13131314return Error::success();1315}13161317struct GlobalSymtabInfo {1318uint64_t SymNum;1319StringRef SymbolTable;1320StringRef SymbolOffsetTable;1321StringRef StringTable;1322};13231324static void1325appendGlobalSymbolTableInfo(SmallVector<GlobalSymtabInfo> &SymtabInfos,1326const char *GlobalSymtabLoc, uint64_t Size) {1327// In a big archive, a global symbol table contains the following information:1328// - The number of symbols.1329// - The array of offsets into the archive file. The length is eight1330// times the number of symbols.1331// - The name-string table. The size is:1332// Size-(8*(the number of symbols + 1)).13331334StringRef SymbolTable =1335StringRef(GlobalSymtabLoc + sizeof(BigArMemHdrType), Size);1336uint64_t SymNum = read64be(GlobalSymtabLoc + sizeof(BigArMemHdrType));1337StringRef SymbolOffsetTable = StringRef(SymbolTable.data() + 8, 8 * SymNum);1338unsigned SymOffsetsSize = 8 * (SymNum + 1);1339uint64_t SymbolTableStringSize = Size - SymOffsetsSize;1340StringRef StringTable =1341StringRef(SymbolTable.data() + SymOffsetsSize, SymbolTableStringSize);1342SymtabInfos.push_back({SymNum, SymbolTable, SymbolOffsetTable, StringTable});1343}13441345BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)1346: Archive(Source, Err) {1347ErrorAsOutParameter ErrAsOutParam(&Err);1348StringRef Buffer = Data.getBuffer();1349ArFixLenHdr = reinterpret_cast<const FixLenHdr *>(Buffer.data());1350uint64_t BufferSize = Data.getBufferSize();13511352if (BufferSize < sizeof(FixLenHdr)) {1353Err = malformedError("malformed AIX big archive: incomplete fixed length "1354"header, the archive is only" +1355Twine(BufferSize) + " byte(s)");1356return;1357}13581359StringRef RawOffset = getFieldRawString(ArFixLenHdr->FirstChildOffset);1360if (RawOffset.getAsInteger(10, FirstChildOffset))1361// TODO: Out-of-line.1362Err = malformedError("malformed AIX big archive: first member offset \"" +1363RawOffset + "\" is not a number");13641365RawOffset = getFieldRawString(ArFixLenHdr->LastChildOffset);1366if (RawOffset.getAsInteger(10, LastChildOffset))1367// TODO: Out-of-line.1368Err = malformedError("malformed AIX big archive: last member offset \"" +1369RawOffset + "\" is not a number");13701371uint64_t GlobSymtab32Offset = 0;1372RawOffset = getFieldRawString(ArFixLenHdr->GlobSymOffset);1373if (RawOffset.getAsInteger(10, GlobSymtab32Offset)) {1374Err = malformedError("global symbol table "1375"offset of 32-bit members \"" +1376RawOffset + "\" is not a number");1377return;1378}13791380uint64_t GlobSymtab64Offset = 0;1381RawOffset = getFieldRawString(ArFixLenHdr->GlobSym64Offset);1382if (RawOffset.getAsInteger(10, GlobSymtab64Offset)) {1383Err = malformedError("global symbol table "1384"offset of 64-bit members\"" +1385RawOffset + "\" is not a number");1386return;1387}13881389const char *GlobSymtab32Loc = nullptr;1390const char *GlobSymtab64Loc = nullptr;1391uint64_t GlobSymtab32Size = 0;1392uint64_t GlobSymtab64Size = 0;1393const MemoryBufferRef &MemBuffRef = getMemoryBufferRef();13941395if (GlobSymtab32Offset) {1396Err =1397getGlobalSymtabLocAndSize(MemBuffRef, GlobSymtab32Offset,1398GlobSymtab32Loc, GlobSymtab32Size, "32-bit");1399if (Err)1400return;14011402Has32BitGlobalSymtab = true;1403}14041405if (GlobSymtab64Offset) {1406Err =1407getGlobalSymtabLocAndSize(MemBuffRef, GlobSymtab64Offset,1408GlobSymtab64Loc, GlobSymtab64Size, "64-bit");1409if (Err)1410return;14111412Has64BitGlobalSymtab = true;1413}14141415SmallVector<GlobalSymtabInfo> SymtabInfos;14161417if (GlobSymtab32Offset)1418appendGlobalSymbolTableInfo(SymtabInfos, GlobSymtab32Loc, GlobSymtab32Size);1419if (GlobSymtab64Offset)1420appendGlobalSymbolTableInfo(SymtabInfos, GlobSymtab64Loc, GlobSymtab64Size);14211422if (SymtabInfos.size() == 1) {1423SymbolTable = SymtabInfos[0].SymbolTable;1424StringTable = SymtabInfos[0].StringTable;1425} else if (SymtabInfos.size() == 2) {1426// In order to let the Archive::Symbol::getNext() work for both 32-bit and1427// 64-bit global symbol tables, we need to merge them into a single table.1428raw_string_ostream Out(MergedGlobalSymtabBuf);1429uint64_t SymNum = SymtabInfos[0].SymNum + SymtabInfos[1].SymNum;1430write(Out, SymNum, llvm::endianness::big);1431// Merge symbol offset.1432Out << SymtabInfos[0].SymbolOffsetTable;1433Out << SymtabInfos[1].SymbolOffsetTable;1434// Merge string table.1435Out << SymtabInfos[0].StringTable;1436Out << SymtabInfos[1].StringTable;1437SymbolTable = MergedGlobalSymtabBuf;1438// The size of the symbol offset to the member file is 8 bytes.1439StringTable = StringRef(SymbolTable.begin() + (SymNum + 1) * 8,1440SymtabInfos[0].StringTable.size() +1441SymtabInfos[1].StringTable.size());1442}14431444child_iterator I = child_begin(Err, false);1445if (Err)1446return;1447child_iterator E = child_end();1448if (I == E) {1449Err = Error::success();1450return;1451}1452setFirstRegular(*I);1453Err = Error::success();1454}145514561457