[PATCH 0/6] Fixes for new mach-o load commands

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/6] Fixes for new mach-o load commands

Roman Bolshakov
Apple has added a set of new load commands that weren't handled by bfd.
Some of them are rarely processed by binutils, like binaries with
LC_VERSION_MIN_TVOS.

But inability to handle LC_BUILD_VERSION resulted in a few bug reports,
and rendered binutils/gdb to be unusable with Mojave binaries:
  binutils/23728, gdb/23742, binutils/23746

The patch series implements processing of the new commands in bfd and
dump routines in objectdump.

Roman Bolshakov (6):
  mach-o: Don't split version into a few fields
  mach-o: Print sdk field in LC_VERSION_MIN_*
  mach-o: Print LC_VERSION_MIN_WATCHOS
  mach-o: Handle LC_VERSION_MIN_TVOS
  mach-o: Handle LC_NOTE
  mach-o: Handle LC_BUILD_VERSION command

 bfd/ChangeLog             |  19 +++++++
 bfd/mach-o.c              |  48 +++++++++++++++---
 bfd/mach-o.h              |  44 ++++++++++++++--
 binutils/ChangeLog        |  11 ++++
 binutils/od-macho.c       | 103 +++++++++++++++++++++++++++++++++++++-
 include/ChangeLog         |  11 ++++
 include/mach-o/external.h |  17 ++++++-
 include/mach-o/loader.h   |   5 +-
 8 files changed, 244 insertions(+), 14 deletions(-)

--
2.19.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 1/6] mach-o: Don't split version into a few fields

Roman Bolshakov
X.Y.Z tuple is used for minos version and sdk version fields in a number of
load commands:
  LC_VERSION_MIN_MACOSX
  LC_VERSION_MIN_IOS
  LC_VERSION_MIN_WATCHOS
  LC_VERSION_MIN_TVOS
  LC_BUILD_VERSION

We could use a macro to avoid code duplication for reading and setting
the X/Y/Z fields in all the load commands. But since there're no users
of the fields except od, we can just add a function that properly prints
all version components out of 4-byte unsigned integer and remove the
version subfields until they're really needed.

This also fixes incorrect length of the first version subfield as it
should be two bytes long instead of one:
  X.Y.Z is encoded in nibbles xxxx.yy.zz
---
 bfd/ChangeLog       |  7 +++++++
 bfd/mach-o.c        |  6 +-----
 bfd/mach-o.h        |  6 ++----
 binutils/ChangeLog  |  5 +++++
 binutils/od-macho.c | 13 ++++++++++++-
 5 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index d8b50f5381..4015c26cbf 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2018-11-06  Roman Bolshakov <[hidden email]>
+
+ * mach-o.h (bfd_mach_o_version_min_command): Don't split version into
+ a few fields.
+ * mach-o.c (bfd_mach_o_read_version_min): Don't split version into a
+ few fields.
+
 2018-11-02  Alan Modra  <[hidden email]>
 
  PR 23850
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 1b461f5988..7e4aa7d068 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -4598,15 +4598,11 @@ bfd_mach_o_read_version_min (bfd *abfd, bfd_mach_o_load_command *command)
 {
   bfd_mach_o_version_min_command *cmd = &command->command.version_min;
   struct mach_o_version_min_command_external raw;
-  unsigned int ver;
 
   if (bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
     return FALSE;
 
-  ver = bfd_get_32 (abfd, raw.version);
-  cmd->rel = ver >> 16;
-  cmd->maj = ver >> 8;
-  cmd->min = ver;
+  cmd->version = bfd_get_32 (abfd, raw.version);
   cmd->reserved = bfd_get_32 (abfd, raw.reserved);
   return TRUE;
 }
diff --git a/bfd/mach-o.h b/bfd/mach-o.h
index d80d43991e..4fd229f352 100644
--- a/bfd/mach-o.h
+++ b/bfd/mach-o.h
@@ -519,10 +519,8 @@ bfd_mach_o_dyld_info_command;
 
 typedef struct bfd_mach_o_version_min_command
 {
-  unsigned char rel;
-  unsigned char maj;
-  unsigned char min;
-  unsigned int reserved;
+  uint32_t version;
+  uint32_t reserved;
 }
 bfd_mach_o_version_min_command;
 
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index bdbee0fff6..d8970aae88 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,8 @@
+2018-11-06  Roman Bolshakov  <[hidden email]>
+
+ * od-macho.c (printf_version): New.
+ (dump_load_command): Use it to print version.
+
 2018-11-03  H.J. Lu  <[hidden email]>
 
  * elfedit.c (update_elf_header): Move EI_MAG? check to ...
diff --git a/binutils/od-macho.c b/binutils/od-macho.c
index 8153adae92..98551118c0 100644
--- a/binutils/od-macho.c
+++ b/binutils/od-macho.c
@@ -1438,6 +1438,15 @@ dump_twolevel_hints (bfd *abfd, bfd_mach_o_twolevel_hints_command *cmd)
   free (buf);
 }
 
