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

437 Size += MemberSize.get();

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 }

506 Size += MemberSize.get();

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;

750 C = &*I;

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}