1 //===- Archive.cpp - ar File Format implementation --------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the ArchiveObjectFile class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/Object/Archive.h"
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/ADT/Twine.h"
17 #include "llvm/Support/Endian.h"
18 #include "llvm/Support/MemoryBuffer.h"
19 #include "llvm/Support/Path.h"
20 
21 using namespace llvm;
22 using namespace object;
23 using namespace llvm::support::endian;
24 
25 static const char *const Magic = "!<arch>\n";
26 static const char *const ThinMagic = "!<thin>\n";
27 
28 void Archive::anchor() { }
29 
30 static Error
31 malformedError(Twine Msg) {
32   std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")";
33   return make_error<GenericBinaryError>(std::move(StringMsg),
34                                         object_error::parse_failed);
35 }
36 
37 ArchiveMemberHeader::ArchiveMemberHeader(const Archive *Parent,
38                                          const char *RawHeaderPtr,
39                                          uint64_t Size, Error *Err)
40     : Parent(Parent),
41       ArMemHdr(reinterpret_cast<const ArMemHdrType *>(RawHeaderPtr)) {
42   if (RawHeaderPtr == nullptr)
43     return;
44   ErrorAsOutParameter ErrAsOutParam(Err);
45 
46   // TODO: For errors messages with the ArchiveMemberHeader class use the
47   // archive member name instead of the the offset to the archive member header.
48   // When there is also error getting the member name then use the offset to
49   // the member in the message.
50 
51   if (Size < sizeof(ArMemHdrType)) {
52     if (Err) {
53       uint64_t Offset = RawHeaderPtr - Parent->getData().data();
54       *Err = malformedError("remaining size of archive too small for next "
55                             "archive member header at offset " +
56                             Twine(Offset));
57     }
58     return;
59   }
60   if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') {
61     if (Err) {
62       std::string Buf;
63       raw_string_ostream OS(Buf);
64       OS.write_escaped(llvm::StringRef(ArMemHdr->Terminator,
65                                        sizeof(ArMemHdr->Terminator)));
66       OS.flush();
67       uint64_t Offset = RawHeaderPtr - Parent->getData().data();
68       *Err = malformedError("terminator characters in archive member \"" + Buf +
69                             "\" not the correct \"`\\n\" values for the "
70                             "archive member header at offset " + Twine(Offset));
71     }
72     return;
73   }
74 }
75 
76 StringRef ArchiveMemberHeader::getName() const {
77   char EndCond;
78   if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#')
79     EndCond = ' ';
80   else
81     EndCond = '/';
82   llvm::StringRef::size_type end =
83       llvm::StringRef(ArMemHdr->Name, sizeof(ArMemHdr->Name)).find(EndCond);
84   if (end == llvm::StringRef::npos)
85     end = sizeof(ArMemHdr->Name);
86   assert(end <= sizeof(ArMemHdr->Name) && end > 0);
87   // Don't include the EndCond if there is one.
88   return llvm::StringRef(ArMemHdr->Name, end);
89 }
90 
91 Expected<uint32_t> ArchiveMemberHeader::getSize() const {
92   uint32_t Ret;
93   if (llvm::StringRef(ArMemHdr->Size,
94         sizeof(ArMemHdr->Size)).rtrim(" ").getAsInteger(10, Ret)) {
95     std::string Buf;
96     raw_string_ostream OS(Buf);
97     OS.write_escaped(llvm::StringRef(ArMemHdr->Size,
98                                      sizeof(ArMemHdr->Size)).rtrim(" "));
99     OS.flush();
100     uint64_t Offset = reinterpret_cast<const char *>(ArMemHdr) -
101                       Parent->getData().data();
102     return malformedError("characters in size field in archive header are not "
103                           "all decimal numbers: '" + Buf + "' for archive "
104                           "member header at offset " + Twine(Offset));
105   }
106   return Ret;
107 }
108 
109 sys::fs::perms ArchiveMemberHeader::getAccessMode() const {
110   unsigned Ret;
111   if (StringRef(ArMemHdr->AccessMode,
112                 sizeof(ArMemHdr->AccessMode)).rtrim(' ').getAsInteger(8, Ret))
113     llvm_unreachable("Access mode is not an octal number.");
114   return static_cast<sys::fs::perms>(Ret);
115 }
116 
117 sys::TimeValue ArchiveMemberHeader::getLastModified() const {
118   unsigned Seconds;
119   if (StringRef(ArMemHdr->LastModified,
120                 sizeof(ArMemHdr->LastModified)).rtrim(' ')
121           .getAsInteger(10, Seconds))
122     llvm_unreachable("Last modified time not a decimal number.");
123 
124   sys::TimeValue Ret;
125   Ret.fromEpochTime(Seconds);
126   return Ret;
127 }
128 
129 unsigned ArchiveMemberHeader::getUID() const {
130   unsigned Ret;
131   StringRef User = StringRef(ArMemHdr->UID, sizeof(ArMemHdr->UID)).rtrim(' ');
132   if (User.empty())
133     return 0;
134   if (User.getAsInteger(10, Ret))
135     llvm_unreachable("UID time not a decimal number.");
136   return Ret;
137 }
138 
139 unsigned ArchiveMemberHeader::getGID() const {
140   unsigned Ret;
141   StringRef Group = StringRef(ArMemHdr->GID, sizeof(ArMemHdr->GID)).rtrim(' ');
142   if (Group.empty())
143     return 0;
144   if (Group.getAsInteger(10, Ret))
145     llvm_unreachable("GID time not a decimal number.");
146   return Ret;
147 }
148 
149 Archive::Child::Child(const Archive *Parent, StringRef Data,
150                       uint16_t StartOfFile)
151     : Parent(Parent), Header(Parent, Data.data(), Data.size(), nullptr),
152       Data(Data), StartOfFile(StartOfFile) {
153 }
154 
155 Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
156     : Parent(Parent), Header(Parent, Start, Parent->getData().size() -
157                              (Start - Parent->getData().data()), Err) {
158   if (!Start)
159     return;
160   ErrorAsOutParameter ErrAsOutParam(Err);
161 
162   // If there was an error in the construction of the Header and we were passed
163   // Err that is not nullptr then just return with the error now set.
164   if (Err && *Err)
165     return;
166 
167   uint64_t Size = Header.getSizeOf();
168   Data = StringRef(Start, Size);
169   if (!isThinMember()) {
170     Expected<uint64_t> MemberSize = getRawSize();
171     if (!MemberSize) {
172       if (Err)
173         *Err = MemberSize.takeError();
174       return;
175     }
176     Size += MemberSize.get();
177     Data = StringRef(Start, Size);
178   }
179 
180   // Setup StartOfFile and PaddingBytes.
181   StartOfFile = Header.getSizeOf();
182   // Don't include attached name.
183   StringRef Name = getRawName();
184   if (Name.startswith("#1/")) {
185     uint64_t NameSize;
186     if (Name.substr(3).rtrim(' ').getAsInteger(10, NameSize))
187       llvm_unreachable("Long name length is not an integer");
188     StartOfFile += NameSize;
189   }
190 }
191 
192 Expected<uint64_t> Archive::Child::getSize() const {
193   if (Parent->IsThin) {
194     Expected<uint32_t> Size = Header.getSize();
195     if (!Size)
196       return Size.takeError();
197     return Size.get();
198   }
199   return Data.size() - StartOfFile;
200 }
201 
202 Expected<uint64_t> Archive::Child::getRawSize() const {
203   return Header.getSize();
204 }
205 
206 bool Archive::Child::isThinMember() const {
207   StringRef Name = Header.getName();
208   return Parent->IsThin && Name != "/" && Name != "//";
209 }
210 
211 ErrorOr<std::string> Archive::Child::getFullName() const {
212   assert(isThinMember());
213   ErrorOr<StringRef> NameOrErr = getName();
214   if (std::error_code EC = NameOrErr.getError())
215     return EC;
216   StringRef Name = *NameOrErr;
217   if (sys::path::is_absolute(Name))
218     return Name;
219 
220   SmallString<128> FullName = sys::path::parent_path(
221       Parent->getMemoryBufferRef().getBufferIdentifier());
222   sys::path::append(FullName, Name);
223   return StringRef(FullName);
224 }
225 
226 ErrorOr<StringRef> Archive::Child::getBuffer() const {
227   if (!isThinMember()) {
228     Expected<uint32_t> Size = getSize();
229     if (!Size)
230       return errorToErrorCode(Size.takeError());
231     return StringRef(Data.data() + StartOfFile, Size.get());
232   }
233   ErrorOr<std::string> FullNameOrEr = getFullName();
234   if (std::error_code EC = FullNameOrEr.getError())
235     return EC;
236   const std::string &FullName = *FullNameOrEr;
237   ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName);
238   if (std::error_code EC = Buf.getError())
239     return EC;
240   Parent->ThinBuffers.push_back(std::move(*Buf));
241   return Parent->ThinBuffers.back()->getBuffer();
242 }
243 
244 Expected<Archive::Child> Archive::Child::getNext() const {
245   size_t SpaceToSkip = Data.size();
246   // If it's odd, add 1 to make it even.
247   if (SpaceToSkip & 1)
248     ++SpaceToSkip;
249 
250   const char *NextLoc = Data.data() + SpaceToSkip;
251 
252   // Check to see if this is at the end of the archive.
253   if (NextLoc == Parent->Data.getBufferEnd())
254     return Child(Parent, nullptr, nullptr);
255 
256   // Check to see if this is past the end of the archive.
257   if (NextLoc > Parent->Data.getBufferEnd()) {
258     Twine Msg("offset to next archive member past the end of the archive after "
259               "member ");
260     ErrorOr<StringRef> NameOrErr = getName();
261     if (NameOrErr.getError()) {
262       uint64_t Offset = Data.data() - Parent->getData().data();
263       return malformedError(Msg + "at offset " + Twine(Offset));
264     } else
265       return malformedError(Msg + Twine(NameOrErr.get()));
266   }
267 
268   Error Err;
269   Child Ret(Parent, NextLoc, &Err);
270   if (Err)
271     return std::move(Err);
272   return Ret;
273 }
274 
275 uint64_t Archive::Child::getChildOffset() const {
276   const char *a = Parent->Data.getBuffer().data();
277   const char *c = Data.data();
278   uint64_t offset = c - a;
279   return offset;
280 }
281 
282 ErrorOr<StringRef> Archive::Child::getName() const {
283   StringRef name = getRawName();
284   // Check if it's a special name.
285   if (name[0] == '/') {
286     if (name.size() == 1) // Linker member.
287       return name;
288     if (name.size() == 2 && name[1] == '/') // String table.
289       return name;
290     // It's a long name.
291     // Get the offset.
292     std::size_t offset;
293     if (name.substr(1).rtrim(' ').getAsInteger(10, offset))
294       llvm_unreachable("Long name offset is not an integer");
295 
296     // Verify it.
297     if (offset >= Parent->StringTable.size())
298       return object_error::parse_failed;
299     const char *addr = Parent->StringTable.begin() + offset;
300 
301     // GNU long file names end with a "/\n".
302     if (Parent->kind() == K_GNU || Parent->kind() == K_MIPS64) {
303       StringRef::size_type End = StringRef(addr).find('\n');
304       return StringRef(addr, End - 1);
305     }
306     return StringRef(addr);
307   } else if (name.startswith("#1/")) {
308     uint64_t name_size;
309     if (name.substr(3).rtrim(' ').getAsInteger(10, name_size))
310       llvm_unreachable("Long name length is not an ingeter");
311     return Data.substr(Header.getSizeOf(), name_size).rtrim('\0');
312   } else {
313     // It is not a long name so trim the blanks at the end of the name.
314     if (name[name.size() - 1] != '/') {
315       return name.rtrim(' ');
316     }
317   }
318   // It's a simple name.
319   if (name[name.size() - 1] == '/')
320     return name.substr(0, name.size() - 1);
321   return name;
322 }
323 
324 ErrorOr<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const {
325   ErrorOr<StringRef> NameOrErr = getName();
326   if (std::error_code EC = NameOrErr.getError())
327     return EC;
328   StringRef Name = NameOrErr.get();
329   ErrorOr<StringRef> Buf = getBuffer();
330   if (std::error_code EC = Buf.getError())
331     return EC;
332   return MemoryBufferRef(*Buf, Name);
333 }
334 
335 Expected<std::unique_ptr<Binary>>
336 Archive::Child::getAsBinary(LLVMContext *Context) const {
337   ErrorOr<MemoryBufferRef> BuffOrErr = getMemoryBufferRef();
338   if (std::error_code EC = BuffOrErr.getError())
339     return errorCodeToError(EC);
340 
341   auto BinaryOrErr = createBinary(BuffOrErr.get(), Context);
342   if (BinaryOrErr)
343     return std::move(*BinaryOrErr);
344   return BinaryOrErr.takeError();
345 }
346 
347 Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {
348   Error Err;
349   std::unique_ptr<Archive> Ret(new Archive(Source, Err));
350   if (Err)
351     return std::move(Err);
352   return std::move(Ret);
353 }
354 
355 void Archive::setFirstRegular(const Child &C) {
356   FirstRegularData = C.Data;
357   FirstRegularStartOfFile = C.StartOfFile;
358 }
359 
360 Archive::Archive(MemoryBufferRef Source, Error &Err)
361     : Binary(Binary::ID_Archive, Source) {
362   ErrorAsOutParameter ErrAsOutParam(&Err);
363   StringRef Buffer = Data.getBuffer();
364   // Check for sufficient magic.
365   if (Buffer.startswith(ThinMagic)) {
366     IsThin = true;
367   } else if (Buffer.startswith(Magic)) {
368     IsThin = false;
369   } else {
370     Err = make_error<GenericBinaryError>("File too small to be an archive",
371                                          object_error::invalid_file_type);
372     return;
373   }
374 
375   // Get the special members.
376   child_iterator I = child_begin(Err, false);
377   if (Err)
378     return;
379   child_iterator E = child_end();
380 
381   // This is at least a valid empty archive. Since an empty archive is the
382   // same in all formats, just claim it to be gnu to make sure Format is
383   // initialized.
384   Format = K_GNU;
385 
386   if (I == E) {
387     Err = Error::success();
388     return;
389   }
390   const Child *C = &*I;
391 
392   auto Increment = [&]() {
393     ++I;
394     if (Err)
395       return true;
396     C = &*I;
397     return false;
398   };
399 
400   StringRef Name = C->getRawName();
401 
402   // Below is the pattern that is used to figure out the archive format
403   // GNU archive format
404   //  First member : / (may exist, if it exists, points to the symbol table )
405   //  Second member : // (may exist, if it exists, points to the string table)
406   //  Note : The string table is used if the filename exceeds 15 characters
407   // BSD archive format
408   //  First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table)
409   //  There is no string table, if the filename exceeds 15 characters or has a
410   //  embedded space, the filename has #1/<size>, The size represents the size
411   //  of the filename that needs to be read after the archive header
412   // COFF archive format
413   //  First member : /
414   //  Second member : / (provides a directory of symbols)
415   //  Third member : // (may exist, if it exists, contains the string table)
416   //  Note: Microsoft PE/COFF Spec 8.3 says that the third member is present
417   //  even if the string table is empty. However, lib.exe does not in fact
418   //  seem to create the third member if there's no member whose filename
419   //  exceeds 15 characters. So the third member is optional.
420 
421   if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {
422     if (Name == "__.SYMDEF")
423       Format = K_BSD;
424     else // Name == "__.SYMDEF_64"
425       Format = K_DARWIN64;
426     // We know that the symbol table is not an external file, so we just assert
427     // there is no error.
428     SymbolTable = *C->getBuffer();
429     if (Increment())
430       return;
431     setFirstRegular(*C);
432 
433     Err = Error::success();
434     return;
435   }
436 
437   if (Name.startswith("#1/")) {
438     Format = K_BSD;
439     // We know this is BSD, so getName will work since there is no string table.
440     ErrorOr<StringRef> NameOrErr = C->getName();
441     if (auto ec = NameOrErr.getError()) {
442       Err = errorCodeToError(ec);
443       return;
444     }
445     Name = NameOrErr.get();
446     if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
447       // We know that the symbol table is not an external file, so we just
448       // assert there is no error.
449       SymbolTable = *C->getBuffer();
450       if (Increment())
451         return;
452     }
453     else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {
454       Format = K_DARWIN64;
455       // We know that the symbol table is not an external file, so we just
456       // assert there is no error.
457       SymbolTable = *C->getBuffer();
458       if (Increment())
459         return;
460     }
461     setFirstRegular(*C);
462     return;
463   }
464 
465   // MIPS 64-bit ELF archives use a special format of a symbol table.
466   // This format is marked by `ar_name` field equals to "/SYM64/".
467   // For detailed description see page 96 in the following document:
468   // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
469 
470   bool has64SymTable = false;
471   if (Name == "/" || Name == "/SYM64/") {
472     // We know that the symbol table is not an external file, so we just assert
473     // there is no error.
474     SymbolTable = *C->getBuffer();
475     if (Name == "/SYM64/")
476       has64SymTable = true;
477 
478     if (Increment())
479       return;
480     if (I == E) {
481       Err = Error::success();
482       return;
483     }
484     Name = C->getRawName();
485   }
486 
487   if (Name == "//") {
488     Format = has64SymTable ? K_MIPS64 : K_GNU;
489     // The string table is never an external member, so we just assert on the
490     // ErrorOr.
491     StringTable = *C->getBuffer();
492     if (Increment())
493       return;
494     setFirstRegular(*C);
495     Err = Error::success();
496     return;
497   }
498 
499   if (Name[0] != '/') {
500     Format = has64SymTable ? K_MIPS64 : K_GNU;
501     setFirstRegular(*C);
502     Err = Error::success();
503     return;
504   }
505 
506   if (Name != "/") {
507     Err = errorCodeToError(object_error::parse_failed);
508     return;
509   }
510 
511   Format = K_COFF;
512   // We know that the symbol table is not an external file, so we just assert
513   // there is no error.
514   SymbolTable = *C->getBuffer();
515 
516   if (Increment())
517     return;
518 
519   if (I == E) {
520     setFirstRegular(*C);
521     Err = Error::success();
522     return;
523   }
524 
525   Name = C->getRawName();
526 
527   if (Name == "//") {
528     // The string table is never an external member, so we just assert on the
529     // ErrorOr.
530     StringTable = *C->getBuffer();
531     if (Increment())
532       return;
533   }
534 
535   setFirstRegular(*C);
536   Err = Error::success();
537 }
538 
539 Archive::child_iterator Archive::child_begin(Error &Err,
540                                              bool SkipInternal) const {
541   if (Data.getBufferSize() == 8) // empty archive.
542     return child_end();
543 
544   if (SkipInternal)
545     return child_iterator(Child(this, FirstRegularData,
546                                 FirstRegularStartOfFile),
547                           &Err);
548 
549   const char *Loc = Data.getBufferStart() + strlen(Magic);
550   Child C(this, Loc, &Err);
551   if (Err)
552     return child_end();
553   return child_iterator(C, &Err);
554 }
555 
556 Archive::child_iterator Archive::child_end() const {
557   return child_iterator(Child(this, nullptr, nullptr), nullptr);
558 }
559 
560 StringRef Archive::Symbol::getName() const {
561   return Parent->getSymbolTable().begin() + StringIndex;
562 }
563 
564 ErrorOr<Archive::Child> Archive::Symbol::getMember() const {
565   const char *Buf = Parent->getSymbolTable().begin();
566   const char *Offsets = Buf;
567   if (Parent->kind() == K_MIPS64 || Parent->kind() == K_DARWIN64)
568     Offsets += sizeof(uint64_t);
569   else
570     Offsets += sizeof(uint32_t);
571   uint32_t Offset = 0;
572   if (Parent->kind() == K_GNU) {
573     Offset = read32be(Offsets + SymbolIndex * 4);
574   } else if (Parent->kind() == K_MIPS64) {
575     Offset = read64be(Offsets + SymbolIndex * 8);
576   } else if (Parent->kind() == K_BSD) {
577     // The SymbolIndex is an index into the ranlib structs that start at
578     // Offsets (the first uint32_t is the number of bytes of the ranlib
579     // structs).  The ranlib structs are a pair of uint32_t's the first
580     // being a string table offset and the second being the offset into
581     // the archive of the member that defines the symbol.  Which is what
582     // is needed here.
583     Offset = read32le(Offsets + SymbolIndex * 8 + 4);
584   } else if (Parent->kind() == K_DARWIN64) {
585     // The SymbolIndex is an index into the ranlib_64 structs that start at
586     // Offsets (the first uint64_t is the number of bytes of the ranlib_64
587     // structs).  The ranlib_64 structs are a pair of uint64_t's the first
588     // being a string table offset and the second being the offset into
589     // the archive of the member that defines the symbol.  Which is what
590     // is needed here.
591     Offset = read64le(Offsets + SymbolIndex * 16 + 8);
592   } else {
593     // Skip offsets.
594     uint32_t MemberCount = read32le(Buf);
595     Buf += MemberCount * 4 + 4;
596 
597     uint32_t SymbolCount = read32le(Buf);
598     if (SymbolIndex >= SymbolCount)
599       return object_error::parse_failed;
600 
601     // Skip SymbolCount to get to the indices table.
602     const char *Indices = Buf + 4;
603 
604     // Get the index of the offset in the file member offset table for this
605     // symbol.
606     uint16_t OffsetIndex = read16le(Indices + SymbolIndex * 2);
607     // Subtract 1 since OffsetIndex is 1 based.
608     --OffsetIndex;
609 
610     if (OffsetIndex >= MemberCount)
611       return object_error::parse_failed;
612 
613     Offset = read32le(Offsets + OffsetIndex * 4);
614   }
615 
616   const char *Loc = Parent->getData().begin() + Offset;
617   Error Err;
618   Child C(Parent, Loc, &Err);
619   if (Err)
620     return errorToErrorCode(std::move(Err));
621   return C;
622 }
623 
624 Archive::Symbol Archive::Symbol::getNext() const {
625   Symbol t(*this);
626   if (Parent->kind() == K_BSD) {
627     // t.StringIndex is an offset from the start of the __.SYMDEF or
628     // "__.SYMDEF SORTED" member into the string table for the ranlib
629     // struct indexed by t.SymbolIndex .  To change t.StringIndex to the
630     // offset in the string table for t.SymbolIndex+1 we subtract the
631     // its offset from the start of the string table for t.SymbolIndex
632     // and add the offset of the string table for t.SymbolIndex+1.
633 
634     // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
635     // which is the number of bytes of ranlib structs that follow.  The ranlib
636     // structs are a pair of uint32_t's the first being a string table offset
637     // and the second being the offset into the archive of the member that
638     // define the symbol. After that the next uint32_t is the byte count of
639     // the string table followed by the string table.
640     const char *Buf = Parent->getSymbolTable().begin();
641     uint32_t RanlibCount = 0;
642     RanlibCount = read32le(Buf) / 8;
643     // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount)
644     // don't change the t.StringIndex as we don't want to reference a ranlib
645     // past RanlibCount.
646     if (t.SymbolIndex + 1 < RanlibCount) {
647       const char *Ranlibs = Buf + 4;
648       uint32_t CurRanStrx = 0;
649       uint32_t NextRanStrx = 0;
650       CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8);
651       NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8);
652       t.StringIndex -= CurRanStrx;
653       t.StringIndex += NextRanStrx;
654     }
655   } else {
656     // Go to one past next null.
657     t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1;
658   }
659   ++t.SymbolIndex;
660   return t;
661 }
662 
663 Archive::symbol_iterator Archive::symbol_begin() const {
664   if (!hasSymbolTable())
665     return symbol_iterator(Symbol(this, 0, 0));
666 
667   const char *buf = getSymbolTable().begin();
668   if (kind() == K_GNU) {
669     uint32_t symbol_count = 0;
670     symbol_count = read32be(buf);
671     buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
672   } else if (kind() == K_MIPS64) {
673     uint64_t symbol_count = read64be(buf);
674     buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));
675   } else if (kind() == K_BSD) {
676     // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t
677     // which is the number of bytes of ranlib structs that follow.  The ranlib
678     // structs are a pair of uint32_t's the first being a string table offset
679     // and the second being the offset into the archive of the member that
680     // define the symbol. After that the next uint32_t is the byte count of
681     // the string table followed by the string table.
682     uint32_t ranlib_count = 0;
683     ranlib_count = read32le(buf) / 8;
684     const char *ranlibs = buf + 4;
685     uint32_t ran_strx = 0;
686     ran_strx = read32le(ranlibs);
687     buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t))));
688     // Skip the byte count of the string table.
689     buf += sizeof(uint32_t);
690     buf += ran_strx;
691   } else if (kind() == K_DARWIN64) {
692     // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t
693     // which is the number of bytes of ranlib_64 structs that follow.  The
694     // ranlib_64 structs are a pair of uint64_t's the first being a string
695     // table offset and the second being the offset into the archive of the
696     // member that define the symbol. After that the next uint64_t is the byte
697     // count of the string table followed by the string table.
698     uint64_t ranlib_count = 0;
699     ranlib_count = read64le(buf) / 16;
700     const char *ranlibs = buf + 8;
701     uint64_t ran_strx = 0;
702     ran_strx = read64le(ranlibs);
703     buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t))));
704     // Skip the byte count of the string table.
705     buf += sizeof(uint64_t);
706     buf += ran_strx;
707   } else {
708     uint32_t member_count = 0;
709     uint32_t symbol_count = 0;
710     member_count = read32le(buf);
711     buf += 4 + (member_count * 4); // Skip offsets.
712     symbol_count = read32le(buf);
713     buf += 4 + (symbol_count * 2); // Skip indices.
714   }
715   uint32_t string_start_offset = buf - getSymbolTable().begin();
716   return symbol_iterator(Symbol(this, 0, string_start_offset));
717 }
718 
719 Archive::symbol_iterator Archive::symbol_end() const {
720   return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0));
721 }
722 
723 uint32_t Archive::getNumberOfSymbols() const {
724   if (!hasSymbolTable())
725     return 0;
726   const char *buf = getSymbolTable().begin();
727   if (kind() == K_GNU)
728     return read32be(buf);
729   if (kind() == K_MIPS64)
730     return read64be(buf);
731   if (kind() == K_BSD)
732     return read32le(buf) / 8;
733   if (kind() == K_DARWIN64)
734     return read64le(buf) / 16;
735   uint32_t member_count = 0;
736   member_count = read32le(buf);
737   buf += 4 + (member_count * 4); // Skip offsets.
738   return read32le(buf);
739 }
740 
741 Expected<Optional<Archive::Child>> Archive::findSym(StringRef name) const {
742   Archive::symbol_iterator bs = symbol_begin();
743   Archive::symbol_iterator es = symbol_end();
744 
745   for (; bs != es; ++bs) {
746     StringRef SymName = bs->getName();
747     if (SymName == name) {
748       if (auto MemberOrErr = bs->getMember())
749         return Child(*MemberOrErr);
750       else
751         return errorCodeToError(MemberOrErr.getError());
752     }
753   }
754   return Optional<Child>();
755 }
756 
757 bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }
758