[Mach-O]: Handle new Darwin 12 features

Tristan Gingold gingold@adacore.com
Wed Nov 14 11:03:00 GMT 2012


Hi,

with this patch, bfd will correctly read newest Mach-O binary files, and objdump will display some of them.

Committed on trunk.

Tristan.

bfd/
2012-11-14  Tristan Gingold  <gingold@adacore.com>

	* mach-o.c (bfd_mach_o_read_main)
	(bfd_mach_o_read_source_version): New functions.
	(bfd_mach_o_read_command): Handle BFD_MACH_O_LC_DATA_IN_CODE,
	BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS, BFD_MACH_O_LC_MAIN,
	BFD_MACH_O_LC_SOURCE_VERSION.
	* mach-o.h (bfd_mach_o_main_command)
	(bfd_mach_o_source_version_command): New types.
	(bfd_mach_o_load_command): Add fields for these new types.

binutils/
2012-11-14  Tristan Gingold  <gingold@adacore.com>

	* od-macho.c (bfd_mach_o_load_command_name): Add new definitions.
	(dump_load_command): Handle BFD_MACH_O_LC_SOURCE_VERSION
	and BFD_MACH_O_LC_MAIN.


Index: bfd/mach-o.c
===================================================================
RCS file: /cvs/src/src/bfd/mach-o.c,v
retrieving revision 1.106
diff -c -r1.106 mach-o.c
*** bfd/mach-o.c	14 Nov 2012 10:29:46 -0000	1.106
--- bfd/mach-o.c	14 Nov 2012 11:00:09 -0000
***************
*** 3666,3671 ****
--- 3666,3713 ----
    return TRUE;
  }
  
