// 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()) {
// 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);
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;
}
# 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