Skip to content

Commit 89b2b50

Browse files
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.
1 parent aaa51b6 commit 89b2b50

File tree

1 file changed

+54
-18
lines changed

1 file changed

+54
-18
lines changed

macho.c

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ struct macho_header_64
7575

7676
struct macho_header_fat
7777
{
78-
uint32_t magic; /* Magic number (MACH_O_MH_MAGIC_FAT) */
78+
uint32_t magic; /* Magic number (MACH_O_MH_(MAGIC|CIGAM)_FAT(_64)?) */
7979
uint32_t nfat_arch; /* Number of components */
8080
};
8181

@@ -85,6 +85,8 @@ struct macho_header_fat
8585
#define MACH_O_MH_MAGIC_64 0xfeedfacf
8686
#define MACH_O_MH_MAGIC_FAT 0xcafebabe
8787
#define MACH_O_MH_CIGAM_FAT 0xbebafeca
88+
#define MACH_O_MH_MAGIC_FAT_64 0xcafebabf
89+
#define MACH_O_MH_CIGAM_FAT_64 0xbfbafeca
8890

8991
/* Value for the header filetype field. */
9092

@@ -105,6 +107,20 @@ struct macho_fat_arch
105107
uint32_t align; /* Alignment of this entry */
106108
};
107109

110+
/* A component of a 64-bit fat file. This is used if the magic field
111+
is MAGIC_FAT_64. This is only used when some file size or file
112+
offset is too large to represent in the 32-bit format. */
113+
114+
struct macho_fat_arch_64
115+
{
116+
uint32_t cputype; /* CPU type */
117+
uint32_t cpusubtype; /* CPU subtype */
118+
uint64_t offset; /* File offset of this entry */
119+
uint64_t size; /* Size of this entry */
120+
uint32_t align; /* Alignment of this entry */
121+
uint32_t reserved; /* Reserved */
122+
};
123+
108124
/* Values for the fat_arch cputype field (and the header cputype
109125
field). */
110126

@@ -740,14 +756,14 @@ static int
740756
macho_add_fat (struct backtrace_state *state, const char *filename,
741757
int descriptor, int swapped, off_t offset,
742758
const unsigned char *match_uuid, uintptr_t base_address,
743-
int skip_symtab, uint32_t nfat_arch,
759+
int skip_symtab, uint32_t nfat_arch, int is_64,
744760
backtrace_error_callback error_callback, void *data,
745761
fileline *fileline_fn, int *found_sym)
746762
{
747763
int arch_view_valid;
748764
unsigned int cputype;
765+
size_t arch_size;
749766
struct backtrace_view arch_view;
750-
size_t archoffset;
751767
unsigned int i;
752768

753769
arch_view_valid = 0;
@@ -765,41 +781,57 @@ macho_add_fat (struct backtrace_state *state, const char *filename,
765781
goto fail;
766782
#endif
767783

784+
if (is_64)
785+
arch_size = sizeof (struct macho_fat_arch_64);
786+
else
787+
arch_size = sizeof (struct macho_fat_arch);
788+
768789
if (!backtrace_get_view (state, descriptor, offset,
769-
nfat_arch * sizeof (struct macho_fat_arch),
790+
nfat_arch * arch_size,
770791
error_callback, data, &arch_view))
771792
goto fail;
772793

773-
archoffset = 0;
774794
for (i = 0; i < nfat_arch; ++i)
775795
{
776-
struct macho_fat_arch fat_arch;
796+
struct macho_fat_arch_64 fat_arch;
777797
uint32_t fcputype;
778798

779-
memcpy (&fat_arch,
780-
((const char *) arch_view.data
781-
+ i * sizeof (struct macho_fat_arch)),
782-
sizeof fat_arch);
799+
if (is_64)
800+
memcpy (&fat_arch,
801+
(const char *) arch_view.data + i * arch_size,
802+
arch_size);
803+
else
804+
{
805+
struct macho_fat_arch fat_arch_32;
806+
807+
memcpy (&fat_arch_32,
808+
(const char *) arch_view.data + i * arch_size,
809+
arch_size);
810+
fat_arch.cputype = fat_arch_32.cputype;
811+
fat_arch.cpusubtype = fat_arch_32.cpusubtype;
812+
fat_arch.offset = (uint64_t) fat_arch_32.offset;
813+
fat_arch.size = (uint64_t) fat_arch_32.size;
814+
fat_arch.align = fat_arch_32.align;
815+
fat_arch.reserved = 0;
816+
}
783817

784818
fcputype = fat_arch.cputype;
785819
if (swapped)
786820
fcputype = __builtin_bswap32 (fcputype);
787821

788822
if (fcputype == cputype)
789823
{
790-
uint32_t foffset;
824+
uint64_t foffset;
791825

792826
/* FIXME: What about cpusubtype? */
793827
foffset = fat_arch.offset;
794828
if (swapped)
795-
foffset = __builtin_bswap32 (foffset);
829+
foffset = __builtin_bswap64 (foffset);
796830
backtrace_release_view (state, &arch_view, error_callback, data);
797831
return macho_add (state, filename, descriptor, foffset, match_uuid,
798832
base_address, skip_symtab, error_callback, data,
799833
fileline_fn, found_sym);
800834
}
801-
802-
archoffset += sizeof (struct macho_fat_arch);
803835
}
804836

805837
error_callback (data, "could not find executable in fat file", 0);
@@ -980,17 +1012,20 @@ macho_add (struct backtrace_state *state, const char *filename, int descriptor,
9801012
hdroffset = offset + sizeof (struct macho_header_64);
9811013
break;
9821014
case MACH_O_MH_MAGIC_FAT:
1015+
case MACH_O_MH_MAGIC_FAT_64:
9831016
{
9841017
struct macho_header_fat fat_header;
9851018

9861019
hdroffset = offset + sizeof (struct macho_header_fat);
9871020
memcpy (&fat_header, &header, sizeof fat_header);
9881021
return macho_add_fat (state, filename, descriptor, 0, hdroffset,
9891022
match_uuid, base_address, skip_symtab,
990-
fat_header.nfat_arch, error_callback, data,
991-
fileline_fn, found_sym);
1023+
fat_header.nfat_arch,
1024+
header.magic == MACH_O_MH_MAGIC_FAT_64,
1025+
error_callback, data, fileline_fn, found_sym);
9921026
}
9931027
case MACH_O_MH_CIGAM_FAT:
1028+
case MACH_O_MH_CIGAM_FAT_64:
9941029
{
9951030
struct macho_header_fat fat_header;
9961031
uint32_t nfat_arch;
@@ -1000,8 +1035,9 @@ macho_add (struct backtrace_state *state, const char *filename, int descriptor,
10001035
nfat_arch = __builtin_bswap32 (fat_header.nfat_arch);
10011036
return macho_add_fat (state, filename, descriptor, 1, hdroffset,
10021037
match_uuid, base_address, skip_symtab,
1003-
nfat_arch, error_callback, data,
1004-
fileline_fn, found_sym);
1038+
nfat_arch,
1039+
header.magic == MACH_O_MH_CIGAM_FAT_64,
1040+
error_callback, data, fileline_fn, found_sym);
10051041
}
10061042
default:
10071043
error_callback (data, "executable file is not in Mach-O format", 0);

0 commit comments

Comments
 (0)