clang: lib/InstallAPI/DylibVerifier.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

13#include "llvm/Demangle/Demangle.h"

14#include "llvm/TextAPI/DylibReader.h"

15

17

19namespace installapi {

20

21

23

24

26

27

29

30

32

33

35

36

38};

39

41

43

44

45 DylibReader::SymbolToSourceLocMap SourceLocs{};

46};

47

49

50 return (Name.starts_with("_Z") || Name.starts_with("__Z") ||

51 Name.starts_with("___Z"));

52}

53

54static std::string demangle(StringRef Name) {

55

57 return Name.str();

58 char *Result = llvm::itaniumDemangle(Name);

60 return Name.str();

61

62 std::string Demangled(Result);

64 return Demangled;

65}

66

67std::string DylibVerifier::getAnnotatedName(const Record *R,

68 SymbolContext &SymCtx,

69 bool ValidSourceLoc) {

70 assert(!SymCtx.SymbolName.empty() && "Expected symbol name");

71

72 const StringRef SymbolName = SymCtx.SymbolName;

73 std::string PrettyName =

74 (Demangle && (SymCtx.Kind == EncodeKind::GlobalSymbol))

76 : SymbolName.str();

77

78 std::string Annotation;

79 if (R->isWeakDefined())

80 Annotation += "(weak-def) ";

81 if (R->isWeakReferenced())

82 Annotation += "(weak-ref) ";

83 if (R->isThreadLocalValue())

84 Annotation += "(tlv) ";

85

86

87 switch (SymCtx.ObjCIFKind) {

88 default:

89 break;

90 case ObjCIFSymbolKind::EHType:

91 return Annotation + "Exception Type of " + PrettyName;

92 case ObjCIFSymbolKind::MetaClass:

93 return Annotation + "Metaclass of " + PrettyName;

94 case ObjCIFSymbolKind::Class:

95 return Annotation + "Class of " + PrettyName;

96 }

97

98

99

100

101 if (ValidSourceLoc) {

102 StringRef PrettyNameRef(PrettyName);

103 if ((SymCtx.Kind == EncodeKind::GlobalSymbol) &&

104 isCppMangled(SymbolName) && PrettyNameRef.starts_with("_"))

105 return Annotation + PrettyNameRef.drop_front(1).str();

106 return Annotation + PrettyName;

107 }

108

109 switch (SymCtx.Kind) {

110 case EncodeKind::GlobalSymbol:

111 return Annotation + PrettyName;

112 case EncodeKind::ObjectiveCInstanceVariable:

113 return Annotation + "(ObjC IVar) " + PrettyName;

114 case EncodeKind::ObjectiveCClass:

115 return Annotation + "(ObjC Class) " + PrettyName;

116 case EncodeKind::ObjectiveCClassEHType:

117 return Annotation + "(ObjC Class EH) " + PrettyName;

118 }

119

120 llvm_unreachable("unexpected case for EncodeKind");

121}

122

125 if (Prev == Curr)

126 return Prev;

127

128

131 return Prev;

132

133

136 return Prev;

137

138 return Curr;

139}

140

141

143 if (const FunctionDecl *FD = cast(D))

145 if (const VarDecl *VD = cast(D))

147

148 return false;

149}

150

153 switch (Kind) {

154 case EncodeKind::GlobalSymbol:

155 return Slice->findGlobal(Name);

156 case EncodeKind::ObjectiveCInstanceVariable:

157 return Slice->findObjCIVar(Name.contains('.'), Name);

158 case EncodeKind::ObjectiveCClass:

159 case EncodeKind::ObjectiveCClassEHType:

160 return Slice->findObjCInterface(Name);

161 }

162 llvm_unreachable("unexpected end when finding record");

163}

164

165void DylibVerifier::updateState(Result State) {

167}

168

