From c179ddaa58e0ec3093f98de555ad5791e9cb432a Mon Sep 17 00:00:00 2001 From: Leonard Grey Date: Mon, 13 Mar 2023 18:14:34 -0400 Subject: [PATCH] Mac: don't call NXFindBestFatArch `NXFindBestFatArch` is deprecated in macOS 13. We use this when an architecture is passed in via the `-a` flag. Unfortunately, neither of the potential replacements can help with this use case: - `macho_for_each_slice` as suggested in a reply to FB11955188 just enumerates slices, without the logic for inexact matches (for example, x86_64h -> x86_64 or arm64e -> arm64). - `macho_best_slice` as recommended by the deprecation notice only supports finding a suitable slice to run on the local machine. We could adapt the logic in `NXFindBestFatArch` but it gets quite complex for some architectures. Instead, this change adapts the `NXFindBestFatArch` polyfill used in `dump_syms_mac` for Linux, which returns an exact match if possible, and the first slice that matches the requested CPU type otherwise. I think this is probably Good Enough for most cases; if not, we can try porting the x86_64 and ARM logic and falling back to this for the rest. Change-Id: I3b269dab7246eced768cecd994e915debd95721a Bug: chromium:14206541420654 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/4335477 Reviewed-by: Mark Mentovai --- src/common/mac/arch_utilities.cc | 18 -------- src/common/mac/dump_syms.cc | 75 +++++++++++--------------------- 2 files changed, 26 insertions(+), 67 deletions(-) diff --git a/src/common/mac/arch_utilities.cc b/src/common/mac/arch_utilities.cc index cdc1dfa5..febf8a22 100644 --- a/src/common/mac/arch_utilities.cc +++ b/src/common/mac/arch_utilities.cc @@ -210,22 +210,4 @@ const NXArchInfo *NXGetArchInfoFromCpuType(cpu_type_t cputype, } return candidate; } - -struct fat_arch *NXFindBestFatArch(cpu_type_t cputype, - cpu_subtype_t cpusubtype, - struct fat_arch *fat_archs, - uint32_t nfat_archs) { - struct fat_arch *candidate = NULL; - for (uint32_t f = 0; f < nfat_archs; ++f) { - if (fat_archs[f].cputype == cputype) { - if (fat_archs[f].cpusubtype == cpusubtype) { - return &fat_archs[f]; - } - if (!candidate) { - candidate = &fat_archs[f]; - } - } - } - return candidate; -} #endif // !__APPLE__ diff --git a/src/common/mac/dump_syms.cc b/src/common/mac/dump_syms.cc index 6396e97a..04ccae25 100644 --- a/src/common/mac/dump_syms.cc +++ b/src/common/mac/dump_syms.cc @@ -232,60 +232,37 @@ bool DumpSymbols::SetArchitecture(const ArchInfo& info) { return true; } + SuperFatArch* DumpSymbols::FindBestMatchForArchitecture( - cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) { - // Check if all the object files can be converted to struct fat_arch. - bool can_convert_to_fat_arch = true; - vector fat_arch_vector; - for (vector::const_iterator it = object_files_.begin(); - it != object_files_.end(); - ++it) { - struct fat_arch arch; - bool success = it->ConvertToFatArch(&arch); - if (!success) { - can_convert_to_fat_arch = false; - break; + cpu_type_t cpu_type, + cpu_subtype_t cpu_subtype) { + SuperFatArch* closest_match = nullptr; + for (auto& object_file : object_files_) { + if (static_cast(object_file.cputype) == cpu_type) { + // If there's an exact match, return it directly. + if ((static_cast(object_file.cpusubtype) & + ~CPU_SUBTYPE_MASK) == (cpu_subtype & ~CPU_SUBTYPE_MASK)) { + return &object_file; + } + // Otherwise, hold on to this as the closest match since at least the CPU + // type matches. + if (!closest_match) { + closest_match = &object_file; + } } - fat_arch_vector.push_back(arch); } - - // If all the object files can be converted to struct fat_arch, use - // NXFindBestFatArch. - if (can_convert_to_fat_arch) { - const struct fat_arch* best_match - = NXFindBestFatArch(cpu_type, cpu_subtype, &fat_arch_vector[0], - static_cast(fat_arch_vector.size())); - - for (size_t i = 0; i < fat_arch_vector.size(); ++i) { - if (best_match == &fat_arch_vector[i]) - return &object_files_[i]; - } - assert(best_match == NULL); - // Fall through since NXFindBestFatArch can't find arm slices on x86_64 - // macOS 13. See FB11955188. - } - - // Check for an exact match with cpu_type and cpu_subtype. - for (vector::iterator it = object_files_.begin(); - it != object_files_.end(); - ++it) { - if (static_cast(it->cputype) == cpu_type && - (static_cast(it->cpusubtype) & ~CPU_SUBTYPE_MASK) == - (cpu_subtype & ~CPU_SUBTYPE_MASK)) - return &*it; - } - // No exact match found. - // TODO(erikchen): If it becomes necessary, we can copy the implementation of - // NXFindBestFatArch, located at - // http://web.mit.edu/darwin/src/modules/cctools/libmacho/arch.c. - fprintf(stderr, "Failed to find an exact match for an object file with cpu " - "type: %d and cpu subtype: %d.\n", cpu_type, cpu_subtype); - if (!can_convert_to_fat_arch) { - fprintf(stderr, "Furthermore, at least one object file is larger " - "than 2**32.\n"); + fprintf(stderr, + "Failed to find an exact match for an object file with cpu " + "type: %d and cpu subtype: %d.\n", + cpu_type, cpu_subtype); + if (closest_match) { + fprintf(stderr, "Using %s as the closest match.\n", + GetNameFromCPUType(closest_match->cputype, + closest_match->cpusubtype)); + return closest_match; } - return NULL; + return nullptr; } string DumpSymbols::Identifier() {