Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ObjCopy/Archive.cpp
35233 views
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
9
#include "Archive.h"
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"
17
18
namespace llvm {
19
namespace objcopy {
20
21
using namespace llvm::object;
22
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();
29
if (!ChildNameOrErr)
30
return createFileError(Ar.getFileName(), ChildNameOrErr.takeError());
31
32
Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
33
if (!ChildOrErr)
34
return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")",
35
ChildOrErr.takeError());
36
37
SmallVector<char, 0> Buffer;
38
raw_svector_ostream MemStream(Buffer);
39
40
if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MemStream))
41
return std::move(E);
42
43
Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(
44
Child, Config.getCommonConfig().DeterministicArchives);
45
if (!Member)
46
return createFileError(Ar.getFileName(), Member.takeError());
47
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));
52
}
53
if (Err)
54
return createFileError(Config.getCommonConfig().InputFilename,
55
std::move(Err));
56
return std::move(NewArchiveMembers);
57
}
58
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,
65
bool Thin) {
66
if (Kind == object::Archive::K_BSD && !NewMembers.empty() &&
67
NewMembers.front().detectKindFromObject() == object::Archive::K_DARWIN)
68
Kind = object::Archive::K_DARWIN;
69
70
if (Error E = writeArchive(ArcName, NewMembers, WriteSymtab, Kind,
71
Deterministic, Thin))
72
return createFileError(ArcName, std::move(E));
73
74
if (!Thin)
75
return Error::success();
76
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);
88
if (!FB)
89
return FB.takeError();
90
std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
91
(*FB)->getBufferStart());
92
if (Error E = (*FB)->commit())
93
return E;
94
}
95
return Error::success();
96
}
97
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,
109
Ar.isThin());
110
}
111
112
} // end namespace objcopy
113
} // end namespace llvm
114
115