在 glibc 中有三种方式封装系统调用,包括汇编封装、通过宏进行封装、定制封装。
对于汇编封装的系统调用,需要在 syscalls.list 文件中进行配置,例如:sysdeps/unix/sysv/linux/x86_64/syscalls.list 文件中配置了几个与 socket 相关的系统调用,其内容如下:
# File name Caller Syscall name # args Strong name Weak names
arch_prctl EXTRA arch_prctl i:ii __arch_prctl arch_prctl
modify_ldt EXTRA modify_ldt i:ipi __modify_ldt modify_ldt
syscall_clock_gettime EXTRA clock_gettime Ei:ip __syscall_clock_gettime
# proper socket implementations:
bind - bind i:ipi __bind bind
getpeername - getpeername i:ipp __getpeername getpeername
getsockname - getsockname i:ipp __getsockname getsockname
getsockopt - getsockopt i:iiiBN __getsockopt getsockopt
listen - listen i:ii __listen listen
setsockopt - setsockopt i:iiibn __setsockopt setsockopt
shutdown - shutdown i:ii __shutdown shutdown
socket - socket i:iii __socket socket
socketpair - socketpair i:iiif __socketpair socketpair
由 sysdeps/unix/Makefile 中的处理流程可知,syscalls.list 会被 sysdep/unix/make-syscalls.sh 脚本处理:
ifndef avoid-generated
$(common-objpfx)sysd-syscalls: $(..)sysdeps/unix/make-syscalls.sh \
$(wildcard $(+sysdep_dirs:%=%/syscalls.list)) \
$(common-objpfx)libc-modules.stmp
for dir in $(+sysdep_dirs); do \
test -f $$dir/syscalls.list && \
{ sysdirs='$(sysdirs)' \
asm_CPP='$(COMPILE.S) -E -x assembler-with-cpp' \
$(SHELL) $(dir $<)$(notdir $<) $$dir || exit 1; }; \
test $$dir = $(..)sysdeps/unix && break; \
done > $@T
mv -f $@T $@
endif
sysdep/unix/make-syscalls.sh 脚本会为 syscalls.list 文件中的每个系统调用生成一条编译规则,并将其存放在 build-tree/x86_64-libc/sysd-syscalls 文件中。下面是 socket 系统调用在编译过程中执行的编译命令:
(echo '#define SYSCALL_NAME socket'; \
echo '#define SYSCALL_NARGS 3'; \
echo '#define SYSCALL_SYMBOL __socket'; \
echo '#define SYSCALL_CANCELLABLE 0'; \
echo '#define SYSCALL_NOERRNO 0'; \
echo '#define SYSCALL_ERRVAL 0'; \
echo '#include <syscall-template.S>'; \
echo 'weak_alias (__socket, socket)'; \
echo 'hidden_weak (socket)'; \
) | /opt/cross/x86_64-linux-gnu/bin/x86_64-glibc-linux-gnu-gcc -c -I../include -I/home/azanella/Projects/glibc/build/x86_64-linux-gnu/socket -I/home/azanella/Projects/glibc/build/x86_64-linux-gnu -I../sysdeps/unix/sysv/linux/x86_64/64 -I../sysdeps/unix/sysv/linux/x86_64 -I../sysdeps/unix/sysv/linux/x86 -I../sysdeps/x86/nptl -I../sysdeps/unix/sysv/linux/wordsize-64 -I../sysdeps/x86_64/nptl -I../sysdeps/unix/sysv/linux/include -I../sysdeps/unix/sysv/linux -I../sysdeps/nptl -I../sysdeps/pthread -I../sysdeps/gnu -I../sysdeps/unix/inet -I../sysdeps/unix/sysv -I../sysdeps/unix/x86_64 -I../sysdeps/unix -I../sysdeps/posix -I../sysdeps/x86_64/64 -I../sysdeps/x86_64/fpu/multiarch -I../sysdeps/x86_64/fpu -I../sysdeps/x86/fpu/include -I../sysdeps/x86/fpu -I../sysdeps/x86_64/multiarch -I../sysdeps/x86_64 -I../sysdeps/x86 -I../sysdeps/ieee754/float128 -I../sysdeps/ieee754/ldbl-96/include -I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64/wordsize-64 -I../sysdeps/ieee754/dbl-64 -I../sysdeps/ieee754/flt-32 -I../sysdeps/wordsize-64 -I../sysdeps/ieee754 -I../sysdeps/generic -I.. -I../libio -I. -D_LIBC_REENTRANT -include /home/azanella/Projects/glibc/build/x86_64-linux-gnu/libc-modules.h -DMODULE_NAME=libc -include ../include/libc-symbols.h -DPIC -DSHARED -DTOP_NAMESPACE=glibc -DASSEMBLER -g -Werror=undef -Wa,--noexecstack -o /home/azanella/Projects/glibc/build/x86_64-linux-gnu/socket/socket.os -x assembler-with-cpp - -MD -MP -MF /home/azanella/Projects/glibc/build/x86_64-linux-gnu/socket/socket.os.dt -MT /home/azanella/Projects/glibc/build/x86_64-linux-gnu/socket/socket.os