From 7e09379669b8288f280ddf84e2a10a9cf349d038 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Wed, 9 Nov 2016 12:54:14 -0500 Subject: [PATCH 1/3] vendor: Update ruby-macho to 0.2.6. This brings fixes for behavior expected in #1460. --- Library/Homebrew/vendor/README.md | 2 +- Library/Homebrew/vendor/macho/macho.rb | 2 +- .../Homebrew/vendor/macho/macho/fat_file.rb | 55 +++++++++++-------- .../vendor/macho/macho/load_commands.rb | 40 +------------- 4 files changed, 36 insertions(+), 63 deletions(-) diff --git a/Library/Homebrew/vendor/README.md b/Library/Homebrew/vendor/README.md index b3fff49f42..acca018d1b 100644 --- a/Library/Homebrew/vendor/README.md +++ b/Library/Homebrew/vendor/README.md @@ -5,7 +5,7 @@ Vendored Dependencies * [plist](https://github.com/bleything/plist), version 3.1.0 -* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 0.2.5 +* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 0.2.6 ## Licenses: diff --git a/Library/Homebrew/vendor/macho/macho.rb b/Library/Homebrew/vendor/macho/macho.rb index 5b0974b3f5..de1d4ff435 100644 --- a/Library/Homebrew/vendor/macho/macho.rb +++ b/Library/Homebrew/vendor/macho/macho.rb @@ -13,5 +13,5 @@ require "#{File.dirname(__FILE__)}/macho/tools" # The primary namespace for ruby-macho. module MachO # release version - VERSION = "0.2.5".freeze + VERSION = "0.2.6".freeze end diff --git a/Library/Homebrew/vendor/macho/macho/fat_file.rb b/Library/Homebrew/vendor/macho/macho/fat_file.rb index 7924736489..9f29922e62 100644 --- a/Library/Homebrew/vendor/macho/macho/fat_file.rb +++ b/Library/Homebrew/vendor/macho/macho/fat_file.rb @@ -34,9 +34,7 @@ module MachO @filename = filename @raw_data = File.open(@filename, "rb", &:read) - @header = populate_fat_header - @fat_archs = populate_fat_archs - @machos = populate_machos + populate_fields end # Initializes a new FatFile instance from a binary string. @@ -45,9 +43,7 @@ module MachO def initialize_from_bin(bin) @filename = nil @raw_data = bin - @header = populate_fat_header - @fat_archs = populate_fat_archs - @machos = populate_machos + populate_fields end # The file's raw fat data. @@ -122,6 +118,21 @@ module MachO machos.first.filetype end + # Populate the instance's fields with the raw Fat Mach-O data. + # @return [void] + # @note This method is public, but should (almost) never need to be called. + def populate_fields + @header = populate_fat_header + @fat_archs = populate_fat_archs + @machos = populate_machos + end + + # All load commands responsible for loading dylibs in the file's Mach-O's. + # @return [Array] an array of DylibCommands + def dylib_load_commands + machos.map(&:dylib_load_commands).flatten + end + # The file's dylib ID. If the file is not a dylib, returns `nil`. # @example # file.dylib_id # => 'libBar.dylib' @@ -149,7 +160,7 @@ module MachO macho.change_dylib_id(new_id, options) end - synchronize_raw_data + repopulate_raw_machos end alias dylib_id= change_dylib_id @@ -180,7 +191,7 @@ module MachO macho.change_install_name(old_name, new_name, options) end - synchronize_raw_data + repopulate_raw_machos end alias change_dylib change_install_name @@ -206,7 +217,7 @@ module MachO macho.change_rpath(old_path, new_path, options) end - synchronize_raw_data + repopulate_raw_machos end # Add the given runtime path to the file's Mach-Os. @@ -221,7 +232,7 @@ module MachO macho.add_rpath(path, options) end - synchronize_raw_data + repopulate_raw_machos end # Delete the given runtime path from the file's Mach-Os. @@ -236,7 +247,7 @@ module MachO macho.delete_rpath(path, options) end - synchronize_raw_data + repopulate_raw_machos end # Extract a Mach-O with the given CPU type from the file. @@ -324,6 +335,17 @@ module MachO machos end + # Repopulate the raw Mach-O data with each internal Mach-O object. + # @return [void] + # @api private + def repopulate_raw_machos + machos.each_with_index do |macho, i| + arch = fat_archs[i] + + @raw_data[arch.offset, arch.size] = macho.serialize + end + end + # Yield each Mach-O object in the file, rescuing and accumulating errors. # @param options [Hash] # @option options [Boolean] :strict (true) whether or not to fail loudly @@ -351,16 +373,5 @@ module MachO # Non-strict mode: Raise first error if *all* Mach-O slices failed. raise errors.first if errors.size == machos.size end - - # Synchronize the raw file data with each internal Mach-O object. - # @return [void] - # @api private - def synchronize_raw_data - machos.each_with_index do |macho, i| - arch = fat_archs[i] - - @raw_data[arch.offset, arch.size] = macho.serialize - end - end end end diff --git a/Library/Homebrew/vendor/macho/macho/load_commands.rb b/Library/Homebrew/vendor/macho/macho/load_commands.rb index 3eb130bb82..205110801f 100644 --- a/Library/Homebrew/vendor/macho/macho/load_commands.rb +++ b/Library/Homebrew/vendor/macho/macho/load_commands.rb @@ -612,31 +612,7 @@ module MachO # A load command containing the address of the dynamic shared library # initialization routine and an index into the module table for the module # that defines the routine. Corresponds to LC_ROUTINES_64. - class RoutinesCommand64 < LoadCommand - # @return [Fixnum] the address of the initialization routine - attr_reader :init_address - - # @return [Fixnum] the index into the module table that the init routine is defined in - attr_reader :init_module - - # @return [void] - attr_reader :reserved1 - - # @return [void] - attr_reader :reserved2 - - # @return [void] - attr_reader :reserved3 - - # @return [void] - attr_reader :reserved4 - - # @return [void] - attr_reader :reserved5 - - # @return [void] - attr_reader :reserved6 - + class RoutinesCommand64 < RoutinesCommand # @see MachOStructure::FORMAT # @api private FORMAT = "L=2Q=8".freeze @@ -644,20 +620,6 @@ module MachO # @see MachOStructure::SIZEOF # @api private SIZEOF = 72 - - # @api private - def initialize(view, cmd, cmdsize, init_address, init_module, reserved1, - reserved2, reserved3, reserved4, reserved5, reserved6) - super(view, cmd, cmdsize) - @init_address = init_address - @init_module = init_module - @reserved1 = reserved1 - @reserved2 = reserved2 - @reserved3 = reserved3 - @reserved4 = reserved4 - @reserved5 = reserved5 - @reserved6 = reserved6 - end end # A load command signifying membership of a subframework containing the name From 032ed07bce6ec15ae24bb9e6989fd1ab8ecc27ce Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 7 Nov 2016 19:37:52 -0500 Subject: [PATCH 2/3] os/mac: Allow MachO.dynamically_linked_libraries to be filtered by dylib type. This allows us to filter out weak linkages during audits, preventing a false error from occurring when the dylib cannot be found. --- Library/Homebrew/os/mac/linkage_checker.rb | 5 ++++- Library/Homebrew/os/mac/mach.rb | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Library/Homebrew/os/mac/linkage_checker.rb b/Library/Homebrew/os/mac/linkage_checker.rb index e014e38169..e72227fc48 100644 --- a/Library/Homebrew/os/mac/linkage_checker.rb +++ b/Library/Homebrew/os/mac/linkage_checker.rb @@ -23,7 +23,10 @@ class LinkageChecker @keg.find do |file| next if file.symlink? || file.directory? next unless file.dylib? || file.mach_o_executable? || file.mach_o_bundle? - file.dynamically_linked_libraries.each do |dylib| + + # weakly loaded dylibs may not actually exist on disk, so skip them + # when checking for broken linkage + file.dynamically_linked_libraries(except: :LC_LOAD_WEAK_DYLIB).each do |dylib| @reverse_links[dylib] << file if dylib.start_with? "@" @variable_dylibs << dylib diff --git a/Library/Homebrew/os/mac/mach.rb b/Library/Homebrew/os/mac/mach.rb index 07598a23dd..44c5ee50ad 100644 --- a/Library/Homebrew/os/mac/mach.rb +++ b/Library/Homebrew/os/mac/mach.rb @@ -51,8 +51,10 @@ module MachO end end - def dynamically_linked_libraries - macho.linked_dylibs + def dynamically_linked_libraries(except: :none) + lcs = macho.dylib_load_commands.reject { |lc| lc.type == except } + + lcs.map(&:name).map(&:to_s) end def dylib_id From 9267511e6b561b83e6a3518b7cf4a1d45e2d251d Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Tue, 8 Nov 2016 16:16:34 -0500 Subject: [PATCH 3/3] os/mac: Rename MachO -> MachOShim Prevents namespace conflict with vendored ruby-macho. --- Library/Homebrew/os/mac/mach.rb | 2 +- Library/Homebrew/os/mac/pathname.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/os/mac/mach.rb b/Library/Homebrew/os/mac/mach.rb index 44c5ee50ad..4113a06018 100644 --- a/Library/Homebrew/os/mac/mach.rb +++ b/Library/Homebrew/os/mac/mach.rb @@ -1,7 +1,7 @@ require "vendor/macho/macho" require "os/mac/architecture_list" -module MachO +module MachOShim # @private def macho @macho ||= begin diff --git a/Library/Homebrew/os/mac/pathname.rb b/Library/Homebrew/os/mac/pathname.rb index 9b65d7ac02..5fd59e1e79 100644 --- a/Library/Homebrew/os/mac/pathname.rb +++ b/Library/Homebrew/os/mac/pathname.rb @@ -1,5 +1,5 @@ require "os/mac/mach" class Pathname - include MachO + include MachOShim end