Movatterモバイル変換


[0]ホーム

URL:


LLVM 20.0.0git
ArchiveWriter.cpp
Go to the documentation of this file.
1//===- ArchiveWriter.cpp - ar File Format implementation --------*- C++ -*-===//
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// This file defines the writeArchive function.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Object/ArchiveWriter.h"
14#include "llvm/ADT/ArrayRef.h"
15#include "llvm/ADT/StringMap.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/BinaryFormat/Magic.h"
18#include "llvm/IR/LLVMContext.h"
19#include "llvm/Object/Archive.h"
20#include "llvm/Object/COFF.h"
21#include "llvm/Object/COFFImportFile.h"
22#include "llvm/Object/Error.h"
23#include "llvm/Object/IRObjectFile.h"
24#include "llvm/Object/MachO.h"
25#include "llvm/Object/ObjectFile.h"
26#include "llvm/Object/SymbolicFile.h"
27#include "llvm/Object/XCOFFObjectFile.h"
28#include "llvm/Support/Alignment.h"
29#include "llvm/Support/EndianStream.h"
30#include "llvm/Support/Errc.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/Format.h"
33#include "llvm/Support/MathExtras.h"
34#include "llvm/Support/Path.h"
35#include "llvm/Support/SmallVectorMemoryBuffer.h"
36#include "llvm/Support/raw_ostream.h"
37
38#include <cerrno>
39#include <map>
40
41#if !defined(_MSC_VER) && !defined(__MINGW32__)
42#include <unistd.h>
43#else
44#include <io.h>
45#endif
46
47using namespacellvm;
48using namespacellvm::object;
49
50structSymMap {
51boolUseECMap =false;
52 std::map<std::string, uint16_t>Map;
53 std::map<std::string, uint16_t>ECMap;
54};
55
56NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef)
57 : Buf(MemoryBuffer::getMemBuffer(BufRef,false)),
58 MemberName(BufRef.getBufferIdentifier()) {}
59
60object::Archive::KindNewArchiveMember::detectKindFromObject() const{
61auto MemBufferRef = this->Buf->getMemBufferRef();
62Expected<std::unique_ptr<object::ObjectFile>> OptionalObject =
63object::ObjectFile::createObjectFile(MemBufferRef);
64
65if (OptionalObject) {
66if (isa<object::MachOObjectFile>(**OptionalObject))
67returnobject::Archive::K_DARWIN;
68if (isa<object::XCOFFObjectFile>(**OptionalObject))
69returnobject::Archive::K_AIXBIG;
70if (isa<object::COFFObjectFile>(**OptionalObject) ||
71 isa<object::COFFImportFile>(**OptionalObject))
72returnobject::Archive::K_COFF;
73returnobject::Archive::K_GNU;
74 }
75
76// Squelch the error in case we had a non-object file.
77consumeError(OptionalObject.takeError());
78
79// If we're adding a bitcode file to the archive, detect the Archive kind
80// based on the target triple.
81LLVMContext Context;
82if (identify_magic(MemBufferRef.getBuffer()) ==file_magic::bitcode) {
83if (auto ObjOrErr =object::SymbolicFile::createSymbolicFile(
84 MemBufferRef,file_magic::bitcode, &Context)) {
85auto &IRObject = cast<object::IRObjectFile>(**ObjOrErr);
86auto TargetTriple =Triple(IRObject.getTargetTriple());
87returnobject::Archive::getDefaultKindForTriple(TargetTriple);
88 }else {
89// Squelch the error in case this was not a SymbolicFile.
90consumeError(ObjOrErr.takeError());
91 }
92 }
93
94returnobject::Archive::getDefaultKind();
95}
96
97Expected<NewArchiveMember>
98NewArchiveMember::getOldMember(constobject::Archive::Child &OldMember,
99bool Deterministic) {
100Expected<llvm::MemoryBufferRef> BufOrErr = OldMember.getMemoryBufferRef();
101if (!BufOrErr)
102return BufOrErr.takeError();
103
104NewArchiveMember M;
105 M.Buf =MemoryBuffer::getMemBuffer(*BufOrErr,false);
106 M.MemberName = M.Buf->getBufferIdentifier();
107if (!Deterministic) {
108auto ModTimeOrErr = OldMember.getLastModified();
109if (!ModTimeOrErr)
110return ModTimeOrErr.takeError();
111 M.ModTime = ModTimeOrErr.get();
112Expected<unsigned> UIDOrErr = OldMember.getUID();
113if (!UIDOrErr)
114return UIDOrErr.takeError();
115 M.UID = UIDOrErr.get();
116Expected<unsigned> GIDOrErr = OldMember.getGID();
117if (!GIDOrErr)
118return GIDOrErr.takeError();
119 M.GID = GIDOrErr.get();
120Expected<sys::fs::perms> AccessModeOrErr = OldMember.getAccessMode();
121if (!AccessModeOrErr)
122return AccessModeOrErr.takeError();
123 M.Perms = AccessModeOrErr.get();
124 }
125return std::move(M);
126}
127
128Expected<NewArchiveMember>NewArchiveMember::getFile(StringRef FileName,
129bool Deterministic) {
130sys::fs::file_statusStatus;
131auto FDOrErr =sys::fs::openNativeFileForRead(FileName);
132if (!FDOrErr)
133return FDOrErr.takeError();
134sys::fs::file_t FD = *FDOrErr;
135assert(FD !=sys::fs::kInvalidFile);
136
137if (auto EC =sys::fs::status(FD,Status))
138returnerrorCodeToError(EC);
139
140// Opening a directory doesn't make sense. Let it fail.
141// Linux cannot open directories with open(2), although
142// cygwin and *bsd can.
143if (Status.type() ==sys::fs::file_type::directory_file)
144returnerrorCodeToError(make_error_code(errc::is_a_directory));
145
146ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
147MemoryBuffer::getOpenFile(FD, FileName,Status.getSize(),false);
148if (!MemberBufferOrErr)
149returnerrorCodeToError(MemberBufferOrErr.getError());
150
151if (auto EC =sys::fs::closeFile(FD))
152returnerrorCodeToError(EC);
153
154NewArchiveMember M;
155 M.Buf = std::move(*MemberBufferOrErr);
156 M.MemberName = M.Buf->getBufferIdentifier();
157if (!Deterministic) {
158 M.ModTime = std::chrono::time_point_cast<std::chrono::seconds>(
159Status.getLastModificationTime());
160 M.UID =Status.getUser();
161 M.GID =Status.getGroup();
162 M.Perms =Status.permissions();
163 }
164return std::move(M);
165}
166
167template <typename T>
168staticvoidprintWithSpacePadding(raw_ostream &OS,TData,unsignedSize) {
169uint64_t OldPos =OS.tell();
170OS <<Data;
171unsigned SizeSoFar =OS.tell() - OldPos;
172assert(SizeSoFar <=Size &&"Data doesn't fit in Size");
173OS.indent(Size - SizeSoFar);
174}
175
176staticboolisDarwin(object::Archive::KindKind) {
177returnKind ==object::Archive::K_DARWIN ||
178Kind ==object::Archive::K_DARWIN64;
179}
180
181staticboolisAIXBigArchive(object::Archive::KindKind) {
182returnKind ==object::Archive::K_AIXBIG;
183}
184
185staticboolisCOFFArchive(object::Archive::KindKind) {
186returnKind ==object::Archive::K_COFF;
187}
188
189staticboolisBSDLike(object::Archive::KindKind) {
190switch (Kind) {
191caseobject::Archive::K_GNU:
192caseobject::Archive::K_GNU64:
193caseobject::Archive::K_AIXBIG:
194caseobject::Archive::K_COFF:
195returnfalse;
196caseobject::Archive::K_BSD:
197caseobject::Archive::K_DARWIN:
198caseobject::Archive::K_DARWIN64:
199returntrue;
200 }
201llvm_unreachable("not supported for writting");
202}
203
204template <class T>
205staticvoidprint(raw_ostream &Out,object::Archive::KindKind,T Val) {
206support::endian::write(Out, Val,
207isBSDLike(Kind) ?llvm::endianness::little
208 :llvm::endianness::big);
209}
210
211template <class T>staticvoidprintLE(raw_ostream &Out,T Val) {
212support::endian::write(Out, Val,llvm::endianness::little);
213}
214
215staticvoidprintRestOfMemberHeader(
216raw_ostream &Out,constsys::TimePoint<std::chrono::seconds> &ModTime,
217unsigned UID,unsigned GID,unsigned Perms,uint64_tSize) {
218printWithSpacePadding(Out,sys::toTimeT(ModTime), 12);
219
220// The format has only 6 chars for uid and gid. Truncate if the provided
221// values don't fit.
222printWithSpacePadding(Out, UID % 1000000, 6);
223printWithSpacePadding(Out, GID % 1000000, 6);
224
225printWithSpacePadding(Out,format("%o", Perms), 8);
226printWithSpacePadding(Out,Size, 10);
227 Out <<"`\n";
228}
229
230staticvoid
231printGNUSmallMemberHeader(raw_ostream &Out,StringRefName,
232constsys::TimePoint<std::chrono::seconds> &ModTime,
233unsigned UID,unsigned GID,unsigned Perms,
234uint64_tSize) {
235printWithSpacePadding(Out,Twine(Name) +"/", 16);
236printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,Size);
237}
238
239staticvoid
240printBSDMemberHeader(raw_ostream &Out,uint64_t Pos,StringRefName,
241constsys::TimePoint<std::chrono::seconds> &ModTime,
242unsigned UID,unsigned GID,unsigned Perms,uint64_tSize) {
243uint64_t PosAfterHeader = Pos + 60 +Name.size();
244// Pad so that even 64 bit object files are aligned.
245unsigned Pad =offsetToAlignment(PosAfterHeader,Align(8));
246unsigned NameWithPadding =Name.size() + Pad;
247printWithSpacePadding(Out,Twine("#1/") +Twine(NameWithPadding), 16);
248printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
249 NameWithPadding +Size);
250 Out <<Name;
251while (Pad--)
252 Out.write(uint8_t(0));
253}
254
255staticvoid
256printBigArchiveMemberHeader(raw_ostream &Out,StringRefName,
257constsys::TimePoint<std::chrono::seconds> &ModTime,
258unsigned UID,unsigned GID,unsigned Perms,
259uint64_tSize,uint64_t PrevOffset,
260uint64_t NextOffset) {
261unsigned NameLen =Name.size();
262
263printWithSpacePadding(Out,Size, 20);// File member size
264printWithSpacePadding(Out, NextOffset, 20);// Next member header offset
265printWithSpacePadding(Out, PrevOffset, 20);// Previous member header offset
266printWithSpacePadding(Out,sys::toTimeT(ModTime), 12);// File member date
267// The big archive format has 12 chars for uid and gid.
268printWithSpacePadding(Out, UID % 1000000000000, 12);// UID
269printWithSpacePadding(Out, GID % 1000000000000, 12);// GID
270printWithSpacePadding(Out,format("%o", Perms), 12);// Permission
271printWithSpacePadding(Out, NameLen, 4);// Name length
272if (NameLen) {
273printWithSpacePadding(Out,Name, NameLen);// Name
274if (NameLen % 2)
275 Out.write(uint8_t(0));// Null byte padding
276 }
277 Out <<"`\n";// Terminator
278}
279
280staticbooluseStringTable(bool Thin,StringRefName) {
281return Thin ||Name.size() >= 16 ||Name.contains('/');
282}
283
284staticboolis64BitKind(object::Archive::KindKind) {
285switch (Kind) {
286caseobject::Archive::K_GNU:
287caseobject::Archive::K_BSD:
288caseobject::Archive::K_DARWIN:
289caseobject::Archive::K_COFF:
290returnfalse;
291caseobject::Archive::K_AIXBIG:
292caseobject::Archive::K_DARWIN64:
293caseobject::Archive::K_GNU64:
294returntrue;
295 }
296llvm_unreachable("not supported for writting");
297}
298
299staticvoid
300printMemberHeader(raw_ostream &Out,uint64_t Pos,raw_ostream &StringTable,
301StringMap<uint64_t> &MemberNames,object::Archive::KindKind,
302bool Thin,constNewArchiveMember &M,
303sys::TimePoint<std::chrono::seconds> ModTime,uint64_tSize) {
304if (isBSDLike(Kind))
305returnprintBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID,
306 M.Perms,Size);
307if (!useStringTable(Thin, M.MemberName))
308returnprintGNUSmallMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
309 M.Perms,Size);
310 Out <<'/';
311uint64_t NamePos;
312if (Thin) {
313 NamePos =StringTable.tell();
314StringTable << M.MemberName <<"/\n";
315 }else {
316auto Insertion = MemberNames.insert({M.MemberName,uint64_t(0)});
317if (Insertion.second) {
318 Insertion.first->second =StringTable.tell();
319StringTable << M.MemberName;
320if (isCOFFArchive(Kind))
321StringTable <<'\0';
322else
323StringTable <<"/\n";
324 }
325 NamePos = Insertion.first->second;
326 }
327printWithSpacePadding(Out, NamePos, 15);
328printRestOfMemberHeader(Out, ModTime, M.UID, M.GID, M.Perms,Size);
329}
330
331namespace{
332structMemberData {
333 std::vector<unsigned> Symbols;
334 std::string Header;
335StringRef Data;
336StringRefPadding;
337uint64_t PreHeadPadSize = 0;
338 std::unique_ptr<SymbolicFile> SymFile =nullptr;
339};
340}// namespace
341
342static MemberDatacomputeStringTable(StringRef Names) {
343unsignedSize = Names.size();
344unsigned Pad =offsetToAlignment(Size,Align(2));
345 std::string Header;
346raw_string_ostream Out(Header);
347printWithSpacePadding(Out,"//", 48);
348printWithSpacePadding(Out,Size + Pad, 10);
349 Out <<"`\n";
350 Out.flush();
351return {{}, std::move(Header), Names, Pad ?"\n" :""};
352}
353
354staticsys::TimePoint<std::chrono::seconds>now(bool Deterministic) {
355using namespacestd::chrono;
356
357if (!Deterministic)
358return time_point_cast<seconds>(system_clock::now());
359returnsys::TimePoint<seconds>();
360}
361
362staticboolisArchiveSymbol(constobject::BasicSymbolRef &S) {
363Expected<uint32_t> SymFlagsOrErr = S.getFlags();
364if (!SymFlagsOrErr)
365// TODO: Actually report errors helpfully.
366report_fatal_error(SymFlagsOrErr.takeError());
367if (*SymFlagsOrErr &object::SymbolRef::SF_FormatSpecific)
368returnfalse;
369if (!(*SymFlagsOrErr &object::SymbolRef::SF_Global))
370returnfalse;
371if (*SymFlagsOrErr &object::SymbolRef::SF_Undefined)
372returnfalse;
373returntrue;
374}
375
376staticvoidprintNBits(raw_ostream &Out,object::Archive::KindKind,
377uint64_t Val) {
378if (is64BitKind(Kind))
379 print<uint64_t>(Out,Kind, Val);
380else
381 print<uint32_t>(Out,Kind, Val);
382}
383
384staticuint64_tcomputeSymbolTableSize(object::Archive::KindKind,
385uint64_t NumSyms,uint64_t OffsetSize,
386uint64_t StringTableSize,
387uint32_t *Padding =nullptr) {
388assert((OffsetSize == 4 || OffsetSize == 8) &&"Unsupported OffsetSize");
389uint64_tSize = OffsetSize;// Number of entries
390if (isBSDLike(Kind))
391Size += NumSyms * OffsetSize * 2;// Table
392else
393Size += NumSyms * OffsetSize;// Table
394if (isBSDLike(Kind))
395Size += OffsetSize;// byte count
396Size += StringTableSize;
397// ld64 expects the members to be 8-byte aligned for 64-bit content and at
398// least 4-byte aligned for 32-bit content. Opt for the larger encoding
399// uniformly.
400// We do this for all bsd formats because it simplifies aligning members.
401// For the big archive format, the symbol table is the last member, so there
402// is no need to align.
403uint32_t Pad =isAIXBigArchive(Kind)
404 ? 0
405 :offsetToAlignment(Size,Align(isBSDLike(Kind) ? 8 : 2));
406
407Size += Pad;
408if (Padding)
409 *Padding = Pad;
410returnSize;
411}
412
413staticuint64_tcomputeSymbolMapSize(uint64_t NumObj,SymMap &SymMap,
414uint32_t *Padding =nullptr) {
415uint64_tSize =sizeof(uint32_t) * 2;// Number of symbols and objects entries
416Size += NumObj *sizeof(uint32_t);// Offset table
417
418for (auto S :SymMap.Map)
419Size +=sizeof(uint16_t) + S.first.length() + 1;
420
421uint32_t Pad =offsetToAlignment(Size,Align(2));
422Size += Pad;
423if (Padding)
424 *Padding = Pad;
425returnSize;
426}
427
428staticuint64_tcomputeECSymbolsSize(SymMap &SymMap,
429uint32_t *Padding =nullptr) {
430uint64_tSize =sizeof(uint32_t);// Number of symbols
431
432for (auto S :SymMap.ECMap)
433Size +=sizeof(uint16_t) + S.first.length() + 1;
434
435uint32_t Pad =offsetToAlignment(Size,Align(2));
436Size += Pad;
437if (Padding)
438 *Padding = Pad;
439returnSize;
440}
441
442staticvoidwriteSymbolTableHeader(raw_ostream &Out,object::Archive::KindKind,
443bool Deterministic,uint64_tSize,
444uint64_t PrevMemberOffset = 0,
445uint64_t NextMemberOffset = 0) {
446if (isBSDLike(Kind)) {
447constchar *Name =is64BitKind(Kind) ?"__.SYMDEF_64" :"__.SYMDEF";
448printBSDMemberHeader(Out, Out.tell(),Name,now(Deterministic), 0, 0, 0,
449Size);
450 }elseif (isAIXBigArchive(Kind)) {
451printBigArchiveMemberHeader(Out,"",now(Deterministic), 0, 0, 0,Size,
452 PrevMemberOffset, NextMemberOffset);
453 }else {
454constchar *Name =is64BitKind(Kind) ?"/SYM64" :"";
455printGNUSmallMemberHeader(Out,Name,now(Deterministic), 0, 0, 0,Size);
456 }
457}
458
459staticuint64_tcomputeHeadersSize(object::Archive::KindKind,
460uint64_t NumMembers,
461uint64_t StringMemberSize,uint64_t NumSyms,
462uint64_t SymNamesSize,SymMap *SymMap) {
463uint32_t OffsetSize =is64BitKind(Kind) ? 8 : 4;
464uint64_t SymtabSize =
465computeSymbolTableSize(Kind, NumSyms, OffsetSize, SymNamesSize);
466auto computeSymbolTableHeaderSize = [=] {
467SmallString<0> TmpBuf;
468raw_svector_ostream Tmp(TmpBuf);
469writeSymbolTableHeader(Tmp,Kind,true, SymtabSize);
470return TmpBuf.size();
471 };
472uint32_t HeaderSize = computeSymbolTableHeaderSize();
473uint64_tSize = strlen("!<arch>\n") + HeaderSize + SymtabSize;
474
475if (SymMap) {
476Size += HeaderSize +computeSymbolMapSize(NumMembers, *SymMap);
477if (SymMap->ECMap.size())
478Size += HeaderSize +computeECSymbolsSize(*SymMap);
479 }
480
481returnSize + StringMemberSize;
482}
483
484staticExpected<std::unique_ptr<SymbolicFile>>
485getSymbolicFile(MemoryBufferRef Buf,LLVMContext &Context,
486object::Archive::KindKind,function_ref<void(Error)> Warn) {
487constfile_magicType =identify_magic(Buf.getBuffer());
488// Don't attempt to read non-symbolic file types.
489if (!object::SymbolicFile::isSymbolicFile(Type, &Context))
490returnnullptr;
491if (Type ==file_magic::bitcode) {
492auto ObjOrErr =object::SymbolicFile::createSymbolicFile(
493 Buf,file_magic::bitcode, &Context);
494// An error reading a bitcode file most likely indicates that the file
495// was created by a compiler from the future. Normally we don't try to
496// implement forwards compatibility for bitcode files, but when creating an
497// archive we can implement best-effort forwards compatibility by treating
498// the file as a blob and not creating symbol index entries for it. lld and
499// mold ignore the archive symbol index, so provided that you use one of
500// these linkers, LTO will work as long as lld or the gold plugin is newer
501// than the compiler. We only ignore errors if the archive format is one
502// that is supported by a linker that is known to ignore the index,
503// otherwise there's no chance of this working so we may as well error out.
504// We print a warning on read failure so that users of linkers that rely on
505// the symbol index can diagnose the issue.
506//
507// This is the same behavior as GNU ar when the linker plugin returns an
508// error when reading the input file. If the bitcode file is actually
509// malformed, it will be diagnosed at link time.
510if (!ObjOrErr) {
511switch (Kind) {
512caseobject::Archive::K_BSD:
513caseobject::Archive::K_GNU:
514caseobject::Archive::K_GNU64:
515 Warn(ObjOrErr.takeError());
516returnnullptr;
517caseobject::Archive::K_AIXBIG:
518caseobject::Archive::K_COFF:
519caseobject::Archive::K_DARWIN:
520caseobject::Archive::K_DARWIN64:
521return ObjOrErr.takeError();
522 }
523 }
524return std::move(*ObjOrErr);
525 }else {
526auto ObjOrErr =object::SymbolicFile::createSymbolicFile(Buf);
527if (!ObjOrErr)
528return ObjOrErr.takeError();
529return std::move(*ObjOrErr);
530 }
531}
532
533staticboolis64BitSymbolicFile(constSymbolicFile *SymObj) {
534return SymObj !=nullptr ? SymObj->is64Bit() :false;
535}
536
537// Log2 of PAGESIZE(4096) on an AIX system.
538staticconstuint32_tLog2OfAIXPageSize = 12;
539
540// In the AIX big archive format, since the data content follows the member file
541// name, if the name ends on an odd byte, an extra byte will be added for
542// padding. This ensures that the data within the member file starts at an even
543// byte.
544staticconstuint32_tMinBigArchiveMemDataAlign = 2;
545
546template <typename AuxiliaryHeader>
547uint16_tgetAuxMaxAlignment(uint16_t AuxHeaderSize, AuxiliaryHeader *AuxHeader,
548uint16_t Log2OfMaxAlign) {
549// If the member doesn't have an auxiliary header, it isn't a loadable object
550// and so it just needs aligning at the minimum value.
551if (AuxHeader ==nullptr)
552returnMinBigArchiveMemDataAlign;
553
554// If the auxiliary header does not have both MaxAlignOfData and
555// MaxAlignOfText field, it is not a loadable shared object file, so align at
556// the minimum value. The 'ModuleType' member is located right after
557// 'MaxAlignOfData' in the AuxiliaryHeader.
558if (AuxHeaderSize <offsetof(AuxiliaryHeader, ModuleType))
559returnMinBigArchiveMemDataAlign;
560
561// If the XCOFF object file does not have a loader section, it is not
562// loadable, so align at the minimum value.
563if (AuxHeader->SecNumOfLoader == 0)
564returnMinBigArchiveMemDataAlign;
565
566// The content of the loadable member file needs to be aligned at MAX(maximum
567// alignment of .text, maximum alignment of .data) if there are both fields.
568// If the desired alignment is > PAGESIZE, 32-bit members are aligned on a
569// word boundary, while 64-bit members are aligned on a PAGESIZE(2^12=4096)
570// boundary.
571uint16_t Log2OfAlign =
572 std::max(AuxHeader->MaxAlignOfText, AuxHeader->MaxAlignOfData);
573return 1 << (Log2OfAlign >Log2OfAIXPageSize ? Log2OfMaxAlign : Log2OfAlign);
574}
575
576// AIX big archives may contain shared object members. The AIX OS requires these
577// members to be aligned if they are 64-bit and recommends it for 32-bit
578// members. This ensures that when these members are loaded they are aligned in
579// memory.
580staticuint32_tgetMemberAlignment(SymbolicFile *SymObj) {
581XCOFFObjectFile *XCOFFObj = dyn_cast_or_null<XCOFFObjectFile>(SymObj);
582if (!XCOFFObj)
583returnMinBigArchiveMemDataAlign;
584
585// If the desired alignment is > PAGESIZE, 32-bit members are aligned on a
586// word boundary, while 64-bit members are aligned on a PAGESIZE boundary.
587return XCOFFObj->is64Bit()
588 ?getAuxMaxAlignment(XCOFFObj->fileHeader64()->AuxHeaderSize,
589 XCOFFObj->auxiliaryHeader64(),
590Log2OfAIXPageSize)
591 :getAuxMaxAlignment(XCOFFObj->fileHeader32()->AuxHeaderSize,
592 XCOFFObj->auxiliaryHeader32(), 2);
593}
594
595staticvoidwriteSymbolTable(raw_ostream &Out,object::Archive::KindKind,
596bool Deterministic,ArrayRef<MemberData> Members,
597StringRefStringTable,uint64_t MembersOffset,
598unsigned NumSyms,uint64_t PrevMemberOffset = 0,
599uint64_t NextMemberOffset = 0,
600bool Is64Bit =false) {
601// We don't write a symbol table on an archive with no members -- except on
602// Darwin, where the linker will abort unless the archive has a symbol table.
603if (StringTable.empty() && !isDarwin(Kind) && !isCOFFArchive(Kind))
604return;
605
606uint64_t OffsetSize =is64BitKind(Kind) ? 8 : 4;
607uint32_t Pad;
608uint64_tSize =computeSymbolTableSize(Kind, NumSyms, OffsetSize,
609StringTable.size(), &Pad);
610writeSymbolTableHeader(Out,Kind, Deterministic,Size, PrevMemberOffset,
611 NextMemberOffset);
612
613if (isBSDLike(Kind))
614printNBits(Out,Kind, NumSyms * 2 * OffsetSize);
615else
616printNBits(Out,Kind, NumSyms);
617
618uint64_t Pos = MembersOffset;
619for (const MemberData &M : Members) {
620if (isAIXBigArchive(Kind)) {
621 Pos += M.PreHeadPadSize;
622if (is64BitSymbolicFile(M.SymFile.get()) != Is64Bit) {
623 Pos += M.Header.size() + M.Data.size() + M.Padding.size();
624continue;
625 }
626 }
627
628for (unsigned StringOffset : M.Symbols) {
629if (isBSDLike(Kind))
630printNBits(Out,Kind, StringOffset);
631printNBits(Out,Kind, Pos);// member offset
632 }
633 Pos += M.Header.size() + M.Data.size() + M.Padding.size();
634 }
635
636if (isBSDLike(Kind))
637// byte count of the string table
638printNBits(Out,Kind,StringTable.size());
639 Out <<StringTable;
640
641while (Pad--)
642 Out.write(uint8_t(0));
643}
644
645staticvoidwriteSymbolMap(raw_ostream &Out,object::Archive::KindKind,
646bool Deterministic,ArrayRef<MemberData> Members,
647SymMap &SymMap,uint64_t MembersOffset) {
648uint32_t Pad;
649uint64_tSize =computeSymbolMapSize(Members.size(),SymMap, &Pad);
650writeSymbolTableHeader(Out,Kind, Deterministic,Size, 0);
651
652uint32_t Pos = MembersOffset;
653
654 printLE<uint32_t>(Out, Members.size());
655for (const MemberData &M : Members) {
656printLE(Out, Pos);// member offset
657 Pos += M.Header.size() + M.Data.size() + M.Padding.size();
658 }
659
660 printLE<uint32_t>(Out,SymMap.Map.size());
661
662for (auto S :SymMap.Map)
663printLE(Out, S.second);
664for (auto S :SymMap.Map)
665 Out << S.first <<'\0';
666
667while (Pad--)
668 Out.write(uint8_t(0));
669}
670
671staticvoidwriteECSymbols(raw_ostream &Out,object::Archive::KindKind,
672bool Deterministic,ArrayRef<MemberData> Members,
673SymMap &SymMap) {
674uint32_t Pad;
675uint64_tSize =computeECSymbolsSize(SymMap, &Pad);
676printGNUSmallMemberHeader(Out,"/<ECSYMBOLS>",now(Deterministic), 0, 0, 0,
677Size);
678
679 printLE<uint32_t>(Out,SymMap.ECMap.size());
680
681for (auto S :SymMap.ECMap)
682printLE(Out, S.second);
683for (auto S :SymMap.ECMap)
684 Out << S.first <<'\0';
685while (Pad--)
686 Out.write(uint8_t(0));
687}
688
689staticboolisECObject(object::SymbolicFile &Obj) {
690if (Obj.isCOFF())
691return cast<llvm::object::COFFObjectFile>(&Obj)->getMachine() !=
692COFF::IMAGE_FILE_MACHINE_ARM64;
693
694if (Obj.isCOFFImportFile())
695return cast<llvm::object::COFFImportFile>(&Obj)->getMachine() !=
696COFF::IMAGE_FILE_MACHINE_ARM64;
697
698if (Obj.isIR()) {
699Expected<std::string> TripleStr =
700getBitcodeTargetTriple(Obj.getMemoryBufferRef());
701if (!TripleStr)
702returnfalse;
703TripleT(*TripleStr);
704returnT.isWindowsArm64EC() ||T.getArch() ==Triple::x86_64;
705 }
706
707returnfalse;
708}
709
710staticboolisAnyArm64COFF(object::SymbolicFile &Obj) {
711if (Obj.isCOFF())
712returnCOFF::isAnyArm64(cast<COFFObjectFile>(&Obj)->getMachine());
713
714if (Obj.isCOFFImportFile())
715returnCOFF::isAnyArm64(cast<COFFImportFile>(&Obj)->getMachine());
716
717if (Obj.isIR()) {
718Expected<std::string> TripleStr =
719getBitcodeTargetTriple(Obj.getMemoryBufferRef());
720if (!TripleStr)
721returnfalse;
722TripleT(*TripleStr);
723returnT.isOSWindows() &&T.getArch() ==Triple::aarch64;
724 }
725
726returnfalse;
727}
728
729boolisImportDescriptor(StringRefName) {
730returnName.starts_with(ImportDescriptorPrefix) ||
731Name ==StringRef{NullImportDescriptorSymbolName} ||
732 (Name.starts_with(NullThunkDataPrefix) &&
733Name.ends_with(NullThunkDataSuffix));
734}
735
736staticExpected<std::vector<unsigned>>getSymbols(SymbolicFile *Obj,
737uint16_t Index,
738raw_ostream &SymNames,
739SymMap *SymMap) {
740 std::vector<unsigned> Ret;
741
742if (Obj ==nullptr)
743return Ret;
744
745 std::map<std::string, uint16_t> *Map =nullptr;
746if (SymMap)
747 Map =SymMap->UseECMap &&isECObject(*Obj) ? &SymMap->ECMap : &SymMap->Map;
748
749for (constobject::BasicSymbolRef &S : Obj->symbols()) {
750if (!isArchiveSymbol(S))
751continue;
752if (Map) {
753 std::stringName;
754raw_string_ostream NameStream(Name);
755if (Error E = S.printName(NameStream))
756return std::move(E);
757if (!Map->try_emplace(Name, Index).second)
758continue;// ignore duplicated symbol
759if (Map == &SymMap->Map) {
760 Ret.push_back(SymNames.tell());
761 SymNames <<Name <<'\0';
762// If EC is enabled, then the import descriptors are NOT put into EC
763// objects so we need to copy them to the EC map manually.
764if (SymMap->UseECMap &&isImportDescriptor(Name))
765SymMap->ECMap[Name] = Index;
766 }
767 }else {
768 Ret.push_back(SymNames.tell());
769if (Error E = S.printName(SymNames))
770return std::move(E);
771 SymNames <<'\0';
772 }
773 }
774return Ret;
775}
776
777staticExpected<std::vector<MemberData>>
778computeMemberData(raw_ostream &StringTable,raw_ostream &SymNames,
779object::Archive::KindKind,bool Thin,bool Deterministic,
780SymtabWritingMode NeedSymbols,SymMap *SymMap,
781LLVMContext &Context,ArrayRef<NewArchiveMember> NewMembers,
782 std::optional<bool> IsEC,function_ref<void(Error)> Warn) {
783staticchar PaddingData[8] = {'\n','\n','\n','\n','\n','\n','\n','\n'};
784uint64_t MemHeadPadSize = 0;
785uint64_t Pos =
786isAIXBigArchive(Kind) ?sizeof(object::BigArchive::FixLenHdr) : 0;
787
788 std::vector<MemberData> Ret;
789bool HasObject =false;
790
791// Deduplicate long member names in the string table and reuse earlier name
792// offsets. This especially saves space for COFF Import libraries where all
793// members have the same name.
794StringMap<uint64_t> MemberNames;
795
796// UniqueTimestamps is a special case to improve debugging on Darwin:
797//
798// The Darwin linker does not link debug info into the final
799// binary. Instead, it emits entries of type N_OSO in the output
800// binary's symbol table, containing references to the linked-in
801// object files. Using that reference, the debugger can read the
802// debug data directly from the object files. Alternatively, an
803// invocation of 'dsymutil' will link the debug data from the object
804// files into a dSYM bundle, which can be loaded by the debugger,
805// instead of the object files.
806//
807// For an object file, the N_OSO entries contain the absolute path
808// path to the file, and the file's timestamp. For an object
809// included in an archive, the path is formatted like
810// "/absolute/path/to/archive.a(member.o)", and the timestamp is the
811// archive member's timestamp, rather than the archive's timestamp.
812//
813// However, this doesn't always uniquely identify an object within
814// an archive -- an archive file can have multiple entries with the
815// same filename. (This will happen commonly if the original object
816// files started in different directories.) The only way they get
817// distinguished, then, is via the timestamp. But this process is
818// unable to find the correct object file in the archive when there
819// are two files of the same name and timestamp.
820//
821// Additionally, timestamp==0 is treated specially, and causes the
822// timestamp to be ignored as a match criteria.
823//
824// That will "usually" work out okay when creating an archive not in
825// deterministic timestamp mode, because the objects will probably
826// have been created at different timestamps.
827//
828// To ameliorate this problem, in deterministic archive mode (which
829// is the default), on Darwin we will emit a unique non-zero
830// timestamp for each entry with a duplicated name. This is still
831// deterministic: the only thing affecting that timestamp is the
832// order of the files in the resultant archive.
833//
834// See also the functions that handle the lookup:
835// in lldb: ObjectContainerBSDArchive::Archive::FindObject()
836// in llvm/tools/dsymutil: BinaryHolder::GetArchiveMemberBuffers().
837bool UniqueTimestamps = Deterministic &&isDarwin(Kind);
838 std::map<StringRef, unsigned> FilenameCount;
839if (UniqueTimestamps) {
840for (constNewArchiveMember &M : NewMembers)
841 FilenameCount[M.MemberName]++;
842for (auto &Entry : FilenameCount)
843 Entry.second = Entry.second > 1 ? 1 : 0;
844 }
845
846 std::vector<std::unique_ptr<SymbolicFile>> SymFiles;
847
848if (NeedSymbols !=SymtabWritingMode::NoSymtab ||isAIXBigArchive(Kind)) {
849for (constNewArchiveMember &M : NewMembers) {
850Expected<std::unique_ptr<SymbolicFile>> SymFileOrErr =getSymbolicFile(
851 M.Buf->getMemBufferRef(), Context,Kind, [&](Error Err) {
852 Warn(createFileError(M.MemberName, std::move(Err)));
853 });
854if (!SymFileOrErr)
855returncreateFileError(M.MemberName, SymFileOrErr.takeError());
856 SymFiles.push_back(std::move(*SymFileOrErr));
857 }
858 }
859
860if (SymMap) {
861if (IsEC) {
862SymMap->UseECMap = *IsEC;
863 }else {
864// When IsEC is not specified by the caller, use it when we have both
865// any ARM64 object (ARM64 or ARM64EC) and any EC object (ARM64EC or
866// AMD64). This may be a single ARM64EC object, but may also be separate
867// ARM64 and AMD64 objects.
868bool HaveArm64 =false, HaveEC =false;
869for (std::unique_ptr<SymbolicFile> &SymFile : SymFiles) {
870if (!SymFile)
871continue;
872if (!HaveArm64)
873 HaveArm64 =isAnyArm64COFF(*SymFile);
874if (!HaveEC)
875 HaveEC =isECObject(*SymFile);
876if (HaveArm64 && HaveEC) {
877SymMap->UseECMap =true;
878break;
879 }
880 }
881 }
882 }
883
884// The big archive format needs to know the offset of the previous member
885// header.
886uint64_t PrevOffset = 0;
887uint64_t NextMemHeadPadSize = 0;
888
889for (uint32_t Index = 0; Index < NewMembers.size(); ++Index) {
890constNewArchiveMember *M = &NewMembers[Index];
891 std::string Header;
892raw_string_ostream Out(Header);
893
894MemoryBufferRef Buf = M->Buf->getMemBufferRef();
895StringRefData = Thin ?"" : Buf.getBuffer();
896
897// ld64 expects the members to be 8-byte aligned for 64-bit content and at
898// least 4-byte aligned for 32-bit content. Opt for the larger encoding
899// uniformly. This matches the behaviour with cctools and ensures that ld64
900// is happy with archives that we generate.
901unsigned MemberPadding =
902isDarwin(Kind) ?offsetToAlignment(Data.size(),Align(8)) : 0;
903unsigned TailPadding =
904offsetToAlignment(Data.size() + MemberPadding,Align(2));
905StringRef Padding =StringRef(PaddingData, MemberPadding + TailPadding);
906
907sys::TimePoint<std::chrono::seconds> ModTime;
908if (UniqueTimestamps)
909// Increment timestamp for each file of a given name.
910 ModTime =sys::toTimePoint(FilenameCount[M->MemberName]++);
911else
912 ModTime = M->ModTime;
913
914uint64_tSize = Buf.getBufferSize() + MemberPadding;
915if (Size >object::Archive::MaxMemberSize) {
916 std::string StringMsg =
917"File " + M->MemberName.str() +" exceeds size limit";
918return make_error<object::GenericBinaryError>(
919 std::move(StringMsg),object::object_error::parse_failed);
920 }
921
922 std::unique_ptr<SymbolicFile> CurSymFile;
923if (!SymFiles.empty())
924 CurSymFile = std::move(SymFiles[Index]);
925
926// In the big archive file format, we need to calculate and include the next
927// member offset and previous member offset in the file member header.
928if (isAIXBigArchive(Kind)) {
929uint64_t OffsetToMemData = Pos +sizeof(object::BigArMemHdrType) +
930alignTo(M->MemberName.size(), 2);
931
932if (M == NewMembers.begin())
933 NextMemHeadPadSize =
934alignToPowerOf2(OffsetToMemData,
935getMemberAlignment(CurSymFile.get())) -
936 OffsetToMemData;
937
938 MemHeadPadSize = NextMemHeadPadSize;
939 Pos += MemHeadPadSize;
940uint64_t NextOffset = Pos +sizeof(object::BigArMemHdrType) +
941alignTo(M->MemberName.size(), 2) +alignTo(Size, 2);
942
943// If there is another member file after this, we need to calculate the
944// padding before the header.
945if (Index + 1 != SymFiles.size()) {
946uint64_t OffsetToNextMemData =
947 NextOffset +sizeof(object::BigArMemHdrType) +
948alignTo(NewMembers[Index + 1].MemberName.size(), 2);
949 NextMemHeadPadSize =
950alignToPowerOf2(OffsetToNextMemData,
951getMemberAlignment(SymFiles[Index + 1].get())) -
952 OffsetToNextMemData;
953 NextOffset += NextMemHeadPadSize;
954 }
955printBigArchiveMemberHeader(Out, M->MemberName, ModTime, M->UID, M->GID,
956 M->Perms,Size, PrevOffset, NextOffset);
957 PrevOffset = Pos;
958 }else {
959printMemberHeader(Out, Pos,StringTable, MemberNames,Kind, Thin, *M,
960 ModTime,Size);
961 }
962 Out.flush();
963
964 std::vector<unsigned> Symbols;
965if (NeedSymbols !=SymtabWritingMode::NoSymtab) {
966Expected<std::vector<unsigned>> SymbolsOrErr =
967getSymbols(CurSymFile.get(), Index + 1, SymNames,SymMap);
968if (!SymbolsOrErr)
969returncreateFileError(M->MemberName, SymbolsOrErr.takeError());
970 Symbols = std::move(*SymbolsOrErr);
971if (CurSymFile)
972 HasObject =true;
973 }
974
975 Pos += Header.size() +Data.size() + Padding.size();
976 Ret.push_back({std::move(Symbols), std::move(Header),Data, Padding,
977 MemHeadPadSize, std::move(CurSymFile)});
978 }
979// If there are no symbols, emit an empty symbol table, to satisfy Solaris
980// tools, older versions of which expect a symbol table in a non-empty
981// archive, regardless of whether there are any symbols in it.
982if (HasObject && SymNames.tell() == 0 && !isCOFFArchive(Kind))
983 SymNames <<'\0' <<'\0' <<'\0';
984return std::move(Ret);
985}
986
987namespacellvm {
988
989staticErrorOr<SmallString<128>>canonicalizePath(StringRefP) {
990SmallString<128> Ret =P;
991 std::error_code Err =sys::fs::make_absolute(Ret);
992if (Err)
993return Err;
994sys::path::remove_dots(Ret,/*removedotdot*/true);
995return Ret;
996}
997
998// Compute the relative path from From to To.
999Expected<std::string>computeArchiveRelativePath(StringRefFrom,StringRef To) {
1000ErrorOr<SmallString<128>> PathToOrErr =canonicalizePath(To);
1001ErrorOr<SmallString<128>> DirFromOrErr =canonicalizePath(From);
1002if (!PathToOrErr || !DirFromOrErr)
1003returnerrorCodeToError(errnoAsErrorCode());
1004
1005constSmallString<128> &PathTo = *PathToOrErr;
1006constSmallString<128> &DirFrom =sys::path::parent_path(*DirFromOrErr);
1007
1008// Can't construct a relative path between different roots
1009if (sys::path::root_name(PathTo) !=sys::path::root_name(DirFrom))
1010returnsys::path::convert_to_slash(PathTo);
1011
1012// Skip common prefixes
1013auto FromTo =
1014 std::mismatch(sys::path::begin(DirFrom),sys::path::end(DirFrom),
1015sys::path::begin(PathTo));
1016auto FromI = FromTo.first;
1017auto ToI = FromTo.second;
1018
1019// Construct relative path
1020SmallString<128> Relative;
1021for (auto FromE =sys::path::end(DirFrom); FromI != FromE; ++FromI)
1022sys::path::append(Relative,sys::path::Style::posix,"..");
1023
1024for (auto ToE =sys::path::end(PathTo); ToI != ToE; ++ToI)
1025sys::path::append(Relative,sys::path::Style::posix, *ToI);
1026
1027return std::string(Relative);
1028}
1029
1030ErrorwriteArchiveToStream(raw_ostream &Out,
1031ArrayRef<NewArchiveMember> NewMembers,
1032SymtabWritingMode WriteSymtab,
1033object::Archive::KindKind,bool Deterministic,
1034bool Thin, std::optional<bool> IsEC,
1035function_ref<void(Error)> Warn) {
1036assert((!Thin || !isBSDLike(Kind)) &&"Only the gnu format has a thin mode");
1037
1038SmallString<0> SymNamesBuf;
1039raw_svector_ostream SymNames(SymNamesBuf);
1040SmallString<0> StringTableBuf;
1041raw_svector_ostreamStringTable(StringTableBuf);
1042SymMapSymMap;
1043bool ShouldWriteSymtab = WriteSymtab !=SymtabWritingMode::NoSymtab;
1044
1045// COFF symbol map uses 16-bit indexes, so we can't use it if there are too
1046// many members. COFF format also requires symbol table presence, so use
1047// GNU format when NoSymtab is requested.
1048if (isCOFFArchive(Kind) && (NewMembers.size() > 0xfffe || !ShouldWriteSymtab))
1049Kind =object::Archive::K_GNU;
1050
1051// In the scenario when LLVMContext is populated SymbolicFile will contain a
1052// reference to it, thus SymbolicFile should be destroyed first.
1053LLVMContext Context;
1054
1055Expected<std::vector<MemberData>> DataOrErr =computeMemberData(
1056StringTable, SymNames,Kind, Thin, Deterministic, WriteSymtab,
1057isCOFFArchive(Kind) ? &SymMap :nullptr, Context, NewMembers, IsEC, Warn);
1058if (Error E = DataOrErr.takeError())
1059return E;
1060 std::vector<MemberData> &Data = *DataOrErr;
1061
1062uint64_t StringTableSize = 0;
1063 MemberData StringTableMember;
1064if (!StringTableBuf.empty() && !isAIXBigArchive(Kind)) {
1065 StringTableMember =computeStringTable(StringTableBuf);
1066 StringTableSize = StringTableMember.Header.size() +
1067 StringTableMember.Data.size() +
1068 StringTableMember.Padding.size();
1069 }
1070
1071// We would like to detect if we need to switch to a 64-bit symbol table.
1072uint64_t LastMemberEndOffset = 0;
1073uint64_t LastMemberHeaderOffset = 0;
1074uint64_t NumSyms = 0;
1075uint64_t NumSyms32 = 0;// Store symbol number of 32-bit member files.
1076
1077for (constauto &M :Data) {
1078// Record the start of the member's offset
1079 LastMemberEndOffset += M.PreHeadPadSize;
1080 LastMemberHeaderOffset = LastMemberEndOffset;
1081// Account for the size of each part associated with the member.
1082 LastMemberEndOffset += M.Header.size() + M.Data.size() + M.Padding.size();
1083 NumSyms += M.Symbols.size();
1084
1085// AIX big archive files may contain two global symbol tables. The
1086// first global symbol table locates 32-bit file members that define global
1087// symbols; the second global symbol table does the same for 64-bit file
1088// members. As a big archive can have both 32-bit and 64-bit file members,
1089// we need to know the number of symbols in each symbol table individually.
1090if (isAIXBigArchive(Kind) && ShouldWriteSymtab) {
1091if (!is64BitSymbolicFile(M.SymFile.get()))
1092 NumSyms32 += M.Symbols.size();
1093 }
1094 }
1095
1096 std::optional<uint64_t> HeadersSize;
1097
1098// The symbol table is put at the end of the big archive file. The symbol
1099// table is at the start of the archive file for other archive formats.
1100if (ShouldWriteSymtab && !is64BitKind(Kind)) {
1101// We assume 32-bit offsets to see if 32-bit symbols are possible or not.
1102 HeadersSize =computeHeadersSize(Kind,Data.size(), StringTableSize,
1103 NumSyms, SymNamesBuf.size(),
1104isCOFFArchive(Kind) ? &SymMap :nullptr);
1105
1106// The SYM64 format is used when an archive's member offsets are larger than
1107// 32-bits can hold. The need for this shift in format is detected by
1108// writeArchive. To test this we need to generate a file with a member that
1109// has an offset larger than 32-bits but this demands a very slow test. To
1110// speed the test up we use this environment variable to pretend like the
1111// cutoff happens before 32-bits and instead happens at some much smaller
1112// value.
1113uint64_t Sym64Threshold = 1ULL << 32;
1114constchar *Sym64Env = std::getenv("SYM64_THRESHOLD");
1115if (Sym64Env)
1116StringRef(Sym64Env).getAsInteger(10, Sym64Threshold);
1117
1118// If LastMemberHeaderOffset isn't going to fit in a 32-bit varible we need
1119// to switch to 64-bit. Note that the file can be larger than 4GB as long as
1120// the last member starts before the 4GB offset.
1121if (*HeadersSize + LastMemberHeaderOffset >= Sym64Threshold) {
1122if (Kind ==object::Archive::K_DARWIN)
1123Kind =object::Archive::K_DARWIN64;
1124else
1125Kind =object::Archive::K_GNU64;
1126 HeadersSize.reset();
1127 }
1128 }
1129
1130if (Thin)
1131 Out <<"!<thin>\n";
1132elseif (isAIXBigArchive(Kind))
1133 Out <<"<bigaf>\n";
1134else
1135 Out <<"!<arch>\n";
1136
1137if (!isAIXBigArchive(Kind)) {
1138if (ShouldWriteSymtab) {
1139if (!HeadersSize)
1140 HeadersSize =computeHeadersSize(
1141Kind,Data.size(), StringTableSize, NumSyms, SymNamesBuf.size(),
1142isCOFFArchive(Kind) ? &SymMap :nullptr);
1143writeSymbolTable(Out,Kind, Deterministic,Data, SymNamesBuf,
1144 *HeadersSize, NumSyms);
1145
1146if (isCOFFArchive(Kind))
1147writeSymbolMap(Out,Kind, Deterministic,Data,SymMap, *HeadersSize);
1148 }
1149
1150if (StringTableSize)
1151 Out << StringTableMember.Header << StringTableMember.Data
1152 << StringTableMember.Padding;
1153
1154if (ShouldWriteSymtab &&SymMap.ECMap.size())
1155writeECSymbols(Out,Kind, Deterministic,Data,SymMap);
1156
1157for (const MemberData &M :Data)
1158 Out << M.Header << M.Data << M.Padding;
1159 }else {
1160 HeadersSize =sizeof(object::BigArchive::FixLenHdr);
1161 LastMemberEndOffset += *HeadersSize;
1162 LastMemberHeaderOffset += *HeadersSize;
1163
1164// For the big archive (AIX) format, compute a table of member names and
1165// offsets, used in the member table.
1166uint64_t MemberTableNameStrTblSize = 0;
1167 std::vector<size_t> MemberOffsets;
1168 std::vector<StringRef> MemberNames;
1169// Loop across object to find offset and names.
1170uint64_t MemberEndOffset =sizeof(object::BigArchive::FixLenHdr);
1171for (size_tI = 0,Size = NewMembers.size();I !=Size; ++I) {
1172constNewArchiveMember &Member = NewMembers[I];
1173 MemberTableNameStrTblSize += Member.MemberName.size() + 1;
1174 MemberEndOffset +=Data[I].PreHeadPadSize;
1175 MemberOffsets.push_back(MemberEndOffset);
1176 MemberNames.push_back(Member.MemberName);
1177// File member name ended with "`\n". The length is included in
1178// BigArMemHdrType.
1179 MemberEndOffset +=sizeof(object::BigArMemHdrType) +
1180alignTo(Data[I].Data.size(), 2) +
1181alignTo(Member.MemberName.size(), 2);
1182 }
1183
1184// AIX member table size.
1185uint64_t MemberTableSize = 20 +// Number of members field
1186 20 * MemberOffsets.size() +
1187 MemberTableNameStrTblSize;
1188
1189SmallString<0> SymNamesBuf32;
1190SmallString<0> SymNamesBuf64;
1191raw_svector_ostream SymNames32(SymNamesBuf32);
1192raw_svector_ostream SymNames64(SymNamesBuf64);
1193
1194if (ShouldWriteSymtab && NumSyms)
1195// Generate the symbol names for the members.
1196for (constauto &M :Data) {
1197Expected<std::vector<unsigned>> SymbolsOrErr =getSymbols(
1198 M.SymFile.get(), 0,
1199is64BitSymbolicFile(M.SymFile.get()) ? SymNames64 : SymNames32,
1200nullptr);
1201if (!SymbolsOrErr)
1202return SymbolsOrErr.takeError();
1203 }
1204
1205uint64_t MemberTableEndOffset =
1206 LastMemberEndOffset +
1207alignTo(sizeof(object::BigArMemHdrType) + MemberTableSize, 2);
1208
1209// In AIX OS, The 'GlobSymOffset' field in the fixed-length header contains
1210// the offset to the 32-bit global symbol table, and the 'GlobSym64Offset'
1211// contains the offset to the 64-bit global symbol table.
1212uint64_t GlobalSymbolOffset =
1213 (ShouldWriteSymtab &&
1214 (WriteSymtab !=SymtabWritingMode::BigArchive64) && NumSyms32 > 0)
1215 ? MemberTableEndOffset
1216 : 0;
1217
1218uint64_t GlobalSymbolOffset64 = 0;
1219uint64_t NumSyms64 = NumSyms - NumSyms32;
1220if (ShouldWriteSymtab && (WriteSymtab !=SymtabWritingMode::BigArchive32) &&
1221 NumSyms64 > 0) {
1222if (GlobalSymbolOffset == 0)
1223 GlobalSymbolOffset64 = MemberTableEndOffset;
1224else
1225// If there is a global symbol table for 32-bit members,
1226// the 64-bit global symbol table is after the 32-bit one.
1227 GlobalSymbolOffset64 =
1228 GlobalSymbolOffset +sizeof(object::BigArMemHdrType) +
1229 (NumSyms32 + 1) * 8 +alignTo(SymNamesBuf32.size(), 2);
1230 }
1231
1232// Fixed Sized Header.
1233printWithSpacePadding(Out, NewMembers.size() ? LastMemberEndOffset : 0,
1234 20);// Offset to member table
1235// If there are no file members in the archive, there will be no global
1236// symbol table.
1237printWithSpacePadding(Out, GlobalSymbolOffset, 20);
1238printWithSpacePadding(Out, GlobalSymbolOffset64, 20);
1239printWithSpacePadding(Out,
1240 NewMembers.size()
1241 ?sizeof(object::BigArchive::FixLenHdr) +
1242Data[0].PreHeadPadSize
1243 : 0,
1244 20);// Offset to first archive member
1245printWithSpacePadding(Out, NewMembers.size() ? LastMemberHeaderOffset : 0,
1246 20);// Offset to last archive member
1247printWithSpacePadding(
1248 Out, 0,
1249 20);// Offset to first member of free list - Not supported yet
1250
1251for (const MemberData &M :Data) {
1252 Out << std::string(M.PreHeadPadSize,'\0');
1253 Out << M.Header << M.Data;
1254if (M.Data.size() % 2)
1255 Out <<'\0';
1256 }
1257
1258if (NewMembers.size()) {
1259// Member table.
1260printBigArchiveMemberHeader(Out,"",sys::toTimePoint(0), 0, 0, 0,
1261 MemberTableSize, LastMemberHeaderOffset,
1262 GlobalSymbolOffset ? GlobalSymbolOffset
1263 : GlobalSymbolOffset64);
1264printWithSpacePadding(Out, MemberOffsets.size(), 20);// Number of members
1265for (uint64_t MemberOffset : MemberOffsets)
1266printWithSpacePadding(Out, MemberOffset,
1267 20);// Offset to member file header.
1268for (StringRef MemberName : MemberNames)
1269 Out << MemberName <<'\0';// Member file name, null byte padding.
1270
1271if (MemberTableNameStrTblSize % 2)
1272 Out <<'\0';// Name table must be tail padded to an even number of
1273// bytes.
1274
1275if (ShouldWriteSymtab) {
1276// Write global symbol table for 32-bit file members.
1277if (GlobalSymbolOffset) {
1278writeSymbolTable(Out,Kind, Deterministic,Data, SymNamesBuf32,
1279 *HeadersSize, NumSyms32, LastMemberEndOffset,
1280 GlobalSymbolOffset64);
1281// Add padding between the symbol tables, if needed.
1282if (GlobalSymbolOffset64 && (SymNamesBuf32.size() % 2))
1283 Out <<'\0';
1284 }
1285
1286// Write global symbol table for 64-bit file members.
1287if (GlobalSymbolOffset64)
1288writeSymbolTable(Out,Kind, Deterministic,Data, SymNamesBuf64,
1289 *HeadersSize, NumSyms64,
1290 GlobalSymbolOffset ? GlobalSymbolOffset
1291 : LastMemberEndOffset,
1292 0,true);
1293 }
1294 }
1295 }
1296 Out.flush();
1297returnError::success();
1298}
1299
1300voidwarnToStderr(Error Err) {
1301llvm::logAllUnhandledErrors(std::move(Err),llvm::errs(),"warning: ");
1302}
1303
1304ErrorwriteArchive(StringRef ArcName,ArrayRef<NewArchiveMember> NewMembers,
1305SymtabWritingMode WriteSymtab,object::Archive::KindKind,
1306bool Deterministic,bool Thin,
1307 std::unique_ptr<MemoryBuffer> OldArchiveBuf,
1308 std::optional<bool> IsEC,function_ref<void(Error)> Warn) {
1309Expected<sys::fs::TempFile> Temp =
1310sys::fs::TempFile::create(ArcName +".temp-archive-%%%%%%%.a");
1311if (!Temp)
1312return Temp.takeError();
1313raw_fd_ostream Out(Temp->FD,false);
1314
1315if (Error E =writeArchiveToStream(Out, NewMembers, WriteSymtab,Kind,
1316 Deterministic, Thin, IsEC, Warn)) {
1317if (Error DiscardError = Temp->discard())
1318returnjoinErrors(std::move(E), std::move(DiscardError));
1319return E;
1320 }
1321
1322// At this point, we no longer need whatever backing memory
1323// was used to generate the NewMembers. On Windows, this buffer
1324// could be a mapped view of the file we want to replace (if
1325// we're updating an existing archive, say). In that case, the
1326// rename would still succeed, but it would leave behind a
1327// temporary file (actually the original file renamed) because
1328// a file cannot be deleted while there's a handle open on it,
1329// only renamed. So by freeing this buffer, this ensures that
1330// the last open handle on the destination file, if any, is
1331// closed before we attempt to rename.
1332 OldArchiveBuf.reset();
1333
1334return Temp->keep(ArcName);
1335}
1336
1337Expected<std::unique_ptr<MemoryBuffer>>
1338writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers,
1339SymtabWritingMode WriteSymtab,object::Archive::KindKind,
1340bool Deterministic,bool Thin,
1341function_ref<void(Error)> Warn) {
1342SmallVector<char, 0> ArchiveBufferVector;
1343raw_svector_ostream ArchiveStream(ArchiveBufferVector);
1344
1345if (Error E =
1346writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab,Kind,
1347 Deterministic, Thin, std::nullopt, Warn))
1348return std::move(E);
1349
1350return std::make_unique<SmallVectorMemoryBuffer>(
1351 std::move(ArchiveBufferVector),/*RequiresNullTerminator=*/false);
1352}
1353
1354}// namespace llvm
StringMap.h
This file defines the StringMap class.
offsetof
#define offsetof(TYPE, MEMBER)
Definition:AMDHSAKernelDescriptor.h:30
Alignment.h
printNBits
static void printNBits(raw_ostream &Out, object::Archive::Kind Kind, uint64_t Val)
Definition:ArchiveWriter.cpp:376
isImportDescriptor
bool isImportDescriptor(StringRef Name)
Definition:ArchiveWriter.cpp:729
now
static sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
Definition:ArchiveWriter.cpp:354
isDarwin
static bool isDarwin(object::Archive::Kind Kind)
Definition:ArchiveWriter.cpp:176
computeECSymbolsSize
static uint64_t computeECSymbolsSize(SymMap &SymMap, uint32_t *Padding=nullptr)
Definition:ArchiveWriter.cpp:428
getSymbols
static Expected< std::vector< unsigned > > getSymbols(SymbolicFile *Obj, uint16_t Index, raw_ostream &SymNames, SymMap *SymMap)
Definition:ArchiveWriter.cpp:736
is64BitSymbolicFile
static bool is64BitSymbolicFile(const SymbolicFile *SymObj)
Definition:ArchiveWriter.cpp:533
computeHeadersSize
static uint64_t computeHeadersSize(object::Archive::Kind Kind, uint64_t NumMembers, uint64_t StringMemberSize, uint64_t NumSyms, uint64_t SymNamesSize, SymMap *SymMap)
Definition:ArchiveWriter.cpp:459
isBSDLike
static bool isBSDLike(object::Archive::Kind Kind)
Definition:ArchiveWriter.cpp:189
printBSDMemberHeader
static void printBSDMemberHeader(raw_ostream &Out, uint64_t Pos, StringRef Name, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, uint64_t Size)
Definition:ArchiveWriter.cpp:240
writeSymbolTable
static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef< MemberData > Members, StringRef StringTable, uint64_t MembersOffset, unsigned NumSyms, uint64_t PrevMemberOffset=0, uint64_t NextMemberOffset=0, bool Is64Bit=false)
Definition:ArchiveWriter.cpp:595
MinBigArchiveMemDataAlign
static const uint32_t MinBigArchiveMemDataAlign
Definition:ArchiveWriter.cpp:544
writeSymbolMap
static void writeSymbolMap(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef< MemberData > Members, SymMap &SymMap, uint64_t MembersOffset)
Definition:ArchiveWriter.cpp:645
computeStringTable
static MemberData computeStringTable(StringRef Names)
Definition:ArchiveWriter.cpp:342
getAuxMaxAlignment
uint16_t getAuxMaxAlignment(uint16_t AuxHeaderSize, AuxiliaryHeader *AuxHeader, uint16_t Log2OfMaxAlign)
Definition:ArchiveWriter.cpp:547
Log2OfAIXPageSize
static const uint32_t Log2OfAIXPageSize
Definition:ArchiveWriter.cpp:538
isECObject
static bool isECObject(object::SymbolicFile &Obj)
Definition:ArchiveWriter.cpp:689
getSymbolicFile
static Expected< std::unique_ptr< SymbolicFile > > getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context, object::Archive::Kind Kind, function_ref< void(Error)> Warn)
Definition:ArchiveWriter.cpp:485
isAIXBigArchive
static bool isAIXBigArchive(object::Archive::Kind Kind)
Definition:ArchiveWriter.cpp:181
writeSymbolTableHeader
static void writeSymbolTableHeader(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, uint64_t Size, uint64_t PrevMemberOffset=0, uint64_t NextMemberOffset=0)
Definition:ArchiveWriter.cpp:442
printRestOfMemberHeader
static void printRestOfMemberHeader(raw_ostream &Out, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, uint64_t Size)
Definition:ArchiveWriter.cpp:215
computeSymbolTableSize
static uint64_t computeSymbolTableSize(object::Archive::Kind Kind, uint64_t NumSyms, uint64_t OffsetSize, uint64_t StringTableSize, uint32_t *Padding=nullptr)
Definition:ArchiveWriter.cpp:384
isArchiveSymbol
static bool isArchiveSymbol(const object::BasicSymbolRef &S)
Definition:ArchiveWriter.cpp:362
isCOFFArchive
static bool isCOFFArchive(object::Archive::Kind Kind)
Definition:ArchiveWriter.cpp:185
computeMemberData
static Expected< std::vector< MemberData > > computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, object::Archive::Kind Kind, bool Thin, bool Deterministic, SymtabWritingMode NeedSymbols, SymMap *SymMap, LLVMContext &Context, ArrayRef< NewArchiveMember > NewMembers, std::optional< bool > IsEC, function_ref< void(Error)> Warn)
Definition:ArchiveWriter.cpp:778
printMemberHeader
static void printMemberHeader(raw_ostream &Out, uint64_t Pos, raw_ostream &StringTable, StringMap< uint64_t > &MemberNames, object::Archive::Kind Kind, bool Thin, const NewArchiveMember &M, sys::TimePoint< std::chrono::seconds > ModTime, uint64_t Size)
Definition:ArchiveWriter.cpp:300
writeECSymbols
static void writeECSymbols(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef< MemberData > Members, SymMap &SymMap)
Definition:ArchiveWriter.cpp:671
computeSymbolMapSize
static uint64_t computeSymbolMapSize(uint64_t NumObj, SymMap &SymMap, uint32_t *Padding=nullptr)
Definition:ArchiveWriter.cpp:413
printLE
static void printLE(raw_ostream &Out, T Val)
Definition:ArchiveWriter.cpp:211
printGNUSmallMemberHeader
static void printGNUSmallMemberHeader(raw_ostream &Out, StringRef Name, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, uint64_t Size)
Definition:ArchiveWriter.cpp:231
useStringTable
static bool useStringTable(bool Thin, StringRef Name)
Definition:ArchiveWriter.cpp:280
is64BitKind
static bool is64BitKind(object::Archive::Kind Kind)
Definition:ArchiveWriter.cpp:284
getMemberAlignment
static uint32_t getMemberAlignment(SymbolicFile *SymObj)
Definition:ArchiveWriter.cpp:580
printBigArchiveMemberHeader
static void printBigArchiveMemberHeader(raw_ostream &Out, StringRef Name, const sys::TimePoint< std::chrono::seconds > &ModTime, unsigned UID, unsigned GID, unsigned Perms, uint64_t Size, uint64_t PrevOffset, uint64_t NextOffset)
Definition:ArchiveWriter.cpp:256
printWithSpacePadding
static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size)
Definition:ArchiveWriter.cpp:168
isAnyArm64COFF
static bool isAnyArm64COFF(object::SymbolicFile &Obj)
Definition:ArchiveWriter.cpp:710
ArchiveWriter.h
ArrayRef.h
From
BlockVerifier::State From
Definition:BlockVerifier.cpp:57
COFFImportFile.h
Name
std::string Name
Definition:ELFObjHandler.cpp:77
Size
uint64_t Size
Definition:ELFObjHandler.cpp:81
EndianStream.h
Errc.h
Format.h
IRObjectFile.h
LLVMContext.h
I
#define I(x, y, z)
Definition:MD5.cpp:58
Magic.h
MathExtras.h
ObjectFile.h
COFF.h
MachO.h
P
#define P(N)
Path.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
OS
raw_pwrite_stream & OS
Definition:SampleProfWriter.cpp:51
SmallVectorMemoryBuffer.h
StringRef.h
SymbolicFile.h
XCOFFObjectFile.h
T
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition:ArrayRef.h:41
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition:ArrayRef.h:168
llvm::ArrayRef::begin
iterator begin() const
Definition:ArrayRef.h:156
llvm::ErrorOr
Represents either an error or a value T.
Definition:ErrorOr.h:56
llvm::ErrorOr::getError
std::error_code getError() const
Definition:ErrorOr.h:152
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition:Error.h:160
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition:Error.h:337
llvm::Expected
Tagged union holding either a T or a Error.
Definition:Error.h:481
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition:Error.h:608
llvm::Expected::get
reference get()
Returns a reference to the stored T value.
Definition:Error.h:578
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition:LLVMContext.h:67
llvm::MemoryBufferRef
Definition:MemoryBufferRef.h:22
llvm::MemoryBufferRef::getBufferSize
size_t getBufferSize() const
Definition:MemoryBufferRef.h:37
llvm::MemoryBufferRef::getBuffer
StringRef getBuffer() const
Definition:MemoryBufferRef.h:32
llvm::MemoryBuffer
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition:MemoryBuffer.h:51
llvm::MemoryBuffer::getOpenFile
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
Definition:MemoryBuffer.cpp:550
llvm::MemoryBuffer::getMemBuffer
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
Definition:MemoryBuffer.cpp:129
llvm::SmallString
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition:SmallString.h:26
llvm::SmallVectorBase::empty
bool empty() const
Definition:SmallVector.h:81
llvm::SmallVectorBase::size
size_t size() const
Definition:SmallVector.h:78
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition:SmallVector.h:1196
llvm::StringMap
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition:StringMap.h:128
llvm::StringMap::insert
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition:StringMap.h:308
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition:StringRef.h:51
llvm::StringRef::getAsInteger
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition:StringRef.h:470
llvm::StringRef::size
constexpr size_t size() const
size - Get the string size.
Definition:StringRef.h:150
llvm::StringTable
A table of densely packed, null-terminated strings indexed by offset.
Definition:StringTable.h:33
llvm::StringTable::size
constexpr size_t size() const
Returns the byte size of the table.
Definition:StringTable.h:97
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition:Triple.h:44
llvm::Triple::x86_64
@ x86_64
Definition:Triple.h:86
llvm::Triple::aarch64
@ aarch64
Definition:Triple.h:51
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition:Twine.h:81
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition:Type.h:45
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition:STLFunctionalExtras.h:37
llvm::object::Archive::Child
Definition:Archive.h:160
llvm::object::Archive::Child::getGID
Expected< unsigned > getGID() const
Definition:Archive.h:236
llvm::object::Archive::Child::getMemoryBufferRef
Expected< MemoryBufferRef > getMemoryBufferRef() const
Definition:Archive.cpp:645
llvm::object::Archive::Child::getUID
Expected< unsigned > getUID() const
Definition:Archive.h:235
llvm::object::Archive::Child::getAccessMode
Expected< sys::fs::perms > getAccessMode() const
Definition:Archive.h:238
llvm::object::Archive::Child::getLastModified
Expected< sys::TimePoint< std::chrono::seconds > > getLastModified() const
Definition:Archive.h:227
llvm::object::Archive::getDefaultKind
static object::Archive::Kind getDefaultKind()
Definition:Archive.cpp:981
llvm::object::Archive::getDefaultKindForTriple
static object::Archive::Kind getDefaultKindForTriple(const Triple &T)
Definition:Archive.cpp:971
llvm::object::Archive::Kind
Kind
Definition:Archive.h:337
llvm::object::Archive::K_AIXBIG
@ K_AIXBIG
Definition:Archive.h:337
llvm::object::Archive::K_DARWIN
@ K_DARWIN
Definition:Archive.h:337
llvm::object::Archive::K_GNU
@ K_GNU
Definition:Archive.h:337
llvm::object::Archive::K_BSD
@ K_BSD
Definition:Archive.h:337
llvm::object::Archive::K_COFF
@ K_COFF
Definition:Archive.h:337
llvm::object::Archive::K_DARWIN64
@ K_DARWIN64
Definition:Archive.h:337
llvm::object::Archive::K_GNU64
@ K_GNU64
Definition:Archive.h:337
llvm::object::Archive::MaxMemberSize
static const uint64_t MaxMemberSize
Size field is 10 decimal digits long.
Definition:Archive.h:335
llvm::object::BasicSymbolRef
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition:SymbolicFile.h:103
llvm::object::BasicSymbolRef::getFlags
Expected< uint32_t > getFlags() const
Get symbol flags (bitwise OR of SymbolRef::Flags)
Definition:SymbolicFile.h:206
llvm::object::BasicSymbolRef::SF_Global
@ SF_Global
Definition:SymbolicFile.h:111
llvm::object::BasicSymbolRef::SF_FormatSpecific
@ SF_FormatSpecific
Definition:SymbolicFile.h:117
llvm::object::BasicSymbolRef::SF_Undefined
@ SF_Undefined
Definition:SymbolicFile.h:110
llvm::object::Binary::isIR
bool isIR() const
Definition:Binary.h:145
llvm::object::Binary::isCOFFImportFile
bool isCOFFImportFile() const
Definition:Binary.h:141
llvm::object::Binary::getMemoryBufferRef
MemoryBufferRef getMemoryBufferRef() const
Definition:Binary.cpp:43
llvm::object::Binary::isCOFF
bool isCOFF() const
Definition:Binary.h:131
llvm::object::ObjectFile::createObjectFile
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition:ObjectFile.cpp:209
llvm::object::SymbolicFile
Definition:SymbolicFile.h:145
llvm::object::SymbolicFile::createSymbolicFile
static Expected< std::unique_ptr< SymbolicFile > > createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type, LLVMContext *Context, bool InitContent=true)
Definition:SymbolicFile.cpp:37
llvm::object::SymbolicFile::is64Bit
virtual bool is64Bit() const =0
llvm::object::SymbolicFile::symbols
basic_symbol_iterator_range symbols() const
Definition:SymbolicFile.h:165
llvm::object::SymbolicFile::isSymbolicFile
static bool isSymbolicFile(file_magic Type, const LLVMContext *Context)
Definition:SymbolicFile.cpp:98
llvm::object::XCOFFObjectFile
Definition:XCOFFObjectFile.h:532
llvm::object::XCOFFObjectFile::auxiliaryHeader32
const XCOFFAuxiliaryHeader32 * auxiliaryHeader32() const
Definition:XCOFFObjectFile.cpp:190
llvm::object::XCOFFObjectFile::fileHeader64
const XCOFFFileHeader64 * fileHeader64() const
Definition:XCOFFObjectFile.cpp:185
llvm::object::XCOFFObjectFile::fileHeader32
const XCOFFFileHeader32 * fileHeader32() const
Definition:XCOFFObjectFile.cpp:180
llvm::object::XCOFFObjectFile::auxiliaryHeader64
const XCOFFAuxiliaryHeader64 * auxiliaryHeader64() const
Definition:XCOFFObjectFile.cpp:195
llvm::object::XCOFFObjectFile::is64Bit
bool is64Bit() const override
Definition:XCOFFObjectFile.cpp:773
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition:raw_ostream.h:460
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition:raw_ostream.h:52
llvm::raw_ostream::tell
uint64_t tell() const
tell - Return the current offset with the file.
Definition:raw_ostream.h:147
llvm::raw_ostream::flush
void flush()
Definition:raw_ostream.h:198
llvm::raw_ostream::write
raw_ostream & write(unsigned char C)
Definition:raw_ostream.cpp:225
llvm::raw_ostream::indent
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
Definition:raw_ostream.cpp:495
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition:raw_ostream.h:661
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition:raw_ostream.h:691
llvm::sys::fs::TempFile::create
static Expected< TempFile > create(const Twine &Model, unsigned Mode=all_read|all_write, OpenFlags ExtraFlags=OF_None)
This creates a temporary file with createUniqueFile and schedules it for deletion with sys::RemoveFil...
Definition:Path.cpp:1325
llvm::sys::fs::file_status
Represents the result of a call to sys::fs::status().
Definition:FileSystem.h:221
uint16_t
uint32_t
uint64_t
uint8_t
Archive.h
Error.h
ErrorHandling.h
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition:ErrorHandling.h:143
false
Definition:StackSlotColoring.cpp:193
llvm::COFF::IMAGE_FILE_MACHINE_ARM64
@ IMAGE_FILE_MACHINE_ARM64
Definition:COFF.h:100
llvm::COFF::isAnyArm64
bool isAnyArm64(T Machine)
Definition:COFF.h:129
llvm::object
Definition:DWARFDebugLoc.h:24
llvm::object::NullImportDescriptorSymbolName
constexpr std::string_view NullImportDescriptorSymbolName
Definition:COFFImportFile.h:31
llvm::object::Kind
Kind
Definition:COFFModuleDefinition.cpp:31
llvm::object::object_error::parse_failed
@ parse_failed
llvm::object::NullThunkDataPrefix
constexpr std::string_view NullThunkDataPrefix
Definition:COFFImportFile.h:33
llvm::object::NullThunkDataSuffix
constexpr std::string_view NullThunkDataSuffix
Definition:COFFImportFile.h:34
llvm::object::ImportDescriptorPrefix
constexpr std::string_view ImportDescriptorPrefix
Definition:COFFImportFile.h:30
llvm::pdb::PDB_ColorItem::Padding
@ Padding
llvm::support::endian::write
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition:Endian.h:92
llvm::sys::fs::make_absolute
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition:Path.cpp:906
llvm::sys::fs::kInvalidFile
const file_t kInvalidFile
llvm::sys::fs::file_t
int file_t
Definition:FileSystem.h:55
llvm::sys::fs::closeFile
std::error_code closeFile(file_t &F)
Close the file object.
llvm::sys::fs::status
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
llvm::sys::fs::file_type::directory_file
@ directory_file
llvm::sys::fs::openNativeFileForRead
Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
llvm::sys::path::begin
const_iterator begin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get begin iterator over path.
Definition:Path.cpp:226
llvm::sys::path::remove_dots
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
Definition:Path.cpp:715
llvm::sys::path::parent_path
StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
Definition:Path.cpp:467
llvm::sys::path::Style::posix
@ posix
llvm::sys::path::convert_to_slash
std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
Definition:Path.cpp:568
llvm::sys::path::root_name
StringRef root_name(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get root name.
Definition:Path.cpp:373
llvm::sys::path::append
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition:Path.cpp:456
llvm::sys::path::end
const_iterator end(StringRef path LLVM_LIFETIME_BOUND)
Get end iterator over path.
Definition:Path.cpp:235
llvm::sys::TimePoint
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition:Chrono.h:34
llvm::sys::toTimePoint
TimePoint< std::chrono::seconds > toTimePoint(std::time_t T)
Convert a std::time_t to a TimePoint.
Definition:Chrono.h:65
llvm::sys::toTimeT
std::time_t toTimeT(TimePoint<> TP)
Convert a TimePoint to std::time_t.
Definition:Chrono.h:50
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::identify_magic
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition:Magic.cpp:33
llvm::logAllUnhandledErrors
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition:Error.cpp:65
llvm::writeArchiveToBuffer
Expected< std::unique_ptr< MemoryBuffer > > writeArchiveToBuffer(ArrayRef< NewArchiveMember > NewMembers, SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, function_ref< void(Error)> Warn=warnToStderr)
Definition:ArchiveWriter.cpp:1338
llvm::createFileError
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition:Error.h:1385
llvm::writeArchive
Error writeArchive(StringRef ArcName, ArrayRef< NewArchiveMember > NewMembers, SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr< MemoryBuffer > OldArchiveBuf=nullptr, std::optional< bool > IsEC=std::nullopt, function_ref< void(Error)> Warn=warnToStderr)
Definition:ArchiveWriter.cpp:1304
llvm::make_error_code
std::error_code make_error_code(BitcodeError E)
Definition:BitcodeReader.h:310
llvm::getBitcodeTargetTriple
Expected< std::string > getBitcodeTargetTriple(MemoryBufferRef Buffer)
Read the header of the specified bitcode buffer and extract just the triple information.
Definition:BitcodeReader.cpp:8730
llvm::print
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
Definition:GCNRegPressure.cpp:227
llvm::errc::is_a_directory
@ is_a_directory
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition:Error.h:438
llvm::get
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
Definition:PointerIntPair.h:270
llvm::alignToPowerOf2
constexpr T alignToPowerOf2(U Value, V Align)
Will overflow only if result is not representable in T.
Definition:MathExtras.h:503
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition:Error.cpp:167
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition:Format.h:125
llvm::offsetToAlignment
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
Definition:Alignment.h:197
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition:raw_ostream.cpp:907
llvm::warnToStderr
void warnToStderr(Error Err)
Definition:ArchiveWriter.cpp:1300
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition:Alignment.h:155
llvm::computeArchiveRelativePath
Expected< std::string > computeArchiveRelativePath(StringRef From, StringRef To)
Definition:ArchiveWriter.cpp:999
llvm::errorCodeToError
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition:Error.cpp:111
llvm::canonicalizePath
static ErrorOr< SmallString< 128 > > canonicalizePath(StringRef P)
Definition:ArchiveWriter.cpp:989
llvm::errnoAsErrorCode
std::error_code errnoAsErrorCode()
Helper to get errno as an std::error_code.
Definition:Error.h:1226
llvm::endianness::little
@ little
llvm::endianness::big
@ big
llvm::Data
@ Data
Definition:SIMachineScheduler.h:55
llvm::writeArchiveToStream
Error writeArchiveToStream(raw_ostream &Out, ArrayRef< NewArchiveMember > NewMembers, SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::optional< bool > IsEC=std::nullopt, function_ref< void(Error)> Warn=warnToStderr)
Definition:ArchiveWriter.cpp:1030
llvm::SymtabWritingMode
SymtabWritingMode
Definition:ArchiveWriter.h:43
llvm::SymtabWritingMode::BigArchive64
@ BigArchive64
llvm::SymtabWritingMode::BigArchive32
@ BigArchive32
llvm::SymtabWritingMode::NoSymtab
@ NoSymtab
llvm::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition:Error.h:1069
raw_ostream.h
Status
Definition:SIModeRegister.cpp:29
SymMap
Definition:ArchiveWriter.cpp:50
SymMap::ECMap
std::map< std::string, uint16_t > ECMap
Definition:ArchiveWriter.cpp:53
SymMap::UseECMap
bool UseECMap
Definition:ArchiveWriter.cpp:51
SymMap::Map
std::map< std::string, uint16_t > Map
Definition:ArchiveWriter.cpp:52
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition:Alignment.h:39
llvm::NewArchiveMember
Definition:ArchiveWriter.h:20
llvm::NewArchiveMember::detectKindFromObject
object::Archive::Kind detectKindFromObject() const
Definition:ArchiveWriter.cpp:60
llvm::NewArchiveMember::NewArchiveMember
NewArchiveMember()=default
llvm::NewArchiveMember::getFile
static Expected< NewArchiveMember > getFile(StringRef FileName, bool Deterministic)
Definition:ArchiveWriter.cpp:128
llvm::NewArchiveMember::getOldMember
static Expected< NewArchiveMember > getOldMember(const object::Archive::Child &OldMember, bool Deterministic)
Definition:ArchiveWriter.cpp:98
llvm::NewArchiveMember::Buf
std::unique_ptr< MemoryBuffer > Buf
Definition:ArchiveWriter.h:21
llvm::file_magic
file_magic - An "enum class" enumeration of file types based on magic (the first N bytes of the file)...
Definition:Magic.h:20
llvm::file_magic::bitcode
@ bitcode
Bitcode file.
Definition:Magic.h:23
llvm::object::BigArMemHdrType
Definition:Archive.h:120
llvm::object::BigArchive::FixLenHdr
Fixed-Length Header.
Definition:Archive.h:400
llvm::object::XCOFFFileHeader32::AuxHeaderSize
support::ubig16_t AuxHeaderSize
Definition:XCOFFObjectFile.h:40
llvm::object::XCOFFFileHeader64::AuxHeaderSize
support::ubig16_t AuxHeaderSize
Definition:XCOFFObjectFile.h:53

Generated on Thu Jul 17 2025 12:34:20 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp