[BUG] Kernel#syscall on x86_64 linux

My ruby init scripts for the 'Rubyx' linux distro fall over trying to do syscalls
when running on x86_64 with a 64bit ruby installation.

The code in question:

module Kernel
  def poweroff(); syscall(88,-18751827,369367448,0x4321fedc); end
  def reboot(); syscall(88,-18751827,672274793,0x1234567); end
  def halt(); syscall(88,-18751827,672274793,0xcdef0123); end
  def cad(enable); syscall(88,-18751827,672274793,enable ? 0x89abcdef : 0); end
end

although any syscall seems to fail. Trying the simple example from the
Pickaxe:

root@orac / # irb
irb(main):001:0> syscall 4,1,"hello\n",6
Errno::EFAULT: Bad address
        from (irb):1:in `syscall'
        from (irb):1

Is there something I need to do differently in64bit land, or is syscall() broken?

Andrew Walrond

Hi,

At Fri, 10 Sep 2004 00:56:44 +0900,
Andrew Walrond wrote in [ruby-talk:112019]:

Is there something I need to do differently in64bit land, or is syscall() broken?

syscall assumes all arguments to system calls should be
unsigned long. This works fine on platforms int and long are
same, but is int on x86_64 32bits?

···

--
Nobu Nakada

Sizeof short: 2
Sizeof int: 4
Sizeof long: 8
Sizeof long long: 8

So sizeof(int) != sizeof(long). I guess you need to change unsigned long to
unsigned int. in the code.

I'll make the change to the ruby source and test it...

···

On Friday 10 Sep 2004 03:19, nobu.nokada@softhome.net wrote:

syscall assumes all arguments to system calls should be
unsigned long. This works fine on platforms int and long are
same, but is int on x86_64 32bits?

Hi,

At Fri, 10 Sep 2004 17:32:28 +0900,
Andrew Walrond wrote in [ruby-talk:112137]:

>
> syscall assumes all arguments to system calls should be
> unsigned long. This works fine on platforms int and long are
> same, but is int on x86_64 32bits?

Sizeof short: 2
Sizeof int: 4
Sizeof long: 8
Sizeof long long: 8

So sizeof(int) != sizeof(long). I guess you need to change unsigned long to
unsigned int. in the code.

Isn't sizeof(void*) 8?

Use ext/dl or make an extension library instead, I think
syscall should be deprecated now. It just came from perl.

···

On Friday 10 Sep 2004 03:19, nobu.nokada@softhome.net wrote:

--
Nobu Nakada

Andrew Walrond wrote in [ruby-talk:112137]:
> > syscall assumes all arguments to system calls should be
> > unsigned long. This works fine on platforms int and long are
> > same, but is int on x86_64 32bits?
>
> Sizeof short: 2
> Sizeof int: 4
> Sizeof long: 8
> Sizeof long long: 8
>
> So sizeof(int) != sizeof(long). I guess you need to change unsigned long
> to unsigned int. in the code.

Isn't sizeof(void*) 8?

Yes. But ignore my mail; I was mislead by 'man syscall' which gives the
prototype as
int syscall(int SYSNO, ...)
but the correct definition is given by 'info syscall'
long int syscall(long int SYSNO, ...)

So the fix is obviously not what I said before.

Use ext/dl or make an extension library instead, I think
syscall should be deprecated now. It just came from perl.

Ok Fine.

I'll make an extension library for glibc's reboot() instead.

Thanks

Andrew Walrond

···

On Friday 10 Sep 2004 15:04, nobu.nokada@softhome.net wrote:

> On Friday 10 Sep 2004 03:19, nobu.nokada@softhome.net wrote:

Actually, now I went away and checked out what you meant by ext/dl, I'll be
using that. What a great feature (that I never knew about)!

Andrew

···

On Friday 10 Sep 2004 15:45, Andrew Walrond wrote:

On Friday 10 Sep 2004 15:04, nobu.nokada@softhome.net wrote:

> Use ext/dl or make an extension library instead, I think

And, of course, it worked flawlessly :wink: Thanks for the tip!

require "dl/import"
module LIBC
  extend DL::Importable
  dlload "libc.so.6"
  extern "int reboot(int)"
end

module Kernel
  #See man (2) reboot
  def poweroff(); LIBC.reboot(0x4321fedc); end
  def reboot(); LIBC.reboot(0x01234567); end
  def halt(); LIBC.reboot(0xcdef0123); end
  def cad(enable); LIBC.reboot(enable ? 0x89abcdef : 0); end
end

···

On Friday 10 Sep 2004 15:52, Andrew Walrond wrote:

Actually, now I went away and checked out what you meant by ext/dl, I'll be
using that. What a great feature (that I never knew about)!