From 5caa812e2cc762f0af772a51ccf24b9524dea7a5 Mon Sep 17 00:00:00 2001
From: William Woodruff <william@tuffbizz.com>
Date: Sun, 7 Aug 2016 13:36:19 -0400
Subject: [PATCH] vendor: Update vendored ruby-macho to 0.2.5.

---
 Library/Homebrew/vendor/README.md             |   2 +-
 Library/Homebrew/vendor/macho/macho.rb        |   3 +-
 .../Homebrew/vendor/macho/macho/exceptions.rb |  89 ++-
 .../Homebrew/vendor/macho/macho/fat_file.rb   | 169 ++++-
 .../Homebrew/vendor/macho/macho/headers.rb    | 156 +++-
 .../vendor/macho/macho/load_commands.rb       | 695 +++++++++++++-----
 .../Homebrew/vendor/macho/macho/macho_file.rb | 426 ++++++-----
 Library/Homebrew/vendor/macho/macho/open.rb   |  10 +-
 .../Homebrew/vendor/macho/macho/sections.rb   |  29 +-
 .../Homebrew/vendor/macho/macho/structure.rb  |  24 +-
 Library/Homebrew/vendor/macho/macho/tools.rb  |  49 +-
 Library/Homebrew/vendor/macho/macho/utils.rb  | 126 +++-
 Library/Homebrew/vendor/macho/macho/view.rb   |  23 +
 13 files changed, 1296 insertions(+), 505 deletions(-)
 create mode 100644 Library/Homebrew/vendor/macho/macho/view.rb

diff --git a/Library/Homebrew/vendor/README.md b/Library/Homebrew/vendor/README.md
index c485718959..848ce703ff 100644
--- a/Library/Homebrew/vendor/README.md
+++ b/Library/Homebrew/vendor/README.md
@@ -3,7 +3,7 @@ Vendored Dependencies
 
 * [okjson](https://github.com/kr/okjson), version 43.
 
-* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 0.2.4
+* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 0.2.5
 
 ## Licenses:
 
diff --git a/Library/Homebrew/vendor/macho/macho.rb b/Library/Homebrew/vendor/macho/macho.rb
index c94eec77b7..5b0974b3f5 100644
--- a/Library/Homebrew/vendor/macho/macho.rb
+++ b/Library/Homebrew/vendor/macho/macho.rb
@@ -1,4 +1,5 @@
 require "#{File.dirname(__FILE__)}/macho/structure"
+require "#{File.dirname(__FILE__)}/macho/view"
 require "#{File.dirname(__FILE__)}/macho/headers"
 require "#{File.dirname(__FILE__)}/macho/load_commands"
 require "#{File.dirname(__FILE__)}/macho/sections"
@@ -12,5 +13,5 @@ require "#{File.dirname(__FILE__)}/macho/tools"
 # The primary namespace for ruby-macho.
 module MachO
   # release version
-  VERSION = "0.2.4".freeze
+  VERSION = "0.2.5".freeze
 end
diff --git a/Library/Homebrew/vendor/macho/macho/exceptions.rb b/Library/Homebrew/vendor/macho/macho/exceptions.rb
index 6840060e88..262c195a35 100644
--- a/Library/Homebrew/vendor/macho/macho/exceptions.rb
+++ b/Library/Homebrew/vendor/macho/macho/exceptions.rb
@@ -3,6 +3,26 @@ module MachO
   class MachOError < RuntimeError
   end
 
+  # Raised when a Mach-O file modification fails.
+  class ModificationError < MachOError
+  end
+
+  # Raised when a Mach-O file modification fails but can be recovered when
+  # operating on multiple Mach-O slices of a fat binary in non-strict mode.
+  class RecoverableModificationError < ModificationError
+    # @return [Fixnum, nil] The index of the Mach-O slice of a fat binary for
+    #   which modification failed or `nil` if not a fat binary. This is used to
+    #   make the error message more useful.
+    attr_accessor :macho_slice
+
+    # @return [String] The exception message.
+    def to_s
+      s = super.to_s
+      s = "While modifying Mach-O slice #{@macho_slice}: #{s}" if @macho_slice
+      s
+    end
+  end
+
   # Raised when a file is not a Mach-O.
   class NotAMachOError < MachOError
     # @param error [String] the error in question
@@ -80,32 +100,89 @@ module MachO
     end
   end
 
+  # Raised when a load command can't be created manually.
+  class LoadCommandNotCreatableError < MachOError
+    # @param cmd_sym [Symbol] the uncreatable load command's symbol
+    def initialize(cmd_sym)
+      super "Load commands of type #{cmd_sym} cannot be created manually"
+    end
+  end
+
+  # Raised when the number of arguments used to create a load command manually is wrong.
+  class LoadCommandCreationArityError < MachOError
+    # @param cmd_sym [Symbol] the load command's symbol
+    # @param expected_arity [Fixnum] the number of arguments expected
+    # @param actual_arity [Fixnum] the number of arguments received
+    def initialize(cmd_sym, expected_arity, actual_arity)
+      super "Expected #{expected_arity} arguments for #{cmd_sym} creation, got #{actual_arity}"
+    end
+  end
+
+  # Raised when a load command can't be serialized.
+  class LoadCommandNotSerializableError < MachOError
+    # @param cmd_sym [Symbol] the load command's symbol
+    def initialize(cmd_sym)
+      super "Load commands of type #{cmd_sym} cannot be serialized"
+    end
+  end
+
+  # Raised when a load command string is malformed in some way.
+  class LCStrMalformedError < MachOError
+    # @param lc [MachO::LoadCommand] the load command containing the string
+    def initialize(lc)
+      super "Load command #{lc.type} at offset #{lc.view.offset} contains a malformed string"
+    end
+  end
+
+  # Raised when a change at an offset is not valid.
+  class OffsetInsertionError < ModificationError
+    # @param offset [Fixnum] the invalid offset
+    def initialize(offset)
+      super "Insertion at offset #{offset} is not valid"
+    end
+  end
+
   # Raised when load commands are too large to fit in the current file.
-  class HeaderPadError < MachOError
+  class HeaderPadError < ModificationError
     # @param filename [String] the filename
     def initialize(filename)
-      super "Updated load commands do not fit in the header of " +
-      "#{filename}. #{filename} needs to be relinked, possibly with " +
-      "-headerpad or -headerpad_max_install_names"
+      super "Updated load commands do not fit in the header of " \
+        "#{filename}. #{filename} needs to be relinked, possibly with " \
+        "-headerpad or -headerpad_max_install_names"
     end
   end
 
   # Raised when attempting to change a dylib name that doesn't exist.
-  class DylibUnknownError < MachOError
+  class DylibUnknownError < RecoverableModificationError
     # @param dylib [String] the unknown shared library name
     def initialize(dylib)
       super "No such dylib name: #{dylib}"
     end
   end
 
+  # Raised when a dylib is missing an ID
+  class DylibIdMissingError < RecoverableModificationError
+    def initialize
+      super "Dylib is missing a dylib ID"
+    end
+  end
+
   # Raised when attempting to change an rpath that doesn't exist.
-  class RpathUnknownError < MachOError
+  class RpathUnknownError < RecoverableModificationError
     # @param path [String] the unknown runtime path
     def initialize(path)
       super "No such runtime path: #{path}"
     end
   end
 
+  # Raised when attempting to add an rpath that already exists.
+  class RpathExistsError < RecoverableModificationError
+    # @param path [String] the extant path
+    def initialize(path)
+      super "#{path} already exists"
+    end
+  end
+
   # Raised whenever unfinished code is called.
   class UnimplementedError < MachOError
     # @param thing [String] the thing that is unimplemented
diff --git a/Library/Homebrew/vendor/macho/macho/fat_file.rb b/Library/Homebrew/vendor/macho/macho/fat_file.rb
index dd24fa10fb..7924736489 100644
--- a/Library/Homebrew/vendor/macho/macho/fat_file.rb
+++ b/Library/Homebrew/vendor/macho/macho/fat_file.rb
@@ -30,22 +30,24 @@ module MachO
     # @param filename [String] the fat file to load from
     # @raise [ArgumentError] if the given file does not exist
     def initialize(filename)
-      raise ArgumentError.new("#{filename}: no such file") unless File.file?(filename)
+      raise ArgumentError, "#{filename}: no such file" unless File.file?(filename)
 
       @filename = filename
-      @raw_data = File.open(@filename, "rb") { |f| f.read }
-      @header = get_fat_header
-      @fat_archs = get_fat_archs
-      @machos = get_machos
+      @raw_data = File.open(@filename, "rb", &:read)
+      @header = populate_fat_header
+      @fat_archs = populate_fat_archs
+      @machos = populate_machos
     end
 
+    # Initializes a new FatFile instance from a binary string.
+    # @see MachO::FatFile.new_from_bin
     # @api private
     def initialize_from_bin(bin)
       @filename = nil
       @raw_data = bin
-      @header = get_fat_header
-      @fat_archs = get_fat_archs
-      @machos = get_machos
+      @header = populate_fat_header
+      @fat_archs = populate_fat_archs
+      @machos = populate_machos
     end
 
     # The file's raw fat data.
@@ -115,7 +117,7 @@ module MachO
     end
 
     # The file's type. Assumed to be the same for every Mach-O within.
-    # @return [String] the filetype
+    # @return [Symbol] the filetype
     def filetype
       machos.first.filetype
     end
@@ -124,34 +126,37 @@ module MachO
     # @example
     #  file.dylib_id # => 'libBar.dylib'
     # @return [String, nil] the file's dylib ID
+    # @see MachO::MachOFile#linked_dylibs
     def dylib_id
       machos.first.dylib_id
     end
 
     # Changes the file's dylib ID to `new_id`. If the file is not a dylib, does nothing.
     # @example
-    #  file.dylib_id = 'libFoo.dylib'
+    #  file.change_dylib_id('libFoo.dylib')
     # @param new_id [String] the new dylib ID
+    # @param options [Hash]
+    # @option options [Boolean] :strict (true) if true, fail if one slice fails.
+    #  if false, fail only if all slices fail.
     # @return [void]
     # @raise [ArgumentError] if `new_id` is not a String
-    def dylib_id=(new_id)
-      if !new_id.is_a?(String)
-        raise ArgumentError.new("argument must be a String")
-      end
-
-      if !machos.all?(&:dylib?)
-        return nil
-      end
+    # @see MachO::MachOFile#linked_dylibs
+    def change_dylib_id(new_id, options = {})
+      raise ArgumentError, "argument must be a String" unless new_id.is_a?(String)
+      return unless machos.all?(&:dylib?)
 
-      machos.each do |macho|
-        macho.dylib_id = new_id
+      each_macho(options) do |macho|
+        macho.change_dylib_id(new_id, options)
       end
 
       synchronize_raw_data
     end
 
+    alias dylib_id= change_dylib_id
+
     # All shared libraries linked to the file's Mach-Os.
     # @return [Array<String>] an array of all shared libraries
+    # @see MachO::MachOFile#linked_dylibs
     def linked_dylibs
       # Individual architectures in a fat binary can link to different subsets
       # of libraries, but at this point we want to have the full picture, i.e.
@@ -165,16 +170,74 @@ module MachO
     #  file.change_install_name('/usr/lib/libFoo.dylib', '/usr/lib/libBar.dylib')
     # @param old_name [String] the shared library name being changed
     # @param new_name [String] the new name
-    # @todo incomplete
-    def change_install_name(old_name, new_name)
-      machos.each do |macho|
-        macho.change_install_name(old_name, new_name)
+    # @param options [Hash]
+    # @option options [Boolean] :strict (true) if true, fail if one slice fails.
+    #  if false, fail only if all slices fail.
+    # @return [void]
+    # @see MachO::MachOFile#change_install_name
+    def change_install_name(old_name, new_name, options = {})
+      each_macho(options) do |macho|
+        macho.change_install_name(old_name, new_name, options)
+      end
+
+      synchronize_raw_data
+    end
+
+    alias change_dylib change_install_name
+
+    # All runtime paths associated with the file's Mach-Os.
+    # @return [Array<String>] an array of all runtime paths
+    # @see MachO::MachOFile#rpaths
+    def rpaths
+      # Can individual architectures have different runtime paths?
+      machos.map(&:rpaths).flatten.uniq
+    end
+
+    # Change the runtime path `old_path` to `new_path` in the file's Mach-Os.
+    # @param old_path [String] the old runtime path
+    # @param new_path [String] the new runtime path
+    # @param options [Hash]
+    # @option options [Boolean] :strict (true) if true, fail if one slice fails.
+    #  if false, fail only if all slices fail.
+    # @return [void]
+    # @see MachO::MachOFile#change_rpath
+    def change_rpath(old_path, new_path, options = {})
+      each_macho(options) do |macho|
+        macho.change_rpath(old_path, new_path, options)
+      end
+
+      synchronize_raw_data
+    end
+
+    # Add the given runtime path to the file's Mach-Os.
+    # @param path [String] the new runtime path
+    # @param options [Hash]
+    # @option options [Boolean] :strict (true) if true, fail if one slice fails.
+    #  if false, fail only if all slices fail.
+    # @return [void]
+    # @see MachO::MachOFile#add_rpath
+    def add_rpath(path, options = {})
+      each_macho(options) do |macho|
+        macho.add_rpath(path, options)
       end
 
       synchronize_raw_data
     end
 
-    alias :change_dylib :change_install_name
+    # Delete the given runtime path from the file's Mach-Os.
+    # @param path [String] the runtime path to delete
+    # @param options [Hash]
+    # @option options [Boolean] :strict (true) if true, fail if one slice fails.
+    #  if false, fail only if all slices fail.
+    # @return void
+    # @see MachO::MachOFile#delete_rpath
+    def delete_rpath(path, options = {})
+      each_macho(options) do |macho|
+        macho.delete_rpath(path, options)
+      end
+
+      synchronize_raw_data
+    end
 
     # Extract a Mach-O with the given CPU type from the file.
     # @example
@@ -197,7 +260,7 @@ module MachO
     # @note Overwrites all data in the file!
     def write!
       if filename.nil?
-        raise MachOError.new("cannot write to a default file when initialized from a binary string")
+        raise MachOError, "cannot write to a default file when initialized from a binary string"
       else
         File.open(@filename, "wb") { |f| f.write(@raw_data) }
       end
@@ -211,15 +274,15 @@ module MachO
     # @raise [MachO::MagicError] if the magic is not valid Mach-O magic
     # @raise [MachO::MachOBinaryError] if the magic is for a non-fat Mach-O file
     # @raise [MachO::JavaClassFileError] if the file is a Java classfile
-    # @private
-    def get_fat_header
+    # @api private
+    def populate_fat_header
       # the smallest fat Mach-O header is 8 bytes
-      raise TruncatedFileError.new if @raw_data.size < 8
+      raise TruncatedFileError if @raw_data.size < 8
 
       fh = FatHeader.new_from_bin(:big, @raw_data[0, FatHeader.bytesize])
 
-      raise MagicError.new(fh.magic) unless MachO.magic?(fh.magic)
-      raise MachOBinaryError.new unless MachO.fat_magic?(fh.magic)
+      raise MagicError, fh.magic unless Utils.magic?(fh.magic)
+      raise MachOBinaryError unless Utils.fat_magic?(fh.magic)
 
       # Rationale: Java classfiles have the same magic as big-endian fat
       # Mach-Os. Classfiles encode their version at the same offset as
@@ -228,15 +291,15 @@ module MachO
       # technically possible for a fat Mach-O to have over 30 architectures,
       # but this is extremely unlikely and in practice distinguishes the two
       # formats.
-      raise JavaClassFileError.new if fh.nfat_arch > 30
+      raise JavaClassFileError if fh.nfat_arch > 30
 
       fh
     end
 
     # Obtain an array of fat architectures from raw file data.
     # @return [Array<MachO::FatArch>] an array of fat architectures
-    # @private
-    def get_fat_archs
+    # @api private
+    def populate_fat_archs
       archs = []
 
       fa_off = FatHeader.bytesize
@@ -250,8 +313,8 @@ module MachO
 
     # Obtain an array of Mach-O blobs from raw file data.
     # @return [Array<MachO::MachOFile>] an array of Mach-Os
-    # @private
-    def get_machos
+    # @api private
+    def populate_machos
       machos = []
 
       fat_archs.each do |arch|
@@ -261,9 +324,37 @@ module MachO
       machos
     end
 
-    # @todo this needs to be redesigned. arch[:offset] and arch[:size] are
-    # already out-of-date, and the header needs to be synchronized as well.
-    # @private
+    # 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
+    #  with an exception if at least one Mach-O raises an exception. If false,
+    #  only raises an exception if *all* Mach-Os raise exceptions.
+    # @raise [MachO::RecoverableModificationError] under the conditions of
+    #  the `:strict` option above.
+    # @api private
+    def each_macho(options = {})
+      strict = options.fetch(:strict, true)
+      errors = []
+
+      machos.each_with_index do |macho, index|
+        begin
+          yield macho
+        rescue RecoverableModificationError => error
+          error.macho_slice = index
+
+          # Strict mode: Immediately re-raise. Otherwise: Retain, check later.
+          raise error if strict
+          errors << error
+        end
+      end
+
+      # 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]
diff --git a/Library/Homebrew/vendor/macho/macho/headers.rb b/Library/Homebrew/vendor/macho/macho/headers.rb
index 79b5a1802f..7272503af9 100644
--- a/Library/Homebrew/vendor/macho/macho/headers.rb
+++ b/Library/Homebrew/vendor/macho/macho/headers.rb
@@ -1,64 +1,82 @@
 module MachO
   # big-endian fat magic
+  # @api private
   FAT_MAGIC = 0xcafebabe
 
   # little-endian fat magic
   # this is defined, but should never appear in ruby-macho code because
   # fat headers are always big-endian and therefore always unpacked as such.
+  # @api private
   FAT_CIGAM = 0xbebafeca
 
   # 32-bit big-endian magic
+  # @api private
   MH_MAGIC = 0xfeedface
 
   # 32-bit little-endian magic
+  # @api private
   MH_CIGAM = 0xcefaedfe
 
   # 64-bit big-endian magic
+  # @api private
   MH_MAGIC_64 = 0xfeedfacf
 
   # 64-bit little-endian magic
+  # @api private
   MH_CIGAM_64 = 0xcffaedfe
 
   # association of magic numbers to string representations
+  # @api private
   MH_MAGICS = {
     FAT_MAGIC => "FAT_MAGIC",
     MH_MAGIC => "MH_MAGIC",
     MH_CIGAM => "MH_CIGAM",
     MH_MAGIC_64 => "MH_MAGIC_64",
-    MH_CIGAM_64 => "MH_CIGAM_64"
-  }
+    MH_CIGAM_64 => "MH_CIGAM_64",
+  }.freeze
 
   # mask for CPUs with 64-bit architectures (when running a 64-bit ABI?)
