Re: Syscall changes registers beyond %eax, on linux-i386

Petr Vandrovec
2002-09-19T17:39:50Z

On 19 Sep 02 at 13:22, Richard B. Johnson wrote:

> > >>A short snippet of sys_poll, with irrelavant data removed.
> > >>
> > >>sys_poll(struct pollfd *ufds, .. , ..) {
> > >> ...
> > >> ufds++;
> > >> ...
>
> Well which one? Here is an ioctl(). It certainly modifies one
> of its parameter values.

poll(), as was already noted. Program below should
print same value for B= and F=, but it reports f + 8*c instead
(where c = number of filedescriptors passed to poll).

And you must call it from assembly, as your calls to getpid() or
ioctl() (or poll()) are wrapped in libc - and glibc's code begins with
push %ebx because of %ebx is used by -fPIC code.

It is questinable whether we should try to not modify parameters
passed into functions. It is definitely nice behavior, but I think
that we should only guarantee that syscalls do not modify unused
registers.
Petr Vandrovec
vandrove@vc.cvut.cz

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/poll.h>

struct pollfd f[5];

int main(int argc, char* argv[]) {
unsigned int i;
void * reg;

for (i = 0; i < 5; i++) {
f[i].fd = 0;
f[i].events = POLLIN;
}
__asm__ __volatile__("int $0x80\n" : "=b"(reg) : "a"(168), "0"(f), "c"(5), "d"(1));
printf("B=%p F=%p\n", reg, f);
return 0;
}