#include "Archive.h"
#include "llvm/ObjCopy/CommonConfig.h"
#include "llvm/ObjCopy/MultiFormatConfig.h"
#include "llvm/ObjCopy/ObjCopy.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/SmallVectorMemoryBuffer.h"
namespace llvm {
namespace objcopy {
using namespace llvm::object;
Expected<std::vector<NewArchiveMember>>
createNewArchiveMembers(const MultiFormatConfig &Config, const Archive &Ar) {
std::vector<NewArchiveMember> NewArchiveMembers;
Error Err = Error::success();
for (const Archive::Child &Child : Ar.children(Err)) {
Expected<StringRef> ChildNameOrErr = Child.getName();
if (!ChildNameOrErr)
return createFileError(Ar.getFileName(), ChildNameOrErr.takeError());
Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
if (!ChildOrErr)
return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")",
ChildOrErr.takeError());
SmallVector<char, 0> Buffer;
raw_svector_ostream MemStream(Buffer);
if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MemStream))
return std::move(E);
Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(
Child, Config.getCommonConfig().DeterministicArchives);
if (!Member)
return createFileError(Ar.getFileName(), Member.takeError());
Member->Buf = std::make_unique<SmallVectorMemoryBuffer>(
std::move(Buffer), ChildNameOrErr.get());
Member->MemberName = Member->Buf->getBufferIdentifier();
NewArchiveMembers.push_back(std::move(*Member));
}
if (Err)
return createFileError(Config.getCommonConfig().InputFilename,
std::move(Err));
return std::move(NewArchiveMembers);
}
static Error deepWriteArchive(StringRef ArcName,
ArrayRef<NewArchiveMember> NewMembers,
bool WriteSymtab, object::Archive::Kind Kind,
bool Deterministic, bool Thin) {
if (Kind == object::Archive::K_BSD && !NewMembers.empty() &&
NewMembers.front().detectKindFromObject() == object::Archive::K_DARWIN)
Kind = object::Archive::K_DARWIN;
if (Error E = writeArchive(ArcName, NewMembers, WriteSymtab, Kind,
Deterministic, Thin))
return createFileError(ArcName, std::move(E));
if (!Thin)
return Error::success();
for (const NewArchiveMember &Member : NewMembers) {
Expected<std::unique_ptr<FileOutputBuffer>> FB =
FileOutputBuffer::create(Member.MemberName, Member.Buf->getBufferSize(),
FileOutputBuffer::F_executable);
if (!FB)
return FB.takeError();
std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
(*FB)->getBufferStart());
if (Error E = (*FB)->commit())
return E;
}
return Error::success();
}
Error executeObjcopyOnArchive(const MultiFormatConfig &Config,
const object::Archive &Ar) {
Expected<std::vector<NewArchiveMember>> NewArchiveMembersOrErr =
createNewArchiveMembers(Config, Ar);
if (!NewArchiveMembersOrErr)
return NewArchiveMembersOrErr.takeError();
const CommonConfig &CommonConfig = Config.getCommonConfig();
return deepWriteArchive(CommonConfig.OutputFilename, *NewArchiveMembersOrErr,
Ar.hasSymbolTable(), Ar.kind(),
CommonConfig.DeterministicArchives, Ar.isThin());
}
} }