+  # @api private
   CPU_ARCH_ABI64 = 0x01000000
 
   # any CPU (unused?)
+  # @api private
   CPU_TYPE_ANY = -1
 
   # m68k compatible CPUs
+  # @api private
   CPU_TYPE_MC680X0 = 0x06
 
   # i386 and later compatible CPUs
+  # @api private
   CPU_TYPE_I386 = 0x07
 
   # x86_64 (AMD64) compatible CPUs
+  # @api private
   CPU_TYPE_X86_64 = (CPU_TYPE_I386 | CPU_ARCH_ABI64)
 
   # 32-bit ARM compatible CPUs
+  # @api private
   CPU_TYPE_ARM = 0x0c
 
   # m88k compatible CPUs
+  # @api private
   CPU_TYPE_MC88000 = 0xd
 
   # 64-bit ARM compatible CPUs
+  # @api private
   CPU_TYPE_ARM64 = (CPU_TYPE_ARM | CPU_ARCH_ABI64)
 
   # PowerPC compatible CPUs
+  # @api private
   CPU_TYPE_POWERPC = 0x12
 
   # PowerPC64 compatible CPUs
+  # @api private
   CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
 
   # association of cpu types to symbol representations
+  # @api private
   CPU_TYPES = {
     CPU_TYPE_ANY => :any,
     CPU_TYPE_I386 => :i386,
@@ -67,156 +85,213 @@ module MachO
     CPU_TYPE_ARM64 => :arm64,
     CPU_TYPE_POWERPC => :ppc,
     CPU_TYPE_POWERPC64 => :ppc64,
-  }
+  }.freeze
 
   # mask for CPU subtype capabilities
+  # @api private
   CPU_SUBTYPE_MASK = 0xff000000
 
   # 64-bit libraries (undocumented!)
   # @see http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
+  # @api private
   CPU_SUBTYPE_LIB64 = 0x80000000
 
   # the lowest common sub-type for `CPU_TYPE_I386`
+  # @api private
   CPU_SUBTYPE_I386 = 3
 
   # the i486 sub-type for `CPU_TYPE_I386`
+  # @api private
   CPU_SUBTYPE_486 = 4
 
   # the i486SX sub-type for `CPU_TYPE_I386`
+  # @api private
   CPU_SUBTYPE_486SX = 132
 
   # the i586 (P5, Pentium) sub-type for `CPU_TYPE_I386`
+  # @api private
   CPU_SUBTYPE_586 = 5
-  CPU_SUBTYPE_PENT  = CPU_SUBTYPE_586
+
+  # @see CPU_SUBTYPE_586
+  # @api private
+  CPU_SUBTYPE_PENT = CPU_SUBTYPE_586
 
   # the Pentium Pro (P6) sub-type for `CPU_TYPE_I386`
+  # @api private
   CPU_SUBTYPE_PENTPRO = 22
 
   # the Pentium II (P6, M3?) sub-type for `CPU_TYPE_I386`
+  # @api private
   CPU_SUBTYPE_PENTII_M3 = 54
 
   # the Pentium II (P6, M5?) sub-type for `CPU_TYPE_I386`
+  # @api private
   CPU_SUBTYPE_PENTII_M5 = 86
 
   # the Pentium 4 (Netburst) sub-type for `CPU_TYPE_I386`
+  # @api private
   CPU_SUBTYPE_PENTIUM_4 = 10
 
   # the lowest common sub-type for `CPU_TYPE_MC680X0`
+  # @api private
   CPU_SUBTYPE_MC680X0_ALL = 1
+
+  # @see CPU_SUBTYPE_MC680X0_ALL
+  # @api private
   CPU_SUBTYPE_MC68030 = CPU_SUBTYPE_MC680X0_ALL
 
   # the 040 subtype for `CPU_TYPE_MC680X0`
+  # @api private
   CPU_SUBTYPE_MC68040 = 2
 
   # the 030 subtype for `CPU_TYPE_MC680X0`
+  # @api private
   CPU_SUBTYPE_MC68030_ONLY = 3
 
   # the lowest common sub-type for `CPU_TYPE_X86_64`
+  # @api private
   CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_I386
 
   # the Haskell sub-type for `CPU_TYPE_X86_64`
+  # @api private
   CPU_SUBTYPE_X86_64_H = 8
 
   # the lowest common sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_ALL = 0
 
   # the v4t sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V4T = 5
 
   # the v6 sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V6 = 6
 
   # the v5 sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V5TEJ = 7
 
   # the xscale (v5 family) sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_XSCALE = 8
 
   # the v7 sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V7 = 9
 
   # the v7f (Cortex A9) sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V7F = 10
 
   # the v7s ("Swift") sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V7S = 11
 
   # the v7k ("Kirkwood40") sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V7K = 12
 
   # the v6m sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V6M = 14
 
   # the v7m sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V7M = 15
 
   # the v7em sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V7EM = 16
 
   # the v8 sub-type for `CPU_TYPE_ARM`
+  # @api private
   CPU_SUBTYPE_ARM_V8 = 13
 
   # the lowest common sub-type for `CPU_TYPE_ARM64`
+  # @api private
   CPU_SUBTYPE_ARM64_ALL = 0
 
   # the v8 sub-type for `CPU_TYPE_ARM64`
+  # @api private
   CPU_SUBTYPE_ARM64_V8 = 1
 
   # the lowest common sub-type for `CPU_TYPE_MC88000`
+  # @api private
   CPU_SUBTYPE_MC88000_ALL = 0
+
+  # @see CPU_SUBTYPE_MC88000_ALL
+  # @api private
   CPU_SUBTYPE_MMAX_JPC = CPU_SUBTYPE_MC88000_ALL
 
   # the 100 sub-type for `CPU_TYPE_MC88000`
+  # @api private
   CPU_SUBTYPE_MC88100 = 1
 
   # the 110 sub-type for `CPU_TYPE_MC88000`
+  # @api private
   CPU_SUBTYPE_MC88110 = 2
 
   # the lowest common sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_ALL = 0
 
   # the 601 sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_601 = 1
 
   # the 602 sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_602 = 2
 
   # the 603 sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_603 = 3
 
   # the 603e (G2) sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_603E = 4
 
   # the 603ev sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_603EV = 5
 
   # the 604 sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_604 = 6
 
   # the 604e sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_604E = 7
 
   # the 620 sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_620 = 8
 
   # the 750 (G3) sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_750 = 9
 
   # the 7400 (G4) sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_7400 = 10
 
   # the 7450 (G4 "Voyager") sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_7450 = 11
 
   # the 970 (G5) sub-type for `CPU_TYPE_POWERPC`
