1 | //===- Archive.cpp - ar File Format implementation ------------------------===// |
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 ArchiveObjectFile class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/Object/Archive.h" |
14 | #include "llvm/ADT/SmallString.h" |
15 | #include "llvm/ADT/StringRef.h" |
16 | #include "llvm/ADT/Twine.h" |
17 | #include "llvm/Object/Binary.h" |
18 | #include "llvm/Object/Error.h" |
19 | #include "llvm/Support/Chrono.h" |
20 | #include "llvm/Support/Endian.h" |
21 | #include "llvm/Support/EndianStream.h" |
22 | #include "llvm/Support/Error.h" |
23 | #include "llvm/Support/ErrorOr.h" |
24 | #include "llvm/Support/FileSystem.h" |
25 | #include "llvm/Support/MathExtras.h" |
26 | #include "llvm/Support/MemoryBuffer.h" |
27 | #include "llvm/Support/Path.h" |
28 | #include "llvm/Support/raw_ostream.h" |
29 | #include "llvm/TargetParser/Host.h" |
30 | #include <algorithm> |
31 | #include <cassert> |
32 | #include <cstddef> |
33 | #include <cstdint> |
34 | #include <memory> |
35 | #include <string> |
36 | #include <system_error> |
37 | |
38 | using namespace llvm; |
39 | using namespace object; |
40 | using namespace llvm::support::endian; |
41 | |
42 | void Archive::anchor() {} |
43 | |
44 | static Error malformedError(Twine Msg) { |
45 | std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")" ; |
46 | return make_error<GenericBinaryError>(Args: std::move(StringMsg), |
47 | Args: object_error::parse_failed); |
48 | } |
49 | |
50 | static Error |
51 | (const AbstractArchiveMemberHeader *, |
52 | const char *, uint64_t Size) { |
53 | StringRef Msg("remaining size of archive too small for next archive " |
54 | "member header " ); |
55 | |
56 | Expected<StringRef> NameOrErr = ArMemHeader->getName(Size); |
57 | if (NameOrErr) |
58 | return malformedError(Msg: Msg + "for " + *NameOrErr); |
59 | |
60 | consumeError(Err: NameOrErr.takeError()); |
61 | uint64_t Offset = RawHeaderPtr - ArMemHeader->Parent->getData().data(); |
62 | return malformedError(Msg: Msg + "at offset " + Twine(Offset)); |
63 | } |
64 | |
65 | template <class T, std::size_t N> |
66 | StringRef getFieldRawString(const T (&Field)[N]) { |
67 | return StringRef(Field, N).rtrim(Chars: " " ); |
68 | } |
69 | |
70 | template <class T> |
71 | StringRef CommonArchiveMemberHeader<T>::() const { |
72 | return getFieldRawString(ArMemHdr->AccessMode); |
73 | } |
74 | |
75 | template <class T> |
76 | StringRef CommonArchiveMemberHeader<T>::() const { |
77 | return getFieldRawString(ArMemHdr->LastModified); |
78 | } |
79 | |
80 | template <class T> StringRef CommonArchiveMemberHeader<T>::() const { |
81 | return getFieldRawString(ArMemHdr->UID); |
82 | } |
83 | |
84 | template <class T> StringRef CommonArchiveMemberHeader<T>::() const { |
85 | return getFieldRawString(ArMemHdr->GID); |
86 | } |
87 | |
88 | template <class T> uint64_t CommonArchiveMemberHeader<T>::() const { |
89 | return reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); |
90 | } |
91 | |
92 | template class object::<UnixArMemHdrType>; |
93 | template class object::<BigArMemHdrType>; |
94 | |
95 | ArchiveMemberHeader::(const Archive *Parent, |
96 | const char *, |
97 | uint64_t Size, Error *Err) |
98 | : CommonArchiveMemberHeader<UnixArMemHdrType>( |
99 | Parent, reinterpret_cast<const UnixArMemHdrType *>(RawHeaderPtr)) { |
100 | if (RawHeaderPtr == nullptr) |
101 | return; |
102 | ErrorAsOutParameter ErrAsOutParam(Err); |
103 | |
104 | if (Size < getSizeOf()) { |
105 | *Err = createMemberHeaderParseError(ArMemHeader: this, RawHeaderPtr, Size); |
106 | return; |
107 | } |
108 | if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') { |
109 | if (Err) { |
110 | std::string Buf; |
111 | raw_string_ostream OS(Buf); |
112 | OS.write_escaped( |
113 | Str: StringRef(ArMemHdr->Terminator, sizeof(ArMemHdr->Terminator))); |
114 | OS.flush(); |
115 | std::string Msg("terminator characters in archive member \"" + Buf + |
116 | "\" not the correct \"`\\n\" values for the archive " |
117 | "member header " ); |
118 | Expected<StringRef> NameOrErr = getName(Size); |
119 | if (!NameOrErr) { |
120 | consumeError(Err: NameOrErr.takeError()); |
121 | uint64_t Offset = RawHeaderPtr - Parent->getData().data(); |
122 | *Err = malformedError(Msg: Msg + "at offset " + Twine(Offset)); |
123 | } else |
124 | *Err = malformedError(Msg: Msg + "for " + NameOrErr.get()); |
125 | } |
126 | return; |
127 | } |
128 | } |
129 | |
130 | BigArchiveMemberHeader::(const Archive *Parent, |
131 | const char *, |
132 | uint64_t Size, Error *Err) |
133 | : CommonArchiveMemberHeader<BigArMemHdrType>( |
134 | Parent, reinterpret_cast<const BigArMemHdrType *>(RawHeaderPtr)) { |
135 | if (RawHeaderPtr == nullptr) |
136 | return; |
137 | ErrorAsOutParameter ErrAsOutParam(Err); |
138 | |
139 | if (RawHeaderPtr + getSizeOf() >= Parent->getData().end()) { |
140 | if (Err) |
141 | *Err = malformedError(Msg: "malformed AIX big archive: remaining buffer is " |
142 | "unable to contain next archive member" ); |
143 | return; |
144 | } |
145 | |
146 | if (Size < getSizeOf()) { |
147 | Error SubErr = createMemberHeaderParseError(ArMemHeader: this, RawHeaderPtr, Size); |
148 | if (Err) |
149 | *Err = std::move(SubErr); |
150 | } |
151 | } |
152 | |
153 | // This gets the raw name from the ArMemHdr->Name field and checks that it is |
154 | // valid for the kind of archive. If it is not valid it returns an Error. |
155 | Expected<StringRef> ArchiveMemberHeader::() const { |
156 | char EndCond; |
157 | auto Kind = Parent->kind(); |
158 | if (Kind == Archive::K_BSD || Kind == Archive::K_DARWIN64) { |
159 | if (ArMemHdr->Name[0] == ' ') { |
160 | uint64_t Offset = |
161 | reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); |
162 | return malformedError(Msg: "name contains a leading space for archive member " |
163 | "header at offset " + |
164 | Twine(Offset)); |
165 | } |
166 | EndCond = ' '; |
167 | } else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#') |
168 | EndCond = ' '; |
169 | else |
170 | EndCond = '/'; |
171 | StringRef::size_type end = |
172 | StringRef(ArMemHdr->Name, sizeof(ArMemHdr->Name)).find(C: EndCond); |
173 | if (end == StringRef::npos) |
174 | end = sizeof(ArMemHdr->Name); |
175 | assert(end <= sizeof(ArMemHdr->Name) && end > 0); |
176 | // Don't include the EndCond if there is one. |
177 | return StringRef(ArMemHdr->Name, end); |
178 | } |
179 | |
180 | Expected<uint64_t> |
181 | (Twine FieldName, const StringRef RawField, |
182 | const Archive *Parent, |
183 | const AbstractArchiveMemberHeader *) { |
184 | uint64_t Value; |
185 | if (RawField.getAsInteger(Radix: 10, Result&: Value)) { |
186 | uint64_t Offset = MemHeader->getOffset(); |
187 | return malformedError(Msg: "characters in " + FieldName + |
188 | " field in archive member header are not " |
189 | "all decimal numbers: '" + |
190 | RawField + |
191 | "' for the archive " |
192 | "member header at offset " + |
193 | Twine(Offset)); |
194 | } |
195 | return Value; |
196 | } |
197 | |
198 | Expected<uint64_t> |
199 | (Twine FieldName, const StringRef RawField, |
200 | const Archive *Parent, |
201 | const AbstractArchiveMemberHeader *) { |
202 | uint64_t Value; |
203 | if (RawField.getAsInteger(Radix: 8, Result&: Value)) { |
204 | uint64_t Offset = MemHeader->getOffset(); |
205 | return malformedError(Msg: "characters in " + FieldName + |
206 | " field in archive member header are not " |
207 | "all octal numbers: '" + |
208 | RawField + |
209 | "' for the archive " |
210 | "member header at offset " + |
211 | Twine(Offset)); |
212 | } |
213 | return Value; |
214 | } |
215 | |
216 | Expected<StringRef> BigArchiveMemberHeader::() const { |
217 | Expected<uint64_t> NameLenOrErr = getArchiveMemberDecField( |
218 | FieldName: "NameLen" , RawField: getFieldRawString(Field: ArMemHdr->NameLen), Parent, MemHeader: this); |
219 | if (!NameLenOrErr) |
220 | // TODO: Out-of-line. |
221 | return NameLenOrErr.takeError(); |
222 | uint64_t NameLen = NameLenOrErr.get(); |
223 | |
224 | // If the name length is odd, pad with '\0' to get an even length. After |
225 | // padding, there is the name terminator "`\n". |
226 | uint64_t NameLenWithPadding = alignTo(Value: NameLen, Align: 2); |
227 | StringRef NameTerminator = "`\n" ; |
228 | StringRef NameStringWithNameTerminator = |
229 | StringRef(ArMemHdr->Name, NameLenWithPadding + NameTerminator.size()); |
230 | if (!NameStringWithNameTerminator.ends_with(Suffix: NameTerminator)) { |
231 | uint64_t Offset = |
232 | reinterpret_cast<const char *>(ArMemHdr->Name + NameLenWithPadding) - |
233 | Parent->getData().data(); |
234 | // TODO: Out-of-line. |
235 | return malformedError( |
236 | Msg: "name does not have name terminator \"`\\n\" for archive member" |
237 | "header at offset " + |
238 | Twine(Offset)); |
239 | } |
240 | return StringRef(ArMemHdr->Name, NameLen); |
241 | } |
242 | |
243 | // member including the header, so the size of any name following the header |
244 | // is checked to make sure it does not overflow. |
245 | Expected<StringRef> ArchiveMemberHeader::(uint64_t Size) const { |
246 | |
247 | // This can be called from the ArchiveMemberHeader constructor when the |
248 | // archive header is truncated to produce an error message with the name. |
249 | // Make sure the name field is not truncated. |
250 | if (Size < offsetof(UnixArMemHdrType, Name) + sizeof(ArMemHdr->Name)) { |
251 | uint64_t ArchiveOffset = |
252 | reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); |
253 | return malformedError(Msg: "archive header truncated before the name field " |
254 | "for archive member header at offset " + |
255 | Twine(ArchiveOffset)); |
256 | } |
257 | |
258 | // The raw name itself can be invalid. |
259 | Expected<StringRef> NameOrErr = getRawName(); |
260 | if (!NameOrErr) |
261 | return NameOrErr.takeError(); |
262 | StringRef Name = NameOrErr.get(); |
263 | |
264 | // Check if it's a special name. |
265 | if (Name[0] == '/') { |
266 | if (Name.size() == 1) // Linker member. |
267 | return Name; |
268 | if (Name.size() == 2 && Name[1] == '/') // String table. |
269 | return Name; |
270 | // System libraries from the Windows SDK for Windows 11 contain this symbol. |
271 | // It looks like a CFG guard: we just skip it for now. |
272 | if (Name == "/<XFGHASHMAP>/" ) |
273 | return Name; |
274 | // Some libraries (e.g., arm64rt.lib) from the Windows WDK |
275 | // (version 10.0.22000.0) contain this undocumented special member. |
276 | if (Name == "/<ECSYMBOLS>/" ) |
277 | return Name; |
278 | // It's a long name. |
279 | // Get the string table offset. |
280 | std::size_t StringOffset; |
281 | if (Name.substr(Start: 1).rtrim(Char: ' ').getAsInteger(Radix: 10, Result&: StringOffset)) { |
282 | std::string Buf; |
283 | raw_string_ostream OS(Buf); |
284 | OS.write_escaped(Str: Name.substr(Start: 1).rtrim(Char: ' ')); |
285 | OS.flush(); |
286 | uint64_t ArchiveOffset = |
287 | reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); |
288 | return malformedError(Msg: "long name offset characters after the '/' are " |
289 | "not all decimal numbers: '" + |
290 | Buf + "' for archive member header at offset " + |
291 | Twine(ArchiveOffset)); |
292 | } |
293 | |
294 | // Verify it. |
295 | if (StringOffset >= Parent->getStringTable().size()) { |
296 | uint64_t ArchiveOffset = |
297 | reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); |
298 | return malformedError(Msg: "long name offset " + Twine(StringOffset) + |
299 | " past the end of the string table for archive " |
300 | "member header at offset " + |
301 | Twine(ArchiveOffset)); |
302 | } |
303 | |
304 | // GNU long file names end with a "/\n". |
305 | if (Parent->kind() == Archive::K_GNU || |
306 | Parent->kind() == Archive::K_GNU64) { |
307 | size_t End = Parent->getStringTable().find(C: '\n', /*From=*/StringOffset); |
308 | if (End == StringRef::npos || End < 1 || |
309 | Parent->getStringTable()[End - 1] != '/') { |
310 | return malformedError(Msg: "string table at long name offset " + |
311 | Twine(StringOffset) + "not terminated" ); |
312 | } |
313 | return Parent->getStringTable().slice(Start: StringOffset, End: End - 1); |
314 | } |
315 | return Parent->getStringTable().begin() + StringOffset; |
316 | } |
317 | |
318 | if (Name.starts_with(Prefix: "#1/" )) { |
319 | uint64_t NameLength; |
320 | if (Name.substr(Start: 3).rtrim(Char: ' ').getAsInteger(Radix: 10, Result&: NameLength)) { |
321 | std::string Buf; |
322 | raw_string_ostream OS(Buf); |
323 | OS.write_escaped(Str: Name.substr(Start: 3).rtrim(Char: ' ')); |
324 | OS.flush(); |
325 | uint64_t ArchiveOffset = |
326 | reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); |
327 | return malformedError(Msg: "long name length characters after the #1/ are " |
328 | "not all decimal numbers: '" + |
329 | Buf + "' for archive member header at offset " + |
330 | Twine(ArchiveOffset)); |
331 | } |
332 | if (getSizeOf() + NameLength > Size) { |
333 | uint64_t ArchiveOffset = |
334 | reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data(); |
335 | return malformedError(Msg: "long name length: " + Twine(NameLength) + |
336 | " extends past the end of the member or archive " |
337 | "for archive member header at offset " + |
338 | Twine(ArchiveOffset)); |
339 | } |
340 | return StringRef(reinterpret_cast<const char *>(ArMemHdr) + getSizeOf(), |
341 | NameLength) |
342 | .rtrim(Char: '\0'); |
343 | } |
344 | |
345 | // It is not a long name so trim the blanks at the end of the name. |
346 | if (Name[Name.size() - 1] != '/') |
347 | return Name.rtrim(Char: ' '); |
348 | |
349 | // It's a simple name. |
350 | return Name.drop_back(N: 1); |
351 | } |
352 | |
353 | Expected<StringRef> BigArchiveMemberHeader::(uint64_t Size) const { |
354 | return getRawName(); |
355 | } |
356 | |
357 | Expected<uint64_t> ArchiveMemberHeader::() const { |
358 | return getArchiveMemberDecField(FieldName: "size" , RawField: getFieldRawString(Field: ArMemHdr->Size), |
359 | Parent, MemHeader: this); |
360 | } |
361 | |
362 | Expected<uint64_t> BigArchiveMemberHeader::() const { |
363 | Expected<uint64_t> SizeOrErr = getArchiveMemberDecField( |
364 | FieldName: "size" , RawField: getFieldRawString(Field: ArMemHdr->Size), Parent, MemHeader: this); |
365 | if (!SizeOrErr) |
366 | return SizeOrErr.takeError(); |
367 | |
368 | Expected<uint64_t> NameLenOrErr = getRawNameSize(); |
369 | if (!NameLenOrErr) |
370 | return NameLenOrErr.takeError(); |
371 | |
372 | return *SizeOrErr + alignTo(Value: *NameLenOrErr, Align: 2); |
373 | } |
374 | |
375 | Expected<uint64_t> BigArchiveMemberHeader::() const { |
376 | return getArchiveMemberDecField( |
377 | FieldName: "NameLen" , RawField: getFieldRawString(Field: ArMemHdr->NameLen), Parent, MemHeader: this); |
378 | } |
379 | |
380 | Expected<uint64_t> BigArchiveMemberHeader::() const { |
381 | return getArchiveMemberDecField( |
382 | FieldName: "NextOffset" , RawField: getFieldRawString(Field: ArMemHdr->NextOffset), Parent, MemHeader: this); |
383 | } |
384 | |
385 | Expected<sys::fs::perms> AbstractArchiveMemberHeader::() const { |
386 | Expected<uint64_t> AccessModeOrErr = |
387 | getArchiveMemberOctField(FieldName: "AccessMode" , RawField: getRawAccessMode(), Parent, MemHeader: this); |
388 | if (!AccessModeOrErr) |
389 | return AccessModeOrErr.takeError(); |
390 | return static_cast<sys::fs::perms>(*AccessModeOrErr); |
391 | } |
392 | |
393 | Expected<sys::TimePoint<std::chrono::seconds>> |
394 | AbstractArchiveMemberHeader::() const { |
395 | Expected<uint64_t> SecondsOrErr = getArchiveMemberDecField( |
396 | FieldName: "LastModified" , RawField: getRawLastModified(), Parent, MemHeader: this); |
397 | |
398 | if (!SecondsOrErr) |
399 | return SecondsOrErr.takeError(); |
400 | |
401 | return sys::toTimePoint(T: *SecondsOrErr); |
402 | } |
403 | |
404 | Expected<unsigned> AbstractArchiveMemberHeader::() const { |
405 | StringRef User = getRawUID(); |
406 | if (User.empty()) |
407 | return 0; |
408 | return getArchiveMemberDecField(FieldName: "UID" , RawField: User, Parent, MemHeader: this); |
409 | } |
410 | |
411 | Expected<unsigned> AbstractArchiveMemberHeader::() const { |
412 | StringRef Group = getRawGID(); |
413 | if (Group.empty()) |
414 | return 0; |
415 | return getArchiveMemberDecField(FieldName: "GID" , RawField: Group, Parent, MemHeader: this); |
416 | } |
417 | |
418 | Expected<bool> ArchiveMemberHeader::() const { |
419 | Expected<StringRef> NameOrErr = getRawName(); |
420 | if (!NameOrErr) |
421 | return NameOrErr.takeError(); |
422 | StringRef Name = NameOrErr.get(); |
423 | return Parent->isThin() && Name != "/" && Name != "//" && Name != "/SYM64/" ; |
424 | } |
425 | |
426 | Expected<const char *> ArchiveMemberHeader::() const { |
427 | uint64_t Size = getSizeOf(); |
428 | Expected<bool> isThinOrErr = isThin(); |
429 | if (!isThinOrErr) |
430 | return isThinOrErr.takeError(); |
431 | |
432 | bool isThin = isThinOrErr.get(); |
433 | if (!isThin) { |
434 | Expected<uint64_t> MemberSize = getSize(); |
435 | if (!MemberSize) |
436 | return MemberSize.takeError(); |
437 | |
438 | Size += MemberSize.get(); |
439 | } |
440 | |
441 | // If Size is odd, add 1 to make it even. |
442 | const char *NextLoc = |
443 | reinterpret_cast<const char *>(ArMemHdr) + alignTo(Value: Size, Align: 2); |
444 | |
445 | if (NextLoc == Parent->getMemoryBufferRef().getBufferEnd()) |
446 | return nullptr; |
447 | |
448 | return NextLoc; |
449 | } |
450 | |
451 | Expected<const char *> BigArchiveMemberHeader::() const { |
452 | if (getOffset() == |
453 | static_cast<const BigArchive *>(Parent)->getLastChildOffset()) |
454 | return nullptr; |
455 | |
456 | Expected<uint64_t> NextOffsetOrErr = getNextOffset(); |
457 | if (!NextOffsetOrErr) |
458 | return NextOffsetOrErr.takeError(); |
459 | return Parent->getData().data() + NextOffsetOrErr.get(); |
460 | } |
461 | |
462 | Archive::Child::Child(const Archive *Parent, StringRef Data, |
463 | uint16_t StartOfFile) |
464 | : Parent(Parent), Data(Data), StartOfFile(StartOfFile) { |
465 | Header = Parent->createArchiveMemberHeader(RawHeaderPtr: Data.data(), Size: Data.size(), Err: nullptr); |
466 | } |
467 | |
468 | Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err) |
469 | : Parent(Parent) { |
470 | if (!Start) { |
471 | Header = nullptr; |
472 | StartOfFile = -1; |
473 | return; |
474 | } |
475 | |
476 | Header = Parent->createArchiveMemberHeader( |
477 | RawHeaderPtr: Start, |
478 | Size: Parent ? Parent->getData().size() - (Start - Parent->getData().data()) |
479 | : 0, |
480 | Err); |
481 | |
482 | // If we are pointed to real data, Start is not a nullptr, then there must be |
483 | // a non-null Err pointer available to report malformed data on. Only in |
484 | // the case sentinel value is being constructed is Err is permitted to be a |
485 | // nullptr. |
486 | assert(Err && "Err can't be nullptr if Start is not a nullptr" ); |
487 | |
488 | ErrorAsOutParameter ErrAsOutParam(Err); |
489 | |
490 | // If there was an error in the construction of the Header |
491 | // then just return with the error now set. |
492 | if (*Err) |
493 | return; |
494 | |
495 | uint64_t Size = Header->getSizeOf(); |
496 | Data = StringRef(Start, Size); |
497 | Expected<bool> isThinOrErr = isThinMember(); |
498 | if (!isThinOrErr) { |
499 | *Err = isThinOrErr.takeError(); |
500 | return; |
501 | } |
502 | bool isThin = isThinOrErr.get(); |
503 | if (!isThin) { |
504 | Expected<uint64_t> MemberSize = getRawSize(); |
505 | if (!MemberSize) { |
506 | *Err = MemberSize.takeError(); |
507 | return; |
508 | } |
509 | Size += MemberSize.get(); |
510 | Data = StringRef(Start, Size); |
511 | } |
512 | |
513 | // Setup StartOfFile and PaddingBytes. |
514 | StartOfFile = Header->getSizeOf(); |
515 | // Don't include attached name. |
516 | Expected<StringRef> NameOrErr = getRawName(); |
517 | if (!NameOrErr) { |
518 | *Err = NameOrErr.takeError(); |
519 | return; |
520 | } |
521 | StringRef Name = NameOrErr.get(); |
522 | |
523 | if (Parent->kind() == Archive::K_AIXBIG) { |
524 | // The actual start of the file is after the name and any necessary |
525 | // even-alignment padding. |
526 | StartOfFile += ((Name.size() + 1) >> 1) << 1; |
527 | } else if (Name.starts_with(Prefix: "#1/" )) { |
528 | uint64_t NameSize; |
529 | StringRef RawNameSize = Name.substr(Start: 3).rtrim(Char: ' '); |
530 | if (RawNameSize.getAsInteger(Radix: 10, Result&: NameSize)) { |
531 | uint64_t Offset = Start - Parent->getData().data(); |
532 | *Err = malformedError(Msg: "long name length characters after the #1/ are " |
533 | "not all decimal numbers: '" + |
534 | RawNameSize + |
535 | "' for archive member header at offset " + |
536 | Twine(Offset)); |
537 | return; |
538 | } |
539 | StartOfFile += NameSize; |
540 | } |
541 | } |
542 | |
543 | Expected<uint64_t> Archive::Child::getSize() const { |
544 | if (Parent->IsThin) |
545 | return Header->getSize(); |
546 | return Data.size() - StartOfFile; |
547 | } |
548 | |
549 | Expected<uint64_t> Archive::Child::getRawSize() const { |
550 | return Header->getSize(); |
551 | } |
552 | |
553 | Expected<bool> Archive::Child::isThinMember() const { return Header->isThin(); } |
554 | |
555 | Expected<std::string> Archive::Child::getFullName() const { |
556 | Expected<bool> isThin = isThinMember(); |
557 | if (!isThin) |
558 | return isThin.takeError(); |
559 | assert(isThin.get()); |
560 | Expected<StringRef> NameOrErr = getName(); |
561 | if (!NameOrErr) |
562 | return NameOrErr.takeError(); |
563 | StringRef Name = *NameOrErr; |
564 | if (sys::path::is_absolute(path: Name)) |
565 | return std::string(Name); |
566 | |
567 | SmallString<128> FullName = sys::path::parent_path( |
568 | path: Parent->getMemoryBufferRef().getBufferIdentifier()); |
569 | sys::path::append(path&: FullName, a: Name); |
570 | return std::string(FullName); |
571 | } |
572 | |
573 | Expected<StringRef> Archive::Child::getBuffer() const { |
574 | Expected<bool> isThinOrErr = isThinMember(); |
575 | if (!isThinOrErr) |
576 | return isThinOrErr.takeError(); |
577 | bool isThin = isThinOrErr.get(); |
578 | if (!isThin) { |
579 | Expected<uint64_t> Size = getSize(); |
580 | if (!Size) |
581 | return Size.takeError(); |
582 | return StringRef(Data.data() + StartOfFile, Size.get()); |
583 | } |
584 | Expected<std::string> FullNameOrErr = getFullName(); |
585 | if (!FullNameOrErr) |
586 | return FullNameOrErr.takeError(); |
587 | const std::string &FullName = *FullNameOrErr; |
588 | ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(Filename: FullName); |
589 | if (std::error_code EC = Buf.getError()) |
590 | return errorCodeToError(EC); |
591 | Parent->ThinBuffers.push_back(x: std::move(*Buf)); |
592 | return Parent->ThinBuffers.back()->getBuffer(); |
593 | } |
594 | |
595 | Expected<Archive::Child> Archive::Child::getNext() const { |
596 | Expected<const char *> NextLocOrErr = Header->getNextChildLoc(); |
597 | if (!NextLocOrErr) |
598 | return NextLocOrErr.takeError(); |
599 | |
600 | const char *NextLoc = *NextLocOrErr; |
601 | |
602 | // Check to see if this is at the end of the archive. |
603 | if (NextLoc == nullptr) |
604 | return Child(nullptr, nullptr, nullptr); |
605 | |
606 | // Check to see if this is past the end of the archive. |
607 | if (NextLoc > Parent->Data.getBufferEnd()) { |
608 | std::string Msg("offset to next archive member past the end of the archive " |
609 | "after member " ); |
610 | Expected<StringRef> NameOrErr = getName(); |
611 | if (!NameOrErr) { |
612 | consumeError(Err: NameOrErr.takeError()); |
613 | uint64_t Offset = Data.data() - Parent->getData().data(); |
614 | return malformedError(Msg: Msg + "at offset " + Twine(Offset)); |
615 | } else |
616 | return malformedError(Msg: Msg + NameOrErr.get()); |
617 | } |
618 | |
619 | Error Err = Error::success(); |
620 | Child Ret(Parent, NextLoc, &Err); |
621 | if (Err) |
622 | return std::move(Err); |
623 | return Ret; |
624 | } |
625 | |
626 | uint64_t Archive::Child::getChildOffset() const { |
627 | const char *a = Parent->Data.getBuffer().data(); |
628 | const char *c = Data.data(); |
629 | uint64_t offset = c - a; |
630 | return offset; |
631 | } |
632 | |
633 | Expected<StringRef> Archive::Child::getName() const { |
634 | Expected<uint64_t> RawSizeOrErr = getRawSize(); |
635 | if (!RawSizeOrErr) |
636 | return RawSizeOrErr.takeError(); |
637 | uint64_t RawSize = RawSizeOrErr.get(); |
638 | Expected<StringRef> NameOrErr = |
639 | Header->getName(Size: Header->getSizeOf() + RawSize); |
640 | if (!NameOrErr) |
641 | return NameOrErr.takeError(); |
642 | StringRef Name = NameOrErr.get(); |
643 | return Name; |
644 | } |
645 | |
646 | Expected<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const { |
647 | Expected<StringRef> NameOrErr = getName(); |
648 | if (!NameOrErr) |
649 | return NameOrErr.takeError(); |
650 | StringRef Name = NameOrErr.get(); |
651 | Expected<StringRef> Buf = getBuffer(); |
652 | if (!Buf) |
653 | return createFileError(F: Name, E: Buf.takeError()); |
654 | return MemoryBufferRef(*Buf, Name); |
655 | } |
656 | |
657 | Expected<std::unique_ptr<Binary>> |
658 | Archive::Child::getAsBinary(LLVMContext *Context) const { |
659 | Expected<MemoryBufferRef> BuffOrErr = getMemoryBufferRef(); |
660 | if (!BuffOrErr) |
661 | return BuffOrErr.takeError(); |
662 | |
663 | auto BinaryOrErr = createBinary(Source: BuffOrErr.get(), Context); |
664 | if (BinaryOrErr) |
665 | return std::move(*BinaryOrErr); |
666 | return BinaryOrErr.takeError(); |
667 | } |
668 | |
669 | Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) { |
670 | Error Err = Error::success(); |
671 | std::unique_ptr<Archive> Ret; |
672 | StringRef Buffer = Source.getBuffer(); |
673 | |
674 | if (Buffer.starts_with(Prefix: BigArchiveMagic)) |
675 | Ret = std::make_unique<BigArchive>(args&: Source, args&: Err); |
676 | else |
677 | Ret = std::make_unique<Archive>(args&: Source, args&: Err); |
678 | |
679 | if (Err) |
680 | return std::move(Err); |
681 | return std::move(Ret); |
682 | } |
683 | |
684 | std::unique_ptr<AbstractArchiveMemberHeader> |
685 | Archive::(const char *, uint64_t Size, |
686 | Error *Err) const { |
687 | ErrorAsOutParameter ErrAsOutParam(Err); |
688 | if (kind() != K_AIXBIG) |
689 | return std::make_unique<ArchiveMemberHeader>(args: this, args&: RawHeaderPtr, args&: Size, args&: Err); |
690 | return std::make_unique<BigArchiveMemberHeader>(args: this, args&: RawHeaderPtr, args&: Size, |
691 | args&: Err); |
692 | } |
693 | |
694 | uint64_t Archive::getArchiveMagicLen() const { |
695 | if (isThin()) |
696 | return sizeof(ThinArchiveMagic) - 1; |
697 | |
698 | if (Kind() == K_AIXBIG) |
699 | return sizeof(BigArchiveMagic) - 1; |
700 | |
701 | return sizeof(ArchiveMagic) - 1; |
702 | } |
703 | |
704 | void Archive::setFirstRegular(const Child &C) { |
705 | FirstRegularData = C.Data; |
706 | FirstRegularStartOfFile = C.StartOfFile; |
707 | } |
708 | |
709 | Archive::Archive(MemoryBufferRef Source, Error &Err) |
710 | : Binary(Binary::ID_Archive, Source) { |
711 | ErrorAsOutParameter ErrAsOutParam(&Err); |
712 | StringRef Buffer = Data.getBuffer(); |
713 | // Check for sufficient magic. |
714 | if (Buffer.starts_with(Prefix: ThinArchiveMagic)) { |
715 | IsThin = true; |
716 | } else if (Buffer.starts_with(Prefix: ArchiveMagic)) { |
717 | IsThin = false; |
718 | } else if (Buffer.starts_with(Prefix: BigArchiveMagic)) { |
719 | Format = K_AIXBIG; |
720 | IsThin = false; |
721 | return; |
722 | } else { |
723 | Err = make_error<GenericBinaryError>(Args: "file too small to be an archive" , |
724 | Args: object_error::invalid_file_type); |
725 | return; |
726 | } |
727 | |
728 | // Make sure Format is initialized before any call to |
729 | // ArchiveMemberHeader::getName() is made. This could be a valid empty |
730 | // archive which is the same in all formats. So claiming it to be gnu to is |
731 | // fine if not totally correct before we look for a string table or table of |
732 | // contents. |
733 | Format = K_GNU; |
734 | |
735 | // Get the special members. |
736 | child_iterator I = child_begin(Err, SkipInternal: false); |
737 | if (Err) |
738 | return; |
739 | child_iterator E = child_end(); |
740 | |
741 | // See if this is a valid empty archive and if so return. |
742 | if (I == E) { |
743 | Err = Error::success(); |
744 | return; |
745 | } |
746 | const Child *C = &*I; |
747 | |
748 | auto Increment = [&]() { |
749 | ++I; |
750 | if (Err) |
751 | return true; |
752 | C = &*I; |
753 | return false; |
754 | }; |
755 | |
756 | Expected<StringRef> NameOrErr = C->getRawName(); |
757 | if (!NameOrErr) { |
758 | Err = NameOrErr.takeError(); |
759 | return; |
760 | } |
761 | StringRef Name = NameOrErr.get(); |
762 | |
763 | // Below is the pattern that is used to figure out the archive format |
764 | // GNU archive format |
765 | // First member : / (may exist, if it exists, points to the symbol table ) |
766 | // Second member : // (may exist, if it exists, points to the string table) |
767 | // Note : The string table is used if the filename exceeds 15 characters |
768 | // BSD archive format |
769 | // First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table) |
770 | // There is no string table, if the filename exceeds 15 characters or has a |
771 | // embedded space, the filename has #1/<size>, The size represents the size |
772 | // of the filename that needs to be read after the archive header |
773 | // COFF archive format |
774 | // First member : / |
775 | // Second member : / (provides a directory of symbols) |
776 | // Third member : // (may exist, if it exists, contains the string table) |
777 | // Note: Microsoft PE/COFF Spec 8.3 says that the third member is present |
778 | // even if the string table is empty. However, lib.exe does not in fact |
779 | // seem to create the third member if there's no member whose filename |
780 | // exceeds 15 characters. So the third member is optional. |
781 | |
782 | if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64" ) { |
783 | if (Name == "__.SYMDEF" ) |
784 | Format = K_BSD; |
785 | else // Name == "__.SYMDEF_64" |
786 | Format = K_DARWIN64; |
787 | // We know that the symbol table is not an external file, but we still must |
788 | // check any Expected<> return value. |
789 | Expected<StringRef> BufOrErr = C->getBuffer(); |
790 | if (!BufOrErr) { |
791 | Err = BufOrErr.takeError(); |
792 | return; |
793 | } |
794 | SymbolTable = BufOrErr.get(); |
795 | if (Increment()) |
796 | return; |
797 | setFirstRegular(*C); |
798 | |
799 | Err = Error::success(); |
800 | return; |
801 | } |
802 | |
803 | if (Name.starts_with(Prefix: "#1/" )) { |
804 | Format = K_BSD; |
805 | // We know this is BSD, so getName will work since there is no string table. |
806 | Expected<StringRef> NameOrErr = C->getName(); |
807 | if (!NameOrErr) { |
808 | Err = NameOrErr.takeError(); |
809 | return; |
810 | } |
811 | Name = NameOrErr.get(); |
812 | if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF" ) { |
813 | // We know that the symbol table is not an external file, but we still |
814 | // must check any Expected<> return value. |
815 | Expected<StringRef> BufOrErr = C->getBuffer(); |
816 | if (!BufOrErr) { |
817 | Err = BufOrErr.takeError(); |
818 | return; |
819 | } |
820 | SymbolTable = BufOrErr.get(); |
821 | if (Increment()) |
822 | return; |
823 | } else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64" ) { |
824 | Format = K_DARWIN64; |
825 | // We know that the symbol table is not an external file, but we still |
826 | // must check any Expected<> return value. |
827 | Expected<StringRef> BufOrErr = C->getBuffer(); |
828 | if (!BufOrErr) { |
829 | Err = BufOrErr.takeError(); |
830 | return; |
831 | } |
832 | SymbolTable = BufOrErr.get(); |
833 | if (Increment()) |
834 | return; |
835 | } |
836 | setFirstRegular(*C); |
837 | return; |
838 | } |
839 | |
840 | // MIPS 64-bit ELF archives use a special format of a symbol table. |
841 | // This format is marked by `ar_name` field equals to "/SYM64/". |
842 | // For detailed description see page 96 in the following document: |
843 | // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf |
844 | |
845 | bool has64SymTable = false; |
846 | if (Name == "/" || Name == "/SYM64/" ) { |
847 | // We know that the symbol table is not an external file, but we still |
848 | // must check any Expected<> return value. |
849 | Expected<StringRef> BufOrErr = C->getBuffer(); |
850 | if (!BufOrErr) { |
851 | Err = BufOrErr.takeError(); |
852 | return; |
853 | } |
854 | SymbolTable = BufOrErr.get(); |
855 | if (Name == "/SYM64/" ) |
856 | has64SymTable = true; |
857 | |
858 | if (Increment()) |
859 | return; |
860 | if (I == E) { |
861 | Err = Error::success(); |
862 | return; |
863 | } |
864 | Expected<StringRef> NameOrErr = C->getRawName(); |
865 | if (!NameOrErr) { |
866 | Err = NameOrErr.takeError(); |
867 | return; |
868 | } |
869 | Name = NameOrErr.get(); |
870 | } |
871 | |
872 | if (Name == "//" ) { |
873 | Format = has64SymTable ? K_GNU64 : K_GNU; |
874 | // The string table is never an external member, but we still |
875 | // must check any Expected<> return value. |
876 | Expected<StringRef> BufOrErr = C->getBuffer(); |
877 | if (!BufOrErr) { |
878 | Err = BufOrErr.takeError(); |
879 | return; |
880 | } |
881 | StringTable = BufOrErr.get(); |
882 | if (Increment()) |
883 | return; |
884 | setFirstRegular(*C); |
885 | Err = Error::success(); |
886 | return; |
887 | } |
888 | |
889 | if (Name[0] != '/') { |
890 | Format = has64SymTable ? K_GNU64 : K_GNU; |
891 | setFirstRegular(*C); |
892 | Err = Error::success(); |
893 | return; |
894 | } |
895 | |
896 | if (Name != "/" ) { |
897 | Err = errorCodeToError(EC: object_error::parse_failed); |
898 | return; |
899 | } |
900 | |
901 | Format = K_COFF; |
902 | // We know that the symbol table is not an external file, but we still |
903 | // must check any Expected<> return value. |
904 | Expected<StringRef> BufOrErr = C->getBuffer(); |
905 | if (!BufOrErr) { |
906 | Err = BufOrErr.takeError(); |
907 | return; |
908 | } |
909 | SymbolTable = BufOrErr.get(); |
910 | |
911 | if (Increment()) |
912 | return; |
913 | |
914 | if (I == E) { |
915 | setFirstRegular(*C); |
916 | Err = Error::success(); |
917 | return; |
918 | } |
919 | |
920 | NameOrErr = C->getRawName(); |
921 | if (!NameOrErr) { |
922 | Err = NameOrErr.takeError(); |
923 | return; |
924 | } |
925 | Name = NameOrErr.get(); |
926 | |
927 | if (Name == "//" ) { |
928 | // The string table is never an external member, but we still |
929 | // must check any Expected<> return value. |
930 | Expected<StringRef> BufOrErr = C->getBuffer(); |
931 | if (!BufOrErr) { |
932 | Err = BufOrErr.takeError(); |
933 | return; |
934 | } |
935 | StringTable = BufOrErr.get(); |
936 | if (Increment()) |
937 | return; |
938 | |
939 | if (I == E) { |
940 | setFirstRegular(*C); |
941 | Err = Error::success(); |
942 | return; |
943 | } |
944 | |
945 | NameOrErr = C->getRawName(); |
946 | if (!NameOrErr) { |
947 | Err = NameOrErr.takeError(); |
948 | return; |
949 | } |
950 | Name = NameOrErr.get(); |
951 | } |
952 | |
953 | if (Name == "/<ECSYMBOLS>/" ) { |
954 | // ARM64EC-aware libraries contain an additional special member with |
955 | // an EC symbol map after the string table. Its format is similar to a |
956 | // regular symbol map, except it doesn't contain member offsets. Its indexes |
957 | // refer to member offsets from the regular symbol table instead. |
958 | Expected<StringRef> BufOrErr = C->getBuffer(); |
959 | if (!BufOrErr) { |
960 | Err = BufOrErr.takeError(); |
961 | return; |
962 | } |
963 | ECSymbolTable = BufOrErr.get(); |
964 | if (Increment()) |
965 | return; |
966 | } |
967 | |
968 | setFirstRegular(*C); |
969 | Err = Error::success(); |
970 | } |
971 | |
972 | object::Archive::Kind Archive::getDefaultKindForTriple(Triple &T) { |
973 | if (T.isOSDarwin()) |
974 | return object::Archive::K_DARWIN; |
975 | if (T.isOSAIX()) |
976 | return object::Archive::K_AIXBIG; |
977 | if (T.isOSWindows()) |
978 | return object::Archive::K_COFF; |
979 | return object::Archive::K_GNU; |
980 | } |
981 | |
982 | object::Archive::Kind Archive::getDefaultKind() { |
983 | Triple HostTriple(sys::getDefaultTargetTriple()); |
984 | return getDefaultKindForTriple(T&: HostTriple); |
985 | } |
986 | |
987 | Archive::child_iterator Archive::child_begin(Error &Err, |
988 | bool SkipInternal) const { |
989 | if (isEmpty()) |
990 | return child_end(); |
991 | |
992 | if (SkipInternal) |
993 | return child_iterator::itr( |
994 | I: Child(this, FirstRegularData, FirstRegularStartOfFile), Err); |
995 | |
996 | const char *Loc = Data.getBufferStart() + getFirstChildOffset(); |
997 | Child C(this, Loc, &Err); |
998 | if (Err) |
999 | return child_end(); |
1000 | return child_iterator::itr(I: C, Err); |
1001 | } |
1002 | |
1003 | Archive::child_iterator Archive::child_end() const { |
1004 | return child_iterator::end(I: Child(nullptr, nullptr, nullptr)); |
1005 | } |
1006 | |
1007 | bool Archive::Symbol::isECSymbol() const { |
1008 | // Symbols use SymbolCount..SymbolCount+getNumberOfECSymbols() for EC symbol |
1009 | // indexes. |
1010 | uint32_t SymbolCount = Parent->getNumberOfSymbols(); |
1011 | return SymbolCount <= SymbolIndex && |
1012 | SymbolIndex < SymbolCount + Parent->getNumberOfECSymbols(); |
1013 | } |
1014 | |
1015 | StringRef Archive::Symbol::getName() const { |
1016 | if (isECSymbol()) |
1017 | return Parent->ECSymbolTable.begin() + StringIndex; |
1018 | return Parent->getSymbolTable().begin() + StringIndex; |
1019 | } |
1020 | |
1021 | Expected<Archive::Child> Archive::Symbol::getMember() const { |
1022 | const char *Buf = Parent->getSymbolTable().begin(); |
1023 | const char *Offsets = Buf; |
1024 | if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64 || |
1025 | Parent->kind() == K_AIXBIG) |
1026 | Offsets += sizeof(uint64_t); |
1027 | else |
1028 | Offsets += sizeof(uint32_t); |
1029 | uint64_t Offset = 0; |
1030 | if (Parent->kind() == K_GNU) { |
1031 | Offset = read32be(P: Offsets + SymbolIndex * 4); |
1032 | } else if (Parent->kind() == K_GNU64 || Parent->kind() == K_AIXBIG) { |
1033 | Offset = read64be(P: Offsets + SymbolIndex * 8); |
1034 | } else if (Parent->kind() == K_BSD) { |
1035 | // The SymbolIndex is an index into the ranlib structs that start at |
1036 | // Offsets (the first uint32_t is the number of bytes of the ranlib |
1037 | // structs). The ranlib structs are a pair of uint32_t's the first |
1038 | // being a string table offset and the second being the offset into |
1039 | // the archive of the member that defines the symbol. Which is what |
1040 | // is needed here. |
1041 | Offset = read32le(P: Offsets + SymbolIndex * 8 + 4); |
1042 | } else if (Parent->kind() == K_DARWIN64) { |
1043 | // The SymbolIndex is an index into the ranlib_64 structs that start at |
1044 | // Offsets (the first uint64_t is the number of bytes of the ranlib_64 |
1045 | // structs). The ranlib_64 structs are a pair of uint64_t's the first |
1046 | // being a string table offset and the second being the offset into |
1047 | // the archive of the member that defines the symbol. Which is what |
1048 | // is needed here. |
1049 | Offset = read64le(P: Offsets + SymbolIndex * 16 + 8); |
1050 | } else { |
1051 | // Skip offsets. |
1052 | uint32_t MemberCount = read32le(P: Buf); |
1053 | Buf += MemberCount * 4 + 4; |
1054 | |
1055 | uint32_t SymbolCount = read32le(P: Buf); |
1056 | uint16_t OffsetIndex; |
1057 | if (SymbolIndex < SymbolCount) { |
1058 | // Skip SymbolCount to get to the indices table. |
1059 | const char *Indices = Buf + 4; |
1060 | |
1061 | // Get the index of the offset in the file member offset table for this |
1062 | // symbol. |
1063 | OffsetIndex = read16le(P: Indices + SymbolIndex * 2); |
1064 | } else if (isECSymbol()) { |
1065 | // Skip SymbolCount to get to the indices table. |
1066 | const char *Indices = Parent->ECSymbolTable.begin() + 4; |
1067 | |
1068 | // Get the index of the offset in the file member offset table for this |
1069 | // symbol. |
1070 | OffsetIndex = read16le(P: Indices + (SymbolIndex - SymbolCount) * 2); |
1071 | } else { |
1072 | return errorCodeToError(EC: object_error::parse_failed); |
1073 | } |
1074 | // Subtract 1 since OffsetIndex is 1 based. |
1075 | --OffsetIndex; |
1076 | |
1077 | if (OffsetIndex >= MemberCount) |
1078 | return errorCodeToError(EC: object_error::parse_failed); |
1079 | |
1080 | Offset = read32le(P: Offsets + OffsetIndex * 4); |
1081 | } |
1082 | |
1083 | const char *Loc = Parent->getData().begin() + Offset; |
1084 | Error Err = Error::success(); |
1085 | Child C(Parent, Loc, &Err); |
1086 | if (Err) |
1087 | return std::move(Err); |
1088 | return C; |
1089 | } |
1090 | |
1091 | Archive::Symbol Archive::Symbol::getNext() const { |
1092 | Symbol t(*this); |
1093 | if (Parent->kind() == K_BSD) { |
1094 | // t.StringIndex is an offset from the start of the __.SYMDEF or |
1095 | // "__.SYMDEF SORTED" member into the string table for the ranlib |
1096 | // struct indexed by t.SymbolIndex . To change t.StringIndex to the |
1097 | // offset in the string table for t.SymbolIndex+1 we subtract the |
1098 | // its offset from the start of the string table for t.SymbolIndex |
1099 | // and add the offset of the string table for t.SymbolIndex+1. |
1100 | |
1101 | // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t |
1102 | // which is the number of bytes of ranlib structs that follow. The ranlib |
1103 | // structs are a pair of uint32_t's the first being a string table offset |
1104 | // and the second being the offset into the archive of the member that |
1105 | // define the symbol. After that the next uint32_t is the byte count of |
1106 | // the string table followed by the string table. |
1107 | const char *Buf = Parent->getSymbolTable().begin(); |
1108 | uint32_t RanlibCount = 0; |
1109 | RanlibCount = read32le(P: Buf) / 8; |
1110 | // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount) |
1111 | // don't change the t.StringIndex as we don't want to reference a ranlib |
1112 | // past RanlibCount. |
1113 | if (t.SymbolIndex + 1 < RanlibCount) { |
1114 | const char *Ranlibs = Buf + 4; |
1115 | uint32_t CurRanStrx = 0; |
1116 | uint32_t = 0; |
1117 | CurRanStrx = read32le(P: Ranlibs + t.SymbolIndex * 8); |
1118 | NextRanStrx = read32le(P: Ranlibs + (t.SymbolIndex + 1) * 8); |
1119 | t.StringIndex -= CurRanStrx; |
1120 | t.StringIndex += NextRanStrx; |
1121 | } |
1122 | } else if (t.isECSymbol()) { |
1123 | // Go to one past next null. |
1124 | t.StringIndex = Parent->ECSymbolTable.find(C: '\0', From: t.StringIndex) + 1; |
1125 | } else { |
1126 | // Go to one past next null. |
1127 | t.StringIndex = Parent->getSymbolTable().find(C: '\0', From: t.StringIndex) + 1; |
1128 | } |
1129 | ++t.SymbolIndex; |
1130 | return t; |
1131 | } |
1132 | |
1133 | Archive::symbol_iterator Archive::symbol_begin() const { |
1134 | if (!hasSymbolTable()) |
1135 | return symbol_iterator(Symbol(this, 0, 0)); |
1136 | |
1137 | const char *buf = getSymbolTable().begin(); |
1138 | if (kind() == K_GNU) { |
1139 | uint32_t symbol_count = 0; |
1140 | symbol_count = read32be(P: buf); |
1141 | buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); |
1142 | } else if (kind() == K_GNU64) { |
1143 | uint64_t symbol_count = read64be(P: buf); |
1144 | buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t))); |
1145 | } else if (kind() == K_BSD) { |
1146 | // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t |
1147 | // which is the number of bytes of ranlib structs that follow. The ranlib |
1148 | // structs are a pair of uint32_t's the first being a string table offset |
1149 | // and the second being the offset into the archive of the member that |
1150 | // define the symbol. After that the next uint32_t is the byte count of |
1151 | // the string table followed by the string table. |
1152 | uint32_t ranlib_count = 0; |
1153 | ranlib_count = read32le(P: buf) / 8; |
1154 | const char *ranlibs = buf + 4; |
1155 | uint32_t ran_strx = 0; |
1156 | ran_strx = read32le(P: ranlibs); |
1157 | buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t)))); |
1158 | // Skip the byte count of the string table. |
1159 | buf += sizeof(uint32_t); |
1160 | buf += ran_strx; |
1161 | } else if (kind() == K_DARWIN64) { |
1162 | // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t |
1163 | // which is the number of bytes of ranlib_64 structs that follow. The |
1164 | // ranlib_64 structs are a pair of uint64_t's the first being a string |
1165 | // table offset and the second being the offset into the archive of the |
1166 | // member that define the symbol. After that the next uint64_t is the byte |
1167 | // count of the string table followed by the string table. |
1168 | uint64_t ranlib_count = 0; |
1169 | ranlib_count = read64le(P: buf) / 16; |
1170 | const char *ranlibs = buf + 8; |
1171 | uint64_t ran_strx = 0; |
1172 | ran_strx = read64le(P: ranlibs); |
1173 | buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t)))); |
1174 | // Skip the byte count of the string table. |
1175 | buf += sizeof(uint64_t); |
1176 | buf += ran_strx; |
1177 | } else if (kind() == K_AIXBIG) { |
1178 | buf = getStringTable().begin(); |
1179 | } else { |
1180 | uint32_t member_count = 0; |
1181 | uint32_t symbol_count = 0; |
1182 | member_count = read32le(P: buf); |
1183 | buf += 4 + (member_count * 4); // Skip offsets. |
1184 | symbol_count = read32le(P: buf); |
1185 | buf += 4 + (symbol_count * 2); // Skip indices. |
1186 | } |
1187 | uint32_t string_start_offset = buf - getSymbolTable().begin(); |
1188 | return symbol_iterator(Symbol(this, 0, string_start_offset)); |
1189 | } |
1190 | |
1191 | Archive::symbol_iterator Archive::symbol_end() const { |
1192 | return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0)); |
1193 | } |
1194 | |
1195 | Expected<iterator_range<Archive::symbol_iterator>> Archive::ec_symbols() const { |
1196 | uint32_t Count = 0; |
1197 | |
1198 | // Validate EC symbol table. |
1199 | if (!ECSymbolTable.empty()) { |
1200 | if (ECSymbolTable.size() < sizeof(uint32_t)) |
1201 | return malformedError(Msg: "invalid EC symbols size (" + |
1202 | Twine(ECSymbolTable.size()) + ")" ); |
1203 | if (SymbolTable.size() < sizeof(uint32_t)) |
1204 | return malformedError(Msg: "invalid symbols size (" + |
1205 | Twine(ECSymbolTable.size()) + ")" ); |
1206 | |
1207 | Count = read32le(P: ECSymbolTable.begin()); |
1208 | size_t StringIndex = sizeof(uint32_t) + Count * sizeof(uint16_t); |
1209 | if (ECSymbolTable.size() < StringIndex) |
1210 | return malformedError(Msg: "invalid EC symbols size. Size was " + |
1211 | Twine(ECSymbolTable.size()) + ", but expected " + |
1212 | Twine(StringIndex)); |
1213 | |
1214 | uint32_t MemberCount = read32le(P: SymbolTable.begin()); |
1215 | const char *Indexes = ECSymbolTable.begin() + sizeof(uint32_t); |
1216 | |
1217 | for (uint32_t i = 0; i < Count; ++i) { |
1218 | uint16_t Index = read16le(P: Indexes + i * sizeof(uint16_t)); |
1219 | if (!Index) |
1220 | return malformedError(Msg: "invalid EC symbol index 0" ); |
1221 | if (Index > MemberCount) |
1222 | return malformedError(Msg: "invalid EC symbol index " + Twine(Index) + |
1223 | " is larger than member count " + |
1224 | Twine(MemberCount)); |
1225 | |
1226 | StringIndex = ECSymbolTable.find(C: '\0', From: StringIndex); |
1227 | if (StringIndex == StringRef::npos) |
1228 | return malformedError(Msg: "malformed EC symbol names: not null-terminated" ); |
1229 | ++StringIndex; |
1230 | } |
1231 | } |
1232 | |
1233 | uint32_t SymbolCount = getNumberOfSymbols(); |
1234 | return make_range( |
1235 | x: symbol_iterator(Symbol(this, SymbolCount, |
1236 | sizeof(uint32_t) + Count * sizeof(uint16_t))), |
1237 | y: symbol_iterator(Symbol(this, SymbolCount + Count, 0))); |
1238 | } |
1239 | |
1240 | uint32_t Archive::getNumberOfSymbols() const { |
1241 | if (!hasSymbolTable()) |
1242 | return 0; |
1243 | const char *buf = getSymbolTable().begin(); |
1244 | if (kind() == K_GNU) |
1245 | return read32be(P: buf); |
1246 | if (kind() == K_GNU64 || kind() == K_AIXBIG) |
1247 | return read64be(P: buf); |
1248 | if (kind() == K_BSD) |
1249 | return read32le(P: buf) / 8; |
1250 | if (kind() == K_DARWIN64) |
1251 | return read64le(P: buf) / 16; |
1252 | uint32_t member_count = 0; |
1253 | member_count = read32le(P: buf); |
1254 | buf += 4 + (member_count * 4); // Skip offsets. |
1255 | return read32le(P: buf); |
1256 | } |
1257 | |
1258 | uint32_t Archive::getNumberOfECSymbols() const { |
1259 | if (ECSymbolTable.size() < sizeof(uint32_t)) |
1260 | return 0; |
1261 | return read32le(P: ECSymbolTable.begin()); |
1262 | } |
1263 | |
1264 | Expected<std::optional<Archive::Child>> Archive::findSym(StringRef name) const { |
1265 | Archive::symbol_iterator bs = symbol_begin(); |
1266 | Archive::symbol_iterator es = symbol_end(); |
1267 | |
1268 | for (; bs != es; ++bs) { |
1269 | StringRef SymName = bs->getName(); |
1270 | if (SymName == name) { |
1271 | if (auto MemberOrErr = bs->getMember()) |
1272 | return Child(*MemberOrErr); |
1273 | else |
1274 | return MemberOrErr.takeError(); |
1275 | } |
1276 | } |
1277 | return std::nullopt; |
1278 | } |
1279 | |
1280 | // Returns true if archive file contains no member file. |
1281 | bool Archive::isEmpty() const { |
1282 | return Data.getBufferSize() == getArchiveMagicLen(); |
1283 | } |
1284 | |
1285 | bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); } |
1286 | |
1287 | static Error getGlobalSymtabLocAndSize(const MemoryBufferRef &Data, |
1288 | uint64_t GlobalSymtabOffset, |
1289 | const char *&GlobalSymtabLoc, |
1290 | uint64_t &Size, const char *BitMessage) { |
1291 | uint64_t BufferSize = Data.getBufferSize(); |
1292 | uint64_t GlobalSymtabContentOffset = |
1293 | GlobalSymtabOffset + sizeof(BigArMemHdrType); |
1294 | if (GlobalSymtabContentOffset > BufferSize) |
1295 | return malformedError( |
1296 | Msg: Twine(BitMessage) + " global symbol table header at offset 0x" + |
1297 | Twine::utohexstr(Val: GlobalSymtabOffset) + " and size 0x" + |
1298 | Twine::utohexstr(Val: sizeof(BigArMemHdrType)) + |
1299 | " goes past the end of file" ); |
1300 | |
1301 | GlobalSymtabLoc = Data.getBufferStart() + GlobalSymtabOffset; |
1302 | const BigArMemHdrType *GlobalSymHdr = |
1303 | reinterpret_cast<const BigArMemHdrType *>(GlobalSymtabLoc); |
1304 | StringRef RawOffset = getFieldRawString(Field: GlobalSymHdr->Size); |
1305 | if (RawOffset.getAsInteger(Radix: 10, Result&: Size)) |
1306 | return malformedError(Msg: Twine(BitMessage) + " global symbol table size \"" + |
1307 | RawOffset + "\" is not a number" ); |
1308 | |
1309 | if (GlobalSymtabContentOffset + Size > BufferSize) |
1310 | return malformedError( |
1311 | Msg: Twine(BitMessage) + " global symbol table content at offset 0x" + |
1312 | Twine::utohexstr(Val: GlobalSymtabContentOffset) + " and size 0x" + |
1313 | Twine::utohexstr(Val: Size) + " goes past the end of file" ); |
1314 | |
1315 | return Error::success(); |
1316 | } |
1317 | |
1318 | struct GlobalSymtabInfo { |
1319 | uint64_t SymNum; |
1320 | StringRef SymbolTable; |
1321 | StringRef SymbolOffsetTable; |
1322 | StringRef StringTable; |
1323 | }; |
1324 | |
1325 | static void |
1326 | appendGlobalSymbolTableInfo(SmallVector<GlobalSymtabInfo> &SymtabInfos, |
1327 | const char *GlobalSymtabLoc, uint64_t Size) { |
1328 | // In a big archive, a global symbol table contains the following information: |
1329 | // - The number of symbols. |
1330 | // - The array of offsets into the archive file. The length is eight |
1331 | // times the number of symbols. |
1332 | // - The name-string table. The size is: |
1333 | // Size-(8*(the number of symbols + 1)). |
1334 | |
1335 | StringRef SymbolTable = |
1336 | StringRef(GlobalSymtabLoc + sizeof(BigArMemHdrType), Size); |
1337 | uint64_t SymNum = read64be(P: GlobalSymtabLoc + sizeof(BigArMemHdrType)); |
1338 | StringRef SymbolOffsetTable = StringRef(SymbolTable.data() + 8, 8 * SymNum); |
1339 | unsigned SymOffsetsSize = 8 * (SymNum + 1); |
1340 | uint64_t SymbolTableStringSize = Size - SymOffsetsSize; |
1341 | StringRef StringTable = |
1342 | StringRef(SymbolTable.data() + SymOffsetsSize, SymbolTableStringSize); |
1343 | SymtabInfos.push_back(Elt: {.SymNum: SymNum, .SymbolTable: SymbolTable, .SymbolOffsetTable: SymbolOffsetTable, .StringTable: StringTable}); |
1344 | } |
1345 | |
1346 | BigArchive::BigArchive(MemoryBufferRef Source, Error &Err) |
1347 | : Archive(Source, Err) { |
1348 | ErrorAsOutParameter ErrAsOutParam(&Err); |
1349 | StringRef Buffer = Data.getBuffer(); |
1350 | ArFixLenHdr = reinterpret_cast<const FixLenHdr *>(Buffer.data()); |
1351 | uint64_t BufferSize = Data.getBufferSize(); |
1352 | |
1353 | if (BufferSize < sizeof(FixLenHdr)) { |
1354 | Err = malformedError(Msg: "malformed AIX big archive: incomplete fixed length " |
1355 | "header, the archive is only" + |
1356 | Twine(BufferSize) + " byte(s)" ); |
1357 | return; |
1358 | } |
1359 | |
1360 | StringRef RawOffset = getFieldRawString(Field: ArFixLenHdr->FirstChildOffset); |
1361 | if (RawOffset.getAsInteger(Radix: 10, Result&: FirstChildOffset)) |
1362 | // TODO: Out-of-line. |
1363 | Err = malformedError(Msg: "malformed AIX big archive: first member offset \"" + |
1364 | RawOffset + "\" is not a number" ); |
1365 | |
1366 | RawOffset = getFieldRawString(Field: ArFixLenHdr->LastChildOffset); |
1367 | if (RawOffset.getAsInteger(Radix: 10, Result&: LastChildOffset)) |
1368 | // TODO: Out-of-line. |
1369 | Err = malformedError(Msg: "malformed AIX big archive: last member offset \"" + |
1370 | RawOffset + "\" is not a number" ); |
1371 | |
1372 | uint64_t GlobSymtab32Offset = 0; |
1373 | RawOffset = getFieldRawString(Field: ArFixLenHdr->GlobSymOffset); |
1374 | if (RawOffset.getAsInteger(Radix: 10, Result&: GlobSymtab32Offset)) { |
1375 | Err = malformedError(Msg: "global symbol table " |
1376 | "offset of 32-bit members \"" + |
1377 | RawOffset + "\" is not a number" ); |
1378 | return; |
1379 | } |
1380 | |
1381 | uint64_t GlobSymtab64Offset = 0; |
1382 | RawOffset = getFieldRawString(Field: ArFixLenHdr->GlobSym64Offset); |
1383 | if (RawOffset.getAsInteger(Radix: 10, Result&: GlobSymtab64Offset)) { |
1384 | Err = malformedError(Msg: "global symbol table " |
1385 | "offset of 64-bit members\"" + |
1386 | RawOffset + "\" is not a number" ); |
1387 | return; |
1388 | } |
1389 | |
1390 | const char *GlobSymtab32Loc = nullptr; |
1391 | const char *GlobSymtab64Loc = nullptr; |
1392 | uint64_t GlobSymtab32Size = 0; |
1393 | uint64_t GlobSymtab64Size = 0; |
1394 | const MemoryBufferRef &MemBuffRef = getMemoryBufferRef(); |
1395 | |
1396 | if (GlobSymtab32Offset) { |
1397 | Err = |
1398 | getGlobalSymtabLocAndSize(Data: MemBuffRef, GlobalSymtabOffset: GlobSymtab32Offset, |
1399 | GlobalSymtabLoc&: GlobSymtab32Loc, Size&: GlobSymtab32Size, BitMessage: "32-bit" ); |
1400 | if (Err) |
1401 | return; |
1402 | |
1403 | Has32BitGlobalSymtab = true; |
1404 | } |
1405 | |
1406 | if (GlobSymtab64Offset) { |
1407 | Err = |
1408 | getGlobalSymtabLocAndSize(Data: MemBuffRef, GlobalSymtabOffset: GlobSymtab64Offset, |
1409 | GlobalSymtabLoc&: GlobSymtab64Loc, Size&: GlobSymtab64Size, BitMessage: "64-bit" ); |
1410 | if (Err) |
1411 | return; |
1412 | |
1413 | Has64BitGlobalSymtab = true; |
1414 | } |
1415 | |
1416 | SmallVector<GlobalSymtabInfo> SymtabInfos; |
1417 | |
1418 | if (GlobSymtab32Offset) |
1419 | appendGlobalSymbolTableInfo(SymtabInfos, GlobalSymtabLoc: GlobSymtab32Loc, Size: GlobSymtab32Size); |
1420 | if (GlobSymtab64Offset) |
1421 | appendGlobalSymbolTableInfo(SymtabInfos, GlobalSymtabLoc: GlobSymtab64Loc, Size: GlobSymtab64Size); |
1422 | |
1423 | if (SymtabInfos.size() == 1) { |
1424 | SymbolTable = SymtabInfos[0].SymbolTable; |
1425 | StringTable = SymtabInfos[0].StringTable; |
1426 | } else if (SymtabInfos.size() == 2) { |
1427 | // In order to let the Archive::Symbol::getNext() work for both 32-bit and |
1428 | // 64-bit global symbol tables, we need to merge them into a single table. |
1429 | raw_string_ostream Out(MergedGlobalSymtabBuf); |
1430 | uint64_t SymNum = SymtabInfos[0].SymNum + SymtabInfos[1].SymNum; |
1431 | write(os&: Out, value: SymNum, endian: llvm::endianness::big); |
1432 | // Merge symbol offset. |
1433 | Out << SymtabInfos[0].SymbolOffsetTable; |
1434 | Out << SymtabInfos[1].SymbolOffsetTable; |
1435 | // Merge string table. |
1436 | Out << SymtabInfos[0].StringTable; |
1437 | Out << SymtabInfos[1].StringTable; |
1438 | SymbolTable = MergedGlobalSymtabBuf; |
1439 | // The size of the symbol offset to the member file is 8 bytes. |
1440 | StringTable = StringRef(SymbolTable.begin() + (SymNum + 1) * 8, |
1441 | SymtabInfos[0].StringTable.size() + |
1442 | SymtabInfos[1].StringTable.size()); |
1443 | } |
1444 | |
1445 | child_iterator I = child_begin(Err, SkipInternal: false); |
1446 | if (Err) |
1447 | return; |
1448 | child_iterator E = child_end(); |
1449 | if (I == E) { |
1450 | Err = Error::success(); |
1451 | return; |
1452 | } |
1453 | setFirstRegular(*I); |
1454 | Err = Error::success(); |
1455 | } |
1456 | |