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
16namespace clang {
17namespace installapi {
18struct FrontendAttrs;
19
20/// A list of InstallAPI verification modes.
21enum class VerificationMode {
22 Invalid,
23 ErrorsOnly,
24 ErrorsAndWarnings,
25 Pedantic,
26};
27
28using LibAttrs = llvm::StringMap<ArchitectureSet>;
29using 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.
34struct ZipperedDeclSource {
35 const FrontendAttrs *FA;
36 clang::SourceManager *SrcMgr;
37 Target T;
38};
39using 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.
45class DylibVerifier : llvm::MachO::RecordVisitor {
46private:
47 struct SymbolContext;
48 struct DWARFContext;
49
50public:
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;
75 VerifierContext(DiagnosticsEngine *Diag) : Diag(Diag) {}
76 };
77
78 DylibVerifier() = default;
79
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.
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
117private:
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 "seperate" 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

source code of clang/include/clang/InstallAPI/DylibVerifier.h