+  # @api private
   CPU_SUBTYPE_POWERPC_970 = 100
 
   # any CPU sub-type for CPU type `CPU_TYPE_POWERPC64`
+  # @api private
   CPU_SUBTYPE_POWERPC64_ALL = CPU_SUBTYPE_POWERPC_ALL
 
   # association of CPU types/subtype pairs to symbol representations in
   # (very) roughly descending order of commonness
   # @see https://opensource.apple.com/source/cctools/cctools-877.8/libstuff/arch.c
+  # @api private
   CPU_SUBTYPES = {
     CPU_TYPE_I386 => {
       CPU_SUBTYPE_I386 => :i386,
@@ -280,53 +355,64 @@ module MachO
   }.freeze
 
   # relocatable object file
+  # @api private
   MH_OBJECT = 0x1
 
   # demand paged executable file
+  # @api private
   MH_EXECUTE = 0x2
 
   # fixed VM shared library file
+  # @api private
   MH_FVMLIB = 0x3
 
   # core dump file
+  # @api private
   MH_CORE = 0x4
 
   # preloaded executable file
+  # @api private
   MH_PRELOAD = 0x5
 
   # dynamically bound shared library
+  # @api private
   MH_DYLIB = 0x6
 
   # dynamic link editor
+  # @api private
   MH_DYLINKER = 0x7
 
   # dynamically bound bundle file
+  # @api private
   MH_BUNDLE = 0x8
 
   # shared library stub for static linking only, no section contents
+  # @api private
   MH_DYLIB_STUB = 0x9
 
   # companion file with only debug sections
+  # @api private
   MH_DSYM = 0xa
 
   # x86_64 kexts
+  # @api private
   MH_KEXT_BUNDLE = 0xb
 
-  # association of filetypes to string representations
+  # association of filetypes to Symbol representations
   # @api private
   MH_FILETYPES = {
-    MH_OBJECT => "MH_OBJECT",
-    MH_EXECUTE => "MH_EXECUTE",
-    MH_FVMLIB => "MH_FVMLIB",
-    MH_CORE => "MH_CORE",
-    MH_PRELOAD => "MH_PRELOAD",
-    MH_DYLIB => "MH_DYLIB",
-    MH_DYLINKER => "MH_DYLINKER",
-    MH_BUNDLE => "MH_BUNDLE",
-    MH_DYLIB_STUB => "MH_DYLIB_STUB",
-    MH_DSYM => "MH_DSYM",
-    MH_KEXT_BUNDLE => "MH_KEXT_BUNDLE"
-  }
+    MH_OBJECT => :object,
+    MH_EXECUTE => :execute,
+    MH_FVMLIB => :fvmlib,
+    MH_CORE => :core,
+    MH_PRELOAD => :preload,
+    MH_DYLIB => :dylib,
+    MH_DYLINKER => :dylinker,
+    MH_BUNDLE => :bundle,
+    MH_DYLIB_STUB => :dylib_stub,
+    MH_DSYM => :dsym,
+    MH_KEXT_BUNDLE => :kext_bundle,
+  }.freeze
 
   # association of mach header flag symbols to values
   # @api private
@@ -356,8 +442,8 @@ module MachO
     :MH_DEAD_STRIPPABLE_DYLIB => 0x400000,
     :MH_HAS_TLV_DESCRIPTORS => 0x800000,
     :MH_NO_HEAP_EXECUTION => 0x1000000,
-    :MH_APP_EXTENSION_SAFE => 0x02000000
-  }
+    :MH_APP_EXTENSION_SAFE => 0x02000000,
+  }.freeze
 
   # Fat binary header structure
   # @see MachO::FatArch
@@ -369,7 +455,12 @@ module MachO
     attr_reader :nfat_arch
 
     # always big-endian
-    FORMAT = "N2"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "N2".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 8
 
     # @api private
@@ -399,7 +490,12 @@ module MachO
     attr_reader :align
 
     # always big-endian
-    FORMAT = "N5"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "N5".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 20
 
     # @api private
@@ -435,12 +531,17 @@ module MachO
     # @return [Fixnum] the header flags associated with the Mach-O
     attr_reader :flags
 
-    FORMAT = "L=7"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=7".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 28
 
     # @api private
     def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
-        flags)
+                   flags)
       @magic = magic
       @cputype = cputype
       # For now we're not interested in additional capability bits also to be
@@ -468,12 +569,17 @@ module MachO
     # @return [void]
     attr_reader :reserved
 
-    FORMAT = "L=8"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=8".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 32
 
     # @api private
     def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
-        flags, reserved)
+                   flags, reserved)
       super(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags)
       @reserved = reserved
     end
diff --git a/Library/Homebrew/vendor/macho/macho/load_commands.rb b/Library/Homebrew/vendor/macho/macho/load_commands.rb
index 0e7695ee9a..3eb130bb82 100644
--- a/Library/Homebrew/vendor/macho/macho/load_commands.rb
+++ b/Library/Homebrew/vendor/macho/macho/load_commands.rb
@@ -1,6 +1,7 @@
 module MachO
   # load commands added after OS X 10.1 need to be bitwise ORed with
   # LC_REQ_DYLD to be recognized by the dynamic linder (dyld)
+  # @api private
   LC_REQ_DYLD = 0x80000000
 
   # association of load commands to symbol representations
@@ -57,6 +58,10 @@ module MachO
     0x30 => :LC_VERSION_MIN_WATCHOS,
   }.freeze
 
+  # association of symbol representations to load command constants
+  # @api private
+  LOAD_COMMAND_CONSTANTS = LOAD_COMMANDS.invert.freeze
+
   # load commands responsible for loading dylibs
   # @api private
   DYLIB_LOAD_COMMANDS = [
@@ -67,19 +72,27 @@ module MachO
     :LC_LOAD_UPWARD_DYLIB,
   ].freeze
 
+  # load commands that can be created manually via {LoadCommand.create}
+  # @api private
+  CREATABLE_LOAD_COMMANDS = DYLIB_LOAD_COMMANDS + [
+    :LC_ID_DYLIB,
+    :LC_RPATH,
+    :LC_LOAD_DYLINKER,
+  ].freeze
+
   # association of load command symbols to string representations of classes
   # @api private
   LC_STRUCTURES = {
     :LC_SEGMENT => "SegmentCommand",
     :LC_SYMTAB => "SymtabCommand",
-    :LC_SYMSEG => "LoadCommand", # obsolete
+    :LC_SYMSEG => "SymsegCommand", # obsolete
     :LC_THREAD => "ThreadCommand", # seems obsolete, but not documented as such
     :LC_UNIXTHREAD => "ThreadCommand",
-    :LC_LOADFVMLIB => "LoadCommand", # obsolete
-    :LC_IDFVMLIB => "LoadCommand", # obsolete
-    :LC_IDENT => "LoadCommand", # obsolete
-    :LC_FVMFILE => "LoadCommand", # reserved for internal use only
-    :LC_PREPAGE => "LoadCommand", # reserved for internal use only
+    :LC_LOADFVMLIB => "FvmlibCommand", # obsolete
+    :LC_IDFVMLIB => "FvmlibCommand", # obsolete
+    :LC_IDENT => "IdentCommand", # obsolete
+    :LC_FVMFILE => "FvmfileCommand", # reserved for internal use only
+    :LC_PREPAGE => "LoadCommand", # reserved for internal use only, no public struct
     :LC_DYSYMTAB => "DysymtabCommand",
     :LC_LOAD_DYLIB => "DylibCommand",
     :LC_ID_DYLIB => "DylibCommand",
@@ -148,8 +161,8 @@ module MachO
   # represented, and no actual data. Used when a more specific class
   # isn't available/implemented.
   class LoadCommand < MachOStructure
-    # @return [Fixnum] the offset in the file the command was created from
-    attr_reader :offset
+    # @return [MachO::MachOView] the raw view associated with the load command
+    attr_reader :view
 
     # @return [Fixnum] the load command's identifying number
     attr_reader :cmd
@@ -157,40 +170,80 @@ module MachO
     # @return [Fixnum] the size of the load command, in bytes
     attr_reader :cmdsize
 
-    FORMAT = "L=2"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=2".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 8
 
-    # Creates a new LoadCommand given an offset and binary string
-    # @param raw_data [String] the raw Mach-O data
-    # @param endianness [Symbol] the endianness of the command (:big or :little)
-    # @param offset [Fixnum] the offset to initialize with
-    # @param bin [String] the binary string to initialize with
+    # Instantiates a new LoadCommand given a view into its origin Mach-O
+    # @param view [MachO::MachOView] the load command's raw view
     # @return [MachO::LoadCommand] the new load command
     # @api private
-    def self.new_from_bin(raw_data, endianness, offset, bin)
-      format = specialize_format(self::FORMAT, endianness)
+    def self.new_from_bin(view)
+      bin = view.raw_data.slice(view.offset, bytesize)
+      format = Utils.specialize_format(self::FORMAT, view.endianness)
+
+      new(view, *bin.unpack(format))
+    end
+
+    # Creates a new (viewless) command corresponding to the symbol provided
+    # @param cmd_sym [Symbol] the symbol of the load command being created
+    # @param args [Array] the arguments for the load command being created
+    def self.create(cmd_sym, *args)
+      raise LoadCommandNotCreatableError, cmd_sym unless CREATABLE_LOAD_COMMANDS.include?(cmd_sym)
+
+      klass = MachO.const_get LC_STRUCTURES[cmd_sym]
+      cmd = LOAD_COMMAND_CONSTANTS[cmd_sym]
 
-      self.new(raw_data, offset, *bin.unpack(format))
+      # cmd will be filled in, view and cmdsize will be left unpopulated
+      klass_arity = klass.instance_method(:initialize).arity - 3
+
+      raise LoadCommandCreationArityError.new(cmd_sym, klass_arity, args.size) if klass_arity != args.size
+
+      klass.new(nil, cmd, nil, *args)
     end
 
-    # @param raw_data [String] the raw Mach-O data
-    # @param offset [Fixnum] the offset to initialize with
+    # @param view [MachO::MachOView] the load command's raw view
     # @param cmd [Fixnum] the load command's identifying number
     # @param cmdsize [Fixnum] the size of the load command in bytes
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize)
-      @raw_data = raw_data
-      @offset = offset
+    def initialize(view, cmd, cmdsize)
+      @view = view
       @cmd = cmd
       @cmdsize = cmdsize
     end
 
+    # @return [Boolean] true if the load command can be serialized, false otherwise
+    def serializable?
+      CREATABLE_LOAD_COMMANDS.include?(LOAD_COMMANDS[cmd])
+    end
+
+    # @param context [MachO::LoadCommand::SerializationContext] the context
+    #  to serialize into
+    # @return [String, nil] the serialized fields of the load command, or nil
+    #  if the load command can't be serialized
+    # @api private
+    def serialize(context)
+      raise LoadCommandNotSerializableError, LOAD_COMMANDS[cmd] unless serializable?
+      format = Utils.specialize_format(FORMAT, context.endianness)
+      [cmd, SIZEOF].pack(format)
+    end
+
+    # @return [Fixnum] the load command's offset in the source file
+    # @deprecated use {#view} instead
+    def offset
+      view.offset
+    end
+
     # @return [Symbol] a symbol representation of the load command's identifying number
     def type
       LOAD_COMMANDS[cmd]
     end
 
-    alias :to_sym :type
+    alias to_sym type
 
     # @return [String] a string representation of the load command's identifying number
     def to_s
@@ -202,25 +255,62 @@ module MachO
     # pretend that strings stored in LCs are immediately available without
     # explicit operations on the raw Mach-O data.
     class LCStr
-      # @param raw_data [String] the raw Mach-O data.
       # @param lc [MachO::LoadCommand] the load command
-      # @param lc_str [Fixnum] the offset to the beginning of the string
+      # @param lc_str [Fixnum, String] the offset to the beginning of the string,
+      #  or the string itself if not being initialized with a view.
+      # @raise [MachO::LCStrMalformedError] if the string is malformed
+      # @todo devise a solution such that the `lc_str` parameter is not
+      #  interpreted differently depending on `lc.view`. The current behavior
+      #  is a hack to allow viewless load command creation.
       # @api private
-      def initialize(raw_data, lc, lc_str)
-        @raw_data = raw_data
-        @lc = lc
-        @lc_str = lc_str
-        @str = @raw_data.slice(@lc.offset + @lc_str...@lc.offset + @lc.cmdsize).delete("\x00")
+      def initialize(lc, lc_str)
+        view = lc.view
+
+        if view
+          lc_str_abs = view.offset + lc_str
+          lc_end = view.offset + lc.cmdsize - 1
+          raw_string = view.raw_data.slice(lc_str_abs..lc_end)
+          @string, null_byte, _padding = raw_string.partition("\x00")
+          raise LCStrMalformedError, lc if null_byte.empty?
+          @string_offset = lc_str
+        else
+          @string = lc_str
+          @string_offset = 0
+        end
       end
 
       # @return [String] a string representation of the LCStr
       def to_s
