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 <mark@chromium.org>
This commit is contained in:
Leonard Grey 2023-03-13 18:14:34 -04:00
parent 9cc38fec8b
commit c179ddaa58
2 changed files with 26 additions and 67 deletions

View file

@ -210,22 +210,4 @@ const NXArchInfo *NXGetArchInfoFromCpuType(cpu_type_t cputype,
} }
return candidate; 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__ #endif // !__APPLE__

View file

@ -232,60 +232,37 @@ bool DumpSymbols::SetArchitecture(const ArchInfo& info) {
return true; return true;
} }
SuperFatArch* DumpSymbols::FindBestMatchForArchitecture( SuperFatArch* DumpSymbols::FindBestMatchForArchitecture(
cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) { cpu_type_t cpu_type,
// Check if all the object files can be converted to struct fat_arch. cpu_subtype_t cpu_subtype) {
bool can_convert_to_fat_arch = true; SuperFatArch* closest_match = nullptr;
vector<struct fat_arch> fat_arch_vector; for (auto& object_file : object_files_) {
for (vector<SuperFatArch>::const_iterator it = object_files_.begin(); if (static_cast<cpu_type_t>(object_file.cputype) == cpu_type) {
it != object_files_.end(); // If there's an exact match, return it directly.
++it) { if ((static_cast<cpu_subtype_t>(object_file.cpusubtype) &
struct fat_arch arch; ~CPU_SUBTYPE_MASK) == (cpu_subtype & ~CPU_SUBTYPE_MASK)) {
bool success = it->ConvertToFatArch(&arch); return &object_file;
if (!success) { }
can_convert_to_fat_arch = false; // Otherwise, hold on to this as the closest match since at least the CPU
break; // 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<uint32_t>(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<SuperFatArch>::iterator it = object_files_.begin();
it != object_files_.end();
++it) {
if (static_cast<cpu_type_t>(it->cputype) == cpu_type &&
(static_cast<cpu_subtype_t>(it->cpusubtype) & ~CPU_SUBTYPE_MASK) ==
(cpu_subtype & ~CPU_SUBTYPE_MASK))
return &*it;
}
// No exact match found. // No exact match found.
// TODO(erikchen): If it becomes necessary, we can copy the implementation of fprintf(stderr,
// NXFindBestFatArch, located at "Failed to find an exact match for an object file with cpu "
// http://web.mit.edu/darwin/src/modules/cctools/libmacho/arch.c. "type: %d and cpu subtype: %d.\n",
fprintf(stderr, "Failed to find an exact match for an object file with cpu " cpu_type, cpu_subtype);
"type: %d and cpu subtype: %d.\n", cpu_type, cpu_subtype); if (closest_match) {
if (!can_convert_to_fat_arch) { fprintf(stderr, "Using %s as the closest match.\n",
fprintf(stderr, "Furthermore, at least one object file is larger " GetNameFromCPUType(closest_match->cputype,
"than 2**32.\n"); closest_match->cpusubtype));
return closest_match;
} }
return NULL; return nullptr;
} }
string DumpSymbols::Identifier() { string DumpSymbols::Identifier() {