169void DylibVerifier::addSymbol(const Record *R, SymbolContext &SymCtx,

171 if (Targets.empty())

172 Targets = {Ctx.Target};

173

174 Exports->addGlobal(SymCtx.Kind, SymCtx.SymbolName, R->getFlags(), Targets);

175}

176

177bool DylibVerifier::shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx,

179 if (!SymCtx.FA->Avail.isObsoleted())

180 return false;

181

182 if (Zippered)

183 DeferredZipperedSymbols[SymCtx.SymbolName].emplace_back(ZipperedDeclSource{

185 return true;

186}

187

188bool DylibVerifier::shouldIgnoreReexport(const Record *R,

189 SymbolContext &SymCtx) const {

190 StringRef SymName = SymCtx.SymbolName;

191

192 if (SymName.starts_with("$ld$"))

193 return false;

194

195 if (Reexports.empty())

196 return false;

197

199 if (!Lib.hasTarget(Ctx.Target))

200 continue;

201 if (auto Sym = Lib.getSymbol(SymCtx.Kind, SymName, SymCtx.ObjCIFKind))

202 if ((*Sym)->hasTarget(Ctx.Target))

203 return true;

204 }

205 return false;

206}

207

208bool DylibVerifier::shouldIgnoreInternalZipperedSymbol(

209 const Record *R, const SymbolContext &SymCtx) const {

210 if (!Zippered)

211 return false;

212

213 return Exports->findSymbol(SymCtx.Kind, SymCtx.SymbolName,

214 SymCtx.ObjCIFKind) != nullptr;

215}

216

217bool DylibVerifier::shouldIgnoreZipperedAvailability(const Record *R,

218 SymbolContext &SymCtx) {

219 if (!(Zippered && SymCtx.FA->Avail.isUnavailable()))

220 return false;

221

222

223

224 DeferredZipperedSymbols[SymCtx.SymbolName].emplace_back(

225 ZipperedDeclSource{SymCtx.FA, SourceManagers.back().get(), Ctx.Target});

226

227 return true;

228}

229

230bool DylibVerifier::compareObjCInterfaceSymbols(const Record *R,

231 SymbolContext &SymCtx,

233 const bool IsDeclVersionComplete =

234 ((SymCtx.ObjCIFKind & ObjCIFSymbolKind::Class) ==

235 ObjCIFSymbolKind::Class) &&

236 ((SymCtx.ObjCIFKind & ObjCIFSymbolKind::MetaClass) ==

237 ObjCIFSymbolKind::MetaClass);

238

239 const bool IsDylibVersionComplete = DR->isCompleteInterface();

240

241

242 if (IsDeclVersionComplete && IsDylibVersionComplete)

243 return true;

244

245 auto PrintDiagnostic = [&](auto SymLinkage, const Record *Record,

246 StringRef SymName, bool PrintAsWarning = false) {

247 if (SymLinkage == RecordLinkage::Unknown)

249 Ctx.Diag->Report(SymCtx.FA->Loc, PrintAsWarning

250 ? diag::warn_library_missing_symbol

251 : diag::err_library_missing_symbol)

252 << SymName;

253 });

254 else

256 Ctx.Diag->Report(SymCtx.FA->Loc, PrintAsWarning

257 ? diag::warn_library_hidden_symbol

258 : diag::err_library_hidden_symbol)

259 << SymName;

260 });

261 };

262

263 if (IsDeclVersionComplete) {

264

265

266

267 if (!DR->isExportedSymbol(ObjCIFSymbolKind::Class)) {

268 SymCtx.ObjCIFKind = ObjCIFSymbolKind::Class;

269 PrintDiagnostic(DR->getLinkageForSymbol(ObjCIFSymbolKind::Class), R,

270 getAnnotatedName(R, SymCtx),

271 true);

272 }

273 if (!DR->isExportedSymbol(ObjCIFSymbolKind::MetaClass)) {

274 SymCtx.ObjCIFKind = ObjCIFSymbolKind::MetaClass;

275 PrintDiagnostic(DR->getLinkageForSymbol(ObjCIFSymbolKind::MetaClass), R,

276 getAnnotatedName(R, SymCtx),

277 true);

278 }

279 return true;

280 }