-        @str
+        @string
       end
 
       # @return [Fixnum] the offset to the beginning of the string in the load command
       def to_i
-        @lc_str
+        @string_offset
+      end
+    end
+
+    # Represents the contextual information needed by a load command to
+    # serialize itself correctly into a binary string.
+    class SerializationContext
+      # @return [Symbol] the endianness of the serialized load command
+      attr_reader :endianness
+
+      # @return [Fixnum] the constant alignment value used to pad the serialized load command
+      attr_reader :alignment
+
+      # @param macho [MachO::MachOFile] the file to contextualize
+      # @return [MachO::LoadCommand::SerializationContext] the resulting context
+      def self.context_for(macho)
+        new(macho.endianness, macho.alignment)
+      end
+
+      # @param endianness [Symbol] the endianness of the context
+      # @param alignment [Fixnum] the alignment of the context
+      # @api private
+      def initialize(endianness, alignment)
+        @endianness = endianness
+        @alignment = alignment
       end
     end
   end
@@ -231,12 +321,17 @@ module MachO
     # @return [Array<Fixnum>] the UUID
     attr_reader :uuid
 
-    FORMAT = "L=2a16"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=2a16".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 24
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, uuid)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, uuid)
+      super(view, cmd, cmdsize)
       @uuid = uuid.unpack("C16") # re-unpack for the actual UUID array
     end
 
@@ -282,13 +377,18 @@ module MachO
     # @return [Fixnum] any flags associated with the segment
     attr_reader :flags
 
-    FORMAT = "L=2a16L=4l=2L=2"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=2a16L=4l=2L=2".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 56
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
-        filesize, maxprot, initprot, nsects, flags)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
+                   filesize, maxprot, initprot, nsects, flags)
+      super(view, cmd, cmdsize)
       @segname = segname.delete("\x00")
       @vmaddr = vmaddr
       @vmsize = vmsize
@@ -300,6 +400,23 @@ module MachO
       @flags = flags
     end
 
+    # All sections referenced within this segment.
+    # @return [Array<MachO::Section>] if the Mach-O is 32-bit
+    # @return [Array<MachO::Section64>] if the Mach-O is 64-bit
+    def sections
+      klass = case self
+      when MachO::SegmentCommand64
+        MachO::Section64
+      when MachO::SegmentCommand
+        MachO::Section
+      end
+
+      bins = view.raw_data[view.offset + self.class.bytesize, nsects * klass.bytesize]
+      bins.unpack("a#{klass.bytesize}" * nsects).map do |bin|
+        klass.new_from_bin(view.endianness, bin)
+      end
+    end
+
     # @example
     #  puts "this segment relocated in/to it" if sect.flag?(:SG_NORELOC)
     # @param flag [Symbol] a segment flag symbol
@@ -313,61 +430,14 @@ module MachO
 
   # A load command indicating that part of this file is to be mapped into
   # the task's address space. Corresponds to LC_SEGMENT_64.
-  class SegmentCommand64 < LoadCommand
-    # @return [String] the name of the segment
-    attr_reader :segname
-
-    # @return [Fixnum] the memory address of the segment
-    attr_reader :vmaddr
-
-    # @return [Fixnum] the memory size of the segment
-    attr_reader :vmsize
-
-    # @return [Fixnum] the file offset of the segment
-    attr_reader :fileoff
-
-    # @return [Fixnum] the amount to map from the file
-    attr_reader :filesize
-
-    # @return [Fixnum] the maximum VM protection
-    attr_reader :maxprot
-
-    # @return [Fixnum] the initial VM protection
-    attr_reader :initprot
-
-    # @return [Fixnum] the number of sections in the segment
-    attr_reader :nsects
-
-    # @return [Fixnum] any flags associated with the segment
-    attr_reader :flags
-
-    FORMAT = "L=2a16Q=4l=2L=2"
-    SIZEOF = 72
-
+  class SegmentCommand64 < SegmentCommand
+    # @see MachOStructure::FORMAT
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
-        filesize, maxprot, initprot, nsects, flags)
-      super(raw_data, offset, cmd, cmdsize)
-      @segname = segname.delete("\x00")
-      @vmaddr = vmaddr
-      @vmsize = vmsize
-      @fileoff = fileoff
-      @filesize = filesize
-      @maxprot = maxprot
-      @initprot = initprot
-      @nsects = nsects
-      @flags = flags
-    end
+    FORMAT = "L=2a16Q=4l=2L=2".freeze
 
-    # @example
-    #  puts "this segment relocated in/to it" if sect.flag?(:SG_NORELOC)
-    # @param flag [Symbol] a segment flag symbol
-    # @return [Boolean] true if `flag` is present in the segment's flag field
-    def flag?(flag)
-      flag = SEGMENT_FLAGS[flag]
-      return false if flag.nil?
-      flags & flag == flag
-    end
+    # @see MachOStructure::SIZEOF
+    # @api private
+    SIZEOF = 72
   end
 
   # A load command representing some aspect of shared libraries, depending
@@ -386,18 +456,33 @@ module MachO
     # @return [Fixnum] the library's compatibility version number
     attr_reader :compatibility_version
 
-    FORMAT = "L=6"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=6".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 24
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, name, timestamp, current_version,
-        compatibility_version)
-      super(raw_data, offset, cmd, cmdsize)
-      @name = LCStr.new(raw_data, self, name)
+    def initialize(view, cmd, cmdsize, name, timestamp, current_version, compatibility_version)
+      super(view, cmd, cmdsize)
+      @name = LCStr.new(self, name)
       @timestamp = timestamp
       @current_version = current_version
       @compatibility_version = compatibility_version
     end
+
+    # @param context [MachO::LoadCcommand::SerializationContext] the context
+    # @return [String] the serialized fields of the load command
+    # @api private
+    def serialize(context)
+      format = Utils.specialize_format(FORMAT, context.endianness)
+      string_payload, string_offsets = Utils.pack_strings(SIZEOF, context.alignment, :name => name.to_s)
+      cmdsize = SIZEOF + string_payload.bytesize
+      [cmd, cmdsize, string_offsets[:name], timestamp, current_version,
+       compatibility_version].pack(format) + string_payload
+    end
   end
 
   # A load command representing some aspect of the dynamic linker, depending
@@ -407,13 +492,28 @@ module MachO
     # @return [MachO::LoadCommand::LCStr] the dynamic linker's path name as an LCStr
     attr_reader :name
 
-    FORMAT = "L=3"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=3".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 12
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, name)
-      super(raw_data, offset, cmd, cmdsize)
-      @name = LCStr.new(raw_data, self, name)
+    def initialize(view, cmd, cmdsize, name)
+      super(view, cmd, cmdsize)
+      @name = LCStr.new(self, name)
+    end
+
+    # @param context [MachO::LoadCcommand::SerializationContext] the context
+    # @return [String] the serialized fields of the load command
+    # @api private
+    def serialize(context)
+      format = Utils.specialize_format(FORMAT, context.endianness)
+      string_payload, string_offsets = Utils.pack_strings(SIZEOF, context.alignment, :name => name.to_s)
+      cmdsize = SIZEOF + string_payload.bytesize
+      [cmd, cmdsize, string_offsets[:name]].pack(format) + string_payload
     end
   end
 
@@ -429,13 +529,18 @@ module MachO
     # @return [Fixnum] a bit vector of linked modules
     attr_reader :linked_modules
 
-    FORMAT = "L=5"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=5".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 20
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, name, nmodules, linked_modules)
-      super(raw_data, offset, cmd, cmdsize)
-      @name = LCStr.new(raw_data, self, name)
+    def initialize(view, cmd, cmdsize, name, nmodules, linked_modules)
+      super(view, cmd, cmdsize)
+      @name = LCStr.new(self, name)
       @nmodules = nmodules
       @linked_modules = linked_modules
     end
@@ -444,7 +549,12 @@ module MachO
   # A load command used to represent threads.
   # @note cctools-870 has all fields of thread_command commented out except common ones (cmd, cmdsize)
   class ThreadCommand < LoadCommand
-    FORMAT = "L=2"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=2".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 8
   end
 
@@ -476,14 +586,18 @@ module MachO
     # @return [void]
     attr_reader :reserved6
 
-    FORMAT = "L=10"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=10".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 40
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, init_address, init_module,
-        reserved1, reserved2, reserved3, reserved4, reserved5,
-        reserved6)
-      super(raw_data, offset, cmd, cmdsize)
+    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
@@ -523,14 +637,18 @@ module MachO
     # @return [void]
     attr_reader :reserved6
 
-    FORMAT = "L=2Q=8"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=2Q=8".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 72
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, init_address, init_module,
-        reserved1, reserved2, reserved3, reserved4, reserved5,
-        reserved6)
-      super(raw_data, offset, cmd, cmdsize)
+    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
@@ -548,13 +666,18 @@ module MachO
     # @return [MachO::LoadCommand::LCStr] the umbrella framework name as an LCStr
     attr_reader :umbrella
 
-    FORMAT = "L=3"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=3".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 12
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, umbrella)
-      super(raw_data, offset, cmd, cmdsize)
-      @umbrella = LCStr.new(raw_data, self, umbrella)
+    def initialize(view, cmd, cmdsize, umbrella)
+      super(view, cmd, cmdsize)
+      @umbrella = LCStr.new(self, umbrella)
     end
   end
 
@@ -564,13 +687,18 @@ module MachO
     # @return [MachO::LoadCommand::LCStr] the subumbrella framework name as an LCStr
     attr_reader :sub_umbrella
 
-    FORMAT = "L=3"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=3".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 12
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, sub_umbrella)
-      super(raw_data, offset, cmd, cmdsize)
-      @sub_umbrella = LCStr.new(raw_data, self, sub_umbrella)
+    def initialize(view, cmd, cmdsize, sub_umbrella)
+      super(view, cmd, cmdsize)
+      @sub_umbrella = LCStr.new(self, sub_umbrella)
     end
   end
 
@@ -580,13 +708,18 @@ module MachO
     # @return [MachO::LoadCommand::LCStr] the sublibrary name as an LCStr
     attr_reader :sub_library
 
-    FORMAT = "L=3"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=3".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 12
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, sub_library)
-      super(raw_data, offset, cmd, cmdsize)
-      @sub_library = LCStr.new(raw_data, self, sub_library)
+    def initialize(view, cmd, cmdsize, sub_library)
+      super(view, cmd, cmdsize)
+      @sub_library = LCStr.new(self, sub_library)
     end
   end
 
@@ -596,13 +729,18 @@ module MachO
     # @return [MachO::LoadCommand::LCStr] the subclient name as an LCStr
     attr_reader :sub_client
 
-    FORMAT = "L=3"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=3".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 12
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, sub_client)
-      super(raw_data, offset, cmd, cmdsize)
-      @sub_client = LCStr.new(raw_data, self, sub_client)
+    def initialize(view, cmd, cmdsize, sub_client)
+      super(view, cmd, cmdsize)
+      @sub_client = LCStr.new(self, sub_client)
     end
   end
 
@@ -621,12 +759,17 @@ module MachO
     # @return the string table size in bytes
     attr_reader :strsize
 
-    FORMAT = "L=6"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=6".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 24
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, symoff, nsyms, stroff, strsize)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, symoff, nsyms, stroff, strsize)
+      super(view, cmd, cmdsize)
       @symoff = symoff
       @nsyms = nsyms
       @stroff = stroff
@@ -691,17 +834,21 @@ module MachO
     # @return [Fixnum] the number of local relocation entries
     attr_reader :nlocrel
 
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=20".freeze
 
-    FORMAT = "L=20"
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 80
 
     # ugh
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, ilocalsym, nlocalsym, iextdefsym,
-        nextdefsym, iundefsym, nundefsym, tocoff, ntoc, modtaboff,
-        nmodtab, extrefsymoff, nextrefsyms, indirectsymoff,
-        nindirectsyms, extreloff, nextrel, locreloff, nlocrel)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, ilocalsym, nlocalsym, iextdefsym,
+                   nextdefsym, iundefsym, nundefsym, tocoff, ntoc, modtaboff,
+                   nmodtab, extrefsymoff, nextrefsyms, indirectsymoff,
+                   nindirectsyms, extreloff, nextrel, locreloff, nlocrel)
+      super(view, cmd, cmdsize)
       @ilocalsym = ilocalsym
       @nlocalsym = nlocalsym
       @iextdefsym = iextdefsym