+static void
+printf_version (uint32_t version) {
+  uint32_t maj, min, upd;
+  maj = (version >> 16) & 0xffff;
+  min = (version >> 8) & 0xff;
+  upd = version & 0xff;
+  printf ("%u.%u.%u", maj, min, upd);
+}
+
 static void
 dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
                    unsigned int idx, bfd_boolean verbose)
@@ -1585,7 +1594,9 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
       {
         bfd_mach_o_version_min_command *ver = &cmd->command.version_min;
 
-        printf ("    %u.%u.%u\n", ver->rel, ver->maj, ver->min);
+        printf ("   os: ");
+        printf_version (ver->version);
+        printf ("\n");
       }
       break;
     case BFD_MACH_O_LC_SOURCE_VERSION:
--
2.19.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 2/6] mach-o: Print sdk field in LC_VERSION_MIN_*

Roman Bolshakov
In reply to this post by Roman Bolshakov
sdk field was read by bfd but never printed.
Rename it to sdk and dump it in od.

Signed-off-by: Roman Bolshakov <[hidden email]>
Signed-off-by: Saagar Jha  <[hidden email]>
Cc: Tristan Gingold <[hidden email]>
---
 bfd/ChangeLog             | 5 +++--
 bfd/mach-o.c              | 2 +-
 bfd/mach-o.h              | 2 +-
 binutils/ChangeLog        | 3 ++-
 binutils/od-macho.c       | 2 ++
 include/ChangeLog         | 6 ++++++
 include/mach-o/external.h | 2 +-
 7 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4015c26cbf..7dcdb45d3f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,9 +1,10 @@
 2018-11-06  Roman Bolshakov <[hidden email]>
+    Saagar Jha  <[hidden email]>
 
  * mach-o.h (bfd_mach_o_version_min_command): Don't split version into
- a few fields.
+ a few fields. Rename reserved to sdk.
  * mach-o.c (bfd_mach_o_read_version_min): Don't split version into a
- few fields.
+ few fields. Rename reserved to sdk.
 
 2018-11-02  Alan Modra  <[hidden email]>
 
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 7e4aa7d068..45d774f14e 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -4603,7 +4603,7 @@ bfd_mach_o_read_version_min (bfd *abfd, bfd_mach_o_load_command *command)
     return FALSE;
 
   cmd->version = bfd_get_32 (abfd, raw.version);
-  cmd->reserved = bfd_get_32 (abfd, raw.reserved);
+  cmd->sdk = bfd_get_32 (abfd, raw.sdk);
   return TRUE;
 }
 
diff --git a/bfd/mach-o.h b/bfd/mach-o.h
index 4fd229f352..28ccb09c69 100644
--- a/bfd/mach-o.h
+++ b/bfd/mach-o.h
@@ -520,7 +520,7 @@ bfd_mach_o_dyld_info_command;
 typedef struct bfd_mach_o_version_min_command
 {
   uint32_t version;
-  uint32_t reserved;
+  uint32_t sdk;
 }
 bfd_mach_o_version_min_command;
 
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index d8970aae88..2e75d67dcd 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,7 +1,8 @@
 2018-11-06  Roman Bolshakov  <[hidden email]>
+    Saagar Jha  <[hidden email]>
 
  * od-macho.c (printf_version): New.
- (dump_load_command): Use it to print version.
+ (dump_load_command): Use it to print version. Print sdk version.
 
 2018-11-03  H.J. Lu  <[hidden email]>
 
diff --git a/binutils/od-macho.c b/binutils/od-macho.c
index 98551118c0..c8972eaf7b 100644
--- a/binutils/od-macho.c
+++ b/binutils/od-macho.c
@@ -1596,6 +1596,8 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
 
         printf ("   os: ");
         printf_version (ver->version);
+        printf ("\n   sdk: ");
+        printf_version (ver->sdk);
         printf ("\n");
       }
       break;
diff --git a/include/ChangeLog b/include/ChangeLog
index 124efb1775..b1115e973f 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,9 @@
+2018-11-06  Roman Bolshakov <[hidden email]>
+    Saagar Jha  <[hidden email]>
+
+ * mach-o/external.h (mach_o_version_min_command_external): Rename
+ reserved to sdk.
+
 2018-11-06  Sudakshina Das  <[hidden email]>
 
  * opcode/arm.h (ARM_ARCH_V8_5A): Move ARM_EXT2_PREDRES and
diff --git a/include/mach-o/external.h b/include/mach-o/external.h
index 2609bad982..aa7260a58a 100644
--- a/include/mach-o/external.h
+++ b/include/mach-o/external.h
@@ -308,7 +308,7 @@ struct mach_o_twolevel_hints_command_external
 struct mach_o_version_min_command_external
 {
   unsigned char version[4];
-  unsigned char reserved[4];
+  unsigned char sdk[4];
 };
 
 struct mach_o_encryption_info_command_external
