Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

patchelf.rb reading for everyone :) #8241

Merged
merged 2 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 0 additions & 5 deletions Library/Homebrew/brew.sh
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,6 @@ export HOMEBREW_USER_AGENT
export HOMEBREW_USER_AGENT_CURL
export HOMEBREW_BOTTLE_DEFAULT_DOMAIN

if [[ -n "$HOMEBREW_DEVELOPER" ]] && [[ -z "$HOMEBREW_NO_PATCHELF_RB" ]]
then
export HOMEBREW_PATCHELF_RB="1"
fi

if [[ -n "$HOMEBREW_MACOS" && -x "/usr/bin/xcode-select" ]]
then
XCODE_SELECT_PATH=$('/usr/bin/xcode-select' --print-path 2>/dev/null)
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/diagnostic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ def check_git_status

# these will result in uncommitted gems.
if path == HOMEBREW_REPOSITORY
next if ENV["HOMEBREW_SORBET"] || ENV["HOMEBREW_PATCHELF_RB"]
next if ENV["HOMEBREW_SORBET"]
end

message ||= ""
Expand Down
91 changes: 4 additions & 87 deletions Library/Homebrew/os/linux/elf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,41 +71,19 @@ def binary_executable?
def rpath
return @rpath if defined? @rpath

@rpath = if HOMEBREW_PATCHELF_RB
rpath_using_patchelf_rb
else
rpath_using_patchelf
end
@rpath = rpath_using_patchelf_rb
end

def interpreter
return @interpreter if defined? @interpreter

@interpreter = if HOMEBREW_PATCHELF_RB
patchelf_patcher.interpreter
elsif (patchelf = DevelopmentTools.locate "patchelf")
interp = Utils.popen_read(patchelf, "--print-interpreter", to_s, err: :out).strip
$CHILD_STATUS.success? ? interp : nil
elsif (file = DevelopmentTools.locate("file"))
output = Utils.popen_read(file, "-L", "-b", to_s, err: :out).strip
output[/^ELF.*, interpreter (.+?), /, 1]
else
raise "Please install either patchelf or file."
end
@interpreter = patchelf_patcher.interpreter
end

def dynamic_elf?
return @dynamic_elf if defined? @dynamic_elf

@dynamic_elf = if HOMEBREW_PATCHELF_RB
patchelf_patcher.elf.segment_by_type(:DYNAMIC).present?
elsif which "readelf"
Utils.popen_read("readelf", "-l", to_path).include?(" DYNAMIC ")
elsif which "file"
!Utils.popen_read("file", "-L", "-b", to_path)[/dynamic|shared/].nil?
else
raise "Please install either readelf (from binutils) or file."
end
@dynamic_elf = patchelf_patcher.elf.segment_by_type(:DYNAMIC).present?
end

class Metadata
Expand Down Expand Up @@ -139,81 +117,20 @@ def initialize(path)
def needed_libraries(path)
return [nil, []] unless path.dynamic_elf?

if HOMEBREW_PATCHELF_RB
needed_libraries_using_patchelf_rb path
elsif DevelopmentTools.locate "readelf"
needed_libraries_using_readelf path
elsif DevelopmentTools.locate "patchelf"
needed_libraries_using_patchelf path
else
return [nil, []] if path.basename.to_s == "patchelf"

raise "patchelf must be installed: brew install patchelf"
end
needed_libraries_using_patchelf_rb path
end

def needed_libraries_using_patchelf_rb(path)
patcher = path.patchelf_patcher
[patcher.soname, patcher.needed]
end

def needed_libraries_using_patchelf(path)
patchelf = DevelopmentTools.locate "patchelf"
if path.dylib?
command = [patchelf, "--print-soname", path.expand_path.to_s]
soname = Utils.safe_popen_read(*command).chomp
end
command = [patchelf, "--print-needed", path.expand_path.to_s]
needed = Utils.safe_popen_read(*command).split("\n")
[soname, needed]
end

def needed_libraries_using_readelf(path)
soname = nil
needed = []
command = ["readelf", "-d", path.expand_path.to_s]
lines = Utils.popen_read(*command, err: :out).split("\n")
lines.each do |s|
next if s.start_with?("readelf: Warning: possibly corrupt ELF header")

filename = s[/\[(.*)\]/, 1]
next if filename.nil?

if s.include? "(SONAME)"
soname = filename
elsif s.include? "(NEEDED)"
needed << filename
end
end
[soname, needed]
end
end

def rpath_using_patchelf_rb
patchelf_patcher.runpath || patchelf_patcher.rpath
end

def rpath_using_patchelf
patchelf = DevelopmentTools.locate "patchelf"
odie "Could not locate patchelf, please: brew install patchelf." if patchelf.nil?

cmd_rpath = [patchelf, "--print-rpath", to_s]
rpath = Utils.popen_read(*cmd_rpath, err: :out).strip

# patchelf requires that the ELF file have a .dynstr section.
# Skip ELF files that do not have a .dynstr section.
return if ["cannot find section .dynstr", "strange: no string table"].include?(rpath)

unless $CHILD_STATUS.success?
raise ErrorDuringExecution.new(cmd_rpath, status: $CHILD_STATUS, output: [[:stderr, rpath]])
end

rpath unless rpath.blank?
end

def patchelf_patcher
return unless HOMEBREW_PATCHELF_RB

Homebrew.install_bundler_gems!
require "patchelf"
@patchelf_patcher ||= PatchELF::Patcher.new to_s, on_error: :silent
Expand Down
3 changes: 0 additions & 3 deletions Library/Homebrew/os/linux/global.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# frozen_string_literal: true

# enables experimental readelf.rb, patchelf support.
HOMEBREW_PATCHELF_RB = ENV["HOMEBREW_PATCHELF_RB"].present?.freeze

module Homebrew
DEFAULT_PREFIX ||= if Homebrew::EnvConfig.force_homebrew_on_linux?
HOMEBREW_DEFAULT_PREFIX
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/test/os/linux/pathname_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require "extend/pathname"

describe Pathname, skip: HOMEBREW_PATCHELF_RB.blank? do
describe Pathname do
let(:elf_dir) { described_class.new "#{TEST_FIXTURE_DIR}/elf" }
let(:sho) { elf_dir/"libhello.so.0" }
let(:exec) { elf_dir/"hello" }
Expand Down