Archive.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. //===- Archive.cpp --------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #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"
  16. namespace llvm {
  17. namespace objcopy {
  18. using namespace llvm::object;
  19. Expected<std::vector<NewArchiveMember>>
  20. createNewArchiveMembers(const MultiFormatConfig &Config, const Archive &Ar) {
  21. std::vector<NewArchiveMember> NewArchiveMembers;
  22. Error Err = Error::success();
  23. for (const Archive::Child &Child : Ar.children(Err)) {
  24. Expected<StringRef> ChildNameOrErr = Child.getName();
  25. if (!ChildNameOrErr)
  26. return createFileError(Ar.getFileName(), ChildNameOrErr.takeError());
  27. Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
  28. if (!ChildOrErr)
  29. return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")",
  30. ChildOrErr.takeError());
  31. SmallVector<char, 0> Buffer;
  32. raw_svector_ostream MemStream(Buffer);
  33. if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MemStream))
  34. return std::move(E);
  35. Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(
  36. Child, Config.getCommonConfig().DeterministicArchives);
  37. if (!Member)
  38. return createFileError(Ar.getFileName(), Member.takeError());
  39. Member->Buf = std::make_unique<SmallVectorMemoryBuffer>(
  40. std::move(Buffer), ChildNameOrErr.get());
  41. Member->MemberName = Member->Buf->getBufferIdentifier();
  42. NewArchiveMembers.push_back(std::move(*Member));
  43. }
  44. if (Err)
  45. return createFileError(Config.getCommonConfig().InputFilename,
  46. std::move(Err));
  47. return std::move(NewArchiveMembers);
  48. }
  49. // For regular archives this function simply calls llvm::writeArchive,
  50. // For thin archives it writes the archive file itself as well as its members.
  51. static Error deepWriteArchive(StringRef ArcName,
  52. ArrayRef<NewArchiveMember> NewMembers,
  53. bool WriteSymtab, object::Archive::Kind Kind,
  54. bool Deterministic, bool Thin) {
  55. if (Kind == object::Archive::K_BSD && !NewMembers.empty() &&
  56. NewMembers.front().detectKindFromObject() == object::Archive::K_DARWIN)
  57. Kind = object::Archive::K_DARWIN;
  58. if (Error E = writeArchive(ArcName, NewMembers, WriteSymtab, Kind,
  59. Deterministic, Thin))
  60. return createFileError(ArcName, std::move(E));
  61. if (!Thin)
  62. return Error::success();
  63. for (const NewArchiveMember &Member : NewMembers) {
  64. // For regular files (as is the case for deepWriteArchive),
  65. // FileOutputBuffer::create will return OnDiskBuffer.
  66. // OnDiskBuffer uses a temporary file and then renames it. So in reality
  67. // there is no inefficiency / duplicated in-memory buffers in this case. For
  68. // now in-memory buffers can not be completely avoided since
  69. // NewArchiveMember still requires them even though writeArchive does not
  70. // write them on disk.
  71. Expected<std::unique_ptr<FileOutputBuffer>> FB =
  72. FileOutputBuffer::create(Member.MemberName, Member.Buf->getBufferSize(),
  73. FileOutputBuffer::F_executable);
  74. if (!FB)
  75. return FB.takeError();
  76. std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
  77. (*FB)->getBufferStart());
  78. if (Error E = (*FB)->commit())
  79. return E;
  80. }
  81. return Error::success();
  82. }
  83. Error executeObjcopyOnArchive(const MultiFormatConfig &Config,
  84. const object::Archive &Ar) {
  85. Expected<std::vector<NewArchiveMember>> NewArchiveMembersOrErr =
  86. createNewArchiveMembers(Config, Ar);
  87. if (!NewArchiveMembersOrErr)
  88. return NewArchiveMembersOrErr.takeError();
  89. const CommonConfig &CommonConfig = Config.getCommonConfig();
  90. return deepWriteArchive(CommonConfig.OutputFilename, *NewArchiveMembersOrErr,
  91. Ar.hasSymbolTable(), Ar.kind(),
  92. CommonConfig.DeterministicArchives, Ar.isThin());
  93. }
  94. } // end namespace objcopy
  95. } // end namespace llvm