[BUG] Kernel#syscall on x86_64 linux

A

Andrew Walrond

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
 
N

nobu.nokada

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?
 
A

Andrew Walrond

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.

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

nobu.nokada

Hi,

At Fri, 10 Sep 2004 17:32:28 +0900,
Andrew Walrond wrote in [ruby-talk:112137]:
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.
 
A

Andrew Walrond

Andrew Walrond wrote in [ruby-talk:112137]:
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
 
A

Andrew Walrond

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
 
A

Andrew Walrond

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)!

And, of course, it worked flawlessly ;) 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top