diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-ar/llvm-ar.cpp')
| -rw-r--r-- | contrib/llvm/tools/llvm-ar/llvm-ar.cpp | 332 | 
1 files changed, 6 insertions, 326 deletions
diff --git a/contrib/llvm/tools/llvm-ar/llvm-ar.cpp b/contrib/llvm/tools/llvm-ar/llvm-ar.cpp index f813465daafa..1f55e8a4968b 100644 --- a/contrib/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/contrib/llvm/tools/llvm-ar/llvm-ar.cpp @@ -16,6 +16,7 @@  #include "llvm/IR/LLVMContext.h"  #include "llvm/IR/Module.h"  #include "llvm/Object/Archive.h" +#include "llvm/Object/ArchiveWriter.h"  #include "llvm/Object/ObjectFile.h"  #include "llvm/Support/CommandLine.h"  #include "llvm/Support/Errc.h" @@ -45,16 +46,9 @@ using namespace llvm;  // The name this program was invoked as.  static StringRef ToolName; -static const char *TemporaryOutput; -static int TmpArchiveFD = -1; -  // Show the error message and exit.  LLVM_ATTRIBUTE_NORETURN static void fail(Twine Error) {    outs() << ToolName << ": " << Error << ".\n"; -  if (TmpArchiveFD != -1) -    close(TmpArchiveFD); -  if (TemporaryOutput) -    sys::fs::remove(TemporaryOutput);    exit(1);  } @@ -405,70 +399,6 @@ static void performReadOperation(ArchiveOperation Operation,    }  } -namespace { -class NewArchiveIterator { -  bool IsNewMember; -  StringRef Name; - -  object::Archive::child_iterator OldI; - -  StringRef NewFilename; - -public: -  NewArchiveIterator(object::Archive::child_iterator I, StringRef Name); -  NewArchiveIterator(StringRef I, StringRef Name); -  NewArchiveIterator(); -  bool isNewMember() const; -  StringRef getName() const; - -  object::Archive::child_iterator getOld() const; - -  StringRef getNew() const; -  int getFD(sys::fs::file_status &NewStatus) const; -  const sys::fs::file_status &getStatus() const; -}; -} - -NewArchiveIterator::NewArchiveIterator() {} - -NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I, -                                       StringRef Name) -    : IsNewMember(false), Name(Name), OldI(I) {} - -NewArchiveIterator::NewArchiveIterator(StringRef NewFilename, StringRef Name) -    : IsNewMember(true), Name(Name), NewFilename(NewFilename) {} - -StringRef NewArchiveIterator::getName() const { return Name; } - -bool NewArchiveIterator::isNewMember() const { return IsNewMember; } - -object::Archive::child_iterator NewArchiveIterator::getOld() const { -  assert(!IsNewMember); -  return OldI; -} - -StringRef NewArchiveIterator::getNew() const { -  assert(IsNewMember); -  return NewFilename; -} - -int NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const { -  assert(IsNewMember); -  int NewFD; -  failIfError(sys::fs::openFileForRead(NewFilename, NewFD), NewFilename); -  assert(NewFD != -1); - -  failIfError(sys::fs::status(NewFD, NewStatus), NewFilename); - -  // Opening a directory doesn't make sense. Let it fail. -  // Linux cannot open directories with open(2), although -  // cygwin and *bsd can. -  if (NewStatus.type() == sys::fs::file_type::directory_file) -    failIfError(make_error_code(errc::is_a_directory), NewFilename); - -  return NewFD; -} -  template <typename T>  void addMember(std::vector<NewArchiveIterator> &Members, T I, StringRef Name,                 int Pos = -1) { @@ -605,269 +535,19 @@ computeNewArchiveMembers(ArchiveOperation Operation,    return Ret;  } -template <typename T> -static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size, -				  bool MayTruncate = false) { -  uint64_t OldPos = OS.tell(); -  OS << Data; -  unsigned SizeSoFar = OS.tell() - OldPos; -  if (Size > SizeSoFar) { -    unsigned Remaining = Size - SizeSoFar; -    for (unsigned I = 0; I < Remaining; ++I) -      OS << ' '; -  } else if (Size < SizeSoFar) { -    assert(MayTruncate && "Data doesn't fit in Size"); -    // Some of the data this is used for (like UID) can be larger than the -    // space available in the archive format. Truncate in that case. -    OS.seek(OldPos + Size); -  } -} - -static void print32BE(raw_fd_ostream &Out, unsigned Val) { -  for (int I = 3; I >= 0; --I) { -    char V = (Val >> (8 * I)) & 0xff; -    Out << V; -  } -} - -static void printRestOfMemberHeader(raw_fd_ostream &Out, -                                    const sys::TimeValue &ModTime, unsigned UID, -                                    unsigned GID, unsigned Perms, -                                    unsigned Size) { -  printWithSpacePadding(Out, ModTime.toEpochTime(), 12); -  printWithSpacePadding(Out, UID, 6, true); -  printWithSpacePadding(Out, GID, 6, true); -  printWithSpacePadding(Out, format("%o", Perms), 8); -  printWithSpacePadding(Out, Size, 10); -  Out << "`\n"; -} - -static void printMemberHeader(raw_fd_ostream &Out, StringRef Name, -                              const sys::TimeValue &ModTime, unsigned UID, -                              unsigned GID, unsigned Perms, unsigned Size) { -  printWithSpacePadding(Out, Twine(Name) + "/", 16); -  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size); -} - -static void printMemberHeader(raw_fd_ostream &Out, unsigned NameOffset, -                              const sys::TimeValue &ModTime, unsigned UID, -                              unsigned GID, unsigned Perms, unsigned Size) { -  Out << '/'; -  printWithSpacePadding(Out, NameOffset, 15); -  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size); -} - -static void writeStringTable(raw_fd_ostream &Out, -                             ArrayRef<NewArchiveIterator> Members, -                             std::vector<unsigned> &StringMapIndexes) { -  unsigned StartOffset = 0; -  for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(), -                                              E = Members.end(); -       I != E; ++I) { -    StringRef Name = I->getName(); -    if (Name.size() < 16) -      continue; -    if (StartOffset == 0) { -      printWithSpacePadding(Out, "//", 58); -      Out << "`\n"; -      StartOffset = Out.tell(); -    } -    StringMapIndexes.push_back(Out.tell() - StartOffset); -    Out << Name << "/\n"; -  } -  if (StartOffset == 0) -    return; -  if (Out.tell() % 2) -    Out << '\n'; -  int Pos = Out.tell(); -  Out.seek(StartOffset - 12); -  printWithSpacePadding(Out, Pos - StartOffset, 10); -  Out.seek(Pos); -} - -// Returns the offset of the first reference to a member offset. -static unsigned writeSymbolTable(raw_fd_ostream &Out, -                                 ArrayRef<NewArchiveIterator> Members, -                                 ArrayRef<MemoryBufferRef> Buffers, -                                 std::vector<unsigned> &MemberOffsetRefs) { -  unsigned StartOffset = 0; -  unsigned MemberNum = 0; -  std::string NameBuf; -  raw_string_ostream NameOS(NameBuf); -  unsigned NumSyms = 0; -  LLVMContext &Context = getGlobalContext(); -  for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(), -                                              E = Members.end(); -       I != E; ++I, ++MemberNum) { -    MemoryBufferRef MemberBuffer = Buffers[MemberNum]; -    ErrorOr<std::unique_ptr<object::SymbolicFile>> ObjOrErr = -        object::SymbolicFile::createSymbolicFile( -            MemberBuffer, sys::fs::file_magic::unknown, &Context); -    if (!ObjOrErr) -      continue;  // FIXME: check only for "not an object file" errors. -    object::SymbolicFile &Obj = *ObjOrErr.get(); - -    if (!StartOffset) { -      printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0); -      StartOffset = Out.tell(); -      print32BE(Out, 0); -    } - -    for (const object::BasicSymbolRef &S : Obj.symbols()) { -      uint32_t Symflags = S.getFlags(); -      if (Symflags & object::SymbolRef::SF_FormatSpecific) -        continue; -      if (!(Symflags & object::SymbolRef::SF_Global)) -        continue; -      if (Symflags & object::SymbolRef::SF_Undefined) -        continue; -      failIfError(S.printName(NameOS)); -      NameOS << '\0'; -      ++NumSyms; -      MemberOffsetRefs.push_back(MemberNum); -      print32BE(Out, 0); -    } -  } -  Out << NameOS.str(); - -  if (StartOffset == 0) -    return 0; - -  if (Out.tell() % 2) -    Out << '\0'; - -  unsigned Pos = Out.tell(); -  Out.seek(StartOffset - 12); -  printWithSpacePadding(Out, Pos - StartOffset, 10); -  Out.seek(StartOffset); -  print32BE(Out, NumSyms); -  Out.seek(Pos); -  return StartOffset + 4; -} - -static void -performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, -                      std::vector<NewArchiveIterator> &NewMembers) { -  SmallString<128> TmpArchive; -  failIfError(sys::fs::createUniqueFile(ArchiveName + ".temp-archive-%%%%%%%.a", -                                        TmpArchiveFD, TmpArchive)); - -  TemporaryOutput = TmpArchive.c_str(); -  tool_output_file Output(TemporaryOutput, TmpArchiveFD); -  raw_fd_ostream &Out = Output.os(); -  Out << "!<arch>\n"; - -  std::vector<unsigned> MemberOffsetRefs; - -  std::vector<std::unique_ptr<MemoryBuffer>> Buffers; -  std::vector<MemoryBufferRef> Members; -  std::vector<sys::fs::file_status> NewMemberStatus; - -  for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) { -    NewArchiveIterator &Member = NewMembers[I]; -    MemoryBufferRef MemberRef; - -    if (Member.isNewMember()) { -      StringRef Filename = Member.getNew(); -      NewMemberStatus.resize(NewMemberStatus.size() + 1); -      sys::fs::file_status &Status = NewMemberStatus.back(); -      int FD = Member.getFD(Status); -      ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr = -          MemoryBuffer::getOpenFile(FD, Filename, Status.getSize(), false); -      failIfError(MemberBufferOrErr.getError(), Filename); -      if (close(FD) != 0) -        fail("Could not close file"); -      Buffers.push_back(std::move(MemberBufferOrErr.get())); -      MemberRef = Buffers.back()->getMemBufferRef(); -    } else { -      object::Archive::child_iterator OldMember = Member.getOld(); -      ErrorOr<MemoryBufferRef> MemberBufferOrErr = -          OldMember->getMemoryBufferRef(); -      failIfError(MemberBufferOrErr.getError()); -      MemberRef = MemberBufferOrErr.get(); -    } -    Members.push_back(MemberRef); -  } - -  unsigned MemberReferenceOffset = 0; -  if (Symtab) { -    MemberReferenceOffset = -        writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs); -  } - -  std::vector<unsigned> StringMapIndexes; -  writeStringTable(Out, NewMembers, StringMapIndexes); - -  unsigned MemberNum = 0; -  unsigned LongNameMemberNum = 0; -  unsigned NewMemberNum = 0; -  std::vector<unsigned> MemberOffset; -  for (std::vector<NewArchiveIterator>::iterator I = NewMembers.begin(), -                                                 E = NewMembers.end(); -       I != E; ++I, ++MemberNum) { - -    unsigned Pos = Out.tell(); -    MemberOffset.push_back(Pos); - -    MemoryBufferRef File = Members[MemberNum]; -    if (I->isNewMember()) { -      StringRef FileName = I->getNew(); -      const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum]; -      NewMemberNum++; - -      StringRef Name = sys::path::filename(FileName); -      if (Name.size() < 16) -        printMemberHeader(Out, Name, Status.getLastModificationTime(), -                          Status.getUser(), Status.getGroup(), -                          Status.permissions(), Status.getSize()); -      else -        printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++], -                          Status.getLastModificationTime(), Status.getUser(), -                          Status.getGroup(), Status.permissions(), -                          Status.getSize()); -    } else { -      object::Archive::child_iterator OldMember = I->getOld(); -      StringRef Name = I->getName(); - -      if (Name.size() < 16) -        printMemberHeader(Out, Name, OldMember->getLastModified(), -                          OldMember->getUID(), OldMember->getGID(), -                          OldMember->getAccessMode(), OldMember->getSize()); -      else -        printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++], -                          OldMember->getLastModified(), OldMember->getUID(), -                          OldMember->getGID(), OldMember->getAccessMode(), -                          OldMember->getSize()); -    } - -    Out << File.getBuffer(); - -    if (Out.tell() % 2) -      Out << '\n'; -  } - -  if (MemberReferenceOffset) { -    Out.seek(MemberReferenceOffset); -    for (unsigned MemberNum : MemberOffsetRefs) -      print32BE(Out, MemberOffset[MemberNum]); -  } - -  Output.keep(); -  Out.close(); -  sys::fs::rename(TemporaryOutput, ArchiveName); -  TemporaryOutput = nullptr; -} -  static void  performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,                        std::vector<NewArchiveIterator> *NewMembersP) {    if (NewMembersP) { -    performWriteOperation(Operation, OldArchive, *NewMembersP); +    std::pair<StringRef, std::error_code> Result = +        writeArchive(ArchiveName, *NewMembersP, Symtab); +    failIfError(Result.second, Result.first);      return;    }    std::vector<NewArchiveIterator> NewMembers =        computeNewArchiveMembers(Operation, OldArchive); -  performWriteOperation(Operation, OldArchive, NewMembers); +  auto Result = writeArchive(ArchiveName, NewMembers, Symtab); +  failIfError(Result.second, Result.first);  }  static void createSymbolTable(object::Archive *OldArchive) {  | 
