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