109467b48Spatrick //===- Archive.cpp - ar File Format implementation ------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file defines the ArchiveObjectFile class.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick
1309467b48Spatrick #include "llvm/Object/Archive.h"
1409467b48Spatrick #include "llvm/ADT/SmallString.h"
1509467b48Spatrick #include "llvm/ADT/StringRef.h"
1609467b48Spatrick #include "llvm/ADT/Twine.h"
1709467b48Spatrick #include "llvm/Object/Binary.h"
1809467b48Spatrick #include "llvm/Object/Error.h"
1909467b48Spatrick #include "llvm/Support/Chrono.h"
2009467b48Spatrick #include "llvm/Support/Endian.h"
2109467b48Spatrick #include "llvm/Support/Error.h"
2209467b48Spatrick #include "llvm/Support/ErrorOr.h"
2309467b48Spatrick #include "llvm/Support/FileSystem.h"
24*d415bd75Srobert #include "llvm/Support/Host.h"
25*d415bd75Srobert #include "llvm/Support/MathExtras.h"
2609467b48Spatrick #include "llvm/Support/MemoryBuffer.h"
2709467b48Spatrick #include "llvm/Support/Path.h"
2809467b48Spatrick #include "llvm/Support/raw_ostream.h"
2909467b48Spatrick #include <algorithm>
3009467b48Spatrick #include <cassert>
3109467b48Spatrick #include <cstddef>
3209467b48Spatrick #include <cstdint>
3309467b48Spatrick #include <memory>
3409467b48Spatrick #include <string>
3509467b48Spatrick #include <system_error>
3609467b48Spatrick
3709467b48Spatrick using namespace llvm;
3809467b48Spatrick using namespace object;
3909467b48Spatrick using namespace llvm::support::endian;
4009467b48Spatrick
anchor()4109467b48Spatrick void Archive::anchor() {}
4209467b48Spatrick
malformedError(Twine Msg)4373471bf0Spatrick static Error malformedError(Twine Msg) {
4409467b48Spatrick std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")";
4509467b48Spatrick return make_error<GenericBinaryError>(std::move(StringMsg),
4609467b48Spatrick object_error::parse_failed);
4709467b48Spatrick }
4809467b48Spatrick
49*d415bd75Srobert static Error
createMemberHeaderParseError(const AbstractArchiveMemberHeader * ArMemHeader,const char * RawHeaderPtr,uint64_t Size)50*d415bd75Srobert createMemberHeaderParseError(const AbstractArchiveMemberHeader *ArMemHeader,
51*d415bd75Srobert const char *RawHeaderPtr, uint64_t Size) {
52*d415bd75Srobert StringRef Msg("remaining size of archive too small for next archive "
53*d415bd75Srobert "member header ");
54*d415bd75Srobert
55*d415bd75Srobert Expected<StringRef> NameOrErr = ArMemHeader->getName(Size);
56*d415bd75Srobert if (NameOrErr)
57*d415bd75Srobert return malformedError(Msg + "for " + *NameOrErr);
58*d415bd75Srobert
59*d415bd75Srobert consumeError(NameOrErr.takeError());
60*d415bd75Srobert uint64_t Offset = RawHeaderPtr - ArMemHeader->Parent->getData().data();
61*d415bd75Srobert return malformedError(Msg + "at offset " + Twine(Offset));
62*d415bd75Srobert }
63*d415bd75Srobert
64*d415bd75Srobert template <class T, std::size_t N>
getFieldRawString(const T (& Field)[N])65*d415bd75Srobert StringRef getFieldRawString(const T (&Field)[N]) {
66*d415bd75Srobert return StringRef(Field, N).rtrim(" ");
67*d415bd75Srobert }
68*d415bd75Srobert
69*d415bd75Srobert template <class T>
getRawAccessMode() const70*d415bd75Srobert StringRef CommonArchiveMemberHeader<T>::getRawAccessMode() const {
71*d415bd75Srobert return getFieldRawString(ArMemHdr->AccessMode);
72*d415bd75Srobert }
73*d415bd75Srobert
74*d415bd75Srobert template <class T>
getRawLastModified() const75*d415bd75Srobert StringRef CommonArchiveMemberHeader<T>::getRawLastModified() const {
76*d415bd75Srobert return getFieldRawString(ArMemHdr->LastModified);
77*d415bd75Srobert }
78*d415bd75Srobert
getRawUID() const79*d415bd75Srobert template <class T> StringRef CommonArchiveMemberHeader<T>::getRawUID() const {
80*d415bd75Srobert return getFieldRawString(ArMemHdr->UID);
81*d415bd75Srobert }
82*d415bd75Srobert
getRawGID() const83*d415bd75Srobert template <class T> StringRef CommonArchiveMemberHeader<T>::getRawGID() const {
84*d415bd75Srobert return getFieldRawString(ArMemHdr->GID);
85*d415bd75Srobert }
86*d415bd75Srobert
getOffset() const87*d415bd75Srobert template <class T> uint64_t CommonArchiveMemberHeader<T>::getOffset() const {
88*d415bd75Srobert return reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
89*d415bd75Srobert }
90*d415bd75Srobert
91*d415bd75Srobert template class object::CommonArchiveMemberHeader<UnixArMemHdrType>;
92*d415bd75Srobert template class object::CommonArchiveMemberHeader<BigArMemHdrType>;
93*d415bd75Srobert
ArchiveMemberHeader(const Archive * Parent,const char * RawHeaderPtr,uint64_t Size,Error * Err)9409467b48Spatrick ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent,
9509467b48Spatrick const char *RawHeaderPtr,
9609467b48Spatrick uint64_t Size, Error *Err)
97*d415bd75Srobert : CommonArchiveMemberHeader<UnixArMemHdrType>(
98*d415bd75Srobert Parent, reinterpret_cast<const UnixArMemHdrType *>(RawHeaderPtr)) {
9909467b48Spatrick if (RawHeaderPtr == nullptr)
10009467b48Spatrick return;
10109467b48Spatrick ErrorAsOutParameter ErrAsOutParam(Err);
10209467b48Spatrick
103*d415bd75Srobert if (Size < getSizeOf()) {
104*d415bd75Srobert *Err = createMemberHeaderParseError(this, RawHeaderPtr, Size);
10509467b48Spatrick return;
10609467b48Spatrick }
10709467b48Spatrick if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') {
10809467b48Spatrick if (Err) {
10909467b48Spatrick std::string Buf;
11009467b48Spatrick raw_string_ostream OS(Buf);
11173471bf0Spatrick OS.write_escaped(
11273471bf0Spatrick StringRef(ArMemHdr->Terminator, sizeof(ArMemHdr->Terminator)));
11309467b48Spatrick OS.flush();
11409467b48Spatrick std::string Msg("terminator characters in archive member \"" + Buf +
11509467b48Spatrick "\" not the correct \"`\\n\" values for the archive "
11609467b48Spatrick "member header ");
11709467b48Spatrick Expected<StringRef> NameOrErr = getName(Size);
11809467b48Spatrick if (!NameOrErr) {
11909467b48Spatrick consumeError(NameOrErr.takeError());
12009467b48Spatrick uint64_t Offset = RawHeaderPtr - Parent->getData().data();
12109467b48Spatrick *Err = malformedError(Msg + "at offset " + Twine(Offset));
12209467b48Spatrick } else
12309467b48Spatrick *Err = malformedError(Msg + "for " + NameOrErr.get());
12409467b48Spatrick }
12509467b48Spatrick return;
12609467b48Spatrick }
12709467b48Spatrick }
12809467b48Spatrick
BigArchiveMemberHeader(const Archive * Parent,const char * RawHeaderPtr,uint64_t Size,Error * Err)129*d415bd75Srobert BigArchiveMemberHeader::BigArchiveMemberHeader(const Archive *Parent,
130*d415bd75Srobert const char *RawHeaderPtr,
131*d415bd75Srobert uint64_t Size, Error *Err)
132*d415bd75Srobert : CommonArchiveMemberHeader<BigArMemHdrType>(
133*d415bd75Srobert Parent, reinterpret_cast<const BigArMemHdrType *>(RawHeaderPtr)) {
134*d415bd75Srobert if (RawHeaderPtr == nullptr)
135*d415bd75Srobert return;
136*d415bd75Srobert ErrorAsOutParameter ErrAsOutParam(Err);
137*d415bd75Srobert
138*d415bd75Srobert if (Size < getSizeOf()) {
139*d415bd75Srobert Error SubErr = createMemberHeaderParseError(this, RawHeaderPtr, Size);
140*d415bd75Srobert if (Err)
141*d415bd75Srobert *Err = std::move(SubErr);
142*d415bd75Srobert }
143*d415bd75Srobert }
144*d415bd75Srobert
14509467b48Spatrick // This gets the raw name from the ArMemHdr->Name field and checks that it is
14609467b48Spatrick // valid for the kind of archive. If it is not valid it returns an Error.
getRawName() const14709467b48Spatrick Expected<StringRef> ArchiveMemberHeader::getRawName() const {
14809467b48Spatrick char EndCond;
14909467b48Spatrick auto Kind = Parent->kind();
15009467b48Spatrick if (Kind == Archive::K_BSD || Kind == Archive::K_DARWIN64) {
15109467b48Spatrick if (ArMemHdr->Name[0] == ' ') {
15273471bf0Spatrick uint64_t Offset =
15373471bf0Spatrick reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
15409467b48Spatrick return malformedError("name contains a leading space for archive member "
15573471bf0Spatrick "header at offset " +
15673471bf0Spatrick Twine(Offset));
15709467b48Spatrick }
15809467b48Spatrick EndCond = ' ';
15973471bf0Spatrick } else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#')
16009467b48Spatrick EndCond = ' ';
16109467b48Spatrick else
16209467b48Spatrick EndCond = '/';
16309467b48Spatrick StringRef::size_type end =
16409467b48Spatrick StringRef(ArMemHdr->Name, sizeof(ArMemHdr->Name)).find(EndCond);
16509467b48Spatrick if (end == StringRef::npos)
16609467b48Spatrick end = sizeof(ArMemHdr->Name);
16709467b48Spatrick assert(end <= sizeof(ArMemHdr->Name) && end > 0);
16809467b48Spatrick // Don't include the EndCond if there is one.
16909467b48Spatrick return StringRef(ArMemHdr->Name, end);
17009467b48Spatrick }
17109467b48Spatrick
172*d415bd75Srobert Expected<uint64_t>
getArchiveMemberDecField(Twine FieldName,const StringRef RawField,const Archive * Parent,const AbstractArchiveMemberHeader * MemHeader)173*d415bd75Srobert getArchiveMemberDecField(Twine FieldName, const StringRef RawField,
174*d415bd75Srobert const Archive *Parent,
175*d415bd75Srobert const AbstractArchiveMemberHeader *MemHeader) {
176*d415bd75Srobert uint64_t Value;
177*d415bd75Srobert if (RawField.getAsInteger(10, Value)) {
178*d415bd75Srobert uint64_t Offset = MemHeader->getOffset();
179*d415bd75Srobert return malformedError("characters in " + FieldName +
180*d415bd75Srobert " field in archive member header are not "
181*d415bd75Srobert "all decimal numbers: '" +
182*d415bd75Srobert RawField +
183*d415bd75Srobert "' for the archive "
184*d415bd75Srobert "member header at offset " +
185*d415bd75Srobert Twine(Offset));
186*d415bd75Srobert }
187*d415bd75Srobert return Value;
188*d415bd75Srobert }
189*d415bd75Srobert
190*d415bd75Srobert Expected<uint64_t>
getArchiveMemberOctField(Twine FieldName,const StringRef RawField,const Archive * Parent,const AbstractArchiveMemberHeader * MemHeader)191*d415bd75Srobert getArchiveMemberOctField(Twine FieldName, const StringRef RawField,
192*d415bd75Srobert const Archive *Parent,
193*d415bd75Srobert const AbstractArchiveMemberHeader *MemHeader) {
194*d415bd75Srobert uint64_t Value;
195*d415bd75Srobert if (RawField.getAsInteger(8, Value)) {
196*d415bd75Srobert uint64_t Offset = MemHeader->getOffset();
197*d415bd75Srobert return malformedError("characters in " + FieldName +
198*d415bd75Srobert " field in archive member header are not "
199*d415bd75Srobert "all octal numbers: '" +
200*d415bd75Srobert RawField +
201*d415bd75Srobert "' for the archive "
202*d415bd75Srobert "member header at offset " +
203*d415bd75Srobert Twine(Offset));
204*d415bd75Srobert }
205*d415bd75Srobert return Value;
206*d415bd75Srobert }
207*d415bd75Srobert
getRawName() const208*d415bd75Srobert Expected<StringRef> BigArchiveMemberHeader::getRawName() const {
209*d415bd75Srobert Expected<uint64_t> NameLenOrErr = getArchiveMemberDecField(
210*d415bd75Srobert "NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);
211*d415bd75Srobert if (!NameLenOrErr)
212*d415bd75Srobert // TODO: Out-of-line.
213*d415bd75Srobert return NameLenOrErr.takeError();
214*d415bd75Srobert uint64_t NameLen = NameLenOrErr.get();
215*d415bd75Srobert
216*d415bd75Srobert // If the name length is odd, pad with '\0' to get an even length. After
217*d415bd75Srobert // padding, there is the name terminator "`\n".
218*d415bd75Srobert uint64_t NameLenWithPadding = alignTo(NameLen, 2);
219*d415bd75Srobert StringRef NameTerminator = "`\n";
220*d415bd75Srobert StringRef NameStringWithNameTerminator =
221*d415bd75Srobert StringRef(ArMemHdr->Name, NameLenWithPadding + NameTerminator.size());
222*d415bd75Srobert if (!NameStringWithNameTerminator.endswith(NameTerminator)) {
223*d415bd75Srobert uint64_t Offset =
224*d415bd75Srobert reinterpret_cast<const char *>(ArMemHdr->Name + NameLenWithPadding) -
225*d415bd75Srobert Parent->getData().data();
226*d415bd75Srobert // TODO: Out-of-line.
227*d415bd75Srobert return malformedError(
228*d415bd75Srobert "name does not have name terminator \"`\\n\" for archive member"
229*d415bd75Srobert "header at offset " +
230*d415bd75Srobert Twine(Offset));
231*d415bd75Srobert }
232*d415bd75Srobert return StringRef(ArMemHdr->Name, NameLen);
233*d415bd75Srobert }
234*d415bd75Srobert
23509467b48Spatrick // member including the header, so the size of any name following the header
23609467b48Spatrick // is checked to make sure it does not overflow.
getName(uint64_t Size) const23709467b48Spatrick Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
23809467b48Spatrick
23909467b48Spatrick // This can be called from the ArchiveMemberHeader constructor when the
24009467b48Spatrick // archive header is truncated to produce an error message with the name.
24109467b48Spatrick // Make sure the name field is not truncated.
242*d415bd75Srobert if (Size < offsetof(UnixArMemHdrType, Name) + sizeof(ArMemHdr->Name)) {
24373471bf0Spatrick uint64_t ArchiveOffset =
24473471bf0Spatrick reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
24509467b48Spatrick return malformedError("archive header truncated before the name field "
24609467b48Spatrick "for archive member header at offset " +
24709467b48Spatrick Twine(ArchiveOffset));
24809467b48Spatrick }
24909467b48Spatrick
25009467b48Spatrick // The raw name itself can be invalid.
25109467b48Spatrick Expected<StringRef> NameOrErr = getRawName();
25209467b48Spatrick if (!NameOrErr)
25309467b48Spatrick return NameOrErr.takeError();
25409467b48Spatrick StringRef Name = NameOrErr.get();
25509467b48Spatrick
25609467b48Spatrick // Check if it's a special name.
25709467b48Spatrick if (Name[0] == '/') {
25809467b48Spatrick if (Name.size() == 1) // Linker member.
25909467b48Spatrick return Name;
26009467b48Spatrick if (Name.size() == 2 && Name[1] == '/') // String table.
26109467b48Spatrick return Name;
262*d415bd75Srobert // System libraries from the Windows SDK for Windows 11 contain this symbol.
263*d415bd75Srobert // It looks like a CFG guard: we just skip it for now.
264*d415bd75Srobert if (Name.equals("/<XFGHASHMAP>/"))
265*d415bd75Srobert return Name;
266*d415bd75Srobert // Some libraries (e.g., arm64rt.lib) from the Windows WDK
267*d415bd75Srobert // (version 10.0.22000.0) contain this undocumented special member.
268*d415bd75Srobert if (Name.equals("/<ECSYMBOLS>/"))
269*d415bd75Srobert return Name;
27009467b48Spatrick // It's a long name.
27109467b48Spatrick // Get the string table offset.
27209467b48Spatrick std::size_t StringOffset;
27309467b48Spatrick if (Name.substr(1).rtrim(' ').getAsInteger(10, StringOffset)) {
27409467b48Spatrick std::string Buf;
27509467b48Spatrick raw_string_ostream OS(Buf);
27609467b48Spatrick OS.write_escaped(Name.substr(1).rtrim(' '));
27709467b48Spatrick OS.flush();
27873471bf0Spatrick uint64_t ArchiveOffset =
27973471bf0Spatrick reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
28009467b48Spatrick return malformedError("long name offset characters after the '/' are "
28173471bf0Spatrick "not all decimal numbers: '" +
28273471bf0Spatrick Buf + "' for archive member header at offset " +
28309467b48Spatrick Twine(ArchiveOffset));
28409467b48Spatrick }
28509467b48Spatrick
28609467b48Spatrick // Verify it.
28709467b48Spatrick if (StringOffset >= Parent->getStringTable().size()) {
28873471bf0Spatrick uint64_t ArchiveOffset =
28973471bf0Spatrick reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
29073471bf0Spatrick return malformedError("long name offset " + Twine(StringOffset) +
29173471bf0Spatrick " past the end of the string table for archive "
29273471bf0Spatrick "member header at offset " +
29373471bf0Spatrick Twine(ArchiveOffset));
29409467b48Spatrick }
29509467b48Spatrick
29609467b48Spatrick // GNU long file names end with a "/\n".
29709467b48Spatrick if (Parent->kind() == Archive::K_GNU ||
29809467b48Spatrick Parent->kind() == Archive::K_GNU64) {
29909467b48Spatrick size_t End = Parent->getStringTable().find('\n', /*From=*/StringOffset);
30009467b48Spatrick if (End == StringRef::npos || End < 1 ||
30109467b48Spatrick Parent->getStringTable()[End - 1] != '/') {
30209467b48Spatrick return malformedError("string table at long name offset " +
30309467b48Spatrick Twine(StringOffset) + "not terminated");
30409467b48Spatrick }
30509467b48Spatrick return Parent->getStringTable().slice(StringOffset, End - 1);
30609467b48Spatrick }
30709467b48Spatrick return Parent->getStringTable().begin() + StringOffset;
30809467b48Spatrick }
30909467b48Spatrick
31009467b48Spatrick if (Name.startswith("#1/")) {
31109467b48Spatrick uint64_t NameLength;
31209467b48Spatrick if (Name.substr(3).rtrim(' ').getAsInteger(10, NameLength)) {
31309467b48Spatrick std::string Buf;
31409467b48Spatrick raw_string_ostream OS(Buf);
31509467b48Spatrick OS.write_escaped(Name.substr(3).rtrim(' '));
31609467b48Spatrick OS.flush();
31773471bf0Spatrick uint64_t ArchiveOffset =
31873471bf0Spatrick reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
31909467b48Spatrick return malformedError("long name length characters after the #1/ are "
32073471bf0Spatrick "not all decimal numbers: '" +
32173471bf0Spatrick Buf + "' for archive member header at offset " +
32209467b48Spatrick Twine(ArchiveOffset));
32309467b48Spatrick }
32409467b48Spatrick if (getSizeOf() + NameLength > Size) {
32573471bf0Spatrick uint64_t ArchiveOffset =
32673471bf0Spatrick reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
32709467b48Spatrick return malformedError("long name length: " + Twine(NameLength) +
32809467b48Spatrick " extends past the end of the member or archive "
32909467b48Spatrick "for archive member header at offset " +
33009467b48Spatrick Twine(ArchiveOffset));
33109467b48Spatrick }
33209467b48Spatrick return StringRef(reinterpret_cast<const char *>(ArMemHdr) + getSizeOf(),
33373471bf0Spatrick NameLength)
33473471bf0Spatrick .rtrim('\0');
33509467b48Spatrick }
33609467b48Spatrick
33709467b48Spatrick // It is not a long name so trim the blanks at the end of the name.
33809467b48Spatrick if (Name[Name.size() - 1] != '/')
33909467b48Spatrick return Name.rtrim(' ');
34009467b48Spatrick
34109467b48Spatrick // It's a simple name.
34209467b48Spatrick return Name.drop_back(1);
34309467b48Spatrick }
34409467b48Spatrick
getName(uint64_t Size) const345*d415bd75Srobert Expected<StringRef> BigArchiveMemberHeader::getName(uint64_t Size) const {
346*d415bd75Srobert return getRawName();
34709467b48Spatrick }
34809467b48Spatrick
getSize() const349*d415bd75Srobert Expected<uint64_t> ArchiveMemberHeader::getSize() const {
350*d415bd75Srobert return getArchiveMemberDecField("size", getFieldRawString(ArMemHdr->Size),
351*d415bd75Srobert Parent, this);
35209467b48Spatrick }
353*d415bd75Srobert
getSize() const354*d415bd75Srobert Expected<uint64_t> BigArchiveMemberHeader::getSize() const {
355*d415bd75Srobert Expected<uint64_t> SizeOrErr = getArchiveMemberDecField(
356*d415bd75Srobert "size", getFieldRawString(ArMemHdr->Size), Parent, this);
357*d415bd75Srobert if (!SizeOrErr)
358*d415bd75Srobert return SizeOrErr.takeError();
359*d415bd75Srobert
360*d415bd75Srobert Expected<uint64_t> NameLenOrErr = getRawNameSize();
361*d415bd75Srobert if (!NameLenOrErr)
362*d415bd75Srobert return NameLenOrErr.takeError();
363*d415bd75Srobert
364*d415bd75Srobert return *SizeOrErr + alignTo(*NameLenOrErr, 2);
365*d415bd75Srobert }
366*d415bd75Srobert
getRawNameSize() const367*d415bd75Srobert Expected<uint64_t> BigArchiveMemberHeader::getRawNameSize() const {
368*d415bd75Srobert return getArchiveMemberDecField(
369*d415bd75Srobert "NameLen", getFieldRawString(ArMemHdr->NameLen), Parent, this);
370*d415bd75Srobert }
371*d415bd75Srobert
getNextOffset() const372*d415bd75Srobert Expected<uint64_t> BigArchiveMemberHeader::getNextOffset() const {
373*d415bd75Srobert return getArchiveMemberDecField(
374*d415bd75Srobert "NextOffset", getFieldRawString(ArMemHdr->NextOffset), Parent, this);
375*d415bd75Srobert }
376*d415bd75Srobert
getAccessMode() const377*d415bd75Srobert Expected<sys::fs::perms> AbstractArchiveMemberHeader::getAccessMode() const {
378*d415bd75Srobert Expected<uint64_t> AccessModeOrErr =
379*d415bd75Srobert getArchiveMemberOctField("AccessMode", getRawAccessMode(), Parent, this);
380*d415bd75Srobert if (!AccessModeOrErr)
381*d415bd75Srobert return AccessModeOrErr.takeError();
382*d415bd75Srobert return static_cast<sys::fs::perms>(*AccessModeOrErr);
38309467b48Spatrick }
38409467b48Spatrick
38509467b48Spatrick Expected<sys::TimePoint<std::chrono::seconds>>
getLastModified() const386*d415bd75Srobert AbstractArchiveMemberHeader::getLastModified() const {
387*d415bd75Srobert Expected<uint64_t> SecondsOrErr = getArchiveMemberDecField(
388*d415bd75Srobert "LastModified", getRawLastModified(), Parent, this);
389*d415bd75Srobert
390*d415bd75Srobert if (!SecondsOrErr)
391*d415bd75Srobert return SecondsOrErr.takeError();
392*d415bd75Srobert
393*d415bd75Srobert return sys::toTimePoint(*SecondsOrErr);
39409467b48Spatrick }
39509467b48Spatrick
getUID() const396*d415bd75Srobert Expected<unsigned> AbstractArchiveMemberHeader::getUID() const {
397*d415bd75Srobert StringRef User = getRawUID();
39809467b48Spatrick if (User.empty())
39909467b48Spatrick return 0;
400*d415bd75Srobert return getArchiveMemberDecField("UID", User, Parent, this);
40109467b48Spatrick }
40209467b48Spatrick
getGID() const403*d415bd75Srobert Expected<unsigned> AbstractArchiveMemberHeader::getGID() const {
404*d415bd75Srobert StringRef Group = getRawGID();
40509467b48Spatrick if (Group.empty())
40609467b48Spatrick return 0;
407*d415bd75Srobert return getArchiveMemberDecField("GID", Group, Parent, this);
40809467b48Spatrick }
409*d415bd75Srobert
isThin() const410*d415bd75Srobert Expected<bool> ArchiveMemberHeader::isThin() const {
411*d415bd75Srobert Expected<StringRef> NameOrErr = getRawName();
412*d415bd75Srobert if (!NameOrErr)
413*d415bd75Srobert return NameOrErr.takeError();
414*d415bd75Srobert StringRef Name = NameOrErr.get();
415*d415bd75Srobert return Parent->isThin() && Name != "/" && Name != "//" && Name != "/SYM64/";
416*d415bd75Srobert }
417*d415bd75Srobert
getNextChildLoc() const418*d415bd75Srobert Expected<const char *> ArchiveMemberHeader::getNextChildLoc() const {
419*d415bd75Srobert uint64_t Size = getSizeOf();
420*d415bd75Srobert Expected<bool> isThinOrErr = isThin();
421*d415bd75Srobert if (!isThinOrErr)
422*d415bd75Srobert return isThinOrErr.takeError();
423*d415bd75Srobert
424*d415bd75Srobert bool isThin = isThinOrErr.get();
425*d415bd75Srobert if (!isThin) {
426*d415bd75Srobert Expected<uint64_t> MemberSize = getSize();
427*d415bd75Srobert if (!MemberSize)
428*d415bd75Srobert return MemberSize.takeError();
429*d415bd75Srobert
430*d415bd75Srobert Size += MemberSize.get();
431*d415bd75Srobert }
432*d415bd75Srobert
433*d415bd75Srobert // If Size is odd, add 1 to make it even.
434*d415bd75Srobert const char *NextLoc =
435*d415bd75Srobert reinterpret_cast<const char *>(ArMemHdr) + alignTo(Size, 2);
436*d415bd75Srobert
437*d415bd75Srobert if (NextLoc == Parent->getMemoryBufferRef().getBufferEnd())
438*d415bd75Srobert return nullptr;
439*d415bd75Srobert
440*d415bd75Srobert return NextLoc;
441*d415bd75Srobert }
442*d415bd75Srobert
getNextChildLoc() const443*d415bd75Srobert Expected<const char *> BigArchiveMemberHeader::getNextChildLoc() const {
444*d415bd75Srobert if (getOffset() ==
445*d415bd75Srobert static_cast<const BigArchive *>(Parent)->getLastChildOffset())
446*d415bd75Srobert return nullptr;
447*d415bd75Srobert
448*d415bd75Srobert Expected<uint64_t> NextOffsetOrErr = getNextOffset();
449*d415bd75Srobert if (!NextOffsetOrErr)
450*d415bd75Srobert return NextOffsetOrErr.takeError();
451*d415bd75Srobert return Parent->getData().data() + NextOffsetOrErr.get();
45209467b48Spatrick }
45309467b48Spatrick
Child(const Archive * Parent,StringRef Data,uint16_t StartOfFile)45409467b48Spatrick Archive::Child::Child(const Archive *Parent, StringRef Data,
45509467b48Spatrick uint16_t StartOfFile)
456*d415bd75Srobert : Parent(Parent), Data(Data), StartOfFile(StartOfFile) {
457*d415bd75Srobert Header = Parent->createArchiveMemberHeader(Data.data(), Data.size(), nullptr);
458*d415bd75Srobert }
45909467b48Spatrick
Child(const Archive * Parent,const char * Start,Error * Err)46009467b48Spatrick Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
461*d415bd75Srobert : Parent(Parent) {
462*d415bd75Srobert if (!Start) {
463*d415bd75Srobert Header = nullptr;
46409467b48Spatrick return;
465*d415bd75Srobert }
466*d415bd75Srobert
467*d415bd75Srobert Header = Parent->createArchiveMemberHeader(
468*d415bd75Srobert Start,
469*d415bd75Srobert Parent ? Parent->getData().size() - (Start - Parent->getData().data())
470*d415bd75Srobert : 0,
471*d415bd75Srobert Err);
47209467b48Spatrick
47309467b48Spatrick // If we are pointed to real data, Start is not a nullptr, then there must be
47409467b48Spatrick // a non-null Err pointer available to report malformed data on. Only in
47509467b48Spatrick // the case sentinel value is being constructed is Err is permitted to be a
47609467b48Spatrick // nullptr.
47709467b48Spatrick assert(Err && "Err can't be nullptr if Start is not a nullptr");
47809467b48Spatrick
47909467b48Spatrick ErrorAsOutParameter ErrAsOutParam(Err);
48009467b48Spatrick
48109467b48Spatrick // If there was an error in the construction of the Header
48209467b48Spatrick // then just return with the error now set.
48309467b48Spatrick if (*Err)
48409467b48Spatrick return;
48509467b48Spatrick
486*d415bd75Srobert uint64_t Size = Header->getSizeOf();
48709467b48Spatrick Data = StringRef(Start, Size);
48809467b48Spatrick Expected<bool> isThinOrErr = isThinMember();
48909467b48Spatrick if (!isThinOrErr) {
49009467b48Spatrick *Err = isThinOrErr.takeError();
49109467b48Spatrick return;
49209467b48Spatrick }
49309467b48Spatrick bool isThin = isThinOrErr.get();
49409467b48Spatrick if (!isThin) {
49509467b48Spatrick Expected<uint64_t> MemberSize = getRawSize();
49609467b48Spatrick if (!MemberSize) {
49709467b48Spatrick *Err = MemberSize.takeError();
49809467b48Spatrick return;
49909467b48Spatrick }
50009467b48Spatrick Size += MemberSize.get();
50109467b48Spatrick Data = StringRef(Start, Size);
50209467b48Spatrick }
50309467b48Spatrick
50409467b48Spatrick // Setup StartOfFile and PaddingBytes.
505*d415bd75Srobert StartOfFile = Header->getSizeOf();
50609467b48Spatrick // Don't include attached name.
50709467b48Spatrick Expected<StringRef> NameOrErr = getRawName();
50809467b48Spatrick if (!NameOrErr) {
50909467b48Spatrick *Err = NameOrErr.takeError();
51009467b48Spatrick return;
51109467b48Spatrick }
51209467b48Spatrick StringRef Name = NameOrErr.get();
513*d415bd75Srobert
514*d415bd75Srobert if (Parent->kind() == Archive::K_AIXBIG) {
515*d415bd75Srobert // The actual start of the file is after the name and any necessary
516*d415bd75Srobert // even-alignment padding.
517*d415bd75Srobert StartOfFile += ((Name.size() + 1) >> 1) << 1;
518*d415bd75Srobert } else if (Name.startswith("#1/")) {
51909467b48Spatrick uint64_t NameSize;
520*d415bd75Srobert StringRef RawNameSize = Name.substr(3).rtrim(' ');
521*d415bd75Srobert if (RawNameSize.getAsInteger(10, NameSize)) {
52209467b48Spatrick uint64_t Offset = Start - Parent->getData().data();
52309467b48Spatrick *Err = malformedError("long name length characters after the #1/ are "
52473471bf0Spatrick "not all decimal numbers: '" +
525*d415bd75Srobert RawNameSize +
526*d415bd75Srobert "' for archive member header at offset " +
52709467b48Spatrick Twine(Offset));
52809467b48Spatrick return;
52909467b48Spatrick }
53009467b48Spatrick StartOfFile += NameSize;
53109467b48Spatrick }
53209467b48Spatrick }
53309467b48Spatrick
getSize() const53409467b48Spatrick Expected<uint64_t> Archive::Child::getSize() const {
535097a140dSpatrick if (Parent->IsThin)
536*d415bd75Srobert return Header->getSize();
53709467b48Spatrick return Data.size() - StartOfFile;
53809467b48Spatrick }
53909467b48Spatrick
getRawSize() const54009467b48Spatrick Expected<uint64_t> Archive::Child::getRawSize() const {
541*d415bd75Srobert return Header->getSize();
54209467b48Spatrick }
54309467b48Spatrick
isThinMember() const544*d415bd75Srobert Expected<bool> Archive::Child::isThinMember() const { return Header->isThin(); }
54509467b48Spatrick
getFullName() const54609467b48Spatrick Expected<std::string> Archive::Child::getFullName() const {
54709467b48Spatrick Expected<bool> isThin = isThinMember();
54809467b48Spatrick if (!isThin)
54909467b48Spatrick return isThin.takeError();
55009467b48Spatrick assert(isThin.get());
55109467b48Spatrick Expected<StringRef> NameOrErr = getName();
55209467b48Spatrick if (!NameOrErr)
55309467b48Spatrick return NameOrErr.takeError();
55409467b48Spatrick StringRef Name = *NameOrErr;
55509467b48Spatrick if (sys::path::is_absolute(Name))
556097a140dSpatrick return std::string(Name);
55709467b48Spatrick
55809467b48Spatrick SmallString<128> FullName = sys::path::parent_path(
55909467b48Spatrick Parent->getMemoryBufferRef().getBufferIdentifier());
56009467b48Spatrick sys::path::append(FullName, Name);
561097a140dSpatrick return std::string(FullName.str());
56209467b48Spatrick }
56309467b48Spatrick
getBuffer() const56409467b48Spatrick Expected<StringRef> Archive::Child::getBuffer() const {
56509467b48Spatrick Expected<bool> isThinOrErr = isThinMember();
56609467b48Spatrick if (!isThinOrErr)
56709467b48Spatrick return isThinOrErr.takeError();
56809467b48Spatrick bool isThin = isThinOrErr.get();
56909467b48Spatrick if (!isThin) {
570097a140dSpatrick Expected<uint64_t> Size = getSize();
57109467b48Spatrick if (!Size)
57209467b48Spatrick return Size.takeError();
57309467b48Spatrick return StringRef(Data.data() + StartOfFile, Size.get());
57409467b48Spatrick }
57509467b48Spatrick Expected<std::string> FullNameOrErr = getFullName();
57609467b48Spatrick if (!FullNameOrErr)
57709467b48Spatrick return FullNameOrErr.takeError();
57809467b48Spatrick const std::string &FullName = *FullNameOrErr;
57909467b48Spatrick ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName);
58009467b48Spatrick if (std::error_code EC = Buf.getError())
58109467b48Spatrick return errorCodeToError(EC);
58209467b48Spatrick Parent->ThinBuffers.push_back(std::move(*Buf));
58309467b48Spatrick return Parent->ThinBuffers.back()->getBuffer();
58409467b48Spatrick }
58509467b48Spatrick
getNext() const58609467b48Spatrick Expected<Archive::Child> Archive::Child::getNext() const {
587*d415bd75Srobert Expected<const char *> NextLocOrErr = Header->getNextChildLoc();
588*d415bd75Srobert if (!NextLocOrErr)
589*d415bd75Srobert return NextLocOrErr.takeError();
59009467b48Spatrick
591*d415bd75Srobert const char *NextLoc = *NextLocOrErr;
59209467b48Spatrick
59309467b48Spatrick // Check to see if this is at the end of the archive.
594*d415bd75Srobert if (NextLoc == nullptr)
59509467b48Spatrick return Child(nullptr, nullptr, nullptr);
59609467b48Spatrick
59709467b48Spatrick // Check to see if this is past the end of the archive.
59809467b48Spatrick if (NextLoc > Parent->Data.getBufferEnd()) {
59909467b48Spatrick std::string Msg("offset to next archive member past the end of the archive "
60009467b48Spatrick "after member ");
60109467b48Spatrick Expected<StringRef> NameOrErr = getName();
60209467b48Spatrick if (!NameOrErr) {
60309467b48Spatrick consumeError(NameOrErr.takeError());
60409467b48Spatrick uint64_t Offset = Data.data() - Parent->getData().data();
60509467b48Spatrick return malformedError(Msg + "at offset " + Twine(Offset));
60609467b48Spatrick } else
60709467b48Spatrick return malformedError(Msg + NameOrErr.get());
60809467b48Spatrick }
60909467b48Spatrick
61009467b48Spatrick Error Err = Error::success();
61109467b48Spatrick Child Ret(Parent, NextLoc, &Err);
61209467b48Spatrick if (Err)
61309467b48Spatrick return std::move(Err);
61409467b48Spatrick return Ret;
61509467b48Spatrick }
61609467b48Spatrick
getChildOffset() const61709467b48Spatrick uint64_t Archive::Child::getChildOffset() const {
61809467b48Spatrick const char *a = Parent->Data.getBuffer().data();
61909467b48Spatrick const char *c = Data.data();
62009467b48Spatrick uint64_t offset = c - a;
62109467b48Spatrick return offset;
62209467b48Spatrick }
62309467b48Spatrick
getName() const62409467b48Spatrick Expected<StringRef> Archive::Child::getName() const {
62509467b48Spatrick Expected<uint64_t> RawSizeOrErr = getRawSize();
62609467b48Spatrick if (!RawSizeOrErr)
62709467b48Spatrick return RawSizeOrErr.takeError();
62809467b48Spatrick uint64_t RawSize = RawSizeOrErr.get();
629*d415bd75Srobert Expected<StringRef> NameOrErr =
630*d415bd75Srobert Header->getName(Header->getSizeOf() + RawSize);
63109467b48Spatrick if (!NameOrErr)
63209467b48Spatrick return NameOrErr.takeError();
63309467b48Spatrick StringRef Name = NameOrErr.get();
63409467b48Spatrick return Name;
63509467b48Spatrick }
63609467b48Spatrick
getMemoryBufferRef() const63709467b48Spatrick Expected<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {
63809467b48Spatrick Expected<StringRef> NameOrErr = getName();
63909467b48Spatrick if (!NameOrErr)
64009467b48Spatrick return NameOrErr.takeError();
64109467b48Spatrick StringRef Name = NameOrErr.get();
64209467b48Spatrick Expected<StringRef> Buf = getBuffer();
64309467b48Spatrick if (!Buf)
64409467b48Spatrick return createFileError(Name, Buf.takeError());
64509467b48Spatrick return MemoryBufferRef(*Buf, Name);
64609467b48Spatrick }
64709467b48Spatrick
64809467b48Spatrick Expected<std::unique_ptr<Binary>>
getAsBinary(LLVMContext * Context) const64909467b48Spatrick Archive::Child::getAsBinary(LLVMContext *Context) const {
65009467b48Spatrick Expected<MemoryBufferRef> BuffOrErr = getMemoryBufferRef();
65109467b48Spatrick if (!BuffOrErr)
65209467b48Spatrick return BuffOrErr.takeError();
65309467b48Spatrick
65409467b48Spatrick auto BinaryOrErr = createBinary(BuffOrErr.get(), Context);
65509467b48Spatrick if (BinaryOrErr)
65609467b48Spatrick return std::move(*BinaryOrErr);
65709467b48Spatrick return BinaryOrErr.takeError();
65809467b48Spatrick }
65909467b48Spatrick
create(MemoryBufferRef Source)66009467b48Spatrick Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {
66109467b48Spatrick Error Err = Error::success();
662*d415bd75Srobert std::unique_ptr<Archive> Ret;
663*d415bd75Srobert StringRef Buffer = Source.getBuffer();
664*d415bd75Srobert
665*d415bd75Srobert if (Buffer.startswith(BigArchiveMagic))
666*d415bd75Srobert Ret = std::make_unique<BigArchive>(Source, Err);
667*d415bd75Srobert else
668*d415bd75Srobert Ret = std::make_unique<Archive>(Source, Err);
669*d415bd75Srobert
67009467b48Spatrick if (Err)
67109467b48Spatrick return std::move(Err);
67209467b48Spatrick return std::move(Ret);
67309467b48Spatrick }
67409467b48Spatrick
675*d415bd75Srobert std::unique_ptr<AbstractArchiveMemberHeader>
createArchiveMemberHeader(const char * RawHeaderPtr,uint64_t Size,Error * Err) const676*d415bd75Srobert Archive::createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size,
677*d415bd75Srobert Error *Err) const {
678*d415bd75Srobert ErrorAsOutParameter ErrAsOutParam(Err);
679*d415bd75Srobert if (kind() != K_AIXBIG)
680*d415bd75Srobert return std::make_unique<ArchiveMemberHeader>(this, RawHeaderPtr, Size, Err);
681*d415bd75Srobert return std::make_unique<BigArchiveMemberHeader>(this, RawHeaderPtr, Size,
682*d415bd75Srobert Err);
683*d415bd75Srobert }
684*d415bd75Srobert
getArchiveMagicLen() const685*d415bd75Srobert uint64_t Archive::getArchiveMagicLen() const {
686*d415bd75Srobert if (isThin())
687*d415bd75Srobert return sizeof(ThinArchiveMagic) - 1;
688*d415bd75Srobert
689*d415bd75Srobert if (Kind() == K_AIXBIG)
690*d415bd75Srobert return sizeof(BigArchiveMagic) - 1;
691*d415bd75Srobert
692*d415bd75Srobert return sizeof(ArchiveMagic) - 1;
693*d415bd75Srobert }
694*d415bd75Srobert
setFirstRegular(const Child & C)69509467b48Spatrick void Archive::setFirstRegular(const Child &C) {
69609467b48Spatrick FirstRegularData = C.Data;
69709467b48Spatrick FirstRegularStartOfFile = C.StartOfFile;
69809467b48Spatrick }
69909467b48Spatrick
Archive(MemoryBufferRef Source,Error & Err)70009467b48Spatrick Archive::Archive(MemoryBufferRef Source, Error &Err)
70109467b48Spatrick : Binary(Binary::ID_Archive, Source) {
70209467b48Spatrick ErrorAsOutParameter ErrAsOutParam(&Err);
70309467b48Spatrick StringRef Buffer = Data.getBuffer();
70409467b48Spatrick // Check for sufficient magic.
705*d415bd75Srobert if (Buffer.startswith(ThinArchiveMagic)) {
70609467b48Spatrick IsThin = true;
707*d415bd75Srobert } else if (Buffer.startswith(ArchiveMagic)) {
70809467b48Spatrick IsThin = false;
709*d415bd75Srobert } else if (Buffer.startswith(BigArchiveMagic)) {
710*d415bd75Srobert Format = K_AIXBIG;
711*d415bd75Srobert IsThin = false;
712*d415bd75Srobert return;
71309467b48Spatrick } else {
71409467b48Spatrick Err = make_error<GenericBinaryError>("file too small to be an archive",
71509467b48Spatrick object_error::invalid_file_type);
71609467b48Spatrick return;
71709467b48Spatrick }
71809467b48Spatrick
71909467b48Spatrick // Make sure Format is initialized before any call to
72009467b48Spatrick // ArchiveMemberHeader::getName() is made. This could be a valid empty
72109467b48Spatrick // archive which is the same in all formats. So claiming it to be gnu to is
72209467b48Spatrick // fine if not totally correct before we look for a string table or table of
72309467b48Spatrick // contents.
72409467b48Spatrick Format = K_GNU;
72509467b48Spatrick
72609467b48Spatrick // Get the special members.
72709467b48Spatrick child_iterator I = child_begin(Err, false);
72809467b48Spatrick if (Err)
72909467b48Spatrick return;
73009467b48Spatrick child_iterator E = child_end();
73109467b48Spatrick
73209467b48Spatrick // See if this is a valid empty archive and if so return.
73309467b48Spatrick if (I == E) {
73409467b48Spatrick Err = Error::success();
73509467b48Spatrick return;
73609467b48Spatrick }
73709467b48Spatrick const Child *C = &*I;
73809467b48Spatrick
73909467b48Spatrick auto Increment = [&]() {
74009467b48Spatrick ++I;
74109467b48Spatrick if (Err)
74209467b48Spatrick return true;
74309467b48Spatrick C = &*I;
74409467b48Spatrick return false;
74509467b48Spatrick };
74609467b48Spatrick
74709467b48Spatrick Expected<StringRef> NameOrErr = C->getRawName();
74809467b48Spatrick if (!NameOrErr) {
74909467b48Spatrick Err = NameOrErr.takeError();
75009467b48Spatrick return;
75109467b48Spatrick }
75209467b48Spatrick StringRef Name = NameOrErr.get();
75309467b48Spatrick
75409467b48Spatrick // Below is the pattern that is used to figure out the archive format
75509467b48Spatrick // GNU archive format
75609467b48Spatrick // First member : / (may exist, if it exists, points to the symbol table )
75709467b48Spatrick // Second member : // (may exist, if it exists, points to the string table)
75809467b48Spatrick // Note : The string table is used if the filename exceeds 15 characters
75909467b48Spatrick // BSD archive format
76009467b48Spatrick // First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table)
76109467b48Spatrick // There is no string table, if the filename exceeds 15 characters or has a
76209467b48Spatrick // embedded space, the filename has #1/<size>, The size represents the size
76309467b48Spatrick // of the filename that needs to be read after the archive header
76409467b48Spatrick // COFF archive format
76509467b48Spatrick // First member : /
76609467b48Spatrick // Second member : / (provides a directory of symbols)
76709467b48Spatrick // Third member : // (may exist, if it exists, contains the string table)
76809467b48Spatrick // Note: Microsoft PE/COFF Spec 8.3 says that the third member is present
76909467b48Spatrick // even if the string table is empty. However, lib.exe does not in fact
77009467b48Spatrick // seem to create the third member if there's no member whose filename
77109467b48Spatrick // exceeds 15 characters. So the third member is optional.
77209467b48Spatrick
77309467b48Spatrick if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {
77409467b48Spatrick if (Name == "__.SYMDEF")
77509467b48Spatrick Format = K_BSD;
77609467b48Spatrick else // Name == "__.SYMDEF_64"
77709467b48Spatrick Format = K_DARWIN64;
77809467b48Spatrick // We know that the symbol table is not an external file, but we still must
77909467b48Spatrick // check any Expected<> return value.
78009467b48Spatrick Expected<StringRef> BufOrErr = C->getBuffer();
78109467b48Spatrick if (!BufOrErr) {
78209467b48Spatrick Err = BufOrErr.takeError();
78309467b48Spatrick return;
78409467b48Spatrick }
78509467b48Spatrick SymbolTable = BufOrErr.get();
78609467b48Spatrick if (Increment())
78709467b48Spatrick return;
78809467b48Spatrick setFirstRegular(*C);
78909467b48Spatrick
79009467b48Spatrick Err = Error::success();
79109467b48Spatrick return;
79209467b48Spatrick }
79309467b48Spatrick
79409467b48Spatrick if (Name.startswith("#1/")) {
79509467b48Spatrick Format = K_BSD;
79609467b48Spatrick // We know this is BSD, so getName will work since there is no string table.
79709467b48Spatrick Expected<StringRef> NameOrErr = C->getName();
79809467b48Spatrick if (!NameOrErr) {
79909467b48Spatrick Err = NameOrErr.takeError();
80009467b48Spatrick return;
80109467b48Spatrick }
80209467b48Spatrick Name = NameOrErr.get();
80309467b48Spatrick if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
80409467b48Spatrick // We know that the symbol table is not an external file, but we still
80509467b48Spatrick // must check any Expected<> return value.
80609467b48Spatrick Expected<StringRef> BufOrErr = C->getBuffer();
80709467b48Spatrick if (!BufOrErr) {
80809467b48Spatrick Err = BufOrErr.takeError();
80909467b48Spatrick return;
81009467b48Spatrick }
81109467b48Spatrick SymbolTable = BufOrErr.get();
81209467b48Spatrick if (Increment())
81309467b48Spatrick return;
81473471bf0Spatrick } else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {
81509467b48Spatrick Format = K_DARWIN64;
81609467b48Spatrick // We know that the symbol table is not an external file, but we still
81709467b48Spatrick // must check any Expected<> return value.
81809467b48Spatrick Expected<StringRef> BufOrErr = C->getBuffer();
81909467b48Spatrick if (!BufOrErr) {
82009467b48Spatrick Err = BufOrErr.takeError();
82109467b48Spatrick return;
82209467b48Spatrick }
82309467b48Spatrick SymbolTable = BufOrErr.get();
82409467b48Spatrick if (Increment())
82509467b48Spatrick return;
82609467b48Spatrick }
82709467b48Spatrick setFirstRegular(*C);
82809467b48Spatrick return;
82909467b48Spatrick }
83009467b48Spatrick
83109467b48Spatrick // MIPS 64-bit ELF archives use a special format of a symbol table.
83209467b48Spatrick // This format is marked by `ar_name` field equals to "/SYM64/".
83309467b48Spatrick // For detailed description see page 96 in the following document:
83409467b48Spatrick // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
83509467b48Spatrick
83609467b48Spatrick bool has64SymTable = false;
83709467b48Spatrick if (Name == "/" || Name == "/SYM64/") {
83809467b48Spatrick // We know that the symbol table is not an external file, but we still
83909467b48Spatrick // must check any Expected<> return value.
84009467b48Spatrick Expected<StringRef> BufOrErr = C->getBuffer();
84109467b48Spatrick if (!BufOrErr) {
84209467b48Spatrick Err = BufOrErr.takeError();
84309467b48Spatrick return;
84409467b48Spatrick }
84509467b48Spatrick SymbolTable = BufOrErr.get();
84609467b48Spatrick if (Name == "/SYM64/")
84709467b48Spatrick has64SymTable = true;
84809467b48Spatrick
84909467b48Spatrick if (Increment())
85009467b48Spatrick return;
85109467b48Spatrick if (I == E) {
85209467b48Spatrick Err = Error::success();
85309467b48Spatrick return;
85409467b48Spatrick }
85509467b48Spatrick Expected<StringRef> NameOrErr = C->getRawName();
85609467b48Spatrick if (!NameOrErr) {
85709467b48Spatrick Err = NameOrErr.takeError();
85809467b48Spatrick return;
85909467b48Spatrick }
86009467b48Spatrick Name = NameOrErr.get();
86109467b48Spatrick }
86209467b48Spatrick
86309467b48Spatrick if (Name == "//") {
86409467b48Spatrick Format = has64SymTable ? K_GNU64 : K_GNU;
86509467b48Spatrick // The string table is never an external member, but we still
86609467b48Spatrick // must check any Expected<> return value.
86709467b48Spatrick Expected<StringRef> BufOrErr = C->getBuffer();
86809467b48Spatrick if (!BufOrErr) {
86909467b48Spatrick Err = BufOrErr.takeError();
87009467b48Spatrick return;
87109467b48Spatrick }
87209467b48Spatrick StringTable = BufOrErr.get();
87309467b48Spatrick if (Increment())
87409467b48Spatrick return;
87509467b48Spatrick setFirstRegular(*C);
87609467b48Spatrick Err = Error::success();
87709467b48Spatrick return;
87809467b48Spatrick }
87909467b48Spatrick
88009467b48Spatrick if (Name[0] != '/') {
88109467b48Spatrick Format = has64SymTable ? K_GNU64 : K_GNU;
88209467b48Spatrick setFirstRegular(*C);
88309467b48Spatrick Err = Error::success();
88409467b48Spatrick return;
88509467b48Spatrick }
88609467b48Spatrick
88709467b48Spatrick if (Name != "/") {
88809467b48Spatrick Err = errorCodeToError(object_error::parse_failed);
88909467b48Spatrick return;
89009467b48Spatrick }
89109467b48Spatrick
89209467b48Spatrick Format = K_COFF;
89309467b48Spatrick // We know that the symbol table is not an external file, but we still
89409467b48Spatrick // must check any Expected<> return value.
89509467b48Spatrick Expected<StringRef> BufOrErr = C->getBuffer();
89609467b48Spatrick if (!BufOrErr) {
89709467b48Spatrick Err = BufOrErr.takeError();
89809467b48Spatrick return;
89909467b48Spatrick }
90009467b48Spatrick SymbolTable = BufOrErr.get();
90109467b48Spatrick
90209467b48Spatrick if (Increment())
90309467b48Spatrick return;
90409467b48Spatrick
90509467b48Spatrick if (I == E) {
90609467b48Spatrick setFirstRegular(*C);
90709467b48Spatrick Err = Error::success();
90809467b48Spatrick return;
90909467b48Spatrick }
91009467b48Spatrick
91109467b48Spatrick NameOrErr = C->getRawName();
91209467b48Spatrick if (!NameOrErr) {
91309467b48Spatrick Err = NameOrErr.takeError();
91409467b48Spatrick return;
91509467b48Spatrick }
91609467b48Spatrick Name = NameOrErr.get();
91709467b48Spatrick
91809467b48Spatrick if (Name == "//") {
91909467b48Spatrick // The string table is never an external member, but we still
92009467b48Spatrick // must check any Expected<> return value.
92109467b48Spatrick Expected<StringRef> BufOrErr = C->getBuffer();
92209467b48Spatrick if (!BufOrErr) {
92309467b48Spatrick Err = BufOrErr.takeError();
92409467b48Spatrick return;
92509467b48Spatrick }
92609467b48Spatrick StringTable = BufOrErr.get();
92709467b48Spatrick if (Increment())
92809467b48Spatrick return;
92909467b48Spatrick }
93009467b48Spatrick
93109467b48Spatrick setFirstRegular(*C);
93209467b48Spatrick Err = Error::success();
93309467b48Spatrick }
93409467b48Spatrick
getDefaultKindForHost()935*d415bd75Srobert object::Archive::Kind Archive::getDefaultKindForHost() {
936*d415bd75Srobert Triple HostTriple(sys::getProcessTriple());
937*d415bd75Srobert return HostTriple.isOSDarwin()
938*d415bd75Srobert ? object::Archive::K_DARWIN
939*d415bd75Srobert : (HostTriple.isOSAIX() ? object::Archive::K_AIXBIG
940*d415bd75Srobert : object::Archive::K_GNU);
941*d415bd75Srobert }
942*d415bd75Srobert
child_begin(Error & Err,bool SkipInternal) const94309467b48Spatrick Archive::child_iterator Archive::child_begin(Error &Err,
94409467b48Spatrick bool SkipInternal) const {
94509467b48Spatrick if (isEmpty())
94609467b48Spatrick return child_end();
94709467b48Spatrick
94809467b48Spatrick if (SkipInternal)
94909467b48Spatrick return child_iterator::itr(
95009467b48Spatrick Child(this, FirstRegularData, FirstRegularStartOfFile), Err);
95109467b48Spatrick
952*d415bd75Srobert const char *Loc = Data.getBufferStart() + getFirstChildOffset();
95309467b48Spatrick Child C(this, Loc, &Err);
95409467b48Spatrick if (Err)
95509467b48Spatrick return child_end();
95609467b48Spatrick return child_iterator::itr(C, Err);
95709467b48Spatrick }
95809467b48Spatrick
child_end() const95909467b48Spatrick Archive::child_iterator Archive::child_end() const {
96009467b48Spatrick return child_iterator::end(Child(nullptr, nullptr, nullptr));
96109467b48Spatrick }
96209467b48Spatrick
getName() const96309467b48Spatrick StringRef Archive::Symbol::getName() const {
96409467b48Spatrick return Parent->getSymbolTable().begin() + StringIndex;
96509467b48Spatrick }
96609467b48Spatrick
getMember() const96709467b48Spatrick Expected<Archive::Child> Archive::Symbol::getMember() const {
96809467b48Spatrick const char *Buf = Parent->getSymbolTable().begin();
96909467b48Spatrick const char *Offsets = Buf;
970*d415bd75Srobert if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64 ||
971*d415bd75Srobert Parent->kind() == K_AIXBIG)
97209467b48Spatrick Offsets += sizeof(uint64_t);
97309467b48Spatrick else
97409467b48Spatrick Offsets += sizeof(uint32_t);
97509467b48Spatrick uint64_t Offset = 0;
97609467b48Spatrick if (Parent->kind() == K_GNU) {
97709467b48Spatrick Offset = read32be(Offsets + SymbolIndex * 4);
978*d415bd75Srobert } else if (Parent->kind() == K_GNU64 || Parent->kind() == K_AIXBIG) {
97909467b48Spatrick Offset = read64be(Offsets + SymbolIndex * 8);
98009467b48Spatrick } else if (Parent->kind() == K_BSD) {
98109467b48Spatrick // The SymbolIndex is an index into the ranlib structs that start at
98209467b48Spatrick // Offsets (the first uint32_t is the number of bytes of the ranlib
98309467b48Spatrick // structs). The ranlib structs are a pair of uint32_t's the first
98409467b48Spatrick // being a string table offset and the second being the offset into
98509467b48Spatrick // the archive of the member that defines the symbol. Which is what
98609467b48Spatrick // is needed here.
98709467b48Spatrick Offset = read32le(Offsets + SymbolIndex * 8 + 4);
98809467b48Spatrick } else if (Parent->kind() == K_DARWIN64) {
98909467b48Spatrick // The SymbolIndex is an index into the ranlib_64 structs that start at
99009467b48Spatrick // Offsets (the first uint64_t is the number of bytes of the ranlib_64
99109467b48Spatrick // structs). The ranlib_64 structs are a pair of uint64_t's the first
99209467b48Spatrick // being a string table offset and the second being the offset into
99309467b48Spatrick // the archive of the member that defines the symbol. Which is what
99409467b48Spatrick // is needed here.
99509467b48Spatrick Offset = read64le(Offsets + SymbolIndex * 16 + 8);
99609467b48Spatrick } else {
99709467b48Spatrick // Skip offsets.
99809467b48Spatrick uint32_t MemberCount = read32le(Buf);
99909467b48Spatrick Buf += MemberCount * 4 + 4;
100009467b48Spatrick
100109467b48Spatrick uint32_t SymbolCount = read32le(Buf);
100209467b48Spatrick if (SymbolIndex >= SymbolCount)
100309467b48Spatrick return errorCodeToError(object_error::parse_failed);
100409467b48Spatrick
100509467b48Spatrick // Skip SymbolCount to get to the indices table.
100609467b48Spatrick const char *Indices = Buf + 4;
100709467b48Spatrick
100809467b48Spatrick // Get the index of the offset in the file member offset table for this
100909467b48Spatrick // symbol.
101009467b48Spatrick uint16_t OffsetIndex = read16le(Indices + SymbolIndex * 2);
101109467b48Spatrick // Subtract 1 since OffsetIndex is 1 based.
101209467b48Spatrick --OffsetIndex;
101309467b48Spatrick
101409467b48Spatrick if (OffsetIndex >= MemberCount)
101509467b48Spatrick return errorCodeToError(object_error::parse_failed);
101609467b48Spatrick
101709467b48Spatrick Offset = read32le(Offsets + OffsetIndex * 4);
101809467b48Spatrick }
101909467b48Spatrick
102009467b48Spatrick const char *Loc = Parent->getData().begin() + Offset;
102109467b48Spatrick Error Err = Error::success();
102209467b48Spatrick Child C(Parent, Loc, &Err);
102309467b48Spatrick if (Err)
102409467b48Spatrick return std::move(Err);
102509467b48Spatrick return C;
102609467b48Spatrick }
102709467b48Spatrick
getNext() const102809467b48Spatrick Archive::Symbol Archive::Symbol::getNext() const {
102909467b48Spatrick Symbol t(*this);
103009467b48Spatrick if (Parent->kind() == K_BSD) {
103109467b48Spatrick // t.StringIndex is an offset from the start of the __.SYMDEF or
103209467b48Spatrick // "__.SYMDEF SORTED" member into the string table for the ranlib
103309467b48Spatrick // struct indexed by t.SymbolIndex . To change t.StringIndex to the
103409467b48Spatrick // offset in the string table for t.SymbolIndex+1 we subtract the
103509467b48Spatrick // its offset from the start of the string table for t.SymbolIndex
103609467b48Spatrick // and add the offset of the string table for t.SymbolIndex+1.
103709467b48Spatrick
103809467b48Spatrick // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
103909467b48Spatrick // which is the number of bytes of ranlib structs that follow. The ranlib
104009467b48Spatrick // structs are a pair of uint32_t's the first being a string table offset
104109467b48Spatrick // and the second being the offset into the archive of the member that
104209467b48Spatrick // define the symbol. After that the next uint32_t is the byte count of
104309467b48Spatrick // the string table followed by the string table.
104409467b48Spatrick const char *Buf = Parent->getSymbolTable().begin();
104509467b48Spatrick uint32_t RanlibCount = 0;
104609467b48Spatrick RanlibCount = read32le(Buf) / 8;
104709467b48Spatrick // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount)
104809467b48Spatrick // don't change the t.StringIndex as we don't want to reference a ranlib
104909467b48Spatrick // past RanlibCount.
105009467b48Spatrick if (t.SymbolIndex + 1 < RanlibCount) {
105109467b48Spatrick const char *Ranlibs = Buf + 4;
105209467b48Spatrick uint32_t CurRanStrx = 0;
105309467b48Spatrick uint32_t NextRanStrx = 0;
105409467b48Spatrick CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8);
105509467b48Spatrick NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8);
105609467b48Spatrick t.StringIndex -= CurRanStrx;
105709467b48Spatrick t.StringIndex += NextRanStrx;
105809467b48Spatrick }
105909467b48Spatrick } else {
106009467b48Spatrick // Go to one past next null.
106109467b48Spatrick t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1;
106209467b48Spatrick }
106309467b48Spatrick ++t.SymbolIndex;
106409467b48Spatrick return t;
106509467b48Spatrick }
106609467b48Spatrick
symbol_begin() const106709467b48Spatrick Archive::symbol_iterator Archive::symbol_begin() const {
106809467b48Spatrick if (!hasSymbolTable())
106909467b48Spatrick return symbol_iterator(Symbol(this, 0, 0));
107009467b48Spatrick
107109467b48Spatrick const char *buf = getSymbolTable().begin();
107209467b48Spatrick if (kind() == K_GNU) {
107309467b48Spatrick uint32_t symbol_count = 0;
107409467b48Spatrick symbol_count = read32be(buf);
107509467b48Spatrick buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
107609467b48Spatrick } else if (kind() == K_GNU64) {
107709467b48Spatrick uint64_t symbol_count = read64be(buf);
107809467b48Spatrick buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));
107909467b48Spatrick } else if (kind() == K_BSD) {
108009467b48Spatrick // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
108109467b48Spatrick // which is the number of bytes of ranlib structs that follow. The ranlib
108209467b48Spatrick // structs are a pair of uint32_t's the first being a string table offset
108309467b48Spatrick // and the second being the offset into the archive of the member that
108409467b48Spatrick // define the symbol. After that the next uint32_t is the byte count of
108509467b48Spatrick // the string table followed by the string table.
108609467b48Spatrick uint32_t ranlib_count = 0;
108709467b48Spatrick ranlib_count = read32le(buf) / 8;
108809467b48Spatrick const char *ranlibs = buf + 4;
108909467b48Spatrick uint32_t ran_strx = 0;
109009467b48Spatrick ran_strx = read32le(ranlibs);
109109467b48Spatrick buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t))));
109209467b48Spatrick // Skip the byte count of the string table.
109309467b48Spatrick buf += sizeof(uint32_t);
109409467b48Spatrick buf += ran_strx;
109509467b48Spatrick } else if (kind() == K_DARWIN64) {
109609467b48Spatrick // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t
109709467b48Spatrick // which is the number of bytes of ranlib_64 structs that follow. The
109809467b48Spatrick // ranlib_64 structs are a pair of uint64_t's the first being a string
109909467b48Spatrick // table offset and the second being the offset into the archive of the
110009467b48Spatrick // member that define the symbol. After that the next uint64_t is the byte
110109467b48Spatrick // count of the string table followed by the string table.
110209467b48Spatrick uint64_t ranlib_count = 0;
110309467b48Spatrick ranlib_count = read64le(buf) / 16;
110409467b48Spatrick const char *ranlibs = buf + 8;
110509467b48Spatrick uint64_t ran_strx = 0;
110609467b48Spatrick ran_strx = read64le(ranlibs);
110709467b48Spatrick buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t))));
110809467b48Spatrick // Skip the byte count of the string table.
110909467b48Spatrick buf += sizeof(uint64_t);
111009467b48Spatrick buf += ran_strx;
1111*d415bd75Srobert } else if (kind() == K_AIXBIG) {
1112*d415bd75Srobert buf = getStringTable().begin();
111309467b48Spatrick } else {
111409467b48Spatrick uint32_t member_count = 0;
111509467b48Spatrick uint32_t symbol_count = 0;
111609467b48Spatrick member_count = read32le(buf);
111709467b48Spatrick buf += 4 + (member_count * 4); // Skip offsets.
111809467b48Spatrick symbol_count = read32le(buf);
111909467b48Spatrick buf += 4 + (symbol_count * 2); // Skip indices.
112009467b48Spatrick }
112109467b48Spatrick uint32_t string_start_offset = buf - getSymbolTable().begin();
112209467b48Spatrick return symbol_iterator(Symbol(this, 0, string_start_offset));
112309467b48Spatrick }
112409467b48Spatrick
symbol_end() const112509467b48Spatrick Archive::symbol_iterator Archive::symbol_end() const {
112609467b48Spatrick return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0));
112709467b48Spatrick }
112809467b48Spatrick
getNumberOfSymbols() const112909467b48Spatrick uint32_t Archive::getNumberOfSymbols() const {
113009467b48Spatrick if (!hasSymbolTable())
113109467b48Spatrick return 0;
113209467b48Spatrick const char *buf = getSymbolTable().begin();
113309467b48Spatrick if (kind() == K_GNU)
113409467b48Spatrick return read32be(buf);
1135*d415bd75Srobert if (kind() == K_GNU64 || kind() == K_AIXBIG)
113609467b48Spatrick return read64be(buf);
113709467b48Spatrick if (kind() == K_BSD)
113809467b48Spatrick return read32le(buf) / 8;
113909467b48Spatrick if (kind() == K_DARWIN64)
114009467b48Spatrick return read64le(buf) / 16;
114109467b48Spatrick uint32_t member_count = 0;
114209467b48Spatrick member_count = read32le(buf);
114309467b48Spatrick buf += 4 + (member_count * 4); // Skip offsets.
114409467b48Spatrick return read32le(buf);
114509467b48Spatrick }
114609467b48Spatrick
findSym(StringRef name) const1147*d415bd75Srobert Expected<std::optional<Archive::Child>> Archive::findSym(StringRef name) const {
114809467b48Spatrick Archive::symbol_iterator bs = symbol_begin();
114909467b48Spatrick Archive::symbol_iterator es = symbol_end();
115009467b48Spatrick
115109467b48Spatrick for (; bs != es; ++bs) {
115209467b48Spatrick StringRef SymName = bs->getName();
115309467b48Spatrick if (SymName == name) {
115409467b48Spatrick if (auto MemberOrErr = bs->getMember())
115509467b48Spatrick return Child(*MemberOrErr);
115609467b48Spatrick else
115709467b48Spatrick return MemberOrErr.takeError();
115809467b48Spatrick }
115909467b48Spatrick }
1160*d415bd75Srobert return std::nullopt;
116109467b48Spatrick }
116209467b48Spatrick
116309467b48Spatrick // Returns true if archive file contains no member file.
isEmpty() const1164*d415bd75Srobert bool Archive::isEmpty() const {
1165*d415bd75Srobert return Data.getBufferSize() == getArchiveMagicLen();
1166*d415bd75Srobert }
116709467b48Spatrick
hasSymbolTable() const116809467b48Spatrick bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }
1169*d415bd75Srobert
BigArchive(MemoryBufferRef Source,Error & Err)1170*d415bd75Srobert BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)
1171*d415bd75Srobert : Archive(Source, Err) {
1172*d415bd75Srobert ErrorAsOutParameter ErrAsOutParam(&Err);
1173*d415bd75Srobert StringRef Buffer = Data.getBuffer();
1174*d415bd75Srobert ArFixLenHdr = reinterpret_cast<const FixLenHdr *>(Buffer.data());
1175*d415bd75Srobert
1176*d415bd75Srobert StringRef RawOffset = getFieldRawString(ArFixLenHdr->FirstChildOffset);
1177*d415bd75Srobert if (RawOffset.getAsInteger(10, FirstChildOffset))
1178*d415bd75Srobert // TODO: Out-of-line.
1179*d415bd75Srobert Err = malformedError("malformed AIX big archive: first member offset \"" +
1180*d415bd75Srobert RawOffset + "\" is not a number");
1181*d415bd75Srobert
1182*d415bd75Srobert RawOffset = getFieldRawString(ArFixLenHdr->LastChildOffset);
1183*d415bd75Srobert if (RawOffset.getAsInteger(10, LastChildOffset))
1184*d415bd75Srobert // TODO: Out-of-line.
1185*d415bd75Srobert Err = malformedError("malformed AIX big archive: last member offset \"" +
1186*d415bd75Srobert RawOffset + "\" is not a number");
1187*d415bd75Srobert
1188*d415bd75Srobert // Calculate the global symbol table.
1189*d415bd75Srobert uint64_t GlobSymOffset = 0;
1190*d415bd75Srobert RawOffset = getFieldRawString(ArFixLenHdr->GlobSymOffset);
1191*d415bd75Srobert if (RawOffset.getAsInteger(10, GlobSymOffset))
1192*d415bd75Srobert // TODO: add test case.
1193*d415bd75Srobert Err = malformedError(
1194*d415bd75Srobert "malformed AIX big archive: global symbol table offset \"" + RawOffset +
1195*d415bd75Srobert "\" is not a number");
1196*d415bd75Srobert
1197*d415bd75Srobert if (Err)
1198*d415bd75Srobert return;
1199*d415bd75Srobert
1200*d415bd75Srobert if (GlobSymOffset > 0) {
1201*d415bd75Srobert uint64_t BufferSize = Data.getBufferSize();
1202*d415bd75Srobert uint64_t GlobalSymTblContentOffset =
1203*d415bd75Srobert GlobSymOffset + sizeof(BigArMemHdrType);
1204*d415bd75Srobert if (GlobalSymTblContentOffset > BufferSize) {
1205*d415bd75Srobert Err = malformedError("global symbol table header at offset 0x" +
1206*d415bd75Srobert Twine::utohexstr(GlobSymOffset) + " and size 0x" +
1207*d415bd75Srobert Twine::utohexstr(sizeof(BigArMemHdrType)) +
1208*d415bd75Srobert " goes past the end of file");
1209*d415bd75Srobert return;
1210*d415bd75Srobert }
1211*d415bd75Srobert
1212*d415bd75Srobert const char *GlobSymTblLoc = Data.getBufferStart() + GlobSymOffset;
1213*d415bd75Srobert const BigArMemHdrType *GlobalSymHdr =
1214*d415bd75Srobert reinterpret_cast<const BigArMemHdrType *>(GlobSymTblLoc);
1215*d415bd75Srobert RawOffset = getFieldRawString(GlobalSymHdr->Size);
1216*d415bd75Srobert uint64_t Size;
1217*d415bd75Srobert if (RawOffset.getAsInteger(10, Size)) {
1218*d415bd75Srobert // TODO: add test case.
1219*d415bd75Srobert Err = malformedError(
1220*d415bd75Srobert "malformed AIX big archive: global symbol table size \"" + RawOffset +
1221*d415bd75Srobert "\" is not a number");
1222*d415bd75Srobert return;
1223*d415bd75Srobert }
1224*d415bd75Srobert if (GlobalSymTblContentOffset + Size > BufferSize) {
1225*d415bd75Srobert Err = malformedError("global symbol table content at offset 0x" +
1226*d415bd75Srobert Twine::utohexstr(GlobalSymTblContentOffset) +
1227*d415bd75Srobert " and size 0x" + Twine::utohexstr(Size) +
1228*d415bd75Srobert " goes past the end of file");
1229*d415bd75Srobert return;
1230*d415bd75Srobert }
1231*d415bd75Srobert SymbolTable = StringRef(GlobSymTblLoc + sizeof(BigArMemHdrType), Size);
1232*d415bd75Srobert unsigned SymNum = getNumberOfSymbols();
1233*d415bd75Srobert unsigned SymOffsetsSize = 8 * (SymNum + 1);
1234*d415bd75Srobert uint64_t SymbolTableStringSize = Size - SymOffsetsSize;
1235*d415bd75Srobert StringTable =
1236*d415bd75Srobert StringRef(GlobSymTblLoc + sizeof(BigArMemHdrType) + SymOffsetsSize,
1237*d415bd75Srobert SymbolTableStringSize);
1238*d415bd75Srobert }
1239*d415bd75Srobert
1240*d415bd75Srobert child_iterator I = child_begin(Err, false);
1241*d415bd75Srobert if (Err)
1242*d415bd75Srobert return;
1243*d415bd75Srobert child_iterator E = child_end();
1244*d415bd75Srobert if (I == E) {
1245*d415bd75Srobert Err = Error::success();
1246*d415bd75Srobert return;
1247*d415bd75Srobert }
1248*d415bd75Srobert setFirstRegular(*I);
1249*d415bd75Srobert Err = Error::success();
1250*d415bd75Srobert }
1251