LLVM  9.0.0svn
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/StringRef.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "llvm/Object/Archive.h"
19 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Support/Errc.h"
24 #include "llvm/Support/Format.h"
25 #include "llvm/Support/Path.h"
28 
29 #include <map>
30 
31 #if !defined(_MSC_VER) && !defined(__MINGW32__)
32 #include <unistd.h>
33 #else
34 #include <io.h>
35 #endif
36 
37 using namespace llvm;
38 
40  : Buf(MemoryBuffer::getMemBuffer(BufRef, false)),
41  MemberName(BufRef.getBufferIdentifier()) {}
42 
45  bool Deterministic) {
47  if (!BufOrErr)
48  return BufOrErr.takeError();
49 
51  M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
52  M.MemberName = M.Buf->getBufferIdentifier();
53  if (!Deterministic) {
54  auto ModTimeOrErr = OldMember.getLastModified();
55  if (!ModTimeOrErr)
56  return ModTimeOrErr.takeError();
57  M.ModTime = ModTimeOrErr.get();
58  Expected<unsigned> UIDOrErr = OldMember.getUID();
59  if (!UIDOrErr)
60  return UIDOrErr.takeError();
61  M.UID = UIDOrErr.get();
62  Expected<unsigned> GIDOrErr = OldMember.getGID();
63  if (!GIDOrErr)
64  return GIDOrErr.takeError();
65  M.GID = GIDOrErr.get();
66  Expected<sys::fs::perms> AccessModeOrErr = OldMember.getAccessMode();
67  if (!AccessModeOrErr)
68  return AccessModeOrErr.takeError();
69  M.Perms = AccessModeOrErr.get();
70  }
71  return std::move(M);
72 }
73 
75  bool Deterministic) {
77  auto FDOrErr = sys::fs::openNativeFileForRead(FileName);
78  if (!FDOrErr)
79  return FDOrErr.takeError();
80  sys::fs::file_t FD = *FDOrErr;
82 
83  if (auto EC = sys::fs::status(FD, Status))
84  return errorCodeToError(EC);
85 
86  // Opening a directory doesn't make sense. Let it fail.
87  // Linux cannot open directories with open(2), although
88  // cygwin and *bsd can.
91 
92  ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
93  MemoryBuffer::getOpenFile(FD, FileName, Status.getSize(), false);
94  if (!MemberBufferOrErr)
95  return errorCodeToError(MemberBufferOrErr.getError());
96 
97  if (auto EC = sys::fs::closeFile(FD))
98  return errorCodeToError(EC);
99 
101  M.Buf = std::move(*MemberBufferOrErr);
102  M.MemberName = M.Buf->getBufferIdentifier();
103  if (!Deterministic) {
104  M.ModTime = std::chrono::time_point_cast<std::chrono::seconds>(
105  Status.getLastModificationTime());
106  M.UID = Status.getUser();
107  M.GID = Status.getGroup();
108  M.Perms = Status.permissions();
109  }
110  return std::move(M);
111 }
112 
113 template <typename T>
114 static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size) {
115  uint64_t OldPos = OS.tell();
116  OS << Data;
117  unsigned SizeSoFar = OS.tell() - OldPos;
118  assert(SizeSoFar <= Size && "Data doesn't fit in Size");
119  OS.indent(Size - SizeSoFar);
120 }
121 
123  return Kind == object::Archive::K_DARWIN ||
125 }
126 
128  switch (Kind) {
131  return false;
135  return true;
137  break;
138  }
139  llvm_unreachable("not supported for writting");
140 }
141 
142 template <class T>
143 static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val) {
144  support::endian::write(Out, Val,
146 }
147 
150  unsigned UID, unsigned GID, unsigned Perms, unsigned Size) {
151  printWithSpacePadding(Out, sys::toTimeT(ModTime), 12);
152 
153  // The format has only 6 chars for uid and gid. Truncate if the provided
154  // values don't fit.
155  printWithSpacePadding(Out, UID % 1000000, 6);
156  printWithSpacePadding(Out, GID % 1000000, 6);
157 
158  printWithSpacePadding(Out, format("%o", Perms), 8);
159  printWithSpacePadding(Out, Size, 10);
160  Out << "`\n";
161 }
162 
163 static void
166  unsigned UID, unsigned GID, unsigned Perms,
167  unsigned Size) {
168  printWithSpacePadding(Out, Twine(Name) + "/", 16);
169  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
170 }
171 
172 static void
175  unsigned UID, unsigned GID, unsigned Perms,
176  unsigned Size) {
177  uint64_t PosAfterHeader = Pos + 60 + Name.size();
178  // Pad so that even 64 bit object files are aligned.
179  unsigned Pad = OffsetToAlignment(PosAfterHeader, 8);
180  unsigned NameWithPadding = Name.size() + Pad;
181  printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
182  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
183  NameWithPadding + Size);
184  Out << Name;
185  while (Pad--)
186  Out.write(uint8_t(0));
187 }
188 
189 static bool useStringTable(bool Thin, StringRef Name) {
190  return Thin || Name.size() >= 16 || Name.contains('/');
191 }
192 
194  switch (Kind) {
199  return false;
202  return true;
203  }
204  llvm_unreachable("not supported for writting");
205 }
206 
207 static void
208 printMemberHeader(raw_ostream &Out, uint64_t Pos, raw_ostream &StringTable,
210  bool Thin, const NewArchiveMember &M,
212  if (isBSDLike(Kind))
213  return printBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID,
214  M.Perms, Size);
215  if (!useStringTable(Thin, M.MemberName))
216  return printGNUSmallMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
217  M.Perms, Size);
218  Out << '/';
219  uint64_t NamePos;
220  if (Thin) {
221  NamePos = StringTable.tell();
222  StringTable << M.MemberName << "/\n";
223  } else {
224  auto Insertion = MemberNames.insert({M.MemberName, uint64_t(0)});
225  if (Insertion.second) {
226  Insertion.first->second = StringTable.tell();
227  StringTable << M.MemberName << "/\n";
228  }
229  NamePos = Insertion.first->second;
230  }
231  printWithSpacePadding(Out, NamePos, 15);
232  printRestOfMemberHeader(Out, ModTime, M.UID, M.GID, M.Perms, Size);
233 }
234 
235 namespace {
236 struct MemberData {
237  std::vector<unsigned> Symbols;
238  std::string Header;
239  StringRef Data;
240  StringRef Padding;
241 };
242 } // namespace
243 
244 static MemberData computeStringTable(StringRef Names) {
245  unsigned Size = Names.size();
246  unsigned Pad = OffsetToAlignment(Size, 2);
247  std::string Header;
248  raw_string_ostream Out(Header);
249  printWithSpacePadding(Out, "//", 48);
250  printWithSpacePadding(Out, Size + Pad, 10);
251  Out << "`\n";
252  Out.flush();
253  return {{}, std::move(Header), Names, Pad ? "\n" : ""};
254 }
255 
256 static sys::TimePoint<std::chrono::seconds> now(bool Deterministic) {
257  using namespace std::chrono;
258 
259  if (!Deterministic)
260  return time_point_cast<seconds>(system_clock::now());
261  return sys::TimePoint<seconds>();
262 }
263 
265  uint32_t Symflags = S.getFlags();
267  return false;
268  if (!(Symflags & object::SymbolRef::SF_Global))
269  return false;
270  if (Symflags & object::SymbolRef::SF_Undefined)
271  return false;
272  return true;
273 }
274 
276  uint64_t Val) {
277  if (is64BitKind(Kind))
278  print<uint64_t>(Out, Kind, Val);
279  else
280  print<uint32_t>(Out, Kind, Val);
281 }
282 
284  bool Deterministic, ArrayRef<MemberData> Members,
285  StringRef StringTable) {
286  // We don't write a symbol table on an archive with no members -- except on
287  // Darwin, where the linker will abort unless the archive has a symbol table.
288  if (StringTable.empty() && !isDarwin(Kind))
289  return;
290 
291  unsigned NumSyms = 0;
292  for (const MemberData &M : Members)
293  NumSyms += M.Symbols.size();
294 
295  unsigned Size = 0;
296  unsigned OffsetSize = is64BitKind(Kind) ? sizeof(uint64_t) : sizeof(uint32_t);
297 
298  Size += OffsetSize; // Number of entries
299  if (isBSDLike(Kind))
300  Size += NumSyms * OffsetSize * 2; // Table
301  else
302  Size += NumSyms * OffsetSize; // Table
303  if (isBSDLike(Kind))
304  Size += OffsetSize; // byte count
305  Size += StringTable.size();
306  // ld64 expects the members to be 8-byte aligned for 64-bit content and at
307  // least 4-byte aligned for 32-bit content. Opt for the larger encoding
308  // uniformly.
309  // We do this for all bsd formats because it simplifies aligning members.
310  unsigned Alignment = isBSDLike(Kind) ? 8 : 2;
311  unsigned Pad = OffsetToAlignment(Size, Alignment);
312  Size += Pad;
313 
314  if (isBSDLike(Kind)) {
315  const char *Name = is64BitKind(Kind) ? "__.SYMDEF_64" : "__.SYMDEF";
316  printBSDMemberHeader(Out, Out.tell(), Name, now(Deterministic), 0, 0, 0,
317  Size);
318  } else {
319  const char *Name = is64BitKind(Kind) ? "/SYM64" : "";
320  printGNUSmallMemberHeader(Out, Name, now(Deterministic), 0, 0, 0, Size);
321  }
322 
323  uint64_t Pos = Out.tell() + Size;
324 
325  if (isBSDLike(Kind))
326  printNBits(Out, Kind, NumSyms * 2 * OffsetSize);
327  else
328  printNBits(Out, Kind, NumSyms);
329 
330  for (const MemberData &M : Members) {
331  for (unsigned StringOffset : M.Symbols) {
332  if (isBSDLike(Kind))
333  printNBits(Out, Kind, StringOffset);
334  printNBits(Out, Kind, Pos); // member offset
335  }
336  Pos += M.Header.size() + M.Data.size() + M.Padding.size();
337  }
338 
339  if (isBSDLike(Kind))
340  // byte count of the string table
341  printNBits(Out, Kind, StringTable.size());
342  Out << StringTable;
343 
344  while (Pad--)
345  Out.write(uint8_t(0));
346 }
347 
349 getSymbols(MemoryBufferRef Buf, raw_ostream &SymNames, bool &HasObject) {
350  std::vector<unsigned> Ret;
351 
352  // In the scenario when LLVMContext is populated SymbolicFile will contain a
353  // reference to it, thus SymbolicFile should be destroyed first.
355  std::unique_ptr<object::SymbolicFile> Obj;
358  Buf, file_magic::bitcode, &Context);
359  if (!ObjOrErr) {
360  // FIXME: check only for "not an object file" errors.
361  consumeError(ObjOrErr.takeError());
362  return Ret;
363  }
364  Obj = std::move(*ObjOrErr);
365  } else {
366  auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf);
367  if (!ObjOrErr) {
368  // FIXME: check only for "not an object file" errors.
369  consumeError(ObjOrErr.takeError());
370  return Ret;
371  }
372  Obj = std::move(*ObjOrErr);
373  }
374 
375  HasObject = true;
376  for (const object::BasicSymbolRef &S : Obj->symbols()) {
377  if (!isArchiveSymbol(S))
378  continue;
379  Ret.push_back(SymNames.tell());
380  if (Error E = S.printName(SymNames))
381  return std::move(E);
382  SymNames << '\0';
383  }
384  return Ret;
385 }
386 
388 computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
389  object::Archive::Kind Kind, bool Thin, bool Deterministic,
390  ArrayRef<NewArchiveMember> NewMembers) {
391  static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
392 
393  // This ignores the symbol table, but we only need the value mod 8 and the
394  // symbol table is aligned to be a multiple of 8 bytes
395  uint64_t Pos = 0;
396 
397  std::vector<MemberData> Ret;
398  bool HasObject = false;
399 
400  // Deduplicate long member names in the string table and reuse earlier name
401  // offsets. This especially saves space for COFF Import libraries where all
402  // members have the same name.
403  StringMap<uint64_t> MemberNames;
404 
405  // UniqueTimestamps is a special case to improve debugging on Darwin:
406  //
407  // The Darwin linker does not link debug info into the final
408  // binary. Instead, it emits entries of type N_OSO in in the output
409  // binary's symbol table, containing references to the linked-in
410  // object files. Using that reference, the debugger can read the
411  // debug data directly from the object files. Alternatively, an
412  // invocation of 'dsymutil' will link the debug data from the object
413  // files into a dSYM bundle, which can be loaded by the debugger,
414  // instead of the object files.
415  //
416  // For an object file, the N_OSO entries contain the absolute path
417  // path to the file, and the file's timestamp. For an object
418  // included in an archive, the path is formatted like
419  // "/absolute/path/to/archive.a(member.o)", and the timestamp is the
420  // archive member's timestamp, rather than the archive's timestamp.
421  //
422  // However, this doesn't always uniquely identify an object within
423  // an archive -- an archive file can have multiple entries with the
424  // same filename. (This will happen commonly if the original object
425  // files started in different directories.) The only way they get
426  // distinguished, then, is via the timestamp. But this process is
427  // unable to find the correct object file in the archive when there
428  // are two files of the same name and timestamp.
429  //
430  // Additionally, timestamp==0 is treated specially, and causes the
431  // timestamp to be ignored as a match criteria.
432  //
433  // That will "usually" work out okay when creating an archive not in
434  // deterministic timestamp mode, because the objects will probably
435  // have been created at different timestamps.
436  //
437  // To ameliorate this problem, in deterministic archive mode (which
438  // is the default), on Darwin we will emit a unique non-zero
439  // timestamp for each entry with a duplicated name. This is still
440  // deterministic: the only thing affecting that timestamp is the
441  // order of the files in the resultant archive.
442  //
443  // See also the functions that handle the lookup:
444  // in lldb: ObjectContainerBSDArchive::Archive::FindObject()
445  // in llvm/tools/dsymutil: BinaryHolder::GetArchiveMemberBuffers().
446  bool UniqueTimestamps = Deterministic && isDarwin(Kind);
447  std::map<StringRef, unsigned> FilenameCount;
448  if (UniqueTimestamps) {
449  for (const NewArchiveMember &M : NewMembers)
450  FilenameCount[M.MemberName]++;
451  for (auto &Entry : FilenameCount)
452  Entry.second = Entry.second > 1 ? 1 : 0;
453  }
454 
455  for (const NewArchiveMember &M : NewMembers) {
456  std::string Header;
457  raw_string_ostream Out(Header);
458 
459  MemoryBufferRef Buf = M.Buf->getMemBufferRef();
460  StringRef Data = Thin ? "" : Buf.getBuffer();
461 
462  // ld64 expects the members to be 8-byte aligned for 64-bit content and at
463  // least 4-byte aligned for 32-bit content. Opt for the larger encoding
464  // uniformly. This matches the behaviour with cctools and ensures that ld64
465  // is happy with archives that we generate.
466  unsigned MemberPadding =
467  isDarwin(Kind) ? OffsetToAlignment(Data.size(), 8) : 0;
468  unsigned TailPadding = OffsetToAlignment(Data.size() + MemberPadding, 2);
469  StringRef Padding = StringRef(PaddingData, MemberPadding + TailPadding);
470 
472  if (UniqueTimestamps)
473  // Increment timestamp for each file of a given name.
474  ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);
475  else
476  ModTime = M.ModTime;
477  printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M,
478  ModTime, Buf.getBufferSize() + MemberPadding);
479  Out.flush();
480 
482  getSymbols(Buf, SymNames, HasObject);
483  if (auto E = Symbols.takeError())
484  return std::move(E);
485 
486  Pos += Header.size() + Data.size() + Padding.size();
487  Ret.push_back({std::move(*Symbols), std::move(Header), Data, Padding});
488  }
489  // If there are no symbols, emit an empty symbol table, to satisfy Solaris
490  // tools, older versions of which expect a symbol table in a non-empty
491  // archive, regardless of whether there are any symbols in it.
492  if (HasObject && SymNames.tell() == 0)
493  SymNames << '\0' << '\0' << '\0';
494  return Ret;
495 }
496 
497 namespace llvm {
498 
501  std::error_code Err = sys::fs::make_absolute(Ret);
502  if (Err)
503  return Err;
504  sys::path::remove_dots(Ret, /*removedotdot*/ true);
505  return Ret;
506 }
507 
508 // Compute the relative path from From to To.
510  ErrorOr<SmallString<128>> PathToOrErr = canonicalizePath(To);
511  ErrorOr<SmallString<128>> DirFromOrErr = canonicalizePath(From);
512  if (!PathToOrErr || !DirFromOrErr)
513  return errorCodeToError(std::error_code(errno, std::generic_category()));
514 
515  const SmallString<128> &PathTo = *PathToOrErr;
516  const SmallString<128> &DirFrom = sys::path::parent_path(*DirFromOrErr);
517 
518  // Can't construct a relative path between different roots
519  if (sys::path::root_name(PathTo) != sys::path::root_name(DirFrom))
520  return sys::path::convert_to_slash(PathTo);
521 
522  // Skip common prefixes
523  auto FromTo =
524  std::mismatch(sys::path::begin(DirFrom), sys::path::end(DirFrom),
525  sys::path::begin(PathTo));
526  auto FromI = FromTo.first;
527  auto ToI = FromTo.second;
528 
529  // Construct relative path
530  SmallString<128> Relative;
531  for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
533 
534  for (auto ToE = sys::path::end(PathTo); ToI != ToE; ++ToI)
536 
537  return Relative.str();
538 }
539 
541  bool WriteSymtab, object::Archive::Kind Kind,
542  bool Deterministic, bool Thin,
543  std::unique_ptr<MemoryBuffer> OldArchiveBuf) {
544  assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode");
545 
546  SmallString<0> SymNamesBuf;
547  raw_svector_ostream SymNames(SymNamesBuf);
548  SmallString<0> StringTableBuf;
549  raw_svector_ostream StringTable(StringTableBuf);
550 
552  StringTable, SymNames, Kind, Thin, Deterministic, NewMembers);
553  if (Error E = DataOrErr.takeError())
554  return E;
555  std::vector<MemberData> &Data = *DataOrErr;
556 
557  if (!StringTableBuf.empty())
558  Data.insert(Data.begin(), computeStringTable(StringTableBuf));
559 
560  // We would like to detect if we need to switch to a 64-bit symbol table.
561  if (WriteSymtab) {
562  uint64_t MaxOffset = 0;
563  uint64_t LastOffset = MaxOffset;
564  for (const auto &M : Data) {
565  // Record the start of the member's offset
566  LastOffset = MaxOffset;
567  // Account for the size of each part associated with the member.
568  MaxOffset += M.Header.size() + M.Data.size() + M.Padding.size();
569  // We assume 32-bit symbols to see if 32-bit symbols are possible or not.
570  MaxOffset += M.Symbols.size() * 4;
571  }
572 
573  // The SYM64 format is used when an archive's member offsets are larger than
574  // 32-bits can hold. The need for this shift in format is detected by
575  // writeArchive. To test this we need to generate a file with a member that
576  // has an offset larger than 32-bits but this demands a very slow test. To
577  // speed the test up we use this environment variable to pretend like the
578  // cutoff happens before 32-bits and instead happens at some much smaller
579  // value.
580  const char *Sym64Env = std::getenv("SYM64_THRESHOLD");
581  int Sym64Threshold = 32;
582  if (Sym64Env)
583  StringRef(Sym64Env).getAsInteger(10, Sym64Threshold);
584 
585  // If LastOffset isn't going to fit in a 32-bit varible we need to switch
586  // to 64-bit. Note that the file can be larger than 4GB as long as the last
587  // member starts before the 4GB offset.
588  if (LastOffset >= (1ULL << Sym64Threshold)) {
589  if (Kind == object::Archive::K_DARWIN)
591  else
593  }
594  }
595 
597  sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a");
598  if (!Temp)
599  return Temp.takeError();
600 
601  raw_fd_ostream Out(Temp->FD, false);
602  if (Thin)
603  Out << "!<thin>\n";
604  else
605  Out << "!<arch>\n";
606 
607  if (WriteSymtab)
608  writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf);
609 
610  for (const MemberData &M : Data)
611  Out << M.Header << M.Data << M.Padding;
612 
613  Out.flush();
614 
615  // At this point, we no longer need whatever backing memory
616  // was used to generate the NewMembers. On Windows, this buffer
617  // could be a mapped view of the file we want to replace (if
618  // we're updating an existing archive, say). In that case, the
619  // rename would still succeed, but it would leave behind a
620  // temporary file (actually the original file renamed) because
621  // a file cannot be deleted while there's a handle open on it,
622  // only renamed. So by freeing this buffer, this ensures that
623  // the last open handle on the destination file, if any, is
624  // closed before we attempt to rename.
625  OldArchiveBuf.reset();
626 
627  return Temp->keep(ArcName);
628 }
629 
630 } // namespace llvm
const file_t kInvalidFile
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:233
Represents either an error or a value T.
Definition: ErrorOr.h:56
LLVMContext & Context
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:224
This class represents lattice values for constants.
Definition: AllocatorList.h:23
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
static Expected< std::unique_ptr< SymbolicFile > > createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type, LLVMContext *Context)
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:123
static void printBSDMemberHeader(raw_ostream &Out, uint64_t Pos, StringRef Name, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, unsigned Size)
raw_ostream & indent(unsigned NumSpaces)
indent - Insert &#39;NumSpaces&#39; spaces.
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:509
std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
Definition: Path.cpp:556
Error takeError()
Take ownership of the stored error.
Definition: Error.h:552
static Expected< TempFile > create(const Twine &Model, unsigned Mode=all_read|all_write)
This creates a temporary file with createUniqueFile and schedules it for deletion with sys::RemoveFil...
Definition: Path.cpp:1227
Represents the result of a call to sys::fs::status().
Definition: FileSystem.h:246
Error writeArchive(StringRef ArcName, ArrayRef< NewArchiveMember > NewMembers, bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr< MemoryBuffer > OldArchiveBuf=nullptr)
Bitcode file.
Definition: Magic.h:23
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:455
static bool is64BitKind(object::Archive::Kind Kind)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
static Expected< std::vector< unsigned > > getSymbols(MemoryBufferRef Buf, raw_ostream &SymNames, bool &HasObject)
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition: Path.cpp:853
StringRef getBuffer() const
Definition: MemoryBuffer.h:272
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition: Magic.cpp:34
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.
std::error_code make_error_code(BitcodeError E)
Tagged union holding either a T or a Error.
Definition: CachePruning.h:22
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:126
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:266
static ErrorOr< SmallString< 128 > > canonicalizePath(StringRef P)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:130
static void printGNUSmallMemberHeader(raw_ostream &Out, StringRef Name, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, unsigned Size)
static bool isBSDLike(object::Archive::Kind Kind)
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition: Endian.h:99
#define P(N)
static Expected< std::vector< MemberData > > computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, object::Archive::Kind Kind, bool Thin, bool Deterministic, ArrayRef< NewArchiveMember > NewMembers)
Expected< sys::TimePoint< std::chrono::seconds > > getLastModified() const
Definition: Archive.h:117
size_t getBufferSize() const
Definition: MemoryBuffer.h:278
std::time_t toTimeT(TimePoint<> TP)
Convert a TimePoint to std::time_t.
Definition: Chrono.h:36
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:64
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
static void printNBits(raw_ostream &Out, object::Archive::Kind Kind, uint64_t Val)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:87
std::error_code getError() const
Definition: ErrorOr.h:159
TimePoint getLastModificationTime() const
The file modification time as reported from the underlying file system.
static sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
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, unsigned Size)
static bool isDarwin(object::Archive::Kind Kind)
Expected< unsigned > getUID() const
Definition: Archive.h:125
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
LLVM_NODISCARD bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition: StringRef.h:432
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:466
static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size)
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:981
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
raw_ostream & write(unsigned char C)
Expected< sys::fs::perms > getAccessMode() const
Definition: Archive.h:128
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:478
BlockVerifier::State From
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any &#39;.
Definition: Path.cpp:716
static bool useStringTable(bool Thin, StringRef Name)
StringRef root_name(StringRef path, Style style=Style::native)
Get root name.
Definition: Path.cpp:372
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.
reference get()
Returns a reference to the stored T value.
Definition: Error.h:532
std::error_code closeFile(file_t &F)
Close the file object.
static Expected< NewArchiveMember > getOldMember(const object::Archive::Child &OldMember, bool Deterministic)
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition: StringMap.h:370
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:41
static bool isArchiveSymbol(const object::BasicSymbolRef &S)
Expected< MemoryBufferRef > getMemoryBufferRef() const
Definition: Archive.cpp:507
static MemberData computeStringTable(StringRef Names)
Expected< std::string > computeArchiveRelativePath(StringRef From, StringRef To)
uint32_t getFlags() const
Get symbol flags (bitwise OR of SymbolRef::Flags)
Definition: SymbolicFile.h:199
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:365
static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef< MemberData > Members, StringRef StringTable)
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:55
static void printRestOfMemberHeader(raw_ostream &Out, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, unsigned Size)
This is a value type class that represents a single symbol in the list of symbols in the object file...
Definition: SymbolicFile.h:98
uint32_t Size
Definition: Profile.cpp:46
static Expected< NewArchiveMember > getFile(StringRef FileName, bool Deterministic)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:482
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
Definition: MathExtras.h:731
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:99
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
std::unique_ptr< MemoryBuffer > Buf
Definition: ArchiveWriter.h:24
Expected< unsigned > getGID() const
Definition: Archive.h:126
TimePoint< std::chrono::seconds > toTimePoint(std::time_t T)
Convert a std::time_t to a TimePoint.
Definition: Chrono.h:44
sys::TimePoint< std::chrono::seconds > ModTime
Definition: ArchiveWriter.h:26
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition: Chrono.h:33