arch/x86/include/asm/unistd.h vs. include/asm-generic/unistd.h
I don't have a definite answer, but it's not uncommon for redundant files to exist when devs try to shift from old mechanisms to newer ones. Your case here looks quite similar.
If you checkout the 3.4 kernel, you will find that both arch/x86/include/asm/unistd_32.h and arch/x86/include/asm/unistd_64.h are gone. Instead, they are generated using arch/x86/syscalls.
Checkout the latest kernel (3.4.2 stable works for me), and do a "git log --stat arch/x86/include/asm", search for unistd_64.h or unistd_32.h or unistd.h.
I found the following commit might be interesting to you.
commit 303395ac3bf3e2cb488435537d416bc840438fcb
I've never touched syscalls before, so I'd rather not say too much. git log is usually how I sort out confusing files. You can also get into makefiles if you are good at it. (I am not, so I rely on git log. )
What is the linux-2.6.3x.x/include/asm-generic/' for?
asm-generic is a generic versions of functions usually coded in assembly, but coded in plain C, without any inline assembly. It's probably made for easy porting of the kernel to new platforms, and to keep platfom-independent common code in one place.
unistd_64.h in Linux
The syscalls provided by your kernel does not have to match the syscalls your C library knows about. The openat2
was added to glibc
by commit e788bea
in April 2020:
Update syscall lists for Linux 5.6.
Linux 5.6 has new openat2 and pidfd_getfd syscalls. This patch adds
them to syscall-names.list and regenerates the arch-syscall.h files.
The next glibc
release was 2.32
, in August 2020. In Ubuntu, libc6
packages with version >=2.32
are currently only available for groovy
and hirsute
:
Package libc6
- bionic-updates (libs): GNU C Library: Shared libraries
2.27-3ubuntu1.4: amd64 arm64 armhf i386 ppc64el s390x
also provided by: libc6-udeb- focal-updates (libs): GNU C Library: Shared libraries
2.31-0ubuntu9.2: amd64 arm64 armhf i386 ppc64el s390x
also provided by: libc6-udeb- groovy (20.10) (libs): GNU C Library: Shared libraries
2.32-0ubuntu3: amd64 arm64 armhf i386 ppc64el s390x
also provided by: libc6-udeb- hirsute (21.04) (libs): GNU C Library: Shared libraries
2.33-0ubuntu5: amd64 arm64 armhf i386 ppc64el s390x
But since you would not be getting much portability by requiring glibc>=2.32
and linux-kernel>=5.6
anyway, you could define the syscall numbers in your code (ifndef
) and use syscall(2)
instead.
Which header file of system call numbers is correct?
The asm-generic
one is a template version that can be used if you're developing a new architecture for the kernel. I believe you'll find that there are actually many versions of unistd.h
in the kernel source, because the ordering of system calls (and indeed system call existence) varies by architecture. Try this from the root of your kernel source hierarchy:
find . -name 'unistd*.h'
For x86 specifically, the uapi
version is generated when you build the kernel. See the Makefile
and various *.tbl
files in arch/x86/entry/syscalls/
directory. This ends up generating files:
arch/x86/include/generated/uapi/asm/unistd_64.h
arch/x86/include/generated/uapi/asm/unistd_32.h
arch/x86/include/generated/uapi/asm/unistd_x32.h
(all of which are #include
d from a stub unistd.h
file).
Ultimately the creation of a linux "distro" is very architecture-specific, so it's up to the distro creator to copy the correct unistd.h
file(s) into some appropriate location within the /usr/include
hierarchy. (And of course, your libc
will also need to be compiled against the correct version in order for ordinary libc
system calls to work correctly.)
In summary, the version in /usr/include/asm
had better match your running kernel or it won't be possible to correctly generate an ad-hoc system call from a user process on your system, but you shouldn't be using that one within the kernel source hierarchy, because categorically the kernel source hierarchy never relies on user space headers. Within the kernel source, the mechanism for indexing that table is architecture-dependent because the layout and ordering of the table is itself architecture-dependent, and only architecture-specific code (the system call entry code) normally accesses the table, so only that code "needs to know" the correct indices.
Now if you're creating a new system call, you would need to go define its number in all of the unistd.h
files for all of the architectures you want it to appear in.
ausyscall cannot extract new systemcall
They are generated from per-arch header files, e.g. lib/x86_64_table.h
. You can see the commit that added openat2
is 8f41f04
:
Update syscall table to the 5.11 kernel
master
v3.0.1
stevegrubb committed on Jan 18
The information in the headers in turn come from syscall table files from kernel sources. See: lib/syscall-update.txt
.
The place where syscall information is gathered is:
arch/arm/tools/syscall.tbl
arch/arm/include/uapi/asm/unistd.h
arch/powerpc/include/uapi/asm/unistd.h
arch/s390/kernel/syscalls/syscall.tbl
arch/x86/entry/syscalls/syscall_32.tbl
arch/x86/entry/syscalls/syscall_64.tbl
include/uapi/asm-generic/unistd.h
(aarch64)
Weird syscall numbers on Linux 32 bits
If you start with /usr/include/sys/syscall.h (as indicated in syscall(2)) and repeatedly follow the include directives you arrive at /usr/include/asm/unistd_32.h. Hence I recommend you use this header.
can't find the definition of __arm64_sys_ppoll function in linux source
For SYSCALL_DEFINE0, ..., SYSCALL_DEFINE6, first see @Ian Abbott's comment to my original question.
In file include/uapi/asm-generic/unistd.h, you can see the syscall definitions.
For example if you want to see the source code for shmat, you can use grep to see in the file these lines,
/* ipc/shm.c */
#define __NR_shmget 194
__SYSCALL(__NR_shmget, sys_shmget)
#define __NR_shmctl 195
__SC_COMP(__NR_shmctl, sys_shmctl, compat_sys_shmctl)
#define __NR_shmat 196
__SC_COMP(__NR_shmat, sys_shmat, compat_sys_shmat)
#define __NR_shmdt 197
__SYSCALL(__NR_shmdt, sys_shmdt)
So it says the definition is in file ipc/shm.c. There you can see these lines.
SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)
{
unsigned long ret;
long err;
err = do_shmat(shmid, shmaddr, shmflg, &ret, SHMLBA);
if (err)
return err;
force_successful_syscall_return();
return (long)ret;
}
You can see the definition of shmat function with argments list.
Related Topics
Extract/See Content of a Specific File Inside a .War File
/Usr/Bin/Ld: Cannot Find -Lglut
How to Boot with My Latest Rpi-3.18.0 Kernel and Enabling The Device Tree
Dreamweaver Equivalent for Linux
Linux Compile for Enable Uart2
How Does Apparmor Do "Environment Scrubbing"
Linking with 32Bit Libraries Under Linux 64Bit
Error When Compiling Linux Kernel 3.2 for Arm
Gitlab: You Are Not Allowed to Access Master! After Moving Gitlab to Another Server
Why Is Running Node.Js on Port 80 Might Not Be Safe
Linux - Bash Redirect a String to a File
Removing First 3 Characters of File Names in Linux
Cuda - Confusion About The Visual Profiler Results of "Branch" and "Divergent Branch" (2)