diff mbox series

libbacktrace patch committed: Add support for Mach-O 64-bit FAT files

Message ID CAOyqgcUsXnfBraQaQeowogEUdX7h-F7B+ApOxq3txjBLyZLdqw@mail.gmail.com
State New
Headers show
Series libbacktrace patch committed: Add support for Mach-O 64-bit FAT files | expand

Commit Message

Ian Lance Taylor Aug. 24, 2020, 8:10 p.m. UTC
This libbacktrace patch adds support for Mach-O 64-bit FAT files.
Bootstrapped and tested on x86_64-pc-linux-gnu.  Committed to
mainline.

Ian

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.
diff mbox series

Patch

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);