281

282 if (DR->isExportedSymbol(SymCtx.ObjCIFKind)) {

283 if (!IsDylibVersionComplete) {

284

285 SymCtx.Kind = EncodeKind::GlobalSymbol;

286 SymCtx.SymbolName = R->getName();

287 }

288 return true;

289 }

290

291

292

293 PrintDiagnostic(DR->getLinkageForSymbol(SymCtx.ObjCIFKind), R,

294 SymCtx.SymbolName);

295 return false;

296}

297

299 SymbolContext &SymCtx,

301

302 if (R->isExported()) {

303 if (!DR) {

305 Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_library_missing_symbol)

306 << getAnnotatedName(R, SymCtx);

307 });

309 }

310 if (DR->isInternal()) {

312 Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_library_hidden_symbol)

313 << getAnnotatedName(R, SymCtx);

314 });

316 }

317 }

318

319

320

321 if ((R->isInternal() && !SymCtx.Inlined) && DR && DR->isExported()) {

322

325

328

329 if (shouldIgnoreInternalZipperedSymbol(R, SymCtx))

331

332 unsigned ID;

335 ID = diag::warn_header_hidden_symbol;

337 } else {

338 ID = diag::err_header_hidden_symbol;

340 }

342 Ctx.Diag->Report(SymCtx.FA->Loc, ID) << getAnnotatedName(R, SymCtx);

343 });

344 return Outcome;

345 }

346

347 if (R->isInternal())

349

351}

352

354 SymbolContext &SymCtx,

356 if (!SymCtx.FA->Avail.isUnavailable())

358

359 if (shouldIgnoreZipperedAvailability(R, SymCtx))

361

362 const bool IsDeclAvailable = SymCtx.FA->Avail.isUnavailable();

363

364 switch (Mode) {

367 Ctx.Diag->Report(SymCtx.FA->Loc, diag::warn_header_availability_mismatch)

368 << getAnnotatedName(R, SymCtx) << IsDeclAvailable << IsDeclAvailable;

369 });

373 Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_availability_mismatch)

374 << getAnnotatedName(R, SymCtx) << IsDeclAvailable << IsDeclAvailable;

375 });

380 llvm_unreachable("Unexpected verification mode symbol verification");

381 }

382 llvm_unreachable("Unexpected verification mode symbol verification");

383}

384

385bool DylibVerifier::compareSymbolFlags(const Record *R, SymbolContext &SymCtx,

387 if (DR->isThreadLocalValue() && !R->isThreadLocalValue()) {

389 Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_dylib_symbol_flags_mismatch)

390 << getAnnotatedName(DR, SymCtx) << DR->isThreadLocalValue();

391 });

392 return false;

393 }

394 if (!DR->isThreadLocalValue() && R->isThreadLocalValue()) {

396 Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_symbol_flags_mismatch)

397 << getAnnotatedName(R, SymCtx) << R->isThreadLocalValue();

398 });

399 return false;

400 }

401

402 if (DR->isWeakDefined() && !R->isWeakDefined()) {

404 Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_dylib_symbol_flags_mismatch)

405 << getAnnotatedName(DR, SymCtx) << R->isWeakDefined();

406 });

407 return false;

408 }

409 if (!DR->isWeakDefined() && R->isWeakDefined()) {

411 Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_symbol_flags_mismatch)

412 << getAnnotatedName(R, SymCtx) << R->isWeakDefined();

413 });

414 return false;

415 }

416

417 return true;

418}

419

