Skip to content

Commit 49ea149

Browse files
committed
Add support for linker script on Linux
GitHub: fix GH-107 Reported by nicholas a. evans. Thanks!!!
1 parent 9a5a1da commit 49ea149

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

lib/fiddle.rb

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,36 @@ def self.last_error= error
5858
#
5959
# See Fiddle::Handle.new for more.
6060
def dlopen library
61-
Fiddle::Handle.new library
61+
begin
62+
Fiddle::Handle.new(library)
63+
rescue DLError => error
64+
case RUBY_PLATFORM
65+
when /linux/
66+
case error.message
67+
when /\A(\/.+?): (?:invalid ELF header|file too short)/
68+
# This may be a linker script:
69+
# https://sourceware.org/binutils/docs/ld.html#Scripts
70+
path = $1
71+
else
72+
raise
73+
end
74+
else
75+
raise
76+
end
77+
78+
File.open(path) do |input|
79+
input.each_line do |line|
80+
case line
81+
when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/
82+
# TODO: Should we support multiple files?
83+
return dlopen($1)
84+
end
85+
end
86+
end
87+
88+
# Not found
89+
raise
90+
end
6291
end
6392
module_function :dlopen
6493

test/fiddle/test_fiddle.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,38 @@ def test_windows_constant
1414
end
1515
end
1616

17+
def test_dlopen_linker_script_input_linux
18+
omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux")
19+
if Dir.glob("/usr/lib/*/libncurses.so").empty?
20+
omit("libncurses.so is needed")
21+
end
22+
# libncurses.so uses INPUT() on Debian GNU/Linux
23+
# $ cat /usr/lib/x86_64-linux-gnu/libncurses.so
24+
# INPUT(libncurses.so.6 -ltinfo)
25+
handle = Fiddle.dlopen("libncurses.so")
26+
begin
27+
assert_equal("libncurses.so",
28+
File.basename(handle.file_name, ".*"))
29+
ensure
30+
handle.close
31+
end
32+
end
33+
34+
def test_dlopen_linker_script_group_linux
35+
omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux")
36+
# libc.so uses GROUP() on Debian GNU/Linux
37+
# $ cat /usr/lib/x86_64-linux-gnu/libc.so
38+
# /* GNU ld script
39+
# Use the shared library, but some functions are only in
40+
# the static library, so try that secondarily. */
41+
# OUTPUT_FORMAT(elf64-x86-64)
42+
# 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 ) )
43+
handle = Fiddle.dlopen("libc.so")
44+
begin
45+
assert_equal("libc.so",
46+
File.basename(handle.file_name, ".*"))
47+
ensure
48+
handle.close
49+
end
50+
end
1751
end if defined?(Fiddle)

0 commit comments

Comments
 (0)