xref: /llvm-project/clang/lib/InstallAPI/DylibVerifier.cpp (revision a4a8d36b8591801696aad30fa116669c7bb2348c)
16d579cd1SCyndy Ishida //===- DylibVerifier.cpp ----------------------------------------*- C++--*-===//
26d579cd1SCyndy Ishida //
36d579cd1SCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46d579cd1SCyndy Ishida // See https://llvm.org/LICENSE.txt for license information.
56d579cd1SCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66d579cd1SCyndy Ishida //
76d579cd1SCyndy Ishida //===----------------------------------------------------------------------===//
86d579cd1SCyndy Ishida 
9f2794cceSCyndy Ishida #include "clang/InstallAPI/DylibVerifier.h"
1027b2d7d4SCyndy Ishida #include "DiagnosticBuilderWrappers.h"
11f2794cceSCyndy Ishida #include "clang/InstallAPI/FrontendRecords.h"
12936519f2SCyndy Ishida #include "clang/InstallAPI/InstallAPIDiagnostic.h"
13f2794cceSCyndy Ishida #include "llvm/Demangle/Demangle.h"
14a4de589dSCyndy Ishida #include "llvm/TextAPI/DylibReader.h"
15f2794cceSCyndy Ishida 
16f2794cceSCyndy Ishida using namespace llvm::MachO;
17f2794cceSCyndy Ishida 
18f2794cceSCyndy Ishida namespace clang {
19f2794cceSCyndy Ishida namespace installapi {
20f2794cceSCyndy Ishida 
21f2794cceSCyndy Ishida /// Metadata stored about a mapping of a declaration to a symbol.
22f2794cceSCyndy Ishida struct DylibVerifier::SymbolContext {
23f2794cceSCyndy Ishida   // Name to use for all querying and verification
24f2794cceSCyndy Ishida   // purposes.
25f2794cceSCyndy Ishida   std::string SymbolName{""};
26f2794cceSCyndy Ishida 
27f2794cceSCyndy Ishida   // Kind to map symbol type against record.
28f2794cceSCyndy Ishida   EncodeKind Kind = EncodeKind::GlobalSymbol;
29f2794cceSCyndy Ishida 
30f2794cceSCyndy Ishida   // Frontend Attributes tied to the AST.
31f2794cceSCyndy Ishida   const FrontendAttrs *FA = nullptr;
32f2794cceSCyndy Ishida 
33f2794cceSCyndy Ishida   // The ObjCInterface symbol type, if applicable.
34f2794cceSCyndy Ishida   ObjCIFSymbolKind ObjCIFKind = ObjCIFSymbolKind::None;
35936519f2SCyndy Ishida 
36936519f2SCyndy Ishida   // Whether Decl is inlined.
37936519f2SCyndy Ishida   bool Inlined = false;
38f2794cceSCyndy Ishida };
39f2794cceSCyndy Ishida 
40a4de589dSCyndy Ishida struct DylibVerifier::DWARFContext {
41a4de589dSCyndy Ishida   // Track whether DSYM parsing has already been attempted to avoid re-parsing.
42a4de589dSCyndy Ishida   bool ParsedDSYM{false};
43a4de589dSCyndy Ishida 
44a4de589dSCyndy Ishida   // Lookup table for source locations by symbol name.
45a4de589dSCyndy Ishida   DylibReader::SymbolToSourceLocMap SourceLocs{};
46a4de589dSCyndy Ishida };
47a4de589dSCyndy Ishida 
489f168591SCyndy Ishida static bool isCppMangled(StringRef Name) {
499f168591SCyndy Ishida   // InstallAPI currently only supports itanium manglings.
509f168591SCyndy Ishida   return (Name.starts_with("_Z") || Name.starts_with("__Z") ||
519f168591SCyndy Ishida           Name.starts_with("___Z"));
529f168591SCyndy Ishida }
539f168591SCyndy Ishida 
549f168591SCyndy Ishida static std::string demangle(StringRef Name) {
559f168591SCyndy Ishida   // InstallAPI currently only supports itanium manglings.
569f168591SCyndy Ishida   if (!isCppMangled(Name))
579f168591SCyndy Ishida     return Name.str();
589f168591SCyndy Ishida   char *Result = llvm::itaniumDemangle(Name);
599f168591SCyndy Ishida   if (!Result)
609f168591SCyndy Ishida     return Name.str();
619f168591SCyndy Ishida 
629f168591SCyndy Ishida   std::string Demangled(Result);
639f168591SCyndy Ishida   free(Result);
649f168591SCyndy Ishida   return Demangled;
659f168591SCyndy Ishida }
669f168591SCyndy Ishida 
679f168591SCyndy Ishida std::string DylibVerifier::getAnnotatedName(const Record *R,
689f168591SCyndy Ishida                                             SymbolContext &SymCtx,
699f168591SCyndy Ishida                                             bool ValidSourceLoc) {
709f168591SCyndy Ishida   assert(!SymCtx.SymbolName.empty() && "Expected symbol name");
719f168591SCyndy Ishida 
729f168591SCyndy Ishida   const StringRef SymbolName = SymCtx.SymbolName;
739f168591SCyndy Ishida   std::string PrettyName =
749f168591SCyndy Ishida       (Demangle && (SymCtx.Kind == EncodeKind::GlobalSymbol))
759f168591SCyndy Ishida           ? demangle(SymbolName)
769f168591SCyndy Ishida           : SymbolName.str();
77f2794cceSCyndy Ishida 
78f2794cceSCyndy Ishida   std::string Annotation;
79f2794cceSCyndy Ishida   if (R->isWeakDefined())
80f2794cceSCyndy Ishida     Annotation += "(weak-def) ";
81f2794cceSCyndy Ishida   if (R->isWeakReferenced())
82f2794cceSCyndy Ishida     Annotation += "(weak-ref) ";
83f2794cceSCyndy Ishida   if (R->isThreadLocalValue())
84f2794cceSCyndy Ishida     Annotation += "(tlv) ";
85f2794cceSCyndy Ishida 
86f2794cceSCyndy Ishida   // Check if symbol represents only part of a @interface declaration.
87e470ca89SCyndy Ishida   switch (SymCtx.ObjCIFKind) {
88e470ca89SCyndy Ishida   default:
89e470ca89SCyndy Ishida     break;
90e470ca89SCyndy Ishida   case ObjCIFSymbolKind::EHType:
91e470ca89SCyndy Ishida     return Annotation + "Exception Type of " + PrettyName;
92e470ca89SCyndy Ishida   case ObjCIFSymbolKind::MetaClass:
93e470ca89SCyndy Ishida     return Annotation + "Metaclass of " + PrettyName;
94e470ca89SCyndy Ishida   case ObjCIFSymbolKind::Class:
95e470ca89SCyndy Ishida     return Annotation + "Class of " + PrettyName;
96f2794cceSCyndy Ishida   }
97f2794cceSCyndy Ishida 
98f2794cceSCyndy Ishida   // Only print symbol type prefix or leading "_" if there is no source location
99f2794cceSCyndy Ishida   // tied to it. This can only ever happen when the location has to come from
100f2794cceSCyndy Ishida   // debug info.
101f2794cceSCyndy Ishida   if (ValidSourceLoc) {
1029f168591SCyndy Ishida     StringRef PrettyNameRef(PrettyName);
1039f168591SCyndy Ishida     if ((SymCtx.Kind == EncodeKind::GlobalSymbol) &&
1049f168591SCyndy Ishida         !isCppMangled(SymbolName) && PrettyNameRef.starts_with("_"))
1059f168591SCyndy Ishida       return Annotation + PrettyNameRef.drop_front(1).str();
1069f168591SCyndy Ishida     return Annotation + PrettyName;
107f2794cceSCyndy Ishida   }
108f2794cceSCyndy Ishida 
1099f168591SCyndy Ishida   switch (SymCtx.Kind) {
110f2794cceSCyndy Ishida   case EncodeKind::GlobalSymbol:
1119f168591SCyndy Ishida     return Annotation + PrettyName;
112f2794cceSCyndy Ishida   case EncodeKind::ObjectiveCInstanceVariable:
1139f168591SCyndy Ishida     return Annotation + "(ObjC IVar) " + PrettyName;
114f2794cceSCyndy Ishida   case EncodeKind::ObjectiveCClass:
1159f168591SCyndy Ishida     return Annotation + "(ObjC Class) " + PrettyName;
116f2794cceSCyndy Ishida   case EncodeKind::ObjectiveCClassEHType:
1179f168591SCyndy Ishida     return Annotation + "(ObjC Class EH) " + PrettyName;
118f2794cceSCyndy Ishida   }
119f2794cceSCyndy Ishida 
120f2794cceSCyndy Ishida   llvm_unreachable("unexpected case for EncodeKind");
121f2794cceSCyndy Ishida }
122f2794cceSCyndy Ishida 
123f2794cceSCyndy Ishida static DylibVerifier::Result updateResult(const DylibVerifier::Result Prev,
124f2794cceSCyndy Ishida                                           const DylibVerifier::Result Curr) {
125f2794cceSCyndy Ishida   if (Prev == Curr)
126f2794cceSCyndy Ishida     return Prev;
127f2794cceSCyndy Ishida 
128f2794cceSCyndy Ishida   // Never update from invalid or noverify state.
129f2794cceSCyndy Ishida   if ((Prev == DylibVerifier::Result::Invalid) ||
130f2794cceSCyndy Ishida       (Prev == DylibVerifier::Result::NoVerify))
131f2794cceSCyndy Ishida     return Prev;
132f2794cceSCyndy Ishida 
133f2794cceSCyndy Ishida   // Don't let an ignored verification remove a valid one.
134f2794cceSCyndy Ishida   if (Prev == DylibVerifier::Result::Valid &&
135f2794cceSCyndy Ishida       Curr == DylibVerifier::Result::Ignore)
136f2794cceSCyndy Ishida     return Prev;
137f2794cceSCyndy Ishida 
138f2794cceSCyndy Ishida   return Curr;
139f2794cceSCyndy Ishida }
140936519f2SCyndy Ishida // __private_extern__ is a deprecated specifier that clang does not
141936519f2SCyndy Ishida // respect in all contexts, it should just be considered hidden for InstallAPI.
142936519f2SCyndy Ishida static bool shouldIgnorePrivateExternAttr(const Decl *D) {
143936519f2SCyndy Ishida   if (const FunctionDecl *FD = cast<FunctionDecl>(D))
144936519f2SCyndy Ishida     return FD->getStorageClass() == StorageClass::SC_PrivateExtern;
145936519f2SCyndy Ishida   if (const VarDecl *VD = cast<VarDecl>(D))
146936519f2SCyndy Ishida     return VD->getStorageClass() == StorageClass::SC_PrivateExtern;
147936519f2SCyndy Ishida 
148936519f2SCyndy Ishida   return false;
149936519f2SCyndy Ishida }
150936519f2SCyndy Ishida 
151936519f2SCyndy Ishida Record *findRecordFromSlice(const RecordsSlice *Slice, StringRef Name,
152936519f2SCyndy Ishida                             EncodeKind Kind) {
153936519f2SCyndy Ishida   switch (Kind) {
154936519f2SCyndy Ishida   case EncodeKind::GlobalSymbol:
155936519f2SCyndy Ishida     return Slice->findGlobal(Name);
156936519f2SCyndy Ishida   case EncodeKind::ObjectiveCInstanceVariable:
157936519f2SCyndy Ishida     return Slice->findObjCIVar(Name.contains('.'), Name);
158936519f2SCyndy Ishida   case EncodeKind::ObjectiveCClass:
159936519f2SCyndy Ishida   case EncodeKind::ObjectiveCClassEHType:
160936519f2SCyndy Ishida     return Slice->findObjCInterface(Name);
161936519f2SCyndy Ishida   }
162936519f2SCyndy Ishida   llvm_unreachable("unexpected end when finding record");
163936519f2SCyndy Ishida }
164f2794cceSCyndy Ishida 
165f2794cceSCyndy Ishida void DylibVerifier::updateState(Result State) {
166f2794cceSCyndy Ishida   Ctx.FrontendState = updateResult(Ctx.FrontendState, State);
167f2794cceSCyndy Ishida }
168f2794cceSCyndy Ishida 
169f2794cceSCyndy Ishida void DylibVerifier::addSymbol(const Record *R, SymbolContext &SymCtx,
170f2794cceSCyndy Ishida                               TargetList &&Targets) {
171f2794cceSCyndy Ishida   if (Targets.empty())
172f2794cceSCyndy Ishida     Targets = {Ctx.Target};
173f2794cceSCyndy Ishida 
174f2794cceSCyndy Ishida   Exports->addGlobal(SymCtx.Kind, SymCtx.SymbolName, R->getFlags(), Targets);
175f2794cceSCyndy Ishida }
176f2794cceSCyndy Ishida 
177936519f2SCyndy Ishida bool DylibVerifier::shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx,
178936519f2SCyndy Ishida                                          const Record *DR) {
179c24efffaSCyndy Ishida   if (!SymCtx.FA->Avail.isObsoleted())
180c24efffaSCyndy Ishida     return false;
181c24efffaSCyndy Ishida 
182c24efffaSCyndy Ishida   if (Zippered)
183c24efffaSCyndy Ishida     DeferredZipperedSymbols[SymCtx.SymbolName].emplace_back(ZipperedDeclSource{
184c24efffaSCyndy Ishida         SymCtx.FA, &Ctx.Diag->getSourceManager(), Ctx.Target});
185c24efffaSCyndy Ishida   return true;
186936519f2SCyndy Ishida }
187936519f2SCyndy Ishida 
18827b2d7d4SCyndy Ishida bool DylibVerifier::shouldIgnoreReexport(const Record *R,
18927b2d7d4SCyndy Ishida                                          SymbolContext &SymCtx) const {
190*a4a8d36bSCyndy Ishida   StringRef SymName = SymCtx.SymbolName;
191*a4a8d36bSCyndy Ishida   // Linker directive symbols can never be ignored.
192*a4a8d36bSCyndy Ishida   if (SymName.starts_with("$ld$"))
193*a4a8d36bSCyndy Ishida     return false;
194*a4a8d36bSCyndy Ishida 
19527b2d7d4SCyndy Ishida   if (Reexports.empty())
19627b2d7d4SCyndy Ishida     return false;
19727b2d7d4SCyndy Ishida 
19827b2d7d4SCyndy Ishida   for (const InterfaceFile &Lib : Reexports) {
19927b2d7d4SCyndy Ishida     if (!Lib.hasTarget(Ctx.Target))
20027b2d7d4SCyndy Ishida       continue;
201*a4a8d36bSCyndy Ishida     if (auto Sym = Lib.getSymbol(SymCtx.Kind, SymName, SymCtx.ObjCIFKind))
20227b2d7d4SCyndy Ishida       if ((*Sym)->hasTarget(Ctx.Target))
20327b2d7d4SCyndy Ishida         return true;
20427b2d7d4SCyndy Ishida   }
20527b2d7d4SCyndy Ishida   return false;
20627b2d7d4SCyndy Ishida }
20727b2d7d4SCyndy Ishida 
208c24efffaSCyndy Ishida bool DylibVerifier::shouldIgnoreInternalZipperedSymbol(
209c24efffaSCyndy Ishida     const Record *R, const SymbolContext &SymCtx) const {
210c24efffaSCyndy Ishida   if (!Zippered)
211c24efffaSCyndy Ishida     return false;
212c24efffaSCyndy Ishida 
213c24efffaSCyndy Ishida   return Exports->findSymbol(SymCtx.Kind, SymCtx.SymbolName,
214c24efffaSCyndy Ishida                              SymCtx.ObjCIFKind) != nullptr;
215c24efffaSCyndy Ishida }
216c24efffaSCyndy Ishida 
217c24efffaSCyndy Ishida bool DylibVerifier::shouldIgnoreZipperedAvailability(const Record *R,
218c24efffaSCyndy Ishida                                                      SymbolContext &SymCtx) {
219c24efffaSCyndy Ishida   if (!(Zippered && SymCtx.FA->Avail.isUnavailable()))
220c24efffaSCyndy Ishida     return false;
221c24efffaSCyndy Ishida 
222c24efffaSCyndy Ishida   // Collect source location incase there is an exported symbol to diagnose
223c24efffaSCyndy Ishida   // during `verifyRemainingSymbols`.
224c24efffaSCyndy Ishida   DeferredZipperedSymbols[SymCtx.SymbolName].emplace_back(
225c24efffaSCyndy Ishida       ZipperedDeclSource{SymCtx.FA, SourceManagers.back().get(), Ctx.Target});
226c24efffaSCyndy Ishida 
227c24efffaSCyndy Ishida   return true;
228c24efffaSCyndy Ishida }
229c24efffaSCyndy Ishida 
230936519f2SCyndy Ishida bool DylibVerifier::compareObjCInterfaceSymbols(const Record *R,
231936519f2SCyndy Ishida                                                 SymbolContext &SymCtx,
232936519f2SCyndy Ishida                                                 const ObjCInterfaceRecord *DR) {
233936519f2SCyndy Ishida   const bool IsDeclVersionComplete =
234936519f2SCyndy Ishida       ((SymCtx.ObjCIFKind & ObjCIFSymbolKind::Class) ==
235936519f2SCyndy Ishida        ObjCIFSymbolKind::Class) &&
236936519f2SCyndy Ishida       ((SymCtx.ObjCIFKind & ObjCIFSymbolKind::MetaClass) ==
237936519f2SCyndy Ishida        ObjCIFSymbolKind::MetaClass);
238936519f2SCyndy Ishida 
239936519f2SCyndy Ishida   const bool IsDylibVersionComplete = DR->isCompleteInterface();
240936519f2SCyndy Ishida 
241936519f2SCyndy Ishida   // The common case, a complete ObjCInterface.
242936519f2SCyndy Ishida   if (IsDeclVersionComplete && IsDylibVersionComplete)
243936519f2SCyndy Ishida     return true;
244936519f2SCyndy Ishida 
245936519f2SCyndy Ishida   auto PrintDiagnostic = [&](auto SymLinkage, const Record *Record,
246936519f2SCyndy Ishida                              StringRef SymName, bool PrintAsWarning = false) {
247936519f2SCyndy Ishida     if (SymLinkage == RecordLinkage::Unknown)
248936519f2SCyndy Ishida       Ctx.emitDiag([&]() {
249f04452deSCyndy Ishida         Ctx.Diag->Report(SymCtx.FA->Loc, PrintAsWarning
250f04452deSCyndy Ishida                                              ? diag::warn_library_missing_symbol
251936519f2SCyndy Ishida                                              : diag::err_library_missing_symbol)
252936519f2SCyndy Ishida             << SymName;
253936519f2SCyndy Ishida       });
254936519f2SCyndy Ishida     else
255936519f2SCyndy Ishida       Ctx.emitDiag([&]() {
256f04452deSCyndy Ishida         Ctx.Diag->Report(SymCtx.FA->Loc, PrintAsWarning
257f04452deSCyndy Ishida                                              ? diag::warn_library_hidden_symbol
258936519f2SCyndy Ishida                                              : diag::err_library_hidden_symbol)
259936519f2SCyndy Ishida             << SymName;
260936519f2SCyndy Ishida       });
261936519f2SCyndy Ishida   };
262936519f2SCyndy Ishida 
263936519f2SCyndy Ishida   if (IsDeclVersionComplete) {
264936519f2SCyndy Ishida     // The decl represents a complete ObjCInterface, but the symbols in the
265936519f2SCyndy Ishida     // dylib do not. Determine which symbol is missing. To keep older projects
266936519f2SCyndy Ishida     // building, treat this as a warning.
2679f168591SCyndy Ishida     if (!DR->isExportedSymbol(ObjCIFSymbolKind::Class)) {
2689f168591SCyndy Ishida       SymCtx.ObjCIFKind = ObjCIFSymbolKind::Class;
269936519f2SCyndy Ishida       PrintDiagnostic(DR->getLinkageForSymbol(ObjCIFSymbolKind::Class), R,
2709f168591SCyndy Ishida                       getAnnotatedName(R, SymCtx),
271936519f2SCyndy Ishida                       /*PrintAsWarning=*/true);
2729f168591SCyndy Ishida     }
2739f168591SCyndy Ishida     if (!DR->isExportedSymbol(ObjCIFSymbolKind::MetaClass)) {
2749f168591SCyndy Ishida       SymCtx.ObjCIFKind = ObjCIFSymbolKind::MetaClass;
275936519f2SCyndy Ishida       PrintDiagnostic(DR->getLinkageForSymbol(ObjCIFSymbolKind::MetaClass), R,
2769f168591SCyndy Ishida                       getAnnotatedName(R, SymCtx),
277936519f2SCyndy Ishida                       /*PrintAsWarning=*/true);
2789f168591SCyndy Ishida     }
279936519f2SCyndy Ishida     return true;
280936519f2SCyndy Ishida   }
281936519f2SCyndy Ishida 
282936519f2SCyndy Ishida   if (DR->isExportedSymbol(SymCtx.ObjCIFKind)) {
283936519f2SCyndy Ishida     if (!IsDylibVersionComplete) {
284936519f2SCyndy Ishida       // Both the declaration and dylib have a non-complete interface.
285936519f2SCyndy Ishida       SymCtx.Kind = EncodeKind::GlobalSymbol;
286936519f2SCyndy Ishida       SymCtx.SymbolName = R->getName();
287936519f2SCyndy Ishida     }
288936519f2SCyndy Ishida     return true;
289936519f2SCyndy Ishida   }
290936519f2SCyndy Ishida 
291936519f2SCyndy Ishida   // At this point that means there was not a matching class symbol
292936519f2SCyndy Ishida   // to represent the one discovered as a declaration.
293936519f2SCyndy Ishida   PrintDiagnostic(DR->getLinkageForSymbol(SymCtx.ObjCIFKind), R,
2949f168591SCyndy Ishida                   SymCtx.SymbolName);
295936519f2SCyndy Ishida   return false;
296936519f2SCyndy Ishida }
297936519f2SCyndy Ishida 
298936519f2SCyndy Ishida DylibVerifier::Result DylibVerifier::compareVisibility(const Record *R,
299936519f2SCyndy Ishida                                                        SymbolContext &SymCtx,
300936519f2SCyndy Ishida                                                        const Record *DR) {
301936519f2SCyndy Ishida 
302936519f2SCyndy Ishida   if (R->isExported()) {
303936519f2SCyndy Ishida     if (!DR) {
304936519f2SCyndy Ishida       Ctx.emitDiag([&]() {
305f04452deSCyndy Ishida         Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_library_missing_symbol)
3069f168591SCyndy Ishida             << getAnnotatedName(R, SymCtx);
307936519f2SCyndy Ishida       });
308936519f2SCyndy Ishida       return Result::Invalid;
309936519f2SCyndy Ishida     }
310936519f2SCyndy Ishida     if (DR->isInternal()) {
311936519f2SCyndy Ishida       Ctx.emitDiag([&]() {
312f04452deSCyndy Ishida         Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_library_hidden_symbol)
3139f168591SCyndy Ishida             << getAnnotatedName(R, SymCtx);
314936519f2SCyndy Ishida       });
315936519f2SCyndy Ishida       return Result::Invalid;
316936519f2SCyndy Ishida     }
317936519f2SCyndy Ishida   }
318936519f2SCyndy Ishida 
319936519f2SCyndy Ishida   // Emit a diagnostic for hidden declarations with external symbols, except
320936519f2SCyndy Ishida   // when theres an inlined attribute.
321936519f2SCyndy Ishida   if ((R->isInternal() && !SymCtx.Inlined) && DR && DR->isExported()) {
322936519f2SCyndy Ishida 
323936519f2SCyndy Ishida     if (Mode == VerificationMode::ErrorsOnly)
324936519f2SCyndy Ishida       return Result::Ignore;
325936519f2SCyndy Ishida 
326936519f2SCyndy Ishida     if (shouldIgnorePrivateExternAttr(SymCtx.FA->D))
327936519f2SCyndy Ishida       return Result::Ignore;
328936519f2SCyndy Ishida 
329c24efffaSCyndy Ishida     if (shouldIgnoreInternalZipperedSymbol(R, SymCtx))
330c24efffaSCyndy Ishida       return Result::Ignore;
331c24efffaSCyndy Ishida 
332936519f2SCyndy Ishida     unsigned ID;
333936519f2SCyndy Ishida     Result Outcome;
334936519f2SCyndy Ishida     if (Mode == VerificationMode::ErrorsAndWarnings) {
335936519f2SCyndy Ishida       ID = diag::warn_header_hidden_symbol;
336936519f2SCyndy Ishida       Outcome = Result::Ignore;
337936519f2SCyndy Ishida     } else {
338936519f2SCyndy Ishida       ID = diag::err_header_hidden_symbol;
339936519f2SCyndy Ishida       Outcome = Result::Invalid;
340936519f2SCyndy Ishida     }
341936519f2SCyndy Ishida     Ctx.emitDiag([&]() {
342f04452deSCyndy Ishida       Ctx.Diag->Report(SymCtx.FA->Loc, ID) << getAnnotatedName(R, SymCtx);
343936519f2SCyndy Ishida     });
344936519f2SCyndy Ishida     return Outcome;
345936519f2SCyndy Ishida   }
346936519f2SCyndy Ishida 
347936519f2SCyndy Ishida   if (R->isInternal())
348936519f2SCyndy Ishida     return Result::Ignore;
349936519f2SCyndy Ishida 
350936519f2SCyndy Ishida   return Result::Valid;
351936519f2SCyndy Ishida }
352936519f2SCyndy Ishida 
353936519f2SCyndy Ishida DylibVerifier::Result DylibVerifier::compareAvailability(const Record *R,
354936519f2SCyndy Ishida                                                          SymbolContext &SymCtx,
355936519f2SCyndy Ishida                                                          const Record *DR) {
356936519f2SCyndy Ishida   if (!SymCtx.FA->Avail.isUnavailable())
357936519f2SCyndy Ishida     return Result::Valid;
358936519f2SCyndy Ishida 
359c24efffaSCyndy Ishida   if (shouldIgnoreZipperedAvailability(R, SymCtx))
360c24efffaSCyndy Ishida     return Result::Ignore;
361c24efffaSCyndy Ishida 
362936519f2SCyndy Ishida   const bool IsDeclAvailable = SymCtx.FA->Avail.isUnavailable();
363936519f2SCyndy Ishida 
364936519f2SCyndy Ishida   switch (Mode) {
365936519f2SCyndy Ishida   case VerificationMode::ErrorsAndWarnings:
366936519f2SCyndy Ishida     Ctx.emitDiag([&]() {
367f04452deSCyndy Ishida       Ctx.Diag->Report(SymCtx.FA->Loc, diag::warn_header_availability_mismatch)
3689f168591SCyndy Ishida           << getAnnotatedName(R, SymCtx) << IsDeclAvailable << IsDeclAvailable;
369936519f2SCyndy Ishida     });
370936519f2SCyndy Ishida     return Result::Ignore;
371936519f2SCyndy Ishida   case VerificationMode::Pedantic:
372936519f2SCyndy Ishida     Ctx.emitDiag([&]() {
373f04452deSCyndy Ishida       Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_availability_mismatch)
3749f168591SCyndy Ishida           << getAnnotatedName(R, SymCtx) << IsDeclAvailable << IsDeclAvailable;
375936519f2SCyndy Ishida     });
376936519f2SCyndy Ishida     return Result::Invalid;
377936519f2SCyndy Ishida   case VerificationMode::ErrorsOnly:
378936519f2SCyndy Ishida     return Result::Ignore;
379936519f2SCyndy Ishida   case VerificationMode::Invalid:
380936519f2SCyndy Ishida     llvm_unreachable("Unexpected verification mode symbol verification");
381936519f2SCyndy Ishida   }
382936519f2SCyndy Ishida   llvm_unreachable("Unexpected verification mode symbol verification");
383936519f2SCyndy Ishida }
384936519f2SCyndy Ishida 
385936519f2SCyndy Ishida bool DylibVerifier::compareSymbolFlags(const Record *R, SymbolContext &SymCtx,
386936519f2SCyndy Ishida                                        const Record *DR) {
387936519f2SCyndy Ishida   if (DR->isThreadLocalValue() && !R->isThreadLocalValue()) {
388936519f2SCyndy Ishida     Ctx.emitDiag([&]() {
389f04452deSCyndy Ishida       Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_dylib_symbol_flags_mismatch)
3909f168591SCyndy Ishida           << getAnnotatedName(DR, SymCtx) << DR->isThreadLocalValue();
391936519f2SCyndy Ishida     });
392936519f2SCyndy Ishida     return false;
393936519f2SCyndy Ishida   }
394936519f2SCyndy Ishida   if (!DR->isThreadLocalValue() && R->isThreadLocalValue()) {
395936519f2SCyndy Ishida     Ctx.emitDiag([&]() {
396f04452deSCyndy Ishida       Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_symbol_flags_mismatch)
397e470ca89SCyndy Ishida           << getAnnotatedName(R, SymCtx) << R->isThreadLocalValue();
398936519f2SCyndy Ishida     });
399936519f2SCyndy Ishida     return false;
400936519f2SCyndy Ishida   }
401936519f2SCyndy Ishida 
402936519f2SCyndy Ishida   if (DR->isWeakDefined() && !R->isWeakDefined()) {
403936519f2SCyndy Ishida     Ctx.emitDiag([&]() {
404f04452deSCyndy Ishida       Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_dylib_symbol_flags_mismatch)
4059f168591SCyndy Ishida           << getAnnotatedName(DR, SymCtx) << R->isWeakDefined();
406936519f2SCyndy Ishida     });
407936519f2SCyndy Ishida     return false;
408936519f2SCyndy Ishida   }
409936519f2SCyndy Ishida   if (!DR->isWeakDefined() && R->isWeakDefined()) {
410936519f2SCyndy Ishida     Ctx.emitDiag([&]() {
411f04452deSCyndy Ishida       Ctx.Diag->Report(SymCtx.FA->Loc, diag::err_header_symbol_flags_mismatch)
4129f168591SCyndy Ishida           << getAnnotatedName(R, SymCtx) << R->isWeakDefined();
413936519f2SCyndy Ishida     });
414936519f2SCyndy Ishida     return false;
415936519f2SCyndy Ishida   }
416936519f2SCyndy Ishida 
417936519f2SCyndy Ishida   return true;
418936519f2SCyndy Ishida }
419936519f2SCyndy Ishida 
420f2794cceSCyndy Ishida DylibVerifier::Result DylibVerifier::verifyImpl(Record *R,
421f2794cceSCyndy Ishida                                                 SymbolContext &SymCtx) {
422f2794cceSCyndy Ishida   R->setVerify();
423f2794cceSCyndy Ishida   if (!canVerify()) {
424f2794cceSCyndy Ishida     // Accumulate symbols when not in verifying against dylib.
425936519f2SCyndy Ishida     if (R->isExported() && !SymCtx.FA->Avail.isUnavailable() &&
426f2794cceSCyndy Ishida         !SymCtx.FA->Avail.isObsoleted()) {
427f2794cceSCyndy Ishida       addSymbol(R, SymCtx);
428f2794cceSCyndy Ishida     }
429f2794cceSCyndy Ishida     return Ctx.FrontendState;
430f2794cceSCyndy Ishida   }
431936519f2SCyndy Ishida 
43227b2d7d4SCyndy Ishida   if (shouldIgnoreReexport(R, SymCtx)) {
43327b2d7d4SCyndy Ishida     updateState(Result::Ignore);
43427b2d7d4SCyndy Ishida     return Ctx.FrontendState;
43527b2d7d4SCyndy Ishida   }
43627b2d7d4SCyndy Ishida 
437936519f2SCyndy Ishida   Record *DR =
438936519f2SCyndy Ishida       findRecordFromSlice(Ctx.DylibSlice, SymCtx.SymbolName, SymCtx.Kind);
439936519f2SCyndy Ishida   if (DR)
440936519f2SCyndy Ishida     DR->setVerify();
441936519f2SCyndy Ishida 
442936519f2SCyndy Ishida   if (shouldIgnoreObsolete(R, SymCtx, DR)) {
443936519f2SCyndy Ishida     updateState(Result::Ignore);
444936519f2SCyndy Ishida     return Ctx.FrontendState;
445936519f2SCyndy Ishida   }
446936519f2SCyndy Ishida 
447936519f2SCyndy Ishida   // Unavailable declarations don't need matching symbols.
448936519f2SCyndy Ishida   if (SymCtx.FA->Avail.isUnavailable() && (!DR || DR->isInternal())) {
449936519f2SCyndy Ishida     updateState(Result::Valid);
450936519f2SCyndy Ishida     return Ctx.FrontendState;
451936519f2SCyndy Ishida   }
452936519f2SCyndy Ishida 
453936519f2SCyndy Ishida   Result VisibilityCheck = compareVisibility(R, SymCtx, DR);
454936519f2SCyndy Ishida   if (VisibilityCheck != Result::Valid) {
455936519f2SCyndy Ishida     updateState(VisibilityCheck);
456936519f2SCyndy Ishida     return Ctx.FrontendState;
457936519f2SCyndy Ishida   }
458936519f2SCyndy Ishida 
459936519f2SCyndy Ishida   // All missing symbol cases to diagnose have been handled now.
460936519f2SCyndy Ishida   if (!DR) {
461936519f2SCyndy Ishida     updateState(Result::Ignore);
462936519f2SCyndy Ishida     return Ctx.FrontendState;
463936519f2SCyndy Ishida   }
464936519f2SCyndy Ishida 
465936519f2SCyndy Ishida   // Check for mismatching ObjC interfaces.
466936519f2SCyndy Ishida   if (SymCtx.ObjCIFKind != ObjCIFSymbolKind::None) {
467936519f2SCyndy Ishida     if (!compareObjCInterfaceSymbols(
468936519f2SCyndy Ishida             R, SymCtx, Ctx.DylibSlice->findObjCInterface(DR->getName()))) {
469936519f2SCyndy Ishida       updateState(Result::Invalid);
470936519f2SCyndy Ishida       return Ctx.FrontendState;
471936519f2SCyndy Ishida     }
472936519f2SCyndy Ishida   }
473936519f2SCyndy Ishida 
474936519f2SCyndy Ishida   Result AvailabilityCheck = compareAvailability(R, SymCtx, DR);
475936519f2SCyndy Ishida   if (AvailabilityCheck != Result::Valid) {
476936519f2SCyndy Ishida     updateState(AvailabilityCheck);
477936519f2SCyndy Ishida     return Ctx.FrontendState;
478936519f2SCyndy Ishida   }
479936519f2SCyndy Ishida 
480936519f2SCyndy Ishida   if (!compareSymbolFlags(R, SymCtx, DR)) {
481936519f2SCyndy Ishida     updateState(Result::Invalid);
482936519f2SCyndy Ishida     return Ctx.FrontendState;
483936519f2SCyndy Ishida   }
484936519f2SCyndy Ishida 
485936519f2SCyndy Ishida   addSymbol(R, SymCtx);
486936519f2SCyndy Ishida   updateState(Result::Valid);
487f2794cceSCyndy Ishida   return Ctx.FrontendState;
488f2794cceSCyndy Ishida }
489f2794cceSCyndy Ishida 
490f2794cceSCyndy Ishida bool DylibVerifier::canVerify() {
491f2794cceSCyndy Ishida   return Ctx.FrontendState != Result::NoVerify;
492f2794cceSCyndy Ishida }
493f2794cceSCyndy Ishida 
494936519f2SCyndy Ishida void DylibVerifier::assignSlice(const Target &T) {
495936519f2SCyndy Ishida   assert(T == Ctx.Target && "Active targets should match.");
496936519f2SCyndy Ishida   if (Dylib.empty())
497936519f2SCyndy Ishida     return;
498936519f2SCyndy Ishida 
499936519f2SCyndy Ishida   // Note: there are no reexport slices with binaries, as opposed to TBD files,
500936519f2SCyndy Ishida   // so it can be assumed that the target match is the active top-level library.
501936519f2SCyndy Ishida   auto It = find_if(
502936519f2SCyndy Ishida       Dylib, [&T](const auto &Slice) { return T == Slice->getTarget(); });
503936519f2SCyndy Ishida 
504936519f2SCyndy Ishida   assert(It != Dylib.end() && "Target slice should always exist.");
505936519f2SCyndy Ishida   Ctx.DylibSlice = It->get();
506936519f2SCyndy Ishida }
507936519f2SCyndy Ishida 
508f2794cceSCyndy Ishida void DylibVerifier::setTarget(const Target &T) {
509f2794cceSCyndy Ishida   Ctx.Target = T;
510f2794cceSCyndy Ishida   Ctx.DiscoveredFirstError = false;
511936519f2SCyndy Ishida   if (Dylib.empty()) {
512936519f2SCyndy Ishida     updateState(Result::NoVerify);
513936519f2SCyndy Ishida     return;
514936519f2SCyndy Ishida   }
515936519f2SCyndy Ishida   updateState(Result::Ignore);
516936519f2SCyndy Ishida   assignSlice(T);
517f2794cceSCyndy Ishida }
518f2794cceSCyndy Ishida 
519f04452deSCyndy Ishida void DylibVerifier::setSourceManager(
520f04452deSCyndy Ishida     IntrusiveRefCntPtr<SourceManager> SourceMgr) {
521f04452deSCyndy Ishida   if (!Ctx.Diag)
522f04452deSCyndy Ishida     return;
523f04452deSCyndy Ishida   SourceManagers.push_back(std::move(SourceMgr));
524f04452deSCyndy Ishida   Ctx.Diag->setSourceManager(SourceManagers.back().get());
525f04452deSCyndy Ishida }
526f04452deSCyndy Ishida 
527f2794cceSCyndy Ishida DylibVerifier::Result DylibVerifier::verify(ObjCIVarRecord *R,
528f2794cceSCyndy Ishida                                             const FrontendAttrs *FA,
529f2794cceSCyndy Ishida                                             const StringRef SuperClass) {
530f2794cceSCyndy Ishida   if (R->isVerified())
531f2794cceSCyndy Ishida     return getState();
532f2794cceSCyndy Ishida 
533f2794cceSCyndy Ishida   std::string FullName =
534f2794cceSCyndy Ishida       ObjCIVarRecord::createScopedName(SuperClass, R->getName());
5359f168591SCyndy Ishida   SymbolContext SymCtx{FullName, EncodeKind::ObjectiveCInstanceVariable, FA};
536f2794cceSCyndy Ishida   return verifyImpl(R, SymCtx);
537f2794cceSCyndy Ishida }
538f2794cceSCyndy Ishida 
539f2794cceSCyndy Ishida static ObjCIFSymbolKind assignObjCIFSymbolKind(const ObjCInterfaceRecord *R) {
540f2794cceSCyndy Ishida   ObjCIFSymbolKind Result = ObjCIFSymbolKind::None;
541f2794cceSCyndy Ishida   if (R->getLinkageForSymbol(ObjCIFSymbolKind::Class) != RecordLinkage::Unknown)
542f2794cceSCyndy Ishida     Result |= ObjCIFSymbolKind::Class;
543f2794cceSCyndy Ishida   if (R->getLinkageForSymbol(ObjCIFSymbolKind::MetaClass) !=
544f2794cceSCyndy Ishida       RecordLinkage::Unknown)
545f2794cceSCyndy Ishida     Result |= ObjCIFSymbolKind::MetaClass;
546f2794cceSCyndy Ishida   if (R->getLinkageForSymbol(ObjCIFSymbolKind::EHType) !=
547f2794cceSCyndy Ishida       RecordLinkage::Unknown)
548f2794cceSCyndy Ishida     Result |= ObjCIFSymbolKind::EHType;
549f2794cceSCyndy Ishida   return Result;
550f2794cceSCyndy Ishida }
551f2794cceSCyndy Ishida 
552f2794cceSCyndy Ishida DylibVerifier::Result DylibVerifier::verify(ObjCInterfaceRecord *R,
553f2794cceSCyndy Ishida                                             const FrontendAttrs *FA) {
554f2794cceSCyndy Ishida   if (R->isVerified())
555f2794cceSCyndy Ishida     return getState();
556f2794cceSCyndy Ishida   SymbolContext SymCtx;
557f2794cceSCyndy Ishida   SymCtx.SymbolName = R->getName();
558f2794cceSCyndy Ishida   SymCtx.ObjCIFKind = assignObjCIFSymbolKind(R);
559f2794cceSCyndy Ishida 
560f2794cceSCyndy Ishida   SymCtx.Kind = R->hasExceptionAttribute() ? EncodeKind::ObjectiveCClassEHType
561f2794cceSCyndy Ishida                                            : EncodeKind::ObjectiveCClass;
562f2794cceSCyndy Ishida   SymCtx.FA = FA;
563f2794cceSCyndy Ishida 
564f2794cceSCyndy Ishida   return verifyImpl(R, SymCtx);
565f2794cceSCyndy Ishida }
566f2794cceSCyndy Ishida 
567f2794cceSCyndy Ishida DylibVerifier::Result DylibVerifier::verify(GlobalRecord *R,
568f2794cceSCyndy Ishida                                             const FrontendAttrs *FA) {
569f2794cceSCyndy Ishida   if (R->isVerified())
570f2794cceSCyndy Ishida     return getState();
571f2794cceSCyndy Ishida 
572f2794cceSCyndy Ishida   // Global classifications could be obfusciated with `asm`.
573f2794cceSCyndy Ishida   SimpleSymbol Sym = parseSymbol(R->getName());
574f2794cceSCyndy Ishida   SymbolContext SymCtx;
575f2794cceSCyndy Ishida   SymCtx.SymbolName = Sym.Name;
576f2794cceSCyndy Ishida   SymCtx.Kind = Sym.Kind;
577f2794cceSCyndy Ishida   SymCtx.FA = FA;
578936519f2SCyndy Ishida   SymCtx.Inlined = R->isInlined();
579f2794cceSCyndy Ishida   return verifyImpl(R, SymCtx);
580f2794cceSCyndy Ishida }
581f2794cceSCyndy Ishida 
582a4de589dSCyndy Ishida void DylibVerifier::VerifierContext::emitDiag(llvm::function_ref<void()> Report,
583a4de589dSCyndy Ishida                                               RecordLoc *Loc) {
584936519f2SCyndy Ishida   if (!DiscoveredFirstError) {
585936519f2SCyndy Ishida     Diag->Report(diag::warn_target)
586936519f2SCyndy Ishida         << (PrintArch ? getArchitectureName(Target.Arch)
587936519f2SCyndy Ishida                       : getTargetTripleName(Target));
588936519f2SCyndy Ishida     DiscoveredFirstError = true;
589936519f2SCyndy Ishida   }
590a4de589dSCyndy Ishida   if (Loc && Loc->isValid())
591a4de589dSCyndy Ishida     llvm::errs() << Loc->File << ":" << Loc->Line << ":" << 0 << ": ";
592936519f2SCyndy Ishida 
593936519f2SCyndy Ishida   Report();
594936519f2SCyndy Ishida }
595936519f2SCyndy Ishida 
596e470ca89SCyndy Ishida // The existence of weak-defined RTTI can not always be inferred from the
597e470ca89SCyndy Ishida // header files because they can be generated as part of an implementation
598e470ca89SCyndy Ishida // file.
599e470ca89SCyndy Ishida // InstallAPI doesn't warn about weak-defined RTTI, because this doesn't affect
600e470ca89SCyndy Ishida // static linking and so can be ignored for text-api files.
601e470ca89SCyndy Ishida static bool shouldIgnoreCpp(StringRef Name, bool IsWeakDef) {
602e470ca89SCyndy Ishida   return (IsWeakDef &&
603e470ca89SCyndy Ishida           (Name.starts_with("__ZTI") || Name.starts_with("__ZTS")));
604e470ca89SCyndy Ishida }
605e470ca89SCyndy Ishida void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) {
606e470ca89SCyndy Ishida   // Undefined symbols should not be in InstallAPI generated text-api files.
607e470ca89SCyndy Ishida   if (R.isUndefined()) {
608e470ca89SCyndy Ishida     updateState(Result::Valid);
609e470ca89SCyndy Ishida     return;
610e470ca89SCyndy Ishida   }
611e470ca89SCyndy Ishida 
612e470ca89SCyndy Ishida   // Internal symbols should not be in InstallAPI generated text-api files.
613e470ca89SCyndy Ishida   if (R.isInternal()) {
614e470ca89SCyndy Ishida     updateState(Result::Valid);
615e470ca89SCyndy Ishida     return;
616e470ca89SCyndy Ishida   }
617e470ca89SCyndy Ishida 
618e470ca89SCyndy Ishida   // Allow zippered symbols with potentially mismatching availability
619e470ca89SCyndy Ishida   // between macOS and macCatalyst in the final text-api file.
620e470ca89SCyndy Ishida   const StringRef SymbolName(SymCtx.SymbolName);
621e470ca89SCyndy Ishida   if (const Symbol *Sym = Exports->findSymbol(SymCtx.Kind, SymCtx.SymbolName,
622e470ca89SCyndy Ishida                                               SymCtx.ObjCIFKind)) {
623e470ca89SCyndy Ishida     if (Sym->hasArchitecture(Ctx.Target.Arch)) {
624e470ca89SCyndy Ishida       updateState(Result::Ignore);
625e470ca89SCyndy Ishida       return;
626e470ca89SCyndy Ishida     }
627e470ca89SCyndy Ishida   }
628e470ca89SCyndy Ishida 
629c24efffaSCyndy Ishida   const bool IsLinkerSymbol = SymbolName.starts_with("$ld$");
630c24efffaSCyndy Ishida 
631c24efffaSCyndy Ishida   if (R.isVerified()) {
632c24efffaSCyndy Ishida     // Check for unavailable symbols.
633c24efffaSCyndy Ishida     // This should only occur in the zippered case where we ignored
634c24efffaSCyndy Ishida     // availability until all headers have been parsed.
635c24efffaSCyndy Ishida     auto It = DeferredZipperedSymbols.find(SymCtx.SymbolName);
636c24efffaSCyndy Ishida     if (It == DeferredZipperedSymbols.end()) {
637e470ca89SCyndy Ishida       updateState(Result::Valid);
638e470ca89SCyndy Ishida       return;
639e470ca89SCyndy Ishida     }
640e470ca89SCyndy Ishida 
641c24efffaSCyndy Ishida     ZipperedDeclSources Locs;
642c24efffaSCyndy Ishida     for (const ZipperedDeclSource &ZSource : It->second) {
643c24efffaSCyndy Ishida       if (ZSource.FA->Avail.isObsoleted()) {
644c24efffaSCyndy Ishida         updateState(Result::Ignore);
645c24efffaSCyndy Ishida         return;
646c24efffaSCyndy Ishida       }
647c24efffaSCyndy Ishida       if (ZSource.T.Arch != Ctx.Target.Arch)
648c24efffaSCyndy Ishida         continue;
649c24efffaSCyndy Ishida       Locs.emplace_back(ZSource);
650c24efffaSCyndy Ishida     }
651c24efffaSCyndy Ishida     assert(Locs.size() == 2 && "Expected two decls for zippered symbol");
652c24efffaSCyndy Ishida 
653c24efffaSCyndy Ishida     // Print violating declarations per platform.
654c24efffaSCyndy Ishida     for (const ZipperedDeclSource &ZSource : Locs) {
655c24efffaSCyndy Ishida       unsigned DiagID = 0;
656c24efffaSCyndy Ishida       if (Mode == VerificationMode::Pedantic || IsLinkerSymbol) {
657c24efffaSCyndy Ishida         updateState(Result::Invalid);
658c24efffaSCyndy Ishida         DiagID = diag::err_header_availability_mismatch;
659c24efffaSCyndy Ishida       } else if (Mode == VerificationMode::ErrorsAndWarnings) {
660c24efffaSCyndy Ishida         updateState(Result::Ignore);
661c24efffaSCyndy Ishida         DiagID = diag::warn_header_availability_mismatch;
662c24efffaSCyndy Ishida       } else {
663c24efffaSCyndy Ishida         updateState(Result::Ignore);
664c24efffaSCyndy Ishida         return;
665c24efffaSCyndy Ishida       }
666c24efffaSCyndy Ishida       // Bypass emitDiag banner and print the target everytime.
667c24efffaSCyndy Ishida       Ctx.Diag->setSourceManager(ZSource.SrcMgr);
668c24efffaSCyndy Ishida       Ctx.Diag->Report(diag::warn_target) << getTargetTripleName(ZSource.T);
669c24efffaSCyndy Ishida       Ctx.Diag->Report(ZSource.FA->Loc, DiagID)
670c24efffaSCyndy Ishida           << getAnnotatedName(&R, SymCtx) << ZSource.FA->Avail.isUnavailable()
671c24efffaSCyndy Ishida           << ZSource.FA->Avail.isUnavailable();
672c24efffaSCyndy Ishida     }
673c24efffaSCyndy Ishida     return;
674c24efffaSCyndy Ishida   }
675c24efffaSCyndy Ishida 
676c24efffaSCyndy Ishida   if (shouldIgnoreCpp(SymbolName, R.isWeakDefined())) {
677c24efffaSCyndy Ishida     updateState(Result::Valid);
678c24efffaSCyndy Ishida     return;
679c24efffaSCyndy Ishida   }
680a4de589dSCyndy Ishida 
6814c18681aSCyndy Ishida   if (Aliases.count({SymbolName.str(), SymCtx.Kind})) {
6824c18681aSCyndy Ishida     updateState(Result::Valid);
6834c18681aSCyndy Ishida     return;
6844c18681aSCyndy Ishida   }
6854c18681aSCyndy Ishida 
686a4de589dSCyndy Ishida   // All checks at this point classify as some kind of violation.
687a4de589dSCyndy Ishida   // The different verification modes dictate whether they are reported to the
688a4de589dSCyndy Ishida   // user.
689a4de589dSCyndy Ishida   if (IsLinkerSymbol || (Mode > VerificationMode::ErrorsOnly))
690a4de589dSCyndy Ishida     accumulateSrcLocForDylibSymbols();
691a4de589dSCyndy Ishida   RecordLoc Loc = DWARFCtx->SourceLocs.lookup(SymCtx.SymbolName);
692e470ca89SCyndy Ishida 
693e470ca89SCyndy Ishida   // Regardless of verification mode, error out on mismatched special linker
694e470ca89SCyndy Ishida   // symbols.
695a4de589dSCyndy Ishida   if (IsLinkerSymbol) {
696a4de589dSCyndy Ishida     Ctx.emitDiag(
697a4de589dSCyndy Ishida         [&]() {
698e470ca89SCyndy Ishida           Ctx.Diag->Report(diag::err_header_symbol_missing)
699a4de589dSCyndy Ishida               << getAnnotatedName(&R, SymCtx, Loc.isValid());
700a4de589dSCyndy Ishida         },
701a4de589dSCyndy Ishida         &Loc);
702e470ca89SCyndy Ishida     updateState(Result::Invalid);
703e470ca89SCyndy Ishida     return;
704e470ca89SCyndy Ishida   }
705e470ca89SCyndy Ishida 
706e470ca89SCyndy Ishida   // Missing declarations for exported symbols are hard errors on Pedantic mode.
707e470ca89SCyndy Ishida   if (Mode == VerificationMode::Pedantic) {
708a4de589dSCyndy Ishida     Ctx.emitDiag(
709a4de589dSCyndy Ishida         [&]() {
710e470ca89SCyndy Ishida           Ctx.Diag->Report(diag::err_header_symbol_missing)
711a4de589dSCyndy Ishida               << getAnnotatedName(&R, SymCtx, Loc.isValid());
712a4de589dSCyndy Ishida         },
713a4de589dSCyndy Ishida         &Loc);
714e470ca89SCyndy Ishida     updateState(Result::Invalid);
715e470ca89SCyndy Ishida     return;
716e470ca89SCyndy Ishida   }
717e470ca89SCyndy Ishida 
718e470ca89SCyndy Ishida   // Missing declarations for exported symbols are warnings on ErrorsAndWarnings
719e470ca89SCyndy Ishida   // mode.
720e470ca89SCyndy Ishida   if (Mode == VerificationMode::ErrorsAndWarnings) {
721a4de589dSCyndy Ishida     Ctx.emitDiag(
722a4de589dSCyndy Ishida         [&]() {
723e470ca89SCyndy Ishida           Ctx.Diag->Report(diag::warn_header_symbol_missing)
724a4de589dSCyndy Ishida               << getAnnotatedName(&R, SymCtx, Loc.isValid());
725a4de589dSCyndy Ishida         },
726a4de589dSCyndy Ishida         &Loc);
727e470ca89SCyndy Ishida     updateState(Result::Ignore);
728e470ca89SCyndy Ishida     return;
729e470ca89SCyndy Ishida   }
730e470ca89SCyndy Ishida 
731e470ca89SCyndy Ishida   // Missing declarations are dropped for ErrorsOnly mode. It is the last
732e470ca89SCyndy Ishida   // remaining mode.
733e470ca89SCyndy Ishida   updateState(Result::Ignore);
734e470ca89SCyndy Ishida   return;
735e470ca89SCyndy Ishida }
736e470ca89SCyndy Ishida 
737e470ca89SCyndy Ishida void DylibVerifier::visitGlobal(const GlobalRecord &R) {
738e470ca89SCyndy Ishida   SymbolContext SymCtx;
739e470ca89SCyndy Ishida   SimpleSymbol Sym = parseSymbol(R.getName());
740e470ca89SCyndy Ishida   SymCtx.SymbolName = Sym.Name;
741e470ca89SCyndy Ishida   SymCtx.Kind = Sym.Kind;
742e470ca89SCyndy Ishida   visitSymbolInDylib(R, SymCtx);
743e470ca89SCyndy Ishida }
744e470ca89SCyndy Ishida 
745e470ca89SCyndy Ishida void DylibVerifier::visitObjCIVar(const ObjCIVarRecord &R,
746e470ca89SCyndy Ishida                                   const StringRef Super) {
747e470ca89SCyndy Ishida   SymbolContext SymCtx;
748e470ca89SCyndy Ishida   SymCtx.SymbolName = ObjCIVarRecord::createScopedName(Super, R.getName());
749e470ca89SCyndy Ishida   SymCtx.Kind = EncodeKind::ObjectiveCInstanceVariable;
750e470ca89SCyndy Ishida   visitSymbolInDylib(R, SymCtx);
751e470ca89SCyndy Ishida }
752e470ca89SCyndy Ishida 
753a4de589dSCyndy Ishida void DylibVerifier::accumulateSrcLocForDylibSymbols() {
754a4de589dSCyndy Ishida   if (DSYMPath.empty())
755a4de589dSCyndy Ishida     return;
756a4de589dSCyndy Ishida 
757a4de589dSCyndy Ishida   assert(DWARFCtx != nullptr && "Expected an initialized DWARFContext");
758a4de589dSCyndy Ishida   if (DWARFCtx->ParsedDSYM)
759a4de589dSCyndy Ishida     return;
760a4de589dSCyndy Ishida   DWARFCtx->ParsedDSYM = true;
761a4de589dSCyndy Ishida   DWARFCtx->SourceLocs =
762a4de589dSCyndy Ishida       DylibReader::accumulateSourceLocFromDSYM(DSYMPath, Ctx.Target);
763a4de589dSCyndy Ishida }
764a4de589dSCyndy Ishida 
765e470ca89SCyndy Ishida void DylibVerifier::visitObjCInterface(const ObjCInterfaceRecord &R) {
766e470ca89SCyndy Ishida   SymbolContext SymCtx;
767e470ca89SCyndy Ishida   SymCtx.SymbolName = R.getName();
768e470ca89SCyndy Ishida   SymCtx.ObjCIFKind = assignObjCIFSymbolKind(&R);
769e470ca89SCyndy Ishida   if (SymCtx.ObjCIFKind > ObjCIFSymbolKind::EHType) {
770e470ca89SCyndy Ishida     if (R.hasExceptionAttribute()) {
771e470ca89SCyndy Ishida       SymCtx.Kind = EncodeKind::ObjectiveCClassEHType;
772e470ca89SCyndy Ishida       visitSymbolInDylib(R, SymCtx);
773e470ca89SCyndy Ishida     }
774e470ca89SCyndy Ishida     SymCtx.Kind = EncodeKind::ObjectiveCClass;
775e470ca89SCyndy Ishida     visitSymbolInDylib(R, SymCtx);
776e470ca89SCyndy Ishida   } else {
777e470ca89SCyndy Ishida     SymCtx.Kind = R.hasExceptionAttribute() ? EncodeKind::ObjectiveCClassEHType
778e470ca89SCyndy Ishida                                             : EncodeKind::ObjectiveCClass;
779e470ca89SCyndy Ishida     visitSymbolInDylib(R, SymCtx);
780e470ca89SCyndy Ishida   }
781e470ca89SCyndy Ishida 
782e470ca89SCyndy Ishida   for (const ObjCIVarRecord *IV : R.getObjCIVars())
783e470ca89SCyndy Ishida     visitObjCIVar(*IV, R.getName());
784e470ca89SCyndy Ishida }
785e470ca89SCyndy Ishida 
786e470ca89SCyndy Ishida void DylibVerifier::visitObjCCategory(const ObjCCategoryRecord &R) {
787e470ca89SCyndy Ishida   for (const ObjCIVarRecord *IV : R.getObjCIVars())
788e470ca89SCyndy Ishida     visitObjCIVar(*IV, R.getSuperClassName());
789e470ca89SCyndy Ishida }
790e470ca89SCyndy Ishida 
791e470ca89SCyndy Ishida DylibVerifier::Result DylibVerifier::verifyRemainingSymbols() {
792e470ca89SCyndy Ishida   if (getState() == Result::NoVerify)
793e470ca89SCyndy Ishida     return Result::NoVerify;
794e470ca89SCyndy Ishida   assert(!Dylib.empty() && "No binary to verify against");
795e470ca89SCyndy Ishida 
796a4de589dSCyndy Ishida   DWARFContext DWARFInfo;
797a4de589dSCyndy Ishida   DWARFCtx = &DWARFInfo;
798c24efffaSCyndy Ishida   Ctx.Target = Target(Architecture::AK_unknown, PlatformType::PLATFORM_UNKNOWN);
799c24efffaSCyndy Ishida   for (std::shared_ptr<RecordsSlice> Slice : Dylib) {
800c24efffaSCyndy Ishida     if (Ctx.Target.Arch == Slice->getTarget().Arch)
801c24efffaSCyndy Ishida       continue;
802e470ca89SCyndy Ishida     Ctx.DiscoveredFirstError = false;
803e470ca89SCyndy Ishida     Ctx.PrintArch = true;
804e470ca89SCyndy Ishida     Ctx.Target = Slice->getTarget();
805e470ca89SCyndy Ishida     Ctx.DylibSlice = Slice.get();
806e470ca89SCyndy Ishida     Slice->visit(*this);
807e470ca89SCyndy Ishida   }
808e470ca89SCyndy Ishida   return getState();
809e470ca89SCyndy Ishida }
810e470ca89SCyndy Ishida 
81127b2d7d4SCyndy Ishida bool DylibVerifier::verifyBinaryAttrs(const ArrayRef<Target> ProvidedTargets,
81227b2d7d4SCyndy Ishida                                       const BinaryAttrs &ProvidedBA,
81327b2d7d4SCyndy Ishida                                       const LibAttrs &ProvidedReexports,
81427b2d7d4SCyndy Ishida                                       const LibAttrs &ProvidedClients,
81527b2d7d4SCyndy Ishida                                       const LibAttrs &ProvidedRPaths,
81627b2d7d4SCyndy Ishida                                       const FileType &FT) {
81727b2d7d4SCyndy Ishida   assert(!Dylib.empty() && "Need dylib to verify.");
81827b2d7d4SCyndy Ishida 
81927b2d7d4SCyndy Ishida   // Pickup any load commands that can differ per slice to compare.
82027b2d7d4SCyndy Ishida   TargetList DylibTargets;
82127b2d7d4SCyndy Ishida   LibAttrs DylibReexports;
82227b2d7d4SCyndy Ishida   LibAttrs DylibClients;
82327b2d7d4SCyndy Ishida   LibAttrs DylibRPaths;
82427b2d7d4SCyndy Ishida   for (const std::shared_ptr<RecordsSlice> &RS : Dylib) {
82527b2d7d4SCyndy Ishida     DylibTargets.push_back(RS->getTarget());
82627b2d7d4SCyndy Ishida     const BinaryAttrs &BinInfo = RS->getBinaryAttrs();
82727b2d7d4SCyndy Ishida     for (const StringRef LibName : BinInfo.RexportedLibraries)
82827b2d7d4SCyndy Ishida       DylibReexports[LibName].set(DylibTargets.back().Arch);
82927b2d7d4SCyndy Ishida     for (const StringRef LibName : BinInfo.AllowableClients)
83027b2d7d4SCyndy Ishida       DylibClients[LibName].set(DylibTargets.back().Arch);
83127b2d7d4SCyndy Ishida     // Compare attributes that are only representable in >= TBD_V5.
83227b2d7d4SCyndy Ishida     if (FT >= FileType::TBD_V5)
83327b2d7d4SCyndy Ishida       for (const StringRef Name : BinInfo.RPaths)
83427b2d7d4SCyndy Ishida         DylibRPaths[Name].set(DylibTargets.back().Arch);
83527b2d7d4SCyndy Ishida   }
83627b2d7d4SCyndy Ishida 
83727b2d7d4SCyndy Ishida   // Check targets first.
83827b2d7d4SCyndy Ishida   ArchitectureSet ProvidedArchs = mapToArchitectureSet(ProvidedTargets);
83927b2d7d4SCyndy Ishida   ArchitectureSet DylibArchs = mapToArchitectureSet(DylibTargets);
84027b2d7d4SCyndy Ishida   if (ProvidedArchs != DylibArchs) {
84127b2d7d4SCyndy Ishida     Ctx.Diag->Report(diag::err_architecture_mismatch)
84227b2d7d4SCyndy Ishida         << ProvidedArchs << DylibArchs;
84327b2d7d4SCyndy Ishida     return false;
84427b2d7d4SCyndy Ishida   }
84527b2d7d4SCyndy Ishida   auto ProvidedPlatforms = mapToPlatformVersionSet(ProvidedTargets);
84627b2d7d4SCyndy Ishida   auto DylibPlatforms = mapToPlatformVersionSet(DylibTargets);
84727b2d7d4SCyndy Ishida   if (ProvidedPlatforms != DylibPlatforms) {
84827b2d7d4SCyndy Ishida     const bool DiffMinOS =
84927b2d7d4SCyndy Ishida         mapToPlatformSet(ProvidedTargets) == mapToPlatformSet(DylibTargets);
85027b2d7d4SCyndy Ishida     if (DiffMinOS)
85127b2d7d4SCyndy Ishida       Ctx.Diag->Report(diag::warn_platform_mismatch)
85227b2d7d4SCyndy Ishida           << ProvidedPlatforms << DylibPlatforms;
85327b2d7d4SCyndy Ishida     else {
85427b2d7d4SCyndy Ishida       Ctx.Diag->Report(diag::err_platform_mismatch)
85527b2d7d4SCyndy Ishida           << ProvidedPlatforms << DylibPlatforms;
85627b2d7d4SCyndy Ishida       return false;
85727b2d7d4SCyndy Ishida     }
85827b2d7d4SCyndy Ishida   }
85927b2d7d4SCyndy Ishida 
86027b2d7d4SCyndy Ishida   // Because InstallAPI requires certain attributes to match across architecture
86127b2d7d4SCyndy Ishida   // slices, take the first one to compare those with.
86227b2d7d4SCyndy Ishida   const BinaryAttrs &DylibBA = (*Dylib.begin())->getBinaryAttrs();
86327b2d7d4SCyndy Ishida 
86427b2d7d4SCyndy Ishida   if (ProvidedBA.InstallName != DylibBA.InstallName) {
86527b2d7d4SCyndy Ishida     Ctx.Diag->Report(diag::err_install_name_mismatch)
86627b2d7d4SCyndy Ishida         << ProvidedBA.InstallName << DylibBA.InstallName;
86727b2d7d4SCyndy Ishida     return false;
86827b2d7d4SCyndy Ishida   }
86927b2d7d4SCyndy Ishida 
87027b2d7d4SCyndy Ishida   if (ProvidedBA.CurrentVersion != DylibBA.CurrentVersion) {
87127b2d7d4SCyndy Ishida     Ctx.Diag->Report(diag::err_current_version_mismatch)
87227b2d7d4SCyndy Ishida         << ProvidedBA.CurrentVersion << DylibBA.CurrentVersion;
87327b2d7d4SCyndy Ishida     return false;
87427b2d7d4SCyndy Ishida   }
87527b2d7d4SCyndy Ishida 
87627b2d7d4SCyndy Ishida   if (ProvidedBA.CompatVersion != DylibBA.CompatVersion) {
87727b2d7d4SCyndy Ishida     Ctx.Diag->Report(diag::err_compatibility_version_mismatch)
87827b2d7d4SCyndy Ishida         << ProvidedBA.CompatVersion << DylibBA.CompatVersion;
87927b2d7d4SCyndy Ishida     return false;
88027b2d7d4SCyndy Ishida   }
88127b2d7d4SCyndy Ishida 
88227b2d7d4SCyndy Ishida   if (ProvidedBA.AppExtensionSafe != DylibBA.AppExtensionSafe) {
88327b2d7d4SCyndy Ishida     Ctx.Diag->Report(diag::err_appextension_safe_mismatch)
88427b2d7d4SCyndy Ishida         << (ProvidedBA.AppExtensionSafe ? "true" : "false")
88527b2d7d4SCyndy Ishida         << (DylibBA.AppExtensionSafe ? "true" : "false");
88627b2d7d4SCyndy Ishida     return false;
88727b2d7d4SCyndy Ishida   }
88827b2d7d4SCyndy Ishida 
88927b2d7d4SCyndy Ishida   if (!DylibBA.TwoLevelNamespace) {
89027b2d7d4SCyndy Ishida     Ctx.Diag->Report(diag::err_no_twolevel_namespace);
89127b2d7d4SCyndy Ishida     return false;
89227b2d7d4SCyndy Ishida   }
89327b2d7d4SCyndy Ishida 
89427b2d7d4SCyndy Ishida   if (ProvidedBA.OSLibNotForSharedCache != DylibBA.OSLibNotForSharedCache) {
89527b2d7d4SCyndy Ishida     Ctx.Diag->Report(diag::err_shared_cache_eligiblity_mismatch)
89627b2d7d4SCyndy Ishida         << (ProvidedBA.OSLibNotForSharedCache ? "true" : "false")
89727b2d7d4SCyndy Ishida         << (DylibBA.OSLibNotForSharedCache ? "true" : "false");
89827b2d7d4SCyndy Ishida     return false;
89927b2d7d4SCyndy Ishida   }
90027b2d7d4SCyndy Ishida 
90127b2d7d4SCyndy Ishida   if (ProvidedBA.ParentUmbrella.empty() && !DylibBA.ParentUmbrella.empty()) {
90227b2d7d4SCyndy Ishida     Ctx.Diag->Report(diag::err_parent_umbrella_missing)
90327b2d7d4SCyndy Ishida         << "installAPI option" << DylibBA.ParentUmbrella;
90427b2d7d4SCyndy Ishida     return false;
90527b2d7d4SCyndy Ishida   }
90627b2d7d4SCyndy Ishida 
90727b2d7d4SCyndy Ishida   if (!ProvidedBA.ParentUmbrella.empty() && DylibBA.ParentUmbrella.empty()) {
90827b2d7d4SCyndy Ishida     Ctx.Diag->Report(diag::err_parent_umbrella_missing)
90927b2d7d4SCyndy Ishida         << "binary file" << ProvidedBA.ParentUmbrella;
91027b2d7d4SCyndy Ishida     return false;
91127b2d7d4SCyndy Ishida   }
91227b2d7d4SCyndy Ishida 
91327b2d7d4SCyndy Ishida   if ((!ProvidedBA.ParentUmbrella.empty()) &&
91427b2d7d4SCyndy Ishida       (ProvidedBA.ParentUmbrella != DylibBA.ParentUmbrella)) {
91527b2d7d4SCyndy Ishida     Ctx.Diag->Report(diag::err_parent_umbrella_mismatch)
91627b2d7d4SCyndy Ishida         << ProvidedBA.ParentUmbrella << DylibBA.ParentUmbrella;
91727b2d7d4SCyndy Ishida     return false;
91827b2d7d4SCyndy Ishida   }
91927b2d7d4SCyndy Ishida 
92027b2d7d4SCyndy Ishida   auto CompareLibraries = [&](const LibAttrs &Provided, const LibAttrs &Dylib,
92127b2d7d4SCyndy Ishida                               unsigned DiagID_missing, unsigned DiagID_mismatch,
92227b2d7d4SCyndy Ishida                               bool Fatal = true) {
92327b2d7d4SCyndy Ishida     if (Provided == Dylib)
92427b2d7d4SCyndy Ishida       return true;
92527b2d7d4SCyndy Ishida 
92627b2d7d4SCyndy Ishida     for (const llvm::StringMapEntry<ArchitectureSet> &PAttr : Provided) {
92727b2d7d4SCyndy Ishida       const auto DAttrIt = Dylib.find(PAttr.getKey());
92827b2d7d4SCyndy Ishida       if (DAttrIt == Dylib.end()) {
92927b2d7d4SCyndy Ishida         Ctx.Diag->Report(DiagID_missing) << "binary file" << PAttr;
93027b2d7d4SCyndy Ishida         if (Fatal)
93127b2d7d4SCyndy Ishida           return false;
93227b2d7d4SCyndy Ishida       }
93327b2d7d4SCyndy Ishida 
93427b2d7d4SCyndy Ishida       if (PAttr.getValue() != DAttrIt->getValue()) {
93527b2d7d4SCyndy Ishida         Ctx.Diag->Report(DiagID_mismatch) << PAttr << *DAttrIt;
93627b2d7d4SCyndy Ishida         if (Fatal)
93727b2d7d4SCyndy Ishida           return false;
93827b2d7d4SCyndy Ishida       }
93927b2d7d4SCyndy Ishida     }
94027b2d7d4SCyndy Ishida 
94127b2d7d4SCyndy Ishida     for (const llvm::StringMapEntry<ArchitectureSet> &DAttr : Dylib) {
94227b2d7d4SCyndy Ishida       const auto PAttrIt = Provided.find(DAttr.getKey());
94327b2d7d4SCyndy Ishida       if (PAttrIt == Provided.end()) {
94427b2d7d4SCyndy Ishida         Ctx.Diag->Report(DiagID_missing) << "installAPI option" << DAttr;
94527b2d7d4SCyndy Ishida         if (!Fatal)
94627b2d7d4SCyndy Ishida           continue;
94727b2d7d4SCyndy Ishida         return false;
94827b2d7d4SCyndy Ishida       }
94927b2d7d4SCyndy Ishida 
95027b2d7d4SCyndy Ishida       if (PAttrIt->getValue() != DAttr.getValue()) {
95127b2d7d4SCyndy Ishida         if (Fatal)
95227b2d7d4SCyndy Ishida           llvm_unreachable("this case was already covered above.");
95327b2d7d4SCyndy Ishida       }
95427b2d7d4SCyndy Ishida     }
95527b2d7d4SCyndy Ishida     return true;
95627b2d7d4SCyndy Ishida   };
95727b2d7d4SCyndy Ishida 
95827b2d7d4SCyndy Ishida   if (!CompareLibraries(ProvidedReexports, DylibReexports,
95927b2d7d4SCyndy Ishida                         diag::err_reexported_libraries_missing,
96027b2d7d4SCyndy Ishida                         diag::err_reexported_libraries_mismatch))
96127b2d7d4SCyndy Ishida     return false;
96227b2d7d4SCyndy Ishida 
96327b2d7d4SCyndy Ishida   if (!CompareLibraries(ProvidedClients, DylibClients,
96427b2d7d4SCyndy Ishida                         diag::err_allowable_clients_missing,
96527b2d7d4SCyndy Ishida                         diag::err_allowable_clients_mismatch))
96627b2d7d4SCyndy Ishida     return false;
96727b2d7d4SCyndy Ishida 
96827b2d7d4SCyndy Ishida   if (FT >= FileType::TBD_V5) {
96927b2d7d4SCyndy Ishida     // Ignore rpath differences if building an asan variant, since the
97027b2d7d4SCyndy Ishida     //   compiler injects additional paths.
97127b2d7d4SCyndy Ishida     // FIXME: Building with sanitizers does not always change the install
97227b2d7d4SCyndy Ishida     //   name, so this is not a foolproof solution.
97327b2d7d4SCyndy Ishida     if (!ProvidedBA.InstallName.ends_with("_asan")) {
97427b2d7d4SCyndy Ishida       if (!CompareLibraries(ProvidedRPaths, DylibRPaths,
97527b2d7d4SCyndy Ishida                             diag::warn_rpaths_missing,
97627b2d7d4SCyndy Ishida                             diag::warn_rpaths_mismatch,
97727b2d7d4SCyndy Ishida                             /*Fatal=*/false))
97827b2d7d4SCyndy Ishida         return true;
97927b2d7d4SCyndy Ishida     }
98027b2d7d4SCyndy Ishida   }
98127b2d7d4SCyndy Ishida 
98227b2d7d4SCyndy Ishida   return true;
98327b2d7d4SCyndy Ishida }
98427b2d7d4SCyndy Ishida 
9854c18681aSCyndy Ishida std::unique_ptr<SymbolSet> DylibVerifier::takeExports() {
9864c18681aSCyndy Ishida   for (const auto &[Alias, Base] : Aliases) {
9874c18681aSCyndy Ishida     TargetList Targets;
9884c18681aSCyndy Ishida     SymbolFlags Flags = SymbolFlags::None;
9894c18681aSCyndy Ishida     if (const Symbol *Sym = Exports->findSymbol(Base.second, Base.first)) {
9904c18681aSCyndy Ishida       Flags = Sym->getFlags();
9914c18681aSCyndy Ishida       Targets = {Sym->targets().begin(), Sym->targets().end()};
9924c18681aSCyndy Ishida     }
9934c18681aSCyndy Ishida 
9944c18681aSCyndy Ishida     Record R(Alias.first, RecordLinkage::Exported, Flags);
9954c18681aSCyndy Ishida     SymbolContext SymCtx;
9964c18681aSCyndy Ishida     SymCtx.SymbolName = Alias.first;
9974c18681aSCyndy Ishida     SymCtx.Kind = Alias.second;
9984c18681aSCyndy Ishida     addSymbol(&R, SymCtx, std::move(Targets));
9994c18681aSCyndy Ishida   }
10004c18681aSCyndy Ishida 
10014c18681aSCyndy Ishida   return std::move(Exports);
10024c18681aSCyndy Ishida }
10034c18681aSCyndy Ishida 
1004f2794cceSCyndy Ishida } // namespace installapi
1005f2794cceSCyndy Ishida } // namespace clang
1006