From 5c29e3b3f342885f6f6a80a7c3b8af6951c3d359 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Thu, 20 Apr 2023 18:08:13 +0800 Subject: [PATCH] macho.c: update to a more complete source Borrowed from: https://github.com/ianlancetaylor/libbacktrace/blob/master/macho.c --- src/vendor/libbacktrace/macho.c | 100 +++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 27 deletions(-) diff --git a/src/vendor/libbacktrace/macho.c b/src/vendor/libbacktrace/macho.c index 3aea70c..d00aea9 100644 --- a/src/vendor/libbacktrace/macho.c +++ b/src/vendor/libbacktrace/macho.c @@ -1,5 +1,5 @@ /* elf.c -- Get debug data from a Mach-O file for backtraces. - Copyright (C) 2020 Free Software Foundation, Inc. + Copyright (C) 2020-2021 Free Software Foundation, Inc. Written by Ian Lance Taylor, Google. Redistribution and use in source and binary forms, with or without @@ -75,7 +75,7 @@ struct macho_header_64 struct macho_header_fat { - uint32_t magic; /* Magic number (MACH_O_MH_MAGIC_FAT) */ + uint32_t magic; /* Magic number (MACH_O_MH_(MAGIC|CIGAM)_FAT(_64)?) */ uint32_t nfat_arch; /* Number of components */ }; @@ -85,6 +85,8 @@ struct macho_header_fat #define MACH_O_MH_MAGIC_64 0xfeedfacf #define MACH_O_MH_MAGIC_FAT 0xcafebabe #define MACH_O_MH_CIGAM_FAT 0xbebafeca +#define MACH_O_MH_MAGIC_FAT_64 0xcafebabf +#define MACH_O_MH_CIGAM_FAT_64 0xbfbafeca /* Value for the header filetype field. */ @@ -105,6 +107,20 @@ struct macho_fat_arch uint32_t align; /* Alignment of this entry */ }; +/* A component of a 64-bit fat file. This is used if the magic field + is MAGIC_FAT_64. This is only used when some file size or file + offset is too large to represent in the 32-bit format. */ + +struct macho_fat_arch_64 +{ + uint32_t cputype; /* CPU type */ + uint32_t cpusubtype; /* CPU subtype */ + uint64_t offset; /* File offset of this entry */ + uint64_t size; /* Size of this entry */ + uint32_t align; /* Alignment of this entry */ + uint32_t reserved; /* Reserved */ +}; + /* Values for the fat_arch cputype field (and the header cputype field). */ @@ -112,9 +128,11 @@ struct macho_fat_arch #define MACH_O_CPU_TYPE_X86 7 #define MACH_O_CPU_TYPE_ARM 12 +#define MACH_O_CPU_TYPE_PPC 18 #define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64) #define MACH_O_CPU_TYPE_ARM64 (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64) +#define MACH_O_CPU_TYPE_PPC64 (MACH_O_CPU_TYPE_PPC | MACH_O_CPU_ARCH_ABI64) /* The header of a load command. */ @@ -740,14 +758,14 @@ static int macho_add_fat (struct backtrace_state *state, const char *filename, int descriptor, int swapped, off_t offset, const unsigned char *match_uuid, uintptr_t base_address, - int skip_symtab, uint32_t nfat_arch, + int skip_symtab, uint32_t nfat_arch, int is_64, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, int *found_sym) { int arch_view_valid; unsigned int cputype; + size_t arch_size; struct backtrace_view arch_view; - size_t archoffset; unsigned int i; arch_view_valid = 0; @@ -760,46 +778,69 @@ macho_add_fat (struct backtrace_state *state, const char *filename, cputype = MACH_O_CPU_TYPE_ARM64; #elif defined (__arm__) cputype = MACH_O_CPU_TYPE_ARM; +#elif defined (__ppc__) + cputype = MACH_O_CPU_TYPE_PPC; +#elif defined (__ppc64__) + cputype = MACH_O_CPU_TYPE_PPC64; #else error_callback (data, "unknown Mach-O architecture", 0); goto fail; #endif + if (is_64) + arch_size = sizeof (struct macho_fat_arch_64); + else + arch_size = sizeof (struct macho_fat_arch); + if (!backtrace_get_view (state, descriptor, offset, - nfat_arch * sizeof (struct macho_fat_arch), + nfat_arch * arch_size, error_callback, data, &arch_view)) goto fail; - archoffset = 0; for (i = 0; i < nfat_arch; ++i) { - struct macho_fat_arch fat_arch; uint32_t fcputype; + uint64_t foffset; + + if (is_64) + { + struct macho_fat_arch_64 fat_arch_64; - memcpy (&fat_arch, - ((const char *) arch_view.data - + i * sizeof (struct macho_fat_arch)), - sizeof fat_arch); + memcpy (&fat_arch_64, + (const char *) arch_view.data + i * arch_size, + arch_size); + fcputype = fat_arch_64.cputype; + foffset = fat_arch_64.offset; + if (swapped) + { + fcputype = __builtin_bswap32 (fcputype); + foffset = __builtin_bswap64 (foffset); + } + } + else + { + struct macho_fat_arch fat_arch_32; - fcputype = fat_arch.cputype; - if (swapped) - fcputype = __builtin_bswap32 (fcputype); + memcpy (&fat_arch_32, + (const char *) arch_view.data + i * arch_size, + arch_size); + fcputype = fat_arch_32.cputype; + foffset = (uint64_t) fat_arch_32.offset; + if (swapped) + { + fcputype = __builtin_bswap32 (fcputype); + foffset = (uint64_t) __builtin_bswap32 ((uint32_t) foffset); + } + } if (fcputype == cputype) { - uint32_t foffset; - /* FIXME: What about cpusubtype? */ - foffset = fat_arch.offset; - if (swapped) - foffset = __builtin_bswap32 (foffset); backtrace_release_view (state, &arch_view, error_callback, data); return macho_add (state, filename, descriptor, foffset, match_uuid, base_address, skip_symtab, error_callback, data, fileline_fn, found_sym); } - - archoffset += sizeof (struct macho_fat_arch); } error_callback (data, "could not find executable in fat file", 0); @@ -868,6 +909,7 @@ macho_add_dsym (struct backtrace_state *state, const char *filename, dsymsuffixdirlen = strlen (dsymsuffixdir); dsymlen = (dirnamelen + + 1 + basenamelen + dsymsuffixdirlen + basenamelen @@ -890,7 +932,7 @@ macho_add_dsym (struct backtrace_state *state, const char *filename, if (diralc != NULL) { - backtrace_free (state, diralc, dirnamelen, error_callback, data); + backtrace_free (state, diralc, dirnamelen + 1, error_callback, data); diralc = NULL; } @@ -980,6 +1022,7 @@ macho_add (struct backtrace_state *state, const char *filename, int descriptor, hdroffset = offset + sizeof (struct macho_header_64); break; case MACH_O_MH_MAGIC_FAT: + case MACH_O_MH_MAGIC_FAT_64: { struct macho_header_fat fat_header; @@ -987,10 +1030,12 @@ macho_add (struct backtrace_state *state, const char *filename, int descriptor, memcpy (&fat_header, &header, sizeof fat_header); return macho_add_fat (state, filename, descriptor, 0, hdroffset, match_uuid, base_address, skip_symtab, - fat_header.nfat_arch, error_callback, data, - fileline_fn, found_sym); + fat_header.nfat_arch, + header.magic == MACH_O_MH_MAGIC_FAT_64, + error_callback, data, fileline_fn, found_sym); } case MACH_O_MH_CIGAM_FAT: + case MACH_O_MH_CIGAM_FAT_64: { struct macho_header_fat fat_header; uint32_t nfat_arch; @@ -1000,8 +1045,9 @@ macho_add (struct backtrace_state *state, const char *filename, int descriptor, nfat_arch = __builtin_bswap32 (fat_header.nfat_arch); return macho_add_fat (state, filename, descriptor, 1, hdroffset, match_uuid, base_address, skip_symtab, - nfat_arch, error_callback, data, - fileline_fn, found_sym); + nfat_arch, + header.magic == MACH_O_MH_CIGAM_FAT_64, + error_callback, data, fileline_fn, found_sym); } default: error_callback (data, "executable file is not in Mach-O format", 0); @@ -1222,7 +1268,7 @@ backtrace_initialize (struct backtrace_state *state, const char *filename, mff = macho_nodebug; if (!macho_add (state, name, d, 0, NULL, base_address, 0, error_callback, data, &mff, &mfs)) - return 0; + continue; if (mff != macho_nodebug) macho_fileline_fn = mff; -- 2.40.0