@@ -732,14 +879,58 @@ module MachO
     # @return [Fixnum] the number of hints in the hint table
     attr_reader :nhints
 
-    FORMAT = "L=4"
+    # @return [MachO::TwolevelHintsCommand::TwolevelHintTable] the hint table
+    attr_reader :table
+
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=4".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 16
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, htoffset, nhints)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, htoffset, nhints)
+      super(view, cmd, cmdsize)
       @htoffset = htoffset
       @nhints = nhints
+      @table = TwolevelHintsTable.new(view, htoffset, nhints)
+    end
+
+    # A representation of the two-level namespace lookup hints table exposed
+    # by a {TwolevelHintsCommand} (`LC_TWOLEVEL_HINTS`).
+    class TwolevelHintsTable
+      # @return [Array<MachO::TwoLevelHintsTable::TwoLevelHint>] all hints in the table
+      attr_reader :hints
+
+      # @param view [MachO::MachOView] the view into the current Mach-O
+      # @param htoffset [Fixnum] the offset of the hints table
+      # @param nhints [Fixnum] the number of two-level hints in the table
+      # @api private
+      def initialize(view, htoffset, nhints)
+        format = Utils.specialize_format("L=#{nhints}", view.endianness)
+        raw_table = view.raw_data[htoffset, nhints * 4]
+        blobs = raw_table.unpack(format)
+
+        @hints = blobs.map { |b| TwolevelHint.new(b) }
+      end
+
+      # An individual two-level namespace lookup hint.
+      class TwolevelHint
+        # @return [Fixnum] the index into the sub-images
+        attr_reader :isub_image
+
+        # @return [Fixnum] the index into the table of contents
+        attr_reader :itoc
+
+        # @param blob [Fixnum] the 32-bit number containing the lookup hint
+        # @api private
+        def initialize(blob)
+          @isub_image = blob >> 24
+          @itoc = blob & 0x00FFFFFF
+        end
+      end
     end
   end
 
@@ -749,12 +940,17 @@ module MachO
     # @return [Fixnum] the checksum or 0
     attr_reader :cksum
 
-    FORMAT = "L=3"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=3".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 12
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, cksum)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, cksum)
+      super(view, cmd, cmdsize)
       @cksum = cksum
     end
   end
@@ -766,13 +962,28 @@ module MachO
     # @return [MachO::LoadCommand::LCStr] the path to add to the run path as an LCStr
     attr_reader :path
 
-    FORMAT = "L=3"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=3".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 12
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, path)
-      super(raw_data, offset, cmd, cmdsize)
-      @path = LCStr.new(raw_data, self, path)
+    def initialize(view, cmd, cmdsize, path)
+      super(view, cmd, cmdsize)
+      @path = LCStr.new(self, path)
+    end
+
+    # @param context [MachO::LoadCcommand::SerializationContext] the context
+    # @return [String] the serialized fields of the load command
+    # @api private
+    def serialize(context)
+      format = Utils.specialize_format(FORMAT, context.endianness)
+      string_payload, string_offsets = Utils.pack_strings(SIZEOF, context.alignment, :path => path.to_s)
+      cmdsize = SIZEOF + string_payload.bytesize
+      [cmd, cmdsize, string_offsets[:path]].pack(format) + string_payload
     end
   end
 
@@ -786,12 +997,17 @@ module MachO
     # @return [Fixnum] size of the data in the __LINKEDIT segment
     attr_reader :datasize
 
-    FORMAT = "L=4"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=4".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 16
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, dataoff, datasize)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, dataoff, datasize)
+      super(view, cmd, cmdsize)
       @dataoff = dataoff
       @datasize = datasize
     end
@@ -809,12 +1025,17 @@ module MachO
     # @return [Fixnum] the encryption system, or 0 if not encrypted yet
     attr_reader :cryptid
 
-    FORMAT = "L=5"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=5".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 20
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, cryptoff, cryptsize, cryptid)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid)
+      super(view, cmd, cmdsize)
       @cryptoff = cryptoff
       @cryptsize = cryptsize
       @cryptid = cryptid
@@ -836,12 +1057,17 @@ module MachO
     # @return [Fixnum] 64-bit padding value
     attr_reader :pad
 
-    FORMAT = "L=6"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=6".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 24
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, cryptoff, cryptsize, cryptid, pad)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid, pad)
+      super(view, cmd, cmdsize)
       @cryptoff = cryptoff
       @cryptsize = cryptsize
       @cryptid = cryptid
@@ -858,12 +1084,17 @@ module MachO
     # @return [Fixnum] the SDK version X.Y.Z packed as x16.y8.z8
     attr_reader :sdk
 
-    FORMAT = "L=4"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=4".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 16
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, version, sdk)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, version, sdk)
+      super(view, cmd, cmdsize)
       @version = version
       @sdk = sdk
     end
@@ -925,14 +1156,19 @@ module MachO
     # @return [Fixnum] the size of the export information
     attr_reader :export_size
 
-    FORMAT = "L=12"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=12".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 48
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, rebase_off, rebase_size, bind_off,
-        bind_size, weak_bind_off, weak_bind_size, lazy_bind_off,
-        lazy_bind_size, export_off, export_size)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, rebase_off, rebase_size, bind_off,
+                   bind_size, weak_bind_off, weak_bind_size, lazy_bind_off,
+                   lazy_bind_size, export_off, export_size)
+      super(view, cmd, cmdsize)
       @rebase_off = rebase_off
       @rebase_size = rebase_size
       @bind_off = bind_off
@@ -952,12 +1188,17 @@ module MachO
     # @return [Fixnum] the number of strings
     attr_reader :count
 
-    FORMAT = "L=3"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=3".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 12
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, count)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, count)
+      super(view, cmd, cmdsize)
       @count = count
     end
   end
@@ -970,12 +1211,17 @@ module MachO
     # @return [Fixnum] if not 0, the initial stack size.
     attr_reader :stacksize
 
-    FORMAT = "L=2Q=2"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=2Q=2".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 24
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, entryoff, stacksize)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, entryoff, stacksize)
+      super(view, cmd, cmdsize)
       @entryoff = entryoff
       @stacksize = stacksize
     end
@@ -987,12 +1233,17 @@ module MachO
     # @return [Fixnum] the version packed as a24.b10.c10.d10.e10
     attr_reader :version
 
-    FORMAT = "L=2Q=1"
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=2Q=1".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
     SIZEOF = 16
 
     # @api private
-    def initialize(raw_data, offset, cmd, cmdsize, version)
-      super(raw_data, offset, cmd, cmdsize)
+    def initialize(view, cmd, cmdsize, version)
+      super(view, cmd, cmdsize)
       @version = version
     end
 
@@ -1008,4 +1259,94 @@ module MachO
       segs.join(".")
     end
   end
+
+  # An obsolete load command containing the offset and size of the (GNU style)
+  # symbol table information. Corresponds to LC_SYMSEG.
+  class SymsegCommand < LoadCommand
+    # @return [Fixnum] the offset to the symbol segment
+    attr_reader :offset
+
+    # @return [Fixnum] the size of the symbol segment in bytes
+    attr_reader :size
+
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=4".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
+    SIZEOF = 16
+
+    # @api private
+    def initialize(view, cmd, cmdsize, offset, size)
+      super(view, cmd, cmdsize)
+      @offset = offset
+      @size = size
+    end
+  end
+
+  # An obsolete load command containing a free format string table. Each string
+  # is null-terminated and the command is zero-padded to a multiple of 4.
+  # Corresponds to LC_IDENT.
+  class IdentCommand < LoadCommand
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=2".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
+    SIZEOF = 8
+  end
+
+  # An obsolete load command containing the path to a file to be loaded into
+  # memory. Corresponds to LC_FVMFILE.
+  class FvmfileCommand < LoadCommand
+    # @return [MachO::LoadCommand::LCStr] the pathname of the file being loaded
+    attr_reader :name
+
+    # @return [Fixnum] the virtual address being loaded at
+    attr_reader :header_addr
+
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=4".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
+    SIZEOF = 16
+
+    def initialize(view, cmd, cmdsize, name, header_addr)
+      super(view, cmd, cmdsize)
+      @name = LCStr.new(self, name)
+      @header_addr = header_addr
+    end
+  end
+
+  # An obsolete load command containing the path to a library to be loaded into
+  # memory. Corresponds to LC_LOADFVMLIB and LC_IDFVMLIB.
+  class FvmlibCommand < LoadCommand
+    # @return [MachO::LoadCommand::LCStr] the library's target pathname
+    attr_reader :name
+
+    # @return [Fixnum] the library's minor version number
+    attr_reader :minor_version
+
+    # @return [Fixnum] the library's header address
+    attr_reader :header_addr
+
+    # @see MachOStructure::FORMAT
+    # @api private
+    FORMAT = "L=5".freeze
+
+    # @see MachOStructure::SIZEOF
+    # @api private
+    SIZEOF = 20
+
+    def initialize(view, cmd, cmdsize, name, minor_version, header_addr)
+      super(view, cmd, cmdsize)
+      @name = LCStr.new(self, name)
+      @minor_version = minor_version
+      @header_addr = header_addr
+    end
+  end
 end
diff --git a/Library/Homebrew/vendor/macho/macho/macho_file.rb b/Library/Homebrew/vendor/macho/macho/macho_file.rb
index dc8d6fc250..8ece626721 100644
--- a/Library/Homebrew/vendor/macho/macho/macho_file.rb
+++ b/Library/Homebrew/vendor/macho/macho/macho_file.rb
@@ -16,6 +16,7 @@ module MachO
     attr_reader :header
 
     # @return [Array<MachO::LoadCommand>] an array of the file's load commands
+    # @note load commands are provided in order of ascending offset.
     attr_reader :load_commands
 
     # Creates a new MachOFile instance from a binary string.
@@ -32,20 +33,20 @@ module MachO
     # @param filename [String] the Mach-O file to load from
     # @raise [ArgumentError] if the given file does not exist
     def initialize(filename)
-      raise ArgumentError.new("#{filename}: no such file") unless File.file?(filename)
+      raise ArgumentError, "#{filename}: no such file" unless File.file?(filename)
 
       @filename = filename
-      @raw_data = File.open(@filename, "rb") { |f| f.read }
-      @header = get_mach_header
-      @load_commands = get_load_commands
+      @raw_data = File.open(@filename, "rb", &:read)
+      populate_fields
     end
 
+    # Initializes a new MachOFile instance from a binary string.
+    # @see MachO::MachOFile.new_from_bin
     # @api private
     def initialize_from_bin(bin)
       @filename = nil
       @raw_data = bin
-      @header = get_mach_header
-      @load_commands = get_load_commands
+      populate_fields
     end
 
     # The file's raw Mach-O data.
@@ -56,12 +57,17 @@ module MachO
 
     # @return [Boolean] true if the Mach-O has 32-bit magic, false otherwise
     def magic32?
-      MachO.magic32?(header.magic)
+      Utils.magic32?(header.magic)
     end
 
     # @return [Boolean] true if the Mach-O has 64-bit magic, false otherwise
     def magic64?
-      MachO.magic64?(header.magic)
+      Utils.magic64?(header.magic)
+    end
+
+    # @return [Fixnum] the file's internal alignment
+    def alignment
+      magic32? ? 4 : 8
     end
 
     # @return [Boolean] true if the file is of type `MH_OBJECT`, false otherwise
@@ -124,7 +130,7 @@ module MachO
       MH_MAGICS[magic]
     end
 
-    # @return [String] a string representation of the Mach-O's filetype
+    # @return [Symbol] a string representation of the Mach-O's filetype
     def filetype
       MH_FILETYPES[header.filetype]
     end
@@ -164,7 +170,109 @@ module MachO
       load_commands.select { |lc| lc.type == name.to_sym }
     end
 