421 SymbolContext &SymCtx) {

422 R->setVerify();

423 if (!canVerify()) {

424

425 if (R->isExported() && !SymCtx.FA->Avail.isUnavailable() &&

426 !SymCtx.FA->Avail.isObsoleted()) {

427 addSymbol(R, SymCtx);

428 }

430 }

431

432 if (shouldIgnoreReexport(R, SymCtx)) {

435 }

436

439 if (DR)

440 DR->setVerify();

441

442 if (shouldIgnoreObsolete(R, SymCtx, DR)) {

445 }

446

447

448 if (SymCtx.FA->Avail.isUnavailable() && (!DR || DR->isInternal())) {

451 }

452

453 Result VisibilityCheck = compareVisibility(R, SymCtx, DR);

455 updateState(VisibilityCheck);

457 }

458

459

460 if (!DR) {

463 }

464

465

466 if (SymCtx.ObjCIFKind != ObjCIFSymbolKind::None) {

467 if (!compareObjCInterfaceSymbols(

468 R, SymCtx, Ctx.DylibSlice->findObjCInterface(DR->getName()))) {

471 }

472 }

473

474 Result AvailabilityCheck = compareAvailability(R, SymCtx, DR);

476 updateState(AvailabilityCheck);

478 }

479

480 if (!compareSymbolFlags(R, SymCtx, DR)) {

483 }

484

485 addSymbol(R, SymCtx);

488}

489

490bool DylibVerifier::canVerify() {

492}

493

494void DylibVerifier::assignSlice(const Target &T) {

495 assert(T == Ctx.Target && "Active targets should match.");

496 if (Dylib.empty())

497 return;

498

499

500

501 auto It = find_if(

502 Dylib, [&T](const auto &Slice) { return T == Slice->getTarget(); });

503

504 assert(It != Dylib.end() && "Target slice should always exist.");

506}

507

511 if (Dylib.empty()) {

513 return;

514 }

516 assignSlice(T);

517}

518

521 if (!Ctx.Diag)

522 return;

523 SourceManagers.push_back(std::move(SourceMgr));

525}

526

529 const StringRef SuperClass) {

530 if (R->isVerified())

532

534 ObjCIVarRecord::createScopedName(SuperClass, R->getName());

536 return verifyImpl(R, SymCtx);

537}

538

541 if (R->getLinkageForSymbol(ObjCIFSymbolKind::Class) != RecordLinkage::Unknown)

542 Result |= ObjCIFSymbolKind::Class;

543 if (R->getLinkageForSymbol(ObjCIFSymbolKind::MetaClass) !=

544 RecordLinkage::Unknown)

545 Result |= ObjCIFSymbolKind::MetaClass;

546 if (R->getLinkageForSymbol(ObjCIFSymbolKind::EHType) !=

547 RecordLinkage::Unknown)

548 Result |= ObjCIFSymbolKind::EHType;

550}

551

554 if (R->isVerified())

559

560 SymCtx.Kind = R->hasExceptionAttribute() ? EncodeKind::ObjectiveCClassEHType

561 : EncodeKind::ObjectiveCClass;

562 SymCtx.FA = FA;

563

564 return verifyImpl(R, SymCtx);

565}

566

569 if (R->isVerified())

571

572

573 SimpleSymbol Sym = parseSymbol(R->getName());

576 SymCtx.Kind = Sym.Kind;

577 SymCtx.FA = FA;

578 SymCtx.Inlined = R->isInlined();

579 return verifyImpl(R, SymCtx);

580}

581

587 : getTargetTripleName(Target));

589 }

590 if (Loc && Loc->isValid())

591 llvm::errs() << Loc->File << ":" << Loc->Line << ":" << 0 << ": ";

592

594}

595

596

597

598

599

600

602 return (IsWeakDef &&

603 (Name.starts_with("__ZTI") || Name.starts_with("__ZTS")));

604}

