1*9880d681SAndroid Build Coastguard Worker //===- ArchiveWriter.cpp - ar File Format implementation --------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file defines the writeArchive function.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/ArchiveWriter.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/ArrayRef.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringRef.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/Archive.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/ObjectFile.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/SymbolicFile.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/EndianStream.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Errc.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Path.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ToolOutputFile.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker #if !defined(_MSC_VER) && !defined(__MINGW32__)
30*9880d681SAndroid Build Coastguard Worker #include <unistd.h>
31*9880d681SAndroid Build Coastguard Worker #else
32*9880d681SAndroid Build Coastguard Worker #include <io.h>
33*9880d681SAndroid Build Coastguard Worker #endif
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker using namespace llvm;
36*9880d681SAndroid Build Coastguard Worker
NewArchiveMember(MemoryBufferRef BufRef)37*9880d681SAndroid Build Coastguard Worker NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef)
38*9880d681SAndroid Build Coastguard Worker : Buf(MemoryBuffer::getMemBuffer(BufRef, false)) {}
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker Expected<NewArchiveMember>
getOldMember(const object::Archive::Child & OldMember,bool Deterministic)41*9880d681SAndroid Build Coastguard Worker NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,
42*9880d681SAndroid Build Coastguard Worker bool Deterministic) {
43*9880d681SAndroid Build Coastguard Worker ErrorOr<llvm::MemoryBufferRef> BufOrErr = OldMember.getMemoryBufferRef();
44*9880d681SAndroid Build Coastguard Worker if (!BufOrErr)
45*9880d681SAndroid Build Coastguard Worker return errorCodeToError(BufOrErr.getError());
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker NewArchiveMember M;
48*9880d681SAndroid Build Coastguard Worker M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
49*9880d681SAndroid Build Coastguard Worker if (!Deterministic) {
50*9880d681SAndroid Build Coastguard Worker M.ModTime = OldMember.getLastModified();
51*9880d681SAndroid Build Coastguard Worker M.UID = OldMember.getUID();
52*9880d681SAndroid Build Coastguard Worker M.GID = OldMember.getGID();
53*9880d681SAndroid Build Coastguard Worker M.Perms = OldMember.getAccessMode();
54*9880d681SAndroid Build Coastguard Worker }
55*9880d681SAndroid Build Coastguard Worker return std::move(M);
56*9880d681SAndroid Build Coastguard Worker }
57*9880d681SAndroid Build Coastguard Worker
getFile(StringRef FileName,bool Deterministic)58*9880d681SAndroid Build Coastguard Worker Expected<NewArchiveMember> NewArchiveMember::getFile(StringRef FileName,
59*9880d681SAndroid Build Coastguard Worker bool Deterministic) {
60*9880d681SAndroid Build Coastguard Worker sys::fs::file_status Status;
61*9880d681SAndroid Build Coastguard Worker int FD;
62*9880d681SAndroid Build Coastguard Worker if (auto EC = sys::fs::openFileForRead(FileName, FD))
63*9880d681SAndroid Build Coastguard Worker return errorCodeToError(EC);
64*9880d681SAndroid Build Coastguard Worker assert(FD != -1);
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker if (auto EC = sys::fs::status(FD, Status))
67*9880d681SAndroid Build Coastguard Worker return errorCodeToError(EC);
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker // Opening a directory doesn't make sense. Let it fail.
70*9880d681SAndroid Build Coastguard Worker // Linux cannot open directories with open(2), although
71*9880d681SAndroid Build Coastguard Worker // cygwin and *bsd can.
72*9880d681SAndroid Build Coastguard Worker if (Status.type() == sys::fs::file_type::directory_file)
73*9880d681SAndroid Build Coastguard Worker return errorCodeToError(make_error_code(errc::is_a_directory));
74*9880d681SAndroid Build Coastguard Worker
75*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
76*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getOpenFile(FD, FileName, Status.getSize(), false);
77*9880d681SAndroid Build Coastguard Worker if (!MemberBufferOrErr)
78*9880d681SAndroid Build Coastguard Worker return errorCodeToError(MemberBufferOrErr.getError());
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Worker if (close(FD) != 0)
81*9880d681SAndroid Build Coastguard Worker return errorCodeToError(std::error_code(errno, std::generic_category()));
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker NewArchiveMember M;
84*9880d681SAndroid Build Coastguard Worker M.Buf = std::move(*MemberBufferOrErr);
85*9880d681SAndroid Build Coastguard Worker if (!Deterministic) {
86*9880d681SAndroid Build Coastguard Worker M.ModTime = Status.getLastModificationTime();
87*9880d681SAndroid Build Coastguard Worker M.UID = Status.getUser();
88*9880d681SAndroid Build Coastguard Worker M.GID = Status.getGroup();
89*9880d681SAndroid Build Coastguard Worker M.Perms = Status.permissions();
90*9880d681SAndroid Build Coastguard Worker }
91*9880d681SAndroid Build Coastguard Worker return std::move(M);
92*9880d681SAndroid Build Coastguard Worker }
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker template <typename T>
printWithSpacePadding(raw_fd_ostream & OS,T Data,unsigned Size,bool MayTruncate=false)95*9880d681SAndroid Build Coastguard Worker static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size,
96*9880d681SAndroid Build Coastguard Worker bool MayTruncate = false) {
97*9880d681SAndroid Build Coastguard Worker uint64_t OldPos = OS.tell();
98*9880d681SAndroid Build Coastguard Worker OS << Data;
99*9880d681SAndroid Build Coastguard Worker unsigned SizeSoFar = OS.tell() - OldPos;
100*9880d681SAndroid Build Coastguard Worker if (Size > SizeSoFar) {
101*9880d681SAndroid Build Coastguard Worker OS.indent(Size - SizeSoFar);
102*9880d681SAndroid Build Coastguard Worker } else if (Size < SizeSoFar) {
103*9880d681SAndroid Build Coastguard Worker assert(MayTruncate && "Data doesn't fit in Size");
104*9880d681SAndroid Build Coastguard Worker // Some of the data this is used for (like UID) can be larger than the
105*9880d681SAndroid Build Coastguard Worker // space available in the archive format. Truncate in that case.
106*9880d681SAndroid Build Coastguard Worker OS.seek(OldPos + Size);
107*9880d681SAndroid Build Coastguard Worker }
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker
print32(raw_ostream & Out,object::Archive::Kind Kind,uint32_t Val)110*9880d681SAndroid Build Coastguard Worker static void print32(raw_ostream &Out, object::Archive::Kind Kind,
111*9880d681SAndroid Build Coastguard Worker uint32_t Val) {
112*9880d681SAndroid Build Coastguard Worker if (Kind == object::Archive::K_GNU)
113*9880d681SAndroid Build Coastguard Worker support::endian::Writer<support::big>(Out).write(Val);
114*9880d681SAndroid Build Coastguard Worker else
115*9880d681SAndroid Build Coastguard Worker support::endian::Writer<support::little>(Out).write(Val);
116*9880d681SAndroid Build Coastguard Worker }
117*9880d681SAndroid Build Coastguard Worker
printRestOfMemberHeader(raw_fd_ostream & Out,const sys::TimeValue & ModTime,unsigned UID,unsigned GID,unsigned Perms,unsigned Size)118*9880d681SAndroid Build Coastguard Worker static void printRestOfMemberHeader(raw_fd_ostream &Out,
119*9880d681SAndroid Build Coastguard Worker const sys::TimeValue &ModTime, unsigned UID,
120*9880d681SAndroid Build Coastguard Worker unsigned GID, unsigned Perms,
121*9880d681SAndroid Build Coastguard Worker unsigned Size) {
122*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, ModTime.toEpochTime(), 12);
123*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, UID, 6, true);
124*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, GID, 6, true);
125*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, format("%o", Perms), 8);
126*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, Size, 10);
127*9880d681SAndroid Build Coastguard Worker Out << "`\n";
128*9880d681SAndroid Build Coastguard Worker }
129*9880d681SAndroid Build Coastguard Worker
printGNUSmallMemberHeader(raw_fd_ostream & Out,StringRef Name,const sys::TimeValue & ModTime,unsigned UID,unsigned GID,unsigned Perms,unsigned Size)130*9880d681SAndroid Build Coastguard Worker static void printGNUSmallMemberHeader(raw_fd_ostream &Out, StringRef Name,
131*9880d681SAndroid Build Coastguard Worker const sys::TimeValue &ModTime,
132*9880d681SAndroid Build Coastguard Worker unsigned UID, unsigned GID,
133*9880d681SAndroid Build Coastguard Worker unsigned Perms, unsigned Size) {
134*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, Twine(Name) + "/", 16);
135*9880d681SAndroid Build Coastguard Worker printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
136*9880d681SAndroid Build Coastguard Worker }
137*9880d681SAndroid Build Coastguard Worker
printBSDMemberHeader(raw_fd_ostream & Out,StringRef Name,const sys::TimeValue & ModTime,unsigned UID,unsigned GID,unsigned Perms,unsigned Size)138*9880d681SAndroid Build Coastguard Worker static void printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name,
139*9880d681SAndroid Build Coastguard Worker const sys::TimeValue &ModTime, unsigned UID,
140*9880d681SAndroid Build Coastguard Worker unsigned GID, unsigned Perms, unsigned Size) {
141*9880d681SAndroid Build Coastguard Worker uint64_t PosAfterHeader = Out.tell() + 60 + Name.size();
142*9880d681SAndroid Build Coastguard Worker // Pad so that even 64 bit object files are aligned.
143*9880d681SAndroid Build Coastguard Worker unsigned Pad = OffsetToAlignment(PosAfterHeader, 8);
144*9880d681SAndroid Build Coastguard Worker unsigned NameWithPadding = Name.size() + Pad;
145*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
146*9880d681SAndroid Build Coastguard Worker printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
147*9880d681SAndroid Build Coastguard Worker NameWithPadding + Size);
148*9880d681SAndroid Build Coastguard Worker Out << Name;
149*9880d681SAndroid Build Coastguard Worker assert(PosAfterHeader == Out.tell());
150*9880d681SAndroid Build Coastguard Worker while (Pad--)
151*9880d681SAndroid Build Coastguard Worker Out.write(uint8_t(0));
152*9880d681SAndroid Build Coastguard Worker }
153*9880d681SAndroid Build Coastguard Worker
useStringTable(bool Thin,StringRef Name)154*9880d681SAndroid Build Coastguard Worker static bool useStringTable(bool Thin, StringRef Name) {
155*9880d681SAndroid Build Coastguard Worker return Thin || Name.size() >= 16;
156*9880d681SAndroid Build Coastguard Worker }
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker static void
printMemberHeader(raw_fd_ostream & Out,object::Archive::Kind Kind,bool Thin,StringRef Name,std::vector<unsigned>::iterator & StringMapIndexIter,const sys::TimeValue & ModTime,unsigned UID,unsigned GID,unsigned Perms,unsigned Size)159*9880d681SAndroid Build Coastguard Worker printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind, bool Thin,
160*9880d681SAndroid Build Coastguard Worker StringRef Name,
161*9880d681SAndroid Build Coastguard Worker std::vector<unsigned>::iterator &StringMapIndexIter,
162*9880d681SAndroid Build Coastguard Worker const sys::TimeValue &ModTime, unsigned UID, unsigned GID,
163*9880d681SAndroid Build Coastguard Worker unsigned Perms, unsigned Size) {
164*9880d681SAndroid Build Coastguard Worker if (Kind == object::Archive::K_BSD)
165*9880d681SAndroid Build Coastguard Worker return printBSDMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
166*9880d681SAndroid Build Coastguard Worker if (!useStringTable(Thin, Name))
167*9880d681SAndroid Build Coastguard Worker return printGNUSmallMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
168*9880d681SAndroid Build Coastguard Worker Out << '/';
169*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, *StringMapIndexIter++, 15);
170*9880d681SAndroid Build Coastguard Worker printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
171*9880d681SAndroid Build Coastguard Worker }
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker // Compute the relative path from From to To.
computeRelativePath(StringRef From,StringRef To)174*9880d681SAndroid Build Coastguard Worker static std::string computeRelativePath(StringRef From, StringRef To) {
175*9880d681SAndroid Build Coastguard Worker if (sys::path::is_absolute(From) || sys::path::is_absolute(To))
176*9880d681SAndroid Build Coastguard Worker return To;
177*9880d681SAndroid Build Coastguard Worker
178*9880d681SAndroid Build Coastguard Worker StringRef DirFrom = sys::path::parent_path(From);
179*9880d681SAndroid Build Coastguard Worker auto FromI = sys::path::begin(DirFrom);
180*9880d681SAndroid Build Coastguard Worker auto ToI = sys::path::begin(To);
181*9880d681SAndroid Build Coastguard Worker while (*FromI == *ToI) {
182*9880d681SAndroid Build Coastguard Worker ++FromI;
183*9880d681SAndroid Build Coastguard Worker ++ToI;
184*9880d681SAndroid Build Coastguard Worker }
185*9880d681SAndroid Build Coastguard Worker
186*9880d681SAndroid Build Coastguard Worker SmallString<128> Relative;
187*9880d681SAndroid Build Coastguard Worker for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
188*9880d681SAndroid Build Coastguard Worker sys::path::append(Relative, "..");
189*9880d681SAndroid Build Coastguard Worker
190*9880d681SAndroid Build Coastguard Worker for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI)
191*9880d681SAndroid Build Coastguard Worker sys::path::append(Relative, *ToI);
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker return Relative.str();
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker
writeStringTable(raw_fd_ostream & Out,StringRef ArcName,ArrayRef<NewArchiveMember> Members,std::vector<unsigned> & StringMapIndexes,bool Thin)196*9880d681SAndroid Build Coastguard Worker static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName,
197*9880d681SAndroid Build Coastguard Worker ArrayRef<NewArchiveMember> Members,
198*9880d681SAndroid Build Coastguard Worker std::vector<unsigned> &StringMapIndexes,
199*9880d681SAndroid Build Coastguard Worker bool Thin) {
200*9880d681SAndroid Build Coastguard Worker unsigned StartOffset = 0;
201*9880d681SAndroid Build Coastguard Worker for (const NewArchiveMember &M : Members) {
202*9880d681SAndroid Build Coastguard Worker StringRef Path = M.Buf->getBufferIdentifier();
203*9880d681SAndroid Build Coastguard Worker StringRef Name = sys::path::filename(Path);
204*9880d681SAndroid Build Coastguard Worker if (!useStringTable(Thin, Name))
205*9880d681SAndroid Build Coastguard Worker continue;
206*9880d681SAndroid Build Coastguard Worker if (StartOffset == 0) {
207*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, "//", 58);
208*9880d681SAndroid Build Coastguard Worker Out << "`\n";
209*9880d681SAndroid Build Coastguard Worker StartOffset = Out.tell();
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker StringMapIndexes.push_back(Out.tell() - StartOffset);
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Worker if (Thin)
214*9880d681SAndroid Build Coastguard Worker Out << computeRelativePath(ArcName, Path);
215*9880d681SAndroid Build Coastguard Worker else
216*9880d681SAndroid Build Coastguard Worker Out << Name;
217*9880d681SAndroid Build Coastguard Worker
218*9880d681SAndroid Build Coastguard Worker Out << "/\n";
219*9880d681SAndroid Build Coastguard Worker }
220*9880d681SAndroid Build Coastguard Worker if (StartOffset == 0)
221*9880d681SAndroid Build Coastguard Worker return;
222*9880d681SAndroid Build Coastguard Worker if (Out.tell() % 2)
223*9880d681SAndroid Build Coastguard Worker Out << '\n';
224*9880d681SAndroid Build Coastguard Worker int Pos = Out.tell();
225*9880d681SAndroid Build Coastguard Worker Out.seek(StartOffset - 12);
226*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, Pos - StartOffset, 10);
227*9880d681SAndroid Build Coastguard Worker Out.seek(Pos);
228*9880d681SAndroid Build Coastguard Worker }
229*9880d681SAndroid Build Coastguard Worker
now(bool Deterministic)230*9880d681SAndroid Build Coastguard Worker static sys::TimeValue now(bool Deterministic) {
231*9880d681SAndroid Build Coastguard Worker if (!Deterministic)
232*9880d681SAndroid Build Coastguard Worker return sys::TimeValue::now();
233*9880d681SAndroid Build Coastguard Worker sys::TimeValue TV;
234*9880d681SAndroid Build Coastguard Worker TV.fromEpochTime(0);
235*9880d681SAndroid Build Coastguard Worker return TV;
236*9880d681SAndroid Build Coastguard Worker }
237*9880d681SAndroid Build Coastguard Worker
238*9880d681SAndroid Build Coastguard Worker // Returns the offset of the first reference to a member offset.
239*9880d681SAndroid Build Coastguard Worker static ErrorOr<unsigned>
writeSymbolTable(raw_fd_ostream & Out,object::Archive::Kind Kind,ArrayRef<NewArchiveMember> Members,std::vector<unsigned> & MemberOffsetRefs,bool Deterministic)240*9880d681SAndroid Build Coastguard Worker writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
241*9880d681SAndroid Build Coastguard Worker ArrayRef<NewArchiveMember> Members,
242*9880d681SAndroid Build Coastguard Worker std::vector<unsigned> &MemberOffsetRefs, bool Deterministic) {
243*9880d681SAndroid Build Coastguard Worker unsigned HeaderStartOffset = 0;
244*9880d681SAndroid Build Coastguard Worker unsigned BodyStartOffset = 0;
245*9880d681SAndroid Build Coastguard Worker SmallString<128> NameBuf;
246*9880d681SAndroid Build Coastguard Worker raw_svector_ostream NameOS(NameBuf);
247*9880d681SAndroid Build Coastguard Worker LLVMContext Context;
248*9880d681SAndroid Build Coastguard Worker for (unsigned MemberNum = 0, N = Members.size(); MemberNum < N; ++MemberNum) {
249*9880d681SAndroid Build Coastguard Worker MemoryBufferRef MemberBuffer = Members[MemberNum].Buf->getMemBufferRef();
250*9880d681SAndroid Build Coastguard Worker Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
251*9880d681SAndroid Build Coastguard Worker object::SymbolicFile::createSymbolicFile(
252*9880d681SAndroid Build Coastguard Worker MemberBuffer, sys::fs::file_magic::unknown, &Context);
253*9880d681SAndroid Build Coastguard Worker if (!ObjOrErr) {
254*9880d681SAndroid Build Coastguard Worker // FIXME: check only for "not an object file" errors.
255*9880d681SAndroid Build Coastguard Worker consumeError(ObjOrErr.takeError());
256*9880d681SAndroid Build Coastguard Worker continue;
257*9880d681SAndroid Build Coastguard Worker }
258*9880d681SAndroid Build Coastguard Worker object::SymbolicFile &Obj = *ObjOrErr.get();
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Worker if (!HeaderStartOffset) {
261*9880d681SAndroid Build Coastguard Worker HeaderStartOffset = Out.tell();
262*9880d681SAndroid Build Coastguard Worker if (Kind == object::Archive::K_GNU)
263*9880d681SAndroid Build Coastguard Worker printGNUSmallMemberHeader(Out, "", now(Deterministic), 0, 0, 0, 0);
264*9880d681SAndroid Build Coastguard Worker else
265*9880d681SAndroid Build Coastguard Worker printBSDMemberHeader(Out, "__.SYMDEF", now(Deterministic), 0, 0, 0, 0);
266*9880d681SAndroid Build Coastguard Worker BodyStartOffset = Out.tell();
267*9880d681SAndroid Build Coastguard Worker print32(Out, Kind, 0); // number of entries or bytes
268*9880d681SAndroid Build Coastguard Worker }
269*9880d681SAndroid Build Coastguard Worker
270*9880d681SAndroid Build Coastguard Worker for (const object::BasicSymbolRef &S : Obj.symbols()) {
271*9880d681SAndroid Build Coastguard Worker uint32_t Symflags = S.getFlags();
272*9880d681SAndroid Build Coastguard Worker if (Symflags & object::SymbolRef::SF_FormatSpecific)
273*9880d681SAndroid Build Coastguard Worker continue;
274*9880d681SAndroid Build Coastguard Worker if (!(Symflags & object::SymbolRef::SF_Global))
275*9880d681SAndroid Build Coastguard Worker continue;
276*9880d681SAndroid Build Coastguard Worker if (Symflags & object::SymbolRef::SF_Undefined)
277*9880d681SAndroid Build Coastguard Worker continue;
278*9880d681SAndroid Build Coastguard Worker
279*9880d681SAndroid Build Coastguard Worker unsigned NameOffset = NameOS.tell();
280*9880d681SAndroid Build Coastguard Worker if (auto EC = S.printName(NameOS))
281*9880d681SAndroid Build Coastguard Worker return EC;
282*9880d681SAndroid Build Coastguard Worker NameOS << '\0';
283*9880d681SAndroid Build Coastguard Worker MemberOffsetRefs.push_back(MemberNum);
284*9880d681SAndroid Build Coastguard Worker if (Kind == object::Archive::K_BSD)
285*9880d681SAndroid Build Coastguard Worker print32(Out, Kind, NameOffset);
286*9880d681SAndroid Build Coastguard Worker print32(Out, Kind, 0); // member offset
287*9880d681SAndroid Build Coastguard Worker }
288*9880d681SAndroid Build Coastguard Worker }
289*9880d681SAndroid Build Coastguard Worker
290*9880d681SAndroid Build Coastguard Worker if (HeaderStartOffset == 0)
291*9880d681SAndroid Build Coastguard Worker return 0;
292*9880d681SAndroid Build Coastguard Worker
293*9880d681SAndroid Build Coastguard Worker StringRef StringTable = NameOS.str();
294*9880d681SAndroid Build Coastguard Worker if (Kind == object::Archive::K_BSD)
295*9880d681SAndroid Build Coastguard Worker print32(Out, Kind, StringTable.size()); // byte count of the string table
296*9880d681SAndroid Build Coastguard Worker Out << StringTable;
297*9880d681SAndroid Build Coastguard Worker
298*9880d681SAndroid Build Coastguard Worker // ld64 requires the next member header to start at an offset that is
299*9880d681SAndroid Build Coastguard Worker // 4 bytes aligned.
300*9880d681SAndroid Build Coastguard Worker unsigned Pad = OffsetToAlignment(Out.tell(), 4);
301*9880d681SAndroid Build Coastguard Worker while (Pad--)
302*9880d681SAndroid Build Coastguard Worker Out.write(uint8_t(0));
303*9880d681SAndroid Build Coastguard Worker
304*9880d681SAndroid Build Coastguard Worker // Patch up the size of the symbol table now that we know how big it is.
305*9880d681SAndroid Build Coastguard Worker unsigned Pos = Out.tell();
306*9880d681SAndroid Build Coastguard Worker const unsigned MemberHeaderSize = 60;
307*9880d681SAndroid Build Coastguard Worker Out.seek(HeaderStartOffset + 48); // offset of the size field.
308*9880d681SAndroid Build Coastguard Worker printWithSpacePadding(Out, Pos - MemberHeaderSize - HeaderStartOffset, 10);
309*9880d681SAndroid Build Coastguard Worker
310*9880d681SAndroid Build Coastguard Worker // Patch up the number of symbols.
311*9880d681SAndroid Build Coastguard Worker Out.seek(BodyStartOffset);
312*9880d681SAndroid Build Coastguard Worker unsigned NumSyms = MemberOffsetRefs.size();
313*9880d681SAndroid Build Coastguard Worker if (Kind == object::Archive::K_GNU)
314*9880d681SAndroid Build Coastguard Worker print32(Out, Kind, NumSyms);
315*9880d681SAndroid Build Coastguard Worker else
316*9880d681SAndroid Build Coastguard Worker print32(Out, Kind, NumSyms * 8);
317*9880d681SAndroid Build Coastguard Worker
318*9880d681SAndroid Build Coastguard Worker Out.seek(Pos);
319*9880d681SAndroid Build Coastguard Worker return BodyStartOffset + 4;
320*9880d681SAndroid Build Coastguard Worker }
321*9880d681SAndroid Build Coastguard Worker
322*9880d681SAndroid Build Coastguard Worker std::pair<StringRef, std::error_code>
writeArchive(StringRef ArcName,std::vector<NewArchiveMember> & NewMembers,bool WriteSymtab,object::Archive::Kind Kind,bool Deterministic,bool Thin,std::unique_ptr<MemoryBuffer> OldArchiveBuf)323*9880d681SAndroid Build Coastguard Worker llvm::writeArchive(StringRef ArcName,
324*9880d681SAndroid Build Coastguard Worker std::vector<NewArchiveMember> &NewMembers,
325*9880d681SAndroid Build Coastguard Worker bool WriteSymtab, object::Archive::Kind Kind,
326*9880d681SAndroid Build Coastguard Worker bool Deterministic, bool Thin,
327*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MemoryBuffer> OldArchiveBuf) {
328*9880d681SAndroid Build Coastguard Worker assert((!Thin || Kind == object::Archive::K_GNU) &&
329*9880d681SAndroid Build Coastguard Worker "Only the gnu format has a thin mode");
330*9880d681SAndroid Build Coastguard Worker SmallString<128> TmpArchive;
331*9880d681SAndroid Build Coastguard Worker int TmpArchiveFD;
332*9880d681SAndroid Build Coastguard Worker if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
333*9880d681SAndroid Build Coastguard Worker TmpArchiveFD, TmpArchive))
334*9880d681SAndroid Build Coastguard Worker return std::make_pair(ArcName, EC);
335*9880d681SAndroid Build Coastguard Worker
336*9880d681SAndroid Build Coastguard Worker tool_output_file Output(TmpArchive, TmpArchiveFD);
337*9880d681SAndroid Build Coastguard Worker raw_fd_ostream &Out = Output.os();
338*9880d681SAndroid Build Coastguard Worker if (Thin)
339*9880d681SAndroid Build Coastguard Worker Out << "!<thin>\n";
340*9880d681SAndroid Build Coastguard Worker else
341*9880d681SAndroid Build Coastguard Worker Out << "!<arch>\n";
342*9880d681SAndroid Build Coastguard Worker
343*9880d681SAndroid Build Coastguard Worker std::vector<unsigned> MemberOffsetRefs;
344*9880d681SAndroid Build Coastguard Worker
345*9880d681SAndroid Build Coastguard Worker std::vector<std::unique_ptr<MemoryBuffer>> Buffers;
346*9880d681SAndroid Build Coastguard Worker std::vector<MemoryBufferRef> Members;
347*9880d681SAndroid Build Coastguard Worker std::vector<sys::fs::file_status> NewMemberStatus;
348*9880d681SAndroid Build Coastguard Worker
349*9880d681SAndroid Build Coastguard Worker unsigned MemberReferenceOffset = 0;
350*9880d681SAndroid Build Coastguard Worker if (WriteSymtab) {
351*9880d681SAndroid Build Coastguard Worker ErrorOr<unsigned> MemberReferenceOffsetOrErr = writeSymbolTable(
352*9880d681SAndroid Build Coastguard Worker Out, Kind, NewMembers, MemberOffsetRefs, Deterministic);
353*9880d681SAndroid Build Coastguard Worker if (auto EC = MemberReferenceOffsetOrErr.getError())
354*9880d681SAndroid Build Coastguard Worker return std::make_pair(ArcName, EC);
355*9880d681SAndroid Build Coastguard Worker MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
356*9880d681SAndroid Build Coastguard Worker }
357*9880d681SAndroid Build Coastguard Worker
358*9880d681SAndroid Build Coastguard Worker std::vector<unsigned> StringMapIndexes;
359*9880d681SAndroid Build Coastguard Worker if (Kind != object::Archive::K_BSD)
360*9880d681SAndroid Build Coastguard Worker writeStringTable(Out, ArcName, NewMembers, StringMapIndexes, Thin);
361*9880d681SAndroid Build Coastguard Worker
362*9880d681SAndroid Build Coastguard Worker std::vector<unsigned>::iterator StringMapIndexIter = StringMapIndexes.begin();
363*9880d681SAndroid Build Coastguard Worker std::vector<unsigned> MemberOffset;
364*9880d681SAndroid Build Coastguard Worker for (const NewArchiveMember &M : NewMembers) {
365*9880d681SAndroid Build Coastguard Worker MemoryBufferRef File = M.Buf->getMemBufferRef();
366*9880d681SAndroid Build Coastguard Worker
367*9880d681SAndroid Build Coastguard Worker unsigned Pos = Out.tell();
368*9880d681SAndroid Build Coastguard Worker MemberOffset.push_back(Pos);
369*9880d681SAndroid Build Coastguard Worker
370*9880d681SAndroid Build Coastguard Worker printMemberHeader(Out, Kind, Thin,
371*9880d681SAndroid Build Coastguard Worker sys::path::filename(M.Buf->getBufferIdentifier()),
372*9880d681SAndroid Build Coastguard Worker StringMapIndexIter, M.ModTime, M.UID, M.GID, M.Perms,
373*9880d681SAndroid Build Coastguard Worker M.Buf->getBufferSize());
374*9880d681SAndroid Build Coastguard Worker
375*9880d681SAndroid Build Coastguard Worker if (!Thin)
376*9880d681SAndroid Build Coastguard Worker Out << File.getBuffer();
377*9880d681SAndroid Build Coastguard Worker
378*9880d681SAndroid Build Coastguard Worker if (Out.tell() % 2)
379*9880d681SAndroid Build Coastguard Worker Out << '\n';
380*9880d681SAndroid Build Coastguard Worker }
381*9880d681SAndroid Build Coastguard Worker
382*9880d681SAndroid Build Coastguard Worker if (MemberReferenceOffset) {
383*9880d681SAndroid Build Coastguard Worker Out.seek(MemberReferenceOffset);
384*9880d681SAndroid Build Coastguard Worker for (unsigned MemberNum : MemberOffsetRefs) {
385*9880d681SAndroid Build Coastguard Worker if (Kind == object::Archive::K_BSD)
386*9880d681SAndroid Build Coastguard Worker Out.seek(Out.tell() + 4); // skip over the string offset
387*9880d681SAndroid Build Coastguard Worker print32(Out, Kind, MemberOffset[MemberNum]);
388*9880d681SAndroid Build Coastguard Worker }
389*9880d681SAndroid Build Coastguard Worker }
390*9880d681SAndroid Build Coastguard Worker
391*9880d681SAndroid Build Coastguard Worker Output.keep();
392*9880d681SAndroid Build Coastguard Worker Out.close();
393*9880d681SAndroid Build Coastguard Worker
394*9880d681SAndroid Build Coastguard Worker // At this point, we no longer need whatever backing memory
395*9880d681SAndroid Build Coastguard Worker // was used to generate the NewMembers. On Windows, this buffer
396*9880d681SAndroid Build Coastguard Worker // could be a mapped view of the file we want to replace (if
397*9880d681SAndroid Build Coastguard Worker // we're updating an existing archive, say). In that case, the
398*9880d681SAndroid Build Coastguard Worker // rename would still succeed, but it would leave behind a
399*9880d681SAndroid Build Coastguard Worker // temporary file (actually the original file renamed) because
400*9880d681SAndroid Build Coastguard Worker // a file cannot be deleted while there's a handle open on it,
401*9880d681SAndroid Build Coastguard Worker // only renamed. So by freeing this buffer, this ensures that
402*9880d681SAndroid Build Coastguard Worker // the last open handle on the destination file, if any, is
403*9880d681SAndroid Build Coastguard Worker // closed before we attempt to rename.
404*9880d681SAndroid Build Coastguard Worker OldArchiveBuf.reset();
405*9880d681SAndroid Build Coastguard Worker
406*9880d681SAndroid Build Coastguard Worker sys::fs::rename(TmpArchive, ArcName);
407*9880d681SAndroid Build Coastguard Worker return std::make_pair("", std::error_code());
408*9880d681SAndroid Build Coastguard Worker }
409