[前][次][番号順一覧][スレッド一覧]

ruby-changes:74096

From: Sutou <ko1@a...>
Date: Tue, 18 Oct 2022 17:22:00 +0900 (JST)
Subject: [ruby-changes:74096] e84ea4af69 (master): [ruby/fiddle] Add support for linker script on Linux

https://git.ruby-lang.org/ruby.git/commit/?id=e84ea4af69

From e84ea4af695de307c4e66bf0d9aa445a1016a4af Mon Sep 17 00:00:00 2001
From: Sutou Kouhei <kou@c...>
Date: Mon, 11 Apr 2022 08:32:05 +0900
Subject: [ruby/fiddle] Add support for linker script on Linux

GitHub: fix https://github.com/ruby/fiddle/pull/107

Reported by nicholas a. evans. Thanks!!!

https://github.com/ruby/fiddle/commit/49ea1490df
---
 ext/fiddle/lib/fiddle.rb   | 31 ++++++++++++++++++++++++++++++-
 test/fiddle/test_fiddle.rb | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb
index 09262c43ff..6137c487c6 100644
--- a/ext/fiddle/lib/fiddle.rb
+++ b/ext/fiddle/lib/fiddle.rb
@@ -58,7 +58,36 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/ext/fiddle/lib/fiddle.rb#L58
   #
   # See Fiddle::Handle.new for more.
   def dlopen library
-    Fiddle::Handle.new library
+    begin
+      Fiddle::Handle.new(library)
+    rescue DLError => error
+      case RUBY_PLATFORM
+      when /linux/
+        case error.message
+        when /\A(\/.+?): (?:invalid ELF header|file too short)/
+          # This may be a linker script:
+          # https://sourceware.org/binutils/docs/ld.html#Scripts
+          path = $1
+        else
+          raise
+        end
+      else
+        raise
+      end
+
+      File.open(path) do |input|
+        input.each_line do |line|
+          case line
+          when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/
+            # TODO: Should we support multiple files?
+            return dlopen($1)
+          end
+        end
+      end
+
+      # Not found
+      raise
+    end
   end
   module_function :dlopen
 
diff --git a/test/fiddle/test_fiddle.rb b/test/fiddle/test_fiddle.rb
index 8751d96920..2792897074 100644
--- a/test/fiddle/test_fiddle.rb
+++ b/test/fiddle/test_fiddle.rb
@@ -14,4 +14,38 @@ class TestFiddle < Fiddle::TestCase https://github.com/ruby/ruby/blob/trunk/test/fiddle/test_fiddle.rb#L14
     end
   end
 
+  def test_dlopen_linker_script_input_linux
+    omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux")
+    if Dir.glob("/usr/lib/*/libncurses.so").empty?
+      omit("libncurses.so is needed")
+    end
+    # libncurses.so uses INPUT() on Debian GNU/Linux
+    # $ cat /usr/lib/x86_64-linux-gnu/libncurses.so
+    # INPUT(libncurses.so.6 -ltinfo)
+    handle = Fiddle.dlopen("libncurses.so")
+    begin
+      assert_equal("libncurses.so",
+                   File.basename(handle.file_name, ".*"))
+    ensure
+      handle.close
+    end
+  end
+
+  def test_dlopen_linker_script_group_linux
+    omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux")
+    # libc.so uses GROUP() on Debian GNU/Linux
+    # $ cat /usr/lib/x86_64-linux-gnu/libc.so
+    # /* GNU ld script
+    #    Use the shared library, but some functions are only in
+    #    the static library, so try that secondarily.  */
+    # OUTPUT_FORMAT(elf64-x86-64)
+    # GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a  AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) )
+    handle = Fiddle.dlopen("libc.so")
+    begin
+      assert_equal("libc.so",
+                   File.basename(handle.file_name, ".*"))
+    ensure
+      handle.close
+    end
+  end
 end if defined?(Fiddle)
-- 
cgit v1.2.3


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]