605void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) {

606

607 if (R.isUndefined()) {

609 return;

610 }

611

612

613 if (R.isInternal()) {

615 return;

616 }

617

618

619

620 const StringRef SymbolName(SymCtx.SymbolName);

621 if (const Symbol *Sym = Exports->findSymbol(SymCtx.Kind, SymCtx.SymbolName,

622 SymCtx.ObjCIFKind)) {

623 if (Sym->hasArchitecture(Ctx.Target.Arch)) {

625 return;

626 }

627 }

628

629 const bool IsLinkerSymbol = SymbolName.starts_with("$ld$");

630

631 if (R.isVerified()) {

632

633

634

635 auto It = DeferredZipperedSymbols.find(SymCtx.SymbolName);

636 if (It == DeferredZipperedSymbols.end()) {

638 return;

639 }

640

642 for (const ZipperedDeclSource &ZSource : It->second) {

643 if (ZSource.FA->Avail.isObsoleted()) {

645 return;

646 }

647 if (ZSource.T.Arch != Ctx.Target.Arch)

648 continue;

649 Locs.emplace_back(ZSource);

650 }

651 assert(Locs.size() == 2 && "Expected two decls for zippered symbol");

652

653

654 for (const ZipperedDeclSource &ZSource : Locs) {

655 unsigned DiagID = 0;

658 DiagID = diag::err_header_availability_mismatch;

661 DiagID = diag::warn_header_availability_mismatch;

662 } else {

664 return;

665 }

666

668 Ctx.Diag->Report(diag::warn_target) << getTargetTripleName(ZSource.T);

669 Ctx.Diag->Report(ZSource.FA->Loc, DiagID)

670 << getAnnotatedName(&R, SymCtx) << ZSource.FA->Avail.isUnavailable()

671 << ZSource.FA->Avail.isUnavailable();

672 }

673 return;

674 }

675

678 return;

679 }

680

681 if (Aliases.count({SymbolName.str(), SymCtx.Kind})) {

683 return;

684 }

685

686

687

688

690 accumulateSrcLocForDylibSymbols();

692

693

694

695 if (IsLinkerSymbol) {

697 [&]() {

698 Ctx.Diag->Report(diag::err_header_symbol_missing)

699 << getAnnotatedName(&R, SymCtx, Loc.isValid());

700 },

703 return;

704 }

705

706

709 [&]() {

710 Ctx.Diag->Report(diag::err_header_symbol_missing)

711 << getAnnotatedName(&R, SymCtx, Loc.isValid());

712 },

715 return;

716 }

717

718

719

722 [&]() {

723 Ctx.Diag->Report(diag::warn_header_symbol_missing)

724 << getAnnotatedName(&R, SymCtx, Loc.isValid());

725 },

728 return;

729 }

730

731

732

734 return;

735}

736

737void DylibVerifier::visitGlobal(const GlobalRecord &R) {

738 SymbolContext SymCtx;

740 SymCtx.SymbolName = Sym.Name;

741 SymCtx.Kind = Sym.Kind;

742 visitSymbolInDylib(R, SymCtx);

743}

744

745void DylibVerifier::visitObjCIVar(const ObjCIVarRecord &R,

746 const StringRef Super) {

747 SymbolContext SymCtx;

748 SymCtx.SymbolName = ObjCIVarRecord::createScopedName(Super, R.getName());

749 SymCtx.Kind = EncodeKind::ObjectiveCInstanceVariable;

750 visitSymbolInDylib(R, SymCtx);

751}

752

753void DylibVerifier::accumulateSrcLocForDylibSymbols() {

754 if (DSYMPath.empty())

755 return;

756

757 assert(DWARFCtx != nullptr && "Expected an initialized DWARFContext");

759 return;

762 DylibReader::accumulateSourceLocFromDSYM(DSYMPath, Ctx.Target);

763}

764

766 SymbolContext SymCtx;

767 SymCtx.SymbolName = R.getName();

769 if (SymCtx.ObjCIFKind > ObjCIFSymbolKind::EHType) {

770 if (R.hasExceptionAttribute()) {

771 SymCtx.Kind = EncodeKind::ObjectiveCClassEHType;

772 visitSymbolInDylib(R, SymCtx);

773 }

774 SymCtx.Kind = EncodeKind::ObjectiveCClass;

775 visitSymbolInDylib(R, SymCtx);

776 } else {

777 SymCtx.Kind = R.hasExceptionAttribute() ? EncodeKind::ObjectiveCClassEHType

778 : EncodeKind::ObjectiveCClass;

779 visitSymbolInDylib(R, SymCtx);

780 }

