diff options
author | Alexander Shaposhnikov <shal1t712@gmail.com> | 2018-07-06 17:51:03 +0000 |
---|---|---|
committer | Alexander Shaposhnikov <shal1t712@gmail.com> | 2018-07-06 17:51:03 +0000 |
commit | 42b5ef026908953c823b4849ea1b9d3955c5c172 (patch) | |
tree | 92707c71aa6f0cdab6520566d54f9436a07eee9f /llvm/tools/llvm-objcopy/llvm-objcopy.cpp | |
parent | 573958773514f18bbd0ffc13b38ee853d0e32c5a (diff) | |
download | bcm5719-llvm-42b5ef026908953c823b4849ea1b9d3955c5c172.tar.gz bcm5719-llvm-42b5ef026908953c823b4849ea1b9d3955c5c172.zip |
[llvm-objcopy] Add support for static libraries
This diff adds support for handling static libraries
to llvm-objcopy and llvm-strip.
Test plan: make check-all
Differential revision: https://reviews.llvm.org/D48413
llvm-svn: 336455
Diffstat (limited to 'llvm/tools/llvm-objcopy/llvm-objcopy.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/llvm-objcopy.cpp | 114 |
1 files changed, 91 insertions, 23 deletions
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp index bf58f342ee4..c28862f073a 100644 --- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp +++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp @@ -13,6 +13,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ELFTypes.h" @@ -191,23 +193,23 @@ bool OnlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) { } std::unique_ptr<Writer> CreateWriter(const CopyConfig &Config, Object &Obj, - StringRef File, ElfType OutputElfType) { + Buffer &Buf, ElfType OutputElfType) { if (Config.OutputFormat == "binary") { - return llvm::make_unique<BinaryWriter>(File, Obj); + return llvm::make_unique<BinaryWriter>(Obj, Buf); } // Depending on the initial ELFT and OutputFormat we need a different Writer. switch (OutputElfType) { case ELFT_ELF32LE: - return llvm::make_unique<ELFWriter<ELF32LE>>(File, Obj, + return llvm::make_unique<ELFWriter<ELF32LE>>(Obj, Buf, !Config.StripSections); case ELFT_ELF64LE: - return llvm::make_unique<ELFWriter<ELF64LE>>(File, Obj, + return llvm::make_unique<ELFWriter<ELF64LE>>(Obj, Buf, !Config.StripSections); case ELFT_ELF32BE: - return llvm::make_unique<ELFWriter<ELF32BE>>(File, Obj, + return llvm::make_unique<ELFWriter<ELF32BE>>(Obj, Buf, !Config.StripSections); case ELFT_ELF64BE: - return llvm::make_unique<ELFWriter<ELF64BE>>(File, Obj, + return llvm::make_unique<ELFWriter<ELF64BE>>(Obj, Buf, !Config.StripSections); } llvm_unreachable("Invalid output format"); @@ -218,7 +220,8 @@ void SplitDWOToFile(const CopyConfig &Config, const Reader &Reader, auto DWOFile = Reader.create(); DWOFile->removeSections( [&](const SectionBase &Sec) { return OnlyKeepDWOPred(*DWOFile, Sec); }); - auto Writer = CreateWriter(Config, *DWOFile, File, OutputElfType); + FileBuffer FB(File); + auto Writer = CreateWriter(Config, *DWOFile, FB, OutputElfType); Writer->finalize(); Writer->write(); } @@ -441,26 +444,91 @@ void HandleArgs(const CopyConfig &Config, Object &Obj, const Reader &Reader, Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink); } -std::unique_ptr<Reader> CreateReader(StringRef InputFilename, - ElfType &OutputElfType) { - // Right now we can only read ELF files so there's only one reader; - auto Out = llvm::make_unique<ELFReader>(InputFilename); - // We need to set the default ElfType for output. - OutputElfType = Out->getElfType(); - return std::move(Out); -} +void ExecuteElfObjcopyOnBinary(const CopyConfig &Config, Binary &Binary, + Buffer &Out) { + ELFReader Reader(&Binary); + std::unique_ptr<Object> Obj = Reader.create(); -void ExecuteElfObjcopy(const CopyConfig &Config) { - ElfType OutputElfType; - auto Reader = CreateReader(Config.InputFilename, OutputElfType); - auto Obj = Reader->create(); - auto Writer = - CreateWriter(Config, *Obj, Config.OutputFilename, OutputElfType); - HandleArgs(Config, *Obj, *Reader, OutputElfType); + HandleArgs(Config, *Obj, Reader, Reader.getElfType()); + + std::unique_ptr<Writer> Writer = + CreateWriter(Config, *Obj, Out, Reader.getElfType()); Writer->finalize(); Writer->write(); } +// For regular archives this function simply calls llvm::writeArchive, +// For thin archives it writes the archive file itself as well as its members. +Error deepWriteArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, + bool WriteSymtab, object::Archive::Kind Kind, + bool Deterministic, bool Thin) { + Error E = + writeArchive(ArcName, NewMembers, WriteSymtab, Kind, Deterministic, Thin); + if (!Thin || E) + return E; + for (const NewArchiveMember &Member : NewMembers) { + // Internally, FileBuffer will use the buffer created by + // FileOutputBuffer::create, for regular files (that is the case for + // deepWriteArchive) FileOutputBuffer::create will return OnDiskBuffer. + // OnDiskBuffer uses a temporary file and then renames it. So in reality + // there is no inefficiency / duplicated in-memory buffers in this case. For + // now in-memory buffers can not be completely avoided since + // NewArchiveMember still requires them even though writeArchive does not + // write them on disk. + FileBuffer FB(Member.MemberName); + FB.allocate(Member.Buf->getBufferSize()); + std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(), + FB.getBufferStart()); + if (auto E = FB.commit()) + return E; + } + return Error::success(); +} + +void ExecuteElfObjcopyOnArchive(const CopyConfig &Config, const Archive &Ar) { + std::vector<NewArchiveMember> NewArchiveMembers; + Error Err = Error::success(); + for (const Archive::Child &Child : Ar.children(Err)) { + Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary(); + if (!ChildOrErr) + reportError(Ar.getFileName(), ChildOrErr.takeError()); + Expected<StringRef> ChildNameOrErr = Child.getName(); + if (!ChildNameOrErr) + reportError(Ar.getFileName(), ChildNameOrErr.takeError()); + + MemBuffer MB(ChildNameOrErr.get()); + ExecuteElfObjcopyOnBinary(Config, **ChildOrErr, MB); + + Expected<NewArchiveMember> Member = + NewArchiveMember::getOldMember(Child, true); + if (!Member) + reportError(Ar.getFileName(), Member.takeError()); + Member->Buf = MB.releaseMemoryBuffer(); + Member->MemberName = Member->Buf->getBufferIdentifier(); + NewArchiveMembers.push_back(std::move(*Member)); + } + + if (Err) + reportError(Config.InputFilename, std::move(Err)); + if (Error E = + deepWriteArchive(Config.OutputFilename, NewArchiveMembers, + Ar.hasSymbolTable(), Ar.kind(), true, Ar.isThin())) + reportError(Config.OutputFilename, std::move(E)); +} + +void ExecuteElfObjcopy(const CopyConfig &Config) { + Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr = + createBinary(Config.InputFilename); + if (!BinaryOrErr) + reportError(Config.InputFilename, BinaryOrErr.takeError()); + + if (Archive *Ar = dyn_cast<Archive>(BinaryOrErr.get().getBinary())) + return ExecuteElfObjcopyOnArchive(Config, *Ar); + + FileBuffer FB(Config.OutputFilename); + ExecuteElfObjcopyOnBinary(Config, *BinaryOrErr.get().getBinary(), FB); +} + // ParseObjcopyOptions returns the config and sets the input arguments. If a // help flag is set then ParseObjcopyOptions will print the help messege and // exit. @@ -584,7 +652,7 @@ CopyConfig ParseStripOptions(ArrayRef<const char *> ArgsArr) { InputArgs.getLastArgValue(STRIP_output, Positional[0]); Config.StripDebug = InputArgs.hasArg(STRIP_strip_debug); - + Config.DiscardAll = InputArgs.hasArg(STRIP_discard_all); Config.StripUnneeded = InputArgs.hasArg(STRIP_strip_unneeded); |