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 uint64_t PreHeadPadSize = 0; 335 std::unique_ptr<SymbolicFile> SymFile = nullptr; 336 }; 337 } // namespace 338 339 static MemberData computeStringTable(StringRef Names) { 340 unsigned Size = Names.size(); 341 unsigned Pad = offsetToAlignment(Size, Align(2)); 342 std::string Header; 343 raw_string_ostream Out(Header); 344 printWithSpacePadding(Out, "//", 48); 345 printWithSpacePadding(Out, Size + Pad, 10); 346 Out << "`\n"; 347 Out.flush(); 348 return {{}, std::move(Header), Names, Pad ? "\n" : ""}; 349 } 350 351 static sys::TimePoint<std::chrono::seconds> now(bool Deterministic) { 352 using namespace std::chrono; 353 354 if (!Deterministic) 355 return time_point_cast<seconds>(system_clock::now()); 356 return sys::TimePoint<seconds>(); 357 } 358 359 static bool isArchiveSymbol(const object::BasicSymbolRef &S) { 360 Expected<uint32_t> SymFlagsOrErr = S.getFlags(); 361 if (!SymFlagsOrErr) 362 // TODO: Actually report errors helpfully. 363 report_fatal_error(SymFlagsOrErr.takeError()); 364 if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific) 365 return false; 366 if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global)) 367 return false; 368 if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined) 369 return false; 370 return true; 371 } 372 373 static void printNBits(raw_ostream &Out, object::Archive::Kind Kind, 374 uint64_t Val) { 375 if (is64BitKind(Kind)) 376 print<uint64_t>(Out, Kind, Val); 377 else 378 print<uint32_t>(Out, Kind, Val); 379 } 380 381 static uint64_t computeSymbolTableSize(object::Archive::Kind Kind, 382 uint64_t NumSyms, uint64_t OffsetSize, 383 uint64_t StringTableSize, 384 uint32_t *Padding = nullptr) { 385 assert((OffsetSize == 4 || OffsetSize == 8) && "Unsupported OffsetSize"); 386 uint64_t Size = OffsetSize; // Number of entries 387 if (isBSDLike(Kind)) 388 Size += NumSyms * OffsetSize * 2; // Table 389 else 390 Size += NumSyms * OffsetSize; // Table 391 if (isBSDLike(Kind)) 392 Size += OffsetSize; // byte count 393 Size += StringTableSize; 394 // ld64 expects the members to be 8-byte aligned for 64-bit content and at 395 // least 4-byte aligned for 32-bit content. Opt for the larger encoding 396 // uniformly. 397 // We do this for all bsd formats because it simplifies aligning members. 398 // For the big archive format, the symbol table is the last member, so there 399 // is no need to align. 400 uint32_t Pad = isAIXBigArchive(Kind) 401 ? 0 402 : offsetToAlignment(Size, Align(isBSDLike(Kind) ? 8 : 2)); 403 404 Size += Pad; 405 if (Padding) 406 *Padding = Pad; 407 return Size; 408 } 409 410 static uint64_t computeSymbolMapSize(uint64_t NumObj, SymMap &SymMap, 411 uint32_t *Padding = nullptr) { 412 uint64_t Size = sizeof(uint32_t) * 2; // Number of symbols and objects entries 413 Size += NumObj * sizeof(uint32_t); // Offset table 414 415 for (auto S : SymMap.Map) 416 Size += sizeof(uint16_t) + S.first.length() + 1; 417 418 uint32_t Pad = offsetToAlignment(Size, Align(2)); 419 Size += Pad; 420 if (Padding) 421 *Padding = Pad; 422 return Size; 423 } 424 425 static uint64_t computeECSymbolsSize(SymMap &SymMap, 426 uint32_t *Padding = nullptr) { 427 uint64_t Size = sizeof(uint32_t); // Number of symbols 428 429 for (auto S : SymMap.ECMap) 430 Size += sizeof(uint16_t) + S.first.length() + 1; 431 432 uint32_t Pad = offsetToAlignment(Size, Align(2)); 433 Size += Pad; 434 if (Padding) 435 *Padding = Pad; 436 return Size; 437 } 438 439 static void writeSymbolTableHeader(raw_ostream &Out, object::Archive::Kind Kind, 440 bool Deterministic, uint64_t Size, 441 uint64_t PrevMemberOffset = 0, 442 uint64_t NextMemberOffset = 0) { 443 if (isBSDLike(Kind)) { 444 const char *Name = is64BitKind(Kind) ? "__.SYMDEF_64" : "__.SYMDEF"; 445 printBSDMemberHeader(Out, Out.tell(), Name, now(Deterministic), 0, 0, 0, 446 Size); 447 } else if (isAIXBigArchive(Kind)) { 448 printBigArchiveMemberHeader(Out, "", now(Deterministic), 0, 0, 0, Size, 449 PrevMemberOffset, NextMemberOffset); 450 } else { 451 const char *Name = is64BitKind(Kind) ? "/SYM64" : ""; 452 printGNUSmallMemberHeader(Out, Name, now(Deterministic), 0, 0, 0, Size); 453 } 454 } 455 456 static uint64_t computeHeadersSize(object::Archive::Kind Kind, 457 uint64_t NumMembers, 458 uint64_t StringMemberSize, uint64_t NumSyms, 459 uint64_t SymNamesSize, SymMap *SymMap) { 460 uint32_t OffsetSize = is64BitKind(Kind) ? 8 : 4; 461 uint64_t SymtabSize = 462 computeSymbolTableSize(Kind, NumSyms, OffsetSize, SymNamesSize); 463 auto computeSymbolTableHeaderSize = [=] { 464 SmallString<0> TmpBuf; 465 raw_svector_ostream Tmp(TmpBuf); 466 writeSymbolTableHeader(Tmp, Kind, true, SymtabSize); 467 return TmpBuf.size(); 468 }; 469 uint32_t HeaderSize = computeSymbolTableHeaderSize(); 470 uint64_t Size = strlen("!<arch>\n") + HeaderSize + SymtabSize; 471 472 if (SymMap) { 473 Size += HeaderSize + computeSymbolMapSize(NumMembers, *SymMap); 474 if (SymMap->ECMap.size()) 475 Size += HeaderSize + computeECSymbolsSize(*SymMap); 476 } 477 478 return Size + StringMemberSize; 479 } 480 481 static Expected<std::unique_ptr<SymbolicFile>> 482 getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context) { 483 const file_magic Type = identify_magic(Buf.getBuffer()); 484 // Don't attempt to read non-symbolic file types. 485 if (!object::SymbolicFile::isSymbolicFile(Type, &Context)) 486 return nullptr; 487 if (Type == file_magic::bitcode) { 488 auto ObjOrErr = object::SymbolicFile::createSymbolicFile( 489 Buf, file_magic::bitcode, &Context); 490 if (!ObjOrErr) 491 return ObjOrErr.takeError(); 492 return std::move(*ObjOrErr); 493 } else { 494 auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf); 495 if (!ObjOrErr) 496 return ObjOrErr.takeError(); 497 return std::move(*ObjOrErr); 498 } 499 } 500 501 static bool is64BitSymbolicFile(const SymbolicFile *SymObj) { 502 return SymObj != nullptr ? SymObj->is64Bit() : false; 503 } 504 505 // Log2 of PAGESIZE(4096) on an AIX system. 506 static const uint32_t Log2OfAIXPageSize = 12; 507 508 // In the AIX big archive format, since the data content follows the member file 509 // name, if the name ends on an odd byte, an extra byte will be added for 510 // padding. This ensures that the data within the member file starts at an even 511 // byte. 512 static const uint32_t MinBigArchiveMemDataAlign = 2; 513 514 template <typename AuxiliaryHeader> 515 uint16_t getAuxMaxAlignment(uint16_t AuxHeaderSize, AuxiliaryHeader *AuxHeader, 516 uint16_t Log2OfMaxAlign) { 517 // If the member doesn't have an auxiliary header, it isn't a loadable object 518 // and so it just needs aligning at the minimum value. 519 if (AuxHeader == nullptr) 520 return MinBigArchiveMemDataAlign; 521 522 // If the auxiliary header does not have both MaxAlignOfData and 523 // MaxAlignOfText field, it is not a loadable shared object file, so align at 524 // the minimum value. The 'ModuleType' member is located right after 525 // 'MaxAlignOfData' in the AuxiliaryHeader. 526 if (AuxHeaderSize < offsetof(AuxiliaryHeader, ModuleType)) 527 return MinBigArchiveMemDataAlign; 528 529 // If the XCOFF object file does not have a loader section, it is not 530 // loadable, so align at the minimum value. 531 if (AuxHeader->SecNumOfLoader == 0) 532 return MinBigArchiveMemDataAlign; 533 534 // The content of the loadable member file needs to be aligned at MAX(maximum 535 // alignment of .text, maximum alignment of .data) if there are both fields. 536 // If the desired alignment is > PAGESIZE, 32-bit members are aligned on a 537 // word boundary, while 64-bit members are aligned on a PAGESIZE(2^12=4096) 538 // boundary. 539 uint16_t Log2OfAlign = 540 std::max(AuxHeader->MaxAlignOfText, AuxHeader->MaxAlignOfData); 541 return 1 << (Log2OfAlign > Log2OfAIXPageSize ? Log2OfMaxAlign : Log2OfAlign); 542 } 543 544 // AIX big archives may contain shared object members. The AIX OS requires these 545 // members to be aligned if they are 64-bit and recommends it for 32-bit 546 // members. This ensures that when these members are loaded they are aligned in 547 // memory. 548 static uint32_t getMemberAlignment(SymbolicFile *SymObj) { 549 XCOFFObjectFile *XCOFFObj = dyn_cast_or_null<XCOFFObjectFile>(SymObj); 550 if (!XCOFFObj) 551 return MinBigArchiveMemDataAlign; 552 553 // If the desired alignment is > PAGESIZE, 32-bit members are aligned on a 554 // word boundary, while 64-bit members are aligned on a PAGESIZE boundary. 555 return XCOFFObj->is64Bit() 556 ? getAuxMaxAlignment(XCOFFObj->fileHeader64()->AuxHeaderSize, 557 XCOFFObj->auxiliaryHeader64(), 558 Log2OfAIXPageSize) 559 : getAuxMaxAlignment(XCOFFObj->fileHeader32()->AuxHeaderSize, 560 XCOFFObj->auxiliaryHeader32(), 2); 561 } 562 563 static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, 564 bool Deterministic, ArrayRef<MemberData> Members, 565 StringRef StringTable, uint64_t MembersOffset, 566 unsigned NumSyms, uint64_t PrevMemberOffset = 0, 567 uint64_t NextMemberOffset = 0, 568 bool Is64Bit = false) { 569 // We don't write a symbol table on an archive with no members -- except on 570 // Darwin, where the linker will abort unless the archive has a symbol table. 571 if (StringTable.empty() && !isDarwin(Kind) && !isCOFFArchive(Kind)) 572 return; 573 574 uint64_t OffsetSize = is64BitKind(Kind) ? 8 : 4; 575 uint32_t Pad; 576 uint64_t Size = computeSymbolTableSize(Kind, NumSyms, OffsetSize, 577 StringTable.size(), &Pad); 578 writeSymbolTableHeader(Out, Kind, Deterministic, Size, PrevMemberOffset, 579 NextMemberOffset); 580 581 if (isBSDLike(Kind)) 582 printNBits(Out, Kind, NumSyms * 2 * OffsetSize); 583 else 584 printNBits(Out, Kind, NumSyms); 585 586 uint64_t Pos = MembersOffset; 587 for (const MemberData &M : Members) { 588 if (isAIXBigArchive(Kind)) { 589 Pos += M.PreHeadPadSize; 590 if (is64BitSymbolicFile(M.SymFile.get()) != Is64Bit) { 591 Pos += M.Header.size() + M.Data.size() + M.Padding.size(); 592 continue; 593 } 594 } 595 596 for (unsigned StringOffset : M.Symbols) { 597 if (isBSDLike(Kind)) 598 printNBits(Out, Kind, StringOffset); 599 printNBits(Out, Kind, Pos); // member offset 600 } 601 Pos += M.Header.size() + M.Data.size() + M.Padding.size(); 602 } 603 604 if (isBSDLike(Kind)) 605 // byte count of the string table 606 printNBits(Out, Kind, StringTable.size()); 607 Out << StringTable; 608 609 while (Pad--) 610 Out.write(uint8_t(0)); 611 } 612 613 static void writeSymbolMap(raw_ostream &Out, object::Archive::Kind Kind, 614 bool Deterministic, ArrayRef<MemberData> Members, 615 SymMap &SymMap, uint64_t MembersOffset) { 616 uint32_t Pad; 617 uint64_t Size = computeSymbolMapSize(Members.size(), SymMap, &Pad); 618 writeSymbolTableHeader(Out, Kind, Deterministic, Size, 0); 619 620 uint32_t Pos = MembersOffset; 621 622 printLE<uint32_t>(Out, Members.size()); 623 for (const MemberData &M : Members) { 624 printLE(Out, Pos); // member offset 625 Pos += M.Header.size() + M.Data.size() + M.Padding.size(); 626 } 627 628 printLE<uint32_t>(Out, SymMap.Map.size()); 629 630 for (auto S : SymMap.Map) 631 printLE(Out, S.second); 632 for (auto S : SymMap.Map) 633 Out << S.first << '\0'; 634 635 while (Pad--) 636 Out.write(uint8_t(0)); 637 } 638 639 static void writeECSymbols(raw_ostream &Out, object::Archive::Kind Kind, 640 bool Deterministic, ArrayRef<MemberData> Members, 641 SymMap &SymMap) { 642 uint32_t Pad; 643 uint64_t Size = computeECSymbolsSize(SymMap, &Pad); 644 printGNUSmallMemberHeader(Out, "/<ECSYMBOLS>", now(Deterministic), 0, 0, 0, 645 Size); 646 647 printLE<uint32_t>(Out, SymMap.ECMap.size()); 648 649 for (auto S : SymMap.ECMap) 650 printLE(Out, S.second); 651 for (auto S : SymMap.ECMap) 652 Out << S.first << '\0'; 653 while (Pad--) 654 Out.write(uint8_t(0)); 655 } 656 657 static bool isECObject(object::SymbolicFile &Obj) { 658 if (Obj.isCOFF()) 659 return cast<llvm::object::COFFObjectFile>(&Obj)->getMachine() != 660 COFF::IMAGE_FILE_MACHINE_ARM64; 661 662 if (Obj.isIR()) { 663 Expected<std::string> TripleStr = 664 getBitcodeTargetTriple(Obj.getMemoryBufferRef()); 665 if (!TripleStr) 666 return false; 667 Triple T(*TripleStr); 668 return T.isWindowsArm64EC() || T.getArch() == Triple::x86_64; 669 } 670 671 return false; 672 } 673 674 static Expected<std::vector<unsigned>> getSymbols(SymbolicFile *Obj, 675 uint16_t Index, 676 raw_ostream &SymNames, 677 SymMap *SymMap) { 678 std::vector<unsigned> Ret; 679 680 if (Obj == nullptr) 681 return Ret; 682 683 std::map<std::string, uint16_t> *Map = nullptr; 684 if (SymMap) 685 Map = SymMap->UseECMap && isECObject(*Obj) ? &SymMap->ECMap : &SymMap->Map; 686 687 for (const object::BasicSymbolRef &S : Obj->symbols()) { 688 if (!isArchiveSymbol(S)) 689 continue; 690 if (Map) { 691 std::string Name; 692 raw_string_ostream NameStream(Name); 693 if (Error E = S.printName(NameStream)) 694 return std::move(E); 695 if (Map->find(Name) != Map->end()) 696 continue; // ignore duplicated symbol 697 (*Map)[Name] = Index; 698 if (Map == &SymMap->Map) { 699 Ret.push_back(SymNames.tell()); 700 SymNames << Name << '\0'; 701 } 702 } else { 703 Ret.push_back(SymNames.tell()); 704 if (Error E = S.printName(SymNames)) 705 return std::move(E); 706 SymNames << '\0'; 707 } 708 } 709 return Ret; 710 } 711 712 static Expected<std::vector<MemberData>> 713 computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, 714 object::Archive::Kind Kind, bool Thin, bool Deterministic, 715 SymtabWritingMode NeedSymbols, SymMap *SymMap, 716 LLVMContext &Context, ArrayRef<NewArchiveMember> NewMembers) { 717 static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'}; 718 uint64_t MemHeadPadSize = 0; 719 uint64_t Pos = 720 isAIXBigArchive(Kind) ? sizeof(object::BigArchive::FixLenHdr) : 0; 721 722 std::vector<MemberData> Ret; 723 bool HasObject = false; 724 725 // Deduplicate long member names in the string table and reuse earlier name 726 // offsets. This especially saves space for COFF Import libraries where all 727 // members have the same name. 728 StringMap<uint64_t> MemberNames; 729 730 // UniqueTimestamps is a special case to improve debugging on Darwin: 731 // 732 // The Darwin linker does not link debug info into the final 733 // binary. Instead, it emits entries of type N_OSO in the output 734 // binary's symbol table, containing references to the linked-in 735 // object files. Using that reference, the debugger can read the 736 // debug data directly from the object files. Alternatively, an 737 // invocation of 'dsymutil' will link the debug data from the object 738 // files into a dSYM bundle, which can be loaded by the debugger, 739 // instead of the object files. 740 // 741 // For an object file, the N_OSO entries contain the absolute path 742 // path to the file, and the file's timestamp. For an object 743 // included in an archive, the path is formatted like 744 // "/absolute/path/to/archive.a(member.o)", and the timestamp is the 745 // archive member's timestamp, rather than the archive's timestamp. 746 // 747 // However, this doesn't always uniquely identify an object within 748 // an archive -- an archive file can have multiple entries with the 749 // same filename. (This will happen commonly if the original object 750 // files started in different directories.) The only way they get 751 // distinguished, then, is via the timestamp. But this process is 752 // unable to find the correct object file in the archive when there 753 // are two files of the same name and timestamp. 754 // 755 // Additionally, timestamp==0 is treated specially, and causes the 756 // timestamp to be ignored as a match criteria. 757 // 758 // That will "usually" work out okay when creating an archive not in 759 // deterministic timestamp mode, because the objects will probably 760 // have been created at different timestamps. 761 // 762 // To ameliorate this problem, in deterministic archive mode (which 763 // is the default), on Darwin we will emit a unique non-zero 764 // timestamp for each entry with a duplicated name. This is still 765 // deterministic: the only thing affecting that timestamp is the 766 // order of the files in the resultant archive. 767 // 768 // See also the functions that handle the lookup: 769 // in lldb: ObjectContainerBSDArchive::Archive::FindObject() 770 // in llvm/tools/dsymutil: BinaryHolder::GetArchiveMemberBuffers(). 771 bool UniqueTimestamps = Deterministic && isDarwin(Kind); 772 std::map<StringRef, unsigned> FilenameCount; 773 if (UniqueTimestamps) { 774 for (const NewArchiveMember &M : NewMembers) 775 FilenameCount[M.MemberName]++; 776 for (auto &Entry : FilenameCount) 777 Entry.second = Entry.second > 1 ? 1 : 0; 778 } 779 780 // The big archive format needs to know the offset of the previous member 781 // header. 782 uint64_t PrevOffset = 0; 783 uint64_t NextMemHeadPadSize = 0; 784 std::unique_ptr<SymbolicFile> CurSymFile; 785 std::unique_ptr<SymbolicFile> NextSymFile; 786 uint16_t Index = 0; 787 788 for (auto M = NewMembers.begin(); M < NewMembers.end(); ++M) { 789 std::string Header; 790 raw_string_ostream Out(Header); 791 792 MemoryBufferRef Buf = M->Buf->getMemBufferRef(); 793 StringRef Data = Thin ? "" : Buf.getBuffer(); 794 795 Index++; 796 797 // ld64 expects the members to be 8-byte aligned for 64-bit content and at 798 // least 4-byte aligned for 32-bit content. Opt for the larger encoding 799 // uniformly. This matches the behaviour with cctools and ensures that ld64 800 // is happy with archives that we generate. 801 unsigned MemberPadding = 802 isDarwin(Kind) ? offsetToAlignment(Data.size(), Align(8)) : 0; 803 unsigned TailPadding = 804 offsetToAlignment(Data.size() + MemberPadding, Align(2)); 805 StringRef Padding = StringRef(PaddingData, MemberPadding + TailPadding); 806 807 sys::TimePoint<std::chrono::seconds> ModTime; 808 if (UniqueTimestamps) 809 // Increment timestamp for each file of a given name. 810 ModTime = sys::toTimePoint(FilenameCount[M->MemberName]++); 811 else 812 ModTime = M->ModTime; 813 814 uint64_t Size = Buf.getBufferSize() + MemberPadding; 815 if (Size > object::Archive::MaxMemberSize) { 816 std::string StringMsg = 817 "File " + M->MemberName.str() + " exceeds size limit"; 818 return make_error<object::GenericBinaryError>( 819 std::move(StringMsg), object::object_error::parse_failed); 820 } 821 822 if (NeedSymbols != SymtabWritingMode::NoSymtab || isAIXBigArchive(Kind)) { 823 auto SetNextSymFile = [&NextSymFile, 824 &Context](MemoryBufferRef Buf, 825 StringRef MemberName) -> Error { 826 Expected<std::unique_ptr<SymbolicFile>> SymFileOrErr = 827 getSymbolicFile(Buf, Context); 828 if (!SymFileOrErr) 829 return createFileError(MemberName, SymFileOrErr.takeError()); 830 NextSymFile = std::move(*SymFileOrErr); 831 return Error::success(); 832 }; 833 834 if (M == NewMembers.begin()) 835 if (Error Err = SetNextSymFile(Buf, M->MemberName)) 836 return std::move(Err); 837 838 CurSymFile = std::move(NextSymFile); 839 840 if ((M + 1) != NewMembers.end()) 841 if (Error Err = SetNextSymFile((M + 1)->Buf->getMemBufferRef(), 842 (M + 1)->MemberName)) 843 return std::move(Err); 844 } 845 846 // In the big archive file format, we need to calculate and include the next 847 // member offset and previous member offset in the file member header. 848 if (isAIXBigArchive(Kind)) { 849 uint64_t OffsetToMemData = Pos + sizeof(object::BigArMemHdrType) + 850 alignTo(M->MemberName.size(), 2); 851 852 if (M == NewMembers.begin()) 853 NextMemHeadPadSize = 854 alignToPowerOf2(OffsetToMemData, 855 getMemberAlignment(CurSymFile.get())) - 856 OffsetToMemData; 857 858 MemHeadPadSize = NextMemHeadPadSize; 859 Pos += MemHeadPadSize; 860 uint64_t NextOffset = Pos + sizeof(object::BigArMemHdrType) + 861 alignTo(M->MemberName.size(), 2) + alignTo(Size, 2); 862 863 // If there is another member file after this, we need to calculate the 864 // padding before the header. 865 if ((M + 1) != NewMembers.end()) { 866 uint64_t OffsetToNextMemData = NextOffset + 867 sizeof(object::BigArMemHdrType) + 868 alignTo((M + 1)->MemberName.size(), 2); 869 NextMemHeadPadSize = 870 alignToPowerOf2(OffsetToNextMemData, 871 getMemberAlignment(NextSymFile.get())) - 872 OffsetToNextMemData; 873 NextOffset += NextMemHeadPadSize; 874 } 875 printBigArchiveMemberHeader(Out, M->MemberName, ModTime, M->UID, M->GID, 876 M->Perms, Size, PrevOffset, NextOffset); 877 PrevOffset = Pos; 878 } else { 879 printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, *M, 880 ModTime, Size); 881 } 882 Out.flush(); 883 884 std::vector<unsigned> Symbols; 885 if (NeedSymbols != SymtabWritingMode::NoSymtab) { 886 Expected<std::vector<unsigned>> SymbolsOrErr = 887 getSymbols(CurSymFile.get(), Index, SymNames, SymMap); 888 if (!SymbolsOrErr) 889 return createFileError(M->MemberName, SymbolsOrErr.takeError()); 890 Symbols = std::move(*SymbolsOrErr); 891 if (CurSymFile) 892 HasObject = true; 893 } 894 895 Pos += Header.size() + Data.size() + Padding.size(); 896 Ret.push_back({std::move(Symbols), std::move(Header), Data, Padding, 897 MemHeadPadSize, std::move(CurSymFile)}); 898 } 899 // If there are no symbols, emit an empty symbol table, to satisfy Solaris 900 // tools, older versions of which expect a symbol table in a non-empty 901 // archive, regardless of whether there are any symbols in it. 902 if (HasObject && SymNames.tell() == 0 && !isCOFFArchive(Kind)) 903 SymNames << '\0' << '\0' << '\0'; 904 return std::move(Ret); 905 } 906 907 namespace llvm { 908 909 static ErrorOr<SmallString<128>> canonicalizePath(StringRef P) { 910 SmallString<128> Ret = P; 911 std::error_code Err = sys::fs::make_absolute(Ret); 912 if (Err) 913 return Err; 914 sys::path::remove_dots(Ret, /*removedotdot*/ true); 915 return Ret; 916 } 917 918 // Compute the relative path from From to To. 919 Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To) { 920 ErrorOr<SmallString<128>> PathToOrErr = canonicalizePath(To); 921 ErrorOr<SmallString<128>> DirFromOrErr = canonicalizePath(From); 922 if (!PathToOrErr || !DirFromOrErr) 923 return errorCodeToError(std::error_code(errno, std::generic_category())); 924 925 const SmallString<128> &PathTo = *PathToOrErr; 926 const SmallString<128> &DirFrom = sys::path::parent_path(*DirFromOrErr); 927 928 // Can't construct a relative path between different roots 929 if (sys::path::root_name(PathTo) != sys::path::root_name(DirFrom)) 930 return sys::path::convert_to_slash(PathTo); 931 932 // Skip common prefixes 933 auto FromTo = 934 std::mismatch(sys::path::begin(DirFrom), sys::path::end(DirFrom), 935 sys::path::begin(PathTo)); 936 auto FromI = FromTo.first; 937 auto ToI = FromTo.second; 938 939 // Construct relative path 940 SmallString<128> Relative; 941 for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI) 942 sys::path::append(Relative, sys::path::Style::posix, ".."); 943 944 for (auto ToE = sys::path::end(PathTo); ToI != ToE; ++ToI) 945 sys::path::append(Relative, sys::path::Style::posix, *ToI); 946 947 return std::string(Relative.str()); 948 } 949 950 static Error writeArchiveToStream(raw_ostream &Out, 951 ArrayRef<NewArchiveMember> NewMembers, 952 SymtabWritingMode WriteSymtab, 953 object::Archive::Kind Kind, 954 bool Deterministic, bool Thin, bool IsEC) { 955 assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode"); 956 957 SmallString<0> SymNamesBuf; 958 raw_svector_ostream SymNames(SymNamesBuf); 959 SmallString<0> StringTableBuf; 960 raw_svector_ostream StringTable(StringTableBuf); 961 SymMap SymMap; 962 963 // COFF symbol map uses 16-bit indexes, so we can't use it if there are too 964 // many members. 965 if (isCOFFArchive(Kind) && NewMembers.size() > 0xfffe) 966 Kind = object::Archive::K_GNU; 967 968 // In the scenario when LLVMContext is populated SymbolicFile will contain a 969 // reference to it, thus SymbolicFile should be destroyed first. 970 LLVMContext Context; 971 972 SymMap.UseECMap = IsEC; 973 Expected<std::vector<MemberData>> DataOrErr = computeMemberData( 974 StringTable, SymNames, Kind, Thin, Deterministic, WriteSymtab, 975 isCOFFArchive(Kind) ? &SymMap : nullptr, Context, NewMembers); 976 if (Error E = DataOrErr.takeError()) 977 return E; 978 std::vector<MemberData> &Data = *DataOrErr; 979 980 uint64_t StringTableSize = 0; 981 MemberData StringTableMember; 982 if (!StringTableBuf.empty() && !isAIXBigArchive(Kind)) { 983 StringTableMember = computeStringTable(StringTableBuf); 984 StringTableSize = StringTableMember.Header.size() + 985 StringTableMember.Data.size() + 986 StringTableMember.Padding.size(); 987 } 988 989 // We would like to detect if we need to switch to a 64-bit symbol table. 990 uint64_t LastMemberEndOffset = 0; 991 uint64_t LastMemberHeaderOffset = 0; 992 uint64_t NumSyms = 0; 993 uint64_t NumSyms32 = 0; // Store symbol number of 32-bit member files. 994 bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab; 995 996 for (const auto &M : Data) { 997 // Record the start of the member's offset 998 LastMemberEndOffset += M.PreHeadPadSize; 999 LastMemberHeaderOffset = LastMemberEndOffset; 1000 // Account for the size of each part associated with the member. 1001 LastMemberEndOffset += M.Header.size() + M.Data.size() + M.Padding.size(); 1002 NumSyms += M.Symbols.size(); 1003 1004 // AIX big archive files may contain two global symbol tables. The 1005 // first global symbol table locates 32-bit file members that define global 1006 // symbols; the second global symbol table does the same for 64-bit file 1007 // members. As a big archive can have both 32-bit and 64-bit file members, 1008 // we need to know the number of symbols in each symbol table individually. 1009 if (isAIXBigArchive(Kind) && ShouldWriteSymtab) { 1010 if (!is64BitSymbolicFile(M.SymFile.get())) 1011 NumSyms32 += M.Symbols.size(); 1012 } 1013 } 1014 1015 std::optional<uint64_t> HeadersSize; 1016 1017 // The symbol table is put at the end of the big archive file. The symbol 1018 // table is at the start of the archive file for other archive formats. 1019 if (ShouldWriteSymtab && !is64BitKind(Kind)) { 1020 // We assume 32-bit offsets to see if 32-bit symbols are possible or not. 1021 HeadersSize = computeHeadersSize(Kind, Data.size(), StringTableSize, 1022 NumSyms, SymNamesBuf.size(), 1023 isCOFFArchive(Kind) ? &SymMap : nullptr); 1024 1025 // The SYM64 format is used when an archive's member offsets are larger than 1026 // 32-bits can hold. The need for this shift in format is detected by 1027 // writeArchive. To test this we need to generate a file with a member that 1028 // has an offset larger than 32-bits but this demands a very slow test. To 1029 // speed the test up we use this environment variable to pretend like the 1030 // cutoff happens before 32-bits and instead happens at some much smaller 1031 // value. 1032 uint64_t Sym64Threshold = 1ULL << 32; 1033 const char *Sym64Env = std::getenv("SYM64_THRESHOLD"); 1034 if (Sym64Env) 1035 StringRef(Sym64Env).getAsInteger(10, Sym64Threshold); 1036 1037 // If LastMemberHeaderOffset isn't going to fit in a 32-bit varible we need 1038 // to switch to 64-bit. Note that the file can be larger than 4GB as long as 1039 // the last member starts before the 4GB offset. 1040 if (*HeadersSize + LastMemberHeaderOffset >= Sym64Threshold) { 1041 if (Kind == object::Archive::K_DARWIN) 1042 Kind = object::Archive::K_DARWIN64; 1043 else 1044 Kind = object::Archive::K_GNU64; 1045 HeadersSize.reset(); 1046 } 1047 } 1048 1049 if (Thin) 1050 Out << "!<thin>\n"; 1051 else if (isAIXBigArchive(Kind)) 1052 Out << "<bigaf>\n"; 1053 else 1054 Out << "!<arch>\n"; 1055 1056 if (!isAIXBigArchive(Kind)) { 1057 if (ShouldWriteSymtab) { 1058 if (!HeadersSize) 1059 HeadersSize = computeHeadersSize( 1060 Kind, Data.size(), StringTableSize, NumSyms, SymNamesBuf.size(), 1061 isCOFFArchive(Kind) ? &SymMap : nullptr); 1062 writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf, 1063 *HeadersSize, NumSyms); 1064 1065 if (isCOFFArchive(Kind)) 1066 writeSymbolMap(Out, Kind, Deterministic, Data, SymMap, *HeadersSize); 1067 } 1068 1069 if (StringTableSize) 1070 Out << StringTableMember.Header << StringTableMember.Data 1071 << StringTableMember.Padding; 1072 1073 if (ShouldWriteSymtab && SymMap.ECMap.size()) 1074 writeECSymbols(Out, Kind, Deterministic, Data, SymMap); 1075 1076 for (const MemberData &M : Data) 1077 Out << M.Header << M.Data << M.Padding; 1078 } else { 1079 HeadersSize = sizeof(object::BigArchive::FixLenHdr); 1080 LastMemberEndOffset += *HeadersSize; 1081 LastMemberHeaderOffset += *HeadersSize; 1082 1083 // For the big archive (AIX) format, compute a table of member names and 1084 // offsets, used in the member table. 1085 uint64_t MemberTableNameStrTblSize = 0; 1086 std::vector<size_t> MemberOffsets; 1087 std::vector<StringRef> MemberNames; 1088 // Loop across object to find offset and names. 1089 uint64_t MemberEndOffset = sizeof(object::BigArchive::FixLenHdr); 1090 for (size_t I = 0, Size = NewMembers.size(); I != Size; ++I) { 1091 const NewArchiveMember &Member = NewMembers[I]; 1092 MemberTableNameStrTblSize += Member.MemberName.size() + 1; 1093 MemberEndOffset += Data[I].PreHeadPadSize; 1094 MemberOffsets.push_back(MemberEndOffset); 1095 MemberNames.push_back(Member.MemberName); 1096 // File member name ended with "`\n". The length is included in 1097 // BigArMemHdrType. 1098 MemberEndOffset += sizeof(object::BigArMemHdrType) + 1099 alignTo(Data[I].Data.size(), 2) + 1100 alignTo(Member.MemberName.size(), 2); 1101 } 1102 1103 // AIX member table size. 1104 uint64_t MemberTableSize = 20 + // Number of members field 1105 20 * MemberOffsets.size() + 1106 MemberTableNameStrTblSize; 1107 1108 SmallString<0> SymNamesBuf32; 1109 SmallString<0> SymNamesBuf64; 1110 raw_svector_ostream SymNames32(SymNamesBuf32); 1111 raw_svector_ostream SymNames64(SymNamesBuf64); 1112 1113 if (ShouldWriteSymtab && NumSyms) 1114 // Generate the symbol names for the members. 1115 for (const auto &M : Data) { 1116 Expected<std::vector<unsigned>> SymbolsOrErr = getSymbols( 1117 M.SymFile.get(), 0, 1118 is64BitSymbolicFile(M.SymFile.get()) ? SymNames64 : SymNames32, 1119 nullptr); 1120 if (!SymbolsOrErr) 1121 return SymbolsOrErr.takeError(); 1122 } 1123 1124 uint64_t MemberTableEndOffset = 1125 LastMemberEndOffset + 1126 alignTo(sizeof(object::BigArMemHdrType) + MemberTableSize, 2); 1127 1128 // In AIX OS, The 'GlobSymOffset' field in the fixed-length header contains 1129 // the offset to the 32-bit global symbol table, and the 'GlobSym64Offset' 1130 // contains the offset to the 64-bit global symbol table. 1131 uint64_t GlobalSymbolOffset = 1132 (ShouldWriteSymtab && 1133 (WriteSymtab != SymtabWritingMode::BigArchive64) && NumSyms32 > 0) 1134 ? MemberTableEndOffset 1135 : 0; 1136 1137 uint64_t GlobalSymbolOffset64 = 0; 1138 uint64_t NumSyms64 = NumSyms - NumSyms32; 1139 if (ShouldWriteSymtab && (WriteSymtab != SymtabWritingMode::BigArchive32) && 1140 NumSyms64 > 0) { 1141 if (GlobalSymbolOffset == 0) 1142 GlobalSymbolOffset64 = MemberTableEndOffset; 1143 else 1144 // If there is a global symbol table for 32-bit members, 1145 // the 64-bit global symbol table is after the 32-bit one. 1146 GlobalSymbolOffset64 = 1147 GlobalSymbolOffset + sizeof(object::BigArMemHdrType) + 1148 (NumSyms32 + 1) * 8 + alignTo(SymNamesBuf32.size(), 2); 1149 } 1150 1151 // Fixed Sized Header. 1152 printWithSpacePadding(Out, NewMembers.size() ? LastMemberEndOffset : 0, 1153 20); // Offset to member table 1154 // If there are no file members in the archive, there will be no global 1155 // symbol table. 1156 printWithSpacePadding(Out, GlobalSymbolOffset, 20); 1157 printWithSpacePadding(Out, GlobalSymbolOffset64, 20); 1158 printWithSpacePadding(Out, 1159 NewMembers.size() 1160 ? sizeof(object::BigArchive::FixLenHdr) + 1161 Data[0].PreHeadPadSize 1162 : 0, 1163 20); // Offset to first archive member 1164 printWithSpacePadding(Out, NewMembers.size() ? LastMemberHeaderOffset : 0, 1165 20); // Offset to last archive member 1166 printWithSpacePadding( 1167 Out, 0, 1168 20); // Offset to first member of free list - Not supported yet 1169 1170 for (const MemberData &M : Data) { 1171 Out << std::string(M.PreHeadPadSize, '\0'); 1172 Out << M.Header << M.Data; 1173 if (M.Data.size() % 2) 1174 Out << '\0'; 1175 } 1176 1177 if (NewMembers.size()) { 1178 // Member table. 1179 printBigArchiveMemberHeader(Out, "", sys::toTimePoint(0), 0, 0, 0, 1180 MemberTableSize, LastMemberHeaderOffset, 1181 GlobalSymbolOffset ? GlobalSymbolOffset 1182 : GlobalSymbolOffset64); 1183 printWithSpacePadding(Out, MemberOffsets.size(), 20); // Number of members 1184 for (uint64_t MemberOffset : MemberOffsets) 1185 printWithSpacePadding(Out, MemberOffset, 1186 20); // Offset to member file header. 1187 for (StringRef MemberName : MemberNames) 1188 Out << MemberName << '\0'; // Member file name, null byte padding. 1189 1190 if (MemberTableNameStrTblSize % 2) 1191 Out << '\0'; // Name table must be tail padded to an even number of 1192 // bytes. 1193 1194 if (ShouldWriteSymtab) { 1195 // Write global symbol table for 32-bit file members. 1196 if (GlobalSymbolOffset) { 1197 writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf32, 1198 *HeadersSize, NumSyms32, LastMemberEndOffset, 1199 GlobalSymbolOffset64); 1200 // Add padding between the symbol tables, if needed. 1201 if (GlobalSymbolOffset64 && (SymNamesBuf32.size() % 2)) 1202 Out << '\0'; 1203 } 1204 1205 // Write global symbol table for 64-bit file members. 1206 if (GlobalSymbolOffset64) 1207 writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf64, 1208 *HeadersSize, NumSyms64, 1209 GlobalSymbolOffset ? GlobalSymbolOffset 1210 : LastMemberEndOffset, 1211 0, true); 1212 } 1213 } 1214 } 1215 Out.flush(); 1216 return Error::success(); 1217 } 1218 1219 Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, 1220 SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, 1221 bool Deterministic, bool Thin, 1222 std::unique_ptr<MemoryBuffer> OldArchiveBuf, bool IsEC) { 1223 Expected<sys::fs::TempFile> Temp = 1224 sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a"); 1225 if (!Temp) 1226 return Temp.takeError(); 1227 raw_fd_ostream Out(Temp->FD, false); 1228 1229 if (Error E = writeArchiveToStream(Out, NewMembers, WriteSymtab, Kind, 1230 Deterministic, Thin, IsEC)) { 1231 if (Error DiscardError = Temp->discard()) 1232 return joinErrors(std::move(E), std::move(DiscardError)); 1233 return E; 1234 } 1235 1236 // At this point, we no longer need whatever backing memory 1237 // was used to generate the NewMembers. On Windows, this buffer 1238 // could be a mapped view of the file we want to replace (if 1239 // we're updating an existing archive, say). In that case, the 1240 // rename would still succeed, but it would leave behind a 1241 // temporary file (actually the original file renamed) because 1242 // a file cannot be deleted while there's a handle open on it, 1243 // only renamed. So by freeing this buffer, this ensures that 1244 // the last open handle on the destination file, if any, is 1245 // closed before we attempt to rename. 1246 OldArchiveBuf.reset(); 1247 1248 return Temp->keep(ArcName); 1249 } 1250 1251 Expected<std::unique_ptr<MemoryBuffer>> 1252 writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers, 1253 SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, 1254 bool Deterministic, bool Thin) { 1255 SmallVector<char, 0> ArchiveBufferVector; 1256 raw_svector_ostream ArchiveStream(ArchiveBufferVector); 1257 1258 if (Error E = writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab, 1259 Kind, Deterministic, Thin, false)) 1260 return std::move(E); 1261 1262 return std::make_unique<SmallVectorMemoryBuffer>( 1263 std::move(ArchiveBufferVector), /*RequiresNullTerminator=*/false); 1264 } 1265 1266 } // namespace llvm 1267