781

783 visitObjCIVar(*IV, R.getName());

784}

785

788 visitObjCIVar(*IV, R.getSuperClassName());

789}

790

794 assert(!Dylib.empty() && "No binary to verify against");

795

797 DWARFCtx = &DWARFInfo;

798 Ctx.Target = Target(Architecture::AK_unknown, PlatformType::PLATFORM_UNKNOWN);

799 for (std::shared_ptr Slice : Dylib) {

800 if (Ctx.Target.Arch == Slice->getTarget().Arch)

801 continue;

804 Ctx.Target = Slice->getTarget();

806 Slice->visit(*this);

807 }

809}

810

813 const LibAttrs &ProvidedReexports,

814 const LibAttrs &ProvidedClients,

815 const LibAttrs &ProvidedRPaths,

817 assert(!Dylib.empty() && "Need dylib to verify.");

818

819

824 for (const std::shared_ptr &RS : Dylib) {

825 DylibTargets.push_back(RS->getTarget());

826 const BinaryAttrs &BinInfo = RS->getBinaryAttrs();

827 for (const StringRef LibName : BinInfo.RexportedLibraries)

828 DylibReexports[LibName].set(DylibTargets.back().Arch);

829 for (const StringRef LibName : BinInfo.AllowableClients)

830 DylibClients[LibName].set(DylibTargets.back().Arch);

831

832 if (FT >= FileType::TBD_V5)

833 for (const StringRef Name : BinInfo.RPaths)

834 DylibRPaths[Name].set(DylibTargets.back().Arch);

835 }

836

837

838 ArchitectureSet ProvidedArchs = mapToArchitectureSet(ProvidedTargets);

839 ArchitectureSet DylibArchs = mapToArchitectureSet(DylibTargets);

840 if (ProvidedArchs != DylibArchs) {

841 Ctx.Diag->Report(diag::err_architecture_mismatch)

842 << ProvidedArchs << DylibArchs;

843 return false;

844 }

845 auto ProvidedPlatforms = mapToPlatformVersionSet(ProvidedTargets);

846 auto DylibPlatforms = mapToPlatformVersionSet(DylibTargets);

847 if (ProvidedPlatforms != DylibPlatforms) {

848 const bool DiffMinOS =

849 mapToPlatformSet(ProvidedTargets) == mapToPlatformSet(DylibTargets);

850 if (DiffMinOS)

851 Ctx.Diag->Report(diag::warn_platform_mismatch)

852 << ProvidedPlatforms << DylibPlatforms;

853 else {

854 Ctx.Diag->Report(diag::err_platform_mismatch)

855 << ProvidedPlatforms << DylibPlatforms;

856 return false;

857 }

858 }

859

860

861

862 const BinaryAttrs &DylibBA = (*Dylib.begin())->getBinaryAttrs();

863

864 if (ProvidedBA.InstallName != DylibBA.InstallName) {

865 Ctx.Diag->Report(diag::err_install_name_mismatch)

866 << ProvidedBA.InstallName << DylibBA.InstallName;

867 return false;

868 }

869

870 if (ProvidedBA.CurrentVersion != DylibBA.CurrentVersion) {

871 Ctx.Diag->Report(diag::err_current_version_mismatch)

872 << ProvidedBA.CurrentVersion << DylibBA.CurrentVersion;

873 return false;

874 }

875

876 if (ProvidedBA.CompatVersion != DylibBA.CompatVersion) {

877 Ctx.Diag->Report(diag::err_compatibility_version_mismatch)

878 << ProvidedBA.CompatVersion << DylibBA.CompatVersion;

879 return false;

880 }

