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