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