From: Roman Bolshakov Date: Wed, 7 Nov 2018 15:20:22 +0000 (+0000) Subject: Add support for new load commands added by Apple to the MACH-O file format. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fc7b364aba41819a5d74ae0ac69f050af282d057;p=binutils-gdb.git Add support for new load commands added by Apple to the MACH-O file format. bfd * 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, LC_BUILD_VERSION. (bfd_mach_o_read_note): New. (bfd_mach_o_read_build_version): New. PR 23728 binutils* 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, LC_BUILD_VERSION. (dump_buld_version): New. (bfd_mach_o_platform_name): New (bfd_mach_o_tool_name): New * 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 71a8da80db3..ef97897faf2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,22 @@ +2018-11-06 Roman Bolshakov + Saagar Jha + + * 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, + LC_BUILD_VERSION. + (bfd_mach_o_read_note): New. + (bfd_mach_o_read_build_version): New. + 2018-11-07 Yoshinori Sato * config.bfd: Add rx-*-linux. diff --git a/bfd/mach-o.c b/bfd/mach-o.c index 1d0ade3a02c..51217158ce1 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -4598,16 +4598,12 @@ 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->reserved = bfd_get_32 (abfd, raw.reserved); + cmd->version = bfd_get_32 (abfd, raw.version); + cmd->sdk = bfd_get_32 (abfd, raw.sdk); return TRUE; } @@ -4681,6 +4677,37 @@ 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_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, @@ -4877,6 +4904,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; @@ -4889,7 +4917,14 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command) return FALSE; break; case BFD_MACH_O_LC_LINKER_OPTIONS: + break; + case BFD_MACH_O_LC_NOTE: + 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; diff --git a/bfd/mach-o.h b/bfd/mach-o.h index d80d43991ea..61428d6a3ae 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 { @@ -519,10 +531,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 sdk; } bfd_mach_o_version_min_command; @@ -551,6 +561,30 @@ 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_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. */ @@ -584,6 +618,8 @@ 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; + bfd_mach_o_build_version_command build_version; } command; } bfd_mach_o_load_command; @@ -617,10 +653,10 @@ typedef struct mach_o_data_struct /* A place to stash dwarf2 info for this bfd. */ void *dwarf2_find_line_info; - /* BFD of .dSYM file. */ + /* BFD of .dSYM file. */ bfd *dsym_bfd; - /* Cache of dynamic relocs. */ + /* Cache of dynamic relocs. */ arelent *dyn_reloc_cache; } bfd_mach_o_data_struct; diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 8964c96ff17..2eab660faf8 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,4 +1,16 @@ +2018-11-06 Roman Bolshakov + Saagar Jha + + 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, LC_BUILD_VERSION. + (dump_buld_version): New. + (bfd_mach_o_platform_name): New + (bfd_mach_o_tool_name): New + 2018-11-07 Yoshinori Sato + * testsuite/lib/binutils-common.exp: Special section name use only rx-*-elf. diff --git a/binutils/od-macho.c b/binutils/od-macho.c index 8153adae925..c5474c8af66 100644 --- a/binutils/od-macho.c +++ b/binutils/od-macho.c @@ -209,6 +209,10 @@ 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}, + { "note", BFD_MACH_O_LC_NOTE}, + { "build_version", BFD_MACH_O_LC_BUILD_VERSION}, { NULL, 0} }; @@ -229,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) @@ -1438,6 +1460,68 @@ 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_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) @@ -1582,10 +1666,16 @@ 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: + case BFD_MACH_O_LC_VERSION_MIN_TVOS: { 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 sdk: "); + printf_version (ver->sdk); + printf ("\n"); } break; case BFD_MACH_O_LC_SOURCE_VERSION: @@ -1643,6 +1733,21 @@ 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; + } + case BFD_MACH_O_LC_BUILD_VERSION: + dump_build_version (abfd, cmd); + break; default: break; } @@ -2205,9 +2310,9 @@ mach_o_dump (bfd *abfd) /* Vector for Mach-O. */ const struct objdump_private_desc objdump_private_desc_mach_o = - { - mach_o_help, - mach_o_filter, - mach_o_dump, - options - }; +{ + mach_o_help, + mach_o_filter, + mach_o_dump, + options +}; diff --git a/include/ChangeLog b/include/ChangeLog index 3bcf18047b4..cd31f1cd61a 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,13 @@ +2018-11-07 Roman Bolshakov + Saagar Jha + + * 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. + 2018-11-06 Romain Margheriti PR 23742 diff --git a/include/mach-o/external.h b/include/mach-o/external.h index 2609bad982a..bf3c0c890ad 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 @@ -345,12 +345,27 @@ 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. */ +}; + +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. */ struct mach_o_data_in_code_entry_external { - unsigned char offset[4]; /* Offset from the mach_header. */ + unsigned char offset[4]; /* Offset from the mach_header. */ unsigned char length[2]; /* Number of bytes. */ unsigned char kind[2]; /* Kind. See BFD_MACH_O_DICE_ values. */ }; diff --git a/include/mach-o/loader.h b/include/mach-o/loader.h index 9abc51c35dd..7b0a8067e0b 100644 --- a/include/mach-o/loader.h +++ b/include/mach-o/loader.h @@ -161,32 +161,34 @@ typedef enum bfd_mach_o_load_command_type /* Load a dynamically linked shared library that is allowed to be missing (weak). */ BFD_MACH_O_LC_LOAD_WEAK_DYLIB = 0x18, - BFD_MACH_O_LC_SEGMENT_64 = 0x19, /* 64-bit segment of this file to be - mapped. */ - BFD_MACH_O_LC_ROUTINES_64 = 0x1a, /* Address of the dyld init routine - in a dylib. */ - BFD_MACH_O_LC_UUID = 0x1b, /* 128-bit UUID of the executable. */ - BFD_MACH_O_LC_RPATH = 0x1c, /* Run path addiions. */ - BFD_MACH_O_LC_CODE_SIGNATURE = 0x1d, /* Local of code signature. */ - BFD_MACH_O_LC_SEGMENT_SPLIT_INFO = 0x1e, /* Local of info to split seg. */ - BFD_MACH_O_LC_REEXPORT_DYLIB = 0x1f, /* Load and re-export lib. */ - BFD_MACH_O_LC_LAZY_LOAD_DYLIB = 0x20, /* Delay load of lib until use. */ - BFD_MACH_O_LC_ENCRYPTION_INFO = 0x21, /* Encrypted segment info. */ - BFD_MACH_O_LC_DYLD_INFO = 0x22, /* Compressed dyld information. */ - BFD_MACH_O_LC_LOAD_UPWARD_DYLIB = 0x23, /* Load upward dylib. */ - BFD_MACH_O_LC_VERSION_MIN_MACOSX = 0x24, /* Minimal MacOSX version. */ - BFD_MACH_O_LC_VERSION_MIN_IPHONEOS = 0x25, /* Minimal IOS version. */ - BFD_MACH_O_LC_FUNCTION_STARTS = 0x26, /* Compressed table of func start. */ - BFD_MACH_O_LC_DYLD_ENVIRONMENT = 0x27, /* Env variable string for dyld. */ - BFD_MACH_O_LC_MAIN = 0x28, /* Entry point. */ - BFD_MACH_O_LC_DATA_IN_CODE = 0x29, /* Table of non-instructions. */ - BFD_MACH_O_LC_SOURCE_VERSION = 0x2a, /* Source version. */ - BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS = 0x2b, /* DRs from dylibs. */ - 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_WATCHOS = 0x30, /* Minimal WatchOS version. */ - BFD_MACH_O_LC_BUILD_VERSION = 0x32 /* Records linker, SDK, OS, and tools version used. */ + BFD_MACH_O_LC_SEGMENT_64 = 0x19, /* 64-bit segment of this file to be + mapped. */ + BFD_MACH_O_LC_ROUTINES_64 = 0x1a, /* Address of the dyld init routine + in a dylib. */ + BFD_MACH_O_LC_UUID = 0x1b, /* 128-bit UUID of the executable. */ + BFD_MACH_O_LC_RPATH = 0x1c, /* Run path addiions. */ + BFD_MACH_O_LC_CODE_SIGNATURE = 0x1d, /* Local of code signature. */ + BFD_MACH_O_LC_SEGMENT_SPLIT_INFO = 0x1e, /* Local of info to split seg. */ + BFD_MACH_O_LC_REEXPORT_DYLIB = 0x1f, /* Load and re-export lib. */ + BFD_MACH_O_LC_LAZY_LOAD_DYLIB = 0x20, /* Delay load of lib until use. */ + BFD_MACH_O_LC_ENCRYPTION_INFO = 0x21, /* Encrypted segment info. */ + BFD_MACH_O_LC_DYLD_INFO = 0x22, /* Compressed dyld information. */ + BFD_MACH_O_LC_LOAD_UPWARD_DYLIB = 0x23, /* Load upward dylib. */ + BFD_MACH_O_LC_VERSION_MIN_MACOSX = 0x24, /* Minimal MacOSX version. */ + BFD_MACH_O_LC_VERSION_MIN_IPHONEOS = 0x25, /* Minimal IOS version. */ + BFD_MACH_O_LC_FUNCTION_STARTS = 0x26, /* Compressed table of func start. */ + BFD_MACH_O_LC_DYLD_ENVIRONMENT = 0x27, /* Env variable string for dyld. */ + BFD_MACH_O_LC_MAIN = 0x28, /* Entry point. */ + BFD_MACH_O_LC_DATA_IN_CODE = 0x29, /* Table of non-instructions. */ + BFD_MACH_O_LC_SOURCE_VERSION = 0x2a, /* Source version. */ + BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS = 0x2b, /* DRs from dylibs. */ + 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_LC_NOTE = 0x31, /* Region of arbitrary data. */ + BFD_MACH_O_LC_BUILD_VERSION = 0x32, /* Generic build version. */ } bfd_mach_o_load_command_type;