--
2.19.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 3/6] mach-o: Print LC_VERSION_MIN_WATCHOS

Roman Bolshakov
In reply to this post by Roman Bolshakov
Content of LC_VERSION_MIN_WATCHOS gets parsed by bfd but objdump doesn't
print it.

Signed-off-by: Roman Bolshakov <[hidden email]>
Cc: Tristan Gingold <[hidden email]>
---
 binutils/ChangeLog  | 3 ++-
 binutils/od-macho.c | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 2e75d67dcd..d57efdd14f 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -2,7 +2,8 @@
     Saagar Jha  <[hidden email]>
 
  * od-macho.c (printf_version): New.
- (dump_load_command): Use it to print version. Print sdk version.
+ (dump_load_command): Use it to print version. Print sdk version. Print
+ version info for watchOS.
 
 2018-11-03  H.J. Lu  <[hidden email]>
 
diff --git a/binutils/od-macho.c b/binutils/od-macho.c
index c8972eaf7b..dec6228f48 100644
--- a/binutils/od-macho.c
+++ b/binutils/od-macho.c
@@ -209,6 +209,7 @@ static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
   { "encryption_info_64", BFD_MACH_O_LC_ENCRYPTION_INFO_64},
   { "linker_options", BFD_MACH_O_LC_LINKER_OPTIONS},
   { "linker_optimization_hint", BFD_MACH_O_LC_LINKER_OPTIMIZATION_HINT},
+  { "version_min_watchos", BFD_MACH_O_LC_VERSION_MIN_WATCHOS},
   { NULL, 0}
 };
 
@@ -1591,6 +1592,7 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
       break;
     case BFD_MACH_O_LC_VERSION_MIN_MACOSX:
     case BFD_MACH_O_LC_VERSION_MIN_IPHONEOS:
+    case BFD_MACH_O_LC_VERSION_MIN_WATCHOS:
       {
         bfd_mach_o_version_min_command *ver = &cmd->command.version_min;
 
--
2.19.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 4/6] mach-o: Handle LC_VERSION_MIN_TVOS

Roman Bolshakov
In reply to this post by Roman Bolshakov
The load command was introduced shortly after LC_VERSION_MIN_WATCHOS. It
has exactly the same format as the other load commands from the same
family.

Signed-off-by: Roman Bolshakov <[hidden email]>
Cc: Tristan Gingold <[hidden email]>
---
 bfd/ChangeLog           | 1 +
 bfd/mach-o.c            | 1 +
 binutils/ChangeLog      | 2 +-
 binutils/od-macho.c     | 2 ++
 include/ChangeLog       | 1 +
 include/mach-o/loader.h | 1 +
 6 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7dcdb45d3f..b1df3af4ba 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -5,6 +5,7 @@
  a few fields. Rename reserved to sdk.
  * mach-o.c (bfd_mach_o_read_version_min): Don't split version into a
  few fields. Rename reserved to sdk.
+ (bfd_mach_o_read_command): Handle LC_VERSION_MIN_TVOS.
 
 2018-11-02  Alan Modra  <[hidden email]>
 
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 45d774f14e..57ca8fb169 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -4873,6 +4873,7 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
     case BFD_MACH_O_LC_VERSION_MIN_MACOSX:
     case BFD_MACH_O_LC_VERSION_MIN_IPHONEOS:
     case BFD_MACH_O_LC_VERSION_MIN_WATCHOS:
+    case BFD_MACH_O_LC_VERSION_MIN_TVOS:
       if (!bfd_mach_o_read_version_min (abfd, command))
  return FALSE;
       break;
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index d57efdd14f..3db9bcdad8 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -3,7 +3,7 @@
 
  * od-macho.c (printf_version): New.
  (dump_load_command): Use it to print version. Print sdk version. Print
- version info for watchOS.
+ version info for watchOS and tvOS.
 
 2018-11-03  H.J. Lu  <[hidden email]>
 
diff --git a/binutils/od-macho.c b/binutils/od-macho.c
index dec6228f48..43a89bd68d 100644
--- a/binutils/od-macho.c
+++ b/binutils/od-macho.c
@@ -209,6 +209,7 @@ static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
   { "encryption_info_64", BFD_MACH_O_LC_ENCRYPTION_INFO_64},
   { "linker_options", BFD_MACH_O_LC_LINKER_OPTIONS},
   { "linker_optimization_hint", BFD_MACH_O_LC_LINKER_OPTIMIZATION_HINT},
+  { "version_min_tvos", BFD_MACH_O_LC_VERSION_MIN_TVOS},
   { "version_min_watchos", BFD_MACH_O_LC_VERSION_MIN_WATCHOS},
   { NULL, 0}
 };
@@ -1593,6 +1594,7 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
     case BFD_MACH_O_LC_VERSION_MIN_MACOSX:
     case BFD_MACH_O_LC_VERSION_MIN_IPHONEOS:
     case BFD_MACH_O_LC_VERSION_MIN_WATCHOS:
+    case BFD_MACH_O_LC_VERSION_MIN_TVOS:
       {
         bfd_mach_o_version_min_command *ver = &cmd->command.version_min;
 
diff --git a/include/ChangeLog b/include/ChangeLog
index b1115e973f..25a5826664 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -3,6 +3,7 @@
 
  * mach-o/external.h (mach_o_version_min_command_external): Rename
  reserved to sdk.
+ * mach-o/loader.h (BFD_MACH_O_LC_VERSION_MIN_TVOS): Define
 
 2018-11-06  Sudakshina Das  <[hidden email]>
 
diff --git a/include/mach-o/loader.h b/include/mach-o/loader.h
index c075a8e023..19c5e91d64 100644
--- a/include/mach-o/loader.h
+++ b/include/mach-o/loader.h
@@ -185,6 +185,7 @@ typedef enum bfd_mach_o_load_command_type
   BFD_MACH_O_LC_ENCRYPTION_INFO_64 = 0x2c, /* Encrypted 64 bit seg info.  */
   BFD_MACH_O_LC_LINKER_OPTIONS = 0x2d, /* Linker options.  */
   BFD_MACH_O_LC_LINKER_OPTIMIZATION_HINT = 0x2e, /* Optimization hints.  */
+  BFD_MACH_O_LC_VERSION_MIN_TVOS = 0x2f, /* Minimal tvOS version.  */
   BFD_MACH_O_LC_VERSION_MIN_WATCHOS = 0x30 /* Minimal WatchOS version.  */
 }
 bfd_mach_o_load_command_type;
--
2.19.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 5/6] mach-o: Handle LC_NOTE

Roman Bolshakov
In reply to this post by Roman Bolshakov
This is a new command to describe a region of any data. Initially, it's
used in in MH_CORE files.

Signed-off-by: Roman Bolshakov <[hidden email]>
Signed-off-by: Saagar Jha <[hidden email]>
Cc: Tristan Gingold <[hidden email]>
---
 bfd/ChangeLog             |  4 +++-
 bfd/mach-o.c              | 19 +++++++++++++++++++
 bfd/mach-o.h              |  9 +++++++++
 binutils/ChangeLog        |  2 +-
 binutils/od-macho.c       | 13 +++++++++++++
 include/ChangeLog         |  4 +++-
 include/mach-o/external.h |  7 +++++++
 include/mach-o/loader.h   |  3 ++-
 8 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b1df3af4ba..1f017f6fcd 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -3,9 +3,11 @@
 
  * mach-o.h (bfd_mach_o_version_min_command): Don't split version into
  a few fields. Rename reserved to sdk.
+ (struct bfd_mach_o_note_command): New.
  * mach-o.c (bfd_mach_o_read_version_min): Don't split version into a
  few fields. Rename reserved to sdk.
- (bfd_mach_o_read_command): Handle LC_VERSION_MIN_TVOS.
+ (bfd_mach_o_read_command): Handle LC_VERSION_MIN_TVOS, LC_NOTE.
+ (bfd_mach_o_read_note): New.
 
 2018-11-02  Alan Modra  <[hidden email]>
 
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 57ca8fb169..c5d6277c54 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -4677,6 +4677,21 @@ bfd_mach_o_read_source_version (bfd *abfd, bfd_mach_o_load_command *command)
   return TRUE;
 }
 
+static bfd_boolean
+bfd_mach_o_read_note (bfd *abfd, bfd_mach_o_load_command *command)
+{
+  bfd_mach_o_note_command *cmd = &command->command.note;
+  struct mach_o_note_command_external raw;
+
+  if (bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+    return FALSE;
+
+  memcpy (cmd->data_owner, raw.data_owner, 16);
+  cmd->offset = bfd_get_64 (abfd, raw.offset);
+  cmd->size = bfd_get_64 (abfd, raw.size);
+  return TRUE;
+}
+
 static bfd_boolean
 bfd_mach_o_read_segment (bfd *abfd,
  bfd_mach_o_load_command *command,
@@ -4885,6 +4900,10 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
       if (!bfd_mach_o_read_source_version (abfd, command))
  return FALSE;
       break;
+    case BFD_MACH_O_LC_NOTE:
+      if (!bfd_mach_o_read_note (abfd, command))
+        return FALSE;
+      break;
     default:
       command->len = 0;
       _bfd_error_handler (_("%pB: unknown load command %#x"),
diff --git a/bfd/mach-o.h b/bfd/mach-o.h
index 28ccb09c69..805c30e4e2 100644
--- a/bfd/mach-o.h
+++ b/bfd/mach-o.h
@@ -549,6 +549,14 @@ typedef struct bfd_mach_o_source_version_command
 }
 bfd_mach_o_source_version_command;
 
+typedef struct bfd_mach_o_note_command
+{
+  char data_owner[16];
+  bfd_uint64_t offset;
+  bfd_uint64_t size;
+}
+bfd_mach_o_note_command;
+
 typedef struct bfd_mach_o_load_command
 {
   /* Next command in the single linked list.  */
@@ -582,6 +590,7 @@ typedef struct bfd_mach_o_load_command
     bfd_mach_o_fvmlib_command fvmlib;
     bfd_mach_o_main_command main;
     bfd_mach_o_source_version_command source_version;
+    bfd_mach_o_note_command note;
   } command;
 }
 bfd_mach_o_load_command;
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 3db9bcdad8..266ce272d9 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -3,7 +3,7 @@
 
  * od-macho.c (printf_version): New.
  (dump_load_command): Use it to print version. Print sdk version. Print
- version info for watchOS and tvOS.
+ version info for watchOS and tvOS. Print LC_NOTE.
 
 2018-11-03  H.J. Lu  <[hidden email]>
 
diff --git a/binutils/od-macho.c b/binutils/od-macho.c
index 43a89bd68d..4f9bba1d55 100644
--- a/binutils/od-macho.c
+++ b/binutils/od-macho.c
@@ -211,6 +211,7 @@ static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
   { "linker_optimization_hint", BFD_MACH_O_LC_LINKER_OPTIMIZATION_HINT},
   { "version_min_tvos", BFD_MACH_O_LC_VERSION_MIN_TVOS},
   { "version_min_watchos", BFD_MACH_O_LC_VERSION_MIN_WATCHOS},
+  { "note", BFD_MACH_O_LC_NOTE},
   { NULL, 0}
 };
 
