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 bool 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 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) { 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 bool WriteSymtab, object::Archive::Kind Kind, 864 bool Deterministic, bool Thin, bool IsEC) { 865 assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode"); 866 867 SmallString<0> SymNamesBuf; 868 raw_svector_ostream SymNames(SymNamesBuf); 869 SmallString<0> StringTableBuf; 870 raw_svector_ostream StringTable(StringTableBuf); 871 SymMap SymMap; 872 873 // COFF symbol map uses 16-bit indexes, so we can't use it if there are too 874 // many members. 875 if (isCOFFArchive(Kind) && NewMembers.size() > 0xfffe) 876 Kind = object::Archive::K_GNU; 877 878 SymMap.UseECMap = IsEC; 879 Expected<std::vector<MemberData>> DataOrErr = computeMemberData( 880 StringTable, SymNames, Kind, Thin, Deterministic, WriteSymtab, 881 isCOFFArchive(Kind) ? &SymMap : nullptr, NewMembers); 882 if (Error E = DataOrErr.takeError()) 883 return E; 884 std::vector<MemberData> &Data = *DataOrErr; 885 886 uint64_t StringTableSize = 0; 887 MemberData StringTableMember; 888 if (!StringTableBuf.empty() && !isAIXBigArchive(Kind)) { 889 StringTableMember = computeStringTable(StringTableBuf); 890 StringTableSize = StringTableMember.Header.size() + 891 StringTableMember.Data.size() + 892 StringTableMember.Padding.size(); 893 } 894 895 // We would like to detect if we need to switch to a 64-bit symbol table. 896 uint64_t LastMemberEndOffset = 0; 897 uint64_t LastMemberHeaderOffset = 0; 898 uint64_t NumSyms = 0; 899 uint64_t NumSyms32 = 0; // Store symbol number of 32-bit member files. 900 901 for (const auto &M : Data) { 902 // Record the start of the member's offset 903 LastMemberHeaderOffset = LastMemberEndOffset; 904 // Account for the size of each part associated with the member. 905 LastMemberEndOffset += M.Header.size() + M.Data.size() + M.Padding.size(); 906 NumSyms += M.Symbols.size(); 907 908 // AIX big archive files may contain two global symbol tables. The 909 // first global symbol table locates 32-bit file members that define global 910 // symbols; the second global symbol table does the same for 64-bit file 911 // members. As a big archive can have both 32-bit and 64-bit file members, 912 // we need to know the number of symbols in each symbol table individually. 913 if (isAIXBigArchive(Kind) && WriteSymtab) { 914 Expected<bool> Is64BitOrErr = is64BitSymbolicFile(M.Data); 915 if (Error E = Is64BitOrErr.takeError()) 916 return E; 917 918 if (!*Is64BitOrErr) 919 NumSyms32 += M.Symbols.size(); 920 } 921 } 922 923 std::optional<uint64_t> HeadersSize; 924 925 // The symbol table is put at the end of the big archive file. The symbol 926 // table is at the start of the archive file for other archive formats. 927 if (WriteSymtab && !is64BitKind(Kind)) { 928 // We assume 32-bit offsets to see if 32-bit symbols are possible or not. 929 HeadersSize = computeHeadersSize(Kind, Data.size(), StringTableSize, 930 NumSyms, SymNamesBuf.size(), 931 isCOFFArchive(Kind) ? &SymMap : nullptr); 932 933 // The SYM64 format is used when an archive's member offsets are larger than 934 // 32-bits can hold. The need for this shift in format is detected by 935 // writeArchive. To test this we need to generate a file with a member that 936 // has an offset larger than 32-bits but this demands a very slow test. To 937 // speed the test up we use this environment variable to pretend like the 938 // cutoff happens before 32-bits and instead happens at some much smaller 939 // value. 940 uint64_t Sym64Threshold = 1ULL << 32; 941 const char *Sym64Env = std::getenv("SYM64_THRESHOLD"); 942 if (Sym64Env) 943 StringRef(Sym64Env).getAsInteger(10, Sym64Threshold); 944 945 // If LastMemberHeaderOffset isn't going to fit in a 32-bit varible we need 946 // to switch to 64-bit. Note that the file can be larger than 4GB as long as 947 // the last member starts before the 4GB offset. 948 if (*HeadersSize + LastMemberHeaderOffset >= Sym64Threshold) { 949 if (Kind == object::Archive::K_DARWIN) 950 Kind = object::Archive::K_DARWIN64; 951 else 952 Kind = object::Archive::K_GNU64; 953 HeadersSize.reset(); 954 } 955 } 956 957 if (Thin) 958 Out << "!<thin>\n"; 959 else if (isAIXBigArchive(Kind)) 960 Out << "<bigaf>\n"; 961 else 962 Out << "!<arch>\n"; 963 964 if (!isAIXBigArchive(Kind)) { 965 if (WriteSymtab) { 966 if (!HeadersSize) 967 HeadersSize = computeHeadersSize( 968 Kind, Data.size(), StringTableSize, NumSyms, SymNamesBuf.size(), 969 isCOFFArchive(Kind) ? &SymMap : nullptr); 970 writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf, 971 *HeadersSize, NumSyms); 972 973 if (isCOFFArchive(Kind)) 974 writeSymbolMap(Out, Kind, Deterministic, Data, SymMap, *HeadersSize); 975 } 976 977 if (StringTableSize) 978 Out << StringTableMember.Header << StringTableMember.Data 979 << StringTableMember.Padding; 980 981 if (WriteSymtab && SymMap.ECMap.size()) 982 writeECSymbols(Out, Kind, Deterministic, Data, SymMap); 983 984 for (const MemberData &M : Data) 985 Out << M.Header << M.Data << M.Padding; 986 } else { 987 HeadersSize = sizeof(object::BigArchive::FixLenHdr); 988 LastMemberEndOffset += *HeadersSize; 989 LastMemberHeaderOffset += *HeadersSize; 990 991 // For the big archive (AIX) format, compute a table of member names and 992 // offsets, used in the member table. 993 uint64_t MemberTableNameStrTblSize = 0; 994 std::vector<size_t> MemberOffsets; 995 std::vector<StringRef> MemberNames; 996 // Loop across object to find offset and names. 997 uint64_t MemberEndOffset = sizeof(object::BigArchive::FixLenHdr); 998 for (size_t I = 0, Size = NewMembers.size(); I != Size; ++I) { 999 const NewArchiveMember &Member = NewMembers[I]; 1000 MemberTableNameStrTblSize += Member.MemberName.size() + 1; 1001 MemberOffsets.push_back(MemberEndOffset); 1002 MemberNames.push_back(Member.MemberName); 1003 // File member name ended with "`\n". The length is included in 1004 // BigArMemHdrType. 1005 MemberEndOffset += sizeof(object::BigArMemHdrType) + 1006 alignTo(Data[I].Data.size(), 2) + 1007 alignTo(Member.MemberName.size(), 2); 1008 } 1009 1010 // AIX member table size. 1011 uint64_t MemberTableSize = 20 + // Number of members field 1012 20 * MemberOffsets.size() + 1013 MemberTableNameStrTblSize; 1014 1015 SmallString<0> SymNamesBuf32; 1016 SmallString<0> SymNamesBuf64; 1017 raw_svector_ostream SymNames32(SymNamesBuf32); 1018 raw_svector_ostream SymNames64(SymNamesBuf64); 1019 1020 if (WriteSymtab && NumSyms) 1021 // Generate the symbol names for the members. 1022 for (const NewArchiveMember &M : NewMembers) { 1023 MemoryBufferRef Buf = M.Buf->getMemBufferRef(); 1024 Expected<bool> Is64BitOrErr = is64BitSymbolicFile(Buf.getBuffer()); 1025 if (!Is64BitOrErr) 1026 return Is64BitOrErr.takeError(); 1027 1028 bool HasObject; 1029 Expected<std::vector<unsigned>> SymbolsOrErr = 1030 getSymbols(Buf, 0, *Is64BitOrErr ? SymNames64 : SymNames32, nullptr, 1031 HasObject); 1032 if (!SymbolsOrErr) 1033 return SymbolsOrErr.takeError(); 1034 } 1035 1036 uint64_t MemberTableEndOffset = 1037 LastMemberEndOffset + 1038 alignTo(sizeof(object::BigArMemHdrType) + MemberTableSize, 2); 1039 1040 // In AIX OS, The 'GlobSymOffset' field in the fixed-length header contains 1041 // the offset to the 32-bit global symbol table, and the 'GlobSym64Offset' 1042 // contains the offset to the 64-bit global symbol table. 1043 uint64_t GlobalSymbolOffset = 1044 (WriteSymtab && NumSyms32 > 0) ? MemberTableEndOffset : 0; 1045 1046 uint64_t GlobalSymbolOffset64 = 0; 1047 uint64_t NumSyms64 = NumSyms - NumSyms32; 1048 if (WriteSymtab && NumSyms64 > 0) { 1049 if (GlobalSymbolOffset == 0) 1050 GlobalSymbolOffset64 = MemberTableEndOffset; 1051 else 1052 // If there is a global symbol table for 32-bit members, 1053 // the 64-bit global symbol table is after the 32-bit one. 1054 GlobalSymbolOffset64 = 1055 GlobalSymbolOffset + sizeof(object::BigArMemHdrType) + 1056 (NumSyms32 + 1) * 8 + alignTo(SymNamesBuf32.size(), 2); 1057 } 1058 1059 // Fixed Sized Header. 1060 printWithSpacePadding(Out, NewMembers.size() ? LastMemberEndOffset : 0, 1061 20); // Offset to member table 1062 // If there are no file members in the archive, there will be no global 1063 // symbol table. 1064 printWithSpacePadding(Out, GlobalSymbolOffset, 20); 1065 printWithSpacePadding(Out, GlobalSymbolOffset64, 20); 1066 printWithSpacePadding( 1067 Out, NewMembers.size() ? sizeof(object::BigArchive::FixLenHdr) : 0, 1068 20); // Offset to first archive member 1069 printWithSpacePadding(Out, NewMembers.size() ? LastMemberHeaderOffset : 0, 1070 20); // Offset to last archive member 1071 printWithSpacePadding( 1072 Out, 0, 1073 20); // Offset to first member of free list - Not supported yet 1074 1075 for (const MemberData &M : Data) { 1076 Out << M.Header << M.Data; 1077 if (M.Data.size() % 2) 1078 Out << '\0'; 1079 } 1080 1081 if (NewMembers.size()) { 1082 // Member table. 1083 printBigArchiveMemberHeader(Out, "", sys::toTimePoint(0), 0, 0, 0, 1084 MemberTableSize, LastMemberHeaderOffset, 1085 GlobalSymbolOffset ? GlobalSymbolOffset 1086 : GlobalSymbolOffset64); 1087 printWithSpacePadding(Out, MemberOffsets.size(), 20); // Number of members 1088 for (uint64_t MemberOffset : MemberOffsets) 1089 printWithSpacePadding(Out, MemberOffset, 1090 20); // Offset to member file header. 1091 for (StringRef MemberName : MemberNames) 1092 Out << MemberName << '\0'; // Member file name, null byte padding. 1093 1094 if (MemberTableNameStrTblSize % 2) 1095 Out << '\0'; // Name table must be tail padded to an even number of 1096 // bytes. 1097 1098 if (WriteSymtab) { 1099 // Write global symbol table for 32-bit file members. 1100 if (GlobalSymbolOffset) { 1101 writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf32, 1102 *HeadersSize, NumSyms32, LastMemberEndOffset, 1103 GlobalSymbolOffset64); 1104 // Add padding between the symbol tables, if needed. 1105 if (GlobalSymbolOffset64 && (SymNamesBuf32.size() % 2)) 1106 Out << '\0'; 1107 } 1108 1109 // Write global symbol table for 64-bit file members. 1110 if (GlobalSymbolOffset64) 1111 writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf64, 1112 *HeadersSize, NumSyms64, 1113 GlobalSymbolOffset ? GlobalSymbolOffset 1114 : LastMemberEndOffset, 1115 0, true); 1116 } 1117 } 1118 } 1119 Out.flush(); 1120 return Error::success(); 1121 } 1122 1123 Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, 1124 bool WriteSymtab, object::Archive::Kind Kind, 1125 bool Deterministic, bool Thin, 1126 std::unique_ptr<MemoryBuffer> OldArchiveBuf, bool IsEC) { 1127 Expected<sys::fs::TempFile> Temp = 1128 sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a"); 1129 if (!Temp) 1130 return Temp.takeError(); 1131 raw_fd_ostream Out(Temp->FD, false); 1132 1133 if (Error E = writeArchiveToStream(Out, NewMembers, WriteSymtab, Kind, 1134 Deterministic, Thin, IsEC)) { 1135 if (Error DiscardError = Temp->discard()) 1136 return joinErrors(std::move(E), std::move(DiscardError)); 1137 return E; 1138 } 1139 1140 // At this point, we no longer need whatever backing memory 1141 // was used to generate the NewMembers. On Windows, this buffer 1142 // could be a mapped view of the file we want to replace (if 1143 // we're updating an existing archive, say). In that case, the 1144 // rename would still succeed, but it would leave behind a 1145 // temporary file (actually the original file renamed) because 1146 // a file cannot be deleted while there's a handle open on it, 1147 // only renamed. So by freeing this buffer, this ensures that 1148 // the last open handle on the destination file, if any, is 1149 // closed before we attempt to rename. 1150 OldArchiveBuf.reset(); 1151 1152 return Temp->keep(ArcName); 1153 } 1154 1155 Expected<std::unique_ptr<MemoryBuffer>> 1156 writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers, bool WriteSymtab, 1157 object::Archive::Kind Kind, bool Deterministic, 1158 bool Thin) { 1159 SmallVector<char, 0> ArchiveBufferVector; 1160 raw_svector_ostream ArchiveStream(ArchiveBufferVector); 1161 1162 if (Error E = writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab, 1163 Kind, Deterministic, Thin, false)) 1164 return std::move(E); 1165 1166 return std::make_unique<SmallVectorMemoryBuffer>( 1167 std::move(ArchiveBufferVector), /*RequiresNullTerminator=*/false); 1168 } 1169 1170 } // namespace llvm 1171