LLVM: lib/Object/Archive.cpp Source File (original) (raw)
88 return reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
89}
90
93
95 const char *RawHeaderPtr,
99 if (RawHeaderPtr == nullptr)
100 return;
102
105 return;
106 }
107 if (ArMemHdr->Terminator[0] != '`' || ArMemHdr->Terminator[1] != '\n') {
108 if (Err) {
109 std::string Buf;
114 std::string Msg("terminator characters in archive member \"" + Buf +
115 "\" not the correct \"`\\n\" values for the archive "
116 "member header ");
118 if (!NameOrErr) {
122 } else
124 }
125 return;
126 }
127}
128
130 const char *RawHeaderPtr,
134 if (RawHeaderPtr == nullptr)
135 return;
137
138 if (RawHeaderPtr + getSizeOf() >= Parent->getData().end()) {
139 if (Err)
140 *Err = malformedError("malformed AIX big archive: remaining buffer is "
141 "unable to contain next archive member");
142 return;
143 }
144
147 if (Err)
148 *Err = std::move(SubErr);
149 }
150}
151
152
153
155 char EndCond;
158 if (ArMemHdr->Name[0] == ' ') {
160 reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
161 return malformedError("name contains a leading space for archive member "
162 "header at offset " +
164 }
165 EndCond = ' ';
166 } else if (ArMemHdr->Name[0] == '/' || ArMemHdr->Name[0] == '#')
167 EndCond = ' ';
168 else
169 EndCond = '/';
173 end = sizeof(ArMemHdr->Name);
175
177}
178
187 " field in archive member header are not "
188 "all decimal numbers: '" +
189 RawField +
190 "' for the archive "
191 "member header at offset " +
193 }
195}
196
197Expected<uint64_t>
205 " field in archive member header are not "
206 "all octal numbers: '" +
207 RawField +
208 "' for the archive "
209 "member header at offset " +
211 }
213}
214
218 if (!NameLenOrErr)
219
222
223
224
226 StringRef NameTerminator = "`\n";
227 StringRef NameStringWithNameTerminator =
229 if (!NameStringWithNameTerminator.ends_with(NameTerminator)) {
231 reinterpret_cast<const char *>(ArMemHdr->Name + NameLenWithPadding) -
232 Parent->getData().data();
233
235 "name does not have name terminator \"`\\n\" for archive member"
236 "header at offset " +
238 }
240}
241
242
243
245
246
247
248
251 reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
252 return malformedError("archive header truncated before the name field "
253 "for archive member header at offset " +
254 Twine(ArchiveOffset));
255 }
256
257
259 if (!NameOrErr)
262
263
264 if (Name[0] == '/') {
265 if (Name.size() == 1)
266 return Name;
267 if (Name.size() == 2 && Name[1] == '/')
268 return Name;
269
270
271 if (Name == "//")
272 return Name;
273
274
275 if (Name == "//")
276 return Name;
277
278
279 std::size_t StringOffset;
280 if (Name.substr(1).rtrim(' ').getAsInteger(10, StringOffset)) {
281 std::string Buf;
286 reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
287 return malformedError("long name offset characters after the '/' are "
288 "not all decimal numbers: '" +
289 Buf + "' for archive member header at offset " +
290 Twine(ArchiveOffset));
291 }
292
293
294 if (StringOffset >= Parent->getStringTable().size()) {
296 reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
298 " past the end of the string table for archive "
299 "member header at offset " +
300 Twine(ArchiveOffset));
301 }
302
303
306 size_t End = Parent->getStringTable().find('\n', StringOffset);
308 Parent->getStringTable()[End - 1] != '/') {
309 return malformedError("string table at long name offset " +
310 Twine(StringOffset) + " not terminated");
311 }
312 return Parent->getStringTable().slice(StringOffset, End - 1);
313 }
314 return Parent->getStringTable().begin() + StringOffset;
315 }
316
317 if (Name.starts_with("#1/")) {
319 if (Name.substr(3).rtrim(' ').getAsInteger(10, NameLength)) {
320 std::string Buf;
325 reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
326 return malformedError("long name length characters after the #1/ are "
327 "not all decimal numbers: '" +
328 Buf + "' for archive member header at offset " +
329 Twine(ArchiveOffset));
330 }
333 reinterpret_cast<const char *>(ArMemHdr) - Parent->getData().data();
335 " extends past the end of the member or archive "
336 "for archive member header at offset " +
337 Twine(ArchiveOffset));
338 }
340 NameLength)
342 }
343
344
345 if (Name[Name.size() - 1] != '/')
346 return Name.rtrim(' ');
347
348
349 return Name.drop_back(1);
350}
351
355
360
364 if (!SizeOrErr)
366
368 if (!NameLenOrErr)
370
371 return *SizeOrErr + alignTo(*NameLenOrErr, 2);
372}
373
378
383
387 if (!AccessModeOrErr)
388 return AccessModeOrErr.takeError();
389 return static_cast<sys::fs::perms>(*AccessModeOrErr);
390}
391
396
397 if (!SecondsOrErr)
399
401}
402
405 if (User.empty())
406 return 0;
408}
409
412 if (Group.empty())
413 return 0;
415}
416
419 if (!NameOrErr)
422 return Parent->isThin() && Name != "/" && Name != "//" && Name != "/SYM64/";
423}
424
428 if (!isThinOrErr)
430
434 if (!MemberSize)
436
438 }
439
440
441 const char *NextLoc =
443
444 if (NextLoc == Parent->getMemoryBufferRef().getBufferEnd())
445 return nullptr;
446
447 return NextLoc;
448}
449
452 static_cast<const BigArchive *>(Parent)->getLastChildOffset())
453 return nullptr;
454
456 if (!NextOffsetOrErr)
457 return NextOffsetOrErr.takeError();
458 return Parent->getData().data() + NextOffsetOrErr.get();
459}
460
463 : Parent(Parent), Data(Data), StartOfFile(StartOfFile) {
464 Header = Parent->createArchiveMemberHeader(Data.data(), Data.size(), nullptr);
465}
466
468 : Parent(Parent) {
469 if (!Start) {
470 Header = nullptr;
471 StartOfFile = -1;
472 return;
473 }
474
475 Header = Parent->createArchiveMemberHeader(
476 Start, Parent->getData().size() - (Start - Parent->getData().data()),
477 Err);
478
479
480
481
482
483 assert(Err && "Err can't be nullptr if Start is not a nullptr");
484
486
487
488
489 if (*Err)
490 return;
491
495 if (!isThinOrErr) {
497 return;
498 }
502 if (!MemberSize) {
504 return;
505 }
508 }
509
510
511 StartOfFile = Header->getSizeOf();
512
514 if (!NameOrErr) {
516 return;
517 }
519
521
522
523 StartOfFile += ((Name.size() + 1) >> 1) << 1;
524 } else if (Name.starts_with("#1/")) {
526 StringRef RawNameSize = Name.substr(3).rtrim(' ');
529 *Err = malformedError("long name length characters after the #1/ are "
530 "not all decimal numbers: '" +
531 RawNameSize +
532 "' for archive member header at offset " +
534 return;
535 }
537 }
538}
539
541 if (Parent->IsThin)
542 return Header->getSize();
543 return Data.size() - StartOfFile;
544}
545
547 return Header->getSize();
548}
549
550Expected Archive::Child::isThinMember() const { return Header->isThin(); }
551
555 return isThin.takeError();
558 if (!NameOrErr)
562 return std::string(Name);
563
565 Parent->getMemoryBufferRef().getBufferIdentifier());
567 return std::string(FullName);
568}
569
572 if (!isThinOrErr)
578 return Size.takeError();
579 return StringRef(Data.data() + StartOfFile, Size.get());
580 }
582 if (!FullNameOrErr)
583 return FullNameOrErr.takeError();
584 const std::string &FullName = *FullNameOrErr;
587 if (std::error_code EC = Buf.getError())
589 Parent->ThinBuffers.push_back(std::move(*Buf));
590 return Parent->ThinBuffers.back()->getBuffer();
591}
592
595 if (!NextLocOrErr)
597
598 const char *NextLoc = *NextLocOrErr;
599
600
601 if (NextLoc == nullptr)
602 return Child(nullptr, nullptr, nullptr);
603
604
605 if (NextLoc > Parent->Data.getBufferEnd()) {
606 std::string Msg("offset to next archive member past the end of the archive "
607 "after member ");
609 if (!NameOrErr) {
611 uint64_t Offset = Data.data() - Parent->getData().data();
613 } else
615 }
616
618 Child Ret(Parent, NextLoc, &Err);
619 if (Err)
620 return std::move(Err);
621 return Ret;
622}
623
625 const char *a = Parent->Data.getBuffer().data();
626 const char *c = Data.data();
628 return offset;
629}
630
633 if (!RawSizeOrErr)
637 Header->getName(Header->getSizeOf() + RawSize);
638 if (!NameOrErr)
641 return Name;
642}
643
646 if (!NameOrErr)
650 if (!Buf)
653}
654
658 if (!BuffOrErr)
660
661 auto BinaryOrErr = createBinary(BuffOrErr.get(), Context);
662 if (BinaryOrErr)
663 return std::move(*BinaryOrErr);
664 return BinaryOrErr.takeError();
665}
666
669 std::unique_ptr Ret;
670 StringRef Buffer = Source.getBuffer();
671
673 Ret = std::make_unique(Source, Err);
674 else
675 Ret = std::make_unique(Source, Err);
676
677 if (Err)
678 return std::move(Err);
679 return std::move(Ret);
680}
681
682std::unique_ptr
684 Error *Err) const {
687 return std::make_unique(this, RawHeaderPtr, Size, Err);
688 return std::make_unique(this, RawHeaderPtr, Size,
689 Err);
690}
691
701
703 FirstRegularData = C.Data;
704 FirstRegularStartOfFile = C.StartOfFile;
705}
706
711
713 IsThin = true;
715 IsThin = false;
718 IsThin = false;
719 return;
720 } else {
723 return;
724 }
725
726
727
728
729
730
732
733
735 if (Err)
736 return;
738
739
740 if (I == E) {
742 return;
743 }
745
747 ++I;
748 if (Err)
749 return true;
751 return false;
752 };
753
755 if (!NameOrErr) {
757 return;
758 }
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780 if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") {
781 if (Name == "__.SYMDEF")
783 else
785
786
788 if (!BufOrErr) {
790 return;
791 }
794 return;
796
798 return;
799 }
800
801 if (Name.starts_with("#1/")) {
803
805 if (!NameOrErr) {
807 return;
808 }
809 Name = NameOrErr.get();
810 if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
811
812
814 if (!BufOrErr) {
816 return;
817 }
820 return;
821 } else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") {
823
824
826 if (!BufOrErr) {
828 return;
829 }
832 return;
833 }
835 return;
836 }
837
838
839
840
841
842
843 bool has64SymTable = false;
844 if (Name == "/" || Name == "/SYM64/") {
845
846
848 if (!BufOrErr) {
850 return;
851 }
853 if (Name == "/SYM64/")
854 has64SymTable = true;
855
857 return;
858 if (I == E) {
860 return;
861 }
863 if (!NameOrErr) {
865 return;
866 }
867 Name = NameOrErr.get();
868 }
869
870 if (Name == "//") {
872
873
875 if (!BufOrErr) {
877 return;
878 }
881 return;
884 return;
885 }
886
887 if (Name[0] != '/') {
891 return;
892 }
893
894 if (Name != "/") {
896 return;
897 }
898
900
901
903 if (!BufOrErr) {
905 return;
906 }
908
910 return;
911
912 if (I == E) {
915 return;
916 }
917
918 NameOrErr = C->getRawName();
919 if (!NameOrErr) {
921 return;
922 }
923 Name = NameOrErr.get();
924
925 if (Name == "//") {
926
927
929 if (!BufOrErr) {
931 return;
932 }
935 return;
936
937 if (I == E) {
940 return;
941 }
942
943 NameOrErr = C->getRawName();
944 if (!NameOrErr) {
946 return;
947 }
948 Name = NameOrErr.get();
949 }
950
951 if (Name == "//") {
952
953
954
955
957 if (!BufOrErr) {
959 return;
960 }
963 return;
964 }
965
968}
969
971 if (T.isOSDarwin())
973 if (T.isOSAIX())
975 if (T.isOSWindows())
978}
979
984
986 bool SkipInternal) const {
989
990 if (SkipInternal)
992 Child(this, FirstRegularData, FirstRegularStartOfFile), Err);
993
996 if (Err)
999}
1000
1004
1006
1007
1008 uint32_t SymbolCount = Parent->getNumberOfSymbols();
1009 return SymbolCount <= SymbolIndex &&
1010 SymbolIndex < SymbolCount + Parent->getNumberOfECSymbols();
1011}
1012
1015 return Parent->ECSymbolTable.begin() + StringIndex;
1016 return Parent->getSymbolTable().begin() + StringIndex;
1017}
1018
1020 const char *Buf = Parent->getSymbolTable().begin();
1021 const char *Offsets = Buf;
1022 if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64 ||
1024 Offsets += sizeof(uint64_t);
1025 else
1026 Offsets += sizeof(uint32_t);
1028 if (Parent->kind() == K_GNU) {
1030 } else if (Parent->kind() == K_GNU64 || Parent->kind() == K_AIXBIG) {
1032 } else if (Parent->kind() == K_BSD) {
1033
1034
1035
1036
1037
1038
1040 } else if (Parent->kind() == K_DARWIN64) {
1041
1042
1043
1044
1045
1046
1048 } else {
1049
1051 Buf += MemberCount * 4 + 4;
1052
1055 if (SymbolIndex < SymbolCount) {
1056
1057 const char *Indices = Buf + 4;
1058
1059
1060
1061 OffsetIndex = read16le(Indices + SymbolIndex * 2);
1063
1064 const char *Indices = Parent->ECSymbolTable.begin() + 4;
1065
1066
1067
1068 OffsetIndex = read16le(Indices + (SymbolIndex - SymbolCount) * 2);
1069 } else {
1071 }
1072
1073 --OffsetIndex;
1074
1075 if (OffsetIndex >= MemberCount)
1077
1079 }
1080
1081 const char *Loc = Parent->getData().begin() + Offset;
1084 if (Err)
1085 return std::move(Err);
1086 return C;
1087}
1088
1091 if (Parent->kind() == K_BSD) {
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 const char *Buf = Parent->getSymbolTable().begin();
1107 RanlibCount = read32le(Buf) / 8;
1108
1109
1110
1111 if (t.SymbolIndex + 1 < RanlibCount) {
1112 const char *Ranlibs = Buf + 4;
1115 CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8);
1116 NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8);
1117 t.StringIndex -= CurRanStrx;
1118 t.StringIndex += NextRanStrx;
1119 }
1121
1122 t.StringIndex = Parent->ECSymbolTable.find('\0', t.StringIndex) + 1;
1123 } else {
1124
1125 t.StringIndex = Parent->getSymbolTable().find('\0', t.StringIndex) + 1;
1126 }
1127 ++t.SymbolIndex;
1128 return t;
1129}
1130
1134
1138 symbol_count = read32be(buf);
1139 buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
1142 buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));
1144
1145
1146
1147
1148
1149
1151 ranlib_count = read32le(buf) / 8;
1152 const char *ranlibs = buf + 4;
1154 ran_strx = read32le(ranlibs);
1155 buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t))));
1156
1158 buf += ran_strx;
1160
1161
1162
1163
1164
1165
1167 ranlib_count = read64le(buf) / 16;
1168 const char *ranlibs = buf + 8;
1170 ran_strx = read64le(ranlibs);
1171 buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t))));
1172
1174 buf += ran_strx;
1177 } else {
1180 member_count = read32le(buf);
1181 buf += 4 + (member_count * 4);
1182 symbol_count = read32le(buf);
1183 buf += 4 + (symbol_count * 2);
1184 }
1187}
1188
1192
1195
1196
1204
1208 return malformedError("invalid EC symbols size. Size was " +
1210 Twine(StringIndex));
1211
1214
1217 if (!Index)
1219 if (Index > MemberCount)
1221 " is larger than member count " +
1222 Twine(MemberCount));
1223
1224 StringIndex = ECSymbolTable.find('\0', StringIndex);
1226 return malformedError("malformed EC symbol names: not null-terminated");
1227 ++StringIndex;
1228 }
1229 }
1230
1236}
1237
1240 return 0;
1251 member_count = read32le(buf);
1252 buf += 4 + (member_count * 4);
1254}
1255
1261
1265
1266 for (; bs != es; ++bs) {
1268 if (SymName == name) {
1269 if (auto MemberOrErr = bs->getMember())
1270 return Child(*MemberOrErr);
1271 else
1272 return MemberOrErr.takeError();
1273 }
1274 }
1275 return std::nullopt;
1276}
1277
1278
1282
1284
1286 uint64_t GlobalSymtabOffset,
1287 const char *&GlobalSymtabLoc,
1290 uint64_t GlobalSymtabContentOffset =
1292 if (GlobalSymtabContentOffset > BufferSize)
1294 Twine(BitMessage) + " global symbol table header at offset 0x" +
1297 " goes past the end of file");
1298
1299 GlobalSymtabLoc = Data.getBufferStart() + GlobalSymtabOffset;
1301 reinterpret_cast<const BigArMemHdrType *>(GlobalSymtabLoc);
1304 return malformedError(Twine(BitMessage) + " global symbol table size \"" +
1305 RawOffset + "\" is not a number");
1306
1307 if (GlobalSymtabContentOffset + Size > BufferSize)
1309 Twine(BitMessage) + " global symbol table content at offset 0x" +
1310 Twine::utohexstr(GlobalSymtabContentOffset) + " and size 0x" +
1312
1314}
1315
1322
1323static void
1325 const char *GlobalSymtabLoc, uint64_t Size) {
1326
1327
1328
1329
1330
1331
1332
1337 unsigned SymOffsetsSize = 8 * (SymNum + 1);
1338 uint64_t SymbolTableStringSize = Size - SymOffsetsSize;
1342}
1343
1345 : Archive(Source, Err) {
1350
1351 if (BufferSize < sizeof(FixLenHdr)) {
1352 Err = malformedError("malformed AIX big archive: incomplete fixed length "
1353 "header, the archive is only" +
1354 Twine(BufferSize) + " byte(s)");
1355 return;
1356 }
1357
1360
1361 Err = malformedError("malformed AIX big archive: first member offset \"" +
1362 RawOffset + "\" is not a number");
1363
1366
1367 Err = malformedError("malformed AIX big archive: last member offset \"" +
1368 RawOffset + "\" is not a number");
1369
1370 uint64_t GlobSymtab32Offset = 0;
1372 if (RawOffset.getAsInteger(10, GlobSymtab32Offset)) {
1374 "offset of 32-bit members \"" +
1375 RawOffset + "\" is not a number");
1376 return;
1377 }
1378
1379 uint64_t GlobSymtab64Offset = 0;
1381 if (RawOffset.getAsInteger(10, GlobSymtab64Offset)) {
1383 "offset of 64-bit members\"" +
1384 RawOffset + "\" is not a number");
1385 return;
1386 }
1387
1388 const char *GlobSymtab32Loc = nullptr;
1389 const char *GlobSymtab64Loc = nullptr;
1390 uint64_t GlobSymtab32Size = 0;
1391 uint64_t GlobSymtab64Size = 0;
1393
1394 if (GlobSymtab32Offset) {
1395 Err =
1397 GlobSymtab32Loc, GlobSymtab32Size, "32-bit");
1398 if (Err)
1399 return;
1400
1402 }
1403
1404 if (GlobSymtab64Offset) {
1405 Err =
1407 GlobSymtab64Loc, GlobSymtab64Size, "64-bit");
1408 if (Err)
1409 return;
1410
1412 }
1413
1415
1416 if (GlobSymtab32Offset)
1418 if (GlobSymtab64Offset)
1420
1421 if (SymtabInfos.size() == 1) {
1422 SymbolTable = SymtabInfos[0].SymbolTable;
1423 StringTable = SymtabInfos[0].StringTable;
1424 } else if (SymtabInfos.size() == 2) {
1425
1426
1428 uint64_t SymNum = SymtabInfos[0].SymNum + SymtabInfos[1].SymNum;
1430
1431 Out << SymtabInfos[0].SymbolOffsetTable;
1432 Out << SymtabInfos[1].SymbolOffsetTable;
1433
1434 Out << SymtabInfos[0].StringTable;
1435 Out << SymtabInfos[1].StringTable;
1437
1439 SymtabInfos[0].StringTable.size() +
1440 SymtabInfos[1].StringTable.size());
1441 }
1442
1444 if (Err)
1445 return;
1447 if (I == E) {
1449 return;
1450 }
1453}