-    alias :[] :command
+    alias [] command
+
+    # Inserts a load command at the given offset.
+    # @param offset [Fixnum] the offset to insert at
+    # @param lc [MachO::LoadCommand] the load command to insert
+    # @param options [Hash]
+    # @option options [Boolean] :repopulate (true) whether or not to repopulate
+    #  the instance fields
+    # @raise [MachO::OffsetInsertionError] if the offset is not in the load command region
+    # @raise [MachO::HeaderPadError] if the new command exceeds the header pad buffer
+    # @note Calling this method with an arbitrary offset in the load command
+    #  region **will leave the object in an inconsistent state**.
+    def insert_command(offset, lc, options = {})
+      context = LoadCommand::SerializationContext.context_for(self)
+      cmd_raw = lc.serialize(context)
+
+      if offset < header.class.bytesize || offset + cmd_raw.bytesize > low_fileoff
+        raise OffsetInsertionError, offset
+      end
+
+      new_sizeofcmds = sizeofcmds + cmd_raw.bytesize
+
+      if header.class.bytesize + new_sizeofcmds > low_fileoff
+        raise HeaderPadError, @filename
+      end
+
+      # update Mach-O header fields to account for inserted load command
+      update_ncmds(ncmds + 1)
+      update_sizeofcmds(new_sizeofcmds)
+
+      @raw_data.insert(offset, cmd_raw)
+      @raw_data.slice!(header.class.bytesize + new_sizeofcmds, cmd_raw.bytesize)
+
+      populate_fields if options.fetch(:repopulate, true)
+    end
+
+    # Replace a load command with another command in the Mach-O, preserving location.
+    # @param old_lc [MachO::LoadCommand] the load command being replaced
+    # @param new_lc [MachO::LoadCommand] the load command being added
+    # @return [void]
+    # @raise [MachO::HeaderPadError] if the new command exceeds the header pad buffer
+    # @see {#insert_command}
+    # @note This is public, but methods like {#dylib_id=} should be preferred.
+    def replace_command(old_lc, new_lc)
+      context = LoadCommand::SerializationContext.context_for(self)
+      cmd_raw = new_lc.serialize(context)
+      new_sizeofcmds = sizeofcmds + cmd_raw.bytesize - old_lc.cmdsize
+      if header.class.bytesize + new_sizeofcmds > low_fileoff
+        raise HeaderPadError, @filename
+      end
+
+      delete_command(old_lc)
+      insert_command(old_lc.view.offset, new_lc)
+    end
+
+    # Appends a new load command to the Mach-O.
+    # @param lc [MachO::LoadCommand] the load command being added
+    # @param options [Hash]
+    # @option options [Boolean] :repopulate (true) whether or not to repopulate
+    #  the instance fields
+    # @return [void]
+    # @see {#insert_command}
+    # @note This is public, but methods like {#add_rpath} should be preferred.
+    #  Setting `repopulate` to false **will leave the instance in an
+    #  inconsistent state** unless {#populate_fields} is called **immediately**
+    #  afterwards.
+    def add_command(lc, options = {})
+      insert_command(header.class.bytesize + sizeofcmds, lc, options)
+    end
+
+    # Delete a load command from the Mach-O.
+    # @param lc [MachO::LoadCommand] the load command being deleted
+    # @param options [Hash]
+    # @option options [Boolean] :repopulate (true) whether or not to repopulate
+    #  the instance fields
+    # @return [void]
+    # @note This is public, but methods like {#delete_rpath} should be preferred.
+    #  Setting `repopulate` to false **will leave the instance in an
+    #  inconsistent state** unless {#populate_fields} is called **immediately**
+    #  afterwards.
+    def delete_command(lc, options = {})
+      @raw_data.slice!(lc.view.offset, lc.cmdsize)
+
+      # update Mach-O header fields to account for deleted load command
+      update_ncmds(ncmds - 1)
+      update_sizeofcmds(sizeofcmds - lc.cmdsize)
+
+      # pad the space after the load commands to preserve offsets
+      null_pad = "\x00" * lc.cmdsize
+      @raw_data.insert(header.class.bytesize + sizeofcmds - lc.cmdsize, null_pad)
+
+      populate_fields if options.fetch(:repopulate, true)
+    end
+
+    # Populate the instance's fields with the raw Mach-O data.
+    # @return [void]
+    # @note This method is public, but should (almost) never need to be called.
+    #  The exception to this rule is when methods like {#add_command} and
+    #  {#delete_command} have been called with `repopulate = false`.
+    def populate_fields
+      @header = populate_mach_header
+      @load_commands = populate_load_commands
+    end
 
     # All load commands responsible for loading dylibs.
     # @return [Array<MachO::DylibCommand>] an array of DylibCommands
@@ -188,9 +296,7 @@ module MachO
     #  file.dylib_id # => 'libBar.dylib'
     # @return [String, nil] the Mach-O's dylib ID
     def dylib_id
-      if !dylib?
-        return nil
-      end
+      return unless dylib?
 
       dylib_id_cmd = command(:LC_ID_DYLIB).first
 
@@ -199,25 +305,30 @@ module MachO
 
     # Changes the Mach-O's dylib ID to `new_id`. Does nothing if not a dylib.
     # @example
-    #  file.dylib_id = "libFoo.dylib"
+    #  file.change_dylib_id("libFoo.dylib")
     # @param new_id [String] the dylib's new ID
+    # @param _options [Hash]
     # @return [void]
     # @raise [ArgumentError] if `new_id` is not a String
-    def dylib_id=(new_id)
-      if !new_id.is_a?(String)
-        raise ArgumentError.new("argument must be a String")
-      end
+    # @note `_options` is currently unused and is provided for signature
+    #  compatibility with {MachO::FatFile#change_dylib_id}
+    def change_dylib_id(new_id, _options = {})
+      raise ArgumentError, "new ID must be a String" unless new_id.is_a?(String)
+      return unless dylib?
 
-      if !dylib?
-        return nil
-      end
+      old_lc = command(:LC_ID_DYLIB).first
+      raise DylibIdMissingError unless old_lc
 
-      dylib_cmd = command(:LC_ID_DYLIB).first
-      old_id = dylib_id
+      new_lc = LoadCommand.create(:LC_ID_DYLIB, new_id,
+                                  old_lc.timestamp,
+                                  old_lc.current_version,
+                                  old_lc.compatibility_version)
 
-      set_name_in_dylib(dylib_cmd, old_id, new_id)
+      replace_command(old_lc, new_lc)
     end
 
+    alias dylib_id= change_dylib_id
+
     # All shared libraries linked to the Mach-O.
     # @return [Array<String>] an array of all shared libraries
     def linked_dylibs
@@ -233,16 +344,24 @@ module MachO
     #  file.change_install_name("/usr/lib/libWhatever.dylib", "/usr/local/lib/libWhatever2.dylib")
     # @param old_name [String] the shared library's old name
     # @param new_name [String] the shared library's new name
+    # @param _options [Hash]
     # @return [void]
     # @raise [MachO::DylibUnknownError] if no shared library has the old name
-    def change_install_name(old_name, new_name)
-      dylib_cmd = dylib_load_commands.find { |d| d.name.to_s == old_name }
-      raise DylibUnknownError.new(old_name) if dylib_cmd.nil?
+    # @note `_options` is currently unused and is provided for signature
+    #  compatibility with {MachO::FatFile#change_install_name}
+    def change_install_name(old_name, new_name, _options = {})
+      old_lc = dylib_load_commands.find { |d| d.name.to_s == old_name }
+      raise DylibUnknownError, old_name if old_lc.nil?
 
-      set_name_in_dylib(dylib_cmd, old_name, new_name)
+      new_lc = LoadCommand.create(old_lc.type, new_name,
+                                  old_lc.timestamp,
+                                  old_lc.current_version,
+                                  old_lc.compatibility_version)
+
+      replace_command(old_lc, new_lc)
     end
 
-    alias :change_dylib :change_install_name
+    alias change_dylib change_install_name
 
     # All runtime paths searched by the dynamic linker for the Mach-O.
     # @return [Array<String>] an array of all runtime paths
@@ -255,44 +374,70 @@ module MachO
     #  file.change_rpath("/usr/lib", "/usr/local/lib")
     # @param old_path [String] the old runtime path
     # @param new_path [String] the new runtime path
+    # @param _options [Hash]
     # @return [void]
     # @raise [MachO::RpathUnknownError] if no such old runtime path exists
-    # @api private
-    def change_rpath(old_path, new_path)
-      rpath_cmd = command(:LC_RPATH).find { |r| r.path.to_s == old_path }
-      raise RpathUnknownError.new(old_path) if rpath_cmd.nil?
+    # @raise [MachO::RpathExistsError] if the new runtime path already exists
+    # @note `_options` is currently unused and is provided for signature
+    #  compatibility with {MachO::FatFile#change_rpath}
+    def change_rpath(old_path, new_path, _options = {})
+      old_lc = command(:LC_RPATH).find { |r| r.path.to_s == old_path }
+      raise RpathUnknownError, old_path if old_lc.nil?
+      raise RpathExistsError, new_path if rpaths.include?(new_path)
+
+      new_lc = LoadCommand.create(:LC_RPATH, new_path)
+
+      delete_rpath(old_path)
+      insert_command(old_lc.view.offset, new_lc)
+    end
 
-      set_path_in_rpath(rpath_cmd, old_path, new_path)
+    # Add the given runtime path to the Mach-O.
+    # @example
+    #  file.rpaths # => ["/lib"]
+    #  file.add_rpath("/usr/lib")
+    #  file.rpaths # => ["/lib", "/usr/lib"]
+    # @param path [String] the new runtime path
+    # @param _options [Hash]
+    # @return [void]
+    # @raise [MachO::RpathExistsError] if the runtime path already exists
+    # @note `_options` is currently unused and is provided for signature
+    #  compatibility with {MachO::FatFile#add_rpath}
+    def add_rpath(path, _options = {})
+      raise RpathExistsError, path if rpaths.include?(path)
+
+      rpath_cmd = LoadCommand.create(:LC_RPATH, path)
+      add_command(rpath_cmd)
+    end
+
+    # Delete the given runtime path from the Mach-O.
+    # @example
+    #  file.rpaths # => ["/lib"]
+    #  file.delete_rpath("/lib")
+    #  file.rpaths # => []
+    # @param path [String] the runtime path to delete
+    # @param _options [Hash]
+    # @return void
+    # @raise [MachO::RpathUnknownError] if no such runtime path exists
+    # @note `_options` is currently unused and is provided for signature
+    #  compatibility with {MachO::FatFile#delete_rpath}
+    def delete_rpath(path, _options = {})
+      rpath_cmds = command(:LC_RPATH).select { |r| r.path.to_s == path }
+      raise RpathUnknownError, path if rpath_cmds.empty?
+
+      # delete the commands in reverse order, offset descending. this
+      # allows us to defer (expensive) field population until the very end
+      rpath_cmds.reverse_each { |cmd| delete_command(cmd, :repopulate => false) }
+
+      populate_fields
     end
 
     # All sections of the segment `segment`.
     # @param segment [MachO::SegmentCommand, MachO::SegmentCommand64] the segment being inspected
     # @return [Array<MachO::Section>] if the Mach-O is 32-bit
     # @return [Array<MachO::Section64>] if the Mach-O is 64-bit
+    # @deprecated use {MachO::SegmentCommand#sections} instead
     def sections(segment)
-      sections = []
-
-      if !segment.is_a?(SegmentCommand) && !segment.is_a?(SegmentCommand64)
-        raise ArgumentError.new("not a valid segment")
-      end
-
-      if segment.nsects.zero?
-        return sections
-      end
-
-      offset = segment.offset + segment.class.bytesize
-
-      segment.nsects.times do
-        if segment.is_a? SegmentCommand
-          sections << Section.new_from_bin(endianness, @raw_data.slice(offset, Section.bytesize))
-          offset += Section.bytesize
-        else
-          sections << Section64.new_from_bin(endianness, @raw_data.slice(offset, Section64.bytesize))
-          offset += Section64.bytesize
-        end
-      end
-
-      sections
+      segment.sections
     end
 
     # Write all Mach-O data to the given filename.
@@ -308,7 +453,7 @@ module MachO
     # @note Overwrites all data in the file!
     def write!
       if @filename.nil?
-        raise MachOError.new("cannot write to a default file when initialized from a binary string")
+        raise MachOError, "cannot write to a default file when initialized from a binary string"
       else
         File.open(@filename, "wb") { |f| f.write(@raw_data) }
       end
@@ -320,13 +465,13 @@ module MachO
     # @return [MachO::MachHeader] if the Mach-O is 32-bit
     # @return [MachO::MachHeader64] if the Mach-O is 64-bit
     # @raise [MachO::TruncatedFileError] if the file is too small to have a valid header
-    # @private
-    def get_mach_header
+    # @api private
+    def populate_mach_header
       # the smallest Mach-O header is 28 bytes
-      raise TruncatedFileError.new if @raw_data.size < 28
+      raise TruncatedFileError if @raw_data.size < 28
 
-      magic = get_and_check_magic
-      mh_klass = MachO.magic32?(magic) ? MachHeader : MachHeader64
+      magic = populate_and_check_magic
+      mh_klass = Utils.magic32?(magic) ? MachHeader : MachHeader64
       mh = mh_klass.new_from_bin(endianness, @raw_data[0, mh_klass.bytesize])
 
       check_cputype(mh.cputype)
@@ -340,14 +485,14 @@ module MachO
     # @return [Fixnum] the magic
     # @raise [MachO::MagicError] if the magic is not valid Mach-O magic
     # @raise [MachO::FatBinaryError] if the magic is for a Fat file
-    # @private
-    def get_and_check_magic
+    # @api private
+    def populate_and_check_magic
       magic = @raw_data[0..3].unpack("N").first
 
