Bug #932: incorrect case statement in "ext/dl/test/test_base.rb" causes library problems on openSUSE 11.1 64-bit
http://redmine.ruby-lang.org/issues/show/932

Author: Ed Borasky
Status: Open, Priority: Normal
Category: ext, Target version: 1.9.1 Release Candidate

I compiled Ruby 1.9.1 from the SVN repository and tried to reproduce the segfault issue #633 on my openSUSE 11.1 x86_64 system. Instead of segfaulting, it did this:

znmeb@DreamScape:~/Packages/ruby/ext/dl/test> ruby test_all.rb 
nil
Loaded suite test_all
Started
EEEEEEEEEEEEEEEEEE
Finished in 0.002599 seconds.

  1) Error:
test_empty(DL::TestBase):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

  2) Error:
test_call_double(DL::TestDL):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

  3) Error:
test_call_int(DL::TestDL):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

  4) Error:
test_call_long(DL::TestDL):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

  5) Error:
test_callback(DL::TestDL):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

  6) Error:
test_cptr(DL::TestDL):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

  7) Error:
test_dlwrap(DL::TestDL):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

  8) Error:
test_empty(DL::TestDL):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

  9) Error:
test_sin(DL::TestDL):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

 10) Error:
test_strcpy(DL::TestDL):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

 11) Error:
test_strlen(DL::TestDL):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

 12) Error:
test_atof(DL::TestFunc):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

 13) Error:
test_empty(DL::TestFunc):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'

    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

 14) Error:
test_isdigit(DL::TestFunc):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

 15) Error:
test_qsort1(DL::TestFunc):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

 16) Error:
test_qsort2(DL::TestFunc):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

 17) Error:
test_strcpy(DL::TestFunc):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

 18) Error:
test_strtod(DL::TestFunc):
DL::DLError: /lib/libc.so.6: wrong ELF class: ELFCLASS32
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `initialize'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `dlopen'
    /home/znmeb/Packages/ruby/ext/dl/test/test_base.rb:29:in `setup'

18 tests, 0 assertions, 0 failures, 18 errors, 0 skips
/home/znmeb/test/lib/ruby/1.9.1/dl/import.rb:52:in `rescue in block in dlload': can't load /lib/libc.so.6 (DL::DLError)
	from /home/znmeb/test/lib/ruby/1.9.1/dl/import.rb:49:in `block in dlload'
	from /home/znmeb/test/lib/ruby/1.9.1/dl/import.rb:40:in `collect'
	from /home/znmeb/test/lib/ruby/1.9.1/dl/import.rb:40:in `dlload'
	from /home/znmeb/Packages/ruby/ext/dl/test/test_import.rb:7:in `<module:LIBC>'
	from /home/znmeb/Packages/ruby/ext/dl/test/test_import.rb:5:in `<module:DL>'
	from /home/znmeb/Packages/ruby/ext/dl/test/test_import.rb:4:in `<top (required)>'
	from test_all.rb:6:in `require'
	from test_all.rb:6:in `<main>'
znmeb@DreamScape:~/Packages/ruby/ext/dl/test> 

After a little poking around with "locate", "ldd" and "grep" I discovered this "case" statement in "test_base.rb":

require 'test/unit'
  2 require 'dl'
  3 
  4 case RUBY_PLATFORM
  5 when /cygwin/
  6   LIBC_SO = "cygwin1.dll"
  7   LIBM_SO = "cygwin1.dll"
  8 when /linux/
  9   LIBC_SO = "/lib/libc.so.6"
 10   LIBM_SO = "/lib/libm.so.6"
 11 when /mingw/, /mswin32/
 12   LIBC_SO = "msvcrt.dll"
 13   LIBM_SO = "msvcrt.dll"
 14 else
 15   LIBC_SO = ARGV[0]
 16   LIBM_SO = ARGV[1]
 17   if( !(LIBC_SO && LIBM_SO) )
 18     $stderr.puts("#{$0} <libc> <libm>")
 19     exit
 20   end
 21 end
 22 

On an openSUSE 11.1 64-bit system, "/lib/libc.so.6" is the 32-bit one, and the 64-bit one is "/lib64/libc.so.6". On my system, "RUBY_PLATFORM" is

znmeb@DreamScape:~/Packages> which ruby
/home/znmeb/test/bin/ruby
znmeb@DreamScape:~/Packages> ruby -e 'puts RUBY_PLATFORM'
x86_64-linux

So I added a branch to the "case":

  3 
  4 case RUBY_PLATFORM
  5 when /cygwin/
  6   LIBC_SO = "cygwin1.dll"
  7   LIBM_SO = "cygwin1.dll"
  8 when /x86_64-linux/
  9   LIBC_SO = "/lib64/libc.so.6"
 10   LIBM_SO = "/lib64/libm.so.6"
 11 when /linux/
 12   LIBC_SO = "/lib/libc.so.6"
 13   LIBM_SO = "/lib/libm.so.6"
 14 when /mingw/, /mswin32/
 15   LIBC_SO = "msvcrt.dll"
 16   LIBM_SO = "msvcrt.dll"
 17 else
 18   LIBC_SO = ARGV[0]
 19   LIBM_SO = ARGV[1]
 20   if( !(LIBC_SO && LIBM_SO) )
 21     $stderr.puts("#{$0} <libc> <libm>")
 22     exit
 23   end
 24 end
 25 

and the library problem goes away. As far as I know, the "libc.so.6" problem shows up only on openSUSE 11.1, but there should probably be a more portable / robust way of setting that constant. I looked at a few other uses of "RUBY_PLATFORM" in the source tree, and there are quite a few places where it's comparing against "just" /linux/. Some of those may also need to differentiate between 32-bit and 64-bit Linux platforms.


----------------------------------------
http://redmine.ruby-lang.org