mach-o: read and dump: prebound_dylib, prebind_cksum, twolevel_hints.
authorTristan Gingold <tristan.gingold@adacore.com>
Wed, 26 Mar 2014 14:01:53 +0000 (15:01 +0100)
committerTristan Gingold <tristan.gingold@adacore.com>
Wed, 2 Apr 2014 13:03:51 +0000 (15:03 +0200)
include/mach-o:
* external.h (mach_o_prebound_dylib_command_external)
(mach_o_prebind_cksum_command_external)
(mach_o_twolevel_hints_command_external): New types.

bfd/
* mach-o.h (bfd_mach_o_twolevel_hints_command)
(bfd_mach_o_prebind_cksum_command): New types.
(bfd_mach_o_prebound_dylib_command): Rewrite.
(bfd_mach_o_load_command): Add prebind_cksum and twolevel_hints
fields.
* mach-o.c (bfd_mach_o_read_prebound_dylib): Read and decode the
command.
(bfd_mach_o_read_prebind_cksum): New function.
(bfd_mach_o_read_twolevel_hints): Ditto.
(bfd_mach_o_read_command): Handle prebind cksum and twolevel hints
commands.

binutils/
* od-macho.c (OPT_TWOLEVEL_HINTS): New macro.
(options): Add entry for twolevel_hints.
(dump_data_in_code): Fix error message.
(dump_twolevel_hints): New function.
(dump_load_command): Handle prebound dylib, prebind cksum
and twolevel hints.
(mach_o_dump): Handle twolevel hints.

bfd/ChangeLog
bfd/mach-o.c
bfd/mach-o.h
binutils/ChangeLog
binutils/od-macho.c
include/mach-o/ChangeLog
include/mach-o/external.h

index 5c7b2b3..d2fb972 100644 (file)
@@ -1,3 +1,17 @@
+2014-04-02  Tristan Gingold  <gingold@adacore.com>
+
+       * mach-o.h (bfd_mach_o_twolevel_hints_command)
+       (bfd_mach_o_prebind_cksum_command): New types.
+       (bfd_mach_o_prebound_dylib_command): Rewrite.
+       (bfd_mach_o_load_command): Add prebind_cksum and twolevel_hints
+       fields.
+       * mach-o.c (bfd_mach_o_read_prebound_dylib): Read and decode the
+       command.
+       (bfd_mach_o_read_prebind_cksum): New function.
+       (bfd_mach_o_read_twolevel_hints): Ditto.
+       (bfd_mach_o_read_command): Handle prebind cksum and twolevel hints
+       commands.
+
 2014-04-02  Alan Modra  <amodra@gmail.com>
 
        * elfcode.h (bfd_from_remote_memory): Add "size" parameter.
index e33c01f..525607e 100644 (file)
@@ -3207,12 +3207,69 @@ bfd_mach_o_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
 }
 
 static int
-bfd_mach_o_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED,
-                                bfd_mach_o_load_command *command ATTRIBUTE_UNUSED)
+bfd_mach_o_read_prebound_dylib (bfd *abfd,
+                                bfd_mach_o_load_command *command)
 {
-  /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
+  bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib;
+  struct mach_o_prebound_dylib_command_external raw;
+  unsigned int nameoff;
+  unsigned int modoff;
+  unsigned int str_len;
+  unsigned char *str;
+
+  if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0
+      || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+    return -1;
+
+  nameoff = bfd_h_get_32 (abfd, raw.name);
+  modoff = bfd_h_get_32 (abfd, raw.linked_modules);
+  if (nameoff > command->len || modoff > command->len)
+    return -1;
+
+  str_len = command->len - sizeof (raw);
+  str = bfd_alloc (abfd, str_len);
+  if (str == NULL)
+    return -1;
+  if (bfd_bread (str, str_len, abfd) != str_len)
+    return -1;
+
+  cmd->name_offset = command->offset + nameoff;
+  cmd->nmodules = bfd_h_get_32 (abfd, raw.nmodules);
+  cmd->linked_modules_offset = command->offset + modoff;
+
+  cmd->name_str = (char *)str + nameoff - (sizeof (raw) + BFD_MACH_O_LC_SIZE);
+  cmd->linked_modules = str + modoff - (sizeof (raw) + BFD_MACH_O_LC_SIZE);
+  return 0;
+}
+
+static int
+bfd_mach_o_read_prebind_cksum (bfd *abfd,
+                              bfd_mach_o_load_command *command)
+{
+  bfd_mach_o_prebind_cksum_command *cmd = &command->command.prebind_cksum;
+  struct mach_o_prebind_cksum_command_external raw;
 
-  BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
+  if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0
+      || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+    return -1;
+
+  cmd->cksum = bfd_get_32 (abfd, raw.cksum);
+  return 0;
+}
+
+static int
+bfd_mach_o_read_twolevel_hints (bfd *abfd,
+                               bfd_mach_o_load_command *command)
+{
+  bfd_mach_o_twolevel_hints_command *cmd = &command->command.twolevel_hints;
+  struct mach_o_twolevel_hints_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 -1;
+
+  cmd->offset = bfd_get_32 (abfd, raw.offset);
+  cmd->nhints = bfd_get_32 (abfd, raw.nhints);
   return 0;
 }
 
