[lld-macho] Improve invalid fat binary warning
authorKeith Smiley <keithbsmiley@gmail.com>
Fri, 13 Jan 2023 22:17:07 +0000 (14:17 -0800)
committerKeith Smiley <keithbsmiley@gmail.com>
Sat, 14 Jan 2023 23:21:16 +0000 (15:21 -0800)
This nearly mirrors ld64's error for this case:

ld: warning: ignoring file path/to/file, file is universal (armv7,arm64) but does not contain the x86_64 architecture: path/to/file

Differential Revision: https://reviews.llvm.org/D141729

lld/MachO/InputFiles.cpp
lld/test/MachO/fat-arch.s

index 50c6987..e128910 100644 (file)
@@ -223,7 +223,11 @@ std::optional<MemoryBufferRef> macho::readFile(StringRef path) {
   // real files for different CPU ISAs. Here, we search for a file that matches
   // with the current link target and returns it as a MemoryBufferRef.
   const auto *arch = reinterpret_cast<const fat_arch *>(buf + sizeof(*hdr));
+  auto getArchName = [](uint32_t cpuType, uint32_t cpuSubtype) {
+    return getArchitectureName(getArchitectureFromCpuType(cpuType, cpuSubtype));
+  };
 
+  std::vector<StringRef> archs;
   for (uint32_t i = 0, n = read32be(&hdr->nfat_arch); i < n; ++i) {
     if (reinterpret_cast<const char *>(arch + i + 1) >
         buf + mbref.getBufferSize()) {
@@ -238,8 +242,10 @@ std::optional<MemoryBufferRef> macho::readFile(StringRef path) {
     // FIXME: LD64 has a more complex fallback logic here.
     // Consider implementing that as well?
     if (cpuType != static_cast<uint32_t>(target->cpuType) ||
-        cpuSubtype != target->cpuSubtype)
+        cpuSubtype != target->cpuSubtype) {
+      archs.emplace_back(getArchName(cpuType, cpuSubtype));
       continue;
+    }
 
     uint32_t offset = read32be(&arch[i].offset);
     uint32_t size = read32be(&arch[i].size);
@@ -251,7 +257,9 @@ std::optional<MemoryBufferRef> macho::readFile(StringRef path) {
                                               path.copy(bAlloc));
   }
 
-  warn("unable to find matching architecture in " + path);
+  auto targetArchName = getArchName(target->cpuType, target->cpuSubtype);
+  warn(path + ": ignoring file because it is universal (" + join(archs, ",") +
+       ") but does not contain the " + targetArchName + " architecture");
   return std::nullopt;
 }
 
index dd6b61b..59b82cd 100644 (file)
 # RUN: llvm-lipo %t.i386.o -create -o %t.noarch.o
 # RUN: not %no-fatal-warnings-lld -o /dev/null %t.noarch.o 2>&1 | \
 # RUN:    FileCheck %s -DFILE=%t.noarch.o
-# CHECK: warning: unable to find matching architecture in [[FILE]]
+# CHECK: warning: [[FILE]]: ignoring file because it is universal (i386) but does not contain the x86_64 architecture
+
+# RUN: not %lld -arch arm64 -o /dev/null %t.fat.o 2>&1 | \
+# RUN:    FileCheck --check-prefix=CHECK-FAT %s -DFILE=%t.fat.o
+# CHECK-FAT: error: [[FILE]]: ignoring file because it is universal (i386,x86_64) but does not contain the arm64 architecture
 
 ## Validates that we read the cpu-subtype correctly from a fat exec.
 # RUN: %lld -o %t.x86_64.out %t.x86_64.o