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