LLVM  15.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"
22 #include "llvm/Object/MachO.h"
23 #include "llvm/Object/ObjectFile.h"
26 #include "llvm/Support/Alignment.h"
28 #include "llvm/Support/Errc.h"
30 #include "llvm/Support/Format.h"
32 #include "llvm/Support/Path.h"
35 
36 #include <map>
37 
38 #if !defined(_MSC_VER) && !defined(__MINGW32__)
39 #include <unistd.h>
40 #else
41 #include <io.h>
42 #endif
43 
44 using namespace llvm;
45 
47  : Buf(MemoryBuffer::getMemBuffer(BufRef, false)),
48  MemberName(BufRef.getBufferIdentifier()) {}
49 
51  auto MemBufferRef = this->Buf->getMemBufferRef();
54 
55  if (OptionalObject)
56  return isa<object::MachOObjectFile>(**OptionalObject)
58  : (isa<object::XCOFFObjectFile>(**OptionalObject)
61 
62  // Squelch the error in case we had a non-object file.
63  consumeError(OptionalObject.takeError());
64 
65  // If we're adding a bitcode file to the archive, detect the Archive kind
66  // based on the target triple.
68  if (identify_magic(MemBufferRef.getBuffer()) == file_magic::bitcode) {
69  if (auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
70  MemBufferRef, file_magic::bitcode, &Context)) {
71  auto &IRObject = cast<object::IRObjectFile>(**ObjOrErr);
72  return Triple(IRObject.getTargetTriple()).isOSDarwin()
75  } else {
76  // Squelch the error in case this was not a SymbolicFile.
77  consumeError(ObjOrErr.takeError());
78  }
79  }
80 
82 }
83 
86  bool Deterministic) {
88  if (!BufOrErr)
89  return BufOrErr.takeError();
90 
92  M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
93  M.MemberName = M.Buf->getBufferIdentifier();
94  if (!Deterministic) {
95  auto ModTimeOrErr = OldMember.getLastModified();
96  if (!ModTimeOrErr)
97  return ModTimeOrErr.takeError();
98  M.ModTime = ModTimeOrErr.get();
99  Expected<unsigned> UIDOrErr = OldMember.getUID();
100  if (!UIDOrErr)
101  return UIDOrErr.takeError();
102  M.UID = UIDOrErr.get();
103  Expected<unsigned> GIDOrErr = OldMember.getGID();
104  if (!GIDOrErr)
105  return GIDOrErr.takeError();
106  M.GID = GIDOrErr.get();
107  Expected<sys::fs::perms> AccessModeOrErr = OldMember.getAccessMode();
108  if (!AccessModeOrErr)
109  return AccessModeOrErr.takeError();
110  M.Perms = AccessModeOrErr.get();
111  }
112  return std::move(M);
113 }
114 
116  bool Deterministic) {
118  auto FDOrErr = sys::fs::openNativeFileForRead(FileName);
119  if (!FDOrErr)
120  return FDOrErr.takeError();
121  sys::fs::file_t FD = *FDOrErr;
123 
124  if (auto EC = sys::fs::status(FD, Status))
125  return errorCodeToError(EC);
126 
127  // Opening a directory doesn't make sense. Let it fail.
128  // Linux cannot open directories with open(2), although
129  // cygwin and *bsd can.
132 
133  ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
134  MemoryBuffer::getOpenFile(FD, FileName, Status.getSize(), false);
135  if (!MemberBufferOrErr)
136  return errorCodeToError(MemberBufferOrErr.getError());
137 
138  if (auto EC = sys::fs::closeFile(FD))
139  return errorCodeToError(EC);
140 
142  M.Buf = std::move(*MemberBufferOrErr);
143  M.MemberName = M.Buf->getBufferIdentifier();
144  if (!Deterministic) {
145  M.ModTime = std::chrono::time_point_cast<std::chrono::seconds>(
146  Status.getLastModificationTime());
147  M.UID = Status.getUser();
148  M.GID = Status.getGroup();
149  M.Perms = Status.permissions();
150  }
151  return std::move(M);
152 }
153 
154 template <typename T>
155 static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size) {
156  uint64_t OldPos = OS.tell();
157  OS << Data;
158  unsigned SizeSoFar = OS.tell() - OldPos;
159  assert(SizeSoFar <= Size && "Data doesn't fit in Size");
160  OS.indent(Size - SizeSoFar);
161 }
162 
164  return Kind == object::Archive::K_DARWIN ||
166 }
167 
170 }
171 
173  switch (Kind) {
177  return false;
181  return true;
183  break;
184  }
185  llvm_unreachable("not supported for writting");
186 }
187 
188 template <class T>
189 static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val) {
190  support::endian::write(Out, Val,
192 }
193 
196  unsigned UID, unsigned GID, unsigned Perms, uint64_t Size) {
197  printWithSpacePadding(Out, sys::toTimeT(ModTime), 12);
198 
199  // The format has only 6 chars for uid and gid. Truncate if the provided
200  // values don't fit.
201  printWithSpacePadding(Out, UID % 1000000, 6);
202  printWithSpacePadding(Out, GID % 1000000, 6);
203 
204  printWithSpacePadding(Out, format("%o", Perms), 8);
205  printWithSpacePadding(Out, Size, 10);
206  Out << "`\n";
207 }
208 
209 static void
212  unsigned UID, unsigned GID, unsigned Perms,
213  uint64_t Size) {
214  printWithSpacePadding(Out, Twine(Name) + "/", 16);
215  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
216 }
217 
218 static void
221  unsigned UID, unsigned GID, unsigned Perms, uint64_t Size) {
222  uint64_t PosAfterHeader = Pos + 60 + Name.size();
223  // Pad so that even 64 bit object files are aligned.
224  unsigned Pad = offsetToAlignment(PosAfterHeader, Align(8));
225  unsigned NameWithPadding = Name.size() + Pad;
226  printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
227  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
228  NameWithPadding + Size);
229  Out << Name;
230  while (Pad--)
231  Out.write(uint8_t(0));
232 }
233 
234 static void
237  unsigned UID, unsigned GID, unsigned Perms,
238  uint64_t Size, unsigned PrevOffset,
239  unsigned NextOffset) {
240  unsigned NameLen = Name.size();
241 
242  printWithSpacePadding(Out, Size, 20); // File member size
243  printWithSpacePadding(Out, NextOffset, 20); // Next member header offset
244  printWithSpacePadding(Out, PrevOffset, 20); // Previous member header offset
245  printWithSpacePadding(Out, sys::toTimeT(ModTime), 12); // File member date
246  // The big archive format has 12 chars for uid and gid.
247  printWithSpacePadding(Out, UID % 1000000000000, 12); // UID
248  printWithSpacePadding(Out, GID % 1000000000000, 12); // GID
249  printWithSpacePadding(Out, format("%o", Perms), 12); // Permission
250  printWithSpacePadding(Out, NameLen, 4); // Name length
251  if (NameLen) {
252  printWithSpacePadding(Out, Name, NameLen); // Name
253  if (NameLen % 2)
254  Out.write(uint8_t(0)); // Null byte padding
255  }
256  Out << "`\n"; // Terminator
257 }
258 
259 static bool useStringTable(bool Thin, StringRef Name) {
260  return Thin || Name.size() >= 16 || Name.contains('/');
261 }
262 
264  switch (Kind) {
269  return false;
273  return true;
274  }
275  llvm_unreachable("not supported for writting");
276 }
277 
278 static void
281  bool Thin, const NewArchiveMember &M,
283  if (isBSDLike(Kind))
284  return printBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID,
285  M.Perms, Size);
286  if (!useStringTable(Thin, M.MemberName))
287  return printGNUSmallMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
288  M.Perms, Size);
289  Out << '/';
290  uint64_t NamePos;
291  if (Thin) {
292  NamePos = StringTable.tell();
293  StringTable << M.MemberName << "/\n";
294  } else {
295  auto Insertion = MemberNames.insert({M.MemberName, uint64_t(0)});
296  if (Insertion.second) {
297  Insertion.first->second = StringTable.tell();
298  StringTable << M.MemberName << "/\n";
299  }
300  NamePos = Insertion.first->second;
301  }
302  printWithSpacePadding(Out, NamePos, 15);
303  printRestOfMemberHeader(Out, ModTime, M.UID, M.GID, M.Perms, Size);
304 }
305 
306 namespace {
307 struct MemberData {
308  std::vector<unsigned> Symbols;
309  std::string Header;
310  StringRef Data;
312 };
313 } // namespace
314 
315 static MemberData computeStringTable(StringRef Names) {
316  unsigned Size = Names.size();
317  unsigned Pad = offsetToAlignment(Size, Align(2));
318  std::string Header;
319  raw_string_ostream Out(Header);
320  printWithSpacePadding(Out, "//", 48);
321  printWithSpacePadding(Out, Size + Pad, 10);
322  Out << "`\n";
323  Out.flush();
324  return {{}, std::move(Header), Names, Pad ? "\n" : ""};
325 }
326 
327 static sys::TimePoint<std::chrono::seconds> now(bool Deterministic) {
328  using namespace std::chrono;
329 
330  if (!Deterministic)
331  return time_point_cast<seconds>(system_clock::now());
332  return sys::TimePoint<seconds>();
333 }
334 
336  Expected<uint32_t> SymFlagsOrErr = S.getFlags();
337  if (!SymFlagsOrErr)
338  // TODO: Actually report errors helpfully.
339  report_fatal_error(SymFlagsOrErr.takeError());
340  if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific)
341  return false;
342  if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global))
343  return false;
344  if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined)
345  return false;
346  return true;
347 }
348 
350  uint64_t Val) {
351  if (is64BitKind(Kind))
352  print<uint64_t>(Out, Kind, Val);
353  else
354  print<uint32_t>(Out, Kind, Val);
355 }
356 
358  uint64_t NumSyms, uint64_t OffsetSize,
359  StringRef StringTable,
360  uint32_t *Padding = nullptr) {
361  assert((OffsetSize == 4 || OffsetSize == 8) && "Unsupported OffsetSize");
362  uint64_t Size = OffsetSize; // Number of entries
363  if (isBSDLike(Kind))
364  Size += NumSyms * OffsetSize * 2; // Table
365  else
366  Size += NumSyms * OffsetSize; // Table
367  if (isBSDLike(Kind))
368  Size += OffsetSize; // byte count
369  Size += StringTable.size();
370  // ld64 expects the members to be 8-byte aligned for 64-bit content and at
371  // least 4-byte aligned for 32-bit content. Opt for the larger encoding
372  // uniformly.
373  // We do this for all bsd formats because it simplifies aligning members.
374  // For the big archive format, the symbol table is the last member, so there
375  // is no need to align.
377  ? 0
378  : offsetToAlignment(Size, Align(isBSDLike(Kind) ? 8 : 2));
379  Size += Pad;
380  if (Padding)
381  *Padding = Pad;
382  return Size;
383 }
384 
386  bool Deterministic, uint64_t Size,
387  uint64_t PrevMemberOffset = 0) {
388  if (isBSDLike(Kind)) {
389  const char *Name = is64BitKind(Kind) ? "__.SYMDEF_64" : "__.SYMDEF";
390  printBSDMemberHeader(Out, Out.tell(), Name, now(Deterministic), 0, 0, 0,
391  Size);
392  } else if (isAIXBigArchive(Kind)) {
393  printBigArchiveMemberHeader(Out, "", now(Deterministic), 0, 0,
394  0, Size, PrevMemberOffset, 0);
395  } else {
396  const char *Name = is64BitKind(Kind) ? "/SYM64" : "";
397  printGNUSmallMemberHeader(Out, Name, now(Deterministic), 0, 0, 0, Size);
398  }
399 }
400 
402  bool Deterministic, ArrayRef<MemberData> Members,
403  StringRef StringTable,
404  uint64_t PrevMemberOffset = 0) {
405  // We don't write a symbol table on an archive with no members -- except on
406  // Darwin, where the linker will abort unless the archive has a symbol table.
407  if (StringTable.empty() && !isDarwin(Kind))
408  return;
409 
410  unsigned NumSyms = 0;
411  for (const MemberData &M : Members)
412  NumSyms += M.Symbols.size();
413 
414  uint64_t OffsetSize = is64BitKind(Kind) ? 8 : 4;
415  uint32_t Pad;
416  uint64_t Size = computeSymbolTableSize(Kind, NumSyms, OffsetSize, StringTable, &Pad);
417  writeSymbolTableHeader(Out, Kind, Deterministic, Size, PrevMemberOffset);
418 
420  : Out.tell() + Size;
421 
422  if (isBSDLike(Kind))
423  printNBits(Out, Kind, NumSyms * 2 * OffsetSize);
424  else
425  printNBits(Out, Kind, NumSyms);
426 
427  for (const MemberData &M : Members) {
428  for (unsigned StringOffset : M.Symbols) {
429  if (isBSDLike(Kind))
430  printNBits(Out, Kind, StringOffset);
431  printNBits(Out, Kind, Pos); // member offset
432  }
433  Pos += M.Header.size() + M.Data.size() + M.Padding.size();
434  }
435 
436  if (isBSDLike(Kind))
437  // byte count of the string table
438  printNBits(Out, Kind, StringTable.size());
439  Out << StringTable;
440 
441  while (Pad--)
442  Out.write(uint8_t(0));
443 }
444 
446 getSymbols(MemoryBufferRef Buf, raw_ostream &SymNames, bool &HasObject) {
447  std::vector<unsigned> Ret;
448 
449  // In the scenario when LLVMContext is populated SymbolicFile will contain a
450  // reference to it, thus SymbolicFile should be destroyed first.
452  std::unique_ptr<object::SymbolicFile> Obj;
453 
454  const file_magic Type = identify_magic(Buf.getBuffer());
455  // Treat unsupported file types as having no symbols.
457  return Ret;
458  if (Type == file_magic::bitcode) {
461  if (!ObjOrErr)
462  return ObjOrErr.takeError();
463  Obj = std::move(*ObjOrErr);
464  } else {
465  auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf);
466  if (!ObjOrErr)
467  return ObjOrErr.takeError();
468  Obj = std::move(*ObjOrErr);
469  }
470 
471  HasObject = true;
472  for (const object::BasicSymbolRef &S : Obj->symbols()) {
473  if (!isArchiveSymbol(S))
474  continue;
475  Ret.push_back(SymNames.tell());
476  if (Error E = S.printName(SymNames))
477  return std::move(E);
478  SymNames << '\0';
479  }
480  return Ret;
481 }
482 
484 computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
485  object::Archive::Kind Kind, bool Thin, bool Deterministic,
486  bool NeedSymbols, ArrayRef<NewArchiveMember> NewMembers) {
487  static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
488 
489  uint64_t Pos =
491 
492  std::vector<MemberData> Ret;
493  bool HasObject = false;
494 
495  // Deduplicate long member names in the string table and reuse earlier name
496  // offsets. This especially saves space for COFF Import libraries where all
497  // members have the same name.
498  StringMap<uint64_t> MemberNames;
499 
500  // UniqueTimestamps is a special case to improve debugging on Darwin:
501  //
502  // The Darwin linker does not link debug info into the final
503  // binary. Instead, it emits entries of type N_OSO in in the output
504  // binary's symbol table, containing references to the linked-in
505  // object files. Using that reference, the debugger can read the
506  // debug data directly from the object files. Alternatively, an
507  // invocation of 'dsymutil' will link the debug data from the object
508  // files into a dSYM bundle, which can be loaded by the debugger,
509  // instead of the object files.
510  //
511  // For an object file, the N_OSO entries contain the absolute path
512  // path to the file, and the file's timestamp. For an object
513  // included in an archive, the path is formatted like
514  // "/absolute/path/to/archive.a(member.o)", and the timestamp is the
515  // archive member's timestamp, rather than the archive's timestamp.
516  //
517  // However, this doesn't always uniquely identify an object within
518  // an archive -- an archive file can have multiple entries with the
519  // same filename. (This will happen commonly if the original object
520  // files started in different directories.) The only way they get
521  // distinguished, then, is via the timestamp. But this process is
522  // unable to find the correct object file in the archive when there
523  // are two files of the same name and timestamp.
524  //
525  // Additionally, timestamp==0 is treated specially, and causes the
526  // timestamp to be ignored as a match criteria.
527  //
528  // That will "usually" work out okay when creating an archive not in
529  // deterministic timestamp mode, because the objects will probably
530  // have been created at different timestamps.
531  //
532  // To ameliorate this problem, in deterministic archive mode (which
533  // is the default), on Darwin we will emit a unique non-zero
534  // timestamp for each entry with a duplicated name. This is still
535  // deterministic: the only thing affecting that timestamp is the
536  // order of the files in the resultant archive.
537  //
538  // See also the functions that handle the lookup:
539  // in lldb: ObjectContainerBSDArchive::Archive::FindObject()
540  // in llvm/tools/dsymutil: BinaryHolder::GetArchiveMemberBuffers().
541  bool UniqueTimestamps = Deterministic && isDarwin(Kind);
542  std::map<StringRef, unsigned> FilenameCount;
543  if (UniqueTimestamps) {
544  for (const NewArchiveMember &M : NewMembers)
545  FilenameCount[M.MemberName]++;
546  for (auto &Entry : FilenameCount)
547  Entry.second = Entry.second > 1 ? 1 : 0;
548  }
549 
550  // The big archive format needs to know the offset of the previous member
551  // header.
552  unsigned PrevOffset = 0;
553  for (const NewArchiveMember &M : NewMembers) {
554  std::string Header;
555  raw_string_ostream Out(Header);
556 
557  MemoryBufferRef Buf = M.Buf->getMemBufferRef();
558  StringRef Data = Thin ? "" : Buf.getBuffer();
559 
560  // ld64 expects the members to be 8-byte aligned for 64-bit content and at
561  // least 4-byte aligned for 32-bit content. Opt for the larger encoding
562  // uniformly. This matches the behaviour with cctools and ensures that ld64
563  // is happy with archives that we generate.
564  unsigned MemberPadding =
565  isDarwin(Kind) ? offsetToAlignment(Data.size(), Align(8)) : 0;
566  unsigned TailPadding =
567  offsetToAlignment(Data.size() + MemberPadding, Align(2));
568  StringRef Padding = StringRef(PaddingData, MemberPadding + TailPadding);
569 
571  if (UniqueTimestamps)
572  // Increment timestamp for each file of a given name.
573  ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);
574  else
575  ModTime = M.ModTime;
576 
577  uint64_t Size = Buf.getBufferSize() + MemberPadding;
578  if (Size > object::Archive::MaxMemberSize) {
579  std::string StringMsg =
580  "File " + M.MemberName.str() + " exceeds size limit";
581  return make_error<object::GenericBinaryError>(
583  }
584 
585  if (isAIXBigArchive(Kind)) {
586  unsigned NextOffset = Pos + sizeof(object::BigArMemHdrType) +
587  alignTo(M.MemberName.size(), 2) + alignTo(Size, 2);
588  printBigArchiveMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
589  M.Perms, Size, PrevOffset, NextOffset);
590  PrevOffset = Pos;
591  } else {
592  printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M,
593  ModTime, Size);
594  }
595  Out.flush();
596 
597  std::vector<unsigned> Symbols;
598  if (NeedSymbols) {
599  Expected<std::vector<unsigned>> SymbolsOrErr =
600  getSymbols(Buf, SymNames, HasObject);
601  if (auto E = SymbolsOrErr.takeError())
602  return std::move(E);
603  Symbols = std::move(*SymbolsOrErr);
604  }
605 
606  Pos += Header.size() + Data.size() + Padding.size();
607  Ret.push_back({std::move(Symbols), std::move(Header), Data, Padding});
608  }
609  // If there are no symbols, emit an empty symbol table, to satisfy Solaris
610  // tools, older versions of which expect a symbol table in a non-empty
611  // archive, regardless of whether there are any symbols in it.
612  if (HasObject && SymNames.tell() == 0)
613  SymNames << '\0' << '\0' << '\0';
614  return Ret;
615 }
616 
617 namespace llvm {
618 
621  std::error_code Err = sys::fs::make_absolute(Ret);
622  if (Err)
623  return Err;
624  sys::path::remove_dots(Ret, /*removedotdot*/ true);
625  return Ret;
626 }
627 
628 // Compute the relative path from From to To.
630  ErrorOr<SmallString<128>> PathToOrErr = canonicalizePath(To);
632  if (!PathToOrErr || !DirFromOrErr)
633  return errorCodeToError(std::error_code(errno, std::generic_category()));
634 
635  const SmallString<128> &PathTo = *PathToOrErr;
636  const SmallString<128> &DirFrom = sys::path::parent_path(*DirFromOrErr);
637 
638  // Can't construct a relative path between different roots
639  if (sys::path::root_name(PathTo) != sys::path::root_name(DirFrom))
640  return sys::path::convert_to_slash(PathTo);
641 
642  // Skip common prefixes
643  auto FromTo =
644  std::mismatch(sys::path::begin(DirFrom), sys::path::end(DirFrom),
645  sys::path::begin(PathTo));
646  auto FromI = FromTo.first;
647  auto ToI = FromTo.second;
648 
649  // Construct relative path
650  SmallString<128> Relative;
651  for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
653 
654  for (auto ToE = sys::path::end(PathTo); ToI != ToE; ++ToI)
656 
657  return std::string(Relative.str());
658 }
659 
661  ArrayRef<NewArchiveMember> NewMembers,
662  bool WriteSymtab, object::Archive::Kind Kind,
663  bool Deterministic, bool Thin) {
664  assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode");
665 
666  SmallString<0> SymNamesBuf;
667  raw_svector_ostream SymNames(SymNamesBuf);
668  SmallString<0> StringTableBuf;
669  raw_svector_ostream StringTable(StringTableBuf);
670 
672  computeMemberData(StringTable, SymNames, Kind, Thin, Deterministic,
673  WriteSymtab, NewMembers);
674  if (Error E = DataOrErr.takeError())
675  return E;
676  std::vector<MemberData> &Data = *DataOrErr;
677 
678  if (!StringTableBuf.empty() && !isAIXBigArchive(Kind))
679  Data.insert(Data.begin(), computeStringTable(StringTableBuf));
680 
681  // We would like to detect if we need to switch to a 64-bit symbol table.
682  uint64_t LastMemberEndOffset =
684  uint64_t LastMemberHeaderOffset = LastMemberEndOffset;
685  uint64_t NumSyms = 0;
686  for (const auto &M : Data) {
687  // Record the start of the member's offset
688  LastMemberHeaderOffset = LastMemberEndOffset;
689  // Account for the size of each part associated with the member.
690  LastMemberEndOffset += M.Header.size() + M.Data.size() + M.Padding.size();
691  NumSyms += M.Symbols.size();
692  }
693 
694  // The symbol table is put at the end of the big archive file. The symbol
695  // table is at the start of the archive file for other archive formats.
696  if (WriteSymtab && !isAIXBigArchive(Kind)) {
697  // We assume 32-bit offsets to see if 32-bit symbols are possible or not.
698  uint64_t SymtabSize = computeSymbolTableSize(Kind, NumSyms, 4, SymNamesBuf);
699  auto computeSymbolTableHeaderSize =
700  [=] {
701  SmallString<0> TmpBuf;
702  raw_svector_ostream Tmp(TmpBuf);
703  writeSymbolTableHeader(Tmp, Kind, Deterministic, SymtabSize);
704  return TmpBuf.size();
705  };
706  LastMemberHeaderOffset += computeSymbolTableHeaderSize() + SymtabSize;
707 
708  // The SYM64 format is used when an archive's member offsets are larger than
709  // 32-bits can hold. The need for this shift in format is detected by
710  // writeArchive. To test this we need to generate a file with a member that
711  // has an offset larger than 32-bits but this demands a very slow test. To
712  // speed the test up we use this environment variable to pretend like the
713  // cutoff happens before 32-bits and instead happens at some much smaller
714  // value.
715  uint64_t Sym64Threshold = 1ULL << 32;
716  const char *Sym64Env = std::getenv("SYM64_THRESHOLD");
717  if (Sym64Env)
718  StringRef(Sym64Env).getAsInteger(10, Sym64Threshold);
719 
720  // If LastMemberHeaderOffset isn't going to fit in a 32-bit varible we need
721  // to switch to 64-bit. Note that the file can be larger than 4GB as long as
722  // the last member starts before the 4GB offset.
723  if (LastMemberHeaderOffset >= Sym64Threshold) {
726  else
728  }
729  }
730 
731  if (Thin)
732  Out << "!<thin>\n";
733  else if (isAIXBigArchive(Kind))
734  Out << "<bigaf>\n";
735  else
736  Out << "!<arch>\n";
737 
738  if (!isAIXBigArchive(Kind)) {
739  if (WriteSymtab)
740  writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf);
741  for (const MemberData &M : Data)
742  Out << M.Header << M.Data << M.Padding;
743  } else {
744  // For the big archive (AIX) format, compute a table of member names and
745  // offsets, used in the member table.
746  uint64_t MemberTableNameStrTblSize = 0;
747  std::vector<size_t> MemberOffsets;
748  std::vector<StringRef> MemberNames;
749  // Loop across object to find offset and names.
750  uint64_t MemberEndOffset = sizeof(object::BigArchive::FixLenHdr);
751  for (size_t I = 0, Size = NewMembers.size(); I != Size; ++I) {
752  const NewArchiveMember &Member = NewMembers[I];
753  MemberTableNameStrTblSize += Member.MemberName.size() + 1;
754  MemberOffsets.push_back(MemberEndOffset);
755  MemberNames.push_back(Member.MemberName);
756  // File member name ended with "`\n". The length is included in
757  // BigArMemHdrType.
758  MemberEndOffset += sizeof(object::BigArMemHdrType) +
759  alignTo(Data[I].Data.size(), 2) +
760  alignTo(Member.MemberName.size(), 2);
761  }
762 
763  // AIX member table size.
764  unsigned MemberTableSize = 20 + // Number of members field
765  20 * MemberOffsets.size() +
766  MemberTableNameStrTblSize;
767 
768  unsigned GlobalSymbolOffset =
769  (WriteSymtab && NumSyms > 0)
770  ? LastMemberEndOffset +
771  alignTo(sizeof(object::BigArMemHdrType) + MemberTableSize, 2)
772  : 0;
773 
774  // Fixed Sized Header.
775  printWithSpacePadding(Out, NewMembers.size() ? LastMemberEndOffset : 0,
776  20); // Offset to member table
777  // If there are no file members in the archive, there will be no global
778  // symbol table.
779  printWithSpacePadding(Out, NewMembers.size() ? GlobalSymbolOffset : 0, 20);
781  Out, 0,
782  20); // Offset to 64 bits global symbol table - Not supported yet
784  Out, NewMembers.size() ? sizeof(object::BigArchive::FixLenHdr) : 0,
785  20); // Offset to first archive member
786  printWithSpacePadding(Out, NewMembers.size() ? LastMemberHeaderOffset : 0,
787  20); // Offset to last archive member
789  Out, 0,
790  20); // Offset to first member of free list - Not supported yet
791 
792  for (const MemberData &M : Data) {
793  Out << M.Header << M.Data;
794  if (M.Data.size() % 2)
795  Out << '\0';
796  }
797 
798  if (NewMembers.size()) {
799  // Member table.
800  printBigArchiveMemberHeader(Out, "", sys::toTimePoint(0), 0, 0, 0,
801  MemberTableSize, LastMemberHeaderOffset,
802  GlobalSymbolOffset);
803  printWithSpacePadding(Out, MemberOffsets.size(), 20); // Number of members
804  for (uint64_t MemberOffset : MemberOffsets)
805  printWithSpacePadding(Out, MemberOffset,
806  20); // Offset to member file header.
807  for (StringRef MemberName : MemberNames)
808  Out << MemberName << '\0'; // Member file name, null byte padding.
809 
810  if (MemberTableNameStrTblSize % 2)
811  Out << '\0'; // Name table must be tail padded to an even number of
812  // bytes.
813 
814  if (WriteSymtab && NumSyms > 0)
815  writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf,
816  LastMemberEndOffset);
817  }
818  }
819  Out.flush();
820  return Error::success();
821 }
822 
824  bool WriteSymtab, object::Archive::Kind Kind,
825  bool Deterministic, bool Thin,
826  std::unique_ptr<MemoryBuffer> OldArchiveBuf) {
828  sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a");
829  if (!Temp)
830  return Temp.takeError();
831  raw_fd_ostream Out(Temp->FD, false);
832 
833  if (Error E = writeArchiveToStream(Out, NewMembers, WriteSymtab, Kind,
834  Deterministic, Thin)) {
835  if (Error DiscardError = Temp->discard())
836  return joinErrors(std::move(E), std::move(DiscardError));
837  return E;
838  }
839 
840  // At this point, we no longer need whatever backing memory
841  // was used to generate the NewMembers. On Windows, this buffer
842  // could be a mapped view of the file we want to replace (if
843  // we're updating an existing archive, say). In that case, the
844  // rename would still succeed, but it would leave behind a
845  // temporary file (actually the original file renamed) because
846  // a file cannot be deleted while there's a handle open on it,
847  // only renamed. So by freeing this buffer, this ensures that
848  // the last open handle on the destination file, if any, is
849  // closed before we attempt to rename.
850  OldArchiveBuf.reset();
851 
852  return Temp->keep(ArcName);
853 }
854 
857  object::Archive::Kind Kind, bool Deterministic,
858  bool Thin) {
859  SmallVector<char, 0> ArchiveBufferVector;
860  raw_svector_ostream ArchiveStream(ArchiveBufferVector);
861 
862  if (Error E = writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab,
863  Kind, Deterministic, Thin))
864  return std::move(E);
865 
866  return std::make_unique<SmallVectorMemoryBuffer>(
867  std::move(ArchiveBufferVector), /*RequiresNullTerminator=*/false);
868 }
869 
870 } // namespace llvm
llvm::NewArchiveMember
Definition: ArchiveWriter.h:20
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:156
llvm::object::Archive::K_GNU64
@ K_GNU64
Definition: Archive.h:339
llvm::raw_ostream::tell
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:136
llvm::object::Archive::K_COFF
@ K_COFF
Definition: Archive.h:339
llvm::sys::fs::file_t
int file_t
Definition: FileSystem.h:60
isDarwin
static bool isDarwin(object::Archive::Kind Kind)
Definition: ArchiveWriter.cpp:163
llvm::object::Archive::Kind
Kind
Definition: Archive.h:339
MathExtras.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::NewArchiveMember::getFile
static Expected< NewArchiveMember > getFile(StringRef FileName, bool Deterministic)
Definition: ArchiveWriter.cpp:115
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:339
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:498
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:189
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:194
llvm::sys::path::Style::posix
@ posix
printWithSpacePadding
static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size)
Definition: ArchiveWriter.cpp:155
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:632
llvm::NewArchiveMember::Buf
std::unique_ptr< MemoryBuffer > Buf
Definition: ArchiveWriter.h:21
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:568
ErrorHandling.h
SmallVectorMemoryBuffer.h
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
llvm::object::Archive::K_GNU
@ K_GNU
Definition: Archive.h:339
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:235
llvm::sys::path::begin
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:226
llvm::MemoryBufferRef::getBufferSize
size_t getBufferSize() const
Definition: MemoryBufferRef.h:37
llvm::object::Archive::Child::getGID
Expected< unsigned > getGID() const
Definition: Archive.h:239
llvm::MipsISD::Ret
@ Ret
Definition: MipsISelLowering.h:119
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
SymbolicFile.h
computeStringTable
static MemberData computeStringTable(StringRef Names)
Definition: ArchiveWriter.cpp:315
Format.h
llvm::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043
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
MachO.h
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:456
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
isBSDLike
static bool isBSDLike(object::Archive::Kind Kind)
Definition: ArchiveWriter.cpp:172
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:115
Error.h
ArchiveWriter.h
Magic.h
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::Triple::isOSDarwin
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, or DriverKit).
Definition: Triple.h:508
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:276
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:103
llvm::object::Archive::MaxMemberSize
static const uint64_t MaxMemberSize
Size field is 10 decimal digits long.
Definition: Archive.h:337
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:823
printBigArchiveMemberHeader
static void printBigArchiveMemberHeader(raw_ostream &Out, StringRef Name, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, uint64_t Size, unsigned PrevOffset, unsigned NextOffset)
Definition: ArchiveWriter.cpp:235
useStringTable
static bool useStringTable(bool Thin, StringRef Name)
Definition: ArchiveWriter.cpp:259
false
Definition: StackSlotColoring.cpp:141
llvm::ErrorOr::getError
std::error_code getError() const
Definition: ErrorOr.h:153
XCOFFObjectFile.h
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:54
llvm::raw_ostream::flush
void flush()
Definition: raw_ostream.h:187
llvm::object::BigArMemHdrType
Definition: Archive.h:123
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:230
Align
uint64_t Align
Definition: ELFObjHandler.cpp:81
isArchiveSymbol
static bool isArchiveSymbol(const object::BasicSymbolRef &S)
Definition: ArchiveWriter.cpp:335
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
writeSymbolTableHeader
static void writeSymbolTableHeader(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, uint64_t Size, uint64_t PrevMemberOffset=0)
Definition: ArchiveWriter.cpp:385
llvm::NewArchiveMember::detectKindFromObject
object::Archive::Kind detectKindFromObject() const
Definition: ArchiveWriter.cpp:50
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:514
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
now
static sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
Definition: ArchiveWriter.cpp:327
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:238
llvm::object::SymbolicFile::isSymbolicFile
static bool isSymbolicFile(file_magic Type, const LLVMContext *Context)
Definition: SymbolicFile.cpp:97
IRObjectFile.h
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:117
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:715
llvm::object::Archive::K_DARWIN64
@ K_DARWIN64
Definition: Archive.h:339
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:68
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::object::BasicSymbolRef::SF_Undefined
@ SF_Undefined
Definition: SymbolicFile.h:110
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:426
llvm::object::Archive::Child::getAccessMode
Expected< sys::fs::perms > getAccessMode() const
Definition: Archive.h:241
ArrayRef.h
llvm::object::ObjectFile::createObjectFile
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition: ObjectFile.cpp:188
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:467
llvm::canonicalizePath
static ErrorOr< SmallString< 128 > > canonicalizePath(StringRef P)
Definition: ArchiveWriter.cpp:619
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:906
Status
Definition: SIModeRegister.cpp:29
llvm::sys::fs::kInvalidFile
const file_t kInvalidFile
llvm::computeArchiveRelativePath
Expected< std::string > computeArchiveRelativePath(StringRef From, StringRef To)
Definition: ArchiveWriter.cpp:629
llvm::object::Archive::K_AIXBIG
@ K_AIXBIG
Definition: Archive.h:339
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:58
isAIXBigArchive
static bool isAIXBigArchive(object::Archive::Kind Kind)
Definition: ArchiveWriter.cpp:168
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
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:210
llvm::Expected::get
reference get()
Returns a reference to the stored T value.
Definition: Error.h:567
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:279
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
Archive.h
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:444
llvm::object::Archive::Child
Definition: Archive.h:163
llvm::make_error_code
std::error_code make_error_code(BitcodeError E)
Definition: BitcodeReader.h:271
is64BitKind
static bool is64BitKind(object::Archive::Kind Kind)
Definition: ArchiveWriter.cpp:263
llvm::StringRef::size
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
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:373
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:660
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
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:446
llvm::object::BigArchive::FixLenHdr
Fixed-Length Header.
Definition: Archive.h:397
llvm::SmallString::str
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:260
llvm::object::Archive::K_DARWIN
@ K_DARWIN
Definition: Archive.h:339
llvm::pdb::PDB_ColorItem::Padding
@ Padding
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:597
llvm::object::Archive::getDefaultKindForHost
static object::Archive::Kind getDefaultKindForHost()
Definition: Archive.cpp:933
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:357
llvm::object::BasicSymbolRef::SF_Global
@ SF_Global
Definition: SymbolicFile.h:111
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::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:164
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:662
writeSymbolTable
static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef< MemberData > Members, StringRef StringTable, uint64_t PrevMemberOffset=0)
Definition: ArchiveWriter.cpp:401
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:484
llvm::object::Archive::Child::getMemoryBufferRef
Expected< MemoryBufferRef > getMemoryBufferRef() const
Definition: Archive.cpp:635
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:1337
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:33
llvm::NewArchiveMember::getOldMember
static Expected< NewArchiveMember > getOldMember(const object::Archive::Child &OldMember, bool Deterministic)
Definition: ArchiveWriter.cpp:85
printNBits
static void printNBits(raw_ostream &Out, object::Archive::Kind Kind, uint64_t Val)
Definition: ArchiveWriter.cpp:349
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:198
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:219
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:856