LLVM  14.0.0git
ArchiveWriter.cpp
Go to the documentation of this file.
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 
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/StringMap.h"
16 #include "llvm/ADT/StringRef.h"
18 #include "llvm/IR/LLVMContext.h"
19 #include "llvm/Object/Archive.h"
20 #include "llvm/Object/Error.h"
21 #include "llvm/Object/ObjectFile.h"
23 #include "llvm/Support/Alignment.h"
25 #include "llvm/Support/Errc.h"
27 #include "llvm/Support/Format.h"
28 #include "llvm/Support/Path.h"
32 
33 #include <map>
34 
35 #if !defined(_MSC_VER) && !defined(__MINGW32__)
36 #include <unistd.h>
37 #else
38 #include <io.h>
39 #endif
40 
41 using namespace llvm;
42 
44  : Buf(MemoryBuffer::getMemBuffer(BufRef, false)),
45  MemberName(BufRef.getBufferIdentifier()) {}
46 
49  bool Deterministic) {
51  if (!BufOrErr)
52  return BufOrErr.takeError();
53 
55  M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
56  M.MemberName = M.Buf->getBufferIdentifier();
57  if (!Deterministic) {
58  auto ModTimeOrErr = OldMember.getLastModified();
59  if (!ModTimeOrErr)
60  return ModTimeOrErr.takeError();
61  M.ModTime = ModTimeOrErr.get();
62  Expected<unsigned> UIDOrErr = OldMember.getUID();
63  if (!UIDOrErr)
64  return UIDOrErr.takeError();
65  M.UID = UIDOrErr.get();
66  Expected<unsigned> GIDOrErr = OldMember.getGID();
67  if (!GIDOrErr)
68  return GIDOrErr.takeError();
69  M.GID = GIDOrErr.get();
70  Expected<sys::fs::perms> AccessModeOrErr = OldMember.getAccessMode();
71  if (!AccessModeOrErr)
72  return AccessModeOrErr.takeError();
73  M.Perms = AccessModeOrErr.get();
74  }
75  return std::move(M);
76 }
77 
79  bool Deterministic) {
81  auto FDOrErr = sys::fs::openNativeFileForRead(FileName);
82  if (!FDOrErr)
83  return FDOrErr.takeError();
84  sys::fs::file_t FD = *FDOrErr;
86 
87  if (auto EC = sys::fs::status(FD, Status))
88  return errorCodeToError(EC);
89 
90  // Opening a directory doesn't make sense. Let it fail.
91  // Linux cannot open directories with open(2), although
92  // cygwin and *bsd can.
95 
96  ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
97  MemoryBuffer::getOpenFile(FD, FileName, Status.getSize(), false);
98  if (!MemberBufferOrErr)
99  return errorCodeToError(MemberBufferOrErr.getError());
100 
101  if (auto EC = sys::fs::closeFile(FD))
102  return errorCodeToError(EC);
103 
105  M.Buf = std::move(*MemberBufferOrErr);
106  M.MemberName = M.Buf->getBufferIdentifier();
107  if (!Deterministic) {
108  M.ModTime = std::chrono::time_point_cast<std::chrono::seconds>(
109  Status.getLastModificationTime());
110  M.UID = Status.getUser();
111  M.GID = Status.getGroup();
112  M.Perms = Status.permissions();
113  }
114  return std::move(M);
115 }
116 
117 template <typename T>
118 static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size) {
119  uint64_t OldPos = OS.tell();
120  OS << Data;
121  unsigned SizeSoFar = OS.tell() - OldPos;
122  assert(SizeSoFar <= Size && "Data doesn't fit in Size");
123  OS.indent(Size - SizeSoFar);
124 }
125 
127  return Kind == object::Archive::K_DARWIN ||
129 }
130 
132  switch (Kind) {
135  return false;
139  return true;
142  break;
143  }
144  llvm_unreachable("not supported for writting");
145 }
146 
147 template <class T>
148 static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val) {
149  support::endian::write(Out, Val,
151 }
152 
155  unsigned UID, unsigned GID, unsigned Perms, uint64_t Size) {
156  printWithSpacePadding(Out, sys::toTimeT(ModTime), 12);
157 
158  // The format has only 6 chars for uid and gid. Truncate if the provided
159  // values don't fit.
160  printWithSpacePadding(Out, UID % 1000000, 6);
161  printWithSpacePadding(Out, GID % 1000000, 6);
162 
163  printWithSpacePadding(Out, format("%o", Perms), 8);
164  printWithSpacePadding(Out, Size, 10);
165  Out << "`\n";
166 }
167 
168 static void
171  unsigned UID, unsigned GID, unsigned Perms,
172  uint64_t Size) {
173  printWithSpacePadding(Out, Twine(Name) + "/", 16);
174  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
175 }
176 
177 static void
180  unsigned UID, unsigned GID, unsigned Perms, uint64_t Size) {
181  uint64_t PosAfterHeader = Pos + 60 + Name.size();
182  // Pad so that even 64 bit object files are aligned.
183  unsigned Pad = offsetToAlignment(PosAfterHeader, Align(8));
184  unsigned NameWithPadding = Name.size() + Pad;
185  printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
186  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
187  NameWithPadding + Size);
188  Out << Name;
189  while (Pad--)
190  Out.write(uint8_t(0));
191 }
192 
193 static bool useStringTable(bool Thin, StringRef Name) {
194  return Thin || Name.size() >= 16 || Name.contains('/');
195 }
196 
198  switch (Kind) {
204  return false;
207  return true;
208  }
209  llvm_unreachable("not supported for writting");
210 }
211 
212 static void
215  bool Thin, const NewArchiveMember &M,
217  if (isBSDLike(Kind))
218  return printBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID,
219  M.Perms, Size);
220  if (!useStringTable(Thin, M.MemberName))
221  return printGNUSmallMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
222  M.Perms, Size);
223  Out << '/';
224  uint64_t NamePos;
225  if (Thin) {
226  NamePos = StringTable.tell();
227  StringTable << M.MemberName << "/\n";
228  } else {
229  auto Insertion = MemberNames.insert({M.MemberName, uint64_t(0)});
230  if (Insertion.second) {
231  Insertion.first->second = StringTable.tell();
232  StringTable << M.MemberName << "/\n";
233  }
234  NamePos = Insertion.first->second;
235  }
236  printWithSpacePadding(Out, NamePos, 15);
237  printRestOfMemberHeader(Out, ModTime, M.UID, M.GID, M.Perms, Size);
238 }
239 
240 namespace {
241 struct MemberData {
242  std::vector<unsigned> Symbols;
243  std::string Header;
244  StringRef Data;
245  StringRef Padding;
246 };
247 } // namespace
248 
249 static MemberData computeStringTable(StringRef Names) {
250  unsigned Size = Names.size();
251  unsigned Pad = offsetToAlignment(Size, Align(2));
252  std::string Header;
253  raw_string_ostream Out(Header);
254  printWithSpacePadding(Out, "//", 48);
255  printWithSpacePadding(Out, Size + Pad, 10);
256  Out << "`\n";
257  Out.flush();
258  return {{}, std::move(Header), Names, Pad ? "\n" : ""};
259 }
260 
261 static sys::TimePoint<std::chrono::seconds> now(bool Deterministic) {
262  using namespace std::chrono;
263 
264  if (!Deterministic)
265  return time_point_cast<seconds>(system_clock::now());
266  return sys::TimePoint<seconds>();
267 }
268 
270  Expected<uint32_t> SymFlagsOrErr = S.getFlags();
271  if (!SymFlagsOrErr)
272  // TODO: Actually report errors helpfully.
273  report_fatal_error(SymFlagsOrErr.takeError());
274  if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific)
275  return false;
276  if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global))
277  return false;
278  if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined)
279  return false;
280  return true;
281 }
282 
284  uint64_t Val) {
285  if (is64BitKind(Kind))
286  print<uint64_t>(Out, Kind, Val);
287  else
288  print<uint32_t>(Out, Kind, Val);
289 }
290 
292  uint64_t NumSyms, uint64_t OffsetSize,
293  StringRef StringTable,
294  uint32_t *Padding = nullptr) {
295  assert((OffsetSize == 4 || OffsetSize == 8) && "Unsupported OffsetSize");
296  uint64_t Size = OffsetSize; // Number of entries
297  if (isBSDLike(Kind))
298  Size += NumSyms * OffsetSize * 2; // Table
299  else
300  Size += NumSyms * OffsetSize; // Table
301  if (isBSDLike(Kind))
302  Size += OffsetSize; // byte count
303  Size += StringTable.size();
304  // ld64 expects the members to be 8-byte aligned for 64-bit content and at
305  // least 4-byte aligned for 32-bit content. Opt for the larger encoding
306  // uniformly.
307  // We do this for all bsd formats because it simplifies aligning members.
309  Size += Pad;
310  if (Padding)
311  *Padding = Pad;
312  return Size;
313 }
314 
316  bool Deterministic, uint64_t Size) {
317  if (isBSDLike(Kind)) {
318  const char *Name = is64BitKind(Kind) ? "__.SYMDEF_64" : "__.SYMDEF";
319  printBSDMemberHeader(Out, Out.tell(), Name, now(Deterministic), 0, 0, 0,
320  Size);
321  } else {
322  const char *Name = is64BitKind(Kind) ? "/SYM64" : "";
323  printGNUSmallMemberHeader(Out, Name, now(Deterministic), 0, 0, 0, Size);
324  }
325 }
326 
328  bool Deterministic, ArrayRef<MemberData> Members,
329  StringRef StringTable) {
330  // We don't write a symbol table on an archive with no members -- except on
331  // Darwin, where the linker will abort unless the archive has a symbol table.
332  if (StringTable.empty() && !isDarwin(Kind))
333  return;
334 
335  unsigned NumSyms = 0;
336  for (const MemberData &M : Members)
337  NumSyms += M.Symbols.size();
338 
339  uint64_t OffsetSize = is64BitKind(Kind) ? 8 : 4;
340  uint32_t Pad;
341  uint64_t Size = computeSymbolTableSize(Kind, NumSyms, OffsetSize, StringTable, &Pad);
342  writeSymbolTableHeader(Out, Kind, Deterministic, Size);
343 
344  uint64_t Pos = Out.tell() + Size;
345 
346  if (isBSDLike(Kind))
347  printNBits(Out, Kind, NumSyms * 2 * OffsetSize);
348  else
349  printNBits(Out, Kind, NumSyms);
350 
351  for (const MemberData &M : Members) {
352  for (unsigned StringOffset : M.Symbols) {
353  if (isBSDLike(Kind))
354  printNBits(Out, Kind, StringOffset);
355  printNBits(Out, Kind, Pos); // member offset
356  }
357  Pos += M.Header.size() + M.Data.size() + M.Padding.size();
358  }
359 
360  if (isBSDLike(Kind))
361  // byte count of the string table
362  printNBits(Out, Kind, StringTable.size());
363  Out << StringTable;
364 
365  while (Pad--)
366  Out.write(uint8_t(0));
367 }
368 
370 getSymbols(MemoryBufferRef Buf, raw_ostream &SymNames, bool &HasObject) {
371  std::vector<unsigned> Ret;
372 
373  // In the scenario when LLVMContext is populated SymbolicFile will contain a
374  // reference to it, thus SymbolicFile should be destroyed first.
376  std::unique_ptr<object::SymbolicFile> Obj;
377 
378  const file_magic Type = identify_magic(Buf.getBuffer());
379  // Treat unsupported file types as having no symbols.
381  return Ret;
382  if (Type == file_magic::bitcode) {
385  if (!ObjOrErr)
386  return ObjOrErr.takeError();
387  Obj = std::move(*ObjOrErr);
388  } else {
389  auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf);
390  if (!ObjOrErr)
391  return ObjOrErr.takeError();
392  Obj = std::move(*ObjOrErr);
393  }
394 
395  HasObject = true;
396  for (const object::BasicSymbolRef &S : Obj->symbols()) {
397  if (!isArchiveSymbol(S))
398  continue;
399  Ret.push_back(SymNames.tell());
400  if (Error E = S.printName(SymNames))
401  return std::move(E);
402  SymNames << '\0';
403  }
404  return Ret;
405 }
406 
408 computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
409  object::Archive::Kind Kind, bool Thin, bool Deterministic,
410  bool NeedSymbols, ArrayRef<NewArchiveMember> NewMembers) {
411  static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
412 
413  // This ignores the symbol table, but we only need the value mod 8 and the
414  // symbol table is aligned to be a multiple of 8 bytes
415  uint64_t Pos = 0;
416 
417  std::vector<MemberData> Ret;
418  bool HasObject = false;
419 
420  // Deduplicate long member names in the string table and reuse earlier name
421  // offsets. This especially saves space for COFF Import libraries where all
422  // members have the same name.
423  StringMap<uint64_t> MemberNames;
424 
425  // UniqueTimestamps is a special case to improve debugging on Darwin:
426  //
427  // The Darwin linker does not link debug info into the final
428  // binary. Instead, it emits entries of type N_OSO in in the output
429  // binary's symbol table, containing references to the linked-in
430  // object files. Using that reference, the debugger can read the
431  // debug data directly from the object files. Alternatively, an
432  // invocation of 'dsymutil' will link the debug data from the object
433  // files into a dSYM bundle, which can be loaded by the debugger,
434  // instead of the object files.
435  //
436  // For an object file, the N_OSO entries contain the absolute path
437  // path to the file, and the file's timestamp. For an object
438  // included in an archive, the path is formatted like
439  // "/absolute/path/to/archive.a(member.o)", and the timestamp is the
440  // archive member's timestamp, rather than the archive's timestamp.
441  //
442  // However, this doesn't always uniquely identify an object within
443  // an archive -- an archive file can have multiple entries with the
444  // same filename. (This will happen commonly if the original object
445  // files started in different directories.) The only way they get
446  // distinguished, then, is via the timestamp. But this process is
447  // unable to find the correct object file in the archive when there
448  // are two files of the same name and timestamp.
449  //
450  // Additionally, timestamp==0 is treated specially, and causes the
451  // timestamp to be ignored as a match criteria.
452  //
453  // That will "usually" work out okay when creating an archive not in
454  // deterministic timestamp mode, because the objects will probably
455  // have been created at different timestamps.
456  //
457  // To ameliorate this problem, in deterministic archive mode (which
458  // is the default), on Darwin we will emit a unique non-zero
459  // timestamp for each entry with a duplicated name. This is still
460  // deterministic: the only thing affecting that timestamp is the
461  // order of the files in the resultant archive.
462  //
463  // See also the functions that handle the lookup:
464  // in lldb: ObjectContainerBSDArchive::Archive::FindObject()
465  // in llvm/tools/dsymutil: BinaryHolder::GetArchiveMemberBuffers().
466  bool UniqueTimestamps = Deterministic && isDarwin(Kind);
467  std::map<StringRef, unsigned> FilenameCount;
468  if (UniqueTimestamps) {
469  for (const NewArchiveMember &M : NewMembers)
470  FilenameCount[M.MemberName]++;
471  for (auto &Entry : FilenameCount)
472  Entry.second = Entry.second > 1 ? 1 : 0;
473  }
474 
475  for (const NewArchiveMember &M : NewMembers) {
476  std::string Header;
477  raw_string_ostream Out(Header);
478 
479  MemoryBufferRef Buf = M.Buf->getMemBufferRef();
480  StringRef Data = Thin ? "" : Buf.getBuffer();
481 
482  // ld64 expects the members to be 8-byte aligned for 64-bit content and at
483  // least 4-byte aligned for 32-bit content. Opt for the larger encoding
484  // uniformly. This matches the behaviour with cctools and ensures that ld64
485  // is happy with archives that we generate.
486  unsigned MemberPadding =
487  isDarwin(Kind) ? offsetToAlignment(Data.size(), Align(8)) : 0;
488  unsigned TailPadding =
489  offsetToAlignment(Data.size() + MemberPadding, Align(2));
490  StringRef Padding = StringRef(PaddingData, MemberPadding + TailPadding);
491 
493  if (UniqueTimestamps)
494  // Increment timestamp for each file of a given name.
495  ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);
496  else
497  ModTime = M.ModTime;
498 
499  uint64_t Size = Buf.getBufferSize() + MemberPadding;
501  std::string StringMsg =
502  "File " + M.MemberName.str() + " exceeds size limit";
503  return make_error<object::GenericBinaryError>(
505  }
506 
507  printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M,
508  ModTime, Size);
509  Out.flush();
510 
511  std::vector<unsigned> Symbols;
512  if (NeedSymbols) {
513  Expected<std::vector<unsigned>> SymbolsOrErr =
514  getSymbols(Buf, SymNames, HasObject);
515  if (auto E = SymbolsOrErr.takeError())
516  return std::move(E);
517  Symbols = std::move(*SymbolsOrErr);
518  }
519 
520  Pos += Header.size() + Data.size() + Padding.size();
521  Ret.push_back({std::move(Symbols), std::move(Header), Data, Padding});
522  }
523  // If there are no symbols, emit an empty symbol table, to satisfy Solaris
524  // tools, older versions of which expect a symbol table in a non-empty
525  // archive, regardless of whether there are any symbols in it.
526  if (HasObject && SymNames.tell() == 0)
527  SymNames << '\0' << '\0' << '\0';
528  return Ret;
529 }
530 
531 namespace llvm {
532 
535  std::error_code Err = sys::fs::make_absolute(Ret);
536  if (Err)
537  return Err;
538  sys::path::remove_dots(Ret, /*removedotdot*/ true);
539  return Ret;
540 }
541 
542 // Compute the relative path from From to To.
544  ErrorOr<SmallString<128>> PathToOrErr = canonicalizePath(To);
546  if (!PathToOrErr || !DirFromOrErr)
547  return errorCodeToError(std::error_code(errno, std::generic_category()));
548 
549  const SmallString<128> &PathTo = *PathToOrErr;
550  const SmallString<128> &DirFrom = sys::path::parent_path(*DirFromOrErr);
551 
552  // Can't construct a relative path between different roots
553  if (sys::path::root_name(PathTo) != sys::path::root_name(DirFrom))
554  return sys::path::convert_to_slash(PathTo);
555 
556  // Skip common prefixes
557  auto FromTo =
558  std::mismatch(sys::path::begin(DirFrom), sys::path::end(DirFrom),
559  sys::path::begin(PathTo));
560  auto FromI = FromTo.first;
561  auto ToI = FromTo.second;
562 
563  // Construct relative path
564  SmallString<128> Relative;
565  for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
567 
568  for (auto ToE = sys::path::end(PathTo); ToI != ToE; ++ToI)
570 
571  return std::string(Relative.str());
572 }
573 
575  ArrayRef<NewArchiveMember> NewMembers,
576  bool WriteSymtab, object::Archive::Kind Kind,
577  bool Deterministic, bool Thin) {
578  assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode");
579 
580  SmallString<0> SymNamesBuf;
581  raw_svector_ostream SymNames(SymNamesBuf);
582  SmallString<0> StringTableBuf;
583  raw_svector_ostream StringTable(StringTableBuf);
584 
586  computeMemberData(StringTable, SymNames, Kind, Thin, Deterministic,
587  WriteSymtab, NewMembers);
588  if (Error E = DataOrErr.takeError())
589  return E;
590  std::vector<MemberData> &Data = *DataOrErr;
591 
592  if (!StringTableBuf.empty())
593  Data.insert(Data.begin(), computeStringTable(StringTableBuf));
594 
595  // We would like to detect if we need to switch to a 64-bit symbol table.
596  if (WriteSymtab) {
597  uint64_t MaxOffset = 8; // For the file signature.
598  uint64_t LastOffset = MaxOffset;
599  uint64_t NumSyms = 0;
600  for (const auto &M : Data) {
601  // Record the start of the member's offset
602  LastOffset = MaxOffset;
603  // Account for the size of each part associated with the member.
604  MaxOffset += M.Header.size() + M.Data.size() + M.Padding.size();
605  NumSyms += M.Symbols.size();
606  }
607 
608  // We assume 32-bit offsets to see if 32-bit symbols are possible or not.
609  uint64_t SymtabSize = computeSymbolTableSize(Kind, NumSyms, 4, SymNamesBuf);
610  auto computeSymbolTableHeaderSize =
611  [=] {
612  SmallString<0> TmpBuf;
613  raw_svector_ostream Tmp(TmpBuf);
614  writeSymbolTableHeader(Tmp, Kind, Deterministic, SymtabSize);
615  return TmpBuf.size();
616  };
617  LastOffset += computeSymbolTableHeaderSize() + SymtabSize;
618 
619  // The SYM64 format is used when an archive's member offsets are larger than
620  // 32-bits can hold. The need for this shift in format is detected by
621  // writeArchive. To test this we need to generate a file with a member that
622  // has an offset larger than 32-bits but this demands a very slow test. To
623  // speed the test up we use this environment variable to pretend like the
624  // cutoff happens before 32-bits and instead happens at some much smaller
625  // value.
626  uint64_t Sym64Threshold = 1ULL << 32;
627  const char *Sym64Env = std::getenv("SYM64_THRESHOLD");
628  if (Sym64Env)
629  StringRef(Sym64Env).getAsInteger(10, Sym64Threshold);
630 
631  // If LastOffset isn't going to fit in a 32-bit varible we need to switch
632  // to 64-bit. Note that the file can be larger than 4GB as long as the last
633  // member starts before the 4GB offset.
634  if (LastOffset >= Sym64Threshold) {
637  else
639  }
640  }
641 
642  if (Thin)
643  Out << "!<thin>\n";
644  else
645  Out << "!<arch>\n";
646 
647  if (WriteSymtab)
648  writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf);
649 
650  for (const MemberData &M : Data)
651  Out << M.Header << M.Data << M.Padding;
652 
653  Out.flush();
654  return Error::success();
655 }
656 
658  bool WriteSymtab, object::Archive::Kind Kind,
659  bool Deterministic, bool Thin,
660  std::unique_ptr<MemoryBuffer> OldArchiveBuf) {
662  sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a");
663  if (!Temp)
664  return Temp.takeError();
665  raw_fd_ostream Out(Temp->FD, false);
666 
667  if (Error E = writeArchiveToStream(Out, NewMembers, WriteSymtab, Kind,
668  Deterministic, Thin)) {
669  if (Error DiscardError = Temp->discard())
670  return joinErrors(std::move(E), std::move(DiscardError));
671  return E;
672  }
673 
674  // At this point, we no longer need whatever backing memory
675  // was used to generate the NewMembers. On Windows, this buffer
676  // could be a mapped view of the file we want to replace (if
677  // we're updating an existing archive, say). In that case, the
678  // rename would still succeed, but it would leave behind a
679  // temporary file (actually the original file renamed) because
680  // a file cannot be deleted while there's a handle open on it,
681  // only renamed. So by freeing this buffer, this ensures that
682  // the last open handle on the destination file, if any, is
683  // closed before we attempt to rename.
684  OldArchiveBuf.reset();
685 
686  return Temp->keep(ArcName);
687 }
688 
691  object::Archive::Kind Kind, bool Deterministic,
692  bool Thin) {
693  SmallVector<char, 0> ArchiveBufferVector;
694  raw_svector_ostream ArchiveStream(ArchiveBufferVector);
695 
696  if (Error E = writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab,
697  Kind, Deterministic, Thin))
698  return std::move(E);
699 
700  return std::make_unique<SmallVectorMemoryBuffer>(
701  std::move(ArchiveBufferVector), /*RequiresNullTerminator=*/false);
702 }
703 
704 } // namespace llvm
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
llvm::NewArchiveMember
Definition: ArchiveWriter.h:20
llvm::object::Archive::K_GNU64
@ K_GNU64
Definition: Archive.h:338
llvm::raw_ostream::tell
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:135
llvm::object::Archive::K_COFF
@ K_COFF
Definition: Archive.h:338
llvm::sys::fs::file_t
int file_t
Definition: FileSystem.h:60
isDarwin
static bool isDarwin(object::Archive::Kind Kind)
Definition: ArchiveWriter.cpp:126
llvm::object::Archive::Kind
Kind
Definition: Archive.h:338
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::NewArchiveMember::getFile
static Expected< NewArchiveMember > getFile(StringRef FileName, bool Deterministic)
Definition: ArchiveWriter.cpp:78
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::object::Archive::K_BSD
@ K_BSD
Definition: Archive.h:338
llvm::MemoryBuffer::getOpenFile
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
Definition: MemoryBuffer.cpp:493
llvm::file_magic
file_magic - An "enum class" enumeration of file types based on magic (the first N bytes of the file)...
Definition: Magic.h:20
print
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Definition: ArchiveWriter.cpp:148
printRestOfMemberHeader
static void printRestOfMemberHeader(raw_ostream &Out, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, uint64_t Size)
Definition: ArchiveWriter.cpp:153
llvm::sys::path::Style::posix
@ posix
T
printWithSpacePadding
static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size)
Definition: ArchiveWriter.cpp:118
StringRef.h
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:631
llvm::SmallVector< char, 0 >
llvm::errc::is_a_directory
@ is_a_directory
Path.h
llvm::sys::path::convert_to_slash
std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
Definition: Path.cpp:569
ErrorHandling.h
SmallVectorMemoryBuffer.h
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
writeSymbolTableHeader
static void writeSymbolTableHeader(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, uint64_t Size)
Definition: ArchiveWriter.cpp:315
llvm::object::Archive::K_GNU
@ K_GNU
Definition: Archive.h:338
Errc.h
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::sys::path::end
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:236
llvm::sys::path::begin
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:227
llvm::MemoryBufferRef::getBufferSize
size_t getBufferSize() const
Definition: MemoryBufferRef.h:37
llvm::object::Archive::Child::getGID
Expected< unsigned > getGID() const
Definition: Archive.h:238
llvm::MipsISD::Ret
@ Ret
Definition: MipsISelLowering.h:116
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
SymbolicFile.h
computeStringTable
static MemberData computeStringTable(StringRef Names)
Definition: ArchiveWriter.cpp:249
Format.h
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::MemoryBufferRef
Definition: MemoryBufferRef.h:22
llvm::MemoryBuffer
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:50
Context
ManagedStatic< detail::RecordContext > Context
Definition: Record.cpp:96
llvm::sys::TimePoint
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition: Chrono.h:34
llvm::file_magic::bitcode
@ bitcode
Bitcode file.
Definition: Magic.h:23
llvm::sys::path::append
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:457
isBSDLike
static bool isBSDLike(object::Archive::Kind Kind)
Definition: ArchiveWriter.cpp:131
llvm::MemoryBuffer::getMemBuffer
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
Definition: MemoryBuffer.cpp:112
Error.h
ArchiveWriter.h
Magic.h
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::support::little
@ little
Definition: Endian.h:27
llvm::StringMap::insert
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition: StringMap.h:274
llvm::errorCodeToError
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:90
llvm::object::BasicSymbolRef
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: SymbolicFile.h:101
llvm::object::Archive::MaxMemberSize
static const uint64_t MaxMemberSize
Size field is 10 decimal digits long.
Definition: Archive.h:336
llvm::writeArchive
Error writeArchive(StringRef ArcName, ArrayRef< NewArchiveMember > NewMembers, bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr< MemoryBuffer > OldArchiveBuf=nullptr)
Definition: ArchiveWriter.cpp:657
useStringTable
static bool useStringTable(bool Thin, StringRef Name)
Definition: ArchiveWriter.cpp:193
false
Definition: StackSlotColoring.cpp:142
llvm::ErrorOr::getError
std::error_code getError() const
Definition: ErrorOr.h:153
llvm::raw_ostream::write
raw_ostream & write(unsigned char C)
Definition: raw_ostream.cpp:219
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:143
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::raw_ostream::flush
void flush()
Definition: raw_ostream.h:186
llvm::object::object_error::parse_failed
@ parse_failed
llvm::sys::fs::openNativeFileForRead
Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
StringMap.h
llvm::object::Archive::Child::getLastModified
Expected< sys::TimePoint< std::chrono::seconds > > getLastModified() const
Definition: Archive.h:229
Align
uint64_t Align
Definition: ELFObjHandler.cpp:82
isArchiveSymbol
static bool isArchiveSymbol(const object::BasicSymbolRef &S)
Definition: ArchiveWriter.cpp:269
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
llvm::StringRef::getAsInteger
std::enable_if_t< std::numeric_limits< T >::is_signed, bool > getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:509
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
now
static sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
Definition: ArchiveWriter.cpp:261
llvm::StringMap< uint64_t >
llvm::SmallString< 128 >
llvm::support::endian::write
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition: Endian.h:97
llvm::object::Archive::Child::getUID
Expected< unsigned > getUID() const
Definition: Archive.h:237
llvm::object::SymbolicFile::isSymbolicFile
static bool isSymbolicFile(file_magic Type, const LLVMContext *Context)
Definition: SymbolicFile.cpp:98
writeSymbolTable
static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef< MemberData > Members, StringRef StringTable)
Definition: ArchiveWriter.cpp:327
llvm::sys::fs::file_status
Represents the result of a call to sys::fs::status().
Definition: FileSystem.h:226
llvm::object::BasicSymbolRef::SF_FormatSpecific
@ SF_FormatSpecific
Definition: SymbolicFile.h:115
llvm::sys::path::remove_dots
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
Definition: Path.cpp:716
llvm::object::Archive::K_DARWIN64
@ K_DARWIN64
Definition: Archive.h:338
uint64_t
llvm::NewArchiveMember::NewArchiveMember
NewArchiveMember()=default
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
llvm::object::BasicSymbolRef::SF_Undefined
@ SF_Undefined
Definition: SymbolicFile.h:108
Archive.h
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:427
llvm::object::Archive::Child::getAccessMode
Expected< sys::fs::perms > getAccessMode() const
Definition: Archive.h:240
ArrayRef.h
ToolOutputFile.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::sys::path::parent_path
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:468
llvm::canonicalizePath
static ErrorOr< SmallString< 128 > > canonicalizePath(StringRef P)
Definition: ArchiveWriter.cpp:533
ObjectFile.h
llvm::sys::fs::closeFile
std::error_code closeFile(file_t &F)
Close the file object.
llvm::MemoryBufferRef::getBuffer
StringRef getBuffer() const
Definition: MemoryBufferRef.h:32
llvm::sys::fs::make_absolute
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:903
Status
Definition: SIModeRegister.cpp:28
llvm::sys::fs::kInvalidFile
const file_t kInvalidFile
llvm::computeArchiveRelativePath
Expected< std::string > computeArchiveRelativePath(StringRef From, StringRef To)
Definition: ArchiveWriter.cpp:543
llvm::object::Archive::K_AIXBIG
@ K_AIXBIG
Definition: Archive.h:338
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
printGNUSmallMemberHeader
static void printGNUSmallMemberHeader(raw_ostream &Out, StringRef Name, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, uint64_t Size)
Definition: ArchiveWriter.cpp:169
llvm::Expected::get
reference get()
Returns a reference to the stored T value.
Definition: Error.h:568
uint32_t
printMemberHeader
static void printMemberHeader(raw_ostream &Out, uint64_t Pos, raw_ostream &StringTable, StringMap< uint64_t > &MemberNames, object::Archive::Kind Kind, bool Thin, const NewArchiveMember &M, sys::TimePoint< std::chrono::seconds > ModTime, uint64_t Size)
Definition: ArchiveWriter.cpp:213
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:443
llvm::object::Archive::Child
Definition: Archive.h:162
llvm::make_error_code
std::error_code make_error_code(BitcodeError E)
Definition: BitcodeReader.h:270
is64BitKind
static bool is64BitKind(object::Archive::Kind Kind)
Definition: ArchiveWriter.cpp:197
llvm::StringRef::size
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:156
llvm::sys::fs::file_type::directory_file
@ directory_file
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
Alignment.h
llvm::sys::path::root_name
StringRef root_name(StringRef path, Style style=Style::native)
Get root name.
Definition: Path.cpp:374
llvm::sys::toTimeT
std::time_t toTimeT(TimePoint<> TP)
Convert a TimePoint to std::time_t.
Definition: Chrono.h:37
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
EndianStream.h
llvm::writeArchiveToStream
static Error writeArchiveToStream(raw_ostream &Out, ArrayRef< NewArchiveMember > NewMembers, bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin)
Definition: ArchiveWriter.cpp:574
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
llvm::object::SymbolicFile::createSymbolicFile
static Expected< std::unique_ptr< SymbolicFile > > createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type, LLVMContext *Context, bool InitContent=true)
getSymbols
static Expected< std::vector< unsigned > > getSymbols(MemoryBufferRef Buf, raw_ostream &SymNames, bool &HasObject)
Definition: ArchiveWriter.cpp:370
llvm::SmallString::str
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:259
llvm::object::Archive::K_DARWIN
@ K_DARWIN
Definition: Archive.h:338
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:598
llvm::raw_ostream::indent
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
Definition: raw_ostream.cpp:496
llvm::sys::fs::status
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
computeSymbolTableSize
static uint64_t computeSymbolTableSize(object::Archive::Kind Kind, uint64_t NumSyms, uint64_t OffsetSize, StringRef StringTable, uint32_t *Padding=nullptr)
Definition: ArchiveWriter.cpp:291
llvm::object::BasicSymbolRef::SF_Global
@ SF_Global
Definition: SymbolicFile.h:109
llvm::sys::toTimePoint
TimePoint< std::chrono::seconds > toTimePoint(std::time_t T)
Convert a std::time_t to a TimePoint.
Definition: Chrono.h:45
llvm::ErrorOr
Represents either an error or a value T.
Definition: ErrorOr.h:56
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:661
computeMemberData
static Expected< std::vector< MemberData > > computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, object::Archive::Kind Kind, bool Thin, bool Deterministic, bool NeedSymbols, ArrayRef< NewArchiveMember > NewMembers)
Definition: ArchiveWriter.cpp:408
llvm::object::Archive::Child::getMemoryBufferRef
Expected< MemoryBufferRef > getMemoryBufferRef() const
Definition: Archive.cpp:627
LLVMContext.h
From
BlockVerifier::State From
Definition: BlockVerifier.cpp:55
llvm::sys::fs::TempFile::create
static Expected< TempFile > create(const Twine &Model, unsigned Mode=all_read|all_write, OpenFlags ExtraFlags=OF_None)
This creates a temporary file with createUniqueFile and schedules it for deletion with sys::RemoveFil...
Definition: Path.cpp:1324
raw_ostream.h
llvm::identify_magic
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition: Magic.cpp:35
llvm::NewArchiveMember::getOldMember
static Expected< NewArchiveMember > getOldMember(const object::Archive::Child &OldMember, bool Deterministic)
Definition: ArchiveWriter.cpp:48
printNBits
static void printNBits(raw_ostream &Out, object::Archive::Kind Kind, uint64_t Val)
Definition: ArchiveWriter.cpp:283
llvm::offsetToAlignment
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
Definition: Alignment.h:196
printBSDMemberHeader
static void printBSDMemberHeader(raw_ostream &Out, uint64_t Pos, StringRef Name, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, uint64_t Size)
Definition: ArchiveWriter.cpp:178
llvm::support::big
@ big
Definition: Endian.h:27
llvm::writeArchiveToBuffer
Expected< std::unique_ptr< MemoryBuffer > > writeArchiveToBuffer(ArrayRef< NewArchiveMember > NewMembers, bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin)
Definition: ArchiveWriter.cpp:690