xref: /llvm-project/llvm/lib/Object/ArchiveWriter.cpp (revision 111fcb0df02db3db8bed1d5db6d911b7ce544d92)
1 //===- ArchiveWriter.cpp - ar File Format implementation --------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the writeArchive function.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/Object/ArchiveWriter.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/StringMap.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/BinaryFormat/Magic.h"
18 #include "llvm/IR/LLVMContext.h"
19 #include "llvm/Object/Archive.h"
20 #include "llvm/Object/COFF.h"
21 #include "llvm/Object/Error.h"
22 #include "llvm/Object/IRObjectFile.h"
23 #include "llvm/Object/MachO.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/Object/SymbolicFile.h"
26 #include "llvm/Object/XCOFFObjectFile.h"
27 #include "llvm/Support/Alignment.h"
28 #include "llvm/Support/EndianStream.h"
29 #include "llvm/Support/Errc.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/Format.h"
32 #include "llvm/Support/MathExtras.h"
33 #include "llvm/Support/Path.h"
34 #include "llvm/Support/SmallVectorMemoryBuffer.h"
35 #include "llvm/Support/raw_ostream.h"
36 
37 #include <cerrno>
38 #include <map>
39 
40 #if !defined(_MSC_VER) && !defined(__MINGW32__)
41 #include <unistd.h>
42 #else
43 #include <io.h>
44 #endif
45 
46 using namespace llvm;
47 using namespace llvm::object;
48 
49 struct SymMap {
50   bool UseECMap;
51   std::map<std::string, uint16_t> Map;
52   std::map<std::string, uint16_t> ECMap;
53 };
54 
55 NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef)
56     : Buf(MemoryBuffer::getMemBuffer(BufRef, false)),
57       MemberName(BufRef.getBufferIdentifier()) {}
58 
59 object::Archive::Kind NewArchiveMember::detectKindFromObject() const {
60   auto MemBufferRef = this->Buf->getMemBufferRef();
61   Expected<std::unique_ptr<object::ObjectFile>> OptionalObject =
62       object::ObjectFile::createObjectFile(MemBufferRef);
63 
64   if (OptionalObject)
65     return isa<object::MachOObjectFile>(**OptionalObject)
66                ? object::Archive::K_DARWIN
67                : (isa<object::XCOFFObjectFile>(**OptionalObject)
68                       ? object::Archive::K_AIXBIG
69                       : object::Archive::K_GNU);
70 
71   // Squelch the error in case we had a non-object file.
72   consumeError(OptionalObject.takeError());
73 
74   // If we're adding a bitcode file to the archive, detect the Archive kind
75   // based on the target triple.
76   LLVMContext Context;
77   if (identify_magic(MemBufferRef.getBuffer()) == file_magic::bitcode) {
78     if (auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
79             MemBufferRef, file_magic::bitcode, &Context)) {
80       auto &IRObject = cast<object::IRObjectFile>(**ObjOrErr);
81       auto TargetTriple = Triple(IRObject.getTargetTriple());
82       return TargetTriple.isOSDarwin()
83                  ? object::Archive::K_DARWIN
84                  : (TargetTriple.isOSAIX() ? object::Archive::K_AIXBIG
85                                            : object::Archive::K_GNU);
86     } else {
87       // Squelch the error in case this was not a SymbolicFile.
88       consumeError(ObjOrErr.takeError());
89     }
90   }
91 
92   return object::Archive::getDefaultKindForHost();
93 }
94 
95 Expected<NewArchiveMember>
96 NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,
97                                bool Deterministic) {
98   Expected<llvm::MemoryBufferRef> BufOrErr = OldMember.getMemoryBufferRef();
99   if (!BufOrErr)
100     return BufOrErr.takeError();
101 
102   NewArchiveMember M;
103   M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
104   M.MemberName = M.Buf->getBufferIdentifier();
105   if (!Deterministic) {
106     auto ModTimeOrErr = OldMember.getLastModified();
107     if (!ModTimeOrErr)
108       return ModTimeOrErr.takeError();
109     M.ModTime = ModTimeOrErr.get();
110     Expected<unsigned> UIDOrErr = OldMember.getUID();
111     if (!UIDOrErr)
112       return UIDOrErr.takeError();
113     M.UID = UIDOrErr.get();
114     Expected<unsigned> GIDOrErr = OldMember.getGID();
115     if (!GIDOrErr)
116       return GIDOrErr.takeError();
117     M.GID = GIDOrErr.get();
118     Expected<sys::fs::perms> AccessModeOrErr = OldMember.getAccessMode();
119     if (!AccessModeOrErr)
120       return AccessModeOrErr.takeError();
121     M.Perms = AccessModeOrErr.get();
122   }
123   return std::move(M);
124 }
125 
126 Expected<NewArchiveMember> NewArchiveMember::getFile(StringRef FileName,
127                                                      bool Deterministic) {
128   sys::fs::file_status Status;
129   auto FDOrErr = sys::fs::openNativeFileForRead(FileName);
130   if (!FDOrErr)
131     return FDOrErr.takeError();
132   sys::fs::file_t FD = *FDOrErr;
133   assert(FD != sys::fs::kInvalidFile);
134 
135   if (auto EC = sys::fs::status(FD, Status))
136     return errorCodeToError(EC);
137 
138   // Opening a directory doesn't make sense. Let it fail.
139   // Linux cannot open directories with open(2), although
140   // cygwin and *bsd can.
141   if (Status.type() == sys::fs::file_type::directory_file)
142     return errorCodeToError(make_error_code(errc::is_a_directory));
143 
144   ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
145       MemoryBuffer::getOpenFile(FD, FileName, Status.getSize(), false);
146   if (!MemberBufferOrErr)
147     return errorCodeToError(MemberBufferOrErr.getError());
148 
149   if (auto EC = sys::fs::closeFile(FD))
150     return errorCodeToError(EC);
151 
152   NewArchiveMember M;
153   M.Buf = std::move(*MemberBufferOrErr);
154   M.MemberName = M.Buf->getBufferIdentifier();
155   if (!Deterministic) {
156     M.ModTime = std::chrono::time_point_cast<std::chrono::seconds>(
157         Status.getLastModificationTime());
158     M.UID = Status.getUser();
159     M.GID = Status.getGroup();
160     M.Perms = Status.permissions();
161   }
162   return std::move(M);
163 }
164 
165 template <typename T>
166 static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size) {
167   uint64_t OldPos = OS.tell();
168   OS << Data;
169   unsigned SizeSoFar = OS.tell() - OldPos;
170   assert(SizeSoFar <= Size && "Data doesn't fit in Size");
171   OS.indent(Size - SizeSoFar);
172 }
173 
174 static bool isDarwin(object::Archive::Kind Kind) {
175   return Kind == object::Archive::K_DARWIN ||
176          Kind == object::Archive::K_DARWIN64;
177 }
178 
179 static bool isAIXBigArchive(object::Archive::Kind Kind) {
180   return Kind == object::Archive::K_AIXBIG;
181 }
182 
183 static bool isCOFFArchive(object::Archive::Kind Kind) {
184   return Kind == object::Archive::K_COFF;
185 }
186 
187 static bool isBSDLike(object::Archive::Kind Kind) {
188   switch (Kind) {
189   case object::Archive::K_GNU:
190   case object::Archive::K_GNU64:
191   case object::Archive::K_AIXBIG:
192   case object::Archive::K_COFF:
193     return false;
194   case object::Archive::K_BSD:
195   case object::Archive::K_DARWIN:
196   case object::Archive::K_DARWIN64:
197     return true;
198   }
199   llvm_unreachable("not supported for writting");
200 }
201 
202 template <class T>
203 static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val) {
204   support::endian::write(Out, Val,
205                          isBSDLike(Kind) ? support::little : support::big);
206 }
207 
208 template <class T> static void printLE(raw_ostream &Out, T Val) {
209   support::endian::write(Out, Val, support::little);
210 }
211 
212 static void printRestOfMemberHeader(
213     raw_ostream &Out, const sys::TimePoint<std::chrono::seconds> &ModTime,
214     unsigned UID, unsigned GID, unsigned Perms, uint64_t Size) {
215   printWithSpacePadding(Out, sys::toTimeT(ModTime), 12);
216 
217   // The format has only 6 chars for uid and gid. Truncate if the provided
218   // values don't fit.
219   printWithSpacePadding(Out, UID % 1000000, 6);
220   printWithSpacePadding(Out, GID % 1000000, 6);
221 
222   printWithSpacePadding(Out, format("%o", Perms), 8);
223   printWithSpacePadding(Out, Size, 10);
224   Out << "`\n";
225 }
226 
227 static void
228 printGNUSmallMemberHeader(raw_ostream &Out, StringRef Name,
229                           const sys::TimePoint<std::chrono::seconds> &ModTime,
230                           unsigned UID, unsigned GID, unsigned Perms,
231                           uint64_t Size) {
232   printWithSpacePadding(Out, Twine(Name) + "/", 16);
233   printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
234 }
235 
236 static void
237 printBSDMemberHeader(raw_ostream &Out, uint64_t Pos, StringRef Name,
238                      const sys::TimePoint<std::chrono::seconds> &ModTime,
239                      unsigned UID, unsigned GID, unsigned Perms, uint64_t Size) {
240   uint64_t PosAfterHeader = Pos + 60 + Name.size();
241   // Pad so that even 64 bit object files are aligned.
242   unsigned Pad = offsetToAlignment(PosAfterHeader, Align(8));
243   unsigned NameWithPadding = Name.size() + Pad;
244   printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
245   printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
246                           NameWithPadding + Size);
247   Out << Name;
248   while (Pad--)
249     Out.write(uint8_t(0));
250 }
251 
252 static void
253 printBigArchiveMemberHeader(raw_ostream &Out, StringRef Name,
254                             const sys::TimePoint<std::chrono::seconds> &ModTime,
255                             unsigned UID, unsigned GID, unsigned Perms,
256                             uint64_t Size, uint64_t PrevOffset,
257                             uint64_t NextOffset) {
258   unsigned NameLen = Name.size();
259 
260   printWithSpacePadding(Out, Size, 20);           // File member size
261   printWithSpacePadding(Out, NextOffset, 20);     // Next member header offset
262   printWithSpacePadding(Out, PrevOffset, 20); // Previous member header offset
263   printWithSpacePadding(Out, sys::toTimeT(ModTime), 12); // File member date
264   // The big archive format has 12 chars for uid and gid.
265   printWithSpacePadding(Out, UID % 1000000000000, 12);   // UID
266   printWithSpacePadding(Out, GID % 1000000000000, 12);   // GID
267   printWithSpacePadding(Out, format("%o", Perms), 12);   // Permission
268   printWithSpacePadding(Out, NameLen, 4);                // Name length
269   if (NameLen) {
270     printWithSpacePadding(Out, Name, NameLen); // Name
271     if (NameLen % 2)
272       Out.write(uint8_t(0)); // Null byte padding
273   }
274   Out << "`\n"; // Terminator
275 }
276 
277 static bool useStringTable(bool Thin, StringRef Name) {
278   return Thin || Name.size() >= 16 || Name.contains('/');
279 }
280 
281 static bool is64BitKind(object::Archive::Kind Kind) {
282   switch (Kind) {
283   case object::Archive::K_GNU:
284   case object::Archive::K_BSD:
285   case object::Archive::K_DARWIN:
286   case object::Archive::K_COFF:
287     return false;
288   case object::Archive::K_AIXBIG:
289   case object::Archive::K_DARWIN64:
290   case object::Archive::K_GNU64:
291     return true;
292   }
293   llvm_unreachable("not supported for writting");
294 }
295 
296 static void
297 printMemberHeader(raw_ostream &Out, uint64_t Pos, raw_ostream &StringTable,
298                   StringMap<uint64_t> &MemberNames, object::Archive::Kind Kind,
299                   bool Thin, const NewArchiveMember &M,
300                   sys::TimePoint<std::chrono::seconds> ModTime, uint64_t Size) {
301   if (isBSDLike(Kind))
302     return printBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID,
303                                 M.Perms, Size);
304   if (!useStringTable(Thin, M.MemberName))
305     return printGNUSmallMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
306                                      M.Perms, Size);
307   Out << '/';
308   uint64_t NamePos;
309   if (Thin) {
310     NamePos = StringTable.tell();
311     StringTable << M.MemberName << "/\n";
312   } else {
313     auto Insertion = MemberNames.insert({M.MemberName, uint64_t(0)});
314     if (Insertion.second) {
315       Insertion.first->second = StringTable.tell();
316       StringTable << M.MemberName;
317       if (isCOFFArchive(Kind))
318         StringTable << '\0';
319       else
320         StringTable << "/\n";
321     }
322     NamePos = Insertion.first->second;
323   }
324   printWithSpacePadding(Out, NamePos, 15);
325   printRestOfMemberHeader(Out, ModTime, M.UID, M.GID, M.Perms, Size);
326 }
327 
328 namespace {
329 struct MemberData {
330   std::vector<unsigned> Symbols;
331   std::string Header;
332   StringRef Data;
333   StringRef Padding;
334 };
335 } // namespace
336 
337 static MemberData computeStringTable(StringRef Names) {
338   unsigned Size = Names.size();
339   unsigned Pad = offsetToAlignment(Size, Align(2));
340   std::string Header;
341   raw_string_ostream Out(Header);
342   printWithSpacePadding(Out, "//", 48);
343   printWithSpacePadding(Out, Size + Pad, 10);
344   Out << "`\n";
345   Out.flush();
346   return {{}, std::move(Header), Names, Pad ? "\n" : ""};
347 }
348 
349 static sys::TimePoint<std::chrono::seconds> now(bool Deterministic) {
350   using namespace std::chrono;
351 
352   if (!Deterministic)
353     return time_point_cast<seconds>(system_clock::now());
354   return sys::TimePoint<seconds>();
355 }
356 
357 static bool isArchiveSymbol(const object::BasicSymbolRef &S) {
358   Expected<uint32_t> SymFlagsOrErr = S.getFlags();
359   if (!SymFlagsOrErr)
360     // TODO: Actually report errors helpfully.
361     report_fatal_error(SymFlagsOrErr.takeError());
362   if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific)
363     return false;
364   if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global))
365     return false;
366   if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined)
367     return false;
368   return true;
369 }
370 
371 static void printNBits(raw_ostream &Out, object::Archive::Kind Kind,
372                        uint64_t Val) {
373   if (is64BitKind(Kind))
374     print<uint64_t>(Out, Kind, Val);
375   else
376     print<uint32_t>(Out, Kind, Val);
377 }
378 
379 static uint64_t computeSymbolTableSize(object::Archive::Kind Kind,
380                                        uint64_t NumSyms, uint64_t OffsetSize,
381                                        uint64_t StringTableSize,
382                                        uint32_t *Padding = nullptr) {
383   assert((OffsetSize == 4 || OffsetSize == 8) && "Unsupported OffsetSize");
384   uint64_t Size = OffsetSize; // Number of entries
385   if (isBSDLike(Kind))
386     Size += NumSyms * OffsetSize * 2; // Table
387   else
388     Size += NumSyms * OffsetSize; // Table
389   if (isBSDLike(Kind))
390     Size += OffsetSize; // byte count
391   Size += StringTableSize;
392   // ld64 expects the members to be 8-byte aligned for 64-bit content and at
393   // least 4-byte aligned for 32-bit content.  Opt for the larger encoding
394   // uniformly.
395   // We do this for all bsd formats because it simplifies aligning members.
396   // For the big archive format, the symbol table is the last member, so there
397   // is no need to align.
398   uint32_t Pad = isAIXBigArchive(Kind)
399                      ? 0
400                      : offsetToAlignment(Size, Align(isBSDLike(Kind) ? 8 : 2));
401 
402   Size += Pad;
403   if (Padding)
404     *Padding = Pad;
405   return Size;
406 }
407 
408 static uint64_t computeSymbolMapSize(uint64_t NumObj, SymMap &SymMap,
409                                      uint32_t *Padding = nullptr) {
410   uint64_t Size = sizeof(uint32_t) * 2; // Number of symbols and objects entries
411   Size += NumObj * sizeof(uint32_t);    // Offset table
412 
413   for (auto S : SymMap.Map)
414     Size += sizeof(uint16_t) + S.first.length() + 1;
415 
416   uint32_t Pad = offsetToAlignment(Size, Align(2));
417   Size += Pad;
418   if (Padding)
419     *Padding = Pad;
420   return Size;
421 }
422 
423 static uint64_t computeECSymbolsSize(SymMap &SymMap,
424                                      uint32_t *Padding = nullptr) {
425   uint64_t Size = sizeof(uint32_t); // Number of symbols
426 
427   for (auto S : SymMap.ECMap)
428     Size += sizeof(uint16_t) + S.first.length() + 1;
429 
430   uint32_t Pad = offsetToAlignment(Size, Align(2));
431   Size += Pad;
432   if (Padding)
433     *Padding = Pad;
434   return Size;
435 }
436 
437 static void writeSymbolTableHeader(raw_ostream &Out, object::Archive::Kind Kind,
438                                    bool Deterministic, uint64_t Size,
439                                    uint64_t PrevMemberOffset = 0,
440                                    uint64_t NextMemberOffset = 0) {
441   if (isBSDLike(Kind)) {
442     const char *Name = is64BitKind(Kind) ? "__.SYMDEF_64" : "__.SYMDEF";
443     printBSDMemberHeader(Out, Out.tell(), Name, now(Deterministic), 0, 0, 0,
444                          Size);
445   } else if (isAIXBigArchive(Kind)) {
446     printBigArchiveMemberHeader(Out, "", now(Deterministic), 0, 0, 0, Size,
447                                 PrevMemberOffset, NextMemberOffset);
448   } else {
449     const char *Name = is64BitKind(Kind) ? "/SYM64" : "";
450     printGNUSmallMemberHeader(Out, Name, now(Deterministic), 0, 0, 0, Size);
451   }
452 }
453 
454 static uint64_t computeHeadersSize(object::Archive::Kind Kind,
455                                    uint64_t NumMembers,
456                                    uint64_t StringMemberSize, uint64_t NumSyms,
457                                    uint64_t SymNamesSize, SymMap *SymMap) {
458   uint32_t OffsetSize = is64BitKind(Kind) ? 8 : 4;
459   uint64_t SymtabSize =
460       computeSymbolTableSize(Kind, NumSyms, OffsetSize, SymNamesSize);
461   auto computeSymbolTableHeaderSize = [=] {
462     SmallString<0> TmpBuf;
463     raw_svector_ostream Tmp(TmpBuf);
464     writeSymbolTableHeader(Tmp, Kind, true, SymtabSize);
465     return TmpBuf.size();
466   };
467   uint32_t HeaderSize = computeSymbolTableHeaderSize();
468   uint64_t Size = strlen("!<arch>\n") + HeaderSize + SymtabSize;
469 
470   if (SymMap) {
471     Size += HeaderSize + computeSymbolMapSize(NumMembers, *SymMap);
472     if (SymMap->ECMap.size())
473       Size += HeaderSize + computeECSymbolsSize(*SymMap);
474   }
475 
476   return Size + StringMemberSize;
477 }
478 
479 static Expected<std::unique_ptr<SymbolicFile>>
480 getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context) {
481   const file_magic Type = identify_magic(Buf.getBuffer());
482   // Don't attempt to read non-symbolic file types.
483   if (!object::SymbolicFile::isSymbolicFile(Type, &Context))
484     return nullptr;
485   if (Type == file_magic::bitcode) {
486     auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
487         Buf, file_magic::bitcode, &Context);
488     if (!ObjOrErr)
489       return ObjOrErr.takeError();
490     return std::move(*ObjOrErr);
491   } else {
492     auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf);
493     if (!ObjOrErr)
494       return ObjOrErr.takeError();
495     return std::move(*ObjOrErr);
496   }
497 }
498 
499 static Expected<bool> is64BitSymbolicFile(const StringRef &ObjStringRef) {
500   MemoryBufferRef ObjMbf(ObjStringRef, "");
501   // In the scenario when LLVMContext is populated SymbolicFile will contain a
502   // reference to it, thus SymbolicFile should be destroyed first.
503   LLVMContext Context;
504   Expected<std::unique_ptr<SymbolicFile>> ObjOrErr =
505       getSymbolicFile(ObjMbf, Context);
506   if (!ObjOrErr)
507     return ObjOrErr.takeError();
508 
509   // Treat non-symbolic file types as not 64-bits.
510   if (!*ObjOrErr)
511     return false;
512 
513   return (*ObjOrErr)->is64Bit();
514 }
515 
516 static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
517                              bool Deterministic, ArrayRef<MemberData> Members,
518                              StringRef StringTable, uint64_t MembersOffset,
519                              unsigned NumSyms, uint64_t PrevMemberOffset = 0,
520                              uint64_t NextMemberOffset = 0,
521                              bool Is64Bit = false) {
522   // We don't write a symbol table on an archive with no members -- except on
523   // Darwin, where the linker will abort unless the archive has a symbol table.
524   if (StringTable.empty() && !isDarwin(Kind) && !isCOFFArchive(Kind))
525     return;
526 
527   uint64_t OffsetSize = is64BitKind(Kind) ? 8 : 4;
528   uint32_t Pad;
529   uint64_t Size = computeSymbolTableSize(Kind, NumSyms, OffsetSize,
530                                          StringTable.size(), &Pad);
531   writeSymbolTableHeader(Out, Kind, Deterministic, Size, PrevMemberOffset,
532                          NextMemberOffset);
533 
534   if (isBSDLike(Kind))
535     printNBits(Out, Kind, NumSyms * 2 * OffsetSize);
536   else
537     printNBits(Out, Kind, NumSyms);
538 
539   uint64_t Pos = MembersOffset;
540   for (const MemberData &M : Members) {
541     if (isAIXBigArchive(Kind)) {
542       Expected<bool> Is64BitOrErr = is64BitSymbolicFile(M.Data);
543       // If there is an error, the error will have been emitted when
544       // 'computeMemberData' called the 'getSymbol' function, so don't need to
545       // handle it here.
546       if (!Is64BitOrErr)
547         cantFail(Is64BitOrErr.takeError());
548       if (*Is64BitOrErr != Is64Bit) {
549         Pos += M.Header.size() + M.Data.size() + M.Padding.size();
550         continue;
551       }
552     }
553 
554     for (unsigned StringOffset : M.Symbols) {
555       if (isBSDLike(Kind))
556         printNBits(Out, Kind, StringOffset);
557       printNBits(Out, Kind, Pos); // member offset
558     }
559     Pos += M.Header.size() + M.Data.size() + M.Padding.size();
560   }
561 
562   if (isBSDLike(Kind))
563     // byte count of the string table
564     printNBits(Out, Kind, StringTable.size());
565   Out << StringTable;
566 
567   while (Pad--)
568     Out.write(uint8_t(0));
569 }
570 
571 static void writeSymbolMap(raw_ostream &Out, object::Archive::Kind Kind,
572                            bool Deterministic, ArrayRef<MemberData> Members,
573                            SymMap &SymMap, uint64_t MembersOffset) {
574   uint32_t Pad;
575   uint64_t Size = computeSymbolMapSize(Members.size(), SymMap, &Pad);
576   writeSymbolTableHeader(Out, Kind, Deterministic, Size, 0);
577 
578   uint32_t Pos = MembersOffset;
579 
580   printLE<uint32_t>(Out, Members.size());
581   for (const MemberData &M : Members) {
582     printLE(Out, Pos); // member offset
583     Pos += M.Header.size() + M.Data.size() + M.Padding.size();
584   }
585 
586   printLE<uint32_t>(Out, SymMap.Map.size());
587 
588   for (auto S : SymMap.Map)
589     printLE(Out, S.second);
590   for (auto S : SymMap.Map)
591     Out << S.first << '\0';
592 
593   while (Pad--)
594     Out.write(uint8_t(0));
595 }
596 
597 static void writeECSymbols(raw_ostream &Out, object::Archive::Kind Kind,
598                            bool Deterministic, ArrayRef<MemberData> Members,
599                            SymMap &SymMap) {
600   uint32_t Pad;
601   uint64_t Size = computeECSymbolsSize(SymMap, &Pad);
602   printGNUSmallMemberHeader(Out, "/<ECSYMBOLS>", now(Deterministic), 0, 0, 0,
603                             Size);
604 
605   printLE<uint32_t>(Out, SymMap.ECMap.size());
606 
607   for (auto S : SymMap.ECMap)
608     printLE(Out, S.second);
609   for (auto S : SymMap.ECMap)
610     Out << S.first << '\0';
611   while (Pad--)
612     Out.write(uint8_t(0));
613 }
614 
615 static bool isECObject(object::SymbolicFile &Obj) {
616   if (Obj.isCOFF())
617     return cast<llvm::object::COFFObjectFile>(&Obj)->getMachine() !=
618            COFF::IMAGE_FILE_MACHINE_ARM64;
619 
620   if (Obj.isIR()) {
621     Expected<std::string> TripleStr =
622         getBitcodeTargetTriple(Obj.getMemoryBufferRef());
623     if (!TripleStr)
624       return false;
625     Triple T(*TripleStr);
626     return T.isWindowsArm64EC() || T.getArch() == Triple::x86_64;
627   }
628 
629   return false;
630 }
631 
632 static Expected<std::vector<unsigned>>
633 getSymbols(MemoryBufferRef Buf, uint16_t Index, raw_ostream &SymNames,
634            SymMap *SymMap, bool &HasObject) {
635   // In the scenario when LLVMContext is populated SymbolicFile will contain a
636   // reference to it, thus SymbolicFile should be destroyed first.
637   LLVMContext Context;
638 
639   std::vector<unsigned> Ret;
640   Expected<std::unique_ptr<SymbolicFile>> ObjOrErr =
641       getSymbolicFile(Buf, Context);
642   if (!ObjOrErr)
643     return ObjOrErr.takeError();
644 
645   // If the member is non-symbolic file, treat it as having no symbols.
646   if (!*ObjOrErr)
647     return Ret;
648 
649   std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr);
650 
651   std::map<std::string, uint16_t> *Map = nullptr;
652   if (SymMap)
653     Map = SymMap->UseECMap && isECObject(*Obj) ? &SymMap->ECMap : &SymMap->Map;
654   HasObject = true;
655   for (const object::BasicSymbolRef &S : Obj->symbols()) {
656     if (!isArchiveSymbol(S))
657       continue;
658     if (Map) {
659       std::string Name;
660       raw_string_ostream NameStream(Name);
661       if (Error E = S.printName(NameStream))
662         return std::move(E);
663       if (Map->find(Name) != Map->end())
664         continue; // ignore duplicated symbol
665       (*Map)[Name] = Index;
666       if (Map == &SymMap->Map) {
667         Ret.push_back(SymNames.tell());
668         SymNames << Name << '\0';
669       }
670     } else {
671       Ret.push_back(SymNames.tell());
672       if (Error E = S.printName(SymNames))
673         return std::move(E);
674       SymNames << '\0';
675     }
676   }
677   return Ret;
678 }
679 
680 static Expected<std::vector<MemberData>>
681 computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
682                   object::Archive::Kind Kind, bool Thin, bool Deterministic,
683                   SymtabWritingMode NeedSymbols, SymMap *SymMap,
684                   ArrayRef<NewArchiveMember> NewMembers) {
685   static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
686 
687   uint64_t Pos =
688       isAIXBigArchive(Kind) ? sizeof(object::BigArchive::FixLenHdr) : 0;
689 
690   std::vector<MemberData> Ret;
691   bool HasObject = false;
692 
693   // Deduplicate long member names in the string table and reuse earlier name
694   // offsets. This especially saves space for COFF Import libraries where all
695   // members have the same name.
696   StringMap<uint64_t> MemberNames;
697 
698   // UniqueTimestamps is a special case to improve debugging on Darwin:
699   //
700   // The Darwin linker does not link debug info into the final
701   // binary. Instead, it emits entries of type N_OSO in the output
702   // binary's symbol table, containing references to the linked-in
703   // object files. Using that reference, the debugger can read the
704   // debug data directly from the object files. Alternatively, an
705   // invocation of 'dsymutil' will link the debug data from the object
706   // files into a dSYM bundle, which can be loaded by the debugger,
707   // instead of the object files.
708   //
709   // For an object file, the N_OSO entries contain the absolute path
710   // path to the file, and the file's timestamp. For an object
711   // included in an archive, the path is formatted like
712   // "/absolute/path/to/archive.a(member.o)", and the timestamp is the
713   // archive member's timestamp, rather than the archive's timestamp.
714   //
715   // However, this doesn't always uniquely identify an object within
716   // an archive -- an archive file can have multiple entries with the
717   // same filename. (This will happen commonly if the original object
718   // files started in different directories.) The only way they get
719   // distinguished, then, is via the timestamp. But this process is
720   // unable to find the correct object file in the archive when there
721   // are two files of the same name and timestamp.
722   //
723   // Additionally, timestamp==0 is treated specially, and causes the
724   // timestamp to be ignored as a match criteria.
725   //
726   // That will "usually" work out okay when creating an archive not in
727   // deterministic timestamp mode, because the objects will probably
728   // have been created at different timestamps.
729   //
730   // To ameliorate this problem, in deterministic archive mode (which
731   // is the default), on Darwin we will emit a unique non-zero
732   // timestamp for each entry with a duplicated name. This is still
733   // deterministic: the only thing affecting that timestamp is the
734   // order of the files in the resultant archive.
735   //
736   // See also the functions that handle the lookup:
737   // in lldb: ObjectContainerBSDArchive::Archive::FindObject()
738   // in llvm/tools/dsymutil: BinaryHolder::GetArchiveMemberBuffers().
739   bool UniqueTimestamps = Deterministic && isDarwin(Kind);
740   std::map<StringRef, unsigned> FilenameCount;
741   if (UniqueTimestamps) {
742     for (const NewArchiveMember &M : NewMembers)
743       FilenameCount[M.MemberName]++;
744     for (auto &Entry : FilenameCount)
745       Entry.second = Entry.second > 1 ? 1 : 0;
746   }
747 
748   // The big archive format needs to know the offset of the previous member
749   // header.
750   uint64_t PrevOffset = 0;
751   uint16_t Index = 0;
752   for (const NewArchiveMember &M : NewMembers) {
753     std::string Header;
754     raw_string_ostream Out(Header);
755 
756     MemoryBufferRef Buf = M.Buf->getMemBufferRef();
757     StringRef Data = Thin ? "" : Buf.getBuffer();
758 
759     Index++;
760 
761     // ld64 expects the members to be 8-byte aligned for 64-bit content and at
762     // least 4-byte aligned for 32-bit content.  Opt for the larger encoding
763     // uniformly.  This matches the behaviour with cctools and ensures that ld64
764     // is happy with archives that we generate.
765     unsigned MemberPadding =
766         isDarwin(Kind) ? offsetToAlignment(Data.size(), Align(8)) : 0;
767     unsigned TailPadding =
768         offsetToAlignment(Data.size() + MemberPadding, Align(2));
769     StringRef Padding = StringRef(PaddingData, MemberPadding + TailPadding);
770 
771     sys::TimePoint<std::chrono::seconds> ModTime;
772     if (UniqueTimestamps)
773       // Increment timestamp for each file of a given name.
774       ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);
775     else
776       ModTime = M.ModTime;
777 
778     uint64_t Size = Buf.getBufferSize() + MemberPadding;
779     if (Size > object::Archive::MaxMemberSize) {
780       std::string StringMsg =
781           "File " + M.MemberName.str() + " exceeds size limit";
782       return make_error<object::GenericBinaryError>(
783           std::move(StringMsg), object::object_error::parse_failed);
784     }
785 
786     if (isAIXBigArchive(Kind)) {
787       uint64_t NextOffset = Pos + sizeof(object::BigArMemHdrType) +
788                             alignTo(M.MemberName.size(), 2) + alignTo(Size, 2);
789       printBigArchiveMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
790                                   M.Perms, Size, PrevOffset, NextOffset);
791       PrevOffset = Pos;
792     } else {
793       printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M,
794                         ModTime, Size);
795     }
796     Out.flush();
797 
798     std::vector<unsigned> Symbols;
799     if (NeedSymbols != SymtabWritingMode::NoSymtab) {
800       Expected<std::vector<unsigned>> SymbolsOrErr =
801           getSymbols(Buf, Index, SymNames, SymMap, HasObject);
802       if (!SymbolsOrErr)
803         return createFileError(M.MemberName, SymbolsOrErr.takeError());
804       Symbols = std::move(*SymbolsOrErr);
805     }
806 
807     Pos += Header.size() + Data.size() + Padding.size();
808     Ret.push_back({std::move(Symbols), std::move(Header), Data, Padding});
809   }
810   // If there are no symbols, emit an empty symbol table, to satisfy Solaris
811   // tools, older versions of which expect a symbol table in a non-empty
812   // archive, regardless of whether there are any symbols in it.
813   if (HasObject && SymNames.tell() == 0 && !isCOFFArchive(Kind))
814     SymNames << '\0' << '\0' << '\0';
815   return Ret;
816 }
817 
818 namespace llvm {
819 
820 static ErrorOr<SmallString<128>> canonicalizePath(StringRef P) {
821   SmallString<128> Ret = P;
822   std::error_code Err = sys::fs::make_absolute(Ret);
823   if (Err)
824     return Err;
825   sys::path::remove_dots(Ret, /*removedotdot*/ true);
826   return Ret;
827 }
828 
829 // Compute the relative path from From to To.
830 Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To) {
831   ErrorOr<SmallString<128>> PathToOrErr = canonicalizePath(To);
832   ErrorOr<SmallString<128>> DirFromOrErr = canonicalizePath(From);
833   if (!PathToOrErr || !DirFromOrErr)
834     return errorCodeToError(std::error_code(errno, std::generic_category()));
835 
836   const SmallString<128> &PathTo = *PathToOrErr;
837   const SmallString<128> &DirFrom = sys::path::parent_path(*DirFromOrErr);
838 
839   // Can't construct a relative path between different roots
840   if (sys::path::root_name(PathTo) != sys::path::root_name(DirFrom))
841     return sys::path::convert_to_slash(PathTo);
842 
843   // Skip common prefixes
844   auto FromTo =
845       std::mismatch(sys::path::begin(DirFrom), sys::path::end(DirFrom),
846                     sys::path::begin(PathTo));
847   auto FromI = FromTo.first;
848   auto ToI = FromTo.second;
849 
850   // Construct relative path
851   SmallString<128> Relative;
852   for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
853     sys::path::append(Relative, sys::path::Style::posix, "..");
854 
855   for (auto ToE = sys::path::end(PathTo); ToI != ToE; ++ToI)
856     sys::path::append(Relative, sys::path::Style::posix, *ToI);
857 
858   return std::string(Relative.str());
859 }
860 
861 static Error writeArchiveToStream(raw_ostream &Out,
862                                   ArrayRef<NewArchiveMember> NewMembers,
863                                   SymtabWritingMode WriteSymtab,
864                                   object::Archive::Kind Kind,
865                                   bool Deterministic, bool Thin, bool IsEC) {
866   assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode");
867 
868   SmallString<0> SymNamesBuf;
869   raw_svector_ostream SymNames(SymNamesBuf);
870   SmallString<0> StringTableBuf;
871   raw_svector_ostream StringTable(StringTableBuf);
872   SymMap SymMap;
873 
874   // COFF symbol map uses 16-bit indexes, so we can't use it if there are too
875   // many members.
876   if (isCOFFArchive(Kind) && NewMembers.size() > 0xfffe)
877     Kind = object::Archive::K_GNU;
878 
879   SymMap.UseECMap = IsEC;
880   Expected<std::vector<MemberData>> DataOrErr = computeMemberData(
881       StringTable, SymNames, Kind, Thin, Deterministic, WriteSymtab,
882       isCOFFArchive(Kind) ? &SymMap : nullptr, NewMembers);
883   if (Error E = DataOrErr.takeError())
884     return E;
885   std::vector<MemberData> &Data = *DataOrErr;
886 
887   uint64_t StringTableSize = 0;
888   MemberData StringTableMember;
889   if (!StringTableBuf.empty() && !isAIXBigArchive(Kind)) {
890     StringTableMember = computeStringTable(StringTableBuf);
891     StringTableSize = StringTableMember.Header.size() +
892                       StringTableMember.Data.size() +
893                       StringTableMember.Padding.size();
894   }
895 
896   // We would like to detect if we need to switch to a 64-bit symbol table.
897   uint64_t LastMemberEndOffset = 0;
898   uint64_t LastMemberHeaderOffset = 0;
899   uint64_t NumSyms = 0;
900   uint64_t NumSyms32 = 0; // Store symbol number of 32-bit member files.
901   bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab;
902 
903   for (const auto &M : Data) {
904     // Record the start of the member's offset
905     LastMemberHeaderOffset = LastMemberEndOffset;
906     // Account for the size of each part associated with the member.
907     LastMemberEndOffset += M.Header.size() + M.Data.size() + M.Padding.size();
908     NumSyms += M.Symbols.size();
909 
910     // AIX big archive files may contain two global symbol tables. The
911     // first global symbol table locates 32-bit file members that define global
912     // symbols; the second global symbol table does the same for 64-bit file
913     // members. As a big archive can have both 32-bit and 64-bit file members,
914     // we need to know the number of symbols in each symbol table individually.
915     if (isAIXBigArchive(Kind) && ShouldWriteSymtab) {
916       Expected<bool> Is64BitOrErr = is64BitSymbolicFile(M.Data);
917       if (Error E = Is64BitOrErr.takeError())
918         return E;
919 
920       if (!*Is64BitOrErr)
921         NumSyms32 += M.Symbols.size();
922     }
923   }
924 
925   std::optional<uint64_t> HeadersSize;
926 
927   // The symbol table is put at the end of the big archive file. The symbol
928   // table is at the start of the archive file for other archive formats.
929   if (ShouldWriteSymtab && !is64BitKind(Kind)) {
930     // We assume 32-bit offsets to see if 32-bit symbols are possible or not.
931     HeadersSize = computeHeadersSize(Kind, Data.size(), StringTableSize,
932                                      NumSyms, SymNamesBuf.size(),
933                                      isCOFFArchive(Kind) ? &SymMap : nullptr);
934 
935     // The SYM64 format is used when an archive's member offsets are larger than
936     // 32-bits can hold. The need for this shift in format is detected by
937     // writeArchive. To test this we need to generate a file with a member that
938     // has an offset larger than 32-bits but this demands a very slow test. To
939     // speed the test up we use this environment variable to pretend like the
940     // cutoff happens before 32-bits and instead happens at some much smaller
941     // value.
942     uint64_t Sym64Threshold = 1ULL << 32;
943     const char *Sym64Env = std::getenv("SYM64_THRESHOLD");
944     if (Sym64Env)
945       StringRef(Sym64Env).getAsInteger(10, Sym64Threshold);
946 
947     // If LastMemberHeaderOffset isn't going to fit in a 32-bit varible we need
948     // to switch to 64-bit. Note that the file can be larger than 4GB as long as
949     // the last member starts before the 4GB offset.
950     if (*HeadersSize + LastMemberHeaderOffset >= Sym64Threshold) {
951       if (Kind == object::Archive::K_DARWIN)
952         Kind = object::Archive::K_DARWIN64;
953       else
954         Kind = object::Archive::K_GNU64;
955       HeadersSize.reset();
956     }
957   }
958 
959   if (Thin)
960     Out << "!<thin>\n";
961   else if (isAIXBigArchive(Kind))
962     Out << "<bigaf>\n";
963   else
964     Out << "!<arch>\n";
965 
966   if (!isAIXBigArchive(Kind)) {
967     if (ShouldWriteSymtab) {
968       if (!HeadersSize)
969         HeadersSize = computeHeadersSize(
970             Kind, Data.size(), StringTableSize, NumSyms, SymNamesBuf.size(),
971             isCOFFArchive(Kind) ? &SymMap : nullptr);
972       writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf,
973                        *HeadersSize, NumSyms);
974 
975       if (isCOFFArchive(Kind))
976         writeSymbolMap(Out, Kind, Deterministic, Data, SymMap, *HeadersSize);
977     }
978 
979     if (StringTableSize)
980       Out << StringTableMember.Header << StringTableMember.Data
981           << StringTableMember.Padding;
982 
983     if (ShouldWriteSymtab && SymMap.ECMap.size())
984       writeECSymbols(Out, Kind, Deterministic, Data, SymMap);
985 
986     for (const MemberData &M : Data)
987       Out << M.Header << M.Data << M.Padding;
988   } else {
989     HeadersSize = sizeof(object::BigArchive::FixLenHdr);
990     LastMemberEndOffset += *HeadersSize;
991     LastMemberHeaderOffset += *HeadersSize;
992 
993     // For the big archive (AIX) format, compute a table of member names and
994     // offsets, used in the member table.
995     uint64_t MemberTableNameStrTblSize = 0;
996     std::vector<size_t> MemberOffsets;
997     std::vector<StringRef> MemberNames;
998     // Loop across object to find offset and names.
999     uint64_t MemberEndOffset = sizeof(object::BigArchive::FixLenHdr);
1000     for (size_t I = 0, Size = NewMembers.size(); I != Size; ++I) {
1001       const NewArchiveMember &Member = NewMembers[I];
1002       MemberTableNameStrTblSize += Member.MemberName.size() + 1;
1003       MemberOffsets.push_back(MemberEndOffset);
1004       MemberNames.push_back(Member.MemberName);
1005       // File member name ended with "`\n". The length is included in
1006       // BigArMemHdrType.
1007       MemberEndOffset += sizeof(object::BigArMemHdrType) +
1008                              alignTo(Data[I].Data.size(), 2) +
1009                              alignTo(Member.MemberName.size(), 2);
1010     }
1011 
1012     // AIX member table size.
1013     uint64_t MemberTableSize = 20 + // Number of members field
1014                                20 * MemberOffsets.size() +
1015                                MemberTableNameStrTblSize;
1016 
1017     SmallString<0> SymNamesBuf32;
1018     SmallString<0> SymNamesBuf64;
1019     raw_svector_ostream SymNames32(SymNamesBuf32);
1020     raw_svector_ostream SymNames64(SymNamesBuf64);
1021 
1022     if (ShouldWriteSymtab && NumSyms)
1023       // Generate the symbol names for the members.
1024       for (const NewArchiveMember &M : NewMembers) {
1025         MemoryBufferRef Buf = M.Buf->getMemBufferRef();
1026         Expected<bool> Is64BitOrErr = is64BitSymbolicFile(Buf.getBuffer());
1027         if (!Is64BitOrErr)
1028           return Is64BitOrErr.takeError();
1029 
1030         bool HasObject;
1031         Expected<std::vector<unsigned>> SymbolsOrErr =
1032             getSymbols(Buf, 0, *Is64BitOrErr ? SymNames64 : SymNames32, nullptr,
1033                        HasObject);
1034         if (!SymbolsOrErr)
1035           return SymbolsOrErr.takeError();
1036       }
1037 
1038     uint64_t MemberTableEndOffset =
1039         LastMemberEndOffset +
1040         alignTo(sizeof(object::BigArMemHdrType) + MemberTableSize, 2);
1041 
1042     // In AIX OS, The 'GlobSymOffset' field in the fixed-length header contains
1043     // the offset to the 32-bit global symbol table, and the 'GlobSym64Offset'
1044     // contains the offset to the 64-bit global symbol table.
1045     uint64_t GlobalSymbolOffset =
1046         (ShouldWriteSymtab &&
1047          (WriteSymtab != SymtabWritingMode::BigArchive64) && NumSyms32 > 0)
1048             ? MemberTableEndOffset
1049             : 0;
1050 
1051     uint64_t GlobalSymbolOffset64 = 0;
1052     uint64_t NumSyms64 = NumSyms - NumSyms32;
1053     if (ShouldWriteSymtab && (WriteSymtab != SymtabWritingMode::BigArchive32) &&
1054         NumSyms64 > 0) {
1055       if (GlobalSymbolOffset == 0)
1056         GlobalSymbolOffset64 = MemberTableEndOffset;
1057       else
1058         // If there is a global symbol table for 32-bit members,
1059         // the 64-bit global symbol table is after the 32-bit one.
1060         GlobalSymbolOffset64 =
1061             GlobalSymbolOffset + sizeof(object::BigArMemHdrType) +
1062             (NumSyms32 + 1) * 8 + alignTo(SymNamesBuf32.size(), 2);
1063     }
1064 
1065     // Fixed Sized Header.
1066     printWithSpacePadding(Out, NewMembers.size() ? LastMemberEndOffset : 0,
1067                           20); // Offset to member table
1068     // If there are no file members in the archive, there will be no global
1069     // symbol table.
1070     printWithSpacePadding(Out, GlobalSymbolOffset, 20);
1071     printWithSpacePadding(Out, GlobalSymbolOffset64, 20);
1072     printWithSpacePadding(
1073         Out, NewMembers.size() ? sizeof(object::BigArchive::FixLenHdr) : 0,
1074         20); // Offset to first archive member
1075     printWithSpacePadding(Out, NewMembers.size() ? LastMemberHeaderOffset : 0,
1076                           20); // Offset to last archive member
1077     printWithSpacePadding(
1078         Out, 0,
1079         20); // Offset to first member of free list - Not supported yet
1080 
1081     for (const MemberData &M : Data) {
1082       Out << M.Header << M.Data;
1083       if (M.Data.size() % 2)
1084         Out << '\0';
1085     }
1086 
1087     if (NewMembers.size()) {
1088       // Member table.
1089       printBigArchiveMemberHeader(Out, "", sys::toTimePoint(0), 0, 0, 0,
1090                                   MemberTableSize, LastMemberHeaderOffset,
1091                                   GlobalSymbolOffset ? GlobalSymbolOffset
1092                                                      : GlobalSymbolOffset64);
1093       printWithSpacePadding(Out, MemberOffsets.size(), 20); // Number of members
1094       for (uint64_t MemberOffset : MemberOffsets)
1095         printWithSpacePadding(Out, MemberOffset,
1096                               20); // Offset to member file header.
1097       for (StringRef MemberName : MemberNames)
1098         Out << MemberName << '\0'; // Member file name, null byte padding.
1099 
1100       if (MemberTableNameStrTblSize % 2)
1101         Out << '\0'; // Name table must be tail padded to an even number of
1102                      // bytes.
1103 
1104       if (ShouldWriteSymtab) {
1105         // Write global symbol table for 32-bit file members.
1106         if (GlobalSymbolOffset) {
1107           writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf32,
1108                            *HeadersSize, NumSyms32, LastMemberEndOffset,
1109                            GlobalSymbolOffset64);
1110           // Add padding between the symbol tables, if needed.
1111           if (GlobalSymbolOffset64 && (SymNamesBuf32.size() % 2))
1112             Out << '\0';
1113         }
1114 
1115         // Write global symbol table for 64-bit file members.
1116         if (GlobalSymbolOffset64)
1117           writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf64,
1118                            *HeadersSize, NumSyms64,
1119                            GlobalSymbolOffset ? GlobalSymbolOffset
1120                                               : LastMemberEndOffset,
1121                            0, true);
1122       }
1123     }
1124   }
1125   Out.flush();
1126   return Error::success();
1127 }
1128 
1129 Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
1130                    SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
1131                    bool Deterministic, bool Thin,
1132                    std::unique_ptr<MemoryBuffer> OldArchiveBuf, bool IsEC) {
1133   Expected<sys::fs::TempFile> Temp =
1134       sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a");
1135   if (!Temp)
1136     return Temp.takeError();
1137   raw_fd_ostream Out(Temp->FD, false);
1138 
1139   if (Error E = writeArchiveToStream(Out, NewMembers, WriteSymtab, Kind,
1140                                      Deterministic, Thin, IsEC)) {
1141     if (Error DiscardError = Temp->discard())
1142       return joinErrors(std::move(E), std::move(DiscardError));
1143     return E;
1144   }
1145 
1146   // At this point, we no longer need whatever backing memory
1147   // was used to generate the NewMembers. On Windows, this buffer
1148   // could be a mapped view of the file we want to replace (if
1149   // we're updating an existing archive, say). In that case, the
1150   // rename would still succeed, but it would leave behind a
1151   // temporary file (actually the original file renamed) because
1152   // a file cannot be deleted while there's a handle open on it,
1153   // only renamed. So by freeing this buffer, this ensures that
1154   // the last open handle on the destination file, if any, is
1155   // closed before we attempt to rename.
1156   OldArchiveBuf.reset();
1157 
1158   return Temp->keep(ArcName);
1159 }
1160 
1161 Expected<std::unique_ptr<MemoryBuffer>>
1162 writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers,
1163                      SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
1164                      bool Deterministic, bool Thin) {
1165   SmallVector<char, 0> ArchiveBufferVector;
1166   raw_svector_ostream ArchiveStream(ArchiveBufferVector);
1167 
1168   if (Error E = writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab,
1169                                      Kind, Deterministic, Thin, false))
1170     return std::move(E);
1171 
1172   return std::make_unique<SmallVectorMemoryBuffer>(
1173       std::move(ArchiveBufferVector), /*RequiresNullTerminator=*/false);
1174 }
1175 
1176 } // namespace llvm
1177