@@ -1660,6 +1661,18 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
  printf ("\n");
         break;
       }
+    case BFD_MACH_O_LC_NOTE:
+      {
+        bfd_mach_o_note_command *note = &cmd->command.note;
+        printf ("   data owner: %.16s\n", note->data_owner);
+        printf ("   offset:     ");
+ printf_uint64 (note->offset);
+        printf ("\n"
+                "   size:       ");
+ printf_uint64 (note->size);
+ printf ("\n");
+        break;
+      }
     default:
       break;
     }
diff --git a/include/ChangeLog b/include/ChangeLog
index 25a5826664..f86bbbf08c 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,9 +1,11 @@
 2018-11-06  Roman Bolshakov <[hidden email]>
     Saagar Jha  <[hidden email]>
 
- * mach-o/external.h (mach_o_version_min_command_external): Rename
+ * mach-o/external.h (mach_o_nversion_min_command_external): Rename
  reserved to sdk.
+ (mach_o_note_command_external): New
  * mach-o/loader.h (BFD_MACH_O_LC_VERSION_MIN_TVOS): Define
+ (BFD_MACH_O_LC_NOTE): Define
 
 2018-11-06  Sudakshina Das  <[hidden email]>
 
diff --git a/include/mach-o/external.h b/include/mach-o/external.h
index aa7260a58a..7889b57794 100644
--- a/include/mach-o/external.h
+++ b/include/mach-o/external.h
@@ -345,6 +345,13 @@ struct mach_o_source_version_command_external
    and 24 bits for A.  */
 };
 
+struct mach_o_note_command_external
+{
+  unsigned char data_owner[16]; /* Owner name for this note. */
+  unsigned char offset[8];      /* File offset of the note. */
+  unsigned char size[8];        /* Length of the note. */
+};
+
 /* The LD_DATA_IN_CODE command use a linkedit_data_command that points to
    a table of entries.  */
 
diff --git a/include/mach-o/loader.h b/include/mach-o/loader.h
index 19c5e91d64..a3d20e04dc 100644
--- a/include/mach-o/loader.h
+++ b/include/mach-o/loader.h
@@ -186,7 +186,8 @@ typedef enum bfd_mach_o_load_command_type
   BFD_MACH_O_LC_LINKER_OPTIONS = 0x2d, /* Linker options.  */
   BFD_MACH_O_LC_LINKER_OPTIMIZATION_HINT = 0x2e, /* Optimization hints.  */
   BFD_MACH_O_LC_VERSION_MIN_TVOS = 0x2f, /* Minimal tvOS version.  */
-  BFD_MACH_O_LC_VERSION_MIN_WATCHOS = 0x30 /* Minimal WatchOS version.  */
+  BFD_MACH_O_LC_VERSION_MIN_WATCHOS = 0x30, /* Minimal watchOS version.  */
+  BFD_MACH_O_LC_NOTE = 0x31, /* Region of arbitrary data. */
 }
 bfd_mach_o_load_command_type;
 
--
2.19.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 6/6] mach-o: Handle LC_BUILD_VERSION command

Roman Bolshakov
In reply to this post by Roman Bolshakov
All new binaries compiled for macOS Mojave (10.14) and a few other new
platforms have started to use the new load command that essentially
replaced LC_*_VERSION_MIN commands.

Inability to handle the command prevented the whole set of binutils,
including gdb from processing new macOS binaries.

