Path: blob/main/contrib/llvm-project/llvm/lib/ObjCopy/Archive.cpp
35233 views
//===- Archive.cpp --------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Archive.h"9#include "llvm/ObjCopy/CommonConfig.h"10#include "llvm/ObjCopy/MultiFormatConfig.h"11#include "llvm/ObjCopy/ObjCopy.h"12#include "llvm/Object/Error.h"13#include "llvm/Object/MachO.h"14#include "llvm/Support/FileOutputBuffer.h"15#include "llvm/Support/SmallVectorMemoryBuffer.h"1617namespace llvm {18namespace objcopy {1920using namespace llvm::object;2122Expected<std::vector<NewArchiveMember>>23createNewArchiveMembers(const MultiFormatConfig &Config, const Archive &Ar) {24std::vector<NewArchiveMember> NewArchiveMembers;25Error Err = Error::success();26for (const Archive::Child &Child : Ar.children(Err)) {27Expected<StringRef> ChildNameOrErr = Child.getName();28if (!ChildNameOrErr)29return createFileError(Ar.getFileName(), ChildNameOrErr.takeError());3031Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();32if (!ChildOrErr)33return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")",34ChildOrErr.takeError());3536SmallVector<char, 0> Buffer;37raw_svector_ostream MemStream(Buffer);3839if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MemStream))40return std::move(E);4142Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(43Child, Config.getCommonConfig().DeterministicArchives);44if (!Member)45return createFileError(Ar.getFileName(), Member.takeError());4647Member->Buf = std::make_unique<SmallVectorMemoryBuffer>(48std::move(Buffer), ChildNameOrErr.get());49Member->MemberName = Member->Buf->getBufferIdentifier();50NewArchiveMembers.push_back(std::move(*Member));51}52if (Err)53return createFileError(Config.getCommonConfig().InputFilename,54std::move(Err));55return std::move(NewArchiveMembers);56}5758// For regular archives this function simply calls llvm::writeArchive,59// For thin archives it writes the archive file itself as well as its members.60static Error deepWriteArchive(StringRef ArcName,61ArrayRef<NewArchiveMember> NewMembers,62SymtabWritingMode WriteSymtab,63object::Archive::Kind Kind, bool Deterministic,64bool Thin) {65if (Kind == object::Archive::K_BSD && !NewMembers.empty() &&66NewMembers.front().detectKindFromObject() == object::Archive::K_DARWIN)67Kind = object::Archive::K_DARWIN;6869if (Error E = writeArchive(ArcName, NewMembers, WriteSymtab, Kind,70Deterministic, Thin))71return createFileError(ArcName, std::move(E));7273if (!Thin)74return Error::success();7576for (const NewArchiveMember &Member : NewMembers) {77// For regular files (as is the case for deepWriteArchive),78// FileOutputBuffer::create will return OnDiskBuffer.79// OnDiskBuffer uses a temporary file and then renames it. So in reality80// there is no inefficiency / duplicated in-memory buffers in this case. For81// now in-memory buffers can not be completely avoided since82// NewArchiveMember still requires them even though writeArchive does not83// write them on disk.84Expected<std::unique_ptr<FileOutputBuffer>> FB =85FileOutputBuffer::create(Member.MemberName, Member.Buf->getBufferSize(),86FileOutputBuffer::F_executable);87if (!FB)88return FB.takeError();89std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),90(*FB)->getBufferStart());91if (Error E = (*FB)->commit())92return E;93}94return Error::success();95}9697Error executeObjcopyOnArchive(const MultiFormatConfig &Config,98const object::Archive &Ar) {99Expected<std::vector<NewArchiveMember>> NewArchiveMembersOrErr =100createNewArchiveMembers(Config, Ar);101if (!NewArchiveMembersOrErr)102return NewArchiveMembersOrErr.takeError();103const CommonConfig &CommonConfig = Config.getCommonConfig();104return deepWriteArchive(CommonConfig.OutputFilename, *NewArchiveMembersOrErr,105Ar.hasSymbolTable() ? SymtabWritingMode::NormalSymtab106: SymtabWritingMode::NoSymtab,107Ar.kind(), CommonConfig.DeterministicArchives,108Ar.isThin());109}110111} // end namespace objcopy112} // end namespace llvm113114115