#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"
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;
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);
}