-      raise MagicError.new(magic) unless MachO.magic?(magic)
-      raise FatBinaryError.new if MachO.fat_magic?(magic)
+      raise MagicError, magic unless Utils.magic?(magic)
+      raise FatBinaryError if Utils.fat_magic?(magic)
 
-      @endianness = MachO.little_magic?(magic) ? :little : :big
+      @endianness = Utils.little_magic?(magic) ? :little : :big
 
       magic
     end
@@ -355,47 +500,48 @@ module MachO
     # Check the file's CPU type.
     # @param cputype [Fixnum] the CPU type
     # @raise [MachO::CPUTypeError] if the CPU type is unknown
-    # @private
+    # @api private
     def check_cputype(cputype)
-      raise CPUTypeError.new(cputype) unless CPU_TYPES.key?(cputype)
+      raise CPUTypeError, cputype unless CPU_TYPES.key?(cputype)
     end
 
     # Check the file's CPU type/subtype pair.
     # @param cpusubtype [Fixnum] the CPU subtype
     # @raise [MachO::CPUSubtypeError] if the CPU sub-type is unknown
-    # @private
+    # @api private
     def check_cpusubtype(cputype, cpusubtype)
-      # Only check sub-type w/o capability bits (see `get_mach_header`).
+      # Only check sub-type w/o capability bits (see `populate_mach_header`).
       raise CPUSubtypeError.new(cputype, cpusubtype) unless CPU_SUBTYPES[cputype].key?(cpusubtype)
     end
 
     # Check the file's type.
     # @param filetype [Fixnum] the file type
     # @raise [MachO::FiletypeError] if the file type is unknown
-    # @private
+    # @api private
     def check_filetype(filetype)
-      raise FiletypeError.new(filetype) unless MH_FILETYPES.key?(filetype)
+      raise FiletypeError, filetype unless MH_FILETYPES.key?(filetype)
     end
 
     # All load commands in the file.
     # @return [Array<MachO::LoadCommand>] an array of load commands
     # @raise [MachO::LoadCommandError] if an unknown load command is encountered
-    # @private
-    def get_load_commands
+    # @api private
+    def populate_load_commands
       offset = header.class.bytesize
       load_commands = []
 
       header.ncmds.times do
-        fmt = (endianness == :little) ? "L<" : "L>"
+        fmt = Utils.specialize_format("L=", endianness)
         cmd = @raw_data.slice(offset, 4).unpack(fmt).first
         cmd_sym = LOAD_COMMANDS[cmd]
 
-        raise LoadCommandError.new(cmd) if cmd_sym.nil?
+        raise LoadCommandError, cmd if cmd_sym.nil?
 
         # why do I do this? i don't like declaring constants below
         # classes, and i need them to resolve...
-        klass = MachO.const_get "#{LC_STRUCTURES[cmd_sym]}"
-        command = klass.new_from_bin(@raw_data, endianness, offset, @raw_data.slice(offset, klass.bytesize))
+        klass = MachO.const_get LC_STRUCTURES[cmd_sym]
+        view = MachOView.new(@raw_data, endianness, offset)
+        command = klass.new_from_bin(view)
 
         load_commands << command
         offset += command.cmdsize
@@ -404,108 +550,44 @@ module MachO
       load_commands
     end
 
-    # Updates the size of all load commands in the raw data.
-    # @param size [Fixnum] the new size, in bytes
-    # @return [void]
-    # @private
-    def set_sizeofcmds(size)
-      fmt = (endianness == :little) ? "L<" : "L>"
-      new_size = [size].pack(fmt)
-      @raw_data[20..23] = new_size
-    end
-
-    # Updates the `name` field in a DylibCommand.
-    # @param dylib_cmd [MachO::DylibCommand] the dylib command
-    # @param old_name [String] the old dylib name
-    # @param new_name [String] the new dylib name
-    # @return [void]
-    # @private
-    def set_name_in_dylib(dylib_cmd, old_name, new_name)
-      set_lc_str_in_cmd(dylib_cmd, dylib_cmd.name, old_name, new_name)
-    end
-
-    # Updates the `path` field in an RpathCommand.
-    # @param rpath_cmd [MachO::RpathCommand] the rpath command
-    # @param old_path [String] the old runtime name
-    # @param new_path [String] the new runtime name
-    # @return [void]
-    # @private
-    def set_path_in_rpath(rpath_cmd, old_path, new_path)
-      set_lc_str_in_cmd(rpath_cmd, rpath_cmd.path, old_path, new_path)
-    end
-
-    # Updates a generic LCStr field in any LoadCommand.
-    # @param cmd [MachO::LoadCommand] the load command
-    # @param lc_str [MachO::LoadCommand::LCStr] the load command string
-    # @param old_str [String] the old string
-    # @param new_str [String] the new string
-    # @raise [MachO::HeaderPadError] if the new name exceeds the header pad buffer
-    # @private
-    def set_lc_str_in_cmd(cmd, lc_str, old_str, new_str)
-      if magic32?
-        cmd_round = 4
-      else
-        cmd_round = 8
-      end
-
-      new_sizeofcmds = header.sizeofcmds
-      old_str = old_str.dup
-      new_str = new_str.dup
-
-      old_pad = MachO.round(old_str.size + 1, cmd_round) - old_str.size
-      new_pad = MachO.round(new_str.size + 1, cmd_round) - new_str.size
-
-      # pad the old and new IDs with null bytes to meet command bounds
-      old_str << "\x00" * old_pad
-      new_str << "\x00" * new_pad
-
-      # calculate the new size of the cmd and sizeofcmds in MH
-      new_size = cmd.class.bytesize + new_str.size
-      new_sizeofcmds += new_size - cmd.cmdsize
-
-      low_fileoff = @raw_data.size
+    # The low file offset (offset to first section data).
+    # @return [Fixnum] the offset
+    # @api private
+    def low_fileoff
+      offset = @raw_data.size
 
-      # calculate the low file offset (offset to first section data)
       segments.each do |seg|
-        sections(seg).each do |sect|
-          next if sect.size == 0
+        seg.sections.each do |sect|
+          next if sect.empty?
           next if sect.flag?(:S_ZEROFILL)
           next if sect.flag?(:S_THREAD_LOCAL_ZEROFILL)
-          next unless sect.offset < low_fileoff
+          next unless sect.offset < offset
 
-          low_fileoff = sect.offset
+          offset = sect.offset
         end
       end
 
-      if new_sizeofcmds + header.class.bytesize > low_fileoff
-        raise HeaderPadError.new(@filename)
-      end
-
-      # update sizeofcmds in mach_header
-      set_sizeofcmds(new_sizeofcmds)
-
-      # update cmdsize in the cmd
-      fmt = (endianness == :little) ? "L<" : "L>"
-      @raw_data[cmd.offset + 4, 4] = [new_size].pack(fmt)
-
-      # delete the old str
-      @raw_data.slice!(cmd.offset + lc_str.to_i...cmd.offset + cmd.class.bytesize + old_str.size)
-
-      # insert the new str
-      @raw_data.insert(cmd.offset + lc_str.to_i, new_str)
-
-      # pad/unpad after new_sizeofcmds until offsets are corrected
-      null_pad = old_str.size - new_str.size
+      offset
+    end
 
-      if null_pad < 0
-        @raw_data.slice!(new_sizeofcmds + header.class.bytesize, null_pad.abs)
-      else
-        @raw_data.insert(new_sizeofcmds + header.class.bytesize, "\x00" * null_pad)
-      end
+    # Updates the number of load commands in the raw data.
+    # @param ncmds [Fixnum] the new number of commands
+    # @return [void]
+    # @api private
+    def update_ncmds(ncmds)
+      fmt = Utils.specialize_format("L=", endianness)
+      ncmds_raw = [ncmds].pack(fmt)
+      @raw_data[16..19] = ncmds_raw
+    end
 
-      # synchronize fields with the raw data
-      @header = get_mach_header
-      @load_commands = get_load_commands
+    # Updates the size of all load commands in the raw data.
+    # @param size [Fixnum] the new size, in bytes
+    # @return [void]
+    # @api private
+    def update_sizeofcmds(size)
+      fmt = Utils.specialize_format("L=", endianness)
+      size_raw = [size].pack(fmt)
+      @raw_data[20..23] = size_raw
     end
   end
 end
diff --git a/Library/Homebrew/vendor/macho/macho/open.rb b/Library/Homebrew/vendor/macho/macho/open.rb
index ad1b02bb21..103f617410 100644
--- a/Library/Homebrew/vendor/macho/macho/open.rb
+++ b/Library/Homebrew/vendor/macho/macho/open.rb
@@ -7,17 +7,17 @@ module MachO
   # @raise [MachO::TruncatedFileError] if the file is too small to have a valid header
   # @raise [MachO::MagicError] if the file's magic is not valid Mach-O magic
   def self.open(filename)
-    raise ArgumentError.new("#{filename}: no such file") unless File.file?(filename)
-    raise TruncatedFileError.new unless File.stat(filename).size >= 4
+    raise ArgumentError, "#{filename}: no such file" unless File.file?(filename)
+    raise TruncatedFileError unless File.stat(filename).size >= 4
 
     magic = File.open(filename, "rb") { |f| f.read(4) }.unpack("N").first
 
-    if MachO.fat_magic?(magic)
+    if Utils.fat_magic?(magic)
       file = FatFile.new(filename)
-    elsif MachO.magic?(magic)
+    elsif Utils.magic?(magic)
       file = MachOFile.new(filename)
     else
-      raise MagicError.new(magic)
+      raise MagicError, magic
     end
 
     file
diff --git a/Library/Homebrew/vendor/macho/macho/sections.rb b/Library/Homebrew/vendor/macho/macho/sections.rb
index 3ea1e3fa4b..bd6218bb5a 100644
--- a/Library/Homebrew/vendor/macho/macho/sections.rb
+++ b/Library/Homebrew/vendor/macho/macho/sections.rb
@@ -45,7 +45,7 @@ module MachO
     :S_ATTR_DEBUG => 0x02000000,
     :S_ATTR_SOME_INSTRUCTIONS => 0x00000400,
     :S_ATTR_EXT_RELOC => 0x00000200,
-    :S_ATTR_LOC_RELOC => 0x00000100
+    :S_ATTR_LOC_RELOC => 0x00000100,
   }.freeze
 
   # association of section name symbols to names
@@ -62,7 +62,7 @@ module MachO
     :SECT_OBJC_STRINGS => "__selector_strs",
     :SECT_OBJC_REFS => "__selector_refs",
     :SECT_ICON_HEADER => "__header",
-    :SECT_ICON_TIFF => "__tiff"
+    :SECT_ICON_TIFF => "__tiff",
   }.freeze
 
   # Represents a section of a segment for 32-bit architectures.
@@ -91,7 +91,7 @@ module MachO
     # @return [Fixnum] the number of relocation entries
     attr_reader :nreloc
 
-    # @return [Fixnum] flags for type and addrributes of the section
+    # @return [Fixnum] flags for type and attributes of the section
     attr_reader :flags
 
     # @return [void] reserved (for offset or index)
@@ -100,12 +100,15 @@ module MachO
     # @return [void] reserved (for count or sizeof)
     attr_reader :reserved2
 
-    FORMAT = "a16a16L=9"
+    # @see MachOStructure::FORMAT
+    FORMAT = "a16a16L=9".freeze
+
+    # @see MachOStructure::SIZEOF
     SIZEOF = 68
 
     # @api private
     def initialize(sectname, segname, addr, size, offset, align, reloff,
-        nreloc, flags, reserved1, reserved2)
+                   nreloc, flags, reserved1, reserved2)
       @sectname = sectname
       @segname = segname
       @addr = addr
@@ -121,12 +124,17 @@ module MachO
 
     # @return [String] the section's name, with any trailing NULL characters removed
     def section_name
-      @sectname.delete("\x00")
+      sectname.delete("\x00")
     end
 
     # @return [String] the parent segment's name, with any trailing NULL characters removed
     def segment_name
-      @segname.delete("\x00")
+      segname.delete("\x00")
+    end
+
+    # @return [Boolean] true if the section has no contents (i.e, `size` is 0)
+    def empty?
+      size.zero?
     end
 
     # @example
@@ -145,12 +153,15 @@ module MachO
     # @return [void] reserved
     attr_reader :reserved3
 
-    FORMAT = "a16a16Q=2L=8"
+    # @see MachOStructure::FORMAT
+    FORMAT = "a16a16Q=2L=8".freeze
+
+    # @see MachOStructure::SIZEOF
     SIZEOF = 80
 
     # @api private
     def initialize(sectname, segname, addr, size, offset, align, reloff,
-        nreloc, flags, reserved1, reserved2, reserved3)
+                   nreloc, flags, reserved1, reserved2, reserved3)
       super(sectname, segname, addr, size, offset, align, reloff,
         nreloc, flags, reserved1, reserved2)
       @reserved3 = reserved3
