aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
Diffstat (limited to 'Library')
-rw-r--r--Library/Homebrew/blacklist.rb92
-rw-r--r--Library/Homebrew/cask/lib/hbc/container.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/container/executable.rb18
-rw-r--r--Library/Homebrew/cmd/info.rb12
-rw-r--r--Library/Homebrew/cmd/install.rb74
-rw-r--r--Library/Homebrew/cmd/link.rb17
-rw-r--r--Library/Homebrew/cmd/log.rb28
-rw-r--r--Library/Homebrew/cmd/outdated.rb8
-rw-r--r--Library/Homebrew/cmd/search.rb9
-rw-r--r--Library/Homebrew/cmd/update-report.rb17
-rw-r--r--Library/Homebrew/dev-cmd/audit.rb67
-rw-r--r--Library/Homebrew/dev-cmd/boneyard-formula-pr.rb166
-rw-r--r--Library/Homebrew/dev-cmd/create.rb6
-rw-r--r--Library/Homebrew/dev-cmd/man.rb9
-rw-r--r--Library/Homebrew/dev-cmd/pull.rb15
-rw-r--r--Library/Homebrew/dev-cmd/tap-new.rb1
-rw-r--r--Library/Homebrew/dev-cmd/tests.rb1
-rw-r--r--Library/Homebrew/dev-cmd/update-test.rb14
-rw-r--r--Library/Homebrew/diagnostic.rb49
-rw-r--r--Library/Homebrew/exceptions.rb8
-rw-r--r--Library/Homebrew/extend/os/blacklist.rb2
-rw-r--r--Library/Homebrew/extend/os/mac/blacklist.rb16
-rw-r--r--Library/Homebrew/extend/os/mac/missing_formula.rb22
-rw-r--r--Library/Homebrew/extend/os/missing_formula.rb2
-rw-r--r--Library/Homebrew/formula.rb8
-rw-r--r--Library/Homebrew/formula_installer.rb7
-rw-r--r--Library/Homebrew/formula_support.rb2
-rw-r--r--Library/Homebrew/gpg.rb4
-rw-r--r--Library/Homebrew/migrator.rb39
-rw-r--r--Library/Homebrew/missing_formula.rb168
-rw-r--r--Library/Homebrew/official_taps.rb3
-rw-r--r--Library/Homebrew/requirement.rb4
-rw-r--r--Library/Homebrew/requirements/gpg2_requirement.rb4
-rw-r--r--Library/Homebrew/tap.rb9
-rw-r--r--Library/Homebrew/test/blacklist_spec.rb115
-rw-r--r--Library/Homebrew/test/cmd/log_spec.rb2
-rw-r--r--Library/Homebrew/test/cmd/outdated_spec.rb92
-rw-r--r--Library/Homebrew/test/formula_installer_spec.rb46
-rw-r--r--Library/Homebrew/test/formula_spec.rb28
-rw-r--r--Library/Homebrew/test/missing_formula_spec.rb179
-rw-r--r--Library/Homebrew/utils/github.rb1
-rw-r--r--Library/Homebrew/vendor/README.md4
-rw-r--r--Library/Homebrew/vendor/macho/macho.rb27
-rw-r--r--Library/Homebrew/vendor/macho/macho/exceptions.rb12
-rw-r--r--Library/Homebrew/vendor/macho/macho/fat_file.rb202
-rw-r--r--Library/Homebrew/vendor/macho/macho/headers.rb1176
-rw-r--r--Library/Homebrew/vendor/macho/macho/load_commands.rb2158
-rw-r--r--Library/Homebrew/vendor/macho/macho/macho_file.rb258
-rw-r--r--Library/Homebrew/vendor/macho/macho/open.rb25
-rw-r--r--Library/Homebrew/vendor/macho/macho/sections.rb320
-rw-r--r--Library/Homebrew/vendor/macho/macho/structure.rb2
-rw-r--r--Library/Homebrew/vendor/macho/macho/tools.rb34
-rw-r--r--Library/Homebrew/vendor/macho/macho/utils.rb35
53 files changed, 3016 insertions, 2603 deletions
diff --git a/Library/Homebrew/blacklist.rb b/Library/Homebrew/blacklist.rb
deleted file mode 100644
index 93c8f81a0..000000000
--- a/Library/Homebrew/blacklist.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-def blacklisted?(name)
- case name.downcase
- when "gem", /^rubygems?$/ then <<-EOS.undent
- Homebrew provides gem via: `brew install ruby`.
- EOS
- when "tex", "tex-live", "texlive", "latex" then <<-EOS.undent
- Installing TeX from source is weird and gross, requires a lot of patches,
- and only builds 32-bit (and thus can't use Homebrew dependencies)
-
- We recommend using a MacTeX distribution: https://www.tug.org/mactex/
-
- You can install it with Homebrew-Cask:
- brew cask install mactex
- EOS
- when "pip" then <<-EOS.undent
- Homebrew provides pip via: `brew install python`. However you will then
- have two Pythons installed on your Mac, so alternatively you can install
- pip via the instructions at:
- #{Formatter.url("https://pip.readthedocs.io/en/stable/installing/")}
- EOS
- when "pil" then <<-EOS.undent
- Instead of PIL, consider `pip install pillow` or `brew install Homebrew/python/pillow`.
- EOS
- when "macruby" then <<-EOS.undent
- MacRuby is not packaged and is on an indefinite development hiatus.
- You can read more about it at:
- #{Formatter.url("https://github.com/MacRuby/MacRuby")}
- EOS
- when /(lib)?lzma/
- "lzma is now part of the xz formula."
- when "gtest", "googletest", "google-test" then <<-EOS.undent
- Installing gtest system-wide is not recommended; it should be vendored
- in your projects that use it.
- EOS
- when "gmock", "googlemock", "google-mock" then <<-EOS.undent
- Installing gmock system-wide is not recommended; it should be vendored
- in your projects that use it.
- EOS
- when "sshpass" then <<-EOS.undent
- We won't add sshpass because it makes it too easy for novice SSH users to
- ruin SSH's security.
- EOS
- when "gsutil" then <<-EOS.undent
- Install gsutil with `pip install gsutil`
- EOS
- when "clojure" then <<-EOS.undent
- Clojure isn't really a program but a library managed as part of a
- project and Leiningen is the user interface to that library.
-
- To install Clojure you should install Leiningen:
- brew install leiningen
- and then follow the tutorial:
- #{Formatter.url("https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md")}
- EOS
- when "osmium" then <<-EOS.undent
- The creator of Osmium requests that it not be packaged and that people
- use the GitHub master branch instead.
- EOS
- when "gfortran" then <<-EOS.undent
- GNU Fortran is now provided as part of GCC, and can be installed with:
- brew install gcc
- EOS
- when "play" then <<-EOS.undent
- Play 2.3 replaces the play command with activator:
- brew install typesafe-activator
-
- You can read more about this change at:
- #{Formatter.url("https://www.playframework.com/documentation/2.3.x/Migration23")}
- #{Formatter.url("https://www.playframework.com/documentation/2.3.x/Highlights23")}
- EOS
- when "haskell-platform" then <<-EOS.undent
- We no longer package haskell-platform. Consider installing ghc
- and cabal-install instead:
- brew install ghc cabal-install
-
- You can install with Homebrew-Cask:
- brew cask install haskell-platform
- EOS
- when "mysqldump-secure" then <<-EOS.undent
- The creator of mysqldump-secure tried to game our popularity metrics.
- EOS
- when "ngrok" then <<-EOS.undent
- Upstream sunsetted 1.x in March 2016 and 2.x is not open-source.
-
- If you wish to use the 2.x release you can install with Homebrew-Cask:
- brew cask install ngrok
- EOS
- end
-end
-alias generic_blacklisted? blacklisted?
-
-require "extend/os/blacklist"
diff --git a/Library/Homebrew/cask/lib/hbc/container.rb b/Library/Homebrew/cask/lib/hbc/container.rb
index fc7246f3d..c6b2c3c37 100644
--- a/Library/Homebrew/cask/lib/hbc/container.rb
+++ b/Library/Homebrew/cask/lib/hbc/container.rb
@@ -4,6 +4,7 @@ require "hbc/container/bzip2"
require "hbc/container/cab"
require "hbc/container/criteria"
require "hbc/container/dmg"
+require "hbc/container/executable"
require "hbc/container/generic_unar"
require "hbc/container/gzip"
require "hbc/container/lzma"
@@ -39,6 +40,7 @@ module Hbc
Gzip, # pure gzip
Lzma, # pure lzma
Xz, # pure xz
+ Executable,
]
# for explicit use only (never autodetected):
# Hbc::Container::Naked
diff --git a/Library/Homebrew/cask/lib/hbc/container/executable.rb b/Library/Homebrew/cask/lib/hbc/container/executable.rb
new file mode 100644
index 000000000..848f6d4be
--- /dev/null
+++ b/Library/Homebrew/cask/lib/hbc/container/executable.rb
@@ -0,0 +1,18 @@
+require "hbc/container/naked"
+require "vendor/macho/macho"
+
+module Hbc
+ class Container
+ class Executable < Naked
+ def self.me?(criteria)
+ return true if criteria.magic_number(/^#!\s*\S+/)
+
+ begin
+ MachO.open(criteria.path).header.executable?
+ rescue MachO::MagicError
+ false
+ end
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb
index b7de0005c..e7ad6821d 100644
--- a/Library/Homebrew/cmd/info.rb
+++ b/Library/Homebrew/cmd/info.rb
@@ -16,7 +16,7 @@
#: See the docs for examples of using the JSON output:
#: <http://docs.brew.sh/Querying-Brew.html>
-require "blacklist"
+require "missing_formula"
require "caveats"
require "options"
require "formula"
@@ -54,10 +54,12 @@ module Homebrew
else
info_formula Formulary.find_with_priority(f)
end
- rescue FormulaUnavailableError
- # No formula with this name, try a blacklist lookup
- raise unless (blacklist = blacklisted?(f))
- puts blacklist
+ rescue FormulaUnavailableError => e
+ ofail e.message
+ # No formula with this name, try a missing formula lookup
+ if (reason = Homebrew::MissingFormula.reason(f))
+ $stderr.puts reason
+ end
end
end
end
diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb
index c825e2796..e54286f09 100644
--- a/Library/Homebrew/cmd/install.rb
+++ b/Library/Homebrew/cmd/install.rb
@@ -55,7 +55,7 @@
#: If `--git` is passed, Homebrew will create a Git repository, useful for
#: creating patches to the software.
-require "blacklist"
+require "missing_formula"
require "diagnostic"
require "cmd/search"
require "formula_installer"
@@ -206,43 +206,47 @@ module Homebrew
# formula was found, but there's a problem with its implementation).
ofail e.message
rescue FormulaUnavailableError => e
- if (blacklist = blacklisted?(e.name))
- ofail "#{e.message}\n#{blacklist}"
- elsif e.name == "updog"
+ if e.name == "updog"
ofail "What's updog?"
+ return
+ end
+
+ ofail e.message
+ if (reason = Homebrew::MissingFormula.reason(e.name))
+ $stderr.puts reason
+ return
+ end
+
+ query = query_regexp(e.name)
+
+ ohai "Searching for similarly named formulae..."
+ formulae_search_results = search_formulae(query)
+ case formulae_search_results.length
+ when 0
+ ofail "No similarly named formulae found."
+ when 1
+ puts "This similarly named formula was found:"
+ puts formulae_search_results
+ puts "To install it, run:\n brew install #{formulae_search_results.first}"
else
- ofail e.message
- query = query_regexp(e.name)
-
- ohai "Searching for similarly named formulae..."
- formulae_search_results = search_formulae(query)
- case formulae_search_results.length
- when 0
- ofail "No similarly named formulae found."
- when 1
- puts "This similarly named formula was found:"
- puts formulae_search_results
- puts "To install it, run:\n brew install #{formulae_search_results.first}"
- else
- puts "These similarly named formulae were found:"
- puts Formatter.columns(formulae_search_results)
- puts "To install one of them, run (for example):\n brew install #{formulae_search_results.first}"
- end
+ puts "These similarly named formulae were found:"
+ puts Formatter.columns(formulae_search_results)
+ puts "To install one of them, run (for example):\n brew install #{formulae_search_results.first}"
+ end
- ohai "Searching taps..."
- taps_search_results = search_taps(query)
- case taps_search_results.length
- when 0
- ofail "No formulae found in taps."
- when 1
- puts "This formula was found in a tap:"
- puts taps_search_results
- puts "To install it, run:\n brew install #{taps_search_results.first}"
- else
- puts "These formulae were found in taps:"
- puts Formatter.columns(taps_search_results)
- puts "To install one of them, run (for example):\n brew install #{taps_search_results.first}"
- end
+ ohai "Searching taps..."
+ taps_search_results = search_taps(query)
+ case taps_search_results.length
+ when 0
+ ofail "No formulae found in taps."
+ when 1
+ puts "This formula was found in a tap:"
+ puts taps_search_results
+ puts "To install it, run:\n brew install #{taps_search_results.first}"
+ else
+ puts "These formulae were found in taps:"
+ puts Formatter.columns(taps_search_results)
+ puts "To install one of them, run (for example):\n brew install #{taps_search_results.first}"
end
end
end
diff --git a/Library/Homebrew/cmd/link.rb b/Library/Homebrew/cmd/link.rb
index 98cf98bf7..293f09eef 100644
--- a/Library/Homebrew/cmd/link.rb
+++ b/Library/Homebrew/cmd/link.rb
@@ -44,6 +44,7 @@ module Homebrew
elsif keg_only && !ARGV.force?
opoo "#{keg.name} is keg-only and must be linked with --force"
puts "Note that doing so can interfere with building software."
+ puts_keg_only_path_message(keg)
next
elsif mode.dry_run && mode.overwrite
puts "Would remove:"
@@ -53,6 +54,7 @@ module Homebrew
elsif mode.dry_run
puts "Would link:"
keg.link(mode)
+ puts_keg_only_path_message(keg) if keg_only
next
end
@@ -69,10 +71,25 @@ module Homebrew
else
puts "#{n} symlinks created"
end
+
+ if keg_only && !ARGV.homebrew_developer?
+ puts_keg_only_path_message(keg)
+ end
end
end
end
+ def puts_keg_only_path_message(keg)
+ bin = keg/"bin"
+ sbin = keg/"sbin"
+ return if !bin.directory? && !sbin.directory?
+
+ opt = HOMEBREW_PREFIX/"opt/#{keg.name}"
+ puts "\nIf you need to have this software first in your PATH instead consider running:"
+ puts " #{Utils::Shell.prepend_path_in_shell_profile(opt)}/bin" if bin.directory?
+ puts " #{Utils::Shell.prepend_path_in_shell_profile(opt)}/sbin" if sbin.directory?
+ end
+
def keg_only?(rack)
Formulary.from_rack(rack).keg_only?
rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
diff --git a/Library/Homebrew/cmd/log.rb b/Library/Homebrew/cmd/log.rb
index 22a3ee11d..9323c762d 100644
--- a/Library/Homebrew/cmd/log.rb
+++ b/Library/Homebrew/cmd/log.rb
@@ -9,20 +9,32 @@ module Homebrew
def log
if ARGV.named.empty?
- cd HOMEBREW_REPOSITORY
- git_log
+ git_log HOMEBREW_REPOSITORY
else
path = Formulary.path(ARGV.named.first)
- cd path.dirname # supports taps
- git_log path
+ tap = Tap.from_path(path)
+ git_log path.dirname, path, tap
end
end
- def git_log(path = nil)
- if File.exist? "#{`git rev-parse --show-toplevel`.chomp}/.git/shallow"
+ def git_log(cd_dir, path = nil, tap = nil)
+ cd cd_dir
+ repo = Utils.popen_read("git rev-parse --show-toplevel").chomp
+ if tap
+ name = tap.to_s
+ git_cd = "$(brew --repo #{tap})"
+ elsif cd_dir == HOMEBREW_REPOSITORY
+ name = "Homebrew/brew"
+ git_cd = "$(brew --repo)"
+ else
+ name, git_cd = cd_dir
+ end
+
+ if File.exist? "#{repo}/.git/shallow"
opoo <<-EOS.undent
- The git repository is a shallow clone therefore the filtering may be incorrect.
- Use `git fetch --unshallow` to get the full repository.
+ #{name} is a shallow clone so only partial output will be shown.
+ To get a full clone run:
+ git -C "#{git_cd}" fetch --unshallow
EOS
end
args = ARGV.options_only
diff --git a/Library/Homebrew/cmd/outdated.rb b/Library/Homebrew/cmd/outdated.rb
index a18f4e399..e94002989 100644
--- a/Library/Homebrew/cmd/outdated.rb
+++ b/Library/Homebrew/cmd/outdated.rb
@@ -64,7 +64,9 @@ module Homebrew
"#{full_name} (#{kegs.map(&:version).join(", ")})"
end.join(", ")
- puts "#{outdated_versions} < #{current_version}"
+ pinned_version = " [pinned at #{f.pinned_version}]" if f.pinned?
+
+ puts "#{outdated_versions} < #{current_version}#{pinned_version}"
else
puts f.full_installed_specified_name
end
@@ -86,7 +88,9 @@ module Homebrew
json << { name: f.full_name,
installed_versions: outdated_versions.collect(&:to_s),
- current_version: current_version }
+ current_version: current_version,
+ pinned: f.pinned?,
+ pinned_version: f.pinned_version }
end
puts JSON.generate(json)
diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb
index e834a00b5..443739f8c 100644
--- a/Library/Homebrew/cmd/search.rb
+++ b/Library/Homebrew/cmd/search.rb
@@ -14,7 +14,7 @@
#: Search for <text> in the given package manager's list.
require "formula"
-require "blacklist"
+require "missing_formula"
require "utils"
require "thread"
require "official_taps"
@@ -67,13 +67,12 @@ module Homebrew
if $stdout.tty?
count = local_results.length + tap_results.length
- if msg = blacklisted?(query)
+ if reason = Homebrew::MissingFormula.reason(query, silent: true)
if count > 0
puts
- puts "If you meant #{query.inspect} precisely:"
- puts
+ puts "If you meant #{query.inspect} specifically:"
end
- puts msg
+ puts reason
elsif count.zero?
puts "No formula found for #{query.inspect}."
begin
diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb
index c13d82090..4002df75c 100644
--- a/Library/Homebrew/cmd/update-report.rb
+++ b/Library/Homebrew/cmd/update-report.rb
@@ -361,7 +361,10 @@ class Reporter
case status
when "A", "D"
- @report[status.to_sym] << tap.formula_file_to_name(src)
+ full_name = tap.formula_file_to_name(src)
+ name = full_name.split("/").last
+ new_tap = tap.tap_migrations[name]
+ @report[status.to_sym] << full_name unless new_tap
when "M"
begin
formula = Formulary.factory(tap.path/src)
@@ -499,9 +502,15 @@ class Reporter
end
def migrate_formula_rename
- report[:R].each do |old_full_name, new_full_name|
- old_name = old_full_name.split("/").last
- next unless (dir = HOMEBREW_CELLAR/old_name).directory? && !dir.subdirs.empty?
+ Formula.installed.map(&:oldname).compact.each do |old_name|
+ old_name_dir = HOMEBREW_CELLAR/old_name
+ next if old_name_dir.symlink?
+ next unless old_name_dir.directory? && !old_name_dir.subdirs.empty?
+
+ new_name = tap.formula_renames[old_name]
+ next unless new_name
+
+ new_full_name = "#{tap}/#{new_name}"
begin
f = Formulary.factory(new_full_name)
diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb
index 677a52447..1a4bb24a1 100644
--- a/Library/Homebrew/dev-cmd/audit.rb
+++ b/Library/Homebrew/dev-cmd/audit.rb
@@ -38,7 +38,7 @@ require "official_taps"
require "cmd/search"
require "cmd/style"
require "date"
-require "blacklist"
+require "missing_formula"
require "digest"
module Homebrew
@@ -331,25 +331,33 @@ class FormulaAuditor
problem "File should end with a newline" unless text.trailing_newline?
- versioned_formulae = Dir[formula.path.to_s.gsub(/\.rb$/, "@*.rb")]
- needs_versioned_alias = !versioned_formulae.empty? &&
- formula.tap &&
- formula.aliases.grep(/.@\d/).empty?
- if needs_versioned_alias
- _, last_alias_version = File.basename(versioned_formulae.sort.reverse.first)
- .gsub(/\.rb$/, "")
- .split("@")
- major, minor, = formula.version.to_s.split(".")
- alias_name = if last_alias_version.split(".").length == 1
- "#{formula.name}@#{major}"
- else
- "#{formula.name}@#{major}.#{minor}"
+ if formula.versioned_formula?
+ unversioned_formula = Pathname.new formula.path.to_s.gsub(/@.*\.rb$/, ".rb")
+ unless unversioned_formula.exist?
+ unversioned_name = unversioned_formula.basename(".rb")
+ problem "#{formula} is versioned but no #{unversioned_name} formula exists"
+ end
+ else
+ versioned_formulae = Dir[formula.path.to_s.gsub(/\.rb$/, "@*.rb")]
+ needs_versioned_alias = !versioned_formulae.empty? &&
+ formula.tap &&
+ formula.aliases.grep(/.@\d/).empty?
+ if needs_versioned_alias
+ _, last_alias_version = File.basename(versioned_formulae.sort.reverse.first)
+ .gsub(/\.rb$/, "")
+ .split("@")
+ major, minor, = formula.version.to_s.split(".")
+ alias_name = if last_alias_version.split(".").length == 1
+ "#{formula.name}@#{major}"
+ else
+ "#{formula.name}@#{major}.#{minor}"
+ end
+ problem <<-EOS.undent
+ Formula has other versions so create an alias:
+ cd #{formula.tap.alias_dir}
+ ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name}
+ EOS
end
- problem <<-EOS.undent
- Formula has other versions so create an alias:
- cd #{formula.tap.alias_dir}
- ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name}
- EOS
end
return unless @strict
@@ -399,7 +407,7 @@ class FormulaAuditor
name = formula.name
full_name = formula.full_name
- if blacklisted?(name)
+ if Homebrew::MissingFormula.blacklisted_reason(name)
problem "'#{name}' is blacklisted."
end
@@ -472,6 +480,12 @@ class FormulaAuditor
problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'."
end
+ if @new_formula && dep_f.keg_only_reason &&
+ !["openssl", "apr", "apr-util"].include?(dep.name) &&
+ [:provided_by_macos, :provided_by_osx].include?(dep_f.keg_only_reason.reason)
+ problem "Dependency '#{dep.name}' may be unnecessary as it is provided by macOS; try to build this formula without it."
+ end
+
dep.options.reject do |opt|
next true if dep_f.option_defined?(opt)
dep_f.requirements.detect do |r|
@@ -775,7 +789,7 @@ class FormulaAuditor
automysqlbackup 3.0-rc6
aview 1.3.0rc1
distcc 3.2rc1
- elm-format 0.5.2-alpha
+ elm-format 0.6.0-alpha
ftgl 2.1.3-rc5
hidapi 0.8.0-rc1
libcaca 0.99b19
@@ -1036,6 +1050,10 @@ class FormulaAuditor
problem ":apr is deprecated. Usage should be \"apr-util\""
end
+ if line =~ /depends_on :tex/
+ problem ":tex is deprecated."
+ end
+
# Commented-out depends_on
problem "Commented-out dep #{$1}" if line =~ /#\s*depends_on\s+(.+)\s*$/
@@ -1166,7 +1184,8 @@ class FormulaAuditor
problem "Use `assert_match` instead of `assert ...include?`"
end
- if line.include?('system "npm", "install"') && !line.include?("Language::Node") && formula.name !~ /^kibana(\d{2})?$/
+ if line.include?('system "npm", "install"') && !line.include?("Language::Node") &&
+ formula.name !~ /^kibana(\@\d+(\.\d+)?)?$/
problem "Use Language::Node for npm install args"
end
@@ -1174,6 +1193,10 @@ class FormulaAuditor
problem "'fails_with :llvm' is now a no-op so should be removed"
end
+ if line =~ /system\s+['"](otool|install_name_tool|lipo)/ && formula.name != "cctools"
+ problem "Use ruby-macho instead of calling #{$1}"
+ end
+
if formula.tap.to_s == "homebrew/core"
["OS.mac?", "OS.linux?"].each do |check|
next unless line.include?(check)
diff --git a/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb b/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb
deleted file mode 100644
index 7531ef9cf..000000000
--- a/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb
+++ /dev/null
@@ -1,166 +0,0 @@
-#: @hide_from_man_page
-#: * `boneyard-formula-pr` [`--dry-run`] [`--local`] [`--reason=<reason>`] <formula> :
-#: Creates a pull request to boneyard a formula.
-#:
-#: If `--dry-run` is passed, print what would be done rather than doing it.
-#:
-#: If `--local` is passed, perform only local operations (i.e. don't push or create PR).
-#:
-#: If `--reason=<reason>` is passed, append this to the commit/PR message.
-
-require "formula"
-require "json"
-require "fileutils"
-
-begin
- require "json"
-rescue LoadError
- puts "Homebrew does not provide Ruby dependencies; install with:"
- puts " gem install json"
- odie "Dependency json is not installed."
-end
-
-module Homebrew
- module_function
-
- def boneyard_formula_pr
- local_only = ARGV.include?("--local")
- formula = ARGV.formulae.first
- reason = ARGV.value("reason")
- odie "No formula found!" unless formula
-
- formula_relpath = formula.path.relative_path_from(formula.tap.path)
- formula_file = "#{formula.name}.rb"
- bottle_block = File.read(formula.path).include? " bottle do"
- boneyard_tap = Tap.fetch("homebrew", "boneyard")
- tap_migrations_path = formula.tap.path/"tap_migrations.json"
- if ARGV.dry_run?
- ohai "brew update"
- ohai "brew tap #{boneyard_tap.name}"
- ohai "cd #{formula.tap.path}"
- cd formula.tap.path
- ohai "cp #{formula_relpath} #{boneyard_tap.path}"
- ohai "git rm #{formula_relpath}"
- unless File.exist? tap_migrations_path
- ohai "Creating tap_migrations.json for #{formula.tap.name}"
- ohai "git add #{tap_migrations_path}"
- end
- ohai "Loading tap_migrations.json"
- ohai "Adding #{formula.name} to tap_migrations.json"
- else
- safe_system HOMEBREW_BREW_FILE, "update"
- safe_system HOMEBREW_BREW_FILE, "tap", boneyard_tap.name
- cd formula.tap.path
- cp formula_relpath, boneyard_tap.formula_dir
- safe_system "git", "rm", formula_relpath
- unless File.exist? tap_migrations_path
- tap_migrations_path.write <<-EOS.undent
- {
- }
- EOS
- safe_system "git", "add", tap_migrations_path
- end
- tap_migrations = JSON.parse(File.read(tap_migrations_path))
- tap_migrations[formula.name] = boneyard_tap.name
- tap_migrations = tap_migrations.sort.inject({}) { |acc, elem| acc.merge!(elem[0] => elem[1]) }
- tap_migrations_path.atomic_write(JSON.pretty_generate(tap_migrations) + "\n")
- end
- unless which("hub") || local_only
- if ARGV.dry_run?
- ohai "brew install hub"
- else
- safe_system HOMEBREW_BREW_FILE, "install", "hub"
- end
- end
- branch = "#{formula.name}-boneyard"
-
- reason = " because #{reason}" if reason
-
- if ARGV.dry_run?
- ohai "cd #{formula.tap.path}"
- ohai "git checkout --no-track -b #{branch} origin/master"
- ohai "git commit --no-edit --verbose --message=\"#{formula.name}: migrate to boneyard\" -- #{formula_relpath} #{tap_migrations_path.basename}"
-
- unless local_only
- ohai "hub fork --no-remote"
- ohai "hub fork"
- ohai "hub fork (to read $HUB_REMOTE)"
- ohai "git push $HUB_REMOTE #{branch}:#{branch}"
- ohai "hub pull-request -m $'#{formula.name}: migrate to boneyard\\n\\nCreated with `brew boneyard-formula-pr`#{reason}.'"
- end
-
- ohai "git checkout -"
- else
- cd formula.tap.path
- safe_system "git", "checkout", "--no-track", "-b", branch, "origin/master"
- safe_system "git", "commit", "--no-edit", "--verbose",
- "--message=#{formula.name}: migrate to boneyard",
- "--", formula_relpath, tap_migrations_path.basename
-
- unless local_only
- safe_system "hub", "fork", "--no-remote"
- quiet_system "hub", "fork"
- remote = Utils.popen_read("hub fork 2>&1")[/fatal: remote (.+) already exists\./, 1]
- odie "cannot get remote from 'hub'!" unless remote
- safe_system "git", "push", remote, "#{branch}:#{branch}"
- pr_message = <<-EOS.undent
- #{formula.name}: migrate to boneyard
-
- Created with `brew boneyard-formula-pr`#{reason}.
- EOS
- pr_url = Utils.popen_read("hub", "pull-request", "-m", pr_message).chomp
- end
-
- safe_system "git", "checkout", "-"
- end
-
- if ARGV.dry_run?
- ohai "cd #{boneyard_tap.path}"
- ohai "git checkout --no-track -b #{branch} origin/master"
- if bottle_block
- ohai "Removing bottle block"
- else
- ohai "No bottle block to remove"
- end
- ohai "git add #{formula_file}"
- ohai "git commit --no-edit --verbose --message=\"#{formula.name}: migrate from #{formula.tap.repo}\" -- #{formula_file}"
-
- unless local_only
- ohai "hub fork --no-remote"
- ohai "hub fork"
- ohai "hub fork (to read $HUB_REMOTE)"
- ohai "git push $HUB_REMOTE #{branch}:#{branch}"
- ohai "hub pull-request --browse -m $'#{formula.name}: migrate from #{formula.tap.repo}\\n\\nGoes together with $PR_URL\\n\\nCreated with `brew boneyard-formula-pr`#{reason}.'"
- end
-
- ohai "git checkout -"
- else
- cd boneyard_tap.formula_dir
- safe_system "git", "checkout", "--no-track", "-b", branch, "origin/master"
- if bottle_block
- Utils::Inreplace.inreplace formula_file, / bottle do.+?end\n\n/m, ""
- end
- safe_system "git", "add", formula_file
- safe_system "git", "commit", "--no-edit", "--verbose",
- "--message=#{formula.name}: migrate from #{formula.tap.repo}",
- "--", formula_file
-
- unless local_only
- safe_system "hub", "fork", "--no-remote"
- quiet_system "hub", "fork"
- remote = Utils.popen_read("hub fork 2>&1")[/fatal: remote (.+) already exists\./, 1]
- odie "cannot get remote from 'hub'!" unless remote
- safe_system "git", "push", remote, "#{branch}:#{branch}"
- safe_system "hub", "pull-request", "--browse", "-m", <<-EOS.undent
- #{formula.name}: migrate from #{formula.tap.repo}
-
- Goes together with #{pr_url}.
-
- Created with `brew boneyard-formula-pr`#{reason}.
- EOS
- end
-
- safe_system "git", "checkout", "-"
- end
- end
-end
diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb
index 9c58dc71a..6855d6f37 100644
--- a/Library/Homebrew/dev-cmd/create.rb
+++ b/Library/Homebrew/dev-cmd/create.rb
@@ -19,7 +19,7 @@
#: the specified tap.
require "formula"
-require "blacklist"
+require "missing_formula"
require "digest"
require "erb"
@@ -73,8 +73,8 @@ module Homebrew
# Don't allow blacklisted formula, or names that shadow aliases,
# unless --force is specified.
unless ARGV.force?
- if msg = blacklisted?(fc.name)
- raise "#{fc.name} is blacklisted for creation.\n#{msg}\nIf you really want to create this formula use --force."
+ if reason = Homebrew::MissingFormula.blacklisted_reason(fc.name)
+ raise "#{fc.name} is blacklisted for creation.\n#{reason}\nIf you really want to create this formula use --force."
end
if Formula.aliases.include? fc.name
diff --git a/Library/Homebrew/dev-cmd/man.rb b/Library/Homebrew/dev-cmd/man.rb
index 581db38ca..a146f23a8 100644
--- a/Library/Homebrew/dev-cmd/man.rb
+++ b/Library/Homebrew/dev-cmd/man.rb
@@ -27,7 +27,7 @@ module Homebrew
regenerate_man_pages
- if system "git", "-C", HOMEBREW_REPOSITORY, "diff", "--quiet", "docs/brew.1.html", "manpages"
+ if system "git", "-C", HOMEBREW_REPOSITORY, "diff", "--quiet", "docs/Manpage.md", "manpages"
puts "No changes to manpage output detected."
elsif ARGV.include?("--fail-if-changed")
Homebrew.failed = true
@@ -38,7 +38,7 @@ module Homebrew
Homebrew.install_gem_setup_path! "ronn"
markup = build_man_page
- convert_man_page(markup, TARGET_DOC_PATH/"brew.1.html")
+ convert_man_page(markup, TARGET_DOC_PATH/"Manpage.md")
convert_man_page(markup, TARGET_MAN_PATH/"brew.1")
cask_markup = (SOURCE_PATH/"brew-cask.1.md").read
@@ -53,8 +53,7 @@ module Homebrew
.grep(/^#:/)
.map { |line| line.slice(2..-1) }
.join
- end
- .reject { |s| s.strip.empty? || s.include?("@hide_from_man_page") }
+ end.reject { |s| s.strip.empty? || s.include?("@hide_from_man_page") }
end
def build_man_page
@@ -113,7 +112,7 @@ module Homebrew
def target_path_to_format(target)
case target.basename
- when /\.html?$/ then ["--fragment", "HTML fragment"]
+ when /\.md$/ then ["--markdown", "markdown"]
when /\.\d$/ then ["--roff", "man page"]
else
odie "Failed to infer output format from '#{target.basename}'."
diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb
index ec89b14b8..36c9ac27c 100644
--- a/Library/Homebrew/dev-cmd/pull.rb
+++ b/Library/Homebrew/dev-cmd/pull.rb
@@ -1,4 +1,5 @@
-#: * `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] <patch-source> [<patch-source>]:
+#: * `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] [`--warn-on-publish-failure`] <patch-source> [<patch-source>]:
+#:
#: Gets a patch from a GitHub commit or pull request and applies it to Homebrew.
#: Optionally, installs the formulae changed by the patch.
#:
@@ -37,6 +38,9 @@
#: clipboard.
#:
#: If `--no-publish` is passed, do not publish bottles to Bintray.
+#:
+#: If `--warn-on-publish-failure` was passed, do not exit if there's a
+#: failure publishing bottles on Bintray.
require "net/http"
require "net/https"
@@ -264,7 +268,7 @@ module Homebrew
changed_formulae_names.each do |name|
f = Formula[name]
next if f.bottle_unneeded? || f.bottle_disabled?
- publish_bottle_file_on_bintray(f, bintray_creds)
+ next unless publish_bottle_file_on_bintray(f, bintray_creds)
published << f.full_name
end
else
@@ -425,7 +429,7 @@ module Homebrew
end
unless info.bottle_info_any
opoo "No bottle defined in formula #{package}"
- return
+ return false
end
version = info.pkg_version
ohai "Publishing on Bintray: #{package} #{version}"
@@ -434,6 +438,11 @@ module Homebrew
"-H", "Content-Type: application/json",
"-d", '{"publish_wait_for_secs": 0}',
"https://api.bintray.com/content/homebrew/#{repo}/#{package}/#{version}/publish"
+ true
+ rescue => e
+ raise unless ARGV.include?("--warn-on-publish-failure")
+ onoe e
+ false
end
# Formula info drawn from an external "brew info --json" call
diff --git a/Library/Homebrew/dev-cmd/tap-new.rb b/Library/Homebrew/dev-cmd/tap-new.rb
index 6e1977446..df295bf26 100644
--- a/Library/Homebrew/dev-cmd/tap-new.rb
+++ b/Library/Homebrew/dev-cmd/tap-new.rb
@@ -60,6 +60,7 @@ module Homebrew
- git -C "$HOMEBREW_REPOSITORY" reset --hard origin/master
- brew update || brew update
- HOMEBREW_TAP_DIR="$(brew --repo "$TRAVIS_REPO_SLUG")"
+ - mkdir -p "$HOMEBREW_TAP_DIR"
- rm -rf "$HOMEBREW_TAP_DIR"
- ln -s "$PWD" "$HOMEBREW_TAP_DIR"
- export HOMEBREW_DEVELOPER="1"
diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb
index 4f7f9e771..18e7d96f2 100644
--- a/Library/Homebrew/dev-cmd/tests.rb
+++ b/Library/Homebrew/dev-cmd/tests.rb
@@ -28,6 +28,7 @@ module Homebrew
ENV.delete("HOMEBREW_VERBOSE")
ENV.delete("VERBOSE")
ENV.delete("HOMEBREW_CASK_OPTS")
+ ENV.delete("HOMEBREW_TEMP")
ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1"
ENV["HOMEBREW_DEVELOPER"] = "1"
ENV["HOMEBREW_NO_COMPAT"] = "1" if ARGV.include? "--no-compat"
diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb
index 2ff168669..add05bc7c 100644
--- a/Library/Homebrew/dev-cmd/update-test.rb
+++ b/Library/Homebrew/dev-cmd/update-test.rb
@@ -33,12 +33,24 @@ module Homebrew
elsif date = ARGV.value("before")
Utils.popen_read("git", "rev-list", "-n1", "--before=#{date}", "origin/master").chomp
elsif ARGV.include?("--to-tag")
- Utils.popen_read("git", "tag", "--list", "--sort=-version:refname").lines[1].chomp
+ previous_tag =
+ Utils.popen_read("git", "tag", "--list", "--sort=-version:refname").lines[1]
+ unless previous_tag
+ safe_system "git", "fetch", "--tags", "--depth=1"
+ previous_tag =
+ Utils.popen_read("git", "tag", "--list", "--sort=-version:refname").lines[1]
+ end
+ previous_tag.to_s.chomp
else
Utils.popen_read("git", "rev-parse", "origin/master").chomp
end
+ odie "Could not find start commit!" if start_commit.empty?
+
start_commit = Utils.popen_read("git", "rev-parse", start_commit).chomp
+ odie "Could not find start commit!" if start_commit.empty?
+
end_commit = Utils.popen_read("git", "rev-parse", "HEAD").chomp
+ odie "Could not find end commit!" if end_commit.empty?
puts "Start commit: #{start_commit}"
puts "End commit: #{end_commit}"
diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb
index c8c4b83d2..61cdf2f1a 100644
--- a/Library/Homebrew/diagnostic.rb
+++ b/Library/Homebrew/diagnostic.rb
@@ -753,13 +753,14 @@ module Homebrew
def check_git_version
# https://help.github.com/articles/https-cloning-errors
return unless Utils.git_available?
- return unless Version.create(Utils.git_version) < Version.create("1.7.10")
+ return unless Version.create(Utils.git_version) < Version.create("1.8.5")
git = Formula["git"]
git_upgrade_cmd = git.any_version_installed? ? "upgrade" : "install"
<<-EOS.undent
An outdated version (#{Utils.git_version}) of Git was detected in your PATH.
- Git 1.7.10 or newer is required to perform checkouts over HTTPS from GitHub.
+ Git 1.8.5 or newer is required to perform checkouts over HTTPS from GitHub and
+ to support the 'git -C <path>' option.
Please upgrade:
brew #{git_upgrade_cmd} git
EOS
@@ -794,31 +795,59 @@ module Homebrew
EOS
end
- def check_git_origin
+ def check_brew_git_origin
return if !Utils.git_available? || !(HOMEBREW_REPOSITORY/".git").exist?
origin = HOMEBREW_REPOSITORY.git_origin
if origin.nil?
<<-EOS.undent
- Missing git origin remote.
+ Missing Homebrew/brew git origin remote.
Without a correctly configured origin, Homebrew won't update
properly. You can solve this by adding the Homebrew remote:
- cd #{HOMEBREW_REPOSITORY}
- git remote add origin #{Formatter.url("https://github.com/Homebrew/brew.git")}
+ git -C "#{HOMEBREW_REPOSITORY}" remote add origin #{Formatter.url("https://github.com/Homebrew/brew.git")}
EOS
- elsif origin !~ %r{Homebrew/brew(\.git)?$}
+ elsif origin !~ %r{Homebrew/brew(\.git|/)?$}
<<-EOS.undent
- Suspicious git origin remote found.
+ Suspicious Homebrew/brew git origin remote found.
With a non-standard origin, Homebrew won't pull updates from
the main repository. The current git origin is:
#{origin}
Unless you have compelling reasons, consider setting the
- origin remote to point at the main repository, located at:
- #{Formatter.url("https://github.com/Homebrew/brew.git")}
+ origin remote to point at the main repository by running:
+ git -C "#{HOMEBREW_REPOSITORY}" remote add origin #{Formatter.url("https://github.com/Homebrew/brew.git")}
+ EOS
+ end
+ end
+
+ def check_coretap_git_origin
+ coretap_path = CoreTap.instance.path
+ return if !Utils.git_available? || !(coretap_path/".git").exist?
+
+ origin = coretap_path.git_origin
+
+ if origin.nil?
+ <<-EOS.undent
+ Missing #{CoreTap.instance} git origin remote.
+
+ Without a correctly configured origin, Homebrew won't update
+ properly. You can solve this by adding the Homebrew remote:
+ git -C "#{coretap_path}" remote add origin #{Formatter.url("https://github.com/Homebrew/homebrew-core.git")}
+ EOS
+ elsif origin !~ %r{Homebrew/homebrew-core(\.git|/)?$}
+ <<-EOS.undent
+ Suspicious #{CoreTap.instance} git origin remote found.
+
+ With a non-standard origin, Homebrew won't pull updates from
+ the main repository. The current git origin is:
+ #{origin}
+
+ Unless you have compelling reasons, consider setting the
+ origin remote to point at the main repository by running:
+ git -C "#{coretap_path}" remote add origin #{Formatter.url("https://github.com/Homebrew/homebrew-core.git")}
EOS
end
end
diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb
index 77da4489e..cfdf5e12d 100644
--- a/Library/Homebrew/exceptions.rb
+++ b/Library/Homebrew/exceptions.rb
@@ -363,14 +363,6 @@ class BuildError < RuntimeError
end
end
- if formula.tap && formula.tap.name == "homebrew/boneyard"
- onoe <<-EOS.undent
- #{formula} was moved to homebrew-boneyard because it has unfixable issues.
- Please do not file any issues about this. Sorry!
- EOS
- return
- end
-
if formula.tap && defined?(OS::ISSUES_URL)
if formula.tap.official?
puts Formatter.error(Formatter.url(OS::ISSUES_URL), label: "READ THIS")
diff --git a/Library/Homebrew/extend/os/blacklist.rb b/Library/Homebrew/extend/os/blacklist.rb
deleted file mode 100644
index 932040f82..000000000
--- a/Library/Homebrew/extend/os/blacklist.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require "blacklist"
-require "extend/os/mac/blacklist" if OS.mac?
diff --git a/Library/Homebrew/extend/os/mac/blacklist.rb b/Library/Homebrew/extend/os/mac/blacklist.rb
deleted file mode 100644
index edff4697e..000000000
--- a/Library/Homebrew/extend/os/mac/blacklist.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-def blacklisted?(name)
- case name.downcase
- when "xcode"
- if MacOS.version >= :lion
- <<-EOS.undent
- Xcode can be installed from the App Store.
- EOS
- else
- <<-EOS.undent
- Xcode can be installed from https://developer.apple.com/xcode/downloads/
- EOS
- end
- else
- generic_blacklisted?(name)
- end
-end
diff --git a/Library/Homebrew/extend/os/mac/missing_formula.rb b/Library/Homebrew/extend/os/mac/missing_formula.rb
new file mode 100644
index 000000000..48dfd2865
--- /dev/null
+++ b/Library/Homebrew/extend/os/mac/missing_formula.rb
@@ -0,0 +1,22 @@
+module Homebrew
+ module MissingFormula
+ class << self
+ def blacklisted_reason(name)
+ case name.downcase
+ when "xcode"
+ if MacOS.version >= :lion
+ <<-EOS.undent
+ Xcode can be installed from the App Store.
+ EOS
+ else
+ <<-EOS.undent
+ Xcode can be installed from #{Formatter.url("https://developer.apple.com/xcode/downloads/")}.
+ EOS
+ end
+ else
+ generic_blacklisted_reason(name)
+ end
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/extend/os/missing_formula.rb b/Library/Homebrew/extend/os/missing_formula.rb
new file mode 100644
index 000000000..02c59f4e4
--- /dev/null
+++ b/Library/Homebrew/extend/os/missing_formula.rb
@@ -0,0 +1,2 @@
+require "missing_formula"
+require "extend/os/mac/missing_formula" if OS.mac?
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index 443619206..523de244d 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -252,12 +252,14 @@ class Formula
public
- # The alias path that was used to install this formula, if present.
+ # The alias path that was used to install this formula, if it exists.
# Can differ from alias_path, which is the alias used to find the formula,
# and is specified to this instance.
def installed_alias_path
path = build.source["path"] if build.is_a?(Tab)
- path if path =~ %r{#{HOMEBREW_TAP_DIR_REGEX}/Aliases}
+ return unless path =~ %r{#{HOMEBREW_TAP_DIR_REGEX}/Aliases}
+ return unless File.symlink?(path)
+ path
end
def installed_alias_name
@@ -1555,6 +1557,8 @@ class Formula
hide.include?(d.name) || d.installed_prefixes.empty?
end
missing_dependencies
+ rescue FormulaUnavailableError
+ []
end
# @private
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index 1f91ad5c4..017be51dc 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -410,10 +410,13 @@ class FormulaInstaller
end
def install_requirement_formula?(req, dependent, build)
- return false unless req.to_dependency
+ req_dependency = req.to_dependency
+ return false unless req_dependency
return true unless req.satisfied?
return false if req.run?
- install_bottle_for?(dependent, build) || build_bottle?
+ return true if build_bottle?
+ return true if req.satisfied_by_formula?
+ install_bottle_for?(dependent, build)
end
def expand_requirements
diff --git a/Library/Homebrew/formula_support.rb b/Library/Homebrew/formula_support.rb
index dcb995a6b..b8476f5cc 100644
--- a/Library/Homebrew/formula_support.rb
+++ b/Library/Homebrew/formula_support.rb
@@ -4,6 +4,8 @@ FormulaConflict = Struct.new(:name, :reason)
# Used to annotate formulae that duplicate macOS provided software
# or cause conflicts when linked in.
class KegOnlyReason
+ attr_reader :reason
+
def initialize(reason, explanation)
@reason = reason
@explanation = explanation
diff --git a/Library/Homebrew/gpg.rb b/Library/Homebrew/gpg.rb
index 066f67864..777542055 100644
--- a/Library/Homebrew/gpg.rb
+++ b/Library/Homebrew/gpg.rb
@@ -5,7 +5,9 @@ class Gpg
which_all(executable).detect do |gpg|
gpg_short_version = Utils.popen_read(gpg, "--version")[/\d\.\d/, 0]
next unless gpg_short_version
- Version.create(gpg_short_version.to_s) == Version.create("2.0")
+ gpg_version = Version.create(gpg_short_version.to_s)
+ gpg_version == Version.create("2.0") ||
+ gpg_version == Version.create("2.1")
end
end
diff --git a/Library/Homebrew/migrator.rb b/Library/Homebrew/migrator.rb
index a80cf0c59..a58ca2059 100644
--- a/Library/Homebrew/migrator.rb
+++ b/Library/Homebrew/migrator.rb
@@ -122,6 +122,13 @@ class Migrator
end
def from_same_taps?
+ new_tap = if old_tap
+ if migrate_tap = old_tap.tap_migrations[formula.oldname]
+ new_tap_user, new_tap_repo, = migrate_tap.split("/")
+ "#{new_tap_user}/#{new_tap_repo}"
+ end
+ end
+
if formula.tap == old_tap
true
# Homebrew didn't use to update tabs while performing tap-migrations,
@@ -129,7 +136,7 @@ class Migrator
# so we check if there is an entry about oldname migrated to tap and if
# newname's tap is the same as tap to which oldname migrated, then we
# can perform migrations and the taps for oldname and newname are the same.
- elsif formula.tap && old_tap && formula.tap == old_tap.tap_migrations[formula.oldname]
+ elsif formula.tap && old_tap && formula.tap == new_tap
fix_tabs
true
else
@@ -147,15 +154,25 @@ class Migrator
end
def migrate
- if new_cellar.exist?
- onoe "#{new_cellar} already exists; remove it manually and run brew migrate #{oldname}."
- return
+ if old_cellar.exist? && new_cellar.exist?
+ conflicted = false
+ old_cellar.each_child do |c|
+ if (new_cellar/c.basename).exist?
+ conflicted = true
+ onoe "#{new_cellar/c.basename} already exists."
+ end
+ end
+ if conflicted
+ onoe "Remove #{new_cellar} manually and run brew migrate #{oldname}."
+ return
+ end
end
begin
oh1 "Migrating #{Formatter.identifier(oldname)} to #{Formatter.identifier(newname)}"
lock
unlink_oldname
+ unlink_newname if new_cellar.exist?
move_to_new_directory
repin
link_oldname_cellar
@@ -178,7 +195,11 @@ class Migrator
# move everything from Cellar/oldname to Cellar/newname
def move_to_new_directory
puts "Moving to: #{new_cellar}"
- FileUtils.mv(old_cellar, new_cellar)
+ if new_cellar.exist?
+ FileUtils.mv(old_cellar.children, new_cellar)
+ else
+ FileUtils.mv(old_cellar, new_cellar)
+ end
end
def repin
@@ -207,6 +228,14 @@ class Migrator
end
end
+ def unlink_newname
+ oh1 "Unlinking #{Formatter.identifier(newname)}"
+ new_cellar.subdirs.each do |d|
+ keg = Keg.new(d)
+ keg.unlink
+ end
+ end
+
def link_newname
oh1 "Linking #{Formatter.identifier(newname)}"
new_keg = Keg.new(new_linked_keg_record)
diff --git a/Library/Homebrew/missing_formula.rb b/Library/Homebrew/missing_formula.rb
new file mode 100644
index 000000000..1b584af8a
--- /dev/null
+++ b/Library/Homebrew/missing_formula.rb
@@ -0,0 +1,168 @@
+require "formulary"
+require "tap"
+require "utils"
+
+module Homebrew
+ module MissingFormula
+ class << self
+ def reason(name, silent: false)
+ blacklisted_reason(name) || tap_migration_reason(name) ||
+ deleted_reason(name, silent: silent)
+ end
+
+ def blacklisted_reason(name)
+ case name.downcase
+ when "gem", /^rubygems?$/ then <<-EOS.undent
+ Homebrew provides gem via: `brew install ruby`.
+ EOS
+ when "tex", "tex-live", "texlive", "latex" then <<-EOS.undent
+ Installing TeX from source is weird and gross, requires a lot of patches,
+ and only builds 32-bit (and thus can't use Homebrew dependencies)
+
+ We recommend using a MacTeX distribution: https://www.tug.org/mactex/
+
+ You can install it with Homebrew-Cask:
+ brew cask install mactex
+ EOS
+ when "pip" then <<-EOS.undent
+ Homebrew provides pip via: `brew install python`. However you will then
+ have two Pythons installed on your Mac, so alternatively you can install
+ pip via the instructions at:
+ #{Formatter.url("https://pip.readthedocs.io/en/stable/installing/")}
+ EOS
+ when "pil" then <<-EOS.undent
+ Instead of PIL, consider `pip install pillow` or `brew install Homebrew/python/pillow`.
+ EOS
+ when "macruby" then <<-EOS.undent
+ MacRuby is not packaged and is on an indefinite development hiatus.
+ You can read more about it at:
+ #{Formatter.url("https://github.com/MacRuby/MacRuby")}
+ EOS
+ when /(lib)?lzma/
+ "lzma is now part of the xz formula."
+ when "gtest", "googletest", "google-test" then <<-EOS.undent
+ Installing gtest system-wide is not recommended; it should be vendored
+ in your projects that use it.
+ EOS
+ when "gmock", "googlemock", "google-mock" then <<-EOS.undent
+ Installing gmock system-wide is not recommended; it should be vendored
+ in your projects that use it.
+ EOS
+ when "sshpass" then <<-EOS.undent
+ We won't add sshpass because it makes it too easy for novice SSH users to
+ ruin SSH's security.
+ EOS
+ when "gsutil" then <<-EOS.undent
+ Install gsutil with `pip install gsutil`
+ EOS
+ when "clojure" then <<-EOS.undent
+ Clojure isn't really a program but a library managed as part of a
+ project and Leiningen is the user interface to that library.
+
+ To install Clojure you should install Leiningen:
+ brew install leiningen
+ and then follow the tutorial:
+ #{Formatter.url("https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md")}
+ EOS
+ when "osmium" then <<-EOS.undent
+ The creator of Osmium requests that it not be packaged and that people
+ use the GitHub master branch instead.
+ EOS
+ when "gfortran" then <<-EOS.undent
+ GNU Fortran is now provided as part of GCC, and can be installed with:
+ brew install gcc
+ EOS
+ when "play" then <<-EOS.undent
+ Play 2.3 replaces the play command with activator:
+ brew install typesafe-activator
+
+ You can read more about this change at:
+ #{Formatter.url("https://www.playframework.com/documentation/2.3.x/Migration23")}
+ #{Formatter.url("https://www.playframework.com/documentation/2.3.x/Highlights23")}
+ EOS
+ when "haskell-platform" then <<-EOS.undent
+ We no longer package haskell-platform. Consider installing ghc
+ and cabal-install instead:
+ brew install ghc cabal-install
+
+ You can install with Homebrew-Cask:
+ brew cask install haskell-platform
+ EOS
+ when "mysqldump-secure" then <<-EOS.undent
+ The creator of mysqldump-secure tried to game our popularity metrics.
+ EOS
+ when "ngrok" then <<-EOS.undent
+ Upstream sunsetted 1.x in March 2016 and 2.x is not open-source.
+
+ If you wish to use the 2.x release you can install with Homebrew-Cask:
+ brew cask install ngrok
+ EOS
+ end
+ end
+ alias generic_blacklisted_reason blacklisted_reason
+
+ def tap_migration_reason(name)
+ message = nil
+
+ Tap.each do |old_tap|
+ new_tap = old_tap.tap_migrations[name]
+ next unless new_tap
+
+ new_tap_user, new_tap_repo, = new_tap.split("/")
+ new_tap_name = "#{new_tap_user}/#{new_tap_repo}"
+
+ message = <<-EOS.undent
+ It was migrated from #{old_tap} to #{new_tap}.
+ You can access it again by running:
+ brew tap #{new_tap_name}
+ EOS
+ break
+ end
+
+ message
+ end
+
+ def deleted_reason(name, silent: false)
+ path = Formulary.path name
+ return if File.exist? path
+ tap = Tap.from_path(path)
+ return unless File.exist? tap.path
+ relative_path = path.relative_path_from tap.path
+
+ tap.path.cd do
+ ohai "Searching for a previously deleted formula..." unless silent
+
+ # We know this may return incomplete results for shallow clones but
+ # we don't want to nag everyone with a shallow clone to unshallow it.
+ log_command = "git log --name-only --max-count=1 --format=%H\\\\n%h\\\\n%B -- #{relative_path}"
+ hash, short_hash, *commit_message, relative_path =
+ Utils.popen_read(log_command).gsub("\\n", "\n").lines.map(&:chomp)
+
+ if hash.to_s.empty? || short_hash.to_s.empty? ||
+ relative_path.to_s.empty?
+ ofail "No previously deleted formula found." unless silent
+ return
+ end
+
+ commit_message = commit_message.reject(&:empty?).join("\n ")
+
+ commit_message.sub!(/ \(#(\d+)\)$/, " (#{tap.issues_url}/\\1)")
+ commit_message.gsub!(/(Closes|Fixes) #(\d+)/, "\\1 #{tap.issues_url}/\\2")
+
+ <<-EOS.undent
+ #{name} was deleted from #{tap.name} in commit #{short_hash}:
+ #{commit_message}
+
+ To show the formula before removal run:
+ git -C "$(brew --repo #{tap})" show #{short_hash}^:#{relative_path}
+
+ If you still use this formula consider creating your own tap:
+ http://docs.brew.sh/How-to-Create-and-Maintain-a-Tap.html
+ EOS
+ end
+ end
+
+ require "extend/os/missing_formula"
+ end
+ end
+end
diff --git a/Library/Homebrew/official_taps.rb b/Library/Homebrew/official_taps.rb
index c7b96ae64..a7bc4a1d6 100644
--- a/Library/Homebrew/official_taps.rb
+++ b/Library/Homebrew/official_taps.rb
@@ -1,11 +1,8 @@
OFFICIAL_TAPS = %w[
apache
- dupes
- fuse
nginx
php
science
- tex
].freeze
OFFICIAL_CMD_TAPS = {
diff --git a/Library/Homebrew/requirement.rb b/Library/Homebrew/requirement.rb
index 49108ca75..bd8cf20c8 100644
--- a/Library/Homebrew/requirement.rb
+++ b/Library/Homebrew/requirement.rb
@@ -125,6 +125,10 @@ class Requirement
@formula || self.class.default_formula
end
+ def satisfied_by_formula?
+ !@formula.nil?
+ end
+
def to_dependency
if formula =~ HOMEBREW_TAP_FORMULA_REGEX
TapDependency.new(formula, tags, method(:modify_build_environment), name)
diff --git a/Library/Homebrew/requirements/gpg2_requirement.rb b/Library/Homebrew/requirements/gpg2_requirement.rb
index 00bf4183a..97fabcca0 100644
--- a/Library/Homebrew/requirements/gpg2_requirement.rb
+++ b/Library/Homebrew/requirements/gpg2_requirement.rb
@@ -3,10 +3,10 @@ require "gpg"
class GPG2Requirement < Requirement
fatal true
- default_formula "gnupg2"
+ default_formula "gnupg"
# MacGPG2/GPGTools installs GnuPG 2.0.x as a vanilla `gpg` symlink
# pointing to `gpg2`, as do we. Ensure we're actually using a 2.0 `gpg`.
- # Temporarily, only support 2.0.x rather than the 2.1.x "modern" series.
+ # Support both the 2.0.x "stable" and 2.1.x "modern" series.
satisfy(build_env: false) { Gpg.gpg2 || Gpg.gpg }
end
diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb
index ba55e3cf6..99138330b 100644
--- a/Library/Homebrew/tap.rb
+++ b/Library/Homebrew/tap.rb
@@ -41,6 +41,15 @@ class Tap
CACHE.fetch(cache_key) { |key| CACHE[key] = Tap.new(user, repo) }
end
+ def self.from_path(path)
+ path.to_s =~ HOMEBREW_TAP_PATH_REGEX
+ raise "Invalid tap path '#{path}'" unless $1
+ fetch($1, $2)
+ rescue
+ # No need to error as a nil tap is sufficient to show failure.
+ nil
+ end
+
extend Enumerable
# The user name of this {Tap}. Usually, it's the Github username of
diff --git a/Library/Homebrew/test/blacklist_spec.rb b/Library/Homebrew/test/blacklist_spec.rb
deleted file mode 100644
index 01882167d..000000000
--- a/Library/Homebrew/test/blacklist_spec.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-require "blacklist"
-
-describe "Blacklist" do
- matcher(:be_blacklisted) { match(&method(:blacklisted?)) }
-
- context "rubygems" do
- %w[gem rubygem rubygems].each do |s|
- subject { s }
-
- it { is_expected.to be_blacklisted }
- end
- end
-
- context "latex" do
- %w[latex tex tex-live texlive TexLive].each do |s|
- subject { s }
-
- it { is_expected.to be_blacklisted }
- end
- end
-
- context "pip" do
- subject { "pip" }
-
- it { is_expected.to be_blacklisted }
- end
-
- context "pil" do
- subject { "pil" }
-
- it { is_expected.to be_blacklisted }
- end
-
- context "macruby" do
- subject { "MacRuby" }
-
- it { is_expected.to be_blacklisted }
- end
-
- context "lzma" do
- %w[lzma liblzma].each do |s|
- subject { s }
-
- it { is_expected.to be_blacklisted }
- end
- end
-
- context "gtest" do
- %w[gtest googletest google-test].each do |s|
- subject { s }
-
- it { is_expected.to be_blacklisted }
- end
- end
-
- context "gmock" do
- %w[gmock googlemock google-mock].each do |s|
- subject { s }
-
- it { is_expected.to be_blacklisted }
- end
- end
-
- context "sshpass" do
- subject { "sshpass" }
-
- it { is_expected.to be_blacklisted }
- end
-
- context "gsutil" do
- subject { "gsutil" }
-
- it { is_expected.to be_blacklisted }
- end
-
- context "clojure" do
- subject { "clojure" }
-
- it { is_expected.to be_blacklisted }
- end
-
- context "osmium" do
- %w[osmium Osmium].each do |s|
- subject { s }
-
- it { is_expected.to be_blacklisted }
- end
- end
-
- context "gfortran" do
- subject { "gfortran" }
-
- it { is_expected.to be_blacklisted }
- end
-
- context "play" do
- subject { "play" }
-
- it { is_expected.to be_blacklisted }
- end
-
- context "haskell-platform" do
- subject { "haskell-platform" }
-
- it { is_expected.to be_blacklisted }
- end
-
- context "xcode", :needs_macos do
- %w[xcode Xcode].each do |s|
- subject { s }
-
- it { is_expected.to be_blacklisted }
- end
- end
-end
diff --git a/Library/Homebrew/test/cmd/log_spec.rb b/Library/Homebrew/test/cmd/log_spec.rb
index bdbca8912..b9e3e8d3e 100644
--- a/Library/Homebrew/test/cmd/log_spec.rb
+++ b/Library/Homebrew/test/cmd/log_spec.rb
@@ -33,7 +33,7 @@ describe "brew log", :integration_test do
expect { brew "log", "#{shallow_tap}/testball" }
.to output(/This is a test commit for Testball/).to_stdout
- .and output(/Warning: The git repository is a shallow clone/).to_stderr
+ .and output(%r{Warning: homebrew/shallow is a shallow clone}).to_stderr
.and be_a_success
expect(shallow_tap.path/".git/shallow").to exist, "A shallow clone should have been created."
diff --git a/Library/Homebrew/test/cmd/outdated_spec.rb b/Library/Homebrew/test/cmd/outdated_spec.rb
index 2ce0825e8..65cce27c3 100644
--- a/Library/Homebrew/test/cmd/outdated_spec.rb
+++ b/Library/Homebrew/test/cmd/outdated_spec.rb
@@ -1,11 +1,87 @@
describe "brew outdated", :integration_test do
- it "prints outdated Formulae" do
- setup_test_formula "testball"
- (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
-
- expect { brew "outdated" }
- .to output("testball\n").to_stdout
- .and not_to_output.to_stderr
- .and be_a_success
+ context "quiet output" do
+ it "prints outdated Formulae" do
+ setup_test_formula "testball"
+ (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
+
+ expect { brew "outdated" }
+ .to output("testball\n").to_stdout
+ .and not_to_output.to_stderr
+ .and be_a_success
+ end
+ end
+
+ context "verbose output" do
+ it "prints out the installed and newer versions" do
+ setup_test_formula "testball"
+ (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
+
+ expect { brew "outdated", "--verbose" }
+ .to output("testball (0.0.1) < 0.1\n").to_stdout
+ .and not_to_output.to_stderr
+ .and be_a_success
+ end
+ end
+
+ context "pinned formula, verbose output" do
+ it "prints out the pinned version" do
+ setup_test_formula "testball"
+ (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
+
+ shutup do
+ expect { brew "pin", "testball" }.to be_a_success
+ end
+
+ expect { brew "outdated", "--verbose" }
+ .to output("testball (0.0.1) < 0.1 [pinned at 0.0.1]\n").to_stdout
+ .and not_to_output.to_stderr
+ .and be_a_success
+ end
+ end
+
+ context "json output" do
+ it "includes pinned version in the json output" do
+ setup_test_formula "testball"
+ (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
+
+ shutup do
+ expect { brew "pin", "testball" }.to be_a_success
+ end
+
+ expected_json = [
+ {
+ name: "testball",
+ installed_versions: ["0.0.1"],
+ current_version: "0.1",
+ pinned: true,
+ pinned_version: "0.0.1",
+ },
+ ].to_json
+
+ expect { brew "outdated", "--json=v1" }
+ .to output(expected_json + "\n").to_stdout
+ .and not_to_output.to_stderr
+ .and be_a_success
+ end
+
+ it "has no pinned version when the formula isn't pinned" do
+ setup_test_formula "testball"
+ (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
+
+ expected_json = [
+ {
+ name: "testball",
+ installed_versions: ["0.0.1"],
+ current_version: "0.1",
+ pinned: false,
+ pinned_version: nil,
+ },
+ ].to_json
+
+ expect { brew "outdated", "--json=v1" }
+ .to output(expected_json + "\n").to_stdout
+ .and not_to_output.to_stderr
+ .and be_a_success
+ end
end
end
diff --git a/Library/Homebrew/test/formula_installer_spec.rb b/Library/Homebrew/test/formula_installer_spec.rb
index 600b4560f..efe2bf5a2 100644
--- a/Library/Homebrew/test/formula_installer_spec.rb
+++ b/Library/Homebrew/test/formula_installer_spec.rb
@@ -134,4 +134,50 @@ describe FormulaInstaller do
fi.check_install_sanity
}.to raise_error(CannotInstallFormulaError)
end
+
+ describe "#install_requirement_formula?" do
+ before do
+ @requirement = Python3Requirement.new
+ allow(@requirement).to receive(:satisfied?).and_return(satisfied?)
+ allow(@requirement).to receive(:satisfied_by_formula?).and_return(satisfied_by_formula?)
+ allow_any_instance_of(Dependency).to receive(:installed?).and_return(installed?)
+ @dependent = formula do
+ url "foo"
+ version "0.1"
+ depends_on :python3
+ end
+ @build = BuildOptions.new [], []
+ @fi = FormulaInstaller.new(@dependent)
+ end
+
+ subject { @fi.install_requirement_formula?(@requirement, @dependent, @build) }
+
+ context "it returns false when requirement is satisfied" do
+ let(:satisfied?) { true }
+ let(:satisfied_by_formula?) { false }
+ let(:installed?) { false }
+ it { is_expected.to be false }
+ end
+
+ context "it returns false when requirement is satisfied but default formula is installed" do
+ let(:satisfied?) { true }
+ let(:satisfied_by_formula?) { false }
+ let(:installed?) { true }
+ it { is_expected.to be false }
+ end
+
+ context "it returns true when requirement isn't satisfied" do
+ let(:satisfied?) { false }
+ let(:satisfied_by_formula?) { false }
+ let(:installed?) { false }
+ it { is_expected.to be true }
+ end
+
+ context "it returns true when requirement is satisfied by a formula" do
+ let(:satisfied?) { true }
+ let(:satisfied_by_formula?) { true }
+ let(:installed?) { false }
+ it { is_expected.to be true }
+ end
+ end
end
diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb
index 1e064912f..2309c36fb 100644
--- a/Library/Homebrew/test/formula_spec.rb
+++ b/Library/Homebrew/test/formula_spec.rb
@@ -129,6 +129,8 @@ describe Formula do
alias_name = "bar"
alias_path = "#{CoreTap.instance.alias_dir}/#{alias_name}"
+ CoreTap.instance.alias_dir.mkpath
+ FileUtils.ln_sf f.path, alias_path
f.build = Tab.new(source: { "path" => alias_path })
@@ -160,6 +162,8 @@ describe Formula do
alias_name = "bar"
full_alias_name = "#{tap.user}/#{tap.repo}/#{alias_name}"
alias_path = "#{tap.alias_dir}/#{alias_name}"
+ tap.alias_dir.mkpath
+ FileUtils.ln_sf f.path, alias_path
f.build = Tab.new(source: { "path" => alias_path })
@@ -168,6 +172,8 @@ describe Formula do
expect(f.full_installed_alias_name).to eq(full_alias_name)
expect(f.installed_specified_name).to eq(alias_name)
expect(f.full_installed_specified_name).to eq(full_alias_name)
+
+ FileUtils.rm_rf HOMEBREW_LIBRARY/"Taps/user"
end
specify "#prefix" do
@@ -402,6 +408,8 @@ describe Formula do
url "foo-1.0"
end
f.build = Tab.new(source: { "path" => source_path.to_s })
+ CoreTap.instance.alias_dir.mkpath
+ FileUtils.ln_sf f.path, source_path
expect(f.alias_path).to eq(alias_path)
expect(f.installed_alias_path).to eq(source_path.to_s)
@@ -443,6 +451,9 @@ describe Formula do
allow(described_class).to receive(:installed).and_return(formulae)
+ CoreTap.instance.alias_dir.mkpath
+ FileUtils.ln_sf formula_with_alias.path, alias_path
+
expect(described_class.installed_with_alias_path(alias_path))
.to eq([formula_with_alias])
end
@@ -940,6 +951,9 @@ describe Formula do
tab.source["path"] = alias_path
stub_formula_loader(f, alias_path)
+ CoreTap.instance.alias_dir.mkpath
+ FileUtils.ln_sf f.path, alias_path
+
expect(f.current_installed_alias_target).to eq(f)
expect(f.latest_formula).to eq(f)
expect(f).not_to have_changed_installed_alias_target
@@ -952,6 +966,9 @@ describe Formula do
tab.source["path"] = alias_path
stub_formula_loader(new_formula, alias_path)
+ CoreTap.instance.alias_dir.mkpath
+ FileUtils.ln_sf new_formula.path, alias_path
+
expect(f.current_installed_alias_target).to eq(new_formula)
expect(f.latest_formula).to eq(new_formula)
expect(f).to have_changed_installed_alias_target
@@ -964,6 +981,9 @@ describe Formula do
tab.source["path"] = alias_path
stub_formula_loader(new_formula, alias_path)
+ CoreTap.instance.alias_dir.mkpath
+ FileUtils.ln_sf new_formula.path, alias_path
+
expect(new_formula.current_installed_alias_target).to eq(new_formula)
expect(new_formula.latest_formula).to eq(new_formula)
expect(new_formula).not_to have_changed_installed_alias_target
@@ -1050,6 +1070,10 @@ describe Formula do
f.follow_installed_alias = true
f.build = setup_tab_for_prefix(same_prefix, path: alias_path)
stub_formula_loader(new_formula, alias_path)
+
+ CoreTap.instance.alias_dir.mkpath
+ FileUtils.ln_sf new_formula.path, alias_path
+
expect(f.outdated_kegs).not_to be_empty
end
@@ -1088,6 +1112,10 @@ describe Formula do
tab = setup_tab_for_prefix(old_alias_target_prefix, path: alias_path)
old_formula.build = tab
allow(described_class).to receive(:installed).and_return([old_formula])
+
+ CoreTap.instance.alias_dir.mkpath
+ FileUtils.ln_sf f.path, alias_path
+
expect(f.outdated_kegs).not_to be_empty
end
diff --git a/Library/Homebrew/test/missing_formula_spec.rb b/Library/Homebrew/test/missing_formula_spec.rb
new file mode 100644
index 000000000..f395965a6
--- /dev/null
+++ b/Library/Homebrew/test/missing_formula_spec.rb
@@ -0,0 +1,179 @@
+require "missing_formula"
+
+describe Homebrew::MissingFormula do
+ context "::reason" do
+ subject { described_class.reason("gem") }
+
+ it { is_expected.to_not be_nil }
+ end
+
+ context "::blacklisted_reason" do
+ matcher(:be_blacklisted) do
+ match(&Homebrew::MissingFormula.method(:blacklisted_reason))
+ end
+
+ context "rubygems" do
+ %w[gem rubygem rubygems].each do |s|
+ subject { s }
+
+ it { is_expected.to be_blacklisted }
+ end
+ end
+
+ context "latex" do
+ %w[latex tex tex-live texlive TexLive].each do |s|
+ subject { s }
+
+ it { is_expected.to be_blacklisted }
+ end
+ end
+
+ context "pip" do
+ subject { "pip" }
+
+ it { is_expected.to be_blacklisted }
+ end
+
+ context "pil" do
+ subject { "pil" }
+
+ it { is_expected.to be_blacklisted }
+ end
+
+ context "macruby" do
+ subject { "MacRuby" }
+
+ it { is_expected.to be_blacklisted }
+ end
+
+ context "lzma" do
+ %w[lzma liblzma].each do |s|
+ subject { s }
+
+ it { is_expected.to be_blacklisted }
+ end
+ end
+
+ context "gtest" do
+ %w[gtest googletest google-test].each do |s|
+ subject { s }
+
+ it { is_expected.to be_blacklisted }
+ end
+ end
+
+ context "gmock" do
+ %w[gmock googlemock google-mock].each do |s|
+ subject { s }
+
+ it { is_expected.to be_blacklisted }
+ end
+ end
+
+ context "sshpass" do
+ subject { "sshpass" }
+
+ it { is_expected.to be_blacklisted }
+ end
+
+ context "gsutil" do
+ subject { "gsutil" }
+
+ it { is_expected.to be_blacklisted }
+ end
+
+ context "clojure" do
+ subject { "clojure" }
+
+ it { is_expected.to be_blacklisted }
+ end
+
+ context "osmium" do
+ %w[osmium Osmium].each do |s|
+ subject { s }
+
+ it { is_expected.to be_blacklisted }
+ end
+ end
+
+ context "gfortran" do
+ subject { "gfortran" }
+
+ it { is_expected.to be_blacklisted }
+ end
+
+ context "play" do
+ subject { "play" }
+
+ it { is_expected.to be_blacklisted }
+ end
+
+ context "haskell-platform" do
+ subject { "haskell-platform" }
+
+ it { is_expected.to be_blacklisted }
+ end
+
+ context "xcode", :needs_macos do
+ %w[xcode Xcode].each do |s|
+ subject { s }
+
+ it { is_expected.to be_blacklisted }
+ end
+ end
+ end
+
+ context "::tap_migration_reason" do
+ subject { described_class.tap_migration_reason(formula) }
+
+ before do
+ Tap.clear_cache
+ tap_path = Tap::TAP_DIRECTORY/"homebrew/homebrew-foo"
+ tap_path.mkpath
+ (tap_path/"tap_migrations.json").write <<-EOS.undent
+ { "migrated-formula": "homebrew/bar" }
+ EOS
+ end
+
+ context "with a migrated formula" do
+ let(:formula) { "migrated-formula" }
+ it { is_expected.to_not be_nil }
+ end
+
+ context "with a missing formula" do
+ let(:formula) { "missing-formula" }
+ it { is_expected.to be_nil }
+ end
+ end
+
+ context "::deleted_reason" do
+ subject { described_class.deleted_reason(formula) }
+
+ before do
+ Tap.clear_cache
+ tap_path = Tap::TAP_DIRECTORY/"homebrew/homebrew-foo"
+ tap_path.mkpath
+ (tap_path/"deleted-formula.rb").write "placeholder"
+
+ tap_path.cd do
+ shutup do
+ system "git", "init"
+ system "git", "add", "--all"
+ system "git", "commit", "-m", "initial state"
+ system "git", "rm", "deleted-formula.rb"
+ system "git", "commit", "-m", "delete formula 'deleted-formula'"
+ end
+ end
+ end
+
+ context "with a deleted formula" do
+ let(:formula) { "homebrew/foo/deleted-formula" }
+ it { is_expected.to_not be_nil }
+ end
+
+ context "with a formula that never existed" do
+ let(:formula) { "homebrew/foo/missing-formula" }
+ it { is_expected.to be_nil }
+ end
+ end
+end
diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb
index 5f961974c..a5ed5394a 100644
--- a/Library/Homebrew/utils/github.rb
+++ b/Library/Homebrew/utils/github.rb
@@ -268,7 +268,6 @@ module GitHub
def print_pull_requests_matching(query)
return [] if ENV["HOMEBREW_NO_GITHUB_API"]
- ohai "Searching pull requests..."
open_or_closed_prs = issues_matching(query, type: "pr")
diff --git a/Library/Homebrew/vendor/README.md b/Library/Homebrew/vendor/README.md
index f998d26c5..906d42918 100644
--- a/Library/Homebrew/vendor/README.md
+++ b/Library/Homebrew/vendor/README.md
@@ -3,7 +3,7 @@ Vendored Dependencies
* [plist](https://github.com/bleything/plist), version 3.1.0
-* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 0.2.6
+* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 1.1.0
## Licenses:
@@ -33,7 +33,7 @@ Vendored Dependencies
### ruby-macho
> The MIT License
-> Copyright (c) 2015, 2016 William Woodruff <william @ tuffbizz.com>
+> Copyright (c) 2015, 2016, 2017 William Woodruff <william @ tuffbizz.com>
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
diff --git a/Library/Homebrew/vendor/macho/macho.rb b/Library/Homebrew/vendor/macho/macho.rb
index de1d4ff43..b7f20ea19 100644
--- a/Library/Homebrew/vendor/macho/macho.rb
+++ b/Library/Homebrew/vendor/macho/macho.rb
@@ -5,7 +5,6 @@ require "#{File.dirname(__FILE__)}/macho/load_commands"
require "#{File.dirname(__FILE__)}/macho/sections"
require "#{File.dirname(__FILE__)}/macho/macho_file"
require "#{File.dirname(__FILE__)}/macho/fat_file"
-require "#{File.dirname(__FILE__)}/macho/open"
require "#{File.dirname(__FILE__)}/macho/exceptions"
require "#{File.dirname(__FILE__)}/macho/utils"
require "#{File.dirname(__FILE__)}/macho/tools"
@@ -13,5 +12,29 @@ require "#{File.dirname(__FILE__)}/macho/tools"
# The primary namespace for ruby-macho.
module MachO
# release version
- VERSION = "0.2.6".freeze
+ VERSION = "1.1.0".freeze
+
+ # Opens the given filename as a MachOFile or FatFile, depending on its magic.
+ # @param filename [String] the file being opened
+ # @return [MachOFile] if the file is a Mach-O
+ # @return [FatFile] if the file is a Fat file
+ # @raise [ArgumentError] if the given file does not exist
+ # @raise [TruncatedFileError] if the file is too small to have a valid header
+ # @raise [MagicError] if the file's magic is not valid Mach-O magic
+ def self.open(filename)
+ 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 Utils.fat_magic?(magic)
+ file = FatFile.new(filename)
+ elsif Utils.magic?(magic)
+ file = MachOFile.new(filename)
+ else
+ raise MagicError, magic
+ end
+
+ file
+ end
end
diff --git a/Library/Homebrew/vendor/macho/macho/exceptions.rb b/Library/Homebrew/vendor/macho/macho/exceptions.rb
index 262c195a3..14c2c22ae 100644
--- a/Library/Homebrew/vendor/macho/macho/exceptions.rb
+++ b/Library/Homebrew/vendor/macho/macho/exceptions.rb
@@ -80,7 +80,8 @@ module MachO
# @param cputype [Fixnum] the CPU type of the unknown pair
# @param cpusubtype [Fixnum] the CPU sub-type of the unknown pair
def initialize(cputype, cpusubtype)
- super "Unrecognized CPU sub-type: 0x#{"%08x" % cpusubtype} (for CPU type: 0x#{"%08x" % cputype})"
+ super "Unrecognized CPU sub-type: 0x#{"%08x" % cpusubtype}" \
+ " (for CPU type: 0x#{"%08x" % cputype})"
end
end
@@ -108,13 +109,15 @@ module MachO
end
end
- # Raised when the number of arguments used to create a load command manually is wrong.
+ # 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}"
+ super "Expected #{expected_arity} arguments for #{cmd_sym} creation," \
+ " got #{actual_arity}"
end
end
@@ -130,7 +133,8 @@ module MachO
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"
+ super "Load command #{lc.type} at offset #{lc.view.offset} contains a" \
+ " malformed string"
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/fat_file.rb b/Library/Homebrew/vendor/macho/macho/fat_file.rb
index 9f29922e6..351be5ac6 100644
--- a/Library/Homebrew/vendor/macho/macho/fat_file.rb
+++ b/Library/Homebrew/vendor/macho/macho/fat_file.rb
@@ -1,24 +1,50 @@
+require "forwardable"
+
module MachO
# Represents a "Fat" file, which contains a header, a listing of available
# architectures, and one or more Mach-O binaries.
# @see https://en.wikipedia.org/wiki/Mach-O#Multi-architecture_binaries
- # @see MachO::MachOFile
+ # @see MachOFile
class FatFile
+ extend Forwardable
+
# @return [String] the filename loaded from, or nil if loaded from a binary string
attr_accessor :filename
- # @return [MachO::FatHeader] the file's header
+ # @return [Headers::FatHeader] the file's header
attr_reader :header
- # @return [Array<MachO::FatArch>] an array of fat architectures
+ # @return [Array<Headers::FatArch>] an array of fat architectures
attr_reader :fat_archs
- # @return [Array<MachO::MachOFile>] an array of Mach-O binaries
+ # @return [Array<MachOFile>] an array of Mach-O binaries
attr_reader :machos
+ # Creates a new FatFile from the given (single-arch) Mach-Os
+ # @param machos [Array<MachOFile>] the machos to combine
+ # @return [FatFile] a new FatFile containing the give machos
+ def self.new_from_machos(*machos)
+ header = Headers::FatHeader.new(Headers::FAT_MAGIC, machos.size)
+ offset = Headers::FatHeader.bytesize + (machos.size * Headers::FatArch.bytesize)
+ fat_archs = []
+ machos.each do |macho|
+ fat_archs << Headers::FatArch.new(macho.header.cputype,
+ macho.header.cpusubtype,
+ offset, macho.serialize.bytesize,
+ macho.alignment)
+ offset += macho.serialize.bytesize
+ end
+
+ bin = header.serialize
+ bin << fat_archs.map(&:serialize).join
+ bin << machos.map(&:serialize).join
+
+ new_from_bin(bin)
+ end
+
# Creates a new FatFile instance from a binary string.
# @param bin [String] a binary string containing raw Mach-O data
- # @return [MachO::FatFile] a new FatFile
+ # @return [FatFile] a new FatFile
def self.new_from_bin(bin)
instance = allocate
instance.initialize_from_bin(bin)
@@ -38,7 +64,7 @@ module MachO
end
# Initializes a new FatFile instance from a binary string.
- # @see MachO::FatFile.new_from_bin
+ # @see new_from_bin
# @api private
def initialize_from_bin(bin)
@filename = nil
@@ -52,70 +78,41 @@ module MachO
@raw_data
end
- # @return [Boolean] true if the file is of type `MH_OBJECT`, false otherwise
- def object?
- machos.first.object?
- end
-
- # @return [Boolean] true if the file is of type `MH_EXECUTE`, false otherwise
- def executable?
- machos.first.executable?
- end
-
- # @return [Boolean] true if the file is of type `MH_FVMLIB`, false otherwise
- def fvmlib?
- machos.first.fvmlib?
- end
-
- # @return [Boolean] true if the file is of type `MH_CORE`, false otherwise
- def core?
- machos.first.core?
- end
-
- # @return [Boolean] true if the file is of type `MH_PRELOAD`, false otherwise
- def preload?
- machos.first.preload?
- end
-
- # @return [Boolean] true if the file is of type `MH_DYLIB`, false otherwise
- def dylib?
- machos.first.dylib?
- end
-
- # @return [Boolean] true if the file is of type `MH_DYLINKER`, false otherwise
- def dylinker?
- machos.first.dylinker?
- end
-
- # @return [Boolean] true if the file is of type `MH_BUNDLE`, false otherwise
- def bundle?
- machos.first.bundle?
- end
-
- # @return [Boolean] true if the file is of type `MH_DSYM`, false otherwise
- def dsym?
- machos.first.dsym?
- end
-
- # @return [Boolean] true if the file is of type `MH_KEXT_BUNDLE`, false otherwise
- def kext?
- machos.first.kext?
- end
-
- # @return [Fixnum] the file's magic number
- def magic
- header.magic
- end
+ # @!method object?
+ # @return (see MachO::MachOFile#object?)
+ # @!method executable?
+ # @return (see MachO::MachOFile#executable?)
+ # @!method fvmlib?
+ # @return (see MachO::MachOFile#fvmlib?)
+ # @!method core?
+ # @return (see MachO::MachOFile#core?)
+ # @!method preload?
+ # @return (see MachO::MachOFile#preload?)
+ # @!method dylib?
+ # @return (see MachO::MachOFile#dylib?)
+ # @!method dylinker?
+ # @return (see MachO::MachOFile#dylinker?)
+ # @!method bundle?
+ # @return (see MachO::MachOFile#bundle?)
+ # @!method dsym?
+ # @return (see MachO::MachOFile#dsym?)
+ # @!method kext?
+ # @return (see MachO::MachOFile#kext?)
+ # @!method filetype
+ # @return (see MachO::MachOFile#filetype)
+ # @!method dylib_id
+ # @return (see MachO::MachOFile#dylib_id)
+ def_delegators :canonical_macho, :object?, :executable?, :fvmlib?,
+ :core?, :preload?, :dylib?, :dylinker?, :bundle?,
+ :dsym?, :kext?, :filetype, :dylib_id
+
+ # @!method magic
+ # @return (see MachO::Headers::FatHeader#magic)
+ def_delegators :header, :magic
# @return [String] a string representation of the file's magic number
def magic_string
- MH_MAGICS[magic]
- end
-
- # The file's type. Assumed to be the same for every Mach-O within.
- # @return [Symbol] the filetype
- def filetype
- machos.first.filetype
+ Headers::MH_MAGICS[magic]
end
# Populate the instance's fields with the raw Fat Mach-O data.
@@ -128,21 +125,13 @@ module MachO
end
# All load commands responsible for loading dylibs in the file's Mach-O's.
- # @return [Array<MachO::DylibCommand>] an array of DylibCommands
+ # @return [Array<LoadCommands::DylibCommand>] an array of DylibCommands
def dylib_load_commands
machos.map(&:dylib_load_commands).flatten
end
- # The file's dylib ID. If the file is not a dylib, returns `nil`.
- # @example
- # file.dylib_id # => 'libBar.dylib'
- # @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.
+ # Changes the file's dylib ID to `new_id`. If the file is not a dylib,
+ # does nothing.
# @example
# file.change_dylib_id('libFoo.dylib')
# @param new_id [String] the new dylib ID
@@ -151,7 +140,7 @@ module MachO
# if false, fail only if all slices fail.
# @return [void]
# @raise [ArgumentError] if `new_id` is not a String
- # @see MachO::MachOFile#linked_dylibs
+ # @see 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?)
@@ -167,7 +156,7 @@ module MachO
# All shared libraries linked to the file's Mach-Os.
# @return [Array<String>] an array of all shared libraries
- # @see MachO::MachOFile#linked_dylibs
+ # @see 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.
@@ -175,8 +164,9 @@ module MachO
machos.map(&:linked_dylibs).flatten.uniq
end
- # Changes all dependent shared library install names from `old_name` to `new_name`.
- # In a fat file, this changes install names in all internal Mach-Os.
+ # Changes all dependent shared library install names from `old_name` to
+ # `new_name`. In a fat file, this changes install names in all internal
+ # Mach-Os.
# @example
# file.change_install_name('/usr/lib/libFoo.dylib', '/usr/lib/libBar.dylib')
# @param old_name [String] the shared library name being changed
@@ -185,7 +175,7 @@ module MachO
# @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
+ # @see 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)
@@ -198,7 +188,7 @@ module MachO
# All runtime paths associated with the file's Mach-Os.
# @return [Array<String>] an array of all runtime paths
- # @see MachO::MachOFile#rpaths
+ # @see MachOFile#rpaths
def rpaths
# Can individual architectures have different runtime paths?
machos.map(&:rpaths).flatten.uniq
@@ -211,7 +201,7 @@ module MachO
# @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
+ # @see MachOFile#change_rpath
def change_rpath(old_path, new_path, options = {})
each_macho(options) do |macho|
macho.change_rpath(old_path, new_path, options)
@@ -226,7 +216,7 @@ module MachO
# @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
+ # @see MachOFile#add_rpath
def add_rpath(path, options = {})
each_macho(options) do |macho|
macho.add_rpath(path, options)
@@ -241,7 +231,7 @@ module MachO
# @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
+ # @see MachOFile#delete_rpath
def delete_rpath(path, options = {})
each_macho(options) do |macho|
macho.delete_rpath(path, options)
@@ -254,20 +244,21 @@ module MachO
# @example
# file.extract(:i386) # => MachO::MachOFile
# @param cputype [Symbol] the CPU type of the Mach-O being extracted
- # @return [MachO::MachOFile, nil] the extracted Mach-O or nil if no Mach-O has the given CPU type
+ # @return [MachOFile, nil] the extracted Mach-O or nil if no Mach-O has the given CPU type
def extract(cputype)
machos.select { |macho| macho.cputype == cputype }.first
end
# Write all (fat) data to the given filename.
# @param filename [String] the file to write to
+ # @return [void]
def write(filename)
File.open(filename, "wb") { |f| f.write(@raw_data) }
end
# Write all (fat) data to the file used to initialize the instance.
# @return [void]
- # @raise [MachO::MachOError] if the instance was initialized without a file
+ # @raise [MachOError] if the instance was initialized without a file
# @note Overwrites all data in the file!
def write!
if filename.nil?
@@ -280,17 +271,18 @@ module MachO
private
# Obtain the fat header from raw file data.
- # @return [MachO::FatHeader] the fat header
- # @raise [MachO::TruncatedFileError] if the file is too small to have a valid header
- # @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
+ # @return [Headers::FatHeader] the fat header
+ # @raise [TruncatedFileError] if the file is too small to have a
+ # valid header
+ # @raise [MagicError] if the magic is not valid Mach-O magic
+ # @raise [MachOBinaryError] if the magic is for a non-fat Mach-O file
+ # @raise [JavaClassFileError] if the file is a Java classfile
# @api private
def populate_fat_header
# the smallest fat Mach-O header is 8 bytes
raise TruncatedFileError if @raw_data.size < 8
- fh = FatHeader.new_from_bin(:big, @raw_data[0, FatHeader.bytesize])
+ fh = Headers::FatHeader.new_from_bin(:big, @raw_data[0, Headers::FatHeader.bytesize])
raise MagicError, fh.magic unless Utils.magic?(fh.magic)
raise MachOBinaryError unless Utils.fat_magic?(fh.magic)
@@ -308,22 +300,22 @@ module MachO
end
# Obtain an array of fat architectures from raw file data.
- # @return [Array<MachO::FatArch>] an array of fat architectures
+ # @return [Array<Headers::FatArch>] an array of fat architectures
# @api private
def populate_fat_archs
archs = []
- fa_off = FatHeader.bytesize
- fa_len = FatArch.bytesize
+ fa_off = Headers::FatHeader.bytesize
+ fa_len = Headers::FatArch.bytesize
header.nfat_arch.times do |i|
- archs << FatArch.new_from_bin(:big, @raw_data[fa_off + (fa_len * i), fa_len])
+ archs << Headers::FatArch.new_from_bin(:big, @raw_data[fa_off + (fa_len * i), fa_len])
end
archs
end
# Obtain an array of Mach-O blobs from raw file data.
- # @return [Array<MachO::MachOFile>] an array of Mach-Os
+ # @return [Array<MachOFile>] an array of Mach-Os
# @api private
def populate_machos
machos = []
@@ -351,7 +343,7 @@ module MachO
# @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
+ # @raise [RecoverableModificationError] under the conditions of
# the `:strict` option above.
# @api private
def each_macho(options = {})
@@ -373,5 +365,13 @@ module MachO
# Non-strict mode: Raise first error if *all* Mach-O slices failed.
raise errors.first if errors.size == machos.size
end
+
+ # Return a single-arch Mach-O that represents this fat Mach-O for purposes
+ # of delegation.
+ # @return [MachOFile] the Mach-O file
+ # @api private
+ def canonical_macho
+ machos.first
+ end
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/headers.rb b/Library/Homebrew/vendor/macho/macho/headers.rb
index 7272503af..08a4b80c4 100644
--- a/Library/Homebrew/vendor/macho/macho/headers.rb
+++ b/Library/Homebrew/vendor/macho/macho/headers.rb
@@ -1,587 +1,665 @@
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",
- }.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,
- CPU_TYPE_X86_64 => :x86_64,
- CPU_TYPE_ARM => :arm,
- 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
-
- # @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
+ # Classes and constants for parsing the headers of Mach-O binaries.
+ module Headers
+ # big-endian fat magic
+ # @api private
+ FAT_MAGIC = 0xcafebabe
- # the v7s ("Swift") sub-type for `CPU_TYPE_ARM`
- # @api private
- CPU_SUBTYPE_ARM_V7S = 11
+ # 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
- # 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,
- CPU_SUBTYPE_486 => :i486,
- CPU_SUBTYPE_486SX => :i486SX,
- CPU_SUBTYPE_586 => :i586, # also "pentium" in arch(3)
- CPU_SUBTYPE_PENTPRO => :i686, # also "pentpro" in arch(3)
- CPU_SUBTYPE_PENTII_M3 => :pentIIm3,
- CPU_SUBTYPE_PENTII_M5 => :pentIIm5,
- CPU_SUBTYPE_PENTIUM_4 => :pentium4,
- }.freeze,
- CPU_TYPE_X86_64 => {
- CPU_SUBTYPE_X86_64_ALL => :x86_64,
- CPU_SUBTYPE_X86_64_H => :x86_64h,
- }.freeze,
- CPU_TYPE_ARM => {
- CPU_SUBTYPE_ARM_ALL => :arm,
- CPU_SUBTYPE_ARM_V4T => :armv4t,
- CPU_SUBTYPE_ARM_V6 => :armv6,
- CPU_SUBTYPE_ARM_V5TEJ => :armv5,
- CPU_SUBTYPE_ARM_XSCALE => :xscale,
- CPU_SUBTYPE_ARM_V7 => :armv7,
- CPU_SUBTYPE_ARM_V7F => :armv7f,
- CPU_SUBTYPE_ARM_V7S => :armv7s,
- CPU_SUBTYPE_ARM_V7K => :armv7k,
- CPU_SUBTYPE_ARM_V6M => :armv6m,
- CPU_SUBTYPE_ARM_V7M => :armv7m,
- CPU_SUBTYPE_ARM_V7EM => :armv7em,
- CPU_SUBTYPE_ARM_V8 => :armv8,
- }.freeze,
- CPU_TYPE_ARM64 => {
- CPU_SUBTYPE_ARM64_ALL => :arm64,
- CPU_SUBTYPE_ARM64_V8 => :arm64v8,
- }.freeze,
- CPU_TYPE_POWERPC => {
- CPU_SUBTYPE_POWERPC_ALL => :ppc,
- CPU_SUBTYPE_POWERPC_601 => :ppc601,
- CPU_SUBTYPE_POWERPC_603 => :ppc603,
- CPU_SUBTYPE_POWERPC_603E => :ppc603e,
- CPU_SUBTYPE_POWERPC_603EV => :ppc603ev,
- CPU_SUBTYPE_POWERPC_604 => :ppc604,
- CPU_SUBTYPE_POWERPC_604E => :ppc604e,
- CPU_SUBTYPE_POWERPC_750 => :ppc750,
- CPU_SUBTYPE_POWERPC_7400 => :ppc7400,
- CPU_SUBTYPE_POWERPC_7450 => :ppc7450,
- CPU_SUBTYPE_POWERPC_970 => :ppc970,
- }.freeze,
- CPU_TYPE_POWERPC64 => {
- CPU_SUBTYPE_POWERPC64_ALL => :ppc64,
- # apparently the only exception to the naming scheme
- CPU_SUBTYPE_POWERPC_970 => :ppc970_64,
- }.freeze,
- CPU_TYPE_MC680X0 => {
- CPU_SUBTYPE_MC680X0_ALL => :m68k,
- CPU_SUBTYPE_MC68030 => :mc68030,
- CPU_SUBTYPE_MC68040 => :mc68040,
- },
- CPU_TYPE_MC88000 => {
- CPU_SUBTYPE_MC88000_ALL => :m88k,
- },
- }.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 Symbol representations
- # @api private
- MH_FILETYPES = {
- 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
- MH_FLAGS = {
- :MH_NOUNDEFS => 0x1,
- :MH_INCRLINK => 0x2,
- :MH_DYLDLINK => 0x4,
- :MH_BINDATLOAD => 0x8,
- :MH_PREBOUND => 0x10,
- :MH_SPLIT_SEGS => 0x20,
- :MH_LAZY_INIT => 0x40,
- :MH_TWOLEVEL => 0x80,
- :MH_FORCE_FLAT => 0x100,
- :MH_NOMULTIDEFS => 0x200,
- :MH_NOPREFIXBINDING => 0x400,
- :MH_PREBINDABLE => 0x800,
- :MH_ALLMODSBOUND => 0x1000,
- :MH_SUBSECTIONS_VIA_SYMBOLS => 0x2000,
- :MH_CANONICAL => 0x4000,
- :MH_WEAK_DEFINES => 0x8000,
- :MH_BINDS_TO_WEAK => 0x10000,
- :MH_ALLOW_STACK_EXECUTION => 0x20000,
- :MH_ROOT_SAFE => 0x40000,
- :MH_SETUID_SAFE => 0x80000,
- :MH_NO_REEXPORTED_DYLIBS => 0x100000,
- :MH_PIE => 0x200000,
- :MH_DEAD_STRIPPABLE_DYLIB => 0x400000,
- :MH_HAS_TLV_DESCRIPTORS => 0x800000,
- :MH_NO_HEAP_EXECUTION => 0x1000000,
- :MH_APP_EXTENSION_SAFE => 0x02000000,
- }.freeze
-
- # Fat binary header structure
- # @see MachO::FatArch
- class FatHeader < MachOStructure
- # @return [Fixnum] the magic number of the header (and file)
- attr_reader :magic
-
- # @return [Fixnum] the number of fat architecture structures following the header
- attr_reader :nfat_arch
-
- # always big-endian
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "N2".freeze
-
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 8
-
- # @api private
- def initialize(magic, nfat_arch)
- @magic = magic
- @nfat_arch = nfat_arch
- end
- end
+ # 32-bit big-endian magic
+ # @api private
+ MH_MAGIC = 0xfeedface
- # Fat binary header architecture structure. A Fat binary has one or more of
- # these, representing one or more internal Mach-O blobs.
- # @see MachO::FatHeader
- class FatArch < MachOStructure
- # @return [Fixnum] the CPU type of the Mach-O
- attr_reader :cputype
+ # 32-bit little-endian magic
+ # @api private
+ MH_CIGAM = 0xcefaedfe
- # @return [Fixnum] the CPU subtype of the Mach-O
- attr_reader :cpusubtype
+ # 64-bit big-endian magic
+ # @api private
+ MH_MAGIC_64 = 0xfeedfacf
- # @return [Fixnum] the file offset to the beginning of the Mach-O data
- attr_reader :offset
+ # 64-bit little-endian magic
+ # @api private
+ MH_CIGAM_64 = 0xcffaedfe
- # @return [Fixnum] the size, in bytes, of the Mach-O data
- attr_reader :size
+ # 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",
+ }.freeze
+
+ # mask for CPUs with 64-bit architectures (when running a 64-bit ABI?)
+ # @api private
+ CPU_ARCH_ABI64 = 0x01000000
- # @return [Fixnum] the alignment, as a power of 2
- attr_reader :align
+ # any CPU (unused?)
+ # @api private
+ CPU_TYPE_ANY = -1
- # always big-endian
- # @see MachOStructure::FORMAT
+ # m68k compatible CPUs
# @api private
- FORMAT = "N5".freeze
+ CPU_TYPE_MC680X0 = 0x06
- # @see MachOStructure::SIZEOF
+ # i386 and later compatible CPUs
# @api private
- SIZEOF = 20
+ CPU_TYPE_I386 = 0x07
+ # x86_64 (AMD64) compatible CPUs
# @api private
- def initialize(cputype, cpusubtype, offset, size, align)
- @cputype = cputype
- @cpusubtype = cpusubtype
- @offset = offset
- @size = size
- @align = align
- end
- end
+ CPU_TYPE_X86_64 = (CPU_TYPE_I386 | CPU_ARCH_ABI64)
- # 32-bit Mach-O file header structure
- class MachHeader < MachOStructure
- # @return [Fixnum] the magic number
- attr_reader :magic
+ # 32-bit ARM compatible CPUs
+ # @api private
+ CPU_TYPE_ARM = 0x0c
- # @return [Fixnum] the CPU type of the Mach-O
- attr_reader :cputype
+ # m88k compatible CPUs
+ # @api private
+ CPU_TYPE_MC88000 = 0xd
- # @return [Fixnum] the CPU subtype of the Mach-O
- attr_reader :cpusubtype
+ # 64-bit ARM compatible CPUs
+ # @api private
+ CPU_TYPE_ARM64 = (CPU_TYPE_ARM | CPU_ARCH_ABI64)
- # @return [Fixnum] the file type of the Mach-O
- attr_reader :filetype
+ # PowerPC compatible CPUs
+ # @api private
+ CPU_TYPE_POWERPC = 0x12
- # @return [Fixnum] the number of load commands in the Mach-O
- attr_reader :ncmds
+ # PowerPC64 compatible CPUs
+ # @api private
+ CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
- # @return [Fixnum] the size of all load commands, in bytes, in the Mach-O
- attr_reader :sizeofcmds
+ # association of cpu types to symbol representations
+ # @api private
+ CPU_TYPES = {
+ CPU_TYPE_ANY => :any,
+ CPU_TYPE_I386 => :i386,
+ CPU_TYPE_X86_64 => :x86_64,
+ CPU_TYPE_ARM => :arm,
+ CPU_TYPE_ARM64 => :arm64,
+ CPU_TYPE_POWERPC => :ppc,
+ CPU_TYPE_POWERPC64 => :ppc64,
+ }.freeze
+
+ # mask for CPU subtype capabilities
+ # @api private
+ CPU_SUBTYPE_MASK = 0xff000000
- # @return [Fixnum] the header flags associated with the Mach-O
- attr_reader :flags
+ # 64-bit libraries (undocumented!)
+ # @see http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
+ # @api private
+ CPU_SUBTYPE_LIB64 = 0x80000000
- # @see MachOStructure::FORMAT
+ # the lowest common sub-type for `CPU_TYPE_I386`
# @api private
- FORMAT = "L=7".freeze
+ CPU_SUBTYPE_I386 = 3
- # @see MachOStructure::SIZEOF
+ # the i486 sub-type for `CPU_TYPE_I386`
# @api private
- SIZEOF = 28
+ CPU_SUBTYPE_486 = 4
+ # the i486SX sub-type for `CPU_TYPE_I386`
# @api private
- def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
- flags)
- @magic = magic
- @cputype = cputype
- # For now we're not interested in additional capability bits also to be
- # found in the `cpusubtype` field. We only care about the CPU sub-type.
- @cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK
- @filetype = filetype
- @ncmds = ncmds
- @sizeofcmds = sizeofcmds
- @flags = flags
- end
+ CPU_SUBTYPE_486SX = 132
- # @example
- # puts "this mach-o has position-independent execution" if header.flag?(:MH_PIE)
- # @param flag [Symbol] a mach header flag symbol
- # @return [Boolean] true if `flag` is present in the header's flag section
- def flag?(flag)
- flag = MH_FLAGS[flag]
- return false if flag.nil?
- flags & flag == flag
- end
- end
+ # the i586 (P5, Pentium) sub-type for `CPU_TYPE_I386`
+ # @api private
+ CPU_SUBTYPE_586 = 5
+
+ # @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
- # 64-bit Mach-O file header structure
- class MachHeader64 < MachHeader
- # @return [void]
- attr_reader :reserved
+ # 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
- # @see MachOStructure::FORMAT
+ # the 7400 (G4) sub-type for `CPU_TYPE_POWERPC`
# @api private
- FORMAT = "L=8".freeze
+ CPU_SUBTYPE_POWERPC_7400 = 10
- # @see MachOStructure::SIZEOF
+ # the 7450 (G4 "Voyager") sub-type for `CPU_TYPE_POWERPC`
# @api private
- SIZEOF = 32
+ CPU_SUBTYPE_POWERPC_7450 = 11
+ # the 970 (G5) sub-type for `CPU_TYPE_POWERPC`
# @api private
- def initialize(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds,
- flags, reserved)
- super(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags)
- @reserved = reserved
+ 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,
+ CPU_SUBTYPE_486 => :i486,
+ CPU_SUBTYPE_486SX => :i486SX,
+ CPU_SUBTYPE_586 => :i586, # also "pentium" in arch(3)
+ CPU_SUBTYPE_PENTPRO => :i686, # also "pentpro" in arch(3)
+ CPU_SUBTYPE_PENTII_M3 => :pentIIm3,
+ CPU_SUBTYPE_PENTII_M5 => :pentIIm5,
+ CPU_SUBTYPE_PENTIUM_4 => :pentium4,
+ }.freeze,
+ CPU_TYPE_X86_64 => {
+ CPU_SUBTYPE_X86_64_ALL => :x86_64,
+ CPU_SUBTYPE_X86_64_H => :x86_64h,
+ }.freeze,
+ CPU_TYPE_ARM => {
+ CPU_SUBTYPE_ARM_ALL => :arm,
+ CPU_SUBTYPE_ARM_V4T => :armv4t,
+ CPU_SUBTYPE_ARM_V6 => :armv6,
+ CPU_SUBTYPE_ARM_V5TEJ => :armv5,
+ CPU_SUBTYPE_ARM_XSCALE => :xscale,
+ CPU_SUBTYPE_ARM_V7 => :armv7,
+ CPU_SUBTYPE_ARM_V7F => :armv7f,
+ CPU_SUBTYPE_ARM_V7S => :armv7s,
+ CPU_SUBTYPE_ARM_V7K => :armv7k,
+ CPU_SUBTYPE_ARM_V6M => :armv6m,
+ CPU_SUBTYPE_ARM_V7M => :armv7m,
+ CPU_SUBTYPE_ARM_V7EM => :armv7em,
+ CPU_SUBTYPE_ARM_V8 => :armv8,
+ }.freeze,
+ CPU_TYPE_ARM64 => {
+ CPU_SUBTYPE_ARM64_ALL => :arm64,
+ CPU_SUBTYPE_ARM64_V8 => :arm64v8,
+ }.freeze,
+ CPU_TYPE_POWERPC => {
+ CPU_SUBTYPE_POWERPC_ALL => :ppc,
+ CPU_SUBTYPE_POWERPC_601 => :ppc601,
+ CPU_SUBTYPE_POWERPC_603 => :ppc603,
+ CPU_SUBTYPE_POWERPC_603E => :ppc603e,
+ CPU_SUBTYPE_POWERPC_603EV => :ppc603ev,
+ CPU_SUBTYPE_POWERPC_604 => :ppc604,
+ CPU_SUBTYPE_POWERPC_604E => :ppc604e,
+ CPU_SUBTYPE_POWERPC_750 => :ppc750,
+ CPU_SUBTYPE_POWERPC_7400 => :ppc7400,
+ CPU_SUBTYPE_POWERPC_7450 => :ppc7450,
+ CPU_SUBTYPE_POWERPC_970 => :ppc970,
+ }.freeze,
+ CPU_TYPE_POWERPC64 => {
+ CPU_SUBTYPE_POWERPC64_ALL => :ppc64,
+ # apparently the only exception to the naming scheme
+ CPU_SUBTYPE_POWERPC_970 => :ppc970_64,
+ }.freeze,
+ CPU_TYPE_MC680X0 => {
+ CPU_SUBTYPE_MC680X0_ALL => :m68k,
+ CPU_SUBTYPE_MC68030 => :mc68030,
+ CPU_SUBTYPE_MC68040 => :mc68040,
+ },
+ CPU_TYPE_MC88000 => {
+ CPU_SUBTYPE_MC88000_ALL => :m88k,
+ },
+ }.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 Symbol representations
+ # @api private
+ MH_FILETYPES = {
+ 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
+ MH_FLAGS = {
+ :MH_NOUNDEFS => 0x1,
+ :MH_INCRLINK => 0x2,
+ :MH_DYLDLINK => 0x4,
+ :MH_BINDATLOAD => 0x8,
+ :MH_PREBOUND => 0x10,
+ :MH_SPLIT_SEGS => 0x20,
+ :MH_LAZY_INIT => 0x40,
+ :MH_TWOLEVEL => 0x80,
+ :MH_FORCE_FLAT => 0x100,
+ :MH_NOMULTIDEFS => 0x200,
+ :MH_NOPREFIXBINDING => 0x400,
+ :MH_PREBINDABLE => 0x800,
+ :MH_ALLMODSBOUND => 0x1000,
+ :MH_SUBSECTIONS_VIA_SYMBOLS => 0x2000,
+ :MH_CANONICAL => 0x4000,
+ :MH_WEAK_DEFINES => 0x8000,
+ :MH_BINDS_TO_WEAK => 0x10000,
+ :MH_ALLOW_STACK_EXECUTION => 0x20000,
+ :MH_ROOT_SAFE => 0x40000,
+ :MH_SETUID_SAFE => 0x80000,
+ :MH_NO_REEXPORTED_DYLIBS => 0x100000,
+ :MH_PIE => 0x200000,
+ :MH_DEAD_STRIPPABLE_DYLIB => 0x400000,
+ :MH_HAS_TLV_DESCRIPTORS => 0x800000,
+ :MH_NO_HEAP_EXECUTION => 0x1000000,
+ :MH_APP_EXTENSION_SAFE => 0x02000000,
+ }.freeze
+
+ # Fat binary header structure
+ # @see MachO::FatArch
+ class FatHeader < MachOStructure
+ # @return [Fixnum] the magic number of the header (and file)
+ attr_reader :magic
+
+ # @return [Fixnum] the number of fat architecture structures following the header
+ attr_reader :nfat_arch
+
+ # always big-endian
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "N2".freeze
+
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 8
+
+ # @api private
+ def initialize(magic, nfat_arch)
+ @magic = magic
+ @nfat_arch = nfat_arch
+ end
+
+ # @return [String] the serialized fields of the fat header
+ def serialize
+ [magic, nfat_arch].pack(FORMAT)
+ end
+ end
+
+ # Fat binary header architecture structure. A Fat binary has one or more of
+ # these, representing one or more internal Mach-O blobs.
+ # @see MachO::Headers::FatHeader
+ class FatArch < MachOStructure
+ # @return [Fixnum] the CPU type of the Mach-O
+ attr_reader :cputype
+
+ # @return [Fixnum] the CPU subtype of the Mach-O
+ attr_reader :cpusubtype
+
+ # @return [Fixnum] the file offset to the beginning of the Mach-O data
+ attr_reader :offset
+
+ # @return [Fixnum] the size, in bytes, of the Mach-O data
+ attr_reader :size
+
+ # @return [Fixnum] the alignment, as a power of 2
+ attr_reader :align
+
+ # always big-endian
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "N5".freeze
+
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 20
+
+ # @api private
+ def initialize(cputype, cpusubtype, offset, size, align)
+ @cputype = cputype
+ @cpusubtype = cpusubtype
+ @offset = offset
+ @size = size
+ @align = align
+ end
+
+ # @return [String] the serialized fields of the fat arch
+ def serialize
+ [cputype, cpusubtype, offset, size, align].pack(FORMAT)
+ end
+ end
+
+ # 32-bit Mach-O file header structure
+ class MachHeader < MachOStructure
+ # @return [Fixnum] the magic number
+ attr_reader :magic
+
+ # @return [Fixnum] the CPU type of the Mach-O
+ attr_reader :cputype
+
+ # @return [Fixnum] the CPU subtype of the Mach-O
+ attr_reader :cpusubtype
+
+ # @return [Fixnum] the file type of the Mach-O
+ attr_reader :filetype
+
+ # @return [Fixnum] the number of load commands in the Mach-O
+ attr_reader :ncmds
+
+ # @return [Fixnum] the size of all load commands, in bytes, in the Mach-O
+ attr_reader :sizeofcmds
+
+ # @return [Fixnum] the header flags associated with the Mach-O
+ attr_reader :flags
+
+ # @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)
+ @magic = magic
+ @cputype = cputype
+ # For now we're not interested in additional capability bits also to be
+ # found in the `cpusubtype` field. We only care about the CPU sub-type.
+ @cpusubtype = cpusubtype & ~CPU_SUBTYPE_MASK
+ @filetype = filetype
+ @ncmds = ncmds
+ @sizeofcmds = sizeofcmds
+ @flags = flags
+ end
+
+ # @example
+ # puts "this mach-o has position-independent execution" if header.flag?(:MH_PIE)
+ # @param flag [Symbol] a mach header flag symbol
+ # @return [Boolean] true if `flag` is present in the header's flag section
+ def flag?(flag)
+ flag = MH_FLAGS[flag]
+ return false if flag.nil?
+ flags & flag == flag
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_OBJECT`
+ def object?
+ filetype == Headers::MH_OBJECT
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_EXECUTE`
+ def executable?
+ filetype == Headers::MH_EXECUTE
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_FVMLIB`
+ def fvmlib?
+ filetype == Headers::MH_FVMLIB
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_CORE`
+ def core?
+ filetype == Headers::MH_CORE
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_PRELOAD`
+ def preload?
+ filetype == Headers::MH_PRELOAD
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_DYLIB`
+ def dylib?
+ filetype == Headers::MH_DYLIB
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_DYLINKER`
+ def dylinker?
+ filetype == Headers::MH_DYLINKER
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_BUNDLE`
+ def bundle?
+ filetype == Headers::MH_BUNDLE
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_DSYM`
+ def dsym?
+ filetype == Headers::MH_DSYM
+ end
+
+ # @return [Boolean] whether or not the file is of type `MH_KEXT_BUNDLE`
+ def kext?
+ filetype == Headers::MH_KEXT_BUNDLE
+ end
+
+ # @return [Boolean] true if the Mach-O has 32-bit magic, false otherwise
+ def magic32?
+ Utils.magic32?(magic)
+ end
+
+ # @return [Boolean] true if the Mach-O has 64-bit magic, false otherwise
+ def magic64?
+ Utils.magic64?(magic)
+ end
+
+ # @return [Fixnum] the file's internal alignment
+ def alignment
+ magic32? ? 4 : 8
+ end
+ end
+
+ # 64-bit Mach-O file header structure
+ class MachHeader64 < MachHeader
+ # @return [void]
+ attr_reader :reserved
+
+ # @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)
+ super(magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags)
+ @reserved = reserved
+ end
end
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/load_commands.rb b/Library/Homebrew/vendor/macho/macho/load_commands.rb
index 205110801..be4319ee2 100644
--- a/Library/Homebrew/vendor/macho/macho/load_commands.rb
+++ b/Library/Homebrew/vendor/macho/macho/load_commands.rb
@@ -1,1314 +1,1350 @@
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
- # @api private
- LOAD_COMMANDS = {
- 0x1 => :LC_SEGMENT,
- 0x2 => :LC_SYMTAB,
- 0x3 => :LC_SYMSEG,
- 0x4 => :LC_THREAD,
- 0x5 => :LC_UNIXTHREAD,
- 0x6 => :LC_LOADFVMLIB,
- 0x7 => :LC_IDFVMLIB,
- 0x8 => :LC_IDENT,
- 0x9 => :LC_FVMFILE,
- 0xa => :LC_PREPAGE,
- 0xb => :LC_DYSYMTAB,
- 0xc => :LC_LOAD_DYLIB,
- 0xd => :LC_ID_DYLIB,
- 0xe => :LC_LOAD_DYLINKER,
- 0xf => :LC_ID_DYLINKER,
- 0x10 => :LC_PREBOUND_DYLIB,
- 0x11 => :LC_ROUTINES,
- 0x12 => :LC_SUB_FRAMEWORK,
- 0x13 => :LC_SUB_UMBRELLA,
- 0x14 => :LC_SUB_CLIENT,
- 0x15 => :LC_SUB_LIBRARY,
- 0x16 => :LC_TWOLEVEL_HINTS,
- 0x17 => :LC_PREBIND_CKSUM,
- (0x18 | LC_REQ_DYLD) => :LC_LOAD_WEAK_DYLIB,
- 0x19 => :LC_SEGMENT_64,
- 0x1a => :LC_ROUTINES_64,
- 0x1b => :LC_UUID,
- (0x1c | LC_REQ_DYLD) => :LC_RPATH,
- 0x1d => :LC_CODE_SIGNATURE,
- 0x1e => :LC_SEGMENT_SPLIT_INFO,
- (0x1f | LC_REQ_DYLD) => :LC_REEXPORT_DYLIB,
- 0x20 => :LC_LAZY_LOAD_DYLIB,
- 0x21 => :LC_ENCRYPTION_INFO,
- 0x22 => :LC_DYLD_INFO,
- (0x22 | LC_REQ_DYLD) => :LC_DYLD_INFO_ONLY,
- (0x23 | LC_REQ_DYLD) => :LC_LOAD_UPWARD_DYLIB,
- 0x24 => :LC_VERSION_MIN_MACOSX,
- 0x25 => :LC_VERSION_MIN_IPHONEOS,
- 0x26 => :LC_FUNCTION_STARTS,
- 0x27 => :LC_DYLD_ENVIRONMENT,
- (0x28 | LC_REQ_DYLD) => :LC_MAIN,
- 0x29 => :LC_DATA_IN_CODE,
- 0x2a => :LC_SOURCE_VERSION,
- 0x2b => :LC_DYLIB_CODE_SIGN_DRS,
- 0x2c => :LC_ENCRYPTION_INFO_64,
- 0x2d => :LC_LINKER_OPTION,
- 0x2e => :LC_LINKER_OPTIMIZATION_HINT,
- 0x2f => :LC_VERSION_MIN_TVOS,
- 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 = [
- :LC_LOAD_DYLIB,
- :LC_LOAD_WEAK_DYLIB,
- :LC_REEXPORT_DYLIB,
- :LC_LAZY_LOAD_DYLIB,
- :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 => "SymsegCommand", # obsolete
- :LC_THREAD => "ThreadCommand", # seems obsolete, but not documented as such
- :LC_UNIXTHREAD => "ThreadCommand",
- :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",
- :LC_LOAD_DYLINKER => "DylinkerCommand",
- :LC_ID_DYLINKER => "DylinkerCommand",
- :LC_PREBOUND_DYLIB => "PreboundDylibCommand",
- :LC_ROUTINES => "RoutinesCommand",
- :LC_SUB_FRAMEWORK => "SubFrameworkCommand",
- :LC_SUB_UMBRELLA => "SubUmbrellaCommand",
- :LC_SUB_CLIENT => "SubClientCommand",
- :LC_SUB_LIBRARY => "SubLibraryCommand",
- :LC_TWOLEVEL_HINTS => "TwolevelHintsCommand",
- :LC_PREBIND_CKSUM => "PrebindCksumCommand",
- :LC_LOAD_WEAK_DYLIB => "DylibCommand",
- :LC_SEGMENT_64 => "SegmentCommand64",
- :LC_ROUTINES_64 => "RoutinesCommand64",
- :LC_UUID => "UUIDCommand",
- :LC_RPATH => "RpathCommand",
- :LC_CODE_SIGNATURE => "LinkeditDataCommand",
- :LC_SEGMENT_SPLIT_INFO => "LinkeditDataCommand",
- :LC_REEXPORT_DYLIB => "DylibCommand",
- :LC_LAZY_LOAD_DYLIB => "DylibCommand",
- :LC_ENCRYPTION_INFO => "EncryptionInfoCommand",
- :LC_DYLD_INFO => "DyldInfoCommand",
- :LC_DYLD_INFO_ONLY => "DyldInfoCommand",
- :LC_LOAD_UPWARD_DYLIB => "DylibCommand",
- :LC_VERSION_MIN_MACOSX => "VersionMinCommand",
- :LC_VERSION_MIN_IPHONEOS => "VersionMinCommand",
- :LC_FUNCTION_STARTS => "LinkeditDataCommand",
- :LC_DYLD_ENVIRONMENT => "DylinkerCommand",
- :LC_MAIN => "EntryPointCommand",
- :LC_DATA_IN_CODE => "LinkeditDataCommand",
- :LC_SOURCE_VERSION => "SourceVersionCommand",
- :LC_DYLIB_CODE_SIGN_DRS => "LinkeditDataCommand",
- :LC_ENCRYPTION_INFO_64 => "EncryptionInfoCommand64",
- :LC_LINKER_OPTION => "LinkerOptionCommand",
- :LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand",
- :LC_VERSION_MIN_TVOS => "VersionMinCommand",
- :LC_VERSION_MIN_WATCHOS => "VersionMinCommand",
- }.freeze
-
- # association of segment name symbols to names
- # @api private
- SEGMENT_NAMES = {
- :SEG_PAGEZERO => "__PAGEZERO",
- :SEG_TEXT => "__TEXT",
- :SEG_DATA => "__DATA",
- :SEG_OBJC => "__OBJC",
- :SEG_ICON => "__ICON",
- :SEG_LINKEDIT => "__LINKEDIT",
- :SEG_UNIXSTACK => "__UNIXSTACK",
- :SEG_IMPORT => "__IMPORT",
- }.freeze
-
- # association of segment flag symbols to values
- # @api private
- SEGMENT_FLAGS = {
- :SG_HIGHVM => 0x1,
- :SG_FVMLIB => 0x2,
- :SG_NORELOC => 0x4,
- :SG_PROTECTED_VERSION_1 => 0x8,
- }.freeze
-
- # Mach-O load command structure
- # This is the most generic load command - only cmd ID and size are
- # represented, and no actual data. Used when a more specific class
- # isn't available/implemented.
- class LoadCommand < MachOStructure
- # @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
-
- # @return [Fixnum] the size of the load command, in bytes
- attr_reader :cmdsize
-
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2".freeze
+ # Classes and constants for parsing load commands in Mach-O binaries.
+ module LoadCommands
+ # load commands added after OS X 10.1 need to be bitwise ORed with
+ # LC_REQ_DYLD to be recognized by the dynamic linker (dyld)
+ # @api private
+ LC_REQ_DYLD = 0x80000000
+
+ # association of load commands to symbol representations
+ # @api private
+ LOAD_COMMANDS = {
+ 0x1 => :LC_SEGMENT,
+ 0x2 => :LC_SYMTAB,
+ 0x3 => :LC_SYMSEG,
+ 0x4 => :LC_THREAD,
+ 0x5 => :LC_UNIXTHREAD,
+ 0x6 => :LC_LOADFVMLIB,
+ 0x7 => :LC_IDFVMLIB,
+ 0x8 => :LC_IDENT,
+ 0x9 => :LC_FVMFILE,
+ 0xa => :LC_PREPAGE,
+ 0xb => :LC_DYSYMTAB,
+ 0xc => :LC_LOAD_DYLIB,
+ 0xd => :LC_ID_DYLIB,
+ 0xe => :LC_LOAD_DYLINKER,
+ 0xf => :LC_ID_DYLINKER,
+ 0x10 => :LC_PREBOUND_DYLIB,
+ 0x11 => :LC_ROUTINES,
+ 0x12 => :LC_SUB_FRAMEWORK,
+ 0x13 => :LC_SUB_UMBRELLA,
+ 0x14 => :LC_SUB_CLIENT,
+ 0x15 => :LC_SUB_LIBRARY,
+ 0x16 => :LC_TWOLEVEL_HINTS,
+ 0x17 => :LC_PREBIND_CKSUM,
+ (0x18 | LC_REQ_DYLD) => :LC_LOAD_WEAK_DYLIB,
+ 0x19 => :LC_SEGMENT_64,
+ 0x1a => :LC_ROUTINES_64,
+ 0x1b => :LC_UUID,
+ (0x1c | LC_REQ_DYLD) => :LC_RPATH,
+ 0x1d => :LC_CODE_SIGNATURE,
+ 0x1e => :LC_SEGMENT_SPLIT_INFO,
+ (0x1f | LC_REQ_DYLD) => :LC_REEXPORT_DYLIB,
+ 0x20 => :LC_LAZY_LOAD_DYLIB,
+ 0x21 => :LC_ENCRYPTION_INFO,
+ 0x22 => :LC_DYLD_INFO,
+ (0x22 | LC_REQ_DYLD) => :LC_DYLD_INFO_ONLY,
+ (0x23 | LC_REQ_DYLD) => :LC_LOAD_UPWARD_DYLIB,
+ 0x24 => :LC_VERSION_MIN_MACOSX,
+ 0x25 => :LC_VERSION_MIN_IPHONEOS,
+ 0x26 => :LC_FUNCTION_STARTS,
+ 0x27 => :LC_DYLD_ENVIRONMENT,
+ (0x28 | LC_REQ_DYLD) => :LC_MAIN,
+ 0x29 => :LC_DATA_IN_CODE,
+ 0x2a => :LC_SOURCE_VERSION,
+ 0x2b => :LC_DYLIB_CODE_SIGN_DRS,
+ 0x2c => :LC_ENCRYPTION_INFO_64,
+ 0x2d => :LC_LINKER_OPTION,
+ 0x2e => :LC_LINKER_OPTIMIZATION_HINT,
+ 0x2f => :LC_VERSION_MIN_TVOS,
+ 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 = [
+ :LC_LOAD_DYLIB,
+ :LC_LOAD_WEAK_DYLIB,
+ :LC_REEXPORT_DYLIB,
+ :LC_LAZY_LOAD_DYLIB,
+ :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",
+ # "obsolete"
+ :LC_SYMSEG => "SymsegCommand",
+ # seems obsolete, but not documented as such
+ :LC_THREAD => "ThreadCommand",
+ :LC_UNIXTHREAD => "ThreadCommand",
+ # "obsolete"
+ :LC_LOADFVMLIB => "FvmlibCommand",
+ # "obsolete"
+ :LC_IDFVMLIB => "FvmlibCommand",
+ # "obsolete"
+ :LC_IDENT => "IdentCommand",
+ # "reserved for internal use only"
+ :LC_FVMFILE => "FvmfileCommand",
+ # "reserved for internal use only", no public struct
+ :LC_PREPAGE => "LoadCommand",
+ :LC_DYSYMTAB => "DysymtabCommand",
+ :LC_LOAD_DYLIB => "DylibCommand",
+ :LC_ID_DYLIB => "DylibCommand",
+ :LC_LOAD_DYLINKER => "DylinkerCommand",
+ :LC_ID_DYLINKER => "DylinkerCommand",
+ :LC_PREBOUND_DYLIB => "PreboundDylibCommand",
+ :LC_ROUTINES => "RoutinesCommand",
+ :LC_SUB_FRAMEWORK => "SubFrameworkCommand",
+ :LC_SUB_UMBRELLA => "SubUmbrellaCommand",
+ :LC_SUB_CLIENT => "SubClientCommand",
+ :LC_SUB_LIBRARY => "SubLibraryCommand",
+ :LC_TWOLEVEL_HINTS => "TwolevelHintsCommand",
+ :LC_PREBIND_CKSUM => "PrebindCksumCommand",
+ :LC_LOAD_WEAK_DYLIB => "DylibCommand",
+ :LC_SEGMENT_64 => "SegmentCommand64",
+ :LC_ROUTINES_64 => "RoutinesCommand64",
+ :LC_UUID => "UUIDCommand",
+ :LC_RPATH => "RpathCommand",
+ :LC_CODE_SIGNATURE => "LinkeditDataCommand",
+ :LC_SEGMENT_SPLIT_INFO => "LinkeditDataCommand",
+ :LC_REEXPORT_DYLIB => "DylibCommand",
+ :LC_LAZY_LOAD_DYLIB => "DylibCommand",
+ :LC_ENCRYPTION_INFO => "EncryptionInfoCommand",
+ :LC_DYLD_INFO => "DyldInfoCommand",
+ :LC_DYLD_INFO_ONLY => "DyldInfoCommand",
+ :LC_LOAD_UPWARD_DYLIB => "DylibCommand",
+ :LC_VERSION_MIN_MACOSX => "VersionMinCommand",
+ :LC_VERSION_MIN_IPHONEOS => "VersionMinCommand",
+ :LC_FUNCTION_STARTS => "LinkeditDataCommand",
+ :LC_DYLD_ENVIRONMENT => "DylinkerCommand",
+ :LC_MAIN => "EntryPointCommand",
+ :LC_DATA_IN_CODE => "LinkeditDataCommand",
+ :LC_SOURCE_VERSION => "SourceVersionCommand",
+ :LC_DYLIB_CODE_SIGN_DRS => "LinkeditDataCommand",
+ :LC_ENCRYPTION_INFO_64 => "EncryptionInfoCommand64",
+ :LC_LINKER_OPTION => "LinkerOptionCommand",
+ :LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand",
+ :LC_VERSION_MIN_TVOS => "VersionMinCommand",
+ :LC_VERSION_MIN_WATCHOS => "VersionMinCommand",
+ }.freeze
+
+ # association of segment name symbols to names
+ # @api private
+ SEGMENT_NAMES = {
+ :SEG_PAGEZERO => "__PAGEZERO",
+ :SEG_TEXT => "__TEXT",
+ :SEG_DATA => "__DATA",
+ :SEG_OBJC => "__OBJC",
+ :SEG_ICON => "__ICON",
+ :SEG_LINKEDIT => "__LINKEDIT",
+ :SEG_UNIXSTACK => "__UNIXSTACK",
+ :SEG_IMPORT => "__IMPORT",
+ }.freeze
+
+ # association of segment flag symbols to values
+ # @api private
+ SEGMENT_FLAGS = {
+ :SG_HIGHVM => 0x1,
+ :SG_FVMLIB => 0x2,
+ :SG_NORELOC => 0x4,
+ :SG_PROTECTED_VERSION_1 => 0x8,
+ }.freeze
+
+ # Mach-O load command structure
+ # This is the most generic load command - only cmd ID and size are
+ # represented, and no actual data. Used when a more specific class
+ # isn't available/implemented.
+ class LoadCommand < MachOStructure
+ # @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
+
+ # @return [Fixnum] the size of the load command, in bytes
+ attr_reader :cmdsize
+
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 8
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 8
- # 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(view)
- bin = view.raw_data.slice(view.offset, bytesize)
- format = Utils.specialize_format(self::FORMAT, view.endianness)
+ # Instantiates a new LoadCommand given a view into its origin Mach-O
+ # @param view [MachO::MachOView] the load command's raw view
+ # @return [LoadCommand] the new load command
+ # @api private
+ 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
+ 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)
+ # 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]
+ klass = LoadCommands.const_get LC_STRUCTURES[cmd_sym]
+ cmd = LOAD_COMMAND_CONSTANTS[cmd_sym]
- # cmd will be filled in, view and cmdsize will be left unpopulated
- klass_arity = klass.instance_method(:initialize).arity - 3
+ # 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
+ raise LoadCommandCreationArityError.new(cmd_sym, klass_arity, args.size) if klass_arity != args.size
- klass.new(nil, cmd, nil, *args)
- end
+ klass.new(nil, cmd, nil, *args)
+ end
- # @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(view, cmd, cmdsize)
- @view = view
- @cmd = cmd
- @cmdsize = cmdsize
- end
+ # @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(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
+ # @return [Boolean] whether the load command can be serialized
+ 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
+ # @param context [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 [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
+ # @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
- type.to_s
- end
+ # @return [String] a string representation of the load command's
+ # identifying number
+ def to_s
+ type.to_s
+ end
- # Represents a Load Command string. A rough analogue to the lc_str
- # struct used internally by OS X. This class allows ruby-macho to
- # pretend that strings stored in LCs are immediately available without
- # explicit operations on the raw Mach-O data.
- class LCStr
- # @param lc [MachO::LoadCommand] the load command
- # @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(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
+ # Represents a Load Command string. A rough analogue to the lc_str
+ # struct used internally by OS X. This class allows ruby-macho to
+ # pretend that strings stored in LCs are immediately available without
+ # explicit operations on the raw Mach-O data.
+ class LCStr
+ # @param lc [LoadCommand] the load command
+ # @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(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
- end
- # @return [String] a string representation of the LCStr
- def to_s
- @string
+ # @return [String] a string representation of the LCStr
+ def to_s
+ @string
+ end
+
+ # @return [Fixnum] the offset to the beginning of the string in the
+ # load command
+ def to_i
+ @string_offset
+ end
end
- # @return [Fixnum] the offset to the beginning of the string in the load command
- def to_i
- @string_offset
+ # 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 [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
- # 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
+ # A load command containing a single 128-bit unique random number
+ # identifying an object produced by static link editor. Corresponds to
+ # LC_UUID.
+ class UUIDCommand < LoadCommand
+ # @return [Array<Fixnum>] the UUID
+ attr_reader :uuid
- # @return [Fixnum] the constant alignment value used to pad the serialized load command
- attr_reader :alignment
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2a16".freeze
- # @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
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 24
- # @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
+ def initialize(view, cmd, cmdsize, uuid)
+ super(view, cmd, cmdsize)
+ @uuid = uuid.unpack("C16") # re-unpack for the actual UUID array
end
- end
- end
-
- # A load command containing a single 128-bit unique random number identifying
- # an object produced by static link editor. Corresponds to LC_UUID.
- class UUIDCommand < LoadCommand
- # @return [Array<Fixnum>] the UUID
- attr_reader :uuid
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2a16".freeze
-
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 24
+ # @return [String] a string representation of the UUID
+ def uuid_string
+ hexes = uuid.map { |e| "%02x" % e }
+ segs = [
+ hexes[0..3].join, hexes[4..5].join, hexes[6..7].join,
+ hexes[8..9].join, hexes[10..15].join
+ ]
- # @api private
- def initialize(view, cmd, cmdsize, uuid)
- super(view, cmd, cmdsize)
- @uuid = uuid.unpack("C16") # re-unpack for the actual UUID array
+ segs.join("-")
+ end
end
- # @return [String] a string representation of the UUID
- def uuid_string
- hexes = uuid.map { |e| "%02x" % e }
- segs = [
- hexes[0..3].join, hexes[4..5].join, hexes[6..7].join,
- hexes[8..9].join, hexes[10..15].join
- ]
+ # A load command indicating that part of this file is to be mapped into
+ # the task's address space. Corresponds to LC_SEGMENT.
+ class SegmentCommand < LoadCommand
+ # @return [String] the name of the segment
+ attr_reader :segname
- segs.join("-")
- end
- end
+ # @return [Fixnum] the memory address of the segment
+ attr_reader :vmaddr
- # A load command indicating that part of this file is to be mapped into
- # the task's address space. Corresponds to LC_SEGMENT.
- class SegmentCommand < LoadCommand
- # @return [String] the name of the segment
- attr_reader :segname
+ # @return [Fixnum] the memory size of the segment
+ attr_reader :vmsize
- # @return [Fixnum] the memory address of the segment
- attr_reader :vmaddr
+ # @return [Fixnum] the file offset of the segment
+ attr_reader :fileoff
- # @return [Fixnum] the memory size of the segment
- attr_reader :vmsize
+ # @return [Fixnum] the amount to map from the file
+ attr_reader :filesize
- # @return [Fixnum] the file offset of the segment
- attr_reader :fileoff
+ # @return [Fixnum] the maximum VM protection
+ attr_reader :maxprot
- # @return [Fixnum] the amount to map from the file
- attr_reader :filesize
+ # @return [Fixnum] the initial VM protection
+ attr_reader :initprot
- # @return [Fixnum] the maximum VM protection
- attr_reader :maxprot
+ # @return [Fixnum] the number of sections in the segment
+ attr_reader :nsects
- # @return [Fixnum] the initial VM protection
- attr_reader :initprot
+ # @return [Fixnum] any flags associated with the segment
+ attr_reader :flags
- # @return [Fixnum] the number of sections in the segment
- attr_reader :nsects
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2a16L=4l=2L=2".freeze
- # @return [Fixnum] any flags associated with the segment
- attr_reader :flags
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 56
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2a16L=4l=2L=2".freeze
+ # @api private
+ 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
+ @fileoff = fileoff
+ @filesize = filesize
+ @maxprot = maxprot
+ @initprot = initprot
+ @nsects = nsects
+ @flags = flags
+ end
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 56
+ # All sections referenced within this segment.
+ # @return [Array<MachO::Sections::Section>] if the Mach-O is 32-bit
+ # @return [Array<MachO::Sections::Section64>] if the Mach-O is 64-bit
+ def sections
+ klass = case self
+ when SegmentCommand64
+ MachO::Sections::Section64
+ when SegmentCommand
+ MachO::Sections::Section
+ end
- # @api private
- 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
- @fileoff = fileoff
- @filesize = filesize
- @maxprot = maxprot
- @initprot = initprot
- @nsects = nsects
- @flags = flags
- end
+ offset = view.offset + self.class.bytesize
+ length = nsects * klass.bytesize
- # 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
+ bins = view.raw_data[offset, length]
+ bins.unpack("a#{klass.bytesize}" * nsects).map do |bin|
+ klass.new_from_bin(view.endianness, bin)
+ end
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)
+ # @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
end
- # @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
- end
-
- # 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 < SegmentCommand
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2a16Q=4l=2L=2".freeze
+ # 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 < SegmentCommand
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2a16Q=4l=2L=2".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 72
- end
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 72
+ end
- # A load command representing some aspect of shared libraries, depending
- # on filetype. Corresponds to LC_ID_DYLIB, LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB,
- # and LC_REEXPORT_DYLIB.
- class DylibCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the library's path name as an LCStr
- attr_reader :name
+ # A load command representing some aspect of shared libraries, depending
+ # on filetype. Corresponds to LC_ID_DYLIB, LC_LOAD_DYLIB,
+ # LC_LOAD_WEAK_DYLIB, and LC_REEXPORT_DYLIB.
+ class DylibCommand < LoadCommand
+ # @return [LCStr] the library's path
+ # name as an LCStr
+ attr_reader :name
- # @return [Fixnum] the library's build time stamp
- attr_reader :timestamp
+ # @return [Fixnum] the library's build time stamp
+ attr_reader :timestamp
- # @return [Fixnum] the library's current version number
- attr_reader :current_version
+ # @return [Fixnum] the library's current version number
+ attr_reader :current_version
- # @return [Fixnum] the library's compatibility version number
- attr_reader :compatibility_version
+ # @return [Fixnum] the library's compatibility version number
+ attr_reader :compatibility_version
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=6".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=6".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 24
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 24
- # @api private
- 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
+ # @api private
+ 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
+ # @param context [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
- end
- # A load command representing some aspect of the dynamic linker, depending
- # on filetype. Corresponds to LC_ID_DYLINKER, LC_LOAD_DYLINKER, and
- # LC_DYLD_ENVIRONMENT.
- class DylinkerCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the dynamic linker's path name as an LCStr
- attr_reader :name
+ # A load command representing some aspect of the dynamic linker, depending
+ # on filetype. Corresponds to LC_ID_DYLINKER, LC_LOAD_DYLINKER, and
+ # LC_DYLD_ENVIRONMENT.
+ class DylinkerCommand < LoadCommand
+ # @return [LCStr] the dynamic linker's
+ # path name as an LCStr
+ attr_reader :name
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, name)
- super(view, cmd, cmdsize)
- @name = LCStr.new(self, name)
- end
+ # @api private
+ 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
+ # @param context [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
- end
- # A load command used to indicate dynamic libraries used in prebinding.
- # Corresponds to LC_PREBOUND_DYLIB.
- class PreboundDylibCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the library's path name as an LCStr
- attr_reader :name
+ # A load command used to indicate dynamic libraries used in prebinding.
+ # Corresponds to LC_PREBOUND_DYLIB.
+ class PreboundDylibCommand < LoadCommand
+ # @return [LCStr] the library's path
+ # name as an LCStr
+ attr_reader :name
- # @return [Fixnum] the number of modules in the library
- attr_reader :nmodules
+ # @return [Fixnum] the number of modules in the library
+ attr_reader :nmodules
- # @return [Fixnum] a bit vector of linked modules
- attr_reader :linked_modules
+ # @return [Fixnum] a bit vector of linked modules
+ attr_reader :linked_modules
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=5".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=5".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 20
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 20
- # @api private
- def initialize(view, cmd, cmdsize, name, nmodules, linked_modules)
- super(view, cmd, cmdsize)
- @name = LCStr.new(self, name)
- @nmodules = nmodules
- @linked_modules = linked_modules
+ # @api private
+ 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
end
- end
- # 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
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2".freeze
+ # A load command used to represent threads.
+ # @note cctools-870 and onwards have all fields of thread_command commented
+ # out except the common ones (cmd, cmdsize)
+ class ThreadCommand < LoadCommand
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 8
- end
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 8
+ end
- # A load command containing the address of the dynamic shared library
- # initialization routine and an index into the module table for the module
- # that defines the routine. Corresponds to LC_ROUTINES.
- class RoutinesCommand < LoadCommand
- # @return [Fixnum] the address of the initialization routine
- attr_reader :init_address
+ # A load command containing the address of the dynamic shared library
+ # initialization routine and an index into the module table for the module
+ # that defines the routine. Corresponds to LC_ROUTINES.
+ class RoutinesCommand < LoadCommand
+ # @return [Fixnum] the address of the initialization routine
+ attr_reader :init_address
- # @return [Fixnum] the index into the module table that the init routine is defined in
- attr_reader :init_module
+ # @return [Fixnum] the index into the module table that the init routine
+ # is defined in
+ attr_reader :init_module
- # @return [void]
- attr_reader :reserved1
+ # @return [void]
+ attr_reader :reserved1
- # @return [void]
- attr_reader :reserved2
+ # @return [void]
+ attr_reader :reserved2
- # @return [void]
- attr_reader :reserved3
+ # @return [void]
+ attr_reader :reserved3
- # @return [void]
- attr_reader :reserved4
+ # @return [void]
+ attr_reader :reserved4
- # @return [void]
- attr_reader :reserved5
+ # @return [void]
+ attr_reader :reserved5
- # @return [void]
- attr_reader :reserved6
+ # @return [void]
+ attr_reader :reserved6
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=10".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=10".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 40
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 40
- # @api private
- def initialize(view, cmd, cmdsize, init_address, init_module, reserved1,
- reserved2, reserved3, reserved4, reserved5, reserved6)
- super(view, cmd, cmdsize)
- @init_address = init_address
- @init_module = init_module
- @reserved1 = reserved1
- @reserved2 = reserved2
- @reserved3 = reserved3
- @reserved4 = reserved4
- @reserved5 = reserved5
- @reserved6 = reserved6
+ # @api private
+ def initialize(view, cmd, cmdsize, init_address, init_module, reserved1,
+ reserved2, reserved3, reserved4, reserved5, reserved6)
+ super(view, cmd, cmdsize)
+ @init_address = init_address
+ @init_module = init_module
+ @reserved1 = reserved1
+ @reserved2 = reserved2
+ @reserved3 = reserved3
+ @reserved4 = reserved4
+ @reserved5 = reserved5
+ @reserved6 = reserved6
+ end
end
- end
- # A load command containing the address of the dynamic shared library
- # initialization routine and an index into the module table for the module
- # that defines the routine. Corresponds to LC_ROUTINES_64.
- class RoutinesCommand64 < RoutinesCommand
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2Q=8".freeze
+ # A load command containing the address of the dynamic shared library
+ # initialization routine and an index into the module table for the module
+ # that defines the routine. Corresponds to LC_ROUTINES_64.
+ class RoutinesCommand64 < RoutinesCommand
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2Q=8".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 72
- end
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 72
+ end
- # A load command signifying membership of a subframework containing the name
- # of an umbrella framework. Corresponds to LC_SUB_FRAMEWORK.
- class SubFrameworkCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the umbrella framework name as an LCStr
- attr_reader :umbrella
+ # A load command signifying membership of a subframework containing the name
+ # of an umbrella framework. Corresponds to LC_SUB_FRAMEWORK.
+ class SubFrameworkCommand < LoadCommand
+ # @return [LCStr] the umbrella framework name as an LCStr
+ attr_reader :umbrella
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, umbrella)
- super(view, cmd, cmdsize)
- @umbrella = LCStr.new(self, umbrella)
+ # @api private
+ def initialize(view, cmd, cmdsize, umbrella)
+ super(view, cmd, cmdsize)
+ @umbrella = LCStr.new(self, umbrella)
+ end
end
- end
- # A load command signifying membership of a subumbrella containing the name
- # of an umbrella framework. Corresponds to LC_SUB_UMBRELLA.
- class SubUmbrellaCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the subumbrella framework name as an LCStr
- attr_reader :sub_umbrella
+ # A load command signifying membership of a subumbrella containing the name
+ # of an umbrella framework. Corresponds to LC_SUB_UMBRELLA.
+ class SubUmbrellaCommand < LoadCommand
+ # @return [LCStr] the subumbrella framework name as an LCStr
+ attr_reader :sub_umbrella
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, sub_umbrella)
- super(view, cmd, cmdsize)
- @sub_umbrella = LCStr.new(self, sub_umbrella)
+ # @api private
+ def initialize(view, cmd, cmdsize, sub_umbrella)
+ super(view, cmd, cmdsize)
+ @sub_umbrella = LCStr.new(self, sub_umbrella)
+ end
end
- end
- # A load command signifying a sublibrary of a shared library. Corresponds
- # to LC_SUB_LIBRARY.
- class SubLibraryCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the sublibrary name as an LCStr
- attr_reader :sub_library
+ # A load command signifying a sublibrary of a shared library. Corresponds
+ # to LC_SUB_LIBRARY.
+ class SubLibraryCommand < LoadCommand
+ # @return [LCStr] the sublibrary name as an LCStr
+ attr_reader :sub_library
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, sub_library)
- super(view, cmd, cmdsize)
- @sub_library = LCStr.new(self, sub_library)
+ # @api private
+ def initialize(view, cmd, cmdsize, sub_library)
+ super(view, cmd, cmdsize)
+ @sub_library = LCStr.new(self, sub_library)
+ end
end
- end
- # A load command signifying a shared library that is a subframework of
- # an umbrella framework. Corresponds to LC_SUB_CLIENT.
- class SubClientCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the subclient name as an LCStr
- attr_reader :sub_client
+ # A load command signifying a shared library that is a subframework of
+ # an umbrella framework. Corresponds to LC_SUB_CLIENT.
+ class SubClientCommand < LoadCommand
+ # @return [LCStr] the subclient name as an LCStr
+ attr_reader :sub_client
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, sub_client)
- super(view, cmd, cmdsize)
- @sub_client = LCStr.new(self, sub_client)
+ # @api private
+ def initialize(view, cmd, cmdsize, sub_client)
+ super(view, cmd, cmdsize)
+ @sub_client = LCStr.new(self, sub_client)
+ end
end
- end
- # A load command containing the offsets and sizes of the link-edit 4.3BSD
- # "stab" style symbol table information. Corresponds to LC_SYMTAB.
- class SymtabCommand < LoadCommand
- # @return [Fixnum] the symbol table's offset
- attr_reader :symoff
+ # A load command containing the offsets and sizes of the link-edit 4.3BSD
+ # "stab" style symbol table information. Corresponds to LC_SYMTAB.
+ class SymtabCommand < LoadCommand
+ # @return [Fixnum] the symbol table's offset
+ attr_reader :symoff
- # @return [Fixnum] the number of symbol table entries
- attr_reader :nsyms
+ # @return [Fixnum] the number of symbol table entries
+ attr_reader :nsyms
- # @return the string table's offset
- attr_reader :stroff
+ # @return the string table's offset
+ attr_reader :stroff
- # @return the string table size in bytes
- attr_reader :strsize
+ # @return the string table size in bytes
+ attr_reader :strsize
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=6".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=6".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 24
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 24
- # @api private
- def initialize(view, cmd, cmdsize, symoff, nsyms, stroff, strsize)
- super(view, cmd, cmdsize)
- @symoff = symoff
- @nsyms = nsyms
- @stroff = stroff
- @strsize = strsize
+ # @api private
+ def initialize(view, cmd, cmdsize, symoff, nsyms, stroff, strsize)
+ super(view, cmd, cmdsize)
+ @symoff = symoff
+ @nsyms = nsyms
+ @stroff = stroff
+ @strsize = strsize
+ end
end
- end
- # A load command containing symbolic information needed to support data
- # structures used by the dynamic link editor. Corresponds to LC_DYSYMTAB.
- class DysymtabCommand < LoadCommand
- # @return [Fixnum] the index to local symbols
- attr_reader :ilocalsym
+ # A load command containing symbolic information needed to support data
+ # structures used by the dynamic link editor. Corresponds to LC_DYSYMTAB.
+ class DysymtabCommand < LoadCommand
+ # @return [Fixnum] the index to local symbols
+ attr_reader :ilocalsym
- # @return [Fixnum] the number of local symbols
- attr_reader :nlocalsym
+ # @return [Fixnum] the number of local symbols
+ attr_reader :nlocalsym
- # @return [Fixnum] the index to externally defined symbols
- attr_reader :iextdefsym
+ # @return [Fixnum] the index to externally defined symbols
+ attr_reader :iextdefsym
- # @return [Fixnum] the number of externally defined symbols
- attr_reader :nextdefsym
+ # @return [Fixnum] the number of externally defined symbols
+ attr_reader :nextdefsym
- # @return [Fixnum] the index to undefined symbols
- attr_reader :iundefsym
+ # @return [Fixnum] the index to undefined symbols
+ attr_reader :iundefsym
- # @return [Fixnum] the number of undefined symbols
- attr_reader :nundefsym
+ # @return [Fixnum] the number of undefined symbols
+ attr_reader :nundefsym
- # @return [Fixnum] the file offset to the table of contents
- attr_reader :tocoff
+ # @return [Fixnum] the file offset to the table of contents
+ attr_reader :tocoff
- # @return [Fixnum] the number of entries in the table of contents
- attr_reader :ntoc
+ # @return [Fixnum] the number of entries in the table of contents
+ attr_reader :ntoc
- # @return [Fixnum] the file offset to the module table
- attr_reader :modtaboff
+ # @return [Fixnum] the file offset to the module table
+ attr_reader :modtaboff
- # @return [Fixnum] the number of entries in the module table
- attr_reader :nmodtab
+ # @return [Fixnum] the number of entries in the module table
+ attr_reader :nmodtab
- # @return [Fixnum] the file offset to the referenced symbol table
- attr_reader :extrefsymoff
+ # @return [Fixnum] the file offset to the referenced symbol table
+ attr_reader :extrefsymoff
- # @return [Fixnum] the number of entries in the referenced symbol table
- attr_reader :nextrefsyms
+ # @return [Fixnum] the number of entries in the referenced symbol table
+ attr_reader :nextrefsyms
- # @return [Fixnum] the file offset to the indirect symbol table
- attr_reader :indirectsymoff
+ # @return [Fixnum] the file offset to the indirect symbol table
+ attr_reader :indirectsymoff
- # @return [Fixnum] the number of entries in the indirect symbol table
- attr_reader :nindirectsyms
+ # @return [Fixnum] the number of entries in the indirect symbol table
+ attr_reader :nindirectsyms
- # @return [Fixnum] the file offset to the external relocation entries
- attr_reader :extreloff
+ # @return [Fixnum] the file offset to the external relocation entries
+ attr_reader :extreloff
- # @return [Fixnum] the number of external relocation entries
- attr_reader :nextrel
+ # @return [Fixnum] the number of external relocation entries
+ attr_reader :nextrel
- # @return [Fixnum] the file offset to the local relocation entries
- attr_reader :locreloff
+ # @return [Fixnum] the file offset to the local relocation entries
+ attr_reader :locreloff
- # @return [Fixnum] the number of local relocation entries
- attr_reader :nlocrel
+ # @return [Fixnum] the number of local relocation entries
+ attr_reader :nlocrel
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=20".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=20".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 80
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 80
- # ugh
- # @api private
- 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
- @nextdefsym = nextdefsym
- @iundefsym = iundefsym
- @nundefsym = nundefsym
- @tocoff = tocoff
- @ntoc = ntoc
- @modtaboff = modtaboff
- @nmodtab = nmodtab
- @extrefsymoff = extrefsymoff
- @nextrefsyms = nextrefsyms
- @indirectsymoff = indirectsymoff
- @nindirectsyms = nindirectsyms
- @extreloff = extreloff
- @nextrel = nextrel
- @locreloff = locreloff
- @nlocrel = nlocrel
+ # ugh
+ # @api private
+ 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
+ @nextdefsym = nextdefsym
+ @iundefsym = iundefsym
+ @nundefsym = nundefsym
+ @tocoff = tocoff
+ @ntoc = ntoc
+ @modtaboff = modtaboff
+ @nmodtab = nmodtab
+ @extrefsymoff = extrefsymoff
+ @nextrefsyms = nextrefsyms
+ @indirectsymoff = indirectsymoff
+ @nindirectsyms = nindirectsyms
+ @extreloff = extreloff
+ @nextrel = nextrel
+ @locreloff = locreloff
+ @nlocrel = nlocrel
+ end
end
- end
- # A load command containing the offset and number of hints in the two-level
- # namespace lookup hints table. Corresponds to LC_TWOLEVEL_HINTS.
- class TwolevelHintsCommand < LoadCommand
- # @return [Fixnum] the offset to the hint table
- attr_reader :htoffset
+ # A load command containing the offset and number of hints in the two-level
+ # namespace lookup hints table. Corresponds to LC_TWOLEVEL_HINTS.
+ class TwolevelHintsCommand < LoadCommand
+ # @return [Fixnum] the offset to the hint table
+ attr_reader :htoffset
- # @return [Fixnum] the number of hints in the hint table
- attr_reader :nhints
+ # @return [Fixnum] the number of hints in the hint table
+ attr_reader :nhints
- # @return [MachO::TwolevelHintsCommand::TwolevelHintTable] the hint table
- attr_reader :table
+ # @return [TwolevelHintsTable]
+ # the hint table
+ attr_reader :table
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=4".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=4".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- # @api private
- def initialize(view, cmd, cmdsize, htoffset, nhints)
- super(view, cmd, cmdsize)
- @htoffset = htoffset
- @nhints = nhints
- @table = TwolevelHintsTable.new(view, htoffset, nhints)
- end
+ # @api private
+ 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
+ # A representation of the two-level namespace lookup hints table exposed
+ # by a {TwolevelHintsCommand} (`LC_TWOLEVEL_HINTS`).
+ class TwolevelHintsTable
+ # @return [Array<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)
+ # @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
+ @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
+ # 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
+ # @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
+ # @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
- end
- # A load command containing the value of the original checksum for prebound
- # files, or zero. Corresponds to LC_PREBIND_CKSUM.
- class PrebindCksumCommand < LoadCommand
- # @return [Fixnum] the checksum or 0
- attr_reader :cksum
+ # A load command containing the value of the original checksum for prebound
+ # files, or zero. Corresponds to LC_PREBIND_CKSUM.
+ class PrebindCksumCommand < LoadCommand
+ # @return [Fixnum] the checksum or 0
+ attr_reader :cksum
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, cksum)
- super(view, cmd, cmdsize)
- @cksum = cksum
+ # @api private
+ def initialize(view, cmd, cmdsize, cksum)
+ super(view, cmd, cmdsize)
+ @cksum = cksum
+ end
end
- end
- # A load command representing an rpath, which specifies a path that should
- # be added to the current run path used to find @rpath prefixed dylibs.
- # Corresponds to LC_RPATH.
- class RpathCommand < LoadCommand
- # @return [MachO::LoadCommand::LCStr] the path to add to the run path as an LCStr
- attr_reader :path
+ # A load command representing an rpath, which specifies a path that should
+ # be added to the current run path used to find @rpath prefixed dylibs.
+ # Corresponds to LC_RPATH.
+ class RpathCommand < LoadCommand
+ # @return [LCStr] the path to add to the run path as an LCStr
+ attr_reader :path
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, path)
- super(view, cmd, cmdsize)
- @path = LCStr.new(self, path)
- end
+ # @api private
+ 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
+ # @param context [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
- end
- # A load command representing the offsets and sizes of a blob of data in
- # the __LINKEDIT segment. Corresponds to LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO,
- # LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS, and LC_LINKER_OPTIMIZATION_HINT.
- class LinkeditDataCommand < LoadCommand
- # @return [Fixnum] offset to the data in the __LINKEDIT segment
- attr_reader :dataoff
+ # A load command representing the offsets and sizes of a blob of data in
+ # the __LINKEDIT segment. Corresponds to LC_CODE_SIGNATURE,
+ # LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE,
+ # LC_DYLIB_CODE_SIGN_DRS, and LC_LINKER_OPTIMIZATION_HINT.
+ class LinkeditDataCommand < LoadCommand
+ # @return [Fixnum] offset to the data in the __LINKEDIT segment
+ attr_reader :dataoff
- # @return [Fixnum] size of the data in the __LINKEDIT segment
- attr_reader :datasize
+ # @return [Fixnum] size of the data in the __LINKEDIT segment
+ attr_reader :datasize
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=4".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=4".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- # @api private
- def initialize(view, cmd, cmdsize, dataoff, datasize)
- super(view, cmd, cmdsize)
- @dataoff = dataoff
- @datasize = datasize
+ # @api private
+ def initialize(view, cmd, cmdsize, dataoff, datasize)
+ super(view, cmd, cmdsize)
+ @dataoff = dataoff
+ @datasize = datasize
+ end
end
- end
- # A load command representing the offset to and size of an encrypted
- # segment. Corresponds to LC_ENCRYPTION_INFO.
- class EncryptionInfoCommand < LoadCommand
- # @return [Fixnum] the offset to the encrypted segment
- attr_reader :cryptoff
+ # A load command representing the offset to and size of an encrypted
+ # segment. Corresponds to LC_ENCRYPTION_INFO.
+ class EncryptionInfoCommand < LoadCommand
+ # @return [Fixnum] the offset to the encrypted segment
+ attr_reader :cryptoff
- # @return [Fixnum] the size of the encrypted segment
- attr_reader :cryptsize
+ # @return [Fixnum] the size of the encrypted segment
+ attr_reader :cryptsize
- # @return [Fixnum] the encryption system, or 0 if not encrypted yet
- attr_reader :cryptid
+ # @return [Fixnum] the encryption system, or 0 if not encrypted yet
+ attr_reader :cryptid
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=5".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=5".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 20
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 20
- # @api private
- def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid)
- super(view, cmd, cmdsize)
- @cryptoff = cryptoff
- @cryptsize = cryptsize
- @cryptid = cryptid
+ # @api private
+ def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid)
+ super(view, cmd, cmdsize)
+ @cryptoff = cryptoff
+ @cryptsize = cryptsize
+ @cryptid = cryptid
+ end
end
- end
- # A load command representing the offset to and size of an encrypted
- # segment. Corresponds to LC_ENCRYPTION_INFO_64.
- class EncryptionInfoCommand64 < LoadCommand
- # @return [Fixnum] the offset to the encrypted segment
- attr_reader :cryptoff
+ # A load command representing the offset to and size of an encrypted
+ # segment. Corresponds to LC_ENCRYPTION_INFO_64.
+ class EncryptionInfoCommand64 < LoadCommand
+ # @return [Fixnum] the offset to the encrypted segment
+ attr_reader :cryptoff
- # @return [Fixnum] the size of the encrypted segment
- attr_reader :cryptsize
+ # @return [Fixnum] the size of the encrypted segment
+ attr_reader :cryptsize
- # @return [Fixnum] the encryption system, or 0 if not encrypted yet
- attr_reader :cryptid
+ # @return [Fixnum] the encryption system, or 0 if not encrypted yet
+ attr_reader :cryptid
- # @return [Fixnum] 64-bit padding value
- attr_reader :pad
+ # @return [Fixnum] 64-bit padding value
+ attr_reader :pad
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=6".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=6".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 24
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 24
- # @api private
- def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid, pad)
- super(view, cmd, cmdsize)
- @cryptoff = cryptoff
- @cryptsize = cryptsize
- @cryptid = cryptid
- @pad = pad
+ # @api private
+ def initialize(view, cmd, cmdsize, cryptoff, cryptsize, cryptid, pad)
+ super(view, cmd, cmdsize)
+ @cryptoff = cryptoff
+ @cryptsize = cryptsize
+ @cryptid = cryptid
+ @pad = pad
+ end
end
- end
- # A load command containing the minimum OS version on which the binary
- # was built to run. Corresponds to LC_VERSION_MIN_MACOSX and LC_VERSION_MIN_IPHONEOS.
- class VersionMinCommand < LoadCommand
- # @return [Fixnum] the version X.Y.Z packed as x16.y8.z8
- attr_reader :version
+ # A load command containing the minimum OS version on which the binary
+ # was built to run. Corresponds to LC_VERSION_MIN_MACOSX and
+ # LC_VERSION_MIN_IPHONEOS.
+ class VersionMinCommand < LoadCommand
+ # @return [Fixnum] the version X.Y.Z packed as x16.y8.z8
+ attr_reader :version
- # @return [Fixnum] the SDK version X.Y.Z packed as x16.y8.z8
- attr_reader :sdk
+ # @return [Fixnum] the SDK version X.Y.Z packed as x16.y8.z8
+ attr_reader :sdk
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=4".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=4".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- # @api private
- def initialize(view, cmd, cmdsize, version, sdk)
- super(view, cmd, cmdsize)
- @version = version
- @sdk = sdk
- end
+ # @api private
+ def initialize(view, cmd, cmdsize, version, sdk)
+ super(view, cmd, cmdsize)
+ @version = version
+ @sdk = sdk
+ end
- # A string representation of the binary's minimum OS version.
- # @return [String] a string representing the minimum OS version.
- def version_string
- binary = "%032b" % version
- segs = [
- binary[0..15], binary[16..23], binary[24..31]
- ].map { |s| s.to_i(2) }
+ # A string representation of the binary's minimum OS version.
+ # @return [String] a string representing the minimum OS version.
+ def version_string
+ binary = "%032b" % version
+ segs = [
+ binary[0..15], binary[16..23], binary[24..31]
+ ].map { |s| s.to_i(2) }
- segs.join(".")
- end
+ segs.join(".")
+ end
- # A string representation of the binary's SDK version.
- # @return [String] a string representing the SDK version.
- def sdk_string
- binary = "%032b" % sdk
- segs = [
- binary[0..15], binary[16..23], binary[24..31]
- ].map { |s| s.to_i(2) }
+ # A string representation of the binary's SDK version.
+ # @return [String] a string representing the SDK version.
+ def sdk_string
+ binary = "%032b" % sdk
+ segs = [
+ binary[0..15], binary[16..23], binary[24..31]
+ ].map { |s| s.to_i(2) }
- segs.join(".")
+ segs.join(".")
+ end
end
- end
- # A load command containing the file offsets and sizes of the new
- # compressed form of the information dyld needs to load the image.
- # Corresponds to LC_DYLD_INFO and LC_DYLD_INFO_ONLY.
- class DyldInfoCommand < LoadCommand
- # @return [Fixnum] the file offset to the rebase information
- attr_reader :rebase_off
+ # A load command containing the file offsets and sizes of the new
+ # compressed form of the information dyld needs to load the image.
+ # Corresponds to LC_DYLD_INFO and LC_DYLD_INFO_ONLY.
+ class DyldInfoCommand < LoadCommand
+ # @return [Fixnum] the file offset to the rebase information
+ attr_reader :rebase_off
- # @return [Fixnum] the size of the rebase information
- attr_reader :rebase_size
+ # @return [Fixnum] the size of the rebase information
+ attr_reader :rebase_size
- # @return [Fixnum] the file offset to the binding information
- attr_reader :bind_off
+ # @return [Fixnum] the file offset to the binding information
+ attr_reader :bind_off
- # @return [Fixnum] the size of the binding information
- attr_reader :bind_size
+ # @return [Fixnum] the size of the binding information
+ attr_reader :bind_size
- # @return [Fixnum] the file offset to the weak binding information
- attr_reader :weak_bind_off
+ # @return [Fixnum] the file offset to the weak binding information
+ attr_reader :weak_bind_off
- # @return [Fixnum] the size of the weak binding information
- attr_reader :weak_bind_size
+ # @return [Fixnum] the size of the weak binding information
+ attr_reader :weak_bind_size
- # @return [Fixnum] the file offset to the lazy binding information
- attr_reader :lazy_bind_off
+ # @return [Fixnum] the file offset to the lazy binding information
+ attr_reader :lazy_bind_off
- # @return [Fixnum] the size of the lazy binding information
- attr_reader :lazy_bind_size
+ # @return [Fixnum] the size of the lazy binding information
+ attr_reader :lazy_bind_size
- # @return [Fixnum] the file offset to the export information
- attr_reader :export_off
+ # @return [Fixnum] the file offset to the export information
+ attr_reader :export_off
- # @return [Fixnum] the size of the export information
- attr_reader :export_size
+ # @return [Fixnum] the size of the export information
+ attr_reader :export_size
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=12".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=12".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 48
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 48
- # @api private
- 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
- @bind_size = bind_size
- @weak_bind_off = weak_bind_off
- @weak_bind_size = weak_bind_size
- @lazy_bind_off = lazy_bind_off
- @lazy_bind_size = lazy_bind_size
- @export_off = export_off
- @export_size = export_size
+ # @api private
+ 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
+ @bind_size = bind_size
+ @weak_bind_off = weak_bind_off
+ @weak_bind_size = weak_bind_size
+ @lazy_bind_off = lazy_bind_off
+ @lazy_bind_size = lazy_bind_size
+ @export_off = export_off
+ @export_size = export_size
+ end
end
- end
- # A load command containing linker options embedded in object files.
- # Corresponds to LC_LINKER_OPTION.
- class LinkerOptionCommand < LoadCommand
- # @return [Fixnum] the number of strings
- attr_reader :count
+ # A load command containing linker options embedded in object files.
+ # Corresponds to LC_LINKER_OPTION.
+ class LinkerOptionCommand < LoadCommand
+ # @return [Fixnum] the number of strings
+ attr_reader :count
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=3".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=3".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 12
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 12
- # @api private
- def initialize(view, cmd, cmdsize, count)
- super(view, cmd, cmdsize)
- @count = count
+ # @api private
+ def initialize(view, cmd, cmdsize, count)
+ super(view, cmd, cmdsize)
+ @count = count
+ end
end
- end
- # A load command specifying the offset of main(). Corresponds to LC_MAIN.
- class EntryPointCommand < LoadCommand
- # @return [Fixnum] the file (__TEXT) offset of main()
- attr_reader :entryoff
+ # A load command specifying the offset of main(). Corresponds to LC_MAIN.
+ class EntryPointCommand < LoadCommand
+ # @return [Fixnum] the file (__TEXT) offset of main()
+ attr_reader :entryoff
- # @return [Fixnum] if not 0, the initial stack size.
- attr_reader :stacksize
+ # @return [Fixnum] if not 0, the initial stack size.
+ attr_reader :stacksize
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2Q=2".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2Q=2".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 24
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 24
- # @api private
- def initialize(view, cmd, cmdsize, entryoff, stacksize)
- super(view, cmd, cmdsize)
- @entryoff = entryoff
- @stacksize = stacksize
+ # @api private
+ def initialize(view, cmd, cmdsize, entryoff, stacksize)
+ super(view, cmd, cmdsize)
+ @entryoff = entryoff
+ @stacksize = stacksize
+ end
end
- end
- # A load command specifying the version of the sources used to build the
- # binary. Corresponds to LC_SOURCE_VERSION.
- class SourceVersionCommand < LoadCommand
- # @return [Fixnum] the version packed as a24.b10.c10.d10.e10
- attr_reader :version
+ # A load command specifying the version of the sources used to build the
+ # binary. Corresponds to LC_SOURCE_VERSION.
+ class SourceVersionCommand < LoadCommand
+ # @return [Fixnum] the version packed as a24.b10.c10.d10.e10
+ attr_reader :version
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=2Q=1".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=2Q=1".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- # @api private
- def initialize(view, cmd, cmdsize, version)
- super(view, cmd, cmdsize)
- @version = version
- end
+ # @api private
+ def initialize(view, cmd, cmdsize, version)
+ super(view, cmd, cmdsize)
+ @version = version
+ end
- # A string representation of the sources used to build the binary.
- # @return [String] a string representation of the version
- def version_string
- binary = "%064b" % version
- segs = [
- binary[0..23], binary[24..33], binary[34..43], binary[44..53],
- binary[54..63]
- ].map { |s| s.to_i(2) }
+ # A string representation of the sources used to build the binary.
+ # @return [String] a string representation of the version
+ def version_string
+ binary = "%064b" % version
+ segs = [
+ binary[0..23], binary[24..33], binary[34..43], binary[44..53],
+ binary[54..63]
+ ].map { |s| s.to_i(2) }
- segs.join(".")
+ segs.join(".")
+ end
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
+ # 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
+ # @return [Fixnum] the size of the symbol segment in bytes
+ attr_reader :size
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=4".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=4".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @see MachOStructure::SIZEOF
+ # @api private
+ SIZEOF = 16
- # @api private
- def initialize(view, cmd, cmdsize, offset, size)
- super(view, cmd, cmdsize)
- @offset = offset
- @size = size
+ # @api private
+ def initialize(view, cmd, cmdsize, offset, size)
+ super(view, cmd, cmdsize)
+ @offset = offset
+ @size = size
+ end
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
+ # 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
+ # @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
+ # An obsolete load command containing the path to a file to be loaded into
+ # memory. Corresponds to LC_FVMFILE.
+ class FvmfileCommand < LoadCommand
+ # @return [LCStr] the pathname of the file being loaded
+ attr_reader :name
- # @return [Fixnum] the virtual address being loaded at
- attr_reader :header_addr
+ # @return [Fixnum] the virtual address being loaded at
+ attr_reader :header_addr
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=4".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=4".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 16
+ # @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
+ def initialize(view, cmd, cmdsize, name, header_addr)
+ super(view, cmd, cmdsize)
+ @name = LCStr.new(self, name)
+ @header_addr = header_addr
+ end
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
+ # 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 [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 minor version number
+ attr_reader :minor_version
- # @return [Fixnum] the library's header address
- attr_reader :header_addr
+ # @return [Fixnum] the library's header address
+ attr_reader :header_addr
- # @see MachOStructure::FORMAT
- # @api private
- FORMAT = "L=5".freeze
+ # @see MachOStructure::FORMAT
+ # @api private
+ FORMAT = "L=5".freeze
- # @see MachOStructure::SIZEOF
- # @api private
- SIZEOF = 20
+ # @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
+ 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
end
diff --git a/Library/Homebrew/vendor/macho/macho/macho_file.rb b/Library/Homebrew/vendor/macho/macho/macho_file.rb
index 8ece62672..7693ab0dd 100644
--- a/Library/Homebrew/vendor/macho/macho/macho_file.rb
+++ b/Library/Homebrew/vendor/macho/macho/macho_file.rb
@@ -1,27 +1,33 @@
+require "forwardable"
+
module MachO
# Represents a Mach-O file, which contains a header and load commands
# as well as binary executable instructions. Mach-O binaries are
# architecture specific.
# @see https://en.wikipedia.org/wiki/Mach-O
- # @see MachO::FatFile
+ # @see FatFile
class MachOFile
- # @return [String] the filename loaded from, or nil if loaded from a binary string
+ extend Forwardable
+
+ # @return [String] the filename loaded from, or nil if loaded from a binary
+ # string
attr_accessor :filename
# @return [Symbol] the endianness of the file, :big or :little
attr_reader :endianness
- # @return [MachO::MachHeader] if the Mach-O is 32-bit
- # @return [MachO::MachHeader64] if the Mach-O is 64-bit
+ # @return [Headers::MachHeader] if the Mach-O is 32-bit
+ # @return [Headers::MachHeader64] if the Mach-O is 64-bit
attr_reader :header
- # @return [Array<MachO::LoadCommand>] an array of the file's load commands
+ # @return [Array<LoadCommands::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.
# @param bin [String] a binary string containing raw Mach-O data
- # @return [MachO::MachOFile] a new MachOFile
+ # @return [MachOFile] a new MachOFile
def self.new_from_bin(bin)
instance = allocate
instance.initialize_from_bin(bin)
@@ -55,109 +61,63 @@ module MachO
@raw_data
end
- # @return [Boolean] true if the Mach-O has 32-bit magic, false otherwise
- def magic32?
- Utils.magic32?(header.magic)
- end
-
- # @return [Boolean] true if the Mach-O has 64-bit magic, false otherwise
- def magic64?
- 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
- def object?
- header.filetype == MH_OBJECT
- end
-
- # @return [Boolean] true if the file is of type `MH_EXECUTE`, false otherwise
- def executable?
- header.filetype == MH_EXECUTE
- end
-
- # @return [Boolean] true if the file is of type `MH_FVMLIB`, false otherwise
- def fvmlib?
- header.filetype == MH_FVMLIB
- end
-
- # @return [Boolean] true if the file is of type `MH_CORE`, false otherwise
- def core?
- header.filetype == MH_CORE
- end
-
- # @return [Boolean] true if the file is of type `MH_PRELOAD`, false otherwise
- def preload?
- header.filetype == MH_PRELOAD
- end
-
- # @return [Boolean] true if the file is of type `MH_DYLIB`, false otherwise
- def dylib?
- header.filetype == MH_DYLIB
- end
-
- # @return [Boolean] true if the file is of type `MH_DYLINKER`, false otherwise
- def dylinker?
- header.filetype == MH_DYLINKER
- end
-
- # @return [Boolean] true if the file is of type `MH_BUNDLE`, false otherwise
- def bundle?
- header.filetype == MH_BUNDLE
- end
-
- # @return [Boolean] true if the file is of type `MH_DSYM`, false otherwise
- def dsym?
- header.filetype == MH_DSYM
- end
-
- # @return [Boolean] true if the file is of type `MH_KEXT_BUNDLE`, false otherwise
- def kext?
- header.filetype == MH_KEXT_BUNDLE
- end
-
- # @return [Fixnum] the file's magic number
- def magic
- header.magic
- end
+ # @!method magic
+ # @return (see MachO::Headers::MachHeader#magic)
+ # @!method ncmds
+ # @return (see MachO::Headers::MachHeader#ncmds)
+ # @!method sizeofcmds
+ # @return (see MachO::Headers::MachHeader#sizeofcmds)
+ # @!method flags
+ # @return (see MachO::Headers::MachHeader#flags)
+ # @!method object?
+ # @return (see MachO::Headers::MachHeader#object?)
+ # @!method executable?
+ # @return (see MachO::Headers::MachHeader#executable?)
+ # @!method fvmlib?
+ # @return (see MachO::Headers::MachHeader#fvmlib?)
+ # @!method core?
+ # @return (see MachO::Headers::MachHeader#core?)
+ # @!method preload?
+ # @return (see MachO::Headers::MachHeader#preload?)
+ # @!method dylib?
+ # @return (see MachO::Headers::MachHeader#dylib?)
+ # @!method dylinker?
+ # @return (see MachO::Headers::MachHeader#dylinker?)
+ # @!method bundle?
+ # @return (see MachO::Headers::MachHeader#bundle?)
+ # @!method dsym?
+ # @return (see MachO::Headers::MachHeader#dsym?)
+ # @!method kext?
+ # @return (see MachO::Headers::MachHeader#kext?)
+ # @!method magic32?
+ # @return (see MachO::Headers::MachHeader#magic32?)
+ # @!method magic64?
+ # @return (see MachO::Headers::MachHeader#magic64?)
+ # @!method alignment
+ # @return (see MachO::Headers::MachHeader#alignment)
+ def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?,
+ :executable?, :fvmlib?, :core?, :preload?, :dylib?,
+ :dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?,
+ :alignment
# @return [String] a string representation of the file's magic number
def magic_string
- MH_MAGICS[magic]
+ Headers::MH_MAGICS[magic]
end
# @return [Symbol] a string representation of the Mach-O's filetype
def filetype
- MH_FILETYPES[header.filetype]
+ Headers::MH_FILETYPES[header.filetype]
end
# @return [Symbol] a symbol representation of the Mach-O's CPU type
def cputype
- CPU_TYPES[header.cputype]
+ Headers::CPU_TYPES[header.cputype]
end
# @return [Symbol] a symbol representation of the Mach-O's CPU subtype
def cpusubtype
- CPU_SUBTYPES[header.cputype][header.cpusubtype]
- end
-
- # @return [Fixnum] the number of load commands in the Mach-O's header
- def ncmds
- header.ncmds
- end
-
- # @return [Fixnum] the size of all load commands, in bytes
- def sizeofcmds
- header.sizeofcmds
- end
-
- # @return [Fixnum] execution flags set by the linker
- def flags
- header.flags
+ Headers::CPU_SUBTYPES[header.cputype][header.cpusubtype]
end
# All load commands of a given name.
@@ -165,7 +125,8 @@ module MachO
# file.command("LC_LOAD_DYLIB")
# file[:LC_LOAD_DYLIB]
# @param [String, Symbol] name the load command ID
- # @return [Array<MachO::LoadCommand>] an array of LoadCommands corresponding to `name`
+ # @return [Array<LoadCommands::LoadCommand>] an array of load commands
+ # corresponding to `name`
def command(name)
load_commands.select { |lc| lc.type == name.to_sym }
end
@@ -174,16 +135,16 @@ module MachO
# 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 lc [LoadCommands::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
+ # @raise [OffsetInsertionError] if the offset is not in the load command region
+ # @raise [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)
+ context = LoadCommands::LoadCommand::SerializationContext.context_for(self)
cmd_raw = lc.serialize(context)
if offset < header.class.bytesize || offset + cmd_raw.bytesize > low_fileoff
@@ -207,14 +168,14 @@ module MachO
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
+ # @param old_lc [LoadCommands::LoadCommand] the load command being replaced
+ # @param new_lc [LoadCommands::LoadCommand] the load command being added
# @return [void]
- # @raise [MachO::HeaderPadError] if the new command exceeds the header pad buffer
- # @see {#insert_command}
+ # @raise [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)
+ context = LoadCommands::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
@@ -226,12 +187,12 @@ module MachO
end
# Appends a new load command to the Mach-O.
- # @param lc [MachO::LoadCommand] the load command being added
+ # @param lc [LoadCommands::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}
+ # @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**
@@ -241,7 +202,7 @@ module MachO
end
# Delete a load command from the Mach-O.
- # @param lc [MachO::LoadCommand] the load command being deleted
+ # @param lc [LoadCommands::LoadCommand] the load command being deleted
# @param options [Hash]
# @option options [Boolean] :repopulate (true) whether or not to repopulate
# the instance fields
@@ -275,14 +236,14 @@ module MachO
end
# All load commands responsible for loading dylibs.
- # @return [Array<MachO::DylibCommand>] an array of DylibCommands
+ # @return [Array<LoadCommands::DylibCommand>] an array of DylibCommands
def dylib_load_commands
- load_commands.select { |lc| DYLIB_LOAD_COMMANDS.include?(lc.type) }
+ load_commands.select { |lc| LoadCommands::DYLIB_LOAD_COMMANDS.include?(lc.type) }
end
# All segment load commands in the Mach-O.
- # @return [Array<MachO::SegmentCommand>] if the Mach-O is 32-bit
- # @return [Array<MachO::SegmentCommand64>] if the Mach-O is 64-bit
+ # @return [Array<LoadCommands::SegmentCommand>] if the Mach-O is 32-bit
+ # @return [Array<LoadCommands::SegmentCommand64>] if the Mach-O is 64-bit
def segments
if magic32?
command(:LC_SEGMENT)
@@ -319,10 +280,10 @@ module MachO
old_lc = command(:LC_ID_DYLIB).first
raise DylibIdMissingError unless old_lc
- new_lc = LoadCommand.create(:LC_ID_DYLIB, new_id,
- old_lc.timestamp,
- old_lc.current_version,
- old_lc.compatibility_version)
+ new_lc = LoadCommands::LoadCommand.create(:LC_ID_DYLIB, new_id,
+ old_lc.timestamp,
+ old_lc.current_version,
+ old_lc.compatibility_version)
replace_command(old_lc, new_lc)
end
@@ -341,22 +302,22 @@ module MachO
# Changes the shared library `old_name` to `new_name`
# @example
- # file.change_install_name("/usr/lib/libWhatever.dylib", "/usr/local/lib/libWhatever2.dylib")
+ # file.change_install_name("abc.dylib", "def.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
+ # @raise [DylibUnknownError] if no shared library has the old name
# @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?
- new_lc = LoadCommand.create(old_lc.type, new_name,
- old_lc.timestamp,
- old_lc.current_version,
- old_lc.compatibility_version)
+ new_lc = LoadCommands::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
@@ -376,8 +337,8 @@ module MachO
# @param new_path [String] the new runtime path
# @param _options [Hash]
# @return [void]
- # @raise [MachO::RpathUnknownError] if no such old runtime path exists
- # @raise [MachO::RpathExistsError] if the new runtime path already exists
+ # @raise [RpathUnknownError] if no such old runtime path exists
+ # @raise [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 = {})
@@ -385,7 +346,7 @@ module MachO
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)
+ new_lc = LoadCommands::LoadCommand.create(:LC_RPATH, new_path)
delete_rpath(old_path)
insert_command(old_lc.view.offset, new_lc)
@@ -399,13 +360,13 @@ module MachO
# @param path [String] the new runtime path
# @param _options [Hash]
# @return [void]
- # @raise [MachO::RpathExistsError] if the runtime path already exists
+ # @raise [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)
+ rpath_cmd = LoadCommands::LoadCommand.create(:LC_RPATH, path)
add_command(rpath_cmd)
end
@@ -417,7 +378,7 @@ module MachO
# @param path [String] the runtime path to delete
# @param _options [Hash]
# @return void
- # @raise [MachO::RpathUnknownError] if no such runtime path exists
+ # @raise [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 = {})
@@ -431,15 +392,6 @@ module MachO
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)
- segment.sections
- end
-
# Write all Mach-O data to the given filename.
# @param filename [String] the file to write to
# @return [void]
@@ -449,7 +401,7 @@ module MachO
# Write all Mach-O data to the file used to initialize the instance.
# @return [void]
- # @raise [MachO::MachOError] if the instance was initialized without a file
+ # @raise [MachOError] if the instance was initialized without a file
# @note Overwrites all data in the file!
def write!
if @filename.nil?
@@ -462,16 +414,16 @@ module MachO
private
# The file's Mach-O header structure.
- # @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
+ # @return [Headers::MachHeader] if the Mach-O is 32-bit
+ # @return [Headers::MachHeader64] if the Mach-O is 64-bit
+ # @raise [TruncatedFileError] if the file is too small to have a valid header
# @api private
def populate_mach_header
# the smallest Mach-O header is 28 bytes
raise TruncatedFileError if @raw_data.size < 28
magic = populate_and_check_magic
- mh_klass = Utils.magic32?(magic) ? MachHeader : MachHeader64
+ mh_klass = Utils.magic32?(magic) ? Headers::MachHeader : Headers::MachHeader64
mh = mh_klass.new_from_bin(endianness, @raw_data[0, mh_klass.bytesize])
check_cputype(mh.cputype)
@@ -483,8 +435,8 @@ module MachO
# Read just the file's magic number and check its validity.
# @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
+ # @raise [MagicError] if the magic is not valid Mach-O magic
+ # @raise [FatBinaryError] if the magic is for a Fat file
# @api private
def populate_and_check_magic
magic = @raw_data[0..3].unpack("N").first
@@ -499,32 +451,32 @@ module MachO
# Check the file's CPU type.
# @param cputype [Fixnum] the CPU type
- # @raise [MachO::CPUTypeError] if the CPU type is unknown
+ # @raise [CPUTypeError] if the CPU type is unknown
# @api private
def check_cputype(cputype)
- raise CPUTypeError, cputype unless CPU_TYPES.key?(cputype)
+ raise CPUTypeError, cputype unless Headers::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
+ # @raise [CPUSubtypeError] if the CPU sub-type is unknown
# @api private
def check_cpusubtype(cputype, cpusubtype)
# Only check sub-type w/o capability bits (see `populate_mach_header`).
- raise CPUSubtypeError.new(cputype, cpusubtype) unless CPU_SUBTYPES[cputype].key?(cpusubtype)
+ raise CPUSubtypeError.new(cputype, cpusubtype) unless Headers::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
+ # @raise [FiletypeError] if the file type is unknown
# @api private
def check_filetype(filetype)
- raise FiletypeError, filetype unless MH_FILETYPES.key?(filetype)
+ raise FiletypeError, filetype unless Headers::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
+ # @return [Array<LoadCommands::LoadCommand>] an array of load commands
+ # @raise [LoadCommandError] if an unknown load command is encountered
# @api private
def populate_load_commands
offset = header.class.bytesize
@@ -533,13 +485,13 @@ module MachO
header.ncmds.times do
fmt = Utils.specialize_format("L=", endianness)
cmd = @raw_data.slice(offset, 4).unpack(fmt).first
- cmd_sym = LOAD_COMMANDS[cmd]
+ cmd_sym = LoadCommands::LOAD_COMMANDS[cmd]
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]
+ klass = LoadCommands.const_get LoadCommands::LC_STRUCTURES[cmd_sym]
view = MachOView.new(@raw_data, endianness, offset)
command = klass.new_from_bin(view)
diff --git a/Library/Homebrew/vendor/macho/macho/open.rb b/Library/Homebrew/vendor/macho/macho/open.rb
deleted file mode 100644
index 103f61741..000000000
--- a/Library/Homebrew/vendor/macho/macho/open.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module MachO
- # Opens the given filename as a MachOFile or FatFile, depending on its magic.
- # @param filename [String] the file being opened
- # @return [MachO::MachOFile] if the file is a Mach-O
- # @return [MachO::FatFile] if the file is a Fat file
- # @raise [ArgumentError] if the given file does not exist
- # @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, "#{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 Utils.fat_magic?(magic)
- file = FatFile.new(filename)
- elsif Utils.magic?(magic)
- file = MachOFile.new(filename)
- else
- raise MagicError, magic
- end
-
- file
- end
-end
diff --git a/Library/Homebrew/vendor/macho/macho/sections.rb b/Library/Homebrew/vendor/macho/macho/sections.rb
index bd6218bb5..1e69e0b61 100644
--- a/Library/Homebrew/vendor/macho/macho/sections.rb
+++ b/Library/Homebrew/vendor/macho/macho/sections.rb
@@ -1,170 +1,176 @@
module MachO
- # type mask
- SECTION_TYPE = 0x000000ff
-
- # attributes mask
- SECTION_ATTRIBUTES = 0xffffff00
-
- # user settable attributes mask
- SECTION_ATTRIBUTES_USR = 0xff000000
-
- # system settable attributes mask
- SECTION_ATTRIBUTES_SYS = 0x00ffff00
-
- # association of section flag symbols to values
- # @api private
- SECTION_FLAGS = {
- :S_REGULAR => 0x0,
- :S_ZEROFILL => 0x1,
- :S_CSTRING_LITERALS => 0x2,
- :S_4BYTE_LITERALS => 0x3,
- :S_8BYTE_LITERALS => 0x4,
- :S_LITERAL_POINTERS => 0x5,
- :S_NON_LAZY_SYMBOL_POINTERS => 0x6,
- :S_LAZY_SYMBOL_POINTERS => 0x7,
- :S_SYMBOL_STUBS => 0x8,
- :S_MOD_INIT_FUNC_POINTERS => 0x9,
- :S_MOD_TERM_FUNC_POINTERS => 0xa,
- :S_COALESCED => 0xb,
- :S_GB_ZEROFILE => 0xc,
- :S_INTERPOSING => 0xd,
- :S_16BYTE_LITERALS => 0xe,
- :S_DTRACE_DOF => 0xf,
- :S_LAZY_DYLIB_SYMBOL_POINTERS => 0x10,
- :S_THREAD_LOCAL_REGULAR => 0x11,
- :S_THREAD_LOCAL_ZEROFILL => 0x12,
- :S_THREAD_LOCAL_VARIABLES => 0x13,
- :S_THREAD_LOCAL_VARIABLE_POINTERS => 0x14,
- :S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => 0x15,
- :S_ATTR_PURE_INSTRUCTIONS => 0x80000000,
- :S_ATTR_NO_TOC => 0x40000000,
- :S_ATTR_STRIP_STATIC_SYMS => 0x20000000,
- :S_ATTR_NO_DEAD_STRIP => 0x10000000,
- :S_ATTR_LIVE_SUPPORT => 0x08000000,
- :S_ATTR_SELF_MODIFYING_CODE => 0x04000000,
- :S_ATTR_DEBUG => 0x02000000,
- :S_ATTR_SOME_INSTRUCTIONS => 0x00000400,
- :S_ATTR_EXT_RELOC => 0x00000200,
- :S_ATTR_LOC_RELOC => 0x00000100,
- }.freeze
-
- # association of section name symbols to names
- # @api private
- SECTION_NAMES = {
- :SECT_TEXT => "__text",
- :SECT_FVMLIB_INIT0 => "__fvmlib_init0",
- :SECT_FVMLIB_INIT1 => "__fvmlib_init1",
- :SECT_DATA => "__data",
- :SECT_BSS => "__bss",
- :SECT_COMMON => "__common",
- :SECT_OBJC_SYMBOLS => "__symbol_table",
- :SECT_OBJC_MODULES => "__module_info",
- :SECT_OBJC_STRINGS => "__selector_strs",
- :SECT_OBJC_REFS => "__selector_refs",
- :SECT_ICON_HEADER => "__header",
- :SECT_ICON_TIFF => "__tiff",
- }.freeze
-
- # Represents a section of a segment for 32-bit architectures.
- class Section < MachOStructure
- # @return [String] the name of the section, including null pad bytes
- attr_reader :sectname
-
- # @return [String] the name of the segment's section, including null pad bytes
- attr_reader :segname
-
- # @return [Fixnum] the memory address of the section
- attr_reader :addr
-
- # @return [Fixnum] the size, in bytes, of the section
- attr_reader :size
-
- # @return [Fixnum] the file offset of the section
- attr_reader :offset
-
- # @return [Fixnum] the section alignment (power of 2) of the section
- attr_reader :align
-
- # @return [Fixnum] the file offset of the section's relocation entries
- attr_reader :reloff
-
- # @return [Fixnum] the number of relocation entries
- attr_reader :nreloc
-
- # @return [Fixnum] flags for type and attributes of the section
- attr_reader :flags
-
- # @return [void] reserved (for offset or index)
- attr_reader :reserved1
-
- # @return [void] reserved (for count or sizeof)
- attr_reader :reserved2
-
- # @see MachOStructure::FORMAT
- FORMAT = "a16a16L=9".freeze
-
- # @see MachOStructure::SIZEOF
- SIZEOF = 68
+ # Classes and constants for parsing sections in Mach-O binaries.
+ module Sections
+ # type mask
+ SECTION_TYPE = 0x000000ff
- # @api private
- def initialize(sectname, segname, addr, size, offset, align, reloff,
- nreloc, flags, reserved1, reserved2)
- @sectname = sectname
- @segname = segname
- @addr = addr
- @size = size
- @offset = offset
- @align = align
- @reloff = reloff
- @nreloc = nreloc
- @flags = flags
- @reserved1 = reserved1
- @reserved2 = reserved2
- end
+ # attributes mask
+ SECTION_ATTRIBUTES = 0xffffff00
- # @return [String] the section's name, with any trailing NULL characters removed
- def section_name
- sectname.delete("\x00")
- end
-
- # @return [String] the parent segment's name, with any trailing NULL characters removed
- def segment_name
- segname.delete("\x00")
- end
+ # user settable attributes mask
+ SECTION_ATTRIBUTES_USR = 0xff000000
- # @return [Boolean] true if the section has no contents (i.e, `size` is 0)
- def empty?
- size.zero?
- end
+ # system settable attributes mask
+ SECTION_ATTRIBUTES_SYS = 0x00ffff00
- # @example
- # puts "this section is regular" if sect.flag?(:S_REGULAR)
- # @param flag [Symbol] a section flag symbol
- # @return [Boolean] true if `flag` is present in the section's flag field
- def flag?(flag)
- flag = SECTION_FLAGS[flag]
- return false if flag.nil?
- flags & flag == flag
+ # association of section flag symbols to values
+ # @api private
+ SECTION_FLAGS = {
+ :S_REGULAR => 0x0,
+ :S_ZEROFILL => 0x1,
+ :S_CSTRING_LITERALS => 0x2,
+ :S_4BYTE_LITERALS => 0x3,
+ :S_8BYTE_LITERALS => 0x4,
+ :S_LITERAL_POINTERS => 0x5,
+ :S_NON_LAZY_SYMBOL_POINTERS => 0x6,
+ :S_LAZY_SYMBOL_POINTERS => 0x7,
+ :S_SYMBOL_STUBS => 0x8,
+ :S_MOD_INIT_FUNC_POINTERS => 0x9,
+ :S_MOD_TERM_FUNC_POINTERS => 0xa,
+ :S_COALESCED => 0xb,
+ :S_GB_ZEROFILE => 0xc,
+ :S_INTERPOSING => 0xd,
+ :S_16BYTE_LITERALS => 0xe,
+ :S_DTRACE_DOF => 0xf,
+ :S_LAZY_DYLIB_SYMBOL_POINTERS => 0x10,
+ :S_THREAD_LOCAL_REGULAR => 0x11,
+ :S_THREAD_LOCAL_ZEROFILL => 0x12,
+ :S_THREAD_LOCAL_VARIABLES => 0x13,
+ :S_THREAD_LOCAL_VARIABLE_POINTERS => 0x14,
+ :S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => 0x15,
+ :S_ATTR_PURE_INSTRUCTIONS => 0x80000000,
+ :S_ATTR_NO_TOC => 0x40000000,
+ :S_ATTR_STRIP_STATIC_SYMS => 0x20000000,
+ :S_ATTR_NO_DEAD_STRIP => 0x10000000,
+ :S_ATTR_LIVE_SUPPORT => 0x08000000,
+ :S_ATTR_SELF_MODIFYING_CODE => 0x04000000,
+ :S_ATTR_DEBUG => 0x02000000,
+ :S_ATTR_SOME_INSTRUCTIONS => 0x00000400,
+ :S_ATTR_EXT_RELOC => 0x00000200,
+ :S_ATTR_LOC_RELOC => 0x00000100,
+ }.freeze
+
+ # association of section name symbols to names
+ # @api private
+ SECTION_NAMES = {
+ :SECT_TEXT => "__text",
+ :SECT_FVMLIB_INIT0 => "__fvmlib_init0",
+ :SECT_FVMLIB_INIT1 => "__fvmlib_init1",
+ :SECT_DATA => "__data",
+ :SECT_BSS => "__bss",
+ :SECT_COMMON => "__common",
+ :SECT_OBJC_SYMBOLS => "__symbol_table",
+ :SECT_OBJC_MODULES => "__module_info",
+ :SECT_OBJC_STRINGS => "__selector_strs",
+ :SECT_OBJC_REFS => "__selector_refs",
+ :SECT_ICON_HEADER => "__header",
+ :SECT_ICON_TIFF => "__tiff",
+ }.freeze
+
+ # Represents a section of a segment for 32-bit architectures.
+ class Section < MachOStructure
+ # @return [String] the name of the section, including null pad bytes
+ attr_reader :sectname
+
+ # @return [String] the name of the segment's section, including null
+ # pad bytes
+ attr_reader :segname
+
+ # @return [Fixnum] the memory address of the section
+ attr_reader :addr
+
+ # @return [Fixnum] the size, in bytes, of the section
+ attr_reader :size
+
+ # @return [Fixnum] the file offset of the section
+ attr_reader :offset
+
+ # @return [Fixnum] the section alignment (power of 2) of the section
+ attr_reader :align
+
+ # @return [Fixnum] the file offset of the section's relocation entries
+ attr_reader :reloff
+
+ # @return [Fixnum] the number of relocation entries
+ attr_reader :nreloc
+
+ # @return [Fixnum] flags for type and attributes of the section
+ attr_reader :flags
+
+ # @return [void] reserved (for offset or index)
+ attr_reader :reserved1
+
+ # @return [void] reserved (for count or sizeof)
+ attr_reader :reserved2
+
+ # @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)
+ @sectname = sectname
+ @segname = segname
+ @addr = addr
+ @size = size
+ @offset = offset
+ @align = align
+ @reloff = reloff
+ @nreloc = nreloc
+ @flags = flags
+ @reserved1 = reserved1
+ @reserved2 = reserved2
+ end
+
+ # @return [String] the section's name, with any trailing NULL characters
+ # removed
+ def section_name
+ sectname.delete("\x00")
+ end
+
+ # @return [String] the parent segment's name, with any trailing NULL
+ # characters removed
+ def segment_name
+ segname.delete("\x00")
+ end
+
+ # @return [Boolean] whether the section is empty (i.e, {size} is 0)
+ def empty?
+ size.zero?
+ end
+
+ # @example
+ # puts "this section is regular" if sect.flag?(:S_REGULAR)
+ # @param flag [Symbol] a section flag symbol
+ # @return [Boolean] whether the flag is present in the section's {flags}
+ def flag?(flag)
+ flag = SECTION_FLAGS[flag]
+ return false if flag.nil?
+ flags & flag == flag
+ end
end
- end
- # Represents a section of a segment for 64-bit architectures.
- class Section64 < Section
- # @return [void] reserved
- attr_reader :reserved3
+ # Represents a section of a segment for 64-bit architectures.
+ class Section64 < Section
+ # @return [void] reserved
+ attr_reader :reserved3
- # @see MachOStructure::FORMAT
- FORMAT = "a16a16Q=2L=8".freeze
+ # @see MachOStructure::FORMAT
+ FORMAT = "a16a16Q=2L=8".freeze
- # @see MachOStructure::SIZEOF
- SIZEOF = 80
+ # @see MachOStructure::SIZEOF
+ SIZEOF = 80
- # @api private
- def initialize(sectname, segname, addr, size, offset, align, reloff,
- nreloc, flags, reserved1, reserved2, reserved3)
- super(sectname, segname, addr, size, offset, align, reloff,
- nreloc, flags, reserved1, reserved2)
- @reserved3 = reserved3
+ # @api private
+ def initialize(sectname, segname, addr, size, offset, align, reloff,
+ nreloc, flags, reserved1, reserved2, reserved3)
+ super(sectname, segname, addr, size, offset, align, reloff,
+ nreloc, flags, reserved1, reserved2)
+ @reserved3 = reserved3
+ end
end
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/structure.rb b/Library/Homebrew/vendor/macho/macho/structure.rb
index 43f7bc84e..bac5342d4 100644
--- a/Library/Homebrew/vendor/macho/macho/structure.rb
+++ b/Library/Homebrew/vendor/macho/macho/structure.rb
@@ -19,7 +19,7 @@ module MachO
# @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`
+ # @return [MachO::MachOStructure] the resulting structure
# @api private
def self.new_from_bin(endianness, bin)
format = Utils.specialize_format(self::FORMAT, endianness)
diff --git a/Library/Homebrew/vendor/macho/macho/tools.rb b/Library/Homebrew/vendor/macho/macho/tools.rb
index f34d75dc1..b49626d9d 100644
--- a/Library/Homebrew/vendor/macho/macho/tools.rb
+++ b/Library/Homebrew/vendor/macho/macho/tools.rb
@@ -1,5 +1,6 @@
module MachO
- # A collection of convenient methods for common operations on Mach-O and Fat binaries.
+ # A collection of convenient methods for common operations on Mach-O and Fat
+ # binaries.
module Tools
# @param filename [String] the Mach-O or Fat binary being read
# @return [Array<String>] an array of all dylibs linked to the binary
@@ -9,7 +10,8 @@ module MachO
file.linked_dylibs
end
- # Changes the dylib ID of a Mach-O or Fat binary, overwriting the source file.
+ # 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]
@@ -23,7 +25,8 @@ module MachO
file.write!
end
- # Changes a shared library install name in a Mach-O or Fat binary, overwriting the source file.
+ # Changes a shared library install name in a Mach-O or Fat binary,
+ # overwriting the source file.
# @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
@@ -38,7 +41,8 @@ module MachO
file.write!
end
- # Changes a runtime path in a Mach-O or Fat binary, overwriting the source file.
+ # Changes a runtime path in 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 new_path [String] the new runtime path
@@ -67,7 +71,8 @@ module MachO
file.write!
end
- # Delete a runtime path from a Mach-O or Fat binary, overwriting the source file.
+ # 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]
@@ -80,5 +85,24 @@ module MachO
file.delete_rpath(old_path, options)
file.write!
end
+
+ # Merge multiple Mach-Os into one universal (Fat) binary.
+ # @param filename [String] the fat binary to create
+ # @param files [Array<MachO::MachOFile, MachO::FatFile>] the files to merge
+ # @return [void]
+ def self.merge_machos(filename, *files)
+ machos = files.map do |file|
+ macho = MachO.open(file)
+ case macho
+ when MachO::MachOFile
+ macho
+ else
+ macho.machos
+ end
+ end.flatten
+
+ fat_macho = MachO::FatFile.new_from_machos(*machos)
+ fat_macho.write(filename)
+ end
end
end
diff --git a/Library/Homebrew/vendor/macho/macho/utils.rb b/Library/Homebrew/vendor/macho/macho/utils.rb
index cedd0bc1c..ecfc8390b 100644
--- a/Library/Homebrew/vendor/macho/macho/utils.rb
+++ b/Library/Homebrew/vendor/macho/macho/utils.rb
@@ -5,7 +5,7 @@ module MachO
# @param value [Fixnum] the number being rounded
# @param round [Fixnum] the number being rounded with
# @return [Fixnum] the rounded value
- # @see https://www.opensource.apple.com/source/cctools/cctools-870/libstuff/rnd.c
+ # @see http://www.opensource.apple.com/source/cctools/cctools-870/libstuff/rnd.c
def self.round(value, round)
round -= 1
value += round
@@ -13,7 +13,8 @@ module MachO
value
end
- # Returns the number of bytes needed to pad the given size to the given alignment.
+ # 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
@@ -21,7 +22,8 @@ module MachO
round(size, alignment) - size
end
- # Converts an abstract (native-endian) String#unpack format to big or little.
+ # 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
@@ -31,7 +33,8 @@ module MachO
end
# Packs tagged strings into an aligned payload.
- # @param fixed_offset [Fixnum] the baseline offset for the first packed string
+ # @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
@@ -53,44 +56,44 @@ module MachO
# 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
+ # @return [Boolean] whether `num` is a valid Mach-O magic number
def self.magic?(num)
- MH_MAGICS.key?(num)
+ Headers::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
+ # @return [Boolean] whether `num` is a valid Fat magic number
def self.fat_magic?(num)
- num == FAT_MAGIC
+ num == Headers::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
+ # @return [Boolean] whether `num` is a valid 32-bit magic number
def self.magic32?(num)
- num == MH_MAGIC || num == MH_CIGAM
+ num == Headers::MH_MAGIC || num == Headers::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
+ # @return [Boolean] whether `num` is a valid 64-bit magic number
def self.magic64?(num)
- num == MH_MAGIC_64 || num == MH_CIGAM_64
+ num == Headers::MH_MAGIC_64 || num == Headers::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
+ # @return [Boolean] whether `num` is a valid little-endian magic number
def self.little_magic?(num)
- num == MH_CIGAM || num == MH_CIGAM_64
+ num == Headers::MH_CIGAM || num == Headers::MH_CIGAM_64
end
# 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
+ # @return [Boolean] whether `num` is a valid big-endian magic number
def self.big_magic?(num)
- num == MH_CIGAM || num == MH_CIGAM_64
+ num == Headers::MH_CIGAM || num == Headers::MH_CIGAM_64
end
end
end