Why are system call numbers for `x86-64` and `x32` different but similar, and why are some not defined in unistd_x32.h?

Issue

I have come across these files on Linux after reading more about system call numbers for particular architecture.

When I ran this command locate unistd_64.h it gives me a path to the system call file /usr/include/asm/unistd_64.h but when I looked in the asm folder I found out there are other two files (unistd_32.h, unistd_x32.h) as well. I know that they are existed for different architecture.

What I observe is that the system call number for unistd_64.h and unistd_32.h are completely different.

// unistd_64.h

#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4
#define __NR_fstat 5

#define __NR_rt_sigaction 13       // this doesn't exist in unistd_x32
// unistd_32.h

#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5

And I believe it is because unistd_32.h supports i386 architecture and I think it will only allow 4GB of ram with 32 bit, maybe and unistd_64.h supports x86-64 architecture, and we can have 18-Quintillion bytes of RAM at maximum.

What I didn’t understood exactly is that what is this unistd_x32.h file stands for? If we see it’s content, it’s pretty much similar to unistd_64.h so I guess system call numbers are the same after all, but it does have a new macro or variable __X32_SYSCALL_BIT. I don’t understand why we are adding this?

// unistd_x32.h

#define __NR_read (__X32_SYSCALL_BIT + 0)
#define __NR_write (__X32_SYSCALL_BIT + 1)
#define __NR_open (__X32_SYSCALL_BIT + 2)
#define __NR_close (__X32_SYSCALL_BIT + 3)
#define __NR_stat (__X32_SYSCALL_BIT + 4)
#define __NR_fstat (__X32_SYSCALL_BIT + 5)

Also, there are few system call numbers missing in unistd_x32.h version, like we have #define __NR_rt_sigaction 13 this system call in unistd_64.h but not in x32 version. There are many system calls like this. So If I assume that x32 is basically 32 bit pointer architecture but it can run on 64 bit version? So it can access only 4GB of ram even if we have more RAM? Correct me if I am wrong in stating the question.

Solution

Yes, Linux’s x32 ABI is an ILP32 ABI for 64-bit mode. https://en.wikipedia.org/wiki/X32_ABI.

As you can see, its syscall numbers are not all the same as for x86-64, because pointer width is different and arg-passing registers holding pointers might have high garbage in the top 32 bits. The kernel needs to ignore this and only use the 32-bit pointer in the low half of the register.

Also some struct layouts maybe be different, as long is a 32-bit type in the x32 ABI.

Answered By – Peter Cordes

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published