From 852c5acb655d8d07037ea251ec2fa38c62b91932 Mon Sep 17 00:00:00 2001 From: Ruoyu Zhong Date: Tue, 16 Apr 2024 02:50:12 +0800 Subject: [PATCH] Revert "os/linux/elf: avoid using ldd for listing dynamic dependencies" --- Library/Homebrew/os/linux/elf.rb | 62 ++++--------------- Library/Homebrew/os/linux/ld.rb | 74 ----------------------- Library/Homebrew/test/os/linux/ld_spec.rb | 47 -------------- Library/Homebrew/test/utils/path_spec.rb | 33 ---------- Library/Homebrew/utils/path.rb | 14 ----- 5 files changed, 13 insertions(+), 217 deletions(-) delete mode 100644 Library/Homebrew/os/linux/ld.rb delete mode 100644 Library/Homebrew/test/os/linux/ld_spec.rb delete mode 100644 Library/Homebrew/test/utils/path_spec.rb delete mode 100644 Library/Homebrew/utils/path.rb diff --git a/Library/Homebrew/os/linux/elf.rb b/Library/Homebrew/os/linux/elf.rb index 49d0b80c63d53..efd855db952ca 100644 --- a/Library/Homebrew/os/linux/elf.rb +++ b/Library/Homebrew/os/linux/elf.rb @@ -1,8 +1,6 @@ # typed: true # frozen_string_literal: true -require "os/linux/ld" - # {Pathname} extension for dealing with ELF files. # @see https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header # @@ -132,7 +130,19 @@ def initialize(path) @dylib_id, needed = needed_libraries path return if needed.empty? - @dylibs = needed.map { |lib| find_full_lib_path(lib).to_s } + ldd = DevelopmentTools.locate "ldd" + ldd_output = Utils.popen_read(ldd, path.expand_path.to_s).split("\n") + return unless $CHILD_STATUS.success? + + ldd_paths = ldd_output.filter_map do |line| + match = line.match(/\t.+ => (.+) \(.+\)|\t(.+) => not found/) + next unless match + + match.captures.compact.first + end + @dylibs = ldd_paths.select do |ldd_path| + needed.include? File.basename(ldd_path) + end end private @@ -147,52 +157,6 @@ def needed_libraries_using_patchelf_rb(path) patcher = path.patchelf_patcher [patcher.soname, patcher.needed] end - - def find_full_lib_path(basename) - local_paths = (path.patchelf_patcher.runpath || path.patchelf_patcher.rpath)&.split(":") - - # Search for dependencies in the runpath/rpath first - local_paths&.each do |local_path| - candidate = Pathname(local_path)/basename - return candidate if candidate.exist? && candidate.elf? - end - - # Check if DF_1_NODEFLIB is set - dt_flags_1 = path.patchelf_patcher.elf.segment_by_type(:dynamic)&.tag_by_type(:flags_1) - nodeflib_flag = if dt_flags_1.nil? - false - else - dt_flags_1.value & ELFTools::Constants::DF::DF_1_NODEFLIB != 0 - end - - linker_library_paths = OS::Linux::Ld.library_paths - linker_system_dirs = OS::Linux::Ld.system_dirs - - # If DF_1_NODEFLIB is set, exclude any library paths that are subdirectories - # of the system dirs - if nodeflib_flag - linker_library_paths = linker_library_paths.reject do |lib_path| - linker_system_dirs.any? { |system_dir| Utils::Path.child_of? system_dir, lib_path } - end - end - - # If not found, search recursively in the paths listed in ld.so.conf (skipping - # paths that are subdirectories of the system dirs if DF_1_NODEFLIB is set) - linker_library_paths.each do |linker_library_path| - candidate = Pathname(linker_library_path)/basename - return candidate if candidate.exist? && candidate.elf? - end - - # If not found, search in the system dirs, unless DF_1_NODEFLIB is set - unless nodeflib_flag - linker_system_dirs.each do |linker_system_dir| - candidate = Pathname(linker_system_dir)/basename - return candidate if candidate.exist? && candidate.elf? - end - end - - basename - end end private_constant :Metadata diff --git a/Library/Homebrew/os/linux/ld.rb b/Library/Homebrew/os/linux/ld.rb deleted file mode 100644 index 1ff2bd05f83e7..0000000000000 --- a/Library/Homebrew/os/linux/ld.rb +++ /dev/null @@ -1,74 +0,0 @@ -# typed: strict -# frozen_string_literal: true - -module OS - module Linux - # Helper functions for querying `ld` information. - # - # @api private - module Ld - sig { returns(String) } - def self.brewed_ld_so_diagnostics - brewed_ld_so = HOMEBREW_PREFIX/"lib/ld.so" - return "" unless brewed_ld_so.exist? - - ld_so_output = Utils.popen_read(brewed_ld_so, "--list-diagnostics") - return "" unless $CHILD_STATUS.success? - - ld_so_output - end - - sig { returns(String) } - def self.sysconfdir - fallback_sysconfdir = "/etc" - - match = brewed_ld_so_diagnostics.match(/path.sysconfdir="(.+)"/) - return fallback_sysconfdir unless match - - match.captures.compact.first || fallback_sysconfdir - end - - sig { returns(T::Array[String]) } - def self.system_dirs - dirs = [] - - brewed_ld_so_diagnostics.split("\n").each do |line| - match = line.match(/path.system_dirs\[0x.*\]="(.*)"/) - next unless match - - dirs << match.captures.compact.first - end - - dirs - end - - sig { params(conf_path: T.any(Pathname, String)).returns(T::Array[String]) } - def self.library_paths(conf_path = Pathname(sysconfdir)/"ld.so.conf") - conf_file = Pathname(conf_path) - paths = Set.new - directory = conf_file.realpath.dirname - - conf_file.readlines.each do |line| - # Remove comments and leading/trailing whitespace - line.strip! - line.sub!(/\s*#.*$/, "") - - if line.start_with?(/\s*include\s+/) - include_path = Pathname(line.sub(/^\s*include\s+/, "")).expand_path - wildcard = include_path.absolute? ? include_path : directory/include_path - - Dir.glob(wildcard.to_s).each do |include_file| - paths += library_paths(include_file) - end - elsif line.empty? - next - else - paths << line - end - end - - paths.to_a - end - end - end -end diff --git a/Library/Homebrew/test/os/linux/ld_spec.rb b/Library/Homebrew/test/os/linux/ld_spec.rb deleted file mode 100644 index b738bbe2537e6..0000000000000 --- a/Library/Homebrew/test/os/linux/ld_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -require "os/linux/ld" -require "tmpdir" - -RSpec.describe OS::Linux::Ld do - describe "::library_paths" do - ld_etc = Pathname("") - before do - ld_etc = Pathname(Dir.mktmpdir("homebrew-tests-ld-etc-", Dir.tmpdir)) - FileUtils.mkdir [ld_etc/"subdir1", ld_etc/"subdir2"] - (ld_etc/"ld.so.conf").write <<~EOS - # This line is a comment - - include #{ld_etc}/subdir1/*.conf # This is an end-of-line comment, should be ignored - - # subdir2 is an empty directory - include #{ld_etc}/subdir2/*.conf - - /a/b/c - /d/e/f # Indentation on this line should be ignored - /a/b/c # Duplicate entry should be ignored - EOS - - (ld_etc/"subdir1/1-1.conf").write <<~EOS - /foo/bar - /baz/qux - EOS - - (ld_etc/"subdir1/1-2.conf").write <<~EOS - /g/h/i - EOS - - # Empty files (or files containing only whitespace) should be ignored - (ld_etc/"subdir1/1-3.conf").write "\n\t\n\t\n" - (ld_etc/"subdir1/1-4.conf").write "" - end - - after do - FileUtils.rm_rf ld_etc - end - - it "parses library paths successfully" do - expect(described_class.library_paths(ld_etc/"ld.so.conf")).to eq(%w[/foo/bar /baz/qux /g/h/i /a/b/c /d/e/f]) - end - end -end diff --git a/Library/Homebrew/test/utils/path_spec.rb b/Library/Homebrew/test/utils/path_spec.rb deleted file mode 100644 index ba7f27436cd1f..0000000000000 --- a/Library/Homebrew/test/utils/path_spec.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -require "utils/path" - -RSpec.describe Utils::Path do - describe "::child_of?" do - it "recognizes a path as its own child" do - expect(described_class.child_of?("/foo/bar", "/foo/bar")).to be(true) - end - - it "recognizes a path that is a child of the parent" do - expect(described_class.child_of?("/foo", "/foo/bar")).to be(true) - end - - it "recognizes a path that is a grandchild of the parent" do - expect(described_class.child_of?("/foo", "/foo/bar/baz")).to be(true) - end - - it "does not recognize a path that is not a child" do - expect(described_class.child_of?("/foo", "/bar/baz")).to be(false) - end - - it "handles . and .. in paths correctly" do - expect(described_class.child_of?("/foo", "/foo/./bar")).to be(true) - expect(described_class.child_of?("/foo/bar", "/foo/../foo/bar/baz")).to be(true) - end - - it "handles relative paths correctly" do - expect(described_class.child_of?("foo", "./bar/baz")).to be(false) - expect(described_class.child_of?("../foo", "./bar/baz/../../../foo/bar/baz")).to be(true) - end - end -end diff --git a/Library/Homebrew/utils/path.rb b/Library/Homebrew/utils/path.rb deleted file mode 100644 index b2f69504f6fd2..0000000000000 --- a/Library/Homebrew/utils/path.rb +++ /dev/null @@ -1,14 +0,0 @@ -# typed: strict -# frozen_string_literal: true - -module Utils - module Path - sig { params(parent: T.any(Pathname, String), child: T.any(Pathname, String)).returns(T::Boolean) } - def self.child_of?(parent, child) - parent_pathname = Pathname(parent).expand_path - child_pathname = Pathname(child).expand_path - child_pathname.ascend { |p| return true if p == parent_pathname } - false - end - end -end