summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-ar/llvm-ar.cpp
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2016-06-22 04:03:28 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2016-06-22 04:03:28 +0000
commita0d42c86dbcb150c2a7a3d8f2a8500dcfb98a5d1 (patch)
tree90489211acda0912e56f46373144cad67cc04d22 /llvm/tools/llvm-ar/llvm-ar.cpp
parent32853ad7079311bb1c938d67c7cf25eddbcec912 (diff)
downloadbcm5719-llvm-a0d42c86dbcb150c2a7a3d8f2a8500dcfb98a5d1.tar.gz
bcm5719-llvm-a0d42c86dbcb150c2a7a3d8f2a8500dcfb98a5d1.zip
llvm-ar: be more clever about default format
Try to be more clever about selecting the default format. When an existing archive is used, use the type of the archive to determine the format. When existing members are present, use the first member's format to determine the format to use. If we are creating an empty archive (MRI mode) or are adding non-object members, default to the current behaviour of using the host type due to the lack of a better alternative. This aids in cross-compilation on Darwin to non-Darwin platforms which rely on GNU format archives. llvm-svn: 273373
Diffstat (limited to 'llvm/tools/llvm-ar/llvm-ar.cpp')
-rw-r--r--llvm/tools/llvm-ar/llvm-ar.cpp94
1 files changed, 76 insertions, 18 deletions
diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp
index 01c8b804a73..0078bda4db4 100644
--- a/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/llvm/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"
@@ -575,21 +576,86 @@ 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 NewArchiveIterator &Member) {
+ if (Member.isNewMember()) {
+ object::Archive::Kind Kind = getDefaultForHost();
+
+ sys::fs::file_status Status;
+ if (auto OptionalFD = Member.getFD(Status)) {
+ auto OptionalMB = MemoryBuffer::getOpenFile(*OptionalFD, Member.getName(),
+ Status.getSize(), false);
+ if (OptionalMB) {
+ MemoryBufferRef MemoryBuffer = (*OptionalMB)->getMemBufferRef();
+
+ Expected<std::unique_ptr<object::ObjectFile>> OptionalObject =
+ object::ObjectFile::createObjectFile(MemoryBuffer);
+
+ if (OptionalObject)
+ Kind = 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());
+ }
+
+ if (close(*OptionalFD) != 0)
+ failIfError(std::error_code(errno, std::generic_category()),
+ "failed to close file");
+ }
+
+ return Kind;
+ } else {
+ const object::Archive::Child &OldMember = Member.getOld();
+ if (OldMember.getParent()->isThin())
+ return object::Archive::Kind::K_GNU;
+
+ auto OptionalMB = OldMember.getMemoryBufferRef();
+ failIfError(OptionalMB.getError());
+
+ Expected<std::unique_ptr<object::ObjectFile>> OptionalObject =
+ object::ObjectFile::createObjectFile(*OptionalMB);
+
+ if (OptionalObject)
+ return isa<object::MachOObjectFile>(*OptionalObject->get())
+ ? 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::unique_ptr<MemoryBuffer> OldArchiveBuf,
std::vector<NewArchiveIterator> *NewMembersP) {
+ std::vector<NewArchiveIterator> NewMembers;
+ if (!NewMembersP)
+ NewMembers = computeNewArchiveMembers(Operation, OldArchive);
+
object::Archive::Kind Kind;
switch (FormatOpt) {
- case Default: {
- Triple T(sys::getProcessTriple());
- if (T.isOSDarwin() && !Thin)
- 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;
@@ -599,18 +665,10 @@ performWriteOperation(ArchiveOperation Operation,
Kind = object::Archive::K_BSD;
break;
}
- if (NewMembersP) {
- std::pair<StringRef, std::error_code> Result = writeArchive(
- ArchiveName, *NewMembersP, Symtab, Kind, Deterministic, Thin,
- std::move(OldArchiveBuf));
- failIfError(Result.second, Result.first);
- return;
- }
- std::vector<NewArchiveIterator> NewMembers =
- computeNewArchiveMembers(Operation, OldArchive);
- auto Result =
- writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin,
- std::move(OldArchiveBuf));
+
+ std::pair<StringRef, std::error_code> Result =
+ writeArchive(ArchiveName, NewMembersP ? *NewMembersP : NewMembers, Symtab,
+ Kind, Deterministic, Thin, std::move(OldArchiveBuf));
failIfError(Result.second, Result.first);
}
OpenPOWER on IntegriCloud