1 //===- Archive.cpp --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 #include "llvm/ObjCopy/CommonConfig.h"
11 #include "llvm/ObjCopy/MultiFormatConfig.h"
12 #include "llvm/ObjCopy/ObjCopy.h"
13 #include "llvm/Object/Error.h"
14 #include "llvm/Object/MachO.h"
15 #include "llvm/Support/FileOutputBuffer.h"
16 #include "llvm/Support/SmallVectorMemoryBuffer.h"
21 using namespace llvm::object
;
23 Expected
<std::vector
<NewArchiveMember
>>
24 createNewArchiveMembers(const MultiFormatConfig
&Config
, const Archive
&Ar
) {
25 std::vector
<NewArchiveMember
> NewArchiveMembers
;
26 Error Err
= Error::success();
27 for (const Archive::Child
&Child
: Ar
.children(Err
)) {
28 Expected
<StringRef
> ChildNameOrErr
= Child
.getName();
30 return createFileError(Ar
.getFileName(), ChildNameOrErr
.takeError());
32 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= Child
.getAsBinary();
34 return createFileError(Ar
.getFileName() + "(" + *ChildNameOrErr
+ ")",
35 ChildOrErr
.takeError());
37 SmallVector
<char, 0> Buffer
;
38 raw_svector_ostream
MemStream(Buffer
);
40 if (Error E
= executeObjcopyOnBinary(Config
, *ChildOrErr
->get(), MemStream
))
43 Expected
<NewArchiveMember
> Member
= NewArchiveMember::getOldMember(
44 Child
, Config
.getCommonConfig().DeterministicArchives
);
46 return createFileError(Ar
.getFileName(), Member
.takeError());
48 Member
->Buf
= std::make_unique
<SmallVectorMemoryBuffer
>(
49 std::move(Buffer
), ChildNameOrErr
.get());
50 Member
->MemberName
= Member
->Buf
->getBufferIdentifier();
51 NewArchiveMembers
.push_back(std::move(*Member
));
54 return createFileError(Config
.getCommonConfig().InputFilename
,
56 return std::move(NewArchiveMembers
);
59 // For regular archives this function simply calls llvm::writeArchive,
60 // For thin archives it writes the archive file itself as well as its members.
61 static Error
deepWriteArchive(StringRef ArcName
,
62 ArrayRef
<NewArchiveMember
> NewMembers
,
63 SymtabWritingMode WriteSymtab
,
64 object::Archive::Kind Kind
, bool Deterministic
,
66 if (Kind
== object::Archive::K_BSD
&& !NewMembers
.empty() &&
67 NewMembers
.front().detectKindFromObject() == object::Archive::K_DARWIN
)
68 Kind
= object::Archive::K_DARWIN
;
70 if (Error E
= writeArchive(ArcName
, NewMembers
, WriteSymtab
, Kind
,
72 return createFileError(ArcName
, std::move(E
));
75 return Error::success();
77 for (const NewArchiveMember
&Member
: NewMembers
) {
78 // For regular files (as is the case for deepWriteArchive),
79 // FileOutputBuffer::create will return OnDiskBuffer.
80 // OnDiskBuffer uses a temporary file and then renames it. So in reality
81 // there is no inefficiency / duplicated in-memory buffers in this case. For
82 // now in-memory buffers can not be completely avoided since
83 // NewArchiveMember still requires them even though writeArchive does not
84 // write them on disk.
85 Expected
<std::unique_ptr
<FileOutputBuffer
>> FB
=
86 FileOutputBuffer::create(Member
.MemberName
, Member
.Buf
->getBufferSize(),
87 FileOutputBuffer::F_executable
);
89 return FB
.takeError();
90 std::copy(Member
.Buf
->getBufferStart(), Member
.Buf
->getBufferEnd(),
91 (*FB
)->getBufferStart());
92 if (Error E
= (*FB
)->commit())
95 return Error::success();
98 Error
executeObjcopyOnArchive(const MultiFormatConfig
&Config
,
99 const object::Archive
&Ar
) {
100 Expected
<std::vector
<NewArchiveMember
>> NewArchiveMembersOrErr
=
101 createNewArchiveMembers(Config
, Ar
);
102 if (!NewArchiveMembersOrErr
)
103 return NewArchiveMembersOrErr
.takeError();
104 const CommonConfig
&CommonConfig
= Config
.getCommonConfig();
105 return deepWriteArchive(CommonConfig
.OutputFilename
, *NewArchiveMembersOrErr
,
106 Ar
.hasSymbolTable() ? SymtabWritingMode::NormalSymtab
107 : SymtabWritingMode::NoSymtab
,
108 Ar
.kind(), CommonConfig
.DeterministicArchives
,
112 } // end namespace objcopy
113 } // end namespace llvm