diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 | 
| commit | 01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch) | |
| tree | 4def12e759965de927d963ac65840d663ef9d1ea /tools/llvm-ar/llvm-ar.cpp | |
| parent | f0f4822ed4b66e3579e92a89f368f8fb860e218e (diff) | |
Notes
Diffstat (limited to 'tools/llvm-ar/llvm-ar.cpp')
| -rw-r--r-- | tools/llvm-ar/llvm-ar.cpp | 224 | 
1 files changed, 137 insertions, 87 deletions
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index ef5fab68b9479..865152b6af831 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -19,6 +19,7 @@  #include "llvm/LibDriver/LibDriver.h"  #include "llvm/Object/Archive.h"  #include "llvm/Object/ArchiveWriter.h" +#include "llvm/Object/MachO.h"  #include "llvm/Object/ObjectFile.h"  #include "llvm/Support/CommandLine.h"  #include "llvm/Support/Errc.h" @@ -64,12 +65,25 @@ static void failIfError(std::error_code EC, Twine Context = "") {    fail(Context + ": " + EC.message());  } +static void failIfError(Error E, Twine Context = "") { +  if (!E) +    return; + +  handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) { +    std::string ContextStr = Context.str(); +    if (ContextStr == "") +      fail(EIB.message()); +    fail(Context + ": " + EIB.message()); +  }); +} +  // llvm-ar/llvm-ranlib remaining positional arguments.  static cl::list<std::string>      RestOfArgs(cl::Positional, cl::ZeroOrMore,                 cl::desc("[relpos] [count] <archive-file> [members]..."));  static cl::opt<bool> MRI("M", cl::desc("")); +static cl::opt<std::string> Plugin("plugin", cl::desc("plugin (ignored for compatibility"));  namespace {  enum Format { Default, GNU, BSD }; @@ -77,7 +91,7 @@ enum Format { Default, GNU, BSD };  static cl::opt<Format>      FormatOpt("format", cl::desc("Archive format to create"), -              cl::values(clEnumValN(Default, "defalut", "default"), +              cl::values(clEnumValN(Default, "default", "default"),                           clEnumValN(GNU, "gnu", "gnu"),                           clEnumValN(BSD, "bsd", "bsd"), clEnumValEnd)); @@ -343,12 +357,9 @@ static void doDisplayTable(StringRef Name, const object::Archive::Child &C) {  static void doExtract(StringRef Name, const object::Archive::Child &C) {    // Retain the original mode.    sys::fs::perms Mode = C.getAccessMode(); -  SmallString<128> Storage = Name;    int FD; -  failIfError( -      sys::fs::openFileForWrite(Storage.c_str(), FD, sys::fs::F_None, Mode), -      Storage.c_str()); +  failIfError(sys::fs::openFileForWrite(Name, FD, sys::fs::F_None, Mode), Name);    {      raw_fd_ostream file(FD, false); @@ -394,35 +405,37 @@ static void performReadOperation(ArchiveOperation Operation,      fail("extracting from a thin archive is not supported");    bool Filter = !Members.empty(); -  for (auto &ChildOrErr : OldArchive->children()) { -    failIfError(ChildOrErr.getError()); -    const object::Archive::Child &C = *ChildOrErr; - -    ErrorOr<StringRef> NameOrErr = C.getName(); -    failIfError(NameOrErr.getError()); -    StringRef Name = NameOrErr.get(); - -    if (Filter) { -      auto I = std::find(Members.begin(), Members.end(), Name); -      if (I == Members.end()) -        continue; -      Members.erase(I); -    } +  { +    Error Err; +    for (auto &C : OldArchive->children(Err)) { +      ErrorOr<StringRef> NameOrErr = C.getName(); +      failIfError(NameOrErr.getError()); +      StringRef Name = NameOrErr.get(); -    switch (Operation) { -    default: -      llvm_unreachable("Not a read operation"); -    case Print: -      doPrint(Name, C); -      break; -    case DisplayTable: -      doDisplayTable(Name, C); -      break; -    case Extract: -      doExtract(Name, C); -      break; +      if (Filter) { +        auto I = std::find(Members.begin(), Members.end(), Name); +        if (I == Members.end()) +          continue; +        Members.erase(I); +      } + +      switch (Operation) { +      default: +        llvm_unreachable("Not a read operation"); +      case Print: +        doPrint(Name, C); +        break; +      case DisplayTable: +        doDisplayTable(Name, C); +        break; +      case Extract: +        doExtract(Name, C); +        break; +      }      } +    failIfError(std::move(Err));    } +    if (Members.empty())      return;    for (StringRef Name : Members) @@ -430,25 +443,28 @@ static void performReadOperation(ArchiveOperation Operation,    std::exit(1);  } -static void addMember(std::vector<NewArchiveIterator> &Members, +static void addMember(std::vector<NewArchiveMember> &Members,                        StringRef FileName, int Pos = -1) { -  NewArchiveIterator NI(FileName); +  Expected<NewArchiveMember> NMOrErr = +      NewArchiveMember::getFile(FileName, Deterministic); +  failIfError(NMOrErr.takeError(), FileName);    if (Pos == -1) -    Members.push_back(NI); +    Members.push_back(std::move(*NMOrErr));    else -    Members[Pos] = NI; +    Members[Pos] = std::move(*NMOrErr);  } -static void addMember(std::vector<NewArchiveIterator> &Members, -                      const object::Archive::Child &M, StringRef Name, -                      int Pos = -1) { +static void addMember(std::vector<NewArchiveMember> &Members, +                      const object::Archive::Child &M, int Pos = -1) {    if (Thin && !M.getParent()->isThin())      fail("Cannot convert a regular archive to a thin one"); -  NewArchiveIterator NI(M, Name); +  Expected<NewArchiveMember> NMOrErr = +      NewArchiveMember::getOldMember(M, Deterministic); +  failIfError(NMOrErr.takeError());    if (Pos == -1) -    Members.push_back(NI); +    Members.push_back(std::move(*NMOrErr));    else -    Members[Pos] = NI; +    Members[Pos] = std::move(*NMOrErr);  }  enum InsertAction { @@ -509,17 +525,16 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,  // We have to walk this twice and computing it is not trivial, so creating an  // explicit std::vector is actually fairly efficient. -static std::vector<NewArchiveIterator> +static std::vector<NewArchiveMember>  computeNewArchiveMembers(ArchiveOperation Operation,                           object::Archive *OldArchive) { -  std::vector<NewArchiveIterator> Ret; -  std::vector<NewArchiveIterator> Moved; +  std::vector<NewArchiveMember> Ret; +  std::vector<NewArchiveMember> Moved;    int InsertPos = -1;    StringRef PosName = sys::path::filename(RelPos);    if (OldArchive) { -    for (auto &ChildOrErr : OldArchive->children()) { -      failIfError(ChildOrErr.getError()); -      auto &Child = ChildOrErr.get(); +    Error Err; +    for (auto &Child : OldArchive->children(Err)) {        int Pos = Ret.size();        ErrorOr<StringRef> NameOrErr = Child.getName();        failIfError(NameOrErr.getError()); @@ -537,7 +552,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,            computeInsertAction(Operation, Child, Name, MemberI);        switch (Action) {        case IA_AddOldMember: -        addMember(Ret, Child, Name); +        addMember(Ret, Child);          break;        case IA_AddNewMeber:          addMember(Ret, *MemberI); @@ -545,7 +560,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,        case IA_Delete:          break;        case IA_MoveOldMember: -        addMember(Moved, Child, Name); +        addMember(Moved, Child);          break;        case IA_MoveNewMember:          addMember(Moved, *MemberI); @@ -554,6 +569,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,        if (MemberI != Members.end())          Members.erase(MemberI);      } +    failIfError(std::move(Err));    }    if (Operation == Delete) @@ -566,10 +582,15 @@ computeNewArchiveMembers(ArchiveOperation Operation,      InsertPos = Ret.size();    assert(unsigned(InsertPos) <= Ret.size()); -  Ret.insert(Ret.begin() + InsertPos, Moved.begin(), Moved.end()); - -  Ret.insert(Ret.begin() + InsertPos, Members.size(), NewArchiveIterator(""));    int Pos = InsertPos; +  for (auto &M : Moved) { +    Ret.insert(Ret.begin() + Pos, std::move(M)); +    ++Pos; +  } + +  for (unsigned I = 0; I != Members.size(); ++I) +    Ret.insert(Ret.begin() + InsertPos, NewArchiveMember()); +  Pos = InsertPos;    for (auto &Member : Members) {      addMember(Ret, Member, Pos);      ++Pos; @@ -578,36 +599,61 @@ computeNewArchiveMembers(ArchiveOperation Operation,    return Ret;  } +static object::Archive::Kind getDefaultForHost() { +  return Triple(sys::getProcessTriple()).isOSDarwin() ? object::Archive::K_BSD +                                                      : object::Archive::K_GNU; +} + +static object::Archive::Kind getKindFromMember(const NewArchiveMember &Member) { +  Expected<std::unique_ptr<object::ObjectFile>> OptionalObject = +      object::ObjectFile::createObjectFile(Member.Buf->getMemBufferRef()); + +  if (OptionalObject) +    return isa<object::MachOObjectFile>(**OptionalObject) +               ? object::Archive::K_BSD +               : object::Archive::K_GNU; + +  // squelch the error in case we had a non-object file +  consumeError(OptionalObject.takeError()); +  return getDefaultForHost(); +} +  static void -performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, -                      std::vector<NewArchiveIterator> *NewMembersP) { +performWriteOperation(ArchiveOperation Operation, +                      object::Archive *OldArchive, +                      std::unique_ptr<MemoryBuffer> OldArchiveBuf, +                      std::vector<NewArchiveMember> *NewMembersP) { +  std::vector<NewArchiveMember> NewMembers; +  if (!NewMembersP) +    NewMembers = computeNewArchiveMembers(Operation, OldArchive); +    object::Archive::Kind Kind;    switch (FormatOpt) { -  case Default: { -    Triple T(sys::getProcessTriple()); -    if (T.isOSDarwin()) -      Kind = object::Archive::K_BSD; -    else +  case Default: +    if (Thin)        Kind = object::Archive::K_GNU; +    else if (OldArchive) +      Kind = OldArchive->kind(); +    else if (NewMembersP) +      Kind = NewMembersP->size() ? getKindFromMember(NewMembersP->front()) +                                 : getDefaultForHost(); +    else +      Kind = NewMembers.size() ? getKindFromMember(NewMembers.front()) +                               : getDefaultForHost();      break; -  }    case GNU:      Kind = object::Archive::K_GNU;      break;    case BSD: +    if (Thin) +      fail("Only the gnu format has a thin mode");      Kind = object::Archive::K_BSD;      break;    } -  if (NewMembersP) { -    std::pair<StringRef, std::error_code> Result = writeArchive( -        ArchiveName, *NewMembersP, Symtab, Kind, Deterministic, Thin); -    failIfError(Result.second, Result.first); -    return; -  } -  std::vector<NewArchiveIterator> NewMembers = -      computeNewArchiveMembers(Operation, OldArchive); -  auto Result = -      writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin); + +  std::pair<StringRef, std::error_code> Result = +      writeArchive(ArchiveName, NewMembersP ? *NewMembersP : NewMembers, Symtab, +                   Kind, Deterministic, Thin, std::move(OldArchiveBuf));    failIfError(Result.second, Result.first);  } @@ -621,12 +667,13 @@ static void createSymbolTable(object::Archive *OldArchive) {    if (OldArchive->hasSymbolTable())      return; -  performWriteOperation(CreateSymTab, OldArchive, nullptr); +  performWriteOperation(CreateSymTab, OldArchive, nullptr, nullptr);  }  static void performOperation(ArchiveOperation Operation,                               object::Archive *OldArchive, -                             std::vector<NewArchiveIterator> *NewMembers) { +                             std::unique_ptr<MemoryBuffer> OldArchiveBuf, +                             std::vector<NewArchiveMember> *NewMembers) {    switch (Operation) {    case Print:    case DisplayTable: @@ -638,7 +685,8 @@ static void performOperation(ArchiveOperation Operation,    case Move:    case QuickAppend:    case ReplaceOrInsert: -    performWriteOperation(Operation, OldArchive, NewMembers); +    performWriteOperation(Operation, OldArchive, std::move(OldArchiveBuf), +                          NewMembers);      return;    case CreateSymTab:      createSymbolTable(OldArchive); @@ -648,7 +696,7 @@ static void performOperation(ArchiveOperation Operation,  }  static int performOperation(ArchiveOperation Operation, -                            std::vector<NewArchiveIterator> *NewMembers) { +                            std::vector<NewArchiveMember> *NewMembers) {    // Create or open the archive object.    ErrorOr<std::unique_ptr<MemoryBuffer>> Buf =        MemoryBuffer::getFile(ArchiveName, -1, false); @@ -657,10 +705,12 @@ static int performOperation(ArchiveOperation Operation,      fail("error opening '" + ArchiveName + "': " + EC.message() + "!");    if (!EC) { -    object::Archive Archive(Buf.get()->getMemBufferRef(), EC); +    Error Err; +    object::Archive Archive(Buf.get()->getMemBufferRef(), Err); +    EC = errorToErrorCode(std::move(Err));      failIfError(EC,                  "error loading '" + ArchiveName + "': " + EC.message() + "!"); -    performOperation(Operation, &Archive, NewMembers); +    performOperation(Operation, &Archive, std::move(Buf.get()), NewMembers);      return 0;    } @@ -675,7 +725,7 @@ static int performOperation(ArchiveOperation Operation,      }    } -  performOperation(Operation, nullptr, NewMembers); +  performOperation(Operation, nullptr, nullptr, NewMembers);    return 0;  } @@ -686,7 +736,7 @@ static void runMRIScript() {    failIfError(Buf.getError());    const MemoryBuffer &Ref = *Buf.get();    bool Saved = false; -  std::vector<NewArchiveIterator> NewMembers; +  std::vector<NewArchiveMember> NewMembers;    std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers;    std::vector<std::unique_ptr<object::Archive>> Archives; @@ -712,15 +762,15 @@ static void runMRIScript() {        ArchiveBuffers.push_back(std::move(*BufOrErr));        auto LibOrErr =            object::Archive::create(ArchiveBuffers.back()->getMemBufferRef()); -      failIfError(LibOrErr.getError(), "Could not parse library"); +      failIfError(errorToErrorCode(LibOrErr.takeError()), +                  "Could not parse library");        Archives.push_back(std::move(*LibOrErr));        object::Archive &Lib = *Archives.back(); -      for (auto &MemberOrErr : Lib.children()) { -        failIfError(MemberOrErr.getError()); -        auto &Member = MemberOrErr.get(); -        ErrorOr<StringRef> NameOrErr = Member.getName(); -        failIfError(NameOrErr.getError()); -        addMember(NewMembers, Member, *NameOrErr); +      { +        Error Err; +        for (auto &Member : Lib.children(Err)) +          addMember(NewMembers, Member); +        failIfError(std::move(Err));        }        break;      } @@ -760,7 +810,7 @@ static int ar_main() {  static int ranlib_main() {    if (RestOfArgs.size() != 1) -    fail(ToolName + "takes just one archive as argument"); +    fail(ToolName + " takes just one archive as an argument");    ArchiveName = RestOfArgs[0];    return performOperation(CreateSymTab, nullptr);  } @@ -768,7 +818,7 @@ static int ranlib_main() {  int main(int argc, char **argv) {    ToolName = argv[0];    // Print a stack trace if we signal out. -  sys::PrintStackTraceOnErrorSignal(); +  sys::PrintStackTraceOnErrorSignal(argv[0]);    PrettyStackTraceProgram X(argc, argv);    llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.  | 