Signed-off-by: Roman Bolshakov <[hidden email]>
Signed-off-by: Saagar Jha  <[hidden email]>
Cc: Tristan Gingold <[hidden email]>
Cc: Tom Tromey <[hidden email]>
---
 bfd/ChangeLog             | 14 ++++++--
 bfd/mach-o.c              | 20 +++++++++++
 bfd/mach-o.h              | 29 ++++++++++++++++
 binutils/ChangeLog        |  6 +++-
 binutils/od-macho.c       | 71 ++++++++++++++++++++++++++++++++++++++-
 include/ChangeLog         |  2 ++
 include/mach-o/external.h |  8 +++++
 include/mach-o/loader.h   |  1 +
 8 files changed, 146 insertions(+), 5 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1f017f6fcd..6c6236032a 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,13 +1,21 @@
 2018-11-06  Roman Bolshakov <[hidden email]>
     Saagar Jha  <[hidden email]>
 
- * mach-o.h (bfd_mach_o_version_min_command): Don't split version into
- a few fields. Rename reserved to sdk.
+ * mach-o.h: Add new enums for BFD_MACH_O_PLATFORM_MACOS,
+ BFD_MACH_O_PLATFORM_IOS, BFD_MACH_O_PLATFORM_TVOS,
+ BFD_MACH_O_PLATFORM_WATCHOS, BFD_MACH_O_PLATFORM_BRIDGEOS,
+ BFD_MACH_O_TOOL_CLANG, BFD_MACH_O_TOOL_SWIFT, BFD_MACH_O_TOOL_LD.
  (struct bfd_mach_o_note_command): New.
+ (struct bfd_mach_o_build_version_tool): New
+ (struct bfd_mach_o_build_version_command): New
+ (bfd_mach_o_read_version_min): Don't split version into
+ a few fields. Rename reserved to sdk.
  * mach-o.c (bfd_mach_o_read_version_min): Don't split version into a
  few fields. Rename reserved to sdk.
- (bfd_mach_o_read_command): Handle LC_VERSION_MIN_TVOS, LC_NOTE.
+ (bfd_mach_o_read_command): Handle LC_VERSION_MIN_TVOS, LC_NOTE,
+ LC_BUILD_VERSION.
  (bfd_mach_o_read_note): New.
+ (bfd_mach_o_read_build_version): New.
 
 2018-11-02  Alan Modra  <[hidden email]>
 
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index c5d6277c54..cfcbadc8ea 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -4692,6 +4692,22 @@ bfd_mach_o_read_note (bfd *abfd, bfd_mach_o_load_command *command)
   return TRUE;
 }
 
+static bfd_boolean
+bfd_mach_o_read_build_version (bfd *abfd, bfd_mach_o_load_command *command)
+{
+  bfd_mach_o_build_version_command *cmd = &command->command.build_version;
+  struct mach_o_build_version_command_external raw;
+
+  if (bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw))
+    return FALSE;
+
+  cmd->platform = bfd_get_32 (abfd, raw.platform);
+  cmd->minos = bfd_get_32 (abfd, raw.minos);
+  cmd->sdk = bfd_get_32 (abfd, raw.sdk);
+  cmd->ntools = bfd_get_32 (abfd, raw.ntools);
+  return TRUE;
+}
+
 static bfd_boolean
 bfd_mach_o_read_segment (bfd *abfd,
  bfd_mach_o_load_command *command,
@@ -4904,6 +4920,10 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
       if (!bfd_mach_o_read_note (abfd, command))
         return FALSE;
       break;
+    case BFD_MACH_O_LC_BUILD_VERSION:
+      if (!bfd_mach_o_read_build_version (abfd, command))
+        return FALSE;
+      break;
     default:
       command->len = 0;
       _bfd_error_handler (_("%pB: unknown load command %#x"),
diff --git a/bfd/mach-o.h b/bfd/mach-o.h
index 805c30e4e2..e4951ec31b 100644
--- a/bfd/mach-o.h
+++ b/bfd/mach-o.h
@@ -113,6 +113,18 @@ bfd_mach_o_segment_command;
 #define BFD_MACH_O_PROT_WRITE   0x02
 #define BFD_MACH_O_PROT_EXECUTE 0x04
 
+/* Target platforms. */
+#define BFD_MACH_O_PLATFORM_MACOS    1
+#define BFD_MACH_O_PLATFORM_IOS      2
+#define BFD_MACH_O_PLATFORM_TVOS     3
+#define BFD_MACH_O_PLATFORM_WATCHOS  4
+#define BFD_MACH_O_PLATFORM_BRIDGEOS 5
+
+/* Build tools. */
+#define BFD_MACH_O_TOOL_CLANG 1
+#define BFD_MACH_O_TOOL_SWIFT 2
+#define BFD_MACH_O_TOOL_LD    3
+
 /* Expanded internal representation of a relocation entry.  */
 typedef struct bfd_mach_o_reloc_info
 {
@@ -557,6 +569,22 @@ typedef struct bfd_mach_o_note_command
 }
 bfd_mach_o_note_command;
 
+typedef struct bfd_mach_o_build_version_tool
+{
+  uint32_t tool;
+  uint32_t version;
+}
+bfd_mach_o_build_version_tool;
+
+typedef struct bfd_mach_o_build_version_command
+{
+  uint32_t platform;
+  uint32_t minos;
+  uint32_t sdk;
+  uint32_t ntools;
+}
+bfd_mach_o_build_version_command;
+
 typedef struct bfd_mach_o_load_command
 {
   /* Next command in the single linked list.  */
@@ -591,6 +619,7 @@ typedef struct bfd_mach_o_load_command
     bfd_mach_o_main_command main;
     bfd_mach_o_source_version_command source_version;
     bfd_mach_o_note_command note;
+    bfd_mach_o_build_version_command build_version;
   } command;
 }
 bfd_mach_o_load_command;
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 266ce272d9..40e545063f 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,9 +1,13 @@
 2018-11-06  Roman Bolshakov  <[hidden email]>
     Saagar Jha  <[hidden email]>
 
+ PR 23728
  * od-macho.c (printf_version): New.
  (dump_load_command): Use it to print version. Print sdk version. Print
- version info for watchOS and tvOS. Print LC_NOTE.
+ version info for watchOS and tvOS. Print LC_NOTE, LC_BUILD_VERSION.
+ (dump_buld_version): New.
+ (bfd_mach_o_platform_name): New
+ (bfd_mach_o_tool_name): New
 
 2018-11-03  H.J. Lu  <[hidden email]>
 
diff --git a/binutils/od-macho.c b/binutils/od-macho.c
index 4f9bba1d55..fdcfc4de4a 100644
--- a/binutils/od-macho.c
+++ b/binutils/od-macho.c
@@ -212,6 +212,7 @@ static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
   { "version_min_tvos", BFD_MACH_O_LC_VERSION_MIN_TVOS},
   { "version_min_watchos", BFD_MACH_O_LC_VERSION_MIN_WATCHOS},
   { "note", BFD_MACH_O_LC_NOTE},
+  { "build_version", BFD_MACH_O_LC_BUILD_VERSION},
   { NULL, 0}
 };
 
