[clang] [InstallAPI] Capture & compare load commands that may differ per arch slice (PR #87674)

Zixu Wang via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 5 10:57:17 PDT 2024


================
@@ -702,5 +724,179 @@ DylibVerifier::Result DylibVerifier::verifyRemainingSymbols() {
   return getState();
 }
 
+bool DylibVerifier::verifyBinaryAttrs(const ArrayRef<Target> ProvidedTargets,
+                                      const BinaryAttrs &ProvidedBA,
+                                      const LibAttrs &ProvidedReexports,
+                                      const LibAttrs &ProvidedClients,
+                                      const LibAttrs &ProvidedRPaths,
+                                      const FileType &FT) {
+  assert(!Dylib.empty() && "Need dylib to verify.");
+
+  // Pickup any load commands that can differ per slice to compare.
+  TargetList DylibTargets;
+  LibAttrs DylibReexports;
+  LibAttrs DylibClients;
+  LibAttrs DylibRPaths;
+  for (const std::shared_ptr<RecordsSlice> &RS : Dylib) {
+    DylibTargets.push_back(RS->getTarget());
+    const BinaryAttrs &BinInfo = RS->getBinaryAttrs();
+    for (const StringRef LibName : BinInfo.RexportedLibraries)
+      DylibReexports[LibName].set(DylibTargets.back().Arch);
+    for (const StringRef LibName : BinInfo.AllowableClients)
+      DylibClients[LibName].set(DylibTargets.back().Arch);
+    // Compare attributes that are only representable in >= TBD_V5.
+    if (FT >= FileType::TBD_V5)
+      for (const StringRef Name : BinInfo.RPaths)
+        DylibRPaths[Name].set(DylibTargets.back().Arch);
+  }
+
+  // Check targets first.
+  ArchitectureSet ProvidedArchs = mapToArchitectureSet(ProvidedTargets);
+  ArchitectureSet DylibArchs = mapToArchitectureSet(DylibTargets);
+  if (ProvidedArchs != DylibArchs) {
+    Ctx.Diag->Report(diag::err_architecture_mismatch)
+        << ProvidedArchs << DylibArchs;
+    return false;
+  }
+  auto ProvidedPlatforms = mapToPlatformVersionSet(ProvidedTargets);
+  auto DylibPlatforms = mapToPlatformVersionSet(DylibTargets);
+  if (ProvidedPlatforms != DylibPlatforms) {
+    const bool DiffMinOS =
+        mapToPlatformSet(ProvidedTargets) == mapToPlatformSet(DylibTargets);
+    if (DiffMinOS)
+      Ctx.Diag->Report(diag::warn_platform_mismatch)
+          << ProvidedPlatforms << DylibPlatforms;
+    else {
+      Ctx.Diag->Report(diag::err_platform_mismatch)
+          << ProvidedPlatforms << DylibPlatforms;
+      return false;
+    }
+  }
+
+  // Because InstallAPI requires certain attributes to match across architecture
+  // slices, take the first one to compare those with.
+  const BinaryAttrs &DylibBA = (*Dylib.begin())->getBinaryAttrs();
+
+  if (ProvidedBA.InstallName != DylibBA.InstallName) {
+    Ctx.Diag->Report(diag::err_install_name_mismatch)
+        << ProvidedBA.InstallName << DylibBA.InstallName;
+    return false;
+  }
+
+  if (ProvidedBA.CurrentVersion != DylibBA.CurrentVersion) {
+    Ctx.Diag->Report(diag::err_current_version_mismatch)
+        << ProvidedBA.CurrentVersion << DylibBA.CurrentVersion;
+    return false;
+  }
+
+  if (ProvidedBA.CompatVersion != DylibBA.CompatVersion) {
+    Ctx.Diag->Report(diag::err_compatibility_version_mismatch)
+        << ProvidedBA.CompatVersion << DylibBA.CompatVersion;
+    return false;
+  }
+
+  if (ProvidedBA.AppExtensionSafe != DylibBA.AppExtensionSafe) {
+    Ctx.Diag->Report(diag::err_appextension_safe_mismatch)
+        << (ProvidedBA.AppExtensionSafe ? "true" : "false")
+        << (DylibBA.AppExtensionSafe ? "true" : "false");
+    return false;
+  }
+
+  if (!DylibBA.TwoLevelNamespace) {
+    Ctx.Diag->Report(diag::err_no_twolevel_namespace);
+    return false;
+  }
+
+  if (ProvidedBA.OSLibNotForSharedCache != DylibBA.OSLibNotForSharedCache) {
+    Ctx.Diag->Report(diag::err_shared_cache_eligiblity_mismatch)
+        << (ProvidedBA.OSLibNotForSharedCache ? "true" : "false")
+        << (DylibBA.OSLibNotForSharedCache ? "true" : "false");
+    return false;
+  }
+
+  if (ProvidedBA.ParentUmbrella.empty() && !DylibBA.ParentUmbrella.empty()) {
+    Ctx.Diag->Report(diag::err_parent_umbrella_missing)
+        << "installAPI option" << DylibBA.ParentUmbrella;
+    return false;
+  }
+
+  if (!ProvidedBA.ParentUmbrella.empty() && !DylibBA.ParentUmbrella.empty()) {
----------------
zixu-w wrote:

Should this be
```
!ProvidedBA.ParentUmbrella.empty() &&  DylibBA.ParentUmbrella.empty()
                                      ^ no negation here
```
?

https://github.com/llvm/llvm-project/pull/87674


More information about the cfe-commits mailing list