@@ -3881,8 +3938,13 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
       if (bfd_mach_o_read_dysymtab (abfd, command) != 0)
        return -1;
       break;
-    case BFD_MACH_O_LC_TWOLEVEL_HINTS:
     case BFD_MACH_O_LC_PREBIND_CKSUM:
+      if (bfd_mach_o_read_prebind_cksum (abfd, command) != 0)
+       return -1;
+      break;
+    case BFD_MACH_O_LC_TWOLEVEL_HINTS:
+      if (bfd_mach_o_read_twolevel_hints (abfd, command) != 0)
+       return -1;
       break;
     case BFD_MACH_O_LC_UUID:
       if (bfd_mach_o_read_uuid (abfd, command) != 0)
index 4418b92..629459b 100644 (file)
@@ -375,6 +375,27 @@ bfd_mach_o_dysymtab_command;
 #define BFD_MACH_O_INDIRECT_SYMBOL_ABS   0x40000000
 #define BFD_MACH_O_INDIRECT_SYMBOL_SIZE  4
 
+/* For LC_TWOLEVEL_HINTS.  */
+
+typedef struct bfd_mach_o_twolevel_hints_command
+{
+  /* Offset to the hint table.  */
+  unsigned int offset;
+
+  /* Number of entries in the table.  */
+  unsigned int nhints;
+}
+bfd_mach_o_twolevel_hints_command;
+
+/* For LC_PREBIND_CKSUM.  */
+
+typedef struct bfd_mach_o_prebind_cksum_command
+{
+  /* Checksum or zero.  */
+  unsigned int cksum;
+}
+bfd_mach_o_prebind_cksum_command;
+
 /* For LC_THREAD or LC_UNIXTHREAD.  */
 
 typedef struct bfd_mach_o_thread_flavour
@@ -421,9 +442,12 @@ bfd_mach_o_dylib_command;
 
 typedef struct bfd_mach_o_prebound_dylib_command
 {
-  unsigned long name;                /* Library's path name.  */
-  unsigned long nmodules;            /* Number of modules in library.  */
-  unsigned long linked_modules;      /* Bit vector of linked modules.  */
+  unsigned int name_offset;           /* Library's path name.  */
+  unsigned int nmodules;              /* Number of modules in library.  */
+  unsigned int linked_modules_offset; /* Bit vector of linked modules.  */
+
+  char *name_str;
+  unsigned char *linked_modules;
 }
 bfd_mach_o_prebound_dylib_command;
 
@@ -535,6 +559,8 @@ typedef struct bfd_mach_o_load_command
     bfd_mach_o_dylib_command dylib;
     bfd_mach_o_dylinker_command dylinker;
     bfd_mach_o_prebound_dylib_command prebound_dylib;
+    bfd_mach_o_prebind_cksum_command prebind_cksum;
+    bfd_mach_o_twolevel_hints_command twolevel_hints;
     bfd_mach_o_uuid_command uuid;
     bfd_mach_o_linkedit_command linkedit;
     bfd_mach_o_str_command str;
index 60f50c3..56ea960 100644 (file)
@@ -1,3 +1,13 @@
+2014-04-02  Tristan Gingold  <gingold@adacore.com>
+
+       * od-macho.c (OPT_TWOLEVEL_HINTS): New macro.
+       (options): Add entry for twolevel_hints.
+       (dump_data_in_code): Fix error message.
+       (dump_twolevel_hints): New function.
+       (dump_load_command): Handle prebound dylib, prebind cksum
+       and twolevel hints.
+       (mach_o_dump): Handle twolevel hints.
+
 2014-04-01  Tristan Gingold  <gingold@adacore.com>
 
        * od-macho.c (OPT_DATA_IN_CODE): New macro.
index 31cce9d..d606a2b 100644 (file)
@@ -44,6 +44,7 @@
 #define OPT_COMPACT_UNWIND 7
 #define OPT_FUNCTION_STARTS 8
 #define OPT_DATA_IN_CODE 9
+#define OPT_TWOLEVEL_HINTS 10
 
 /* List of actions.  */
 static struct objdump_private_option options[] =
@@ -58,6 +59,7 @@ static struct objdump_private_option options[] =
     { "compact_unwind", 0 },
     { "function_starts", 0 },
     { "data_in_code", 0 },
+    { "twolevel_hints", 0 },
     { NULL, 0 }
   };
 
@@ -78,6 +80,7 @@ For Mach-O files:\n\
   compact_unwind   Display compact unwinding info\n\
   function_starts  Display start address of functions\n\
   data_in_code     Display data in code entries\n\
+  twolevel_hints   Display the two-level namespace lookup hints table\n\
 "));
 }
 
