[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
This commit is contained in:
Sutou Kouhei 2022-04-11 08:32:05 +09:00 committed by Nobuyoshi Nakada
parent 93da67d463
commit e84ea4af69
Notes: git 2022-10-18 08:22:06 +00:00
2 changed files with 64 additions and 1 deletions

View File

@ -58,7 +58,36 @@ module Fiddle
#
# 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

View File

@ -14,4 +14,38 @@ class TestFiddle < Fiddle::TestCase
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)