1 //===- InstallAPI/DylibVerifier.h -------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_INSTALLAPI_DYLIBVERIFIER_H 10 #define LLVM_CLANG_INSTALLAPI_DYLIBVERIFIER_H 11 12 #include "clang/Basic/Diagnostic.h" 13 #include "clang/Basic/SourceManager.h" 14 #include "clang/InstallAPI/MachO.h" 15 16 namespace clang { 17 namespace installapi { 18 struct FrontendAttrs; 19 20 /// A list of InstallAPI verification modes. 21 enum class VerificationMode { 22 Invalid, 23 ErrorsOnly, 24 ErrorsAndWarnings, 25 Pedantic, 26 }; 27 28 using LibAttrs = llvm::StringMap<ArchitectureSet>; 29 using ReexportedInterfaces = llvm::SmallVector<llvm::MachO::InterfaceFile, 8>; 30 31 // Pointers to information about a zippered declaration used for 32 // querying and reporting violations against different 33 // declarations that all map to the same symbol. 34 struct ZipperedDeclSource { 35 const FrontendAttrs *FA; 36 clang::SourceManager *SrcMgr; 37 Target T; 38 }; 39 using ZipperedDeclSources = std::vector<ZipperedDeclSource>; 40 41 /// Service responsible to tracking state of verification across the 42 /// lifetime of InstallAPI. 43 /// As declarations are collected during AST traversal, they are 44 /// compared as symbols against what is available in the binary dylib. 45 class DylibVerifier : llvm::MachO::RecordVisitor { 46 private: 47 struct SymbolContext; 48 struct DWARFContext; 49 50 public: 51 enum class Result { NoVerify, Ignore, Valid, Invalid }; 52 struct VerifierContext { 53 // Current target being verified against the AST. 54 llvm::MachO::Target Target; 55 56 // Target specific API from binary. 57 RecordsSlice *DylibSlice = nullptr; 58 59 // Query state of verification after AST has been traversed. 60 Result FrontendState = Result::Ignore; 61 62 // First error for AST traversal, which is tied to the target triple. 63 bool DiscoveredFirstError = false; 64 65 // Determines what kind of banner to print a violation for. 66 bool PrintArch = false; 67 68 // Engine for reporting violations. 69 DiagnosticsEngine *Diag = nullptr; 70 71 // Handle diagnostics reporting for target level violations. 72 void emitDiag(llvm::function_ref<void()> Report, RecordLoc *Loc = nullptr); 73 74 VerifierContext() = default; VerifierContextVerifierContext75 VerifierContext(DiagnosticsEngine *Diag) : Diag(Diag) {} 76 }; 77 78 DylibVerifier() = default; 79 DylibVerifier(llvm::MachO::Records && Dylib,ReexportedInterfaces && Reexports,AliasMap Aliases,DiagnosticsEngine * Diag,VerificationMode Mode,bool Zippered,bool Demangle,StringRef DSYMPath)80 DylibVerifier(llvm::MachO::Records &&Dylib, ReexportedInterfaces &&Reexports, 81 AliasMap Aliases, DiagnosticsEngine *Diag, 82 VerificationMode Mode, bool Zippered, bool Demangle, 83 StringRef DSYMPath) 84 : Dylib(std::move(Dylib)), Reexports(std::move(Reexports)), 85 Aliases(std::move(Aliases)), Mode(Mode), Zippered(Zippered), 86 Demangle(Demangle), DSYMPath(DSYMPath), 87 Exports(std::make_unique<SymbolSet>()), Ctx(VerifierContext{Diag}) {} 88 89 Result verify(GlobalRecord *R, const FrontendAttrs *FA); 90 Result verify(ObjCInterfaceRecord *R, const FrontendAttrs *FA); 91 Result verify(ObjCIVarRecord *R, const FrontendAttrs *FA, 92 const StringRef SuperClass); 93 94 // Scan through dylib slices and report any remaining missing exports. 95 Result verifyRemainingSymbols(); 96 97 /// Compare and report the attributes represented as 98 /// load commands in the dylib to the attributes provided via options. 99 bool verifyBinaryAttrs(const ArrayRef<Target> ProvidedTargets, 100 const BinaryAttrs &ProvidedBA, 101 const LibAttrs &ProvidedReexports, 102 const LibAttrs &ProvidedClients, 103 const LibAttrs &ProvidedRPaths, const FileType &FT); 104 105 /// Initialize target for verification. 106 void setTarget(const Target &T); 107 108 /// Release ownership over exports. 109 std::unique_ptr<SymbolSet> takeExports(); 110 111 /// Get result of verification. getState()112 Result getState() const { return Ctx.FrontendState; } 113 114 /// Set different source managers to the same diagnostics engine. 115 void setSourceManager(IntrusiveRefCntPtr<SourceManager> SourceMgr); 116 117 private: 118 /// Determine whether to compare declaration to symbol in binary. 119 bool canVerify(); 120 121 /// Shared implementation for verifying exported symbols. 122 Result verifyImpl(Record *R, SymbolContext &SymCtx); 123 124 /// Check if declaration is marked as obsolete, they are 125 // expected to result in a symbol mismatch. 126 bool shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx, 127 const Record *DR); 128 129 /// Check if declaration is exported from a reexported library. These 130 /// symbols should be omitted from the text-api file. 131 bool shouldIgnoreReexport(const Record *R, SymbolContext &SymCtx) const; 132 133 // Ignore and omit unavailable symbols in zippered libraries. 134 bool shouldIgnoreZipperedAvailability(const Record *R, SymbolContext &SymCtx); 135 136 // Check if an internal declaration in zippered library has an 137 // external declaration for a different platform. This results 138 // in the symbol being in a "separate" platform slice. 139 bool shouldIgnoreInternalZipperedSymbol(const Record *R, 140 const SymbolContext &SymCtx) const; 141 142 /// Compare the visibility declarations to the linkage of symbol found in 143 /// dylib. 144 Result compareVisibility(const Record *R, SymbolContext &SymCtx, 145 const Record *DR); 146 147 /// An ObjCInterfaceRecord can represent up to three symbols. When verifying, 148 // account for this granularity. 149 bool compareObjCInterfaceSymbols(const Record *R, SymbolContext &SymCtx, 150 const ObjCInterfaceRecord *DR); 151 152 /// Validate availability annotations against dylib. 153 Result compareAvailability(const Record *R, SymbolContext &SymCtx, 154 const Record *DR); 155 156 /// Compare and validate matching symbol flags. 157 bool compareSymbolFlags(const Record *R, SymbolContext &SymCtx, 158 const Record *DR); 159 160 /// Update result state on each call to `verify`. 161 void updateState(Result State); 162 163 /// Add verified exported symbol. 164 void addSymbol(const Record *R, SymbolContext &SymCtx, 165 TargetList &&Targets = {}); 166 167 /// Find matching dylib slice for target triple that is being parsed. 168 void assignSlice(const Target &T); 169 170 /// Shared implementation for verifying exported symbols in dylib. 171 void visitSymbolInDylib(const Record &R, SymbolContext &SymCtx); 172 173 void visitGlobal(const GlobalRecord &R) override; 174 void visitObjCInterface(const ObjCInterfaceRecord &R) override; 175 void visitObjCCategory(const ObjCCategoryRecord &R) override; 176 void visitObjCIVar(const ObjCIVarRecord &R, const StringRef Super); 177 178 /// Gather annotations for symbol for error reporting. 179 std::string getAnnotatedName(const Record *R, SymbolContext &SymCtx, 180 bool ValidSourceLoc = true); 181 182 /// Extract source location for symbol implementations. 183 /// As this is a relatively expensive operation, it is only used 184 /// when there is a violation to report and there is not a known declaration 185 /// in the interface. 186 void accumulateSrcLocForDylibSymbols(); 187 188 // Symbols in dylib. 189 llvm::MachO::Records Dylib; 190 191 // Reexported interfaces apart of the library. 192 ReexportedInterfaces Reexports; 193 194 // Symbol aliases. 195 AliasMap Aliases; 196 197 // Controls what class of violations to report. 198 VerificationMode Mode = VerificationMode::Invalid; 199 200 // Library is zippered. 201 bool Zippered = false; 202 203 // Attempt to demangle when reporting violations. 204 bool Demangle = false; 205 206 // File path to DSYM file. 207 StringRef DSYMPath; 208 209 // Valid symbols in final text file. 210 std::unique_ptr<SymbolSet> Exports = std::make_unique<SymbolSet>(); 211 212 // Unavailable or obsoleted declarations for a zippered library. 213 // These are cross referenced against symbols in the dylib. 214 llvm::StringMap<ZipperedDeclSources> DeferredZipperedSymbols; 215 216 // Track current state of verification while traversing AST. 217 VerifierContext Ctx; 218 219 // Track DWARF provided source location for dylibs. 220 DWARFContext *DWARFCtx = nullptr; 221 222 // Source manager for each unique compiler instance. 223 llvm::SmallVector<IntrusiveRefCntPtr<SourceManager>, 12> SourceManagers; 224 }; 225 226 } // namespace installapi 227 } // namespace clang 228 #endif // LLVM_CLANG_INSTALLAPI_DYLIBVERIFIER_H 229