https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96973
--- Comment #4 from Francois-Xavier Coudert <fxcoudert at gcc dot gnu.org> ---
I've identified the issue and found a fix. The problem is in the calculation of
the offset when !is_64. The current code is take the uint32_t offset value,
casting it into a uint64_t, then calling bswap64, which is wrong.
The correct way is to call bswap32 and then cast to uint64_t.
diff --git a/libbacktrace/macho.c b/libbacktrace/macho.c
index bd737226ca6..5974d8d8a5b 100644
--- a/libbacktrace/macho.c
+++ b/libbacktrace/macho.c
@@ -797,9 +797,13 @@ macho_add_fat (struct backtrace_state *state, const char
*filename,
uint32_t fcputype;
if (is_64)
- memcpy (&fat_arch,
- (const char *) arch_view.data + i * arch_size,
- arch_size);
+ {
+ memcpy (&fat_arch,
+ (const char *) arch_view.data + i * arch_size,
+ arch_size);
+ if (swapped)
+ fat_arch.offset = __builtin_bswap64 (fat_arch.offset);
+ }
else
{
struct macho_fat_arch fat_arch_32;
@@ -809,7 +813,10 @@ macho_add_fat (struct backtrace_state *state, const char
*filename,
arch_size);
fat_arch.cputype = fat_arch_32.cputype;
fat_arch.cpusubtype = fat_arch_32.cpusubtype;
- fat_arch.offset = (uint64_t) fat_arch_32.offset;
+ if (swapped)
+ fat_arch.offset = (uint64_t) __builtin_bswap32(fat_arch_32.offset);
+ else
+ fat_arch.offset = (uint64_t) fat_arch_32.offset;
fat_arch.size = (uint64_t) fat_arch_32.size;
fat_arch.align = fat_arch_32.align;
fat_arch.reserved = 0;
@@ -821,14 +828,9 @@ macho_add_fat (struct backtrace_state *state, const char
*filename,
if (fcputype == cputype)
{
- uint64_t foffset;
-
/* FIXME: What about cpusubtype? */
- foffset = fat_arch.offset;
- if (swapped)
- foffset = __builtin_bswap64 (foffset);
backtrace_release_view (state, &arch_view, error_callback, data);
- return macho_add (state, filename, descriptor, foffset, match_uuid,
+ return macho_add (state, filename, descriptor, fat_arch.offset,
match_uuid,
base_address, skip_symtab, error_callback, data,
fileline_fn, found_sym);
}