@@ -232,7 +233,25 @@ static const bfd_mach_o_xlat_name bfd_mach_o_thread_x86_name[] =
   { "state_none", BFD_MACH_O_x86_THREAD_STATE_NONE},
   { NULL, 0 }
 };
-
+
+static const bfd_mach_o_xlat_name bfd_mach_o_platform_name[] =
+{
+  { "macos", BFD_MACH_O_PLATFORM_MACOS},
+  { "ios", BFD_MACH_O_PLATFORM_IOS},
+  { "tvos", BFD_MACH_O_PLATFORM_TVOS},
+  { "watchos", BFD_MACH_O_PLATFORM_WATCHOS},
+  { "bridgeos", BFD_MACH_O_PLATFORM_BRIDGEOS},
+  { NULL, 0 }
+};
+
+static const bfd_mach_o_xlat_name bfd_mach_o_tool_name[] =
+{
+  { "clang", BFD_MACH_O_TOOL_CLANG},
+  { "swift", BFD_MACH_O_TOOL_SWIFT},
+  { "ld", BFD_MACH_O_TOOL_LD},
+  { NULL, 0 }
+};
+
 static void
 bfd_mach_o_print_flags (const bfd_mach_o_xlat_name *table,
                         unsigned long val)
@@ -1450,6 +1469,53 @@ printf_version (uint32_t version) {
   printf ("%u.%u.%u", maj, min, upd);
 }
 
+static void
+dump_build_version (bfd *abfd, bfd_mach_o_load_command *cmd)
+{
+  const char *platform_name;
+  size_t tools_len, tools_offset;
+  bfd_mach_o_build_version_tool *tools, *tool;
+  bfd_mach_o_build_version_command *ver = &cmd->command.build_version;
+  uint32_t i;
+
+  platform_name = bfd_mach_o_get_name_or_null
+    (bfd_mach_o_platform_name, ver->platform);
+  if (platform_name == NULL)
+    printf ("   platform: 0x%08x\n", ver->platform);
+  else
+    printf ("   platform: %s\n", platform_name);
+  printf ("   os:       ");
+  printf_version (ver->minos);
+  printf ("\n   sdk:      ");
+  printf_version (ver->sdk);
+  printf ("\n   ntools:   %u\n", ver->ntools);
+
+  tools_len = sizeof (bfd_mach_o_build_version_tool) * ver->ntools;
+  tools_offset = cmd->offset + cmd->len - tools_len;
+
+  tools = xmalloc (tools_len);
+  if (bfd_seek (abfd, tools_offset, SEEK_SET) != 0
+      || bfd_bread (tools, tools_len, abfd) != tools_len) {
+    non_fatal (_("cannot read build tools"));
+    free (tools);
+    return;
+  }
+  for (i = 0, tool = tools; i < ver->ntools; i++, tool++)
+  {
+    const char * tool_name;
+    tool_name = bfd_mach_o_get_name_or_null
+      (bfd_mach_o_tool_name, tool->tool);
+    if (tool_name == NULL)
+      printf ("   tool:     0x%08x\n", tool->tool);
+    else
+      printf ("   tool:     %s\n", tool_name);
+    printf ("   version:  ");
+    printf_version (tool->version);
+    printf ("\n");
+  }
+  free (tools);
+}
+
 static void
 dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
                    unsigned int idx, bfd_boolean verbose)
