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/Support/FileOutputBuffer.h"
15 #include "llvm/Support/SmallVectorMemoryBuffer.h"
20 using namespace llvm::object
;
22 Expected
<std::vector
<NewArchiveMember
>>
23 createNewArchiveMembers(const MultiFormatConfig
&Config
, const Archive
&Ar
) {
24 std::vector
<NewArchiveMember
> NewArchiveMembers
;
25 Error Err
= Error::success();
26 for (const Archive::Child
&Child
: Ar
.children(Err
)) {
27 Expected
<StringRef
> ChildNameOrErr
= Child
.getName();
29 return createFileError(Ar
.getFileName(), ChildNameOrErr
.takeError());
31 Expected
<std::unique_ptr
<Binary
>> ChildOrErr
= Child
.getAsBinary();
33 return createFileError(Ar
.getFileName() + "(" + *ChildNameOrErr
+ ")",
34 ChildOrErr
.takeError());
36 SmallVector
<char, 0> Buffer
;
37 raw_svector_ostream
MemStream(Buffer
);
39 if (Error E
= executeObjcopyOnBinary(Config
, *ChildOrErr
->get(), MemStream
))
42 Expected
<NewArchiveMember
> Member
= NewArchiveMember::getOldMember(
43 Child
, Config
.getCommonConfig().DeterministicArchives
);
45 return createFileError(Ar
.getFileName(), Member
.takeError());
47 Member
->Buf
= std::make_unique
<SmallVectorMemoryBuffer
>(
48 std::move(Buffer
), ChildNameOrErr
.get());
49 Member
->MemberName
= Member
->Buf
->getBufferIdentifier();
50 NewArchiveMembers
.push_back(std::move(*Member
));
53 return createFileError(Config
.getCommonConfig().InputFilename
,
55 return std::move(NewArchiveMembers
);
58 // For regular archives this function simply calls llvm::writeArchive,
59 // For thin archives it writes the archive file itself as well as its members.
60 static Error
deepWriteArchive(StringRef ArcName
,
61 ArrayRef
<NewArchiveMember
> NewMembers
,
62 SymtabWritingMode WriteSymtab
,
63 object::Archive::Kind Kind
, bool Deterministic
,
65 if (Kind
== object::Archive::K_BSD
&& !NewMembers
.empty() &&
66 NewMembers
.front().detectKindFromObject() == object::Archive::K_DARWIN
)
67 Kind
= object::Archive::K_DARWIN
;
69 if (Error E
= writeArchive(ArcName
, NewMembers
, WriteSymtab
, Kind
,
71 return createFileError(ArcName
, std::move(E
));
74 return Error::success();
76 for (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 reality
80 // there is no inefficiency / duplicated in-memory buffers in this case. For
81 // now in-memory buffers can not be completely avoided since
82 // NewArchiveMember still requires them even though writeArchive does not
83 // write them on disk.
84 Expected
<std::unique_ptr
<FileOutputBuffer
>> FB
=
85 FileOutputBuffer::create(Member
.MemberName
, Member
.Buf
->getBufferSize(),
86 FileOutputBuffer::F_executable
);
88 return FB
.takeError();
89 std::copy(Member
.Buf
->getBufferStart(), Member
.Buf
->getBufferEnd(),
90 (*FB
)->getBufferStart());
91 if (Error E
= (*FB
)->commit())
94 return Error::success();
97 Error
executeObjcopyOnArchive(const MultiFormatConfig
&Config
,
98 const object::Archive
&Ar
) {
99 Expected
<std::vector
<NewArchiveMember
>> NewArchiveMembersOrErr
=
100 createNewArchiveMembers(Config
, Ar
);
101 if (!NewArchiveMembersOrErr
)
102 return NewArchiveMembersOrErr
.takeError();
103 const CommonConfig
&CommonConfig
= Config
.getCommonConfig();
104 return deepWriteArchive(CommonConfig
.OutputFilename
, *NewArchiveMembersOrErr
,
105 Ar
.hasSymbolTable() ? SymtabWritingMode::NormalSymtab
106 : SymtabWritingMode::NoSymtab
,
107 Ar
.kind(), CommonConfig
.DeterministicArchives
,
111 } // end namespace objcopy
112 } // end namespace llvm