LLVM 22.0.0git
Archive.h
Go to the documentation of this file.
1//===- Archive.h - ar archive file format -----------------------*- 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 declares the ar archive file format class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_OBJECT_ARCHIVE_H
14#define LLVM_OBJECT_ARCHIVE_H
15
16#include "llvm/ADT/StringRef.h"
19#include "llvm/Object/Binary.h"
20#include "llvm/Support/Chrono.h"
22#include "llvm/Support/Error.h"
25#include <cassert>
26#include <cstdint>
27#include <memory>
28#include <string>
29#include <vector>
30
31namespace llvm {
32namespace object {
33
34const char ArchiveMagic[] = "!<arch>\n";
35const char ThinArchiveMagic[] = "!<thin>\n";
36const char BigArchiveMagic[] = "<bigaf>\n";
37
38class Archive;
39
41protected:
43
44public:
45 friend class Archive;
46 virtual std::unique_ptr<AbstractArchiveMemberHeader> clone() const = 0;
47 virtual ~AbstractArchiveMemberHeader() = default;
48
49 /// Get the name without looking up long names.
50 virtual Expected<StringRef> getRawName() const = 0;
51 virtual StringRef getRawAccessMode() const = 0;
52 virtual StringRef getRawLastModified() const = 0;
53 virtual StringRef getRawUID() const = 0;
54 virtual StringRef getRawGID() const = 0;
55
56 /// Get the name looking up long names.
58 virtual Expected<uint64_t> getSize() const = 0;
59 virtual uint64_t getOffset() const = 0;
60
61 /// Get next file member location.
63 virtual Expected<bool> isThin() const = 0;
64
67 getLastModified() const;
70
71 /// Returns the size in bytes of the format-defined member header of the
72 /// concrete archive type.
73 virtual uint64_t getSizeOf() const = 0;
74
76};
77
78template <typename T>
80public:
81 CommonArchiveMemberHeader(const Archive *Parent, const T *RawHeaderPtr)
82 : AbstractArchiveMemberHeader(Parent), ArMemHdr(RawHeaderPtr){};
83 StringRef getRawAccessMode() const override;
84 StringRef getRawLastModified() const override;
85 StringRef getRawUID() const override;
86 StringRef getRawGID() const override;
87
88 uint64_t getOffset() const override;
89 uint64_t getSizeOf() const override { return sizeof(T); }
90
91 T const *ArMemHdr;
92};
93
95 char Name[16];
96 char LastModified[12];
97 char UID[6];
98 char GID[6];
99 char AccessMode[8];
100 char Size[10]; ///< Size of data, not including header or padding.
101 char Terminator[2];
102};
103
105 : public CommonArchiveMemberHeader<UnixArMemHdrType> {
106public:
107 ArchiveMemberHeader(const Archive *Parent, const char *RawHeaderPtr,
108 uint64_t Size, Error *Err);
109
110 std::unique_ptr<AbstractArchiveMemberHeader> clone() const override {
111 return std::make_unique<ArchiveMemberHeader>(*this);
112 }
113
114 Expected<StringRef> getRawName() const override;
115
117 Expected<uint64_t> getSize() const override;
118 Expected<const char *> getNextChildLoc() const override;
119 Expected<bool> isThin() const override;
120};
121
122// File Member Header
124 char Size[20]; // File member size in decimal
125 char NextOffset[20]; // Next member offset in decimal
126 char PrevOffset[20]; // Previous member offset in decimal
127 char LastModified[12];
128 char UID[12];
129 char GID[12];
130 char AccessMode[12];
131 char NameLen[4]; // File member name length in decimal
132 union {
133 char Name[2]; // Start of member name
134 char Terminator[2];
135 };
136};
137
138// Define file member header of AIX big archive.
140 : public CommonArchiveMemberHeader<BigArMemHdrType> {
141
142public:
143 BigArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr,
144 uint64_t Size, Error *Err);
145 std::unique_ptr<AbstractArchiveMemberHeader> clone() const override {
146 return std::make_unique<BigArchiveMemberHeader>(*this);
147 }
148
149 Expected<StringRef> getRawName() const override;
150 Expected<uint64_t> getRawNameSize() const;
151
153 Expected<uint64_t> getSize() const override;
154 Expected<const char *> getNextChildLoc() const override;
155 Expected<uint64_t> getNextOffset() const;
156 Expected<bool> isThin() const override { return false; }
157};
158
159class LLVM_ABI Archive : public Binary {
160 virtual void anchor();
161
162public:
163 class Child {
164 friend Archive;
166
167 const Archive *Parent;
168 std::unique_ptr<AbstractArchiveMemberHeader> Header;
169 /// Includes header but not padding byte.
170 StringRef Data;
171 /// Offset from Data to the start of the file.
172 uint16_t StartOfFile;
173
174 Expected<bool> isThinMember() const;
175
176 public:
177 LLVM_ABI Child(const Archive *Parent, const char *Start, Error *Err);
178 LLVM_ABI Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile);
179
180 Child(const Child &C)
181 : Parent(C.Parent), Data(C.Data), StartOfFile(C.StartOfFile) {
182 if (C.Header)
183 Header = C.Header->clone();
184 }
185
187 Parent = std::move(C.Parent);
188 Header = std::move(C.Header);
189 Data = C.Data;
190 StartOfFile = C.StartOfFile;
191 }
192
193 Child &operator=(Child &&C) noexcept {
194 if (&C == this)
195 return *this;
196
197 Parent = std::move(C.Parent);
198 Header = std::move(C.Header);
199 Data = C.Data;
200 StartOfFile = C.StartOfFile;
201
202 return *this;
203 }
204
206 if (&C == this)
207 return *this;
208
209 Parent = C.Parent;
210 if (C.Header)
211 Header = C.Header->clone();
212 Data = C.Data;
213 StartOfFile = C.StartOfFile;
214
215 return *this;
216 }
217
218 bool operator==(const Child &other) const {
219 assert(!Parent || !other.Parent || Parent == other.Parent);
220 return Data.begin() == other.Data.begin();
221 }
222
223 const Archive *getParent() const { return Parent; }
224 LLVM_ABI Expected<Child> getNext() const;
225
227 LLVM_ABI Expected<std::string> getFullName() const;
228 Expected<StringRef> getRawName() const { return Header->getRawName(); }
229
231 return Header->getLastModified();
232 }
233
235 return Header->getRawLastModified();
236 }
237
238 Expected<unsigned> getUID() const { return Header->getUID(); }
239 Expected<unsigned> getGID() const { return Header->getGID(); }
240
242 return Header->getAccessMode();
243 }
244
245 /// \return the size of the archive member without the header or padding.
247 /// \return the size in the archive header for this member.
248 LLVM_ABI Expected<uint64_t> getRawSize() const;
249
250 LLVM_ABI Expected<StringRef> getBuffer() const;
251 LLVM_ABI uint64_t getChildOffset() const;
252 uint64_t getDataOffset() const { return getChildOffset() + StartOfFile; }
253
254 LLVM_ABI Expected<MemoryBufferRef> getMemoryBufferRef() const;
255
257 getAsBinary(LLVMContext *Context = nullptr) const;
258 };
259
261 Child C;
262
263 public:
264 ChildFallibleIterator() : C(Child(nullptr, nullptr, nullptr)) {}
266
267 const Child *operator->() const { return &C; }
268 const Child &operator*() const { return C; }
269
270 bool operator==(const ChildFallibleIterator &other) const {
271 // Ignore errors here: If an error occurred during increment then getNext
272 // will have been set to child_end(), and the following comparison should
273 // do the right thing.
274 return C == other.C;
275 }
276
277 bool operator!=(const ChildFallibleIterator &other) const {
278 return !(*this == other);
279 }
280
282 auto NextChild = C.getNext();
283 if (!NextChild)
284 return NextChild.takeError();
285 C = std::move(*NextChild);
286 return Error::success();
287 }
288 };
289
291
292 class Symbol {
293 const Archive *Parent;
294 uint32_t SymbolIndex;
295 uint32_t StringIndex; // Extra index to the string.
296
297 public:
298 Symbol(const Archive *p, uint32_t symi, uint32_t stri)
299 : Parent(p), SymbolIndex(symi), StringIndex(stri) {}
300
301 bool operator==(const Symbol &other) const {
302 return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
303 }
304
305 LLVM_ABI StringRef getName() const;
306 LLVM_ABI Expected<Child> getMember() const;
307 LLVM_ABI Symbol getNext() const;
308 LLVM_ABI bool isECSymbol() const;
309 };
310
312 Symbol symbol;
313
314 public:
315 symbol_iterator(const Symbol &s) : symbol(s) {}
316
317 const Symbol *operator->() const { return &symbol; }
318 const Symbol &operator*() const { return symbol; }
319
320 bool operator==(const symbol_iterator &other) const {
321 return symbol == other.symbol;
322 }
323
324 bool operator!=(const symbol_iterator &other) const {
325 return !(*this == other);
326 }
327
328 symbol_iterator &operator++() { // Preincrement
329 symbol = symbol.getNext();
330 return *this;
331 }
332 };
333
334 Archive(MemoryBufferRef Source, Error &Err);
336
337 // Explicitly non-copyable.
338 Archive(Archive const &) = delete;
339 Archive &operator=(Archive const &) = delete;
340
341 /// Size field is 10 decimal digits long
342 static const uint64_t MaxMemberSize = 9999999999;
343
344 enum Kind { K_GNU, K_GNU64, K_BSD, K_DARWIN, K_DARWIN64, K_COFF, K_AIXBIG };
345
346 Kind kind() const { return (Kind)Format; }
347 bool isThin() const { return IsThin; }
348 static object::Archive::Kind getDefaultKind();
349 static object::Archive::Kind getDefaultKindForTriple(const Triple &T);
350
351 child_iterator child_begin(Error &Err, bool SkipInternal = true) const;
352 child_iterator child_end() const;
354 bool SkipInternal = true) const {
355 return make_range(child_begin(Err, SkipInternal), child_end());
356 }
357
358 symbol_iterator symbol_begin() const;
359 symbol_iterator symbol_end() const;
361 return make_range(symbol_begin(), symbol_end());
362 }
363
365
366 static bool classof(Binary const *v) { return v->isArchive(); }
367
368 // check if a symbol is in the archive
370
371 virtual bool isEmpty() const;
372 bool hasSymbolTable() const;
373 StringRef getSymbolTable() const { return SymbolTable; }
375 uint32_t getNumberOfSymbols() const;
376 uint32_t getNumberOfECSymbols() const;
377 virtual uint64_t getFirstChildOffset() const { return getArchiveMagicLen(); }
378
379 std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() {
380 return std::move(ThinBuffers);
381 }
382
383 std::unique_ptr<AbstractArchiveMemberHeader>
384 createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size,
385 Error *Err) const;
386
387protected:
388 uint64_t getArchiveMagicLen() const;
389 void setFirstRegular(const Child &C);
390
394
395private:
396 StringRef FirstRegularData;
397 uint16_t FirstRegularStartOfFile = -1;
398
399 unsigned Format : 3;
400 unsigned IsThin : 1;
401 mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
402};
403
404class BigArchive : public Archive {
405public:
406 /// Fixed-Length Header.
407 struct FixLenHdr {
408 char Magic[sizeof(BigArchiveMagic) - 1]; ///< Big archive magic string.
409 char MemOffset[20]; ///< Offset to member table.
410 char GlobSymOffset[20]; ///< Offset to global symbol table.
411 char
412 GlobSym64Offset[20]; ///< Offset global symbol table for 64-bit objects.
413 char FirstChildOffset[20]; ///< Offset to first archive member.
414 char LastChildOffset[20]; ///< Offset to last archive member.
415 char FreeOffset[20]; ///< Offset to first mem on free list.
416 };
417
424
425public:
427 uint64_t getFirstChildOffset() const override { return FirstChildOffset; }
429 bool isEmpty() const override { return getFirstChildOffset() == 0; }
430
433};
434
435} // end namespace object
436} // end namespace llvm
437
438#endif // LLVM_OBJECT_ARCHIVE_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_ABI
Definition: Compiler.h:213
uint64_t Size
#define T
static StringRef getName(Value *V)
static std::optional< int32_t > getOffset(ArrayRef< int32_t > Offsets, size_t Idx)
static const char * name
Definition: SMEABIPass.cpp:52
static unsigned getSize(unsigned Kind)
Lightweight error class with error context and mandatory checking.
Definition: Error.h:159
Tagged union holding either a T or a Error.
Definition: Error.h:485
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
iterator begin() const
Definition: StringRef.h:120
A table of densely packed, null-terminated strings indexed by offset.
Definition: StringTable.h:33
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:47
A wrapper class for fallible iterators.
A range adaptor for a pair of iterators.
virtual StringRef getRawGID() const =0
virtual StringRef getRawUID() const =0
LLVM_ABI Expected< unsigned > getUID() const
Definition: Archive.cpp:403
virtual Expected< uint64_t > getSize() const =0
LLVM_ABI Expected< sys::fs::perms > getAccessMode() const
Definition: Archive.cpp:384
AbstractArchiveMemberHeader(const Archive *Parent)
Definition: Archive.h:42
LLVM_ABI Expected< unsigned > getGID() const
Definition: Archive.cpp:410
virtual uint64_t getOffset() const =0
virtual Expected< const char * > getNextChildLoc() const =0
Get next file member location.
virtual Expected< StringRef > getRawName() const =0
Get the name without looking up long names.
virtual Expected< bool > isThin() const =0
LLVM_ABI Expected< sys::TimePoint< std::chrono::seconds > > getLastModified() const
Definition: Archive.cpp:393
virtual uint64_t getSizeOf() const =0
Returns the size in bytes of the format-defined member header of the concrete archive type.
virtual StringRef getRawAccessMode() const =0
virtual std::unique_ptr< AbstractArchiveMemberHeader > clone() const =0
virtual StringRef getRawLastModified() const =0
virtual Expected< StringRef > getName(uint64_t Size) const =0
Get the name looking up long names.
std::unique_ptr< AbstractArchiveMemberHeader > clone() const override
Definition: Archive.h:110
bool operator==(const ChildFallibleIterator &other) const
Definition: Archive.h:270
bool operator!=(const ChildFallibleIterator &other) const
Definition: Archive.h:277
StringRef getRawLastModified() const
Definition: Archive.h:234
bool operator==(const Child &other) const
Definition: Archive.h:218
Child & operator=(const Child &C)
Definition: Archive.h:205
Expected< unsigned > getGID() const
Definition: Archive.h:239
uint64_t getDataOffset() const
Definition: Archive.h:252
Expected< StringRef > getRawName() const
Definition: Archive.h:228
Expected< unsigned > getUID() const
Definition: Archive.h:238
Child & operator=(Child &&C) noexcept
Definition: Archive.h:193
Expected< sys::fs::perms > getAccessMode() const
Definition: Archive.h:241
Expected< sys::TimePoint< std::chrono::seconds > > getLastModified() const
Definition: Archive.h:230
const Archive * getParent() const
Definition: Archive.h:223
Child(const Child &C)
Definition: Archive.h:180
LLVM_ABI Symbol getNext() const
Definition: Archive.cpp:1090
Symbol(const Archive *p, uint32_t symi, uint32_t stri)
Definition: Archive.h:298
bool operator==(const Symbol &other) const
Definition: Archive.h:301
symbol_iterator & operator++()
Definition: Archive.h:328
const Symbol & operator*() const
Definition: Archive.h:318
bool operator!=(const symbol_iterator &other) const
Definition: Archive.h:324
const Symbol * operator->() const
Definition: Archive.h:317
bool operator==(const symbol_iterator &other) const
Definition: Archive.h:320
iterator_range< symbol_iterator > symbols() const
Definition: Archive.h:360
virtual uint64_t getFirstChildOffset() const
Definition: Archive.h:377
bool isThin() const
Definition: Archive.h:347
Archive & operator=(Archive const &)=delete
StringRef getStringTable() const
Definition: Archive.h:374
StringRef getSymbolTable() const
Definition: Archive.h:373
StringRef ECSymbolTable
Definition: Archive.h:392
iterator_range< child_iterator > children(Error &Err, bool SkipInternal=true) const
Definition: Archive.h:353
Archive(Archive const &)=delete
static bool classof(Binary const *v)
Definition: Archive.h:366
StringRef StringTable
Definition: Archive.h:393
Kind kind() const
Definition: Archive.h:346
StringRef SymbolTable
Definition: Archive.h:391
std::vector< std::unique_ptr< MemoryBuffer > > takeThinBuffers()
Definition: Archive.h:379
Expected< bool > isThin() const override
Definition: Archive.h:156
std::unique_ptr< AbstractArchiveMemberHeader > clone() const override
Definition: Archive.h:145
bool isEmpty() const override
Definition: Archive.h:429
uint64_t getLastChildOffset() const
Definition: Archive.h:428
std::string MergedGlobalSymtabBuf
Definition: Archive.h:421
const FixLenHdr * ArFixLenHdr
Definition: Archive.h:418
uint64_t FirstChildOffset
Definition: Archive.h:419
uint64_t LastChildOffset
Definition: Archive.h:420
uint64_t getFirstChildOffset() const override
Definition: Archive.h:427
CommonArchiveMemberHeader(const Archive *Parent, const T *RawHeaderPtr)
Definition: Archive.h:81
uint64_t getSizeOf() const override
Returns the size in bytes of the format-defined member header of the concrete archive type.
Definition: Archive.h:89
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
const char ArchiveMagic[]
Definition: Archive.h:34
const char ThinArchiveMagic[]
Definition: Archive.h:35
const char BigArchiveMagic[]
Definition: Archive.h:36
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Fixed-Length Header.
Definition: Archive.h:407
char Magic[sizeof(BigArchiveMagic) - 1]
Big archive magic string.
Definition: Archive.h:408
char FirstChildOffset[20]
Offset to first archive member.
Definition: Archive.h:413
char LastChildOffset[20]
Offset to last archive member.
Definition: Archive.h:414
char FreeOffset[20]
Offset to first mem on free list.
Definition: Archive.h:415
char GlobSym64Offset[20]
Offset global symbol table for 64-bit objects.
Definition: Archive.h:412
char MemOffset[20]
Offset to member table.
Definition: Archive.h:409
char GlobSymOffset[20]
Offset to global symbol table.
Definition: Archive.h:410
char Size[10]
Size of data, not including header or padding.
Definition: Archive.h:100