@@ -1004,7 +1007,7 @@ dump_data_in_code (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
   if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
       || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
     {
-      non_fatal (_("cannot read function starts"));
+      non_fatal (_("cannot read data_in_code"));
       free (buf);
       return;
     }
@@ -1032,6 +1035,45 @@ dump_data_in_code (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
 }
 
 static void
+dump_twolevel_hints (bfd *abfd, bfd_mach_o_twolevel_hints_command *cmd)
+{
+  size_t sz = 4 * cmd->nhints;
+  unsigned char *buf;
+  unsigned char *p;
+
+  buf = xmalloc (sz);
+  if (bfd_seek (abfd, cmd->offset, SEEK_SET) != 0
+      || bfd_bread (buf, sz, abfd) != sz)
+    {
+      non_fatal (_("cannot read twolevel hints"));
+      free (buf);
+      return;
+    }
+
+  for (p = buf; p < buf + sz; p += 4)
+    {
+      unsigned int v;
+      unsigned int isub_image;
+      unsigned int itoc;
+
+      v = bfd_get_32 (abfd, p);
+      if (bfd_big_endian (abfd))
+       {
+         isub_image = (v >> 24) & 0xff;
+         itoc = v & 0xffffff;
+       }
+      else
+       {
+         isub_image = v & 0xff;
+         itoc = (v >> 8) & 0xffffff;
+       }
+
+      printf ("  %3u %8u\n", isub_image, itoc);
+    }
+  free (buf);
+}
+
+static void
 dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
                    bfd_boolean verbose)
 {
@@ -1195,6 +1237,43 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
                version->a, version->b, version->c, version->d, version->e);
         break;
       }
+    case BFD_MACH_O_LC_PREBOUND_DYLIB:
+      {
+        bfd_mach_o_prebound_dylib_command *pbdy = &cmd->command.prebound_dylib;
+       unsigned char *lm = pbdy->linked_modules;
+       unsigned int j;
+       unsigned int last;
+
+        printf (" %s\n", pbdy->name_str);
+        printf ("   nmodules: %u\n", pbdy->nmodules);
+       printf ("   linked modules (at %u): ",
+               pbdy->linked_modules_offset - cmd->offset);
+       last = pbdy->nmodules > 32 ? 32 : pbdy->nmodules;
+       for (j = 0; j < last; j++)
+         printf ("%u", (lm[j >> 3] >> (j & 7)) & 1);
+       if (last < pbdy->nmodules)
+         printf ("...");
+       putchar ('\n');
+        break;
+      }
+    case BFD_MACH_O_LC_PREBIND_CKSUM:
+      {
+        bfd_mach_o_prebind_cksum_command *cksum = &cmd->command.prebind_cksum;
+        printf (" 0x%08x\n", cksum->cksum);
+        break;
+      }
+    case BFD_MACH_O_LC_TWOLEVEL_HINTS:
+      {
+        bfd_mach_o_twolevel_hints_command *hints =
+         &cmd->command.twolevel_hints;
+
+        printf ("\n"
+                "   table offset: 0x%08x  nbr hints: %u\n",
+               hints->offset, hints->nhints);
+       if (verbose)
+         dump_twolevel_hints (abfd, hints);
+        break;
+      }
     case BFD_MACH_O_LC_MAIN:
       {
         bfd_mach_o_main_command *entry = &cmd->command.main;
@@ -1688,6 +1767,8 @@ mach_o_dump (bfd *abfd)
     dump_load_commands (abfd, BFD_MACH_O_LC_FUNCTION_STARTS, 0);
   if (options[OPT_DATA_IN_CODE].selected)
     dump_load_commands (abfd, BFD_MACH_O_LC_DATA_IN_CODE, 0);
+  if (options[OPT_TWOLEVEL_HINTS].selected)
+    dump_load_commands (abfd, BFD_MACH_O_LC_TWOLEVEL_HINTS, 0);
   if (options[OPT_COMPACT_UNWIND].selected)
     {
       dump_section_content (abfd, "__LD", "__compact_unwind",
index 3624f8a..b3dc669 100644 (file)
@@ -1,3 +1,9 @@
+2014-04-02  Tristan Gingold  <gingold@adacore.com>
+
+       * external.h (mach_o_prebound_dylib_command_external)
+       (mach_o_prebind_cksum_command_external)
+       (mach_o_twolevel_hints_command_external): New types.
+
 2014-03-26  Tristan Gingold  <gingold@adacore.com>
 
        * loader.h (bfd_mach_o_cpu_type): Add BFD_MACH_O_CPU_TYPE_ARM64.
index d92c10e..4fb950b 100644 (file)
@@ -287,6 +287,24 @@ struct mach_o_dyld_info_command_external
   unsigned char export_size[4];
 };
 
+struct mach_o_prebound_dylib_command_external
+{
+  unsigned char name[4];
+  unsigned char nmodules[4];
+  unsigned char linked_modules[4];
+};
+
+struct mach_o_prebind_cksum_command_external
+{
+  unsigned char cksum[4];
+};
+
+struct mach_o_twolevel_hints_command_external
+{
+  unsigned char offset[4];
+  unsigned char nhints[4];
+};
+
 struct mach_o_version_min_command_external
 {
   unsigned char version[4];