@@ -1673,6 +1739,9 @@ dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
  printf ("\n");
         break;
       }
+    case BFD_MACH_O_LC_BUILD_VERSION:
+      dump_build_version (abfd, cmd);
+      break;
     default:
       break;
     }
diff --git a/include/ChangeLog b/include/ChangeLog
index f86bbbf08c..bc86439c1c 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -4,8 +4,10 @@
  * mach-o/external.h (mach_o_nversion_min_command_external): Rename
  reserved to sdk.
  (mach_o_note_command_external): New
+ (mach_o_build_version_command_external): New
  * mach-o/loader.h (BFD_MACH_O_LC_VERSION_MIN_TVOS): Define
  (BFD_MACH_O_LC_NOTE): Define
+ (BFD_MACH_O_LC_BUILD_VERSION): Define
 
 2018-11-06  Sudakshina Das  <[hidden email]>
 
diff --git a/include/mach-o/external.h b/include/mach-o/external.h
index 7889b57794..22891e5be2 100644
--- a/include/mach-o/external.h
+++ b/include/mach-o/external.h
@@ -352,6 +352,14 @@ struct mach_o_note_command_external
   unsigned char size[8];        /* Length of the note. */
 };
 
+struct mach_o_build_version_command_external
+{
+  unsigned char platform[4];    /* Target platform. */
+  unsigned char minos[4];       /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+  unsigned char sdk[4];         /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+  unsigned char ntools[4];      /* Number of tool entries following this. */
+};
+
 /* The LD_DATA_IN_CODE command use a linkedit_data_command that points to
    a table of entries.  */
 
diff --git a/include/mach-o/loader.h b/include/mach-o/loader.h
index a3d20e04dc..e735986bc5 100644
--- a/include/mach-o/loader.h
+++ b/include/mach-o/loader.h
@@ -188,6 +188,7 @@ typedef enum bfd_mach_o_load_command_type
   BFD_MACH_O_LC_VERSION_MIN_TVOS = 0x2f, /* Minimal tvOS version.  */
   BFD_MACH_O_LC_VERSION_MIN_WATCHOS = 0x30, /* Minimal watchOS version.  */
   BFD_MACH_O_LC_NOTE = 0x31, /* Region of arbitrary data. */
+  BFD_MACH_O_LC_BUILD_VERSION = 0x32, /* Generic build version. */
 }
 bfd_mach_o_load_command_type;
 
--
2.19.1

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 1/6] mach-o: Don't split version into a few fields

tgingold
In reply to this post by Roman Bolshakov
Hello,

I am ok with your whole patchset, but:

> +static void
> +printf_version (uint32_t version) {
> +  uint32_t maj, min, upd;
> +  maj = (version >> 16) & 0xffff;
> +  min = (version >> 8) & 0xff;
> +  upd = version & 0xff;
> +  printf ("%u.%u.%u", maj, min, upd);
> +}

this doesn't follow the GNU code style.  The '{' must be on a new line.

I haven't upgraded to latest Darwin, so I haven't checked the code.

Thanks,
Tristan.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/6] Fixes for new mach-o load commands

Nick Clifton
In reply to this post by Roman Bolshakov
Hi Roman,

> Apple has added a set of new load commands that weren't handled by bfd.
> Some of them are rarely processed by binutils, like binaries with
> LC_VERSION_MIN_TVOS.
>
> But inability to handle LC_BUILD_VERSION resulted in a few bug reports,
> and rendered binutils/gdb to be unusable with Mojave binaries:
>   binutils/23728, gdb/23742, binutils/23746
>
> The patch series implements processing of the new commands in bfd and
> dump routines in objectdump.

The patch series is approved and has been applied.  I also made some
minor formatting tidy ups.

In the future, please could you provide the ChangeLog entries as plain
text, rather than context diffs, as they almost never apply cleanly.

Cheers
  Nick


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/6] Fixes for new mach-o load commands

Roman Bolshakov
On Wed, Nov 07, 2018 at 03:23:29PM +0000, Nick Clifton wrote:
>
> The patch series is approved and has been applied.  I also made some
> minor formatting tidy ups.
>
> In the future, please could you provide the ChangeLog entries as plain
> text, rather than context diffs, as they almost never apply cleanly.
>

Thank you Nick, I have also had trouble rebasing. Will provide changelog
inside cover letter next time.

Best regards,
Roman