881

882 if (ProvidedBA.AppExtensionSafe != DylibBA.AppExtensionSafe) {

883 Ctx.Diag->Report(diag::err_appextension_safe_mismatch)

884 << (ProvidedBA.AppExtensionSafe ? "true" : "false")

885 << (DylibBA.AppExtensionSafe ? "true" : "false");

886 return false;

887 }

888

889 if (!DylibBA.TwoLevelNamespace) {

890 Ctx.Diag->Report(diag::err_no_twolevel_namespace);

891 return false;

892 }

893

894 if (ProvidedBA.OSLibNotForSharedCache != DylibBA.OSLibNotForSharedCache) {

895 Ctx.Diag->Report(diag::err_shared_cache_eligiblity_mismatch)

896 << (ProvidedBA.OSLibNotForSharedCache ? "true" : "false")

897 << (DylibBA.OSLibNotForSharedCache ? "true" : "false");

898 return false;

899 }

900

901 if (ProvidedBA.ParentUmbrella.empty() && !DylibBA.ParentUmbrella.empty()) {

902 Ctx.Diag->Report(diag::err_parent_umbrella_missing)

903 << "installAPI option" << DylibBA.ParentUmbrella;

904 return false;

905 }

906

907 if (!ProvidedBA.ParentUmbrella.empty() && DylibBA.ParentUmbrella.empty()) {

908 Ctx.Diag->Report(diag::err_parent_umbrella_missing)

909 << "binary file" << ProvidedBA.ParentUmbrella;

910 return false;

911 }

912

913 if ((!ProvidedBA.ParentUmbrella.empty()) &&

914 (ProvidedBA.ParentUmbrella != DylibBA.ParentUmbrella)) {

915 Ctx.Diag->Report(diag::err_parent_umbrella_mismatch)

916 << ProvidedBA.ParentUmbrella << DylibBA.ParentUmbrella;

917 return false;

918 }

919

920 auto CompareLibraries = [&](const LibAttrs &Provided, const LibAttrs &Dylib,

921 unsigned DiagID_missing, unsigned DiagID_mismatch,

922 bool Fatal = true) {

923 if (Provided == Dylib)

924 return true;

925

926 for (const llvm::StringMapEntry &PAttr : Provided) {

927 const auto DAttrIt = Dylib.find(PAttr.getKey());

928 if (DAttrIt == Dylib.end()) {

929 Ctx.Diag->Report(DiagID_missing) << "binary file" << PAttr;

930 if (Fatal)

931 return false;

932 }

933

934 if (PAttr.getValue() != DAttrIt->getValue()) {

935 Ctx.Diag->Report(DiagID_mismatch) << PAttr << *DAttrIt;

936 if (Fatal)

937 return false;

938 }

939 }

940

941 for (const llvm::StringMapEntry &DAttr : Dylib) {

942 const auto PAttrIt = Provided.find(DAttr.getKey());

943 if (PAttrIt == Provided.end()) {

944 Ctx.Diag->Report(DiagID_missing) << "installAPI option" << DAttr;

945 if (!Fatal)

946 continue;

947 return false;

948 }

949

950 if (PAttrIt->getValue() != DAttr.getValue()) {

951 if (Fatal)

952 llvm_unreachable("this case was already covered above.");

953 }

954 }

955 return true;

956 };

957

958 if (!CompareLibraries(ProvidedReexports, DylibReexports,

959 diag::err_reexported_libraries_missing,

960 diag::err_reexported_libraries_mismatch))

961 return false;

962

963 if (!CompareLibraries(ProvidedClients, DylibClients,

964 diag::err_allowable_clients_missing,

965 diag::err_allowable_clients_mismatch))

966 return false;

967

968 if (FT >= FileType::TBD_V5) {

969

970

971

972

973 if (!ProvidedBA.InstallName.ends_with("_asan")) {

974 if (!CompareLibraries(ProvidedRPaths, DylibRPaths,

975 diag::warn_rpaths_missing,

976 diag::warn_rpaths_mismatch,

977 false))

978 return true;

979 }

980 }