diff --git a/Library/Homebrew/vendor/macho/macho/structure.rb b/Library/Homebrew/vendor/macho/macho/structure.rb
index aaa2ada275..43f7bc84ed 100644
--- a/Library/Homebrew/vendor/macho/macho/structure.rb
+++ b/Library/Homebrew/vendor/macho/macho/structure.rb
@@ -3,9 +3,13 @@ module MachO
   # @abstract
   class MachOStructure
     # The String#unpack format of the data structure.
-    FORMAT = ""
+    # @return [String] the unpacking format
+    # @api private
+    FORMAT = "".freeze
 
     # The size of the data structure, in bytes.
+    # @return [Fixnum] the size, in bytes
+    # @api private
     SIZEOF = 0
 
     # @return [Fixnum] the size, in bytes, of the represented structure.
@@ -13,26 +17,14 @@ module MachO
       self::SIZEOF
     end
 
-    # @param endianness [Symbol] either :big or :little
+    # @param endianness [Symbol] either `:big` or `:little`
     # @param bin [String] the string to be unpacked into the new structure
     # @return [MachO::MachOStructure] a new MachOStructure initialized with `bin`
     # @api private
     def self.new_from_bin(endianness, bin)
-      format = specialize_format(self::FORMAT, endianness)
-
-      self.new(*bin.unpack(format))
-    end
-
-    private
+      format = Utils.specialize_format(self::FORMAT, endianness)
 
-    # Convert an abstract (native-endian) String#unpack format to big or little.
-    # @param format [String] the format string being converted
-    # @param endianness [Symbol] either :big or :little
-    # @return [String] the converted string
-    # @api private
-    def self.specialize_format(format, endianness)
-      modifier = (endianness == :big) ? ">" : "<"
-      format.tr("=", modifier)
+      new(*bin.unpack(format))
     end
   end
 end
diff --git a/Library/Homebrew/vendor/macho/macho/tools.rb b/Library/Homebrew/vendor/macho/macho/tools.rb
index fe3da455b4..f34d75dc14 100644
--- a/Library/Homebrew/vendor/macho/macho/tools.rb
+++ b/Library/Homebrew/vendor/macho/macho/tools.rb
@@ -12,12 +12,14 @@ module MachO
     # Changes the dylib ID of a Mach-O or Fat binary, overwriting the source file.
     # @param filename [String] the Mach-O or Fat binary being modified
     # @param new_id [String] the new dylib ID for the binary
+    # @param options [Hash]
+    # @option options [Boolean] :strict (true) whether or not to fail loudly
+    #  with an exception if the change cannot be performed
     # @return [void]
-    # @todo unstub for fat files
-    def self.change_dylib_id(filename, new_id)
+    def self.change_dylib_id(filename, new_id, options = {})
       file = MachO.open(filename)
 
-      file.dylib_id = new_id
+      file.change_dylib_id(new_id, options)
       file.write!
     end
 
@@ -25,12 +27,14 @@ module MachO
     # @param filename [String] the Mach-O or Fat binary being modified
     # @param old_name [String] the old shared library name
     # @param new_name [String] the new shared library name
+    # @param options [Hash]
+    # @option options [Boolean] :strict (true) whether or not to fail loudly
+    #  with an exception if the change cannot be performed
     # @return [void]
-    # @todo unstub for fat files
-    def self.change_install_name(filename, old_name, new_name)
+    def self.change_install_name(filename, old_name, new_name, options = {})
       file = MachO.open(filename)
 
-      file.change_install_name(old_name, new_name)
+      file.change_install_name(old_name, new_name, options)
       file.write!
     end
 
@@ -38,28 +42,43 @@ module MachO
     # @param filename [String] the Mach-O or Fat binary being modified
     # @param old_path [String] the old runtime path
     # @param new_path [String] the new runtime path
+    # @param options [Hash]
+    # @option options [Boolean] :strict (true) whether or not to fail loudly
+    #  with an exception if the change cannot be performed
     # @return [void]
-    # @todo unstub
-    def self.change_rpath(filename, old_path, new_path)
-      raise UnimplementedError.new("changing rpaths in a Mach-O")
+    def self.change_rpath(filename, old_path, new_path, options = {})
+      file = MachO.open(filename)
+
+      file.change_rpath(old_path, new_path, options)
+      file.write!
     end
 
     # Add a runtime path to a Mach-O or Fat binary, overwriting the source file.
     # @param filename [String] the Mach-O or Fat binary being modified
     # @param new_path [String] the new runtime path
+    # @param options [Hash]
+    # @option options [Boolean] :strict (true) whether or not to fail loudly
+    #  with an exception if the change cannot be performed
     # @return [void]
-    # @todo unstub
-    def self.add_rpath(filename, new_path)
-      raise UnimplementedError.new("adding rpaths to a Mach-O")
+    def self.add_rpath(filename, new_path, options = {})
+      file = MachO.open(filename)
+
+      file.add_rpath(new_path, options)
+      file.write!
     end
 
     # Delete a runtime path from a Mach-O or Fat binary, overwriting the source file.
     # @param filename [String] the Mach-O or Fat binary being modified
     # @param old_path [String] the old runtime path
+    # @param options [Hash]
+    # @option options [Boolean] :strict (true) whether or not to fail loudly
+    #  with an exception if the change cannot be performed
     # @return [void]
-    # @todo unstub
-    def self.delete_rpath(filename, old_path)
-      raise UnimplementedError.new("removing rpaths from a Mach-O")
+    def self.delete_rpath(filename, old_path, options = {})
+      file = MachO.open(filename)
+
+      file.delete_rpath(old_path, options)
+      file.write!
     end
   end
 end
diff --git a/Library/Homebrew/vendor/macho/macho/utils.rb b/Library/Homebrew/vendor/macho/macho/utils.rb
index 102f1e57d4..deb4c9c665 100644
--- a/Library/Homebrew/vendor/macho/macho/utils.rb
+++ b/Library/Homebrew/vendor/macho/macho/utils.rb
@@ -1,48 +1,96 @@
 module MachO
-  # @param value [Fixnum] the number being rounded
-  # @param round [Fixnum] the number being rounded with
-  # @return [Fixnum] the next number >= `value` such that `round` is its divisor
-  # @see http://www.opensource.apple.com/source/cctools/cctools-870/libstuff/rnd.c
-  def self.round(value, round)
-    round -= 1
-    value += round
-    value &= ~round
-    value
-  end
+  # A collection of utility functions used throughout ruby-macho.
+  module Utils
+    # Rounds a value to the next multiple of the given round.
+    # @param value [Fixnum] the number being rounded
+    # @param round [Fixnum] the number being rounded with
+    # @return [Fixnum] the rounded value
+    # @see http://www.opensource.apple.com/source/cctools/cctools-870/libstuff/rnd.c
+    def self.round(value, round)
+      round -= 1
+      value += round
+      value &= ~round
+      value
+    end
 
-  # @param num [Fixnum] the number being checked
-  # @return [Boolean] true if `num` is a valid Mach-O magic number, false otherwise
-  def self.magic?(num)
-    MH_MAGICS.has_key?(num)
-  end
+    # Returns the number of bytes needed to pad the given size to the given alignment.
+    # @param size [Fixnum] the unpadded size
+    # @param alignment [Fixnum] the number to alignment the size with
+    # @return [Fixnum] the number of pad bytes required
+    def self.padding_for(size, alignment)
+      round(size, alignment) - size
+    end
 
-  # @param num [Fixnum] the number being checked
-  # @return [Boolean] true if `num` is a valid Fat magic number, false otherwise
-  def self.fat_magic?(num)
-    num == FAT_MAGIC
-  end
+    # Converts an abstract (native-endian) String#unpack format to big or little.
+    # @param format [String] the format string being converted
+    # @param endianness [Symbol] either `:big` or `:little`
+    # @return [String] the converted string
+    def self.specialize_format(format, endianness)
+      modifier = endianness == :big ? ">" : "<"
+      format.tr("=", modifier)
+    end
 
-  # @param num [Fixnum] the number being checked
-  # @return [Boolean] true if `num` is a valid 32-bit magic number, false otherwise
-  def self.magic32?(num)
-    num == MH_MAGIC || num == MH_CIGAM
-  end
+    # Packs tagged strings into an aligned payload.
+    # @param fixed_offset [Fixnum] the baseline offset for the first packed string
+    # @param alignment [Fixnum] the alignment value to use for packing
+    # @param strings [Hash] the labeled strings to pack
+    # @return [Array<String, Hash>] the packed string and labeled offsets
+    def self.pack_strings(fixed_offset, alignment, strings = {})
+      offsets = {}
+      next_offset = fixed_offset
+      payload = ""
 
-  # @param num [Fixnum] the number being checked
-  # @return [Boolean] true if `num` is a valid 64-bit magic number, false otherwise
-  def self.magic64?(num)
-    num == MH_MAGIC_64 || num == MH_CIGAM_64
-  end
+      strings.each do |key, string|
+        offsets[key] = next_offset
+        payload << string
+        payload << "\x00"
+        next_offset += string.bytesize + 1
+      end
 
-  # @param num [Fixnum] the number being checked
-  # @return [Boolean] true if `num` is a valid little-endian magic number, false otherwise
-  def self.little_magic?(num)
-    num == MH_CIGAM || num == MH_CIGAM_64
-  end
+      payload << "\x00" * padding_for(fixed_offset + payload.bytesize, alignment)
+      [payload, offsets]
+    end
+
+    # Compares the given number to valid Mach-O magic numbers.
+    # @param num [Fixnum] the number being checked
+    # @return [Boolean] true if `num` is a valid Mach-O magic number, false otherwise
+    def self.magic?(num)
+      MH_MAGICS.key?(num)
+    end
+
+    # Compares the given number to valid Fat magic numbers.
+    # @param num [Fixnum] the number being checked
+    # @return [Boolean] true if `num` is a valid Fat magic number, false otherwise
+    def self.fat_magic?(num)
+      num == FAT_MAGIC
+    end
+
+    # Compares the given number to valid 32-bit Mach-O magic numbers.
+    # @param num [Fixnum] the number being checked
+    # @return [Boolean] true if `num` is a valid 32-bit magic number, false otherwise
+    def self.magic32?(num)
+      num == MH_MAGIC || num == MH_CIGAM
+    end
+
+    # Compares the given number to valid 64-bit Mach-O magic numbers.
+    # @param num [Fixnum] the number being checked
+    # @return [Boolean] true if `num` is a valid 64-bit magic number, false otherwise
+    def self.magic64?(num)
+      num == MH_MAGIC_64 || num == MH_CIGAM_64
+    end
+
+    # Compares the given number to valid little-endian magic numbers.
+    # @param num [Fixnum] the number being checked
+    # @return [Boolean] true if `num` is a valid little-endian magic number, false otherwise
+    def self.little_magic?(num)
+      num == MH_CIGAM || num == MH_CIGAM_64
+    end
 
-  # @param num [Fixnum] the number being checked
-  # @return [Boolean] true if `num` is a valid big-endian magic number, false otherwise
-  def self.big_magic?(num)
-    num == MH_CIGAM || num == MH_CIGAM_64
+    # Compares the given number to valid big-endian magic numbers.
+    # @param num [Fixnum] the number being checked
+    # @return [Boolean] true if `num` is a valid big-endian magic number, false otherwise
+    def self.big_magic?(num)
+      num == MH_CIGAM || num == MH_CIGAM_64
+    end
   end
 end
diff --git a/Library/Homebrew/vendor/macho/macho/view.rb b/Library/Homebrew/vendor/macho/macho/view.rb
new file mode 100644
index 0000000000..9586e73bee
--- /dev/null
+++ b/Library/Homebrew/vendor/macho/macho/view.rb
@@ -0,0 +1,23 @@
+module MachO
+  # A representation of some unspecified Mach-O data.
+  class MachOView
+    # @return [String] the raw Mach-O data
+    attr_reader :raw_data
+
+    # @return [Symbol] the endianness of the data (`:big` or `:little`)
+    attr_reader :endianness
+
+    # @return [Fixnum] the offset of the relevant data (in {#raw_data})
+    attr_reader :offset
+
+    # Creates a new MachOView.
+    # @param raw_data [String] the raw Mach-O data
+    # @param endianness [Symbol] the endianness of the data
+    # @param offset [Fixnum] the offset of the relevant data
+    def initialize(raw_data, endianness, offset)
+      @raw_data = raw_data
+      @endianness = endianness
+      @offset = offset
+    end
+  end
+end
-- 
GitLab