+ static bfd_boolean
+ bfd_mach_o_read_main (bfd *abfd, bfd_mach_o_load_command *command)
+ {
+   bfd_mach_o_main_command *cmd = &command->command.main;
+   struct mach_o_entry_point_command_external raw;
+ 
+   if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0
+       || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+     return FALSE;
+ 
+   cmd->entryoff = bfd_get_64 (abfd, raw.entryoff);
+   cmd->stacksize = bfd_get_64 (abfd, raw.stacksize);
+   return TRUE;
+ }
+ 
+ static bfd_boolean
+ bfd_mach_o_read_source_version (bfd *abfd, bfd_mach_o_load_command *command)
+ {
+   bfd_mach_o_source_version_command *cmd = &command->command.source_version;
+   struct mach_o_source_version_command_external raw;
+   bfd_uint64_t ver;
+ 
+   if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0
+       || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+     return FALSE;
+ 
+   ver = bfd_get_64 (abfd, raw.version);
+   /* Note: we use a serie of shift to avoid shift > 32 (for which gcc
+      generates warnings) in case of the host doesn't support 64 bit
+      integers.  */
+   cmd->e = ver & 0x3ff;
+   ver >>= 10;
+   cmd->d = ver & 0x3ff;
+   ver >>= 10;
+   cmd->c = ver & 0x3ff;
+   ver >>= 10;
+   cmd->b = ver & 0x3ff;
+   ver >>= 10;
+   cmd->a = ver & 0xffffff;
+   return TRUE;
+ }
+ 
  static int
  bfd_mach_o_read_segment (bfd *abfd,
                           bfd_mach_o_load_command *command,
***************
*** 3842,3847 ****
--- 3884,3891 ----
      case BFD_MACH_O_LC_CODE_SIGNATURE:
      case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
      case BFD_MACH_O_LC_FUNCTION_STARTS:
+     case BFD_MACH_O_LC_DATA_IN_CODE:
+     case BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS:
        if (bfd_mach_o_read_linkedit (abfd, command) != 0)
  	return -1;
        break;
***************
*** 3858,3863 ****
--- 3902,3915 ----
        if (!bfd_mach_o_read_version_min (abfd, command))
  	return -1;
        break;
+     case BFD_MACH_O_LC_MAIN:
+       if (!bfd_mach_o_read_main (abfd, command))
+ 	return -1;
+       break;
+     case BFD_MACH_O_LC_SOURCE_VERSION:
+       if (!bfd_mach_o_read_source_version (abfd, command))
+ 	return -1;
+       break;
      default:
        (*_bfd_error_handler)(_("%B: unknown load command 0x%lx"),
           abfd, (unsigned long) command->type);
Index: bfd/mach-o.h
===================================================================
RCS file: /cvs/src/src/bfd/mach-o.h,v
retrieving revision 1.45
diff -c -r1.45 mach-o.h
*** bfd/mach-o.h	13 Jul 2012 14:22:50 -0000	1.45
--- bfd/mach-o.h	14 Nov 2012 11:00:09 -0000
***************
*** 467,473 ****
  typedef struct bfd_mach_o_dyld_info_command
  {
    /* File offset and size to rebase info.  */
!   unsigned int rebase_off; 
    unsigned int rebase_size;
  
    /* File offset and size of binding info.  */
--- 467,473 ----
  typedef struct bfd_mach_o_dyld_info_command
  {
    /* File offset and size to rebase info.  */
!   unsigned int rebase_off;
    unsigned int rebase_size;
  
    /* File offset and size of binding info.  */
***************
*** 505,510 ****
--- 505,527 ----
  }
  bfd_mach_o_encryption_info_command;
  
+ typedef struct bfd_mach_o_main_command
+ {
+   bfd_uint64_t entryoff;
+   bfd_uint64_t stacksize;
+ }
+ bfd_mach_o_main_command;
+ 
+ typedef struct bfd_mach_o_source_version_command
+ {
+   unsigned int a;
+   unsigned short b;
+   unsigned short c;
+   unsigned short d;
+   unsigned short e;
+ }
+ bfd_mach_o_source_version_command;
+ 
  typedef struct bfd_mach_o_load_command
  {
    bfd_mach_o_load_command_type type;
***************
*** 527,532 ****
--- 544,551 ----
      bfd_mach_o_version_min_command version_min;
      bfd_mach_o_encryption_info_command encryption_info;
      bfd_mach_o_fvmlib_command fvmlib;
+     bfd_mach_o_main_command main;
+     bfd_mach_o_source_version_command source_version;
    }
    command;
  }
Index: binutils/od-macho.c
===================================================================
RCS file: /cvs/src/src/binutils/od-macho.c,v
retrieving revision 1.6
diff -c -r1.6 od-macho.c
*** binutils/od-macho.c	9 Feb 2012 04:51:44 -0000	1.6
--- binutils/od-macho.c	14 Nov 2012 11:00:09 -0000
***************
*** 182,187 ****
--- 182,191 ----
    { "version_min_iphoneos", BFD_MACH_O_LC_VERSION_MIN_IPHONEOS},
    { "function_starts", BFD_MACH_O_LC_FUNCTION_STARTS},
    { "dyld_environment", BFD_MACH_O_LC_DYLD_ENVIRONMENT},
+   { "main", BFD_MACH_O_LC_MAIN},
+   { "data_in_code", BFD_MACH_O_LC_DATA_IN_CODE},
+   { "source_version", BFD_MACH_O_LC_SOURCE_VERSION},
+   { "dylib_code_sign_drs", BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS},
    { NULL, 0}
  };
  
***************
*** 1036,1041 ****
--- 1040,1066 ----
          printf (" %u.%u.%u\n", ver->rel, ver->maj, ver->min);
        }
        break;
+     case BFD_MACH_O_LC_SOURCE_VERSION:
+       {
+         bfd_mach_o_source_version_command *version =
+ 	  &cmd->command.source_version;
+         printf ("\n"
+                 "   version a.b.c.d.e: %u.%u.%u.%u.%u\n",
+ 		version->a, version->b, version->c, version->d, version->e);
+         break;
+       }
+     case BFD_MACH_O_LC_MAIN:
+       {
+         bfd_mach_o_main_command *entry = &cmd->command.main;
+         printf ("\n"
+                 "   entry offset: ");
+ 	printf_vma (entry->entryoff);
+         printf ("\n"
+                 "   stack size:   ");
+ 	printf_vma (entry->stacksize);
+ 	printf ("\n");
+         break;
+       }
      default:
        putchar ('\n');
        printf ("  offset: 0x%08lx\n", (unsigned long)cmd->offset);



More information about the Binutils mailing list