981

982 return true;

983}

984

986 for (const auto &[Alias, Base] : Aliases) {

989 if (const Symbol *Sym = Exports->findSymbol(Base.second, Base.first)) {

990 Flags = Sym->getFlags();

991 Targets = {Sym->targets().begin(), Sym->targets().end()};

992 }

993

994 Record R(Alias.first, RecordLinkage::Exported, Flags);

997 SymCtx.Kind = Alias.second;

998 addSymbol(&R, SymCtx, std::move(Targets));

999 }

1000

1001 return std::move(Exports);

1002}

1003

1004}

1005}

llvm::MachO::ObjCIVarRecord ObjCIVarRecord

llvm::MachO::SymbolFlags SymbolFlags

llvm::MachO::RecordLoc RecordLoc

llvm::MachO::InterfaceFile InterfaceFile

llvm::MachO::ObjCCategoryRecord ObjCCategoryRecord

llvm::MachO::GlobalRecord GlobalRecord

llvm::MachO::ArchitectureSet ArchitectureSet

llvm::MachO::EncodeKind EncodeKind

llvm::MachO::ObjCInterfaceRecord ObjCInterfaceRecord

llvm::MachO::ObjCIFSymbolKind ObjCIFSymbolKind

llvm::MachO::FileType FileType

llvm::MachO::Target Target

llvm::MachO::RecordsSlice::BinaryAttrs BinaryAttrs

llvm::MachO::Record Record

llvm::MachO::TargetList TargetList

llvm::MachO::SimpleSymbol SimpleSymbol

Decl - This represents one declaration (or definition), e.g.

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

void setSourceManager(SourceManager *SrcMgr)

SourceManager & getSourceManager() const

Represents a function declaration or definition.

Represents a variable declaration or definition.

Result verify(GlobalRecord *R, const FrontendAttrs *FA)

Result getState() const

Get result of verification.

void setSourceManager(IntrusiveRefCntPtr< SourceManager > SourceMgr)

Set different source managers to the same diagnostics engine.

std::unique_ptr< SymbolSet > takeExports()

Release ownership over exports.

bool verifyBinaryAttrs(const ArrayRef< Target > ProvidedTargets, const BinaryAttrs &ProvidedBA, const LibAttrs &ProvidedReexports, const LibAttrs &ProvidedClients, const LibAttrs &ProvidedRPaths, const FileType &FT)

Compare and report the attributes represented as load commands in the dylib to the attributes provide...

void setTarget(const Target &T)

Initialize target for verification.

Result verifyRemainingSymbols()

Record * findRecordFromSlice(const RecordsSlice *Slice, StringRef Name, EncodeKind Kind)

llvm::StringMap< ArchitectureSet > LibAttrs

static bool isCppMangled(StringRef Name)

static std::string demangle(StringRef Name)

static DylibVerifier::Result updateResult(const DylibVerifier::Result Prev, const DylibVerifier::Result Curr)

static ObjCIFSymbolKind assignObjCIFSymbolKind(const ObjCInterfaceRecord *R)

static bool shouldIgnorePrivateExternAttr(const Decl *D)

std::vector< ZipperedDeclSource > ZipperedDeclSources

static bool shouldIgnoreCpp(StringRef Name, bool IsWeakDef)

The JSON file list parser is used to communicate input to InstallAPI.

@ Result

The result type of a method or function.

const FunctionProtoType * T

DylibReader::SymbolToSourceLocMap SourceLocs

Metadata stored about a mapping of a declaration to a symbol.

ObjCIFSymbolKind ObjCIFKind

bool DiscoveredFirstError

void emitDiag(llvm::function_ref< void()> Report, RecordLoc *Loc=nullptr)

RecordsSlice * DylibSlice

llvm::MachO::Target Target

Frontend information captured about records.