diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -223,7 +223,11 @@ // 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(buf + sizeof(*hdr)); + auto getArchName = [](uint32_t cpuType, uint32_t cpuSubtype) { + return getArchitectureName(getArchitectureFromCpuType(cpuType, cpuSubtype)); + }; + std::vector archs; for (uint32_t i = 0, n = read32be(&hdr->nfat_arch); i < n; ++i) { if (reinterpret_cast(arch + i + 1) > buf + mbref.getBufferSize()) { @@ -238,8 +242,10 @@ // FIXME: LD64 has a more complex fallback logic here. // Consider implementing that as well? if (cpuType != static_cast(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 @@ 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; } diff --git a/lld/test/MachO/fat-arch.s b/lld/test/MachO/fat-arch.s --- a/lld/test/MachO/fat-arch.s +++ b/lld/test/MachO/fat-arch.s @@ -11,7 +11,11 @@ # 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