xref: /freebsd/contrib/llvm-project/clang/include/clang/InstallAPI/DylibVerifier.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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