aboutsummaryrefslogtreecommitdiff
path: root/libbacktrace
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-08-24 13:06:52 -0700
committerIan Lance Taylor <iant@golang.org>2020-08-24 13:10:26 -0700
commit74c176ca2f1fe702f6e46d86f634685480094335 (patch)
tree63cf9c645ec97c8e98b4535e8187bc29732c73b6 /libbacktrace
parent0d166f4a8773a43d925be006e713b7d81626ddb9 (diff)
libbacktrace: add Mach-O 64-bit FAT support
libbacktrace/: * macho.c (MACH_O_MH_MAGIC_FAT_64): Define. (MACH_O_MH_CIGAM_FAT_64): Define. (struct macho_fat_arch_64): Define. (macho_add_fat): Add and use is_64 parameter. (macho_add): Recognize 64-bit fat files.
Diffstat (limited to 'libbacktrace')
-rw-r--r--libbacktrace/macho.c72
1 files changed, 54 insertions, 18 deletions
diff --git a/libbacktrace/macho.c b/libbacktrace/macho.c
index 3aea70cdbbe..bd737226ca6 100644
--- a/libbacktrace/macho.c
+++ b/libbacktrace/macho.c
@@ -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). */
@@ -740,14 +756,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;
@@ -765,21 +781,39 @@ macho_add_fat (struct backtrace_state *state, const char *filename,
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;
+ struct macho_fat_arch_64 fat_arch;
uint32_t fcputype;
- memcpy (&fat_arch,
- ((const char *) arch_view.data
- + i * sizeof (struct macho_fat_arch)),
- sizeof fat_arch);
+ if (is_64)
+ memcpy (&fat_arch,
+ (const char *) arch_view.data + i * arch_size,
+ arch_size);
+ else
+ {
+ struct macho_fat_arch fat_arch_32;
+
+ memcpy (&fat_arch_32,
+ (const char *) arch_view.data + i * arch_size,
+ 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;
+ fat_arch.size = (uint64_t) fat_arch_32.size;
+ fat_arch.align = fat_arch_32.align;
+ fat_arch.reserved = 0;
+ }
fcputype = fat_arch.cputype;
if (swapped)
@@ -787,19 +821,17 @@ macho_add_fat (struct backtrace_state *state, const char *filename,
if (fcputype == cputype)
{
- uint32_t foffset;
+ uint64_t foffset;
/* FIXME: What about cpusubtype? */
foffset = fat_arch.offset;
if (swapped)
- foffset = __builtin_bswap32 (foffset);
+ foffset = __builtin_bswap64 (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);
@@ -980,6 